From edc2190581a183bbd698e565c9b05704930cc6a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrian=20Z=C3=BCrcher?= Date: Sun, 8 Feb 2026 08:39:17 +0100 Subject: [PATCH] add new statistic page --- backend/main.go | 6 ++ backend/stats/stats.go | 54 +++++++++++++++++ backend/utils/middleware.go | 28 +++++++++ src/layouts/MainLayout.vue | 16 +++++ src/pages/StatsPage.vue | 116 ++++++++++++++++++++++++++++++++++++ src/router/index.ts | 7 ++- src/router/routes.ts | 10 ++++ 7 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 backend/stats/stats.go create mode 100644 backend/utils/middleware.go create mode 100644 src/pages/StatsPage.vue diff --git a/backend/main.go b/backend/main.go index 2535c6f..8e21105 100644 --- a/backend/main.go +++ b/backend/main.go @@ -4,6 +4,7 @@ import ( "backend/env" "backend/models" "backend/server" + "backend/stats" "backend/utils" "flag" "fmt" @@ -119,6 +120,10 @@ func main() { })) //set logger for AuthMiddleware + s.Routes.Use(func(c *gin.Context) { + c.Set("logger", logger) + c.Next() + }) accessHandler.SetMiddlewareLogger(s.Routes) api := s.Routes.Group("/api") //set routes @@ -136,6 +141,7 @@ func main() { role.GET("/members", dbHandler.GetMember) auth.GET("/events", dbHandler.GetEvent) auth.GET("/groups", dbHandler.GetGroup) + auth.POST("/stats", stats.GetStats) auth.GET("/users", accessHandler.GetUser) auth.GET("/roles", accessHandler.GetRole) diff --git a/backend/stats/stats.go b/backend/stats/stats.go new file mode 100644 index 0000000..c87911d --- /dev/null +++ b/backend/stats/stats.go @@ -0,0 +1,54 @@ +package stats + +import ( + "backend/utils" + "net/http" + "os" + + "gitea.tecamino.com/paadi/tecamino-logger/logging" + "github.com/gin-gonic/gin" +) + +type Stats struct { + Database string `json:"database,omitempty"` + DatabaseSize int64 `json:"databaseSize,omitempty"` +} + +func GetStats(c *gin.Context) { + middlewareData, err := utils.GetMiddlewareData(c, "logger") + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": err.Error(), + }) + } + + logger, ok := middlewareData.(*logging.Logger) + if !ok { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "middleware logger for state not defined", + }) + return + } + var stats Stats + err = c.BindJSON(&stats) + if err != nil { + logger.Error("GetStats", err) + c.JSON(http.StatusInternalServerError, nil) + return + } + + f, err := os.Stat(stats.Database) + if err != nil { + logger.Error("GetStats", err) + c.JSON(http.StatusInternalServerError, nil) + return + } + + var returnStats = Stats{ + DatabaseSize: f.Size(), + } + + c.JSON(http.StatusOK, gin.H{ + "data": returnStats, + }) +} diff --git a/backend/utils/middleware.go b/backend/utils/middleware.go new file mode 100644 index 0000000..eea42e5 --- /dev/null +++ b/backend/utils/middleware.go @@ -0,0 +1,28 @@ +package utils + +import ( + "fmt" + "log" + "net/http" + + "github.com/gin-gonic/gin" +) + +func SetMiddlewareData(r *gin.Engine, key string, data any) { + //set logger for middleware + r.Use(func(c *gin.Context) { + c.Set(key, data) + c.Next() + }) +} + +func GetMiddlewareData(c *gin.Context, key string) (any, error) { + // Retrieve logger from Gin context + data, ok := c.Get("logger") + if !ok { + log.Fatal("middleware logger not set — use SetMiddlewareLogger first") + c.AbortWithStatusJSON(http.StatusInternalServerError, http.StatusInternalServerError) + return nil, fmt.Errorf("middleware key '%s'not set ", key) + } + return data, nil +} diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue index bf28454..908915b 100644 --- a/src/layouts/MainLayout.vue +++ b/src/layouts/MainLayout.vue @@ -63,6 +63,22 @@ > {{ $t('groups') }} + + {{ $t('login') }} + + + + {{ $t('stats') }} + diff --git a/src/pages/StatsPage.vue b/src/pages/StatsPage.vue new file mode 100644 index 0000000..ebb3d9e --- /dev/null +++ b/src/pages/StatsPage.vue @@ -0,0 +1,116 @@ + + + diff --git a/src/router/index.ts b/src/router/index.ts index 90402da..f03f2cf 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -40,6 +40,7 @@ export default defineRouter(function (/* { store, ssrContext } */) { Router.beforeEach((to, from, next) => { const userStore = useUserStore(); + const isLoggedIn = userStore.isAuthenticated; if (!userStore.$state.firstLogin && to.path === '/firstlogin') { next('/login'); @@ -51,7 +52,11 @@ export default defineRouter(function (/* { store, ssrContext } */) { to.meta.requiresAdmin && !userStore.isPermittedTo(to.path.replace('/', ''), 'read') ) { - next('/'); + if (to.meta.noBackendAdmin) { + next(); + } else { + next('/'); + } } else { next(); } diff --git a/src/router/routes.ts b/src/router/routes.ts index 936e5f4..d174c4a 100644 --- a/src/router/routes.ts +++ b/src/router/routes.ts @@ -37,6 +37,16 @@ const routes: RouteRecordRaw[] = [ component: () => import('src/pages/GroupTable.vue'), meta: { requiresAuth: true, requiresAdmin: true }, }, + { + path: 'report', + component: () => import('src/pages/ReportPage.vue'), + meta: { requiresAuth: true, requiresAdmin: false }, + }, + { + path: 'stats', + component: () => import('src/pages/StatsPage.vue'), + meta: { requiresAuth: true, requiresAdmin: true, noBackendAdmin: true }, + }, { path: 'settings', component: () => import('pages/SettingsPage.vue'),