Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/src/modules/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class AuthService {
try {
await emailService.sendWelcome({
email: user.email,
name: user.displayName ?? user.username,
name: user.displayName ?? user.username ?? "Usuário",
});
} catch (error) {
logError("Falha ao disparar e-mail de boas-vindas no login social.", {
Expand Down
5 changes: 4 additions & 1 deletion backend/src/modules/auth/connections.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ export class ConnectionsController {
const userId = req.session.userId as string;
const provider = req.params.provider;

if (!(SUPPORTED_PROVIDERS as readonly string[]).includes(provider)) {
if (
typeof provider !== "string" ||
!(SUPPORTED_PROVIDERS as readonly string[]).includes(provider)
) {
throw AppError.validation("Provider inválido.");
}

Expand Down
4 changes: 2 additions & 2 deletions backend/src/modules/auth/credentials.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ export class CredentialsService {
// E-mail de boas-vindas: falha nunca derruba o registro (EMAIL-08).
try {
await emailService.sendWelcome({
email: user.email,
name: user.displayName ?? user.username,
email: normalizedEmail,
name: name?.trim() || normalizedEmail.split("@")[0],
});
} catch (error) {
logError("Falha ao disparar e-mail de boas-vindas.", {
Expand Down
16 changes: 16 additions & 0 deletions backend/tests/integration/routes/connections.routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,20 @@ describe("connections routes", () => {
expect(res.body.code).toBe("VALIDATION_ERROR");
expect(mocks.disconnectProvider).not.toHaveBeenCalled();
});

it("recusa provider não escalar antes de desconectar", async () => {
const controller = new ConnectionsController();

await expect(
controller.disconnect(
{
session: { userId: "user-A" },
params: { provider: ["google", "github"] },
} as any,
{ json: vi.fn() } as any,
),
).rejects.toMatchObject({ code: "VALIDATION_ERROR" });

expect(mocks.disconnectProvider).not.toHaveBeenCalled();
});
});
15 changes: 15 additions & 0 deletions backend/tests/unit/modules/auth/auth.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,5 +216,20 @@ describe("AuthService", () => {
profile: mockProfile,
});
});

it("uses a fallback name when the social profile has no name", async () => {
mocks.exchangeCode.mockResolvedValueOnce(mockProfile);
mocks.findOrCreateUser.mockResolvedValueOnce({
user: { ...mockUser, displayName: null, username: null },
isNewUser: true,
});

await service.handleCallback(validCallbackParams);

expect(mocks.sendWelcome).toHaveBeenCalledWith({
email: mockUser.email,
name: "Usuário",
});
});
});
});
4 changes: 2 additions & 2 deletions backend/tests/unit/modules/auth/credentials.service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ describe("CredentialsService", () => {
await service.register(registerInput);

expect(mocks.sendWelcome).toHaveBeenCalledWith({
email: mockUser.email,
name: mockUser.displayName,
email: registerInput.email,
name: registerInput.name,
});
});

Expand Down
Loading