feat: 实现密码重置功能与用户搜索API,优化注册登录流程

- 新增忘记密码页面与重置密码确认流程(前端+后端)
- 修复注册验证码页登录跳转路由
- 新增用户搜索API(按邮箱查询)
- 简化infra脚本,统一为app.sh
- 补充密码重置与用户API测试覆盖
- 更新runtime文档与AGENTS配置
This commit is contained in:
qzl
2026-02-27 15:22:42 +08:00
parent 0d4811fee5
commit e4e995854d
37 changed files with 2101 additions and 222 deletions
+15
View File
@@ -50,4 +50,19 @@ class AuthApi {
Future<void> deleteSession(LogoutRequest request) async {
await _client.delete('$_prefix/sessions', data: request.toJson());
}
Future<void> requestPasswordReset(String email) async {
await _client.post('$_prefix/password-reset', data: {'email': email});
}
Future<void> confirmPasswordReset({
required String email,
required String token,
required String newPassword,
}) async {
await _client.post(
'$_prefix/password-reset/confirm',
data: {'email': email, 'token': token, 'new_password': newPassword},
);
}
}
@@ -14,4 +14,10 @@ abstract class AuthRepository {
Future<String?> getAccessToken();
Future<String?> getRefreshToken();
Future<bool> isAuthenticated();
Future<void> requestPasswordReset(String email);
Future<void> confirmPasswordReset({
required String email,
required String token,
required String newPassword,
});
}
@@ -77,4 +77,22 @@ class AuthRepositoryImpl implements AuthRepository {
final token = await _tokenStorage.getAccessToken();
return token != null;
}
@override
Future<void> requestPasswordReset(String email) {
return _api.requestPasswordReset(email);
}
@override
Future<void> confirmPasswordReset({
required String email,
required String token,
required String newPassword,
}) {
return _api.confirmPasswordReset(
email: email,
token: token,
newPassword: newPassword,
);
}
}
@@ -2,17 +2,20 @@ class SignupStartRequest {
final String username;
final String email;
final String password;
final String? inviteCode;
const SignupStartRequest({
required this.username,
required this.email,
required this.password,
this.inviteCode,
});
Map<String, dynamic> toJson() => {
'username': username,
'email': email,
'password': password,
if (inviteCode != null) 'invite_code': inviteCode,
};
}