Commit ac6f8aa3 authored by ThinhNC's avatar ThinhNC

feat: implement authentication service and repository for user management and session handling

parent 97a31c0d
...@@ -168,6 +168,7 @@ export class AuthRepository { ...@@ -168,6 +168,7 @@ export class AuthRepository {
async updateProfile(userId: string, data: { async updateProfile(userId: string, data: {
fullName?: string; fullName?: string;
phoneNumber?: string | null; phoneNumber?: string | null;
avatarUrl?: string | null;
}) { }) {
return prisma.user.update({ return prisma.user.update({
where: { id: userId }, where: { id: userId },
......
...@@ -553,6 +553,35 @@ export class AuthService { ...@@ -553,6 +553,35 @@ export class AuthService {
provider: 'zalo', provider: 'zalo',
providerUserId: zaloId, providerUserId: zaloId,
}); });
} else {
// User đã tồn tại: Tự động cập nhật SĐT nếu có resolvedPhone mà user chưa có hoặc khác SĐT cũ
const updateData: { phoneNumber?: string; fullName?: string; avatarUrl?: string } = {};
if (resolvedPhone && user.phoneNumber !== resolvedPhone) {
// Kiểm tra xem số điện thoại này có đang thuộc về tài khoản khác không để tránh lỗi Unique constraint
const existingPhoneUser = await this.repository.findByPhone(resolvedPhone);
if (!existingPhoneUser || existingPhoneUser.id === user.id) {
updateData.phoneNumber = resolvedPhone;
} else {
console.warn(`[ZaloAuth] Phone number ${resolvedPhone} is already linked to another user ${existingPhoneUser.id}`);
}
}
// Cập nhật thêm tên hoặc avatar nếu tài khoản hiện tại chưa có
if (!user.fullName && zaloName) {
updateData.fullName = zaloName;
}
if (!user.avatarUrl && zaloAvatarUrl) {
updateData.avatarUrl = zaloAvatarUrl;
}
if (Object.keys(updateData).length > 0) {
try {
user = await this.repository.updateProfile(user.id, updateData);
} catch (updateErr) {
console.warn('[ZaloAuth] Failed to update user profile with resolved Zalo info:', updateErr);
}
}
} }
// Load role relation nếu chưa có (createSocialUser đã include) // Load role relation nếu chưa có (createSocialUser đã include)
......
...@@ -158,5 +158,30 @@ describe('Zalo Auth Integration Tests', () => { ...@@ -158,5 +158,30 @@ describe('Zalo Auth Integration Tests', () => {
}); });
expect(count).toBe(1); expect(count).toBe(1);
}); });
it('should update phoneNumber for existing user whose phoneNumber was previously null', async () => {
// Giả lập user đã tạo trước đó nhưng phoneNumber là null
await prisma.user.updateMany({
where: { phoneNumber: testPhone },
data: { phoneNumber: null },
});
const res = await request(app)
.post('/api/v1/auth/zalo-login')
.send({
accessToken: 'valid_mock_token_123',
phoneToken: 'valid_phone_token_abc',
});
expect(res.status).toBe(200);
expect(res.body.success).toBe(true);
expect(res.body.data.user.phoneNumber).toBe(testPhone);
const dbUser = await prisma.user.findFirst({
where: { phoneNumber: testPhone },
});
expect(dbUser).not.toBeNull();
expect(dbUser?.phoneNumber).toBe(testPhone);
});
}); });
}); });
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment