mirror of
https://github.com/warmbly/warmbly.git
synced 2026-08-19 00:01:14 +00:00
109 lines
4.3 KiB
Go
109 lines
4.3 KiB
Go
package handler
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/warmbly/warmbly/internal/config"
|
|
)
|
|
|
|
// DeploymentAuthConfig is what the login screen needs to render truthfully.
|
|
//
|
|
// Without it the frontends guess: the Turnstile widget mounted even when
|
|
// captcha was off server-side, social buttons rendered with no client
|
|
// configured, and nothing told a self-hoster their login code was going to a
|
|
// log file. Everything here is public, non-secret configuration.
|
|
type DeploymentAuthConfig struct {
|
|
// Captcha reports whether a Turnstile token is actually verified. When
|
|
// false the client must not mount the widget: a self-hosted or air-gapped
|
|
// install cannot reach challenges.cloudflare.com.
|
|
Captcha bool `json:"captcha"`
|
|
|
|
// PasswordLogin is false when the deployment authenticates only through
|
|
// OIDC or passkeys.
|
|
PasswordLogin bool `json:"password_login"`
|
|
|
|
// LoginCode is always, new_device or off. The client uses it to decide
|
|
// whether to expect a code step, and to explain the flow up front.
|
|
LoginCode string `json:"login_code"`
|
|
|
|
// Registration is false, invite_only or true, already resolved through the
|
|
// first-launch exemption, so a brand new instance reports open signups.
|
|
Registration string `json:"registration"`
|
|
|
|
// EmailVerification reports whether a signup must confirm an emailed code.
|
|
EmailVerification bool `json:"email_verification"`
|
|
|
|
// MailDelivers is false when the platform mail transport does not put mail
|
|
// on the wire (MAIL_TRANSPORT=log). The login screen tells the operator
|
|
// where to find codes instead of leaving them waiting for an email.
|
|
MailDelivers bool `json:"mail_delivers"`
|
|
|
|
// Passkeys reports whether WebAuthn can work here at all. It needs a
|
|
// secure context, so a plain-http LAN origin disables it rather than
|
|
// failing in the browser with an opaque error.
|
|
Passkeys bool `json:"passkeys"`
|
|
|
|
Providers []string `json:"providers"`
|
|
|
|
// SelfHosted lets the UI drop hosted-only affordances (billing prompts,
|
|
// referral fields) that make no sense on someone's own server.
|
|
SelfHosted bool `json:"self_hosted"`
|
|
|
|
// BillingEnabled mirrors the backend feature gate exactly: false when
|
|
// BILLING_PROVIDER=none, in which case every feature is unlocked and the
|
|
// dashboard must not present the org as being on a trial or free tier.
|
|
BillingEnabled bool `json:"billing_enabled"`
|
|
|
|
// SetupRequired is true while the instance has no accounts at all. The
|
|
// login screen redirects to the setup page rather than showing a form
|
|
// nobody can yet use.
|
|
SetupRequired bool `json:"setup_required"`
|
|
|
|
// InvitesRequired mirrors registration == invite_only, precomputed so the
|
|
// client does not reimplement the meaning of a tri-state string.
|
|
InvitesRequired bool `json:"invites_required"`
|
|
|
|
// DocsURL is where to send someone whose signup was refused by deployment
|
|
// policy rather than by anything they did wrong.
|
|
DocsURL string `json:"docs_url"`
|
|
}
|
|
|
|
// accountsDocsURL is the page every registration refusal points at.
|
|
const accountsDocsURL = "https://docs.warmbly.com/development/accounts-and-access/"
|
|
|
|
// AuthConfig serves GET /v1/auth/config. Public and unauthenticated by design:
|
|
// it is the first request the login screen makes.
|
|
func (h *Handler) AuthConfig(c *gin.Context) {
|
|
policy := h.AuthService.Policy()
|
|
|
|
providers := []string{}
|
|
if h.ExternalAuthProviders.GoogleIOSClientID != "" || h.GoogleWebSignIn {
|
|
providers = append(providers, "google")
|
|
}
|
|
if h.ExternalAuthProviders.AppleBundleID != "" || h.AppleWebSignIn {
|
|
providers = append(providers, "apple")
|
|
}
|
|
if h.OIDCEnabled {
|
|
providers = append(providers, "oidc")
|
|
}
|
|
|
|
registration := h.AuthService.RegistrationMode(c.Request.Context())
|
|
|
|
c.JSON(http.StatusOK, DeploymentAuthConfig{
|
|
Captcha: config.CaptchaProvider() != "none",
|
|
PasswordLogin: !policy.DisablePasswordLogin,
|
|
LoginCode: policy.LoginCode,
|
|
Registration: registration,
|
|
EmailVerification: policy.RequireEmailVerification,
|
|
MailDelivers: h.MailDelivers,
|
|
Passkeys: h.PasskeysUsable,
|
|
Providers: providers,
|
|
SelfHosted: config.SelfHosted(),
|
|
BillingEnabled: config.BillingProvider() != "none",
|
|
SetupRequired: h.BootstrapService != nil && h.BootstrapService.Required(c.Request.Context()),
|
|
InvitesRequired: registration == config.RegistrationInviteOnly,
|
|
DocsURL: accountsDocsURL,
|
|
})
|
|
}
|