feat: provider source for oauth-providers and sign-in helpers for social login
- classes.OAuthProvider and classes.OAuthProviderSource; GET /oauth-providers looks the source up per request and keeps the empty body without one - exported RegistrationSettings, RegistrationsFromIP, RefreshTTL, RemoteIP - RegisterOptions.PasswordLess (has_self_set_password=false) and FinishLogin (restore + reactivate mail, last_ip_address, last_seen; no event) - TestOAuthProvidersSourceSmoke, TestSocialHooksSmoke; README
This commit is contained in:
@@ -212,17 +212,36 @@ func Refresh(app *backpack.App) http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// OAuthProviders reports that this app configures no social providers.
|
||||
// OAuthProviders lists the social sign-in providers a social-login plugin
|
||||
// has enabled, as {success: true, providers: [{name, label}]}. The plugin
|
||||
// publishes a classes.OAuthProviderSource, looked up on every request
|
||||
// because it boots after this plugin; without one the list is empty.
|
||||
func OAuthProviders(app *backpack.App) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
providers := []any{}
|
||||
if src, ok := oauthProviderSource(app); ok {
|
||||
for _, p := range src.EnabledOAuthProviders(r.Context()) {
|
||||
providers = append(providers, map[string]any{"name": p.Name, "label": p.Label})
|
||||
}
|
||||
}
|
||||
writeJSON(w, http.StatusOK, map[string]any{
|
||||
"success": true,
|
||||
"providers": wire.Slice([]any{}),
|
||||
"providers": wire.Slice(providers),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const forgotPasswordBody = "If that email exists, a reset link has been sent."
|
||||
// oauthProviderSource returns the social-login plugin's published provider
|
||||
// source, if any.
|
||||
func oauthProviderSource(app *backpack.App) (classes.OAuthProviderSource, bool) {
|
||||
if app == nil {
|
||||
return nil, false
|
||||
}
|
||||
src, ok := app.Lookup[classes.OAuthProviderSource]()
|
||||
return src, ok && src != nil
|
||||
}
|
||||
|
||||
const forgotPasswordBody ="If that email exists, a reset link has been sent."
|
||||
|
||||
// ForgotPassword always returns the same 200 body. A real account also gets a reset mail.
|
||||
func ForgotPassword(app *backpack.App) http.HandlerFunc {
|
||||
@@ -682,6 +701,23 @@ func Register(app *backpack.App) http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// RegistrationSettings returns the registration settings /register
|
||||
// applies: allow is golem15.user.registration.allow_registration (default
|
||||
// true), throttle is golem15.user.registration.use_register_throttle
|
||||
// (default true), mode is golem15.user.activation.activate_mode (auto, user
|
||||
// or admin; default auto) and require is
|
||||
// golem15.user.activation.require_activation (default true).
|
||||
func RegistrationSettings(app *backpack.App) (allow, throttle bool, mode string, require bool) {
|
||||
return registrationSettings(app)
|
||||
}
|
||||
|
||||
// RegistrationsFromIP counts the users created from ip in the last 60
|
||||
// minutes (created_ip_address). /register refuses a registration when the
|
||||
// throttle is on and the count is 3 or more. A query error counts as 0.
|
||||
func RegistrationsFromIP(ctx context.Context, gdb *gorm.DB, ip string) int64 {
|
||||
return registrationsFromIP(ctx, gdb, ip)
|
||||
}
|
||||
|
||||
func registrationSettings(app *backpack.App) (allow, throttle bool, mode string, require bool) {
|
||||
allow, throttle, require = true, true, true
|
||||
mode = "auto"
|
||||
@@ -831,6 +867,13 @@ func mintFor(app *backpack.App, secret string, user *models.User, issuer string)
|
||||
return token, err
|
||||
}
|
||||
|
||||
// RefreshTTL is the refresh window of a session token:
|
||||
// golem15.user.jwt.refresh_ttl minutes, default 20160 (two weeks). A cookie
|
||||
// carrying the token should live this long.
|
||||
func RefreshTTL(app *backpack.App) time.Duration {
|
||||
return refreshTTL(app)
|
||||
}
|
||||
|
||||
func refreshTTL(app *backpack.App) time.Duration {
|
||||
mins := 20160
|
||||
if app != nil && app.Config != nil && app.Config.Int("golem15.user.jwt.refresh_ttl") > 0 {
|
||||
@@ -1012,6 +1055,13 @@ func requestURL(r *http.Request) string {
|
||||
return scheme + "://" + r.Host + r.URL.Path
|
||||
}
|
||||
|
||||
// RemoteIP returns the host part of r.RemoteAddr, the address /login uses
|
||||
// for its throttle (r.RemoteAddr itself when it has no port, "" when it is
|
||||
// empty). /register records surf.ClientIP with the trusted proxies instead.
|
||||
func RemoteIP(r *http.Request) string {
|
||||
return remoteIP(r)
|
||||
}
|
||||
|
||||
func remoteIP(r *http.Request) string {
|
||||
if r.RemoteAddr == "" {
|
||||
return ""
|
||||
|
||||
Reference in New Issue
Block a user