Implement admin dash workspaces tab

This commit is contained in:
2024-11-10 15:03:51 +01:00
parent 148001be43
commit 5e2d434b4b
11 changed files with 258 additions and 189 deletions

View File

@@ -50,6 +50,10 @@ func SetupRoutes(r chi.Router, db *db.DB, fs *filesystem.FileSystem, authMiddlew
r.Put("/{userId}", handler.AdminUpdateUser())
r.Delete("/{userId}", handler.AdminDeleteUser())
})
// Workspace management
r.Route("/workspaces", func(r chi.Router) {
r.Get("/", handler.AdminListWorkspaces())
})
// System stats
r.Get("/stats", handler.AdminGetSystemStats())
})

View File

@@ -249,3 +249,43 @@ func (db *DB) GetLastOpenedFile(workspaceID int) (string, error) {
}
return filePath.String, nil
}
// GetAllWorkspaces retrieves all workspaces in the database
func (db *DB) GetAllWorkspaces() ([]*models.Workspace, error) {
rows, err := db.Query(`
SELECT
id, user_id, name, created_at,
theme, auto_save,
git_enabled, git_url, git_user, git_token,
git_auto_commit, git_commit_msg_template
FROM workspaces`,
)
if err != nil {
return nil, err
}
defer rows.Close()
var workspaces []*models.Workspace
for rows.Next() {
workspace := &models.Workspace{}
var encryptedToken string
err := rows.Scan(
&workspace.ID, &workspace.UserID, &workspace.Name, &workspace.CreatedAt,
&workspace.Theme, &workspace.AutoSave,
&workspace.GitEnabled, &workspace.GitURL, &workspace.GitUser, &encryptedToken,
&workspace.GitAutoCommit, &workspace.GitCommitMsgTemplate,
)
if err != nil {
return nil, err
}
// Decrypt token
workspace.GitToken, err = db.decryptToken(encryptedToken)
if err != nil {
return nil, fmt.Errorf("failed to decrypt token: %w", err)
}
workspaces = append(workspaces, workspace)
}
return workspaces, nil
}

View File

@@ -8,6 +8,7 @@ import (
"novamd/internal/httpcontext"
"novamd/internal/models"
"strconv"
"time"
"github.com/go-chi/chi/v5"
"golang.org/x/crypto/bcrypt"
@@ -204,6 +205,58 @@ func (h *Handler) AdminDeleteUser() http.HandlerFunc {
}
}
// WorkspaceStats holds workspace statistics
type WorkspaceStats struct {
UserID int `json:"userID"`
UserEmail string `json:"userEmail"`
WorkspaceID int `json:"workspaceID"`
WorkspaceName string `json:"workspaceName"`
WorkspaceCreatedAt time.Time `json:"workspaceCreatedAt"`
*filesystem.FileCountStats
}
// AdminListWorkspaces returns a list of all workspaces and their stats
func (h *Handler) AdminListWorkspaces() http.HandlerFunc {
return func(w http.ResponseWriter, _ *http.Request) {
workspaces, err := h.DB.GetAllWorkspaces()
if err != nil {
http.Error(w, "Failed to list workspaces", http.StatusInternalServerError)
return
}
workspacesStats := make([]*WorkspaceStats, 0, len(workspaces))
for _, ws := range workspaces {
workspaceData := &WorkspaceStats{}
user, err := h.DB.GetUserByID(ws.UserID)
if err != nil {
http.Error(w, "Failed to get user", http.StatusInternalServerError)
return
}
workspaceData.UserID = ws.UserID
workspaceData.UserEmail = user.Email
workspaceData.WorkspaceID = ws.ID
workspaceData.WorkspaceName = ws.Name
workspaceData.WorkspaceCreatedAt = ws.CreatedAt
fileStats, err := h.FS.GetFileStats(ws.UserID, ws.ID)
if err != nil {
http.Error(w, "Failed to get file stats", http.StatusInternalServerError)
return
}
workspaceData.FileCountStats = fileStats
workspacesStats = append(workspacesStats, workspaceData)
}
respondJSON(w, workspacesStats)
}
}
// SystemStats holds system-wide statistics
type SystemStats struct {
*db.UserStats