forked from baron/baron-sso
feat: implement multi-identifier architecture (Issue #496)
- Database: Add user_login_ids table for 1:N identifier mapping and remove legacy login_id column - Kratos: Update identity schema to use custom_login_ids array instead of a single id trait - Backend: Implement syncCustomLoginIDs to collect isLoginId fields across tenant schemas - Backend: Add backtracking logic to auto-assign session tenant based on used login identifier - Backend: Add 409 Conflict exception handling for Create/Update operations - AdminFront: Refactor UserDetailPage to a tabbed grid layout (Info, Tenants, Security) - AdminFront: Show '로그인 ID' badge on tenant schema fields used for authentication - UserFront: Remove legacy optional 'Login ID' input from signup flow - Tests: Add multi-identifier repository tests and update handler tests
This commit is contained in:
@@ -97,7 +97,6 @@ export function TenantSchemaPage() {
|
||||
|
||||
useEffect(() => {
|
||||
const rawSchema = tenantQuery.data?.config?.userSchema;
|
||||
const loginIdField = tenantQuery.data?.config?.loginIdField;
|
||||
|
||||
if (Array.isArray(rawSchema)) {
|
||||
setFields(
|
||||
@@ -118,7 +117,7 @@ export function TenantSchemaPage() {
|
||||
validation:
|
||||
typeof field?.validation === "string" ? field.validation : "",
|
||||
unsigned: Boolean(field?.unsigned),
|
||||
isLoginId: field?.key === loginIdField,
|
||||
isLoginId: Boolean(field?.isLoginId),
|
||||
})),
|
||||
);
|
||||
}
|
||||
@@ -126,13 +125,13 @@ export function TenantSchemaPage() {
|
||||
|
||||
const updateMutation = useMutation({
|
||||
mutationFn: (newFields: SchemaField[]) => {
|
||||
const loginIdField = newFields.find((f) => f.isLoginId)?.key || "";
|
||||
// Remove legacy loginIdField, keep isLoginId natively in userSchema
|
||||
const newConfig = { ...tenantQuery.data?.config };
|
||||
delete newConfig.loginIdField;
|
||||
newConfig.userSchema = newFields;
|
||||
|
||||
return updateTenant(tenantId, {
|
||||
config: {
|
||||
...tenantQuery.data?.config,
|
||||
userSchema: newFields,
|
||||
loginIdField: loginIdField,
|
||||
},
|
||||
config: newConfig,
|
||||
});
|
||||
},
|
||||
onSuccess: () => {
|
||||
@@ -344,14 +343,10 @@ export function TenantSchemaPage() {
|
||||
<label className="flex items-center gap-2 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={field.isLoginId}
|
||||
onChange={(e) => {
|
||||
const newFields = fields.map((f, i) => ({
|
||||
...f,
|
||||
isLoginId: i === index ? e.target.checked : false,
|
||||
}));
|
||||
setFields(newFields);
|
||||
}}
|
||||
checked={field.isLoginId || false}
|
||||
onChange={(e) =>
|
||||
updateField(index, { isLoginId: e.target.checked })
|
||||
}
|
||||
className="w-4 h-4 rounded border-gray-300 text-primary focus:ring-primary"
|
||||
/>
|
||||
<span className="text-sm font-medium text-blue-600">
|
||||
|
||||
Reference in New Issue
Block a user