package admin import ( "encoding/json" "log" "net/http" "gitea.local/admin/hspguard/internal/config" imiddleware "gitea.local/admin/hspguard/internal/middleware" "gitea.local/admin/hspguard/internal/repository" "gitea.local/admin/hspguard/internal/util" "gitea.local/admin/hspguard/internal/web" "github.com/go-chi/chi/v5" ) type AdminHandler struct { repo *repository.Queries cfg *config.AppConfig } func New(repo *repository.Queries, cfg *config.AppConfig) *AdminHandler { return &AdminHandler{ repo, cfg, } } func (h *AdminHandler) RegisterRoutes(router chi.Router) { router.Route("/admin", func(r chi.Router) { authMiddleware := imiddleware.NewAuthMiddleware(h.cfg) adminMiddleware := imiddleware.NewAdminMiddleware(h.repo) r.Use(authMiddleware.Runner, adminMiddleware.Runner) r.Get("/api-services", h.GetApiServices) r.Post("/api-services", h.AddApiService) }) } func (h *AdminHandler) GetApiServices(w http.ResponseWriter, r *http.Request) { services, err := h.repo.ListApiServices(r.Context()) if err != nil { log.Println("ERR: Failed to list api services from db:", err) web.Error(w, "failed to get api services", http.StatusInternalServerError) return } apiServices := make([]ApiServiceDTO, 0) for _, service := range services { apiServices = append(apiServices, NewApiServiceDTO(service)) } type Response struct { Items []ApiServiceDTO `json:"items"` Count int `json:"count"` } encoder := json.NewEncoder(w) if err := encoder.Encode(Response{ Items: apiServices, Count: len(apiServices), }); err != nil { web.Error(w, "failed to encode response", http.StatusInternalServerError) } } type AddServiceRequest struct { Name string `json:"name"` RedirectUris []string `json:"redirect_uris"` Scopes []string `json:"scopes"` GrantTypes []string `json:"grant_types"` } func (h *AdminHandler) AddApiService(w http.ResponseWriter, r *http.Request) { var req AddServiceRequest decoder := json.NewDecoder(r.Body) if err := decoder.Decode(&req); err != nil { web.Error(w, "failed to parse request body", http.StatusBadRequest) return } if req.Name == "" { web.Error(w, "name is required for an api service", http.StatusBadRequest) return } clientId, err := util.GenerateClientID() if err != nil { web.Error(w, "failed to generate client id", http.StatusInternalServerError) return } clientSecret, err := util.GenerateClientSecret() if err != nil { web.Error(w, "failed to generate client secret", http.StatusInternalServerError) return } hashSecret, err := util.HashPassword(clientSecret) if err != nil { web.Error(w, "failed to create client secret", http.StatusInternalServerError) return } service, err := h.repo.CreateApiService(r.Context(), repository.CreateApiServiceParams{ ClientID: clientId, ClientSecret: hashSecret, Name: req.Name, RedirectUris: req.RedirectUris, Scopes: req.Scopes, GrantTypes: req.GrantTypes, }) if err != nil { web.Error(w, "failed to create new api service", http.StatusInternalServerError) return } w.Header().Set("Content-Type", "application/json; charset=utf-8") service.ClientSecret = clientSecret encoder := json.NewEncoder(w) if err := encoder.Encode(NewApiServiceDTO(service)); err != nil { web.Error(w, "failed to encode response", http.StatusInternalServerError) } }