package api import ( "context" "errors" "github.com/gin-gonic/gin" openapi_types "github.com/oapi-codegen/runtime/types" "kereru.forms/internal/auth" ) func (s *Server) GetAuthConfig(ctx context.Context, _ GetAuthConfigRequestObject) (GetAuthConfigResponseObject, error) { _, span := s.tracer.Start(ctx, "GetAuthConfig") defer span.End() if s.auth == nil { return GetAuthConfig200JSONResponse(AuthConfig{ Mode: AuthConfigMode("password"), }), nil } cfg := s.auth.PublicConfig() out := AuthConfig{ Mode: AuthConfigMode(cfg.Mode), RequireSubmissionAuth: cfg.RequireSubmissionAuth, } if cfg.OIDC != nil { out.Oidc = &OIDCClientConfig{ IssuerUrl: cfg.OIDC.IssuerURL, AuthorizationEndpoint: cfg.OIDC.AuthorizationEndpoint, TokenEndpoint: cfg.OIDC.TokenEndpoint, ClientId: cfg.OIDC.ClientID, Scopes: cfg.OIDC.Scopes, } } return GetAuthConfig200JSONResponse(out), nil } func (s *Server) Login(ctx context.Context, request LoginRequestObject) (LoginResponseObject, error) { _, span := s.tracer.Start(ctx, "Login") defer span.End() if s.auth == nil { return Login400JSONResponse{ErrorJSONResponse: errJSON("authentication is not configured", "auth_not_configured")}, nil } if request.Body == nil { return Login400JSONResponse{ErrorJSONResponse: errJSON("password is required", "invalid_request")}, nil } token, user, err := s.auth.Login(request.Body.Password) switch { case errors.Is(err, auth.ErrLocalLoginDisabled): return Login400JSONResponse{ErrorJSONResponse: errJSON("local password login is disabled", "local_login_disabled")}, nil case errors.Is(err, auth.ErrInvalidCredentials): return Login401JSONResponse(Error{ Error: "invalid credentials", Code: stringPtr("invalid_credentials"), }), nil case err != nil: s.logger.Error().Err(err).Msg("local login") return Login400JSONResponse{ErrorJSONResponse: errJSON("could not sign in", "internal_error")}, nil default: return Login200JSONResponse(LoginResponse{ Token: token, User: toAPIAuthUser(user), }), nil } } func (s *Server) GetCurrentUser(ctx context.Context, _ GetCurrentUserRequestObject) (GetCurrentUserResponseObject, error) { _, span := s.tracer.Start(ctx, "GetCurrentUser") defer span.End() ginCtx, ok := ctx.(*gin.Context) if !ok { return GetCurrentUser401JSONResponse{ErrorJSONResponse: errJSON("authentication required", "unauthenticated")}, nil } user, ok := CurrentUser(ginCtx) if !ok { return GetCurrentUser401JSONResponse{ErrorJSONResponse: errJSON("authentication required", "unauthenticated")}, nil } return GetCurrentUser200JSONResponse(AuthMeResponse{ Authenticated: true, User: authUserPtr(toAPIAuthUser(user)), }), nil } func (s *Server) Logout(context.Context, LogoutRequestObject) (LogoutResponseObject, error) { return Logout204Response{}, nil } func toAPIAuthUser(user auth.User) AuthUser { roles := user.Roles if roles == nil { roles = []string{} } out := AuthUser{ Id: user.ID, Roles: roles, CanAdmin: user.CanAdmin, CanView: user.CanView, } if user.Name != "" { name := user.Name out.Name = &name } if user.Email != "" { email := openapi_types.Email(user.Email) out.Email = &email } return out } func authUserPtr(user AuthUser) *AuthUser { return &user } func stringPtr(value string) *string { return &value }