feat: merge registration invite and verification input

This commit is contained in:
richjohnrambo
2026-09-16 14:29:59 +08:00
parent 370e9878ed
commit 7461216c03
8 changed files with 157 additions and 29 deletions
+25 -9
View File
@@ -118,11 +118,12 @@ func replyCreateUser(s *Session, msg *ClientComMessage, rec *auth.Rec) {
// Pre-check credentials for validity. We don't know user's access level
// consequently cannot check presence of required credentials. Must do that later.
creds := normalizeCredentials(msg.Acc.Cred, true)
rawCreds := normalizeCredentials(msg.Acc.Cred, true)
creds := make([]MsgCredClient, 0, len(rawCreds))
var registrationPhone string
var registrationTelCredential bool
for i := range creds {
cr := &creds[i]
for i := range rawCreds {
cr := &rawCreds[i]
vld := store.Store.GetValidator(cr.Method)
if vld == nil || !vld.IsInitialized() {
s.queueOut(decodeStoreError(types.ErrCredentials, msg.Id, msg.Timestamp,
@@ -138,6 +139,16 @@ func replyCreateUser(s *Session, msg *ClientComMessage, rec *auth.Rec) {
}
if cr.Method == "tel" {
phone := strings.TrimSpace(strings.TrimPrefix(normalized, "tel:"))
if credentialInviteCode := strings.TrimSpace(cr.Response); isValidIMInviteCode(credentialInviteCode) {
if inviteCode != "" && inviteCode != credentialInviteCode {
s.queueOut(decodeStoreError(types.ErrCredentials, msg.Id, msg.Timestamp,
map[string]any{"what": "invite_code", "reason": "INVITE_CODE_INVALID"}))
return
}
inviteCode = credentialInviteCode
registrationPhone = phone
continue
}
challengeID, _ := cr.Params["challenge_id"].(string)
if phone == "" || strings.TrimSpace(challengeID) == "" || strings.TrimSpace(cr.Response) == "" ||
(registrationPhone != "" && registrationPhone != phone) {
@@ -148,6 +159,7 @@ func replyCreateUser(s *Session, msg *ClientComMessage, rec *auth.Rec) {
registrationPhone = phone
registrationTelCredential = true
}
creds = append(creds, *cr)
}
if !phoneRegistration && registrationTelCredential {
logs.Warn.Println("create user: username registration cannot attach a phone credential, sid=", s.sid)
@@ -155,13 +167,13 @@ func replyCreateUser(s *Session, msg *ClientComMessage, rec *auth.Rec) {
map[string]any{"creds": []string{"tel"}, "reason": "PHONE_NOT_SELECTED"}))
return
}
if phoneRegistration && registrationTelCredential && registrationPhone != phone {
if phoneRegistration && registrationPhone != "" && registrationPhone != phone {
s.queueOut(decodeStoreError(types.ErrCredentials, msg.Id, msg.Timestamp,
map[string]any{"creds": []string{"tel"}, "reason": "PHONE_MISMATCH"}))
return
}
smsEnabled := registrationSMSEnabled(time.Now().UTC())
if phoneRegistration && smsEnabled && !registrationTelCredential {
if phoneRegistration && smsEnabled && !registrationTelCredential && inviteCode == "" {
logs.Warn.Println("create user: verified phone is required while registration SMS is enabled, sid=", s.sid)
s.queueOut(decodeStoreError(types.ErrCredentials, msg.Id, msg.Timestamp,
map[string]any{"creds": []string{"tel"}, "reason": "PHONE_VERIFICATION_REQUIRED"}))
@@ -240,10 +252,14 @@ func replyCreateUser(s *Session, msg *ClientComMessage, rec *auth.Rec) {
}
// When creating an account, the user must provide all required credentials.
// If any are missing, reject the request.
if len(creds) < len(globals.authValidators[rec.AuthLevel]) {
requiredValidators := globals.authValidators[rec.AuthLevel]
if inviteCode != "" {
requiredValidators = slices.DeleteFunc(slices.Clone(requiredValidators), func(method string) bool { return method == "tel" })
}
if len(creds) < len(requiredValidators) {
logs.Warn.Println("create user: missing credentials; have:", creds, "want:",
globals.authValidators[rec.AuthLevel], s.sid)
_, missing, _ := stringSliceDelta(globals.authValidators[rec.AuthLevel], credentialMethods(creds))
requiredValidators, s.sid)
_, missing, _ := stringSliceDelta(requiredValidators, credentialMethods(creds))
s.queueOut(decodeStoreError(types.ErrPolicy, msg.Id, msg.Timestamp,
map[string]any{"creds": missing}))
@@ -310,7 +326,7 @@ func replyCreateUser(s *Session, msg *ClientComMessage, rec *auth.Rec) {
var reply *ServerComMessage
if msg.Acc.Login {
// Process user's login request.
_, missing, _ := stringSliceDelta(globals.authValidators[rec.AuthLevel], validated)
_, missing, _ := stringSliceDelta(requiredValidators, validated)
reply = s.onLogin(msg.Id, msg.Timestamp, rec, missing, msg.Acc.Scheme, account)
} else {
// Not using the new account for logging in.