package admin import ( "context" "fmt" "net/http" "github.com/go-chi/chi/v5" "github.com/ultisuite/ulti-backend/internal/api/apiresponse" "github.com/ultisuite/ulti-backend/internal/api/apivalidate" "github.com/ultisuite/ulti-backend/internal/api/middleware" "github.com/ultisuite/ulti-backend/internal/authentik" ) func (s *Service) SyncIdentityProviders(ctx context.Context, actorSub, providerID string) (map[string]any, error) { stored, _, _, err := s.loadOrgPolicyRaw(ctx) if err != nil { return nil, err } idpSection, _ := stored["identity_providers"].(map[string]any) if idpSection == nil { return nil, fmt.Errorf("identity_providers not configured") } providers, _ := idpSection["providers"].([]any) found := false for _, item := range providers { pm, ok := item.(map[string]any) if !ok { continue } if id, _ := pm["id"].(string); id == providerID { found = true break } } if !found { return nil, fmt.Errorf("provider not found") } syncer := authentik.NewSourceSyncer(s.db, s.cfg) if err := syncer.SyncSection(ctx, idpSection); err != nil { return nil, err } s.logAudit(ctx, actorSub, "sync_identity_provider", map[string]any{ "provider_id": providerID, }) return s.GetOrgSettings(ctx) } func (h *Handler) GetIdentityProviderRedirectURI(w http.ResponseWriter, r *http.Request) { slug := chi.URLParam(r, "slug") if slug == "" { apivalidate.WriteValidationError(w, r, apivalidate.NewValidationError( apivalidate.FieldDetail{Field: "slug", Message: "required"}, )) return } syncer := authentik.NewSourceSyncer(h.svc.db, h.svc.cfg) apiresponse.WriteJSON(w, http.StatusOK, map[string]any{ "slug": slug, "redirect_uri": syncer.RedirectURI(slug), }) } func (h *Handler) TestIdentityProvider(w http.ResponseWriter, r *http.Request) { providerID := chi.URLParam(r, "providerID") if providerID == "" { apivalidate.WriteValidationError(w, r, apivalidate.NewValidationError( apivalidate.FieldDetail{Field: "providerID", Message: "required"}, )) return } syncer := authentik.NewSourceSyncer(h.svc.db, h.svc.cfg) if err := syncer.TestProvider(r.Context(), providerID); err != nil { apiresponse.WriteError(w, r, http.StatusBadRequest, apiresponse.CodeInvalidRequest, err.Error(), nil) return } apiresponse.WriteJSON(w, http.StatusOK, map[string]any{"ok": true}) } func (h *Handler) SyncIdentityProvider(w http.ResponseWriter, r *http.Request) { providerID := chi.URLParam(r, "providerID") if providerID == "" { apivalidate.WriteValidationError(w, r, apivalidate.NewValidationError( apivalidate.FieldDetail{Field: "providerID", Message: "required"}, )) return } claims := middleware.ClaimsFromContext(r.Context()) payload, err := h.svc.SyncIdentityProviders(r.Context(), claims.Sub, providerID) if err != nil { h.logger.Error("sync identity provider", "error", err, "provider_id", providerID) apivalidate.WriteInternal(w, r) return } apiresponse.WriteJSON(w, http.StatusOK, payload) }