Refactor user authentication to unify entry configuration handling
- Renamed and updated functions and tests to replace 'login' terminology with 'entry', reflecting the unified handling of login and registration processes. - Removed deprecated login configuration functions and structures, streamlining the codebase. - Enhanced test coverage for entry configuration retrieval and validation, ensuring comprehensive testing of the new unified approach. - Improved error handling and logging for entry configuration scenarios, contributing to a better user experience during authentication.
This commit is contained in:
parent
b43a38b387
commit
d1a9e5c892
7 changed files with 47 additions and 238 deletions
|
|
@ -22,19 +22,19 @@ func TestGetTeamConfigFunction(t *testing.T) {
|
||||||
assert.Nil(t, teamConfig, "Should return nil when no config is loaded")
|
assert.Nil(t, teamConfig, "Should return nil when no config is loaded")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGetPublicConfigFunction tests the GetPublicConfig function
|
// TestGetEntryConfigFunction tests the GetEntryConfig function
|
||||||
func TestGetPublicConfigFunction(t *testing.T) {
|
func TestGetEntryConfigFunction(t *testing.T) {
|
||||||
// Test with empty locale
|
// Test with empty locale
|
||||||
publicConfig := user.GetPublicConfig("")
|
entryConfig := user.GetEntryConfig("")
|
||||||
assert.Nil(t, publicConfig, "Should return nil when no config is loaded")
|
assert.Nil(t, entryConfig, "Should return nil when no config is loaded")
|
||||||
|
|
||||||
// Test with specific locale
|
// Test with specific locale
|
||||||
publicConfig = user.GetPublicConfig("en")
|
entryConfig = user.GetEntryConfig("en")
|
||||||
assert.Nil(t, publicConfig, "Should return nil when no config is loaded")
|
assert.Nil(t, entryConfig, "Should return nil when no config is loaded")
|
||||||
|
|
||||||
// Test with invalid locale
|
// Test with invalid locale
|
||||||
publicConfig = user.GetPublicConfig("invalid")
|
entryConfig = user.GetEntryConfig("invalid")
|
||||||
assert.Nil(t, publicConfig, "Should return nil when no config is loaded")
|
assert.Nil(t, entryConfig, "Should return nil when no config is loaded")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestGetYaoClientConfigFunction tests the GetYaoClientConfig function
|
// TestGetYaoClientConfigFunction tests the GetYaoClientConfig function
|
||||||
|
|
|
||||||
|
|
@ -30,16 +30,16 @@ func TestUserLoginConfig(t *testing.T) {
|
||||||
|
|
||||||
// Note: user.Load is automatically called by openapi.Load in testutils.Prepare
|
// Note: user.Load is automatically called by openapi.Load in testutils.Prepare
|
||||||
|
|
||||||
// Test API endpoints for signin configuration
|
// Test API endpoints for entry configuration
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
endpoint string
|
endpoint string
|
||||||
expectCode int
|
expectCode int
|
||||||
}{
|
}{
|
||||||
{"get login config without locale", "/user/login", 200},
|
{"get entry config without locale", "/user/entry", 200},
|
||||||
{"get login config with en locale", "/user/login?locale=en", 200},
|
{"get entry config with en locale", "/user/entry?locale=en", 200},
|
||||||
{"get login config with zh-cn locale", "/user/login?locale=zh-cn", 200},
|
{"get entry config with zh-cn locale", "/user/entry?locale=zh-cn", 200},
|
||||||
{"get login config with invalid locale", "/user/login?locale=invalid", 200}, // should fallback to default
|
{"get entry config with invalid locale", "/user/entry?locale=invalid", 200}, // should fallback to default
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
|
@ -57,7 +57,7 @@ func TestUserLoginConfig(t *testing.T) {
|
||||||
body, err := io.ReadAll(resp.Body)
|
body, err := io.ReadAll(resp.Body)
|
||||||
assert.NoError(t, err, "Should read response body")
|
assert.NoError(t, err, "Should read response body")
|
||||||
|
|
||||||
var config user.Config
|
var config user.EntryConfig
|
||||||
err = json.Unmarshal(body, &config)
|
err = json.Unmarshal(body, &config)
|
||||||
assert.NoError(t, err, "Should parse JSON response")
|
assert.NoError(t, err, "Should parse JSON response")
|
||||||
|
|
||||||
|
|
@ -102,13 +102,13 @@ func TestUserLoginConfigLoad(t *testing.T) {
|
||||||
err := user.Load(config.Conf)
|
err := user.Load(config.Conf)
|
||||||
assert.NoError(t, err, "user.Load should succeed")
|
assert.NoError(t, err, "user.Load should succeed")
|
||||||
|
|
||||||
// Test that we can get public config
|
// Test that we can get entry config
|
||||||
publicConfig := user.GetPublicConfig("")
|
entryConfig := user.GetEntryConfig("")
|
||||||
if publicConfig != nil {
|
if entryConfig != nil {
|
||||||
t.Logf("Public config loaded with title: %s", publicConfig.Title)
|
t.Logf("Entry config loaded with title: %s", entryConfig.Title)
|
||||||
assert.IsType(t, &user.Config{}, publicConfig, "Should return correct config type")
|
assert.IsType(t, &user.EntryConfig{}, entryConfig, "Should return correct config type")
|
||||||
} else {
|
} else {
|
||||||
t.Log("No public config found")
|
t.Log("No entry config found")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -122,19 +122,23 @@ func TestUserLoginConfigStructure(t *testing.T) {
|
||||||
// Note: user.Load is automatically called by openapi.Load in testutils.Prepare
|
// Note: user.Load is automatically called by openapi.Load in testutils.Prepare
|
||||||
|
|
||||||
// Get a config to test structure
|
// Get a config to test structure
|
||||||
config := user.GetPublicConfig("")
|
config := user.GetEntryConfig("")
|
||||||
if config != nil {
|
if config != nil {
|
||||||
t.Logf("Config loaded successfully with title: %s", config.Title)
|
t.Logf("Config loaded successfully with title: %s", config.Title)
|
||||||
|
|
||||||
// Verify config structure is valid
|
// Verify config structure is valid
|
||||||
assert.IsType(t, &user.Config{}, config, "Should return correct config type")
|
assert.IsType(t, &user.EntryConfig{}, config, "Should return correct config type")
|
||||||
|
|
||||||
// Test new configuration fields
|
// Test new configuration fields
|
||||||
assert.IsType(t, "", config.ClientID, "ClientID should be string")
|
assert.IsType(t, "", config.ClientID, "ClientID should be string")
|
||||||
assert.IsType(t, "", config.ClientSecret, "ClientSecret should be string")
|
assert.IsType(t, "", config.ClientSecret, "ClientSecret should be string")
|
||||||
assert.IsType(t, false, config.Default, "Default should be boolean")
|
assert.IsType(t, false, config.Default, "Default should be boolean")
|
||||||
t.Logf("Config has ClientID: %t, ClientSecret: %t, Default: %t",
|
assert.IsType(t, false, config.AutoLogin, "AutoLogin should be boolean")
|
||||||
config.ClientID != "", config.ClientSecret != "", config.Default)
|
assert.IsType(t, "", config.Role, "Role should be string")
|
||||||
|
assert.IsType(t, "", config.Type, "Type should be string")
|
||||||
|
assert.IsType(t, false, config.InviteRequired, "InviteRequired should be boolean")
|
||||||
|
t.Logf("Config has ClientID: %t, ClientSecret: %t, Default: %t, AutoLogin: %t",
|
||||||
|
config.ClientID != "", config.ClientSecret != "", config.Default, config.AutoLogin)
|
||||||
|
|
||||||
// Test form configuration
|
// Test form configuration
|
||||||
if config.Form != nil {
|
if config.Form != nil {
|
||||||
|
|
@ -162,6 +166,13 @@ func TestUserLoginConfigStructure(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test messenger configuration (for registration)
|
||||||
|
if config.Messenger != nil {
|
||||||
|
t.Logf("Messenger configuration found")
|
||||||
|
assert.IsType(t, "", config.Messenger.Channel, "Messenger channel should be string")
|
||||||
|
assert.IsType(t, map[string]string{}, config.Messenger.Templates, "Messenger templates should be map")
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
t.Log("No user configuration found")
|
t.Log("No user configuration found")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ func TestUserLogin(t *testing.T) {
|
||||||
|
|
||||||
// Note: user.Load is automatically called by openapi.Load in testutils.Prepare
|
// Note: user.Load is automatically called by openapi.Load in testutils.Prepare
|
||||||
|
|
||||||
// Test login endpoint (currently empty implementation)
|
// Test entry endpoint (unified login/register, currently empty implementation)
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
method string
|
method string
|
||||||
|
|
@ -37,16 +37,16 @@ func TestUserLogin(t *testing.T) {
|
||||||
expectCode int
|
expectCode int
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"post login without credentials",
|
"post entry without credentials",
|
||||||
"POST",
|
"POST",
|
||||||
"/user/login",
|
"/user/entry",
|
||||||
map[string]interface{}{},
|
map[string]interface{}{},
|
||||||
200, // Currently empty implementation, may change when implemented
|
200, // Currently empty implementation, may change when implemented
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"post login with credentials",
|
"post entry with credentials",
|
||||||
"POST",
|
"POST",
|
||||||
"/user/login",
|
"/user/entry",
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"username": "testuser",
|
"username": "testuser",
|
||||||
"password": "testpass",
|
"password": "testpass",
|
||||||
|
|
@ -54,9 +54,9 @@ func TestUserLogin(t *testing.T) {
|
||||||
200, // Currently empty implementation, may change when implemented
|
200, // Currently empty implementation, may change when implemented
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"post login with email",
|
"post entry with email",
|
||||||
"POST",
|
"POST",
|
||||||
"/user/login",
|
"/user/entry",
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"email": "test@example.com",
|
"email": "test@example.com",
|
||||||
"password": "testpass",
|
"password": "testpass",
|
||||||
|
|
@ -149,7 +149,7 @@ func TestUserLoginValidation(t *testing.T) {
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
requestURL := serverURL + baseURL + "/user/login"
|
requestURL := serverURL + baseURL + "/user/entry"
|
||||||
|
|
||||||
var req *http.Request
|
var req *http.Request
|
||||||
var err error
|
var err error
|
||||||
|
|
|
||||||
|
|
@ -23,14 +23,8 @@ var (
|
||||||
// Client config
|
// Client config
|
||||||
yaoClientConfig *YaoClientConfig
|
yaoClientConfig *YaoClientConfig
|
||||||
|
|
||||||
// Full configurations with sensitive data (for backend use)
|
|
||||||
fullConfigs = make(map[string]*Config)
|
|
||||||
// Public configurations without sensitive data (for frontend use)
|
|
||||||
publicConfigs = make(map[string]*Config)
|
|
||||||
// Global providers map (decoupled from locale-specific configs)
|
// Global providers map (decoupled from locale-specific configs)
|
||||||
providers = make(map[string]*Provider)
|
providers = make(map[string]*Provider)
|
||||||
// Default configuration (marked with default: true)
|
|
||||||
defaultConfig *Config
|
|
||||||
// Team configurations by locale
|
// Team configurations by locale
|
||||||
teamConfigs = make(map[string]*TeamConfig)
|
teamConfigs = make(map[string]*TeamConfig)
|
||||||
// Entry configurations by locale (unified login + register)
|
// Entry configurations by locale (unified login + register)
|
||||||
|
|
@ -45,21 +39,12 @@ func Load(appConfig config.Config) error {
|
||||||
defer configMutex.Unlock()
|
defer configMutex.Unlock()
|
||||||
|
|
||||||
// Clear existing configurations
|
// Clear existing configurations
|
||||||
fullConfigs = make(map[string]*Config)
|
|
||||||
publicConfigs = make(map[string]*Config)
|
|
||||||
providers = make(map[string]*Provider)
|
providers = make(map[string]*Provider)
|
||||||
defaultConfig = nil
|
|
||||||
teamConfigs = make(map[string]*TeamConfig)
|
teamConfigs = make(map[string]*TeamConfig)
|
||||||
entryConfigs = make(map[string]*EntryConfig)
|
entryConfigs = make(map[string]*EntryConfig)
|
||||||
|
|
||||||
// Load signin configurations from openapi/user/signin directory
|
|
||||||
err := loadSigninConfigs(appConfig.Root)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to load signin configs: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load entry configurations from openapi/user/entry directory
|
// Load entry configurations from openapi/user/entry directory
|
||||||
err = loadEntryConfigs(appConfig.Root)
|
err := loadEntryConfigs(appConfig.Root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to load entry configs: %v", err)
|
return fmt.Errorf("failed to load entry configs: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -254,75 +239,6 @@ func loadProviders(_ string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadSigninConfigs loads all signin configurations from the openapi/user/signin directory
|
|
||||||
func loadSigninConfigs(_ string) error {
|
|
||||||
// Use Walk to find all configuration files in the signin directory
|
|
||||||
err := application.App.Walk("openapi/user/signin", func(root, filename string, isdir bool) error {
|
|
||||||
if isdir {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only process .yao files
|
|
||||||
if !strings.HasSuffix(filename, ".yao") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract locale from filename (basename without extension)
|
|
||||||
baseName := filepath.Base(filename)
|
|
||||||
locale := strings.ToLower(strings.TrimSuffix(baseName, ".yao"))
|
|
||||||
|
|
||||||
// Read configuration
|
|
||||||
configRaw, err := application.App.Read(filename)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to read signin config %s: %v", filename, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the configuration
|
|
||||||
var config Config
|
|
||||||
err = application.Parse(filename, configRaw, &config)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to parse signin config %s: %v", filename, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process ENV variables in the configuration
|
|
||||||
processConfigENVVariables(&config)
|
|
||||||
|
|
||||||
// Store full configuration
|
|
||||||
fullConfigs[locale] = &config
|
|
||||||
|
|
||||||
// Create public configuration (without sensitive data)
|
|
||||||
publicConfig := config
|
|
||||||
publicConfig.ClientSecret = "" // Remove sensitive data
|
|
||||||
|
|
||||||
// Remove captcha secret from public config
|
|
||||||
if publicConfig.Form != nil && publicConfig.Form.Captcha != nil && publicConfig.Form.Captcha.Options != nil {
|
|
||||||
// Create a copy of captcha options without the secret
|
|
||||||
captchaOptions := make(map[string]interface{})
|
|
||||||
for k, v := range publicConfig.Form.Captcha.Options {
|
|
||||||
if k != "secret" {
|
|
||||||
captchaOptions[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
publicConfig.Form.Captcha.Options = captchaOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
publicConfigs[locale] = &publicConfig
|
|
||||||
|
|
||||||
// Set as default if marked
|
|
||||||
if config.Default {
|
|
||||||
defaultConfig = &config
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to walk signin directory: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// loadTeamConfigs loads all team configurations from the openapi/user/team directory
|
// loadTeamConfigs loads all team configurations from the openapi/user/team directory
|
||||||
func loadTeamConfigs(_ string) error {
|
func loadTeamConfigs(_ string) error {
|
||||||
// Use Walk to find all configuration files in the team directory
|
// Use Walk to find all configuration files in the team directory
|
||||||
|
|
@ -366,41 +282,6 @@ func loadTeamConfigs(_ string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPublicConfig returns the public configuration for a given locale
|
|
||||||
func GetPublicConfig(locale string) *Config {
|
|
||||||
configMutex.RLock()
|
|
||||||
defer configMutex.RUnlock()
|
|
||||||
|
|
||||||
// Normalize language code to lowercase
|
|
||||||
if locale != "" {
|
|
||||||
locale = strings.ToLower(locale)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to get the specific locale configuration
|
|
||||||
if config, exists := publicConfigs[locale]; exists {
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback to default config's public version
|
|
||||||
if defaultConfig != nil {
|
|
||||||
// Find the public version of the default config
|
|
||||||
for lang, fullConfig := range fullConfigs {
|
|
||||||
if fullConfig == defaultConfig {
|
|
||||||
if publicConfig, exists := publicConfigs[lang]; exists {
|
|
||||||
return publicConfig
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no default, try to get any available configuration
|
|
||||||
for _, config := range publicConfigs {
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetProvider returns a provider by ID
|
// GetProvider returns a provider by ID
|
||||||
func GetProvider(providerID string) (*Provider, error) {
|
func GetProvider(providerID string) (*Provider, error) {
|
||||||
configMutex.RLock()
|
configMutex.RLock()
|
||||||
|
|
@ -570,37 +451,6 @@ func processFormConfigENVVariables(form *FormConfig) []string {
|
||||||
return missingEnvVars
|
return missingEnvVars
|
||||||
}
|
}
|
||||||
|
|
||||||
// processConfigENVVariables processes environment variables in the signin configuration
|
|
||||||
func processConfigENVVariables(config *Config) {
|
|
||||||
var missingEnvVars []string
|
|
||||||
|
|
||||||
// Process client_id and client_secret
|
|
||||||
if strings.HasPrefix(config.ClientID, "$ENV.") {
|
|
||||||
envVar := strings.TrimPrefix(config.ClientID, "$ENV.")
|
|
||||||
if _, exists := os.LookupEnv(envVar); !exists {
|
|
||||||
missingEnvVars = append(missingEnvVars, envVar)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
config.ClientID = replaceENVVar(config.ClientID)
|
|
||||||
|
|
||||||
if strings.HasPrefix(config.ClientSecret, "$ENV.") {
|
|
||||||
envVar := strings.TrimPrefix(config.ClientSecret, "$ENV.")
|
|
||||||
if _, exists := os.LookupEnv(envVar); !exists {
|
|
||||||
missingEnvVars = append(missingEnvVars, envVar)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
config.ClientSecret = replaceENVVar(config.ClientSecret)
|
|
||||||
|
|
||||||
// Process form configuration
|
|
||||||
formMissingVars := processFormConfigENVVariables(config.Form)
|
|
||||||
missingEnvVars = append(missingEnvVars, formMissingVars...)
|
|
||||||
|
|
||||||
// Log warning for missing environment variables
|
|
||||||
if len(missingEnvVars) > 0 {
|
|
||||||
fmt.Printf("Warning: The following environment variables are not set in signin configuration: %v\n", missingEnvVars)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// loadEntryConfigs loads all entry configurations from the openapi/user/entry directory
|
// loadEntryConfigs loads all entry configurations from the openapi/user/entry directory
|
||||||
// Entry config merges signin and register configurations
|
// Entry config merges signin and register configurations
|
||||||
func loadEntryConfigs(_ string) error {
|
func loadEntryConfigs(_ string) error {
|
||||||
|
|
|
||||||
|
|
@ -15,45 +15,9 @@ import (
|
||||||
"github.com/yaoapp/yao/openapi/oauth/providers/user"
|
"github.com/yaoapp/yao/openapi/oauth/providers/user"
|
||||||
oauthtypes "github.com/yaoapp/yao/openapi/oauth/types"
|
oauthtypes "github.com/yaoapp/yao/openapi/oauth/types"
|
||||||
"github.com/yaoapp/yao/openapi/response"
|
"github.com/yaoapp/yao/openapi/response"
|
||||||
"github.com/yaoapp/yao/openapi/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// getLoginConfig is the handler for get login configuration (mapped from /signin)
|
// getCaptcha is the handler for get captcha image for entry (login/register)
|
||||||
func getLoginConfig(c *gin.Context) {
|
|
||||||
// Get locale from query parameter (optional)
|
|
||||||
locale := c.Query("locale")
|
|
||||||
|
|
||||||
// Get public configuration for the specified locale
|
|
||||||
config := GetPublicConfig(locale)
|
|
||||||
|
|
||||||
// Set session id if not exists
|
|
||||||
sid := utils.GetSessionID(c)
|
|
||||||
if sid == "" {
|
|
||||||
sid = generateSessionID()
|
|
||||||
response.SendSessionCookie(c, sid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no configuration found, return error
|
|
||||||
if config == nil {
|
|
||||||
errorResp := &response.ErrorResponse{
|
|
||||||
Code: response.ErrInvalidRequest.Code,
|
|
||||||
ErrorDescription: "No signin configuration found for the requested locale",
|
|
||||||
}
|
|
||||||
response.RespondWithError(c, response.StatusNotFound, errorResp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the public configuration
|
|
||||||
response.RespondWithSuccess(c, response.StatusOK, config)
|
|
||||||
}
|
|
||||||
|
|
||||||
// login is the handler for login (password login, mapped from /signin)
|
|
||||||
func login(c *gin.Context) {
|
|
||||||
// This is a placeholder - the original signin function was empty
|
|
||||||
// You may need to implement the actual login logic here
|
|
||||||
}
|
|
||||||
|
|
||||||
// getCaptcha is the handler for get captcha image for login
|
|
||||||
func getCaptcha(c *gin.Context) {
|
func getCaptcha(c *gin.Context) {
|
||||||
var option helper.CaptchaOption = helper.NewCaptchaOption()
|
var option helper.CaptchaOption = helper.NewCaptchaOption()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,20 +23,6 @@ const (
|
||||||
ScopeTeamSelection = "team_selection"
|
ScopeTeamSelection = "team_selection"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config represents the signin page configuration
|
|
||||||
type Config struct {
|
|
||||||
Title string `json:"title,omitempty"`
|
|
||||||
Description string `json:"description,omitempty"`
|
|
||||||
Default bool `json:"default,omitempty"`
|
|
||||||
SuccessURL string `json:"success_url,omitempty"`
|
|
||||||
FailureURL string `json:"failure_url,omitempty"`
|
|
||||||
ClientID string `json:"client_id,omitempty"`
|
|
||||||
ClientSecret string `json:"client_secret,omitempty"`
|
|
||||||
Form *FormConfig `json:"form,omitempty"`
|
|
||||||
Token *TokenConfig `json:"token,omitempty"`
|
|
||||||
ThirdParty *ThirdParty `json:"third_party,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// FormConfig represents the form configuration
|
// FormConfig represents the form configuration
|
||||||
type FormConfig struct {
|
type FormConfig struct {
|
||||||
Username *UsernameConfig `json:"username,omitempty"`
|
Username *UsernameConfig `json:"username,omitempty"`
|
||||||
|
|
|
||||||
|
|
@ -27,12 +27,10 @@ func init() {
|
||||||
// Attach attaches the signin handlers to the router
|
// Attach attaches the signin handlers to the router
|
||||||
func Attach(group *gin.RouterGroup, oauth types.OAuth) {
|
func Attach(group *gin.RouterGroup, oauth types.OAuth) {
|
||||||
|
|
||||||
// User Authentication (migrated from /signin)
|
// User Authentication
|
||||||
group.GET("/login", getLoginConfig) // Get login page config (public) - migrated from /signin
|
|
||||||
group.POST("/login", login) // User login (public) - migrated from /signin
|
|
||||||
group.GET("/login/captcha", getCaptcha) // Get captcha for login (public)
|
|
||||||
group.GET("/entry", getEntryConfig) // Get unified auth entry config (public)
|
group.GET("/entry", getEntryConfig) // Get unified auth entry config (public)
|
||||||
group.POST("/entry", entry) // Unified auth entry (login/register) (public)
|
group.POST("/entry", entry) // Unified auth entry (login/register) (public)
|
||||||
|
group.GET("/entry/captcha", getCaptcha) // Get captcha for login/register (public)
|
||||||
group.POST("/logout", oauth.Guard, placeholder) // User logout
|
group.POST("/logout", oauth.Guard, placeholder) // User logout
|
||||||
|
|
||||||
// Logined User Settings
|
// Logined User Settings
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue