1
0
forked from baron/baron-sso

feat: restore explicit loginId field and add to userfront signup flow

- Revert the removal of loginId from adminfront and backend.
- Prevent phone normalization logic from mangling custom employee ID login fields.
- Add an explicit 'loginId' optional input field to the userfront signup UI.
- Update AuthProxyService.signup and backend AuthHandler.Signup to transmit and map the 'loginId' parameter properly.
This commit is contained in:
2026-03-26 14:22:43 +09:00
parent 85b2049a61
commit aa60a22d57
4 changed files with 33 additions and 6 deletions

View File

@@ -451,8 +451,23 @@ func (h *AuthHandler) Signup(c *fiber.Ctx) error {
// grade는 기존 스키마 필수 키이므로 기본값을 설정
"grade": "member",
}
if req.LoginID != "" {
attributes["id"] = req.LoginID
}
// Sync custom field to LoginID if configured
if tenantID != nil && h.TenantService != nil {
if tenant, err := h.TenantService.GetTenant(c.Context(), *tenantID); err == nil && tenant != nil {
if loginIdField, ok := tenant.Config["loginIdField"].(string); ok && loginIdField != "" {
syncLoginID(attributes, req.Metadata, *tenantID, loginIdField)
}
}
}
brokerUser := &domain.BrokerUser{
Email: req.Email,
LoginID: extractTraitString(attributes, "id"),
Name: req.Name,
PhoneNumber: normalizedPhone,
Attributes: attributes,

View File

@@ -1533,12 +1533,6 @@ func syncLoginID(traits map[string]interface{}, metadata map[string]any, tenantI
}
if loginID != "" {
// Normalize if it looks like a phone number to be consistent with other identifiers
normalized := normalizePhoneNumber(loginID)
if normalized != "" {
loginID = normalized
}
slog.Info("Syncing LoginID from custom field", "field", loginIDField, "value", loginID, "tenantID", tenantID)
traits["id"] = loginID
}

View File

@@ -934,6 +934,7 @@ class AuthProxyService {
static Future<void> signup({
required String email,
String? loginId,
required String password,
required String name,
required String phone,
@@ -949,6 +950,7 @@ class AuthProxyService {
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'email': email,
if (loginId != null && loginId.isNotEmpty) 'loginId': loginId,
'password': password,
'name': name,
'phone': phone,

View File

@@ -31,6 +31,7 @@ class _SignupScreenState extends State<SignupScreen> {
// Controllers
final _emailController = TextEditingController();
final _loginIdController = TextEditingController();
final _emailCodeController = TextEditingController();
final _phoneController = TextEditingController();
final _phoneCodeController = TextEditingController();
@@ -98,6 +99,7 @@ class _SignupScreenState extends State<SignupScreen> {
_emailTimer?.cancel();
_phoneTimer?.cancel();
_emailController.dispose();
_loginIdController.dispose();
_emailCodeController.dispose();
_phoneController.dispose();
_phoneCodeController.dispose();
@@ -311,6 +313,7 @@ class _SignupScreenState extends State<SignupScreen> {
try {
await AuthProxyService.signup(
email: _emailController.text.trim(),
loginId: _loginIdController.text.trim(),
password: _passwordController.text,
name: _nameController.text.trim(),
phone: _phoneController.text.trim(),
@@ -1421,6 +1424,19 @@ class _SignupScreenState extends State<SignupScreen> {
),
),
const SizedBox(height: 18),
_buildProfileFieldGroup(
title: '로그인 ID (선택)',
description: '이메일/전화번호 외에 별도의 식별자로 로그인할 때 사용합니다.',
isDesktop: isDesktop,
child: TextFormField(
controller: _loginIdController,
decoration: const InputDecoration(
labelText: '사번 또는 아이디',
border: OutlineInputBorder(),
),
),
),
const SizedBox(height: 18),
_buildProfileFieldGroup(
title: tr('ui.userfront.signup.profile.affiliation_type'),
description: _isAffiliateEmail