mirror of
https://github.com/hanzoai/calendar.git
synced 2026-09-24 22:42:24 +00:00
ccff0045fc
* fix: Add email verification requirement for API v1 and v2 email updates
- API v2 (/v2/me): Implement email verification check when updating primary email
- Store new email in metadata as emailChangeWaitingForVerification when verification is required
- Send verification email using sendChangeOfEmailVerification
- Allow immediate email change if new email is already a verified secondary email
- Add hasEmailBeenChanged and sendEmailVerification flags to response
- Add tests to verify email verification behavior
- Add findVerifiedSecondaryEmail method to UsersRepository
- Add PrismaFeaturesRepository to MeModule providers
- API v1 (/v1/users/{userId}): Implement same email verification logic
- Check if email-verification feature flag is enabled
- Store new email in metadata when verification is required
- Send verification email for unverified email changes
- Allow immediate change for verified secondary emails
- Preserve existing API v1 response format
- Test fixtures: Add createSecondaryEmail method to UserRepositoryFixture
This fixes the vulnerability where users could update their primary email
without verification via API endpoints.
Co-Authored-By: [email protected] <[email protected]>
* update
* update
* refactor: Extract business logic to MeService and add platform-managed bypass
- Create MeService with all business logic extracted from MeController
- Update MeController to delegate to MeService (thin controller pattern)
- Add PrismaWorkerModule to MeModule imports to provide PrismaWriteService
- Add isPlatformManaged bypass: platform-managed users can update email without verification
- Fix test cleanup to use delete by ID instead of email to avoid failures when email changes
- Remove hasEmailBeenChanged and sendEmailVerification response flags per reviewer feedback
- Add comprehensive documentation to @ApiOperation describing email verification behavior
- Update tests to remove flag assertions
Addresses PR comments:
- supalarry: Extract logic to service layer
- supalarry: Allow platform-managed users to update email without verification
- supalarry: Remove response flags and document behavior in @ApiOperation instead
- cubic-dev-ai: Fix module dependency for PrismaFeaturesRepository
- cubic-dev-ai: Fix test cleanup issue
Co-Authored-By: [email protected] <[email protected]>
* docs: Simplify API operation description
Remove internal implementation details about metadata staging and shorten the description to focus on API consumer behavior.
Co-Authored-By: [email protected] <[email protected]>
* fix
* update
* update
* update
* remove comment
* addressed commit
* review addressed
* use repository
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
import { PrismaReadService } from "@/modules/prisma/prisma-read.service";
|
|
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service";
|
|
import { TestingModule } from "@nestjs/testing";
|
|
|
|
import type { Prisma, User } from "@calcom/prisma/client";
|
|
|
|
export class UserRepositoryFixture {
|
|
private prismaReadClient: PrismaReadService["prisma"];
|
|
private prismaWriteClient: PrismaWriteService["prisma"];
|
|
|
|
constructor(module: TestingModule) {
|
|
this.prismaReadClient = module.get(PrismaReadService).prisma;
|
|
this.prismaWriteClient = module.get(PrismaWriteService).prisma;
|
|
}
|
|
|
|
async get(userId: User["id"]) {
|
|
return this.prismaReadClient.user.findFirst({ where: { id: userId } });
|
|
}
|
|
|
|
async create(data: Prisma.UserCreateInput) {
|
|
try {
|
|
// avoid uniq constraint in tests
|
|
await this.deleteByEmail(data.email);
|
|
} catch {}
|
|
|
|
return this.prismaWriteClient.user.create({ data });
|
|
}
|
|
|
|
async createOAuthManagedUser(email: Prisma.UserCreateInput["email"], oAuthClientId: string) {
|
|
try {
|
|
// avoid uniq constraint in tests
|
|
await this.deleteByEmail(email);
|
|
} catch {}
|
|
|
|
return this.prismaWriteClient.user.create({
|
|
data: {
|
|
email,
|
|
platformOAuthClients: {
|
|
connect: { id: oAuthClientId },
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
async delete(userId: User["id"]) {
|
|
return this.prismaWriteClient.user.delete({ where: { id: userId } });
|
|
}
|
|
|
|
async deleteByEmail(email: User["email"]) {
|
|
return this.prismaWriteClient.user.delete({ where: { email } });
|
|
}
|
|
|
|
async createSecondaryEmail(userId: User["id"], email: string, emailVerified: Date | null) {
|
|
return this.prismaWriteClient.secondaryEmail.create({
|
|
data: {
|
|
userId,
|
|
email,
|
|
emailVerified,
|
|
},
|
|
});
|
|
}
|
|
}
|