Implement registration invite code flow and admin invite codes

This commit is contained in:
2026-04-30 20:49:38 +08:00
parent 2aef81e51d
commit 42aab671ed
32 changed files with 1241 additions and 179 deletions

View File

@@ -9,7 +9,8 @@ use module_auth::{
};
use serde_json::json;
use shared_contracts::auth::{
PhoneLoginRequest, PhoneLoginResponse, PhoneSendCodeRequest, PhoneSendCodeResponse,
PhoneLoginReferralResponse, PhoneLoginRequest, PhoneLoginResponse, PhoneSendCodeRequest,
PhoneSendCodeResponse,
};
use time::OffsetDateTime;
use tracing::{info, warn};
@@ -110,6 +111,7 @@ pub async fn phone_login(
AppError::from_status(StatusCode::BAD_REQUEST).with_message("手机号登录暂未启用")
);
}
let invite_code = payload.invite_code.clone();
let result = match state
.phone_auth_service()
.login(
@@ -146,6 +148,18 @@ pub async fn phone_login(
return Err(map_phone_auth_error(error));
}
};
let created = result.created;
let referral = if created {
bind_referral_invite_code_on_registration(
&state,
&request_context,
result.user.id.clone(),
invite_code,
)
.await
} else {
None
};
let session_client = resolve_session_client_context(&headers);
let signed_session = create_auth_session(
&state,
@@ -174,11 +188,55 @@ pub async fn phone_login(
PhoneLoginResponse {
token: signed_session.access_token,
user: map_auth_user_payload(result.user),
created,
referral,
},
),
))
}
async fn bind_referral_invite_code_on_registration(
state: &AppState,
request_context: &RequestContext,
user_id: String,
invite_code: Option<String>,
) -> Option<PhoneLoginReferralResponse> {
let invite_code = invite_code
.map(|value| value.trim().to_string())
.filter(|value| !value.is_empty())?;
let updated_at_micros = OffsetDateTime::now_utc().unix_timestamp_nanos() / 1_000;
match state
.spacetime_client()
.redeem_profile_referral_invite_code(user_id, invite_code, updated_at_micros as i64)
.await
{
Ok(record) => Some(PhoneLoginReferralResponse {
ok: true,
message: Some("邀请码已绑定".to_string()),
invitee_reward_granted: record.invitee_reward_granted,
inviter_reward_granted: record.inviter_reward_granted,
invitee_balance_after: Some(record.invitee_balance_after),
inviter_balance_after: Some(record.inviter_balance_after),
}),
Err(error) => {
warn!(
request_id = request_context.request_id(),
operation = request_context.operation(),
error = %error,
"注册邀请码绑定失败,登录流程继续"
);
Some(PhoneLoginReferralResponse {
ok: false,
message: Some("邀请码无效,已继续注册".to_string()),
invitee_reward_granted: false,
inviter_reward_granted: false,
invitee_balance_after: None,
inviter_balance_after: None,
})
}
}
}
fn map_phone_auth_scene(raw_scene: Option<&str>) -> Result<PhoneAuthScene, AppError> {
match raw_scene.unwrap_or("login").trim() {
"login" => Ok(PhoneAuthScene::Login),