• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

DigitalTolk / wireguard-ui / 24791061837

22 Apr 2026 04:50PM UTC coverage: 81.067%. First build
24791061837

push

github

web-flow
Add auditlogs (#1)

* Add auditlogs

* test

* test

* test

* test

* test

* test

164 of 233 branches covered (70.39%)

Branch coverage included in aggregate %.

1878 of 2390 new or added lines in 34 files covered. (78.58%)

2722 of 3327 relevant lines covered (81.82%)

6.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.03
/handler/api_v1_audit.go
1
package handler
2

3
import (
4
        "fmt"
5
        "net/http"
6
        "strconv"
7

8
        "github.com/labstack/echo/v4"
9
        "github.com/xuri/excelize/v2"
10

11
        "github.com/DigitalTolk/wireguard-ui/audit"
12
)
13

14
// APIListAuditLogs returns paginated audit logs
15
func APIListAuditLogs(auditLog *audit.Logger) echo.HandlerFunc {
4✔
16
        return func(c echo.Context) error {
8✔
17
                from := c.QueryParam("from")
4✔
18
                to := c.QueryParam("to")
4✔
19
                actor := c.QueryParam("actor")
4✔
20
                action := c.QueryParam("action")
4✔
21
                page, _ := strconv.Atoi(c.QueryParam("page"))
4✔
22
                perPage, _ := strconv.Atoi(c.QueryParam("per_page"))
4✔
23

4✔
24
                entries, total, err := auditLog.Query(from, to, actor, action, page, perPage)
4✔
25
                if err != nil {
4✔
NEW
26
                        return apiInternalError(c, "Cannot query audit logs")
×
NEW
27
                }
×
28

29
                if entries == nil {
5✔
30
                        entries = []audit.LogEntry{}
1✔
31
                }
1✔
32

33
                return c.JSON(http.StatusOK, map[string]interface{}{
4✔
34
                        "data":     entries,
4✔
35
                        "total":    total,
4✔
36
                        "page":     page,
4✔
37
                        "per_page": perPage,
4✔
38
                })
4✔
39
        }
40
}
41

42
// APIExportAuditLogs exports audit logs as an Excel file
43
func APIExportAuditLogs(auditLog *audit.Logger) echo.HandlerFunc {
1✔
44
        return func(c echo.Context) error {
2✔
45
                from := c.QueryParam("from")
1✔
46
                to := c.QueryParam("to")
1✔
47
                actor := c.QueryParam("actor")
1✔
48
                action := c.QueryParam("action")
1✔
49

1✔
50
                entries, err := auditLog.QueryAll(from, to, actor, action)
1✔
51
                if err != nil {
1✔
NEW
52
                        return apiInternalError(c, "Cannot query audit logs")
×
NEW
53
                }
×
54

55
                f := excelize.NewFile()
1✔
56
                sheet := "Audit Logs"
1✔
57
                f.SetSheetName("Sheet1", sheet)
1✔
58

1✔
59
                // headers
1✔
60
                headers := []string{"ID", "Timestamp", "Actor", "Action", "Resource Type", "Resource ID", "Details", "IP Address"}
1✔
61
                for i, h := range headers {
9✔
62
                        cell, _ := excelize.CoordinatesToCellName(i+1, 1)
8✔
63
                        f.SetCellValue(sheet, cell, h)
8✔
64
                }
8✔
65

66
                // style headers bold
67
                style, _ := f.NewStyle(&excelize.Style{
1✔
68
                        Font: &excelize.Font{Bold: true},
1✔
69
                })
1✔
70
                f.SetCellStyle(sheet, "A1", fmt.Sprintf("%s1", string(rune('A'+len(headers)-1))), style)
1✔
71

1✔
72
                // data
1✔
73
                for row, e := range entries {
2✔
74
                        r := row + 2
1✔
75
                        f.SetCellValue(sheet, fmt.Sprintf("A%d", r), e.ID)
1✔
76
                        f.SetCellValue(sheet, fmt.Sprintf("B%d", r), e.Timestamp.Format("2006-01-02 15:04:05"))
1✔
77
                        f.SetCellValue(sheet, fmt.Sprintf("C%d", r), e.Actor)
1✔
78
                        f.SetCellValue(sheet, fmt.Sprintf("D%d", r), e.Action)
1✔
79
                        f.SetCellValue(sheet, fmt.Sprintf("E%d", r), e.ResourceType)
1✔
80
                        f.SetCellValue(sheet, fmt.Sprintf("F%d", r), e.ResourceID)
1✔
81
                        f.SetCellValue(sheet, fmt.Sprintf("G%d", r), e.Details)
1✔
82
                        f.SetCellValue(sheet, fmt.Sprintf("H%d", r), e.IPAddress)
1✔
83
                }
1✔
84

85
                // auto-width columns
86
                for i := range headers {
9✔
87
                        col, _ := excelize.ColumnNumberToName(i + 1)
8✔
88
                        f.SetColWidth(sheet, col, col, 20)
8✔
89
                }
8✔
90

91
                c.Response().Header().Set("Content-Disposition", "attachment; filename=audit-logs.xlsx")
1✔
92
                c.Response().Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
1✔
93
                return f.Write(c.Response())
1✔
94
        }
95
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc