Changeset 0.37.14 (#226)
Co-authored-by: gobha <jasafpro@gmail.com> Co-committed-by: gobha <jasafpro@gmail.com>
This commit is contained in:
117
server/handlers/profile_bootstrap.go
Normal file
117
server/handlers/profile_bootstrap.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package handlers
|
||||
|
||||
// profile_bootstrap.go — Single-call boot payload for the SDK.
|
||||
//
|
||||
// GET /api/v1/profile/bootstrap
|
||||
//
|
||||
// Collapses what previously required 3-4 sequential requests
|
||||
// (profile, permissions, teams/mine, settings) into one call.
|
||||
// The SDK calls this at startup and on token refresh.
|
||||
//
|
||||
// v0.37.15
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sort"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"chat-switchboard/auth"
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ProfileBootstrapHandler serves the combined boot payload.
|
||||
type ProfileBootstrapHandler struct {
|
||||
stores store.Stores
|
||||
}
|
||||
|
||||
func NewProfileBootstrapHandler(s store.Stores) *ProfileBootstrapHandler {
|
||||
return &ProfileBootstrapHandler{stores: s}
|
||||
}
|
||||
|
||||
// GetBootstrap returns everything the shell needs at startup.
|
||||
// GET /api/v1/profile/bootstrap
|
||||
func (h *ProfileBootstrapHandler) GetBootstrap(c *gin.Context) {
|
||||
userID := getUserID(c)
|
||||
role, _ := c.Get("role")
|
||||
ctx := c.Request.Context()
|
||||
|
||||
// ── User profile ────────────────────────
|
||||
user, err := h.stores.Users.GetByID(ctx, userID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
|
||||
return
|
||||
}
|
||||
|
||||
userPayload := gin.H{
|
||||
"id": user.ID,
|
||||
"username": user.Username,
|
||||
"display_name": user.DisplayName,
|
||||
"email": user.Email,
|
||||
"role": user.Role,
|
||||
}
|
||||
if user.AvatarURL != "" {
|
||||
userPayload["avatar"] = user.AvatarURL
|
||||
}
|
||||
|
||||
// ── Permissions ─────────────────────────
|
||||
var permList []string
|
||||
if role == "admin" {
|
||||
permList = make([]string, len(auth.AllPermissions))
|
||||
copy(permList, auth.AllPermissions)
|
||||
} else {
|
||||
perms, err := auth.ResolvePermissions(ctx, h.stores, userID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to resolve permissions"})
|
||||
return
|
||||
}
|
||||
permList = make([]string, 0, len(perms))
|
||||
for p := range perms {
|
||||
permList = append(permList, p)
|
||||
}
|
||||
}
|
||||
sort.Strings(permList)
|
||||
|
||||
// ── Groups ──────────────────────────────
|
||||
groupIDs, _ := h.stores.Groups.GetUserGroupIDs(ctx, userID)
|
||||
if groupIDs == nil {
|
||||
groupIDs = []string{}
|
||||
}
|
||||
groupIDs = append(groupIDs, auth.EveryoneGroupID)
|
||||
|
||||
// ── Teams ───────────────────────────────
|
||||
teams, _ := h.stores.Teams.ListForUser(ctx, userID)
|
||||
teamData := make([]gin.H, 0, len(teams))
|
||||
for _, t := range teams {
|
||||
teamData = append(teamData, gin.H{
|
||||
"id": t.ID,
|
||||
"name": t.Name,
|
||||
"my_role": t.MyRole,
|
||||
})
|
||||
}
|
||||
|
||||
// ── Policies ────────────────────────────
|
||||
policies := make(map[string]bool)
|
||||
if ps := h.stores.Policies; ps != nil {
|
||||
policies["allow_user_byok"], _ = ps.GetBool(ctx, "allow_user_byok")
|
||||
policies["allow_user_personas"], _ = ps.GetBool(ctx, "allow_user_personas")
|
||||
policies["allow_raw_model_access"], _ = ps.GetBool(ctx, "allow_raw_model_access")
|
||||
policies["kb_direct_access"], _ = ps.GetBool(ctx, "kb_direct_access")
|
||||
}
|
||||
|
||||
// ── Settings ────────────────────────────
|
||||
settings := make(map[string]interface{})
|
||||
if user.Settings != nil {
|
||||
settings = user.Settings
|
||||
}
|
||||
|
||||
// ── Response ────────────────────────────
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"user": userPayload,
|
||||
"permissions": permList,
|
||||
"groups": groupIDs,
|
||||
"teams": teamData,
|
||||
"policies": policies,
|
||||
"settings": settings,
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user