Files

135 lines
3.0 KiB
Go

package workspace
import (
"context"
"database/sql"
"encoding/json"
"net/http"
"proxui/backend/internal/auth"
)
type Repository struct {
db *sql.DB
}
func NewRepository(db *sql.DB) Repository {
return Repository{db: db}
}
func (r Repository) GetWorkspace(ctx context.Context, profileID string) (Workspace, error) {
rows, err := r.db.QueryContext(ctx, `
select
t.id::text,
t.name,
t.slug,
m.role::text,
coalesce(p.id::text, '') as project_id,
coalesce(p.name, '') as project_name
from public.tenants t
join public.memberships m
on m.tenant_id = t.id
and m.profile_id = $1
left join public.projects p
on p.tenant_id = t.id
where t.status = 'active'
order by t.name asc, p.name asc
`, profileID)
if err != nil {
return Workspace{}, err
}
defer rows.Close()
tenantMap := make(map[string]*Tenant)
tenantOrder := []string{}
for rows.Next() {
var tenantID, tenantName, tenantSlug, role, projectID, projectName string
if err := rows.Scan(&tenantID, &tenantName, &tenantSlug, &role, &projectID, &projectName); err != nil {
return Workspace{}, err
}
tenant, exists := tenantMap[tenantID]
if !exists {
tenant = &Tenant{
ID: tenantID,
Name: tenantName,
Slug: tenantSlug,
Role: role,
Projects: []Project{},
}
tenantMap[tenantID] = tenant
tenantOrder = append(tenantOrder, tenantID)
}
if projectID != "" {
tenant.Projects = append(tenant.Projects, Project{
ID: projectID,
Name: projectName,
TenantID: tenantID,
})
}
}
if err := rows.Err(); err != nil {
return Workspace{}, err
}
tenants := make([]Tenant, 0, len(tenantOrder))
for _, id := range tenantOrder {
tenants = append(tenants, *tenantMap[id])
}
return Workspace{Tenants: tenants}, nil
}
type Workspace struct {
Tenants []Tenant `json:"tenants"`
}
type Tenant struct {
ID string `json:"id"`
Name string `json:"name"`
Slug string `json:"slug"`
Role string `json:"role"`
Projects []Project `json:"projects"`
}
type Project struct {
ID string `json:"id"`
Name string `json:"name"`
TenantID string `json:"tenant_id"`
}
type Handler struct {
repository Repository
}
func NewHandler(repository Repository) Handler {
return Handler{repository: repository}
}
func (h Handler) GetWorkspace(w http.ResponseWriter, r *http.Request) {
principal, ok := auth.PrincipalFromRequest(r)
if !ok {
writeError(w, http.StatusUnauthorized, "unauthorized")
return
}
workspace, err := h.repository.GetWorkspace(r.Context(), principal.Subject)
if err != nil {
writeError(w, http.StatusInternalServerError, "workspace_failed")
return
}
writeJSON(w, http.StatusOK, workspace)
}
func writeJSON(w http.ResponseWriter, status int, body any) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
_ = json.NewEncoder(w).Encode(body)
}
func writeError(w http.ResponseWriter, status int, message string) {
writeJSON(w, status, map[string]string{"error": message})
}