Skip to content

Commit

Permalink
Fix Google SignIn
Browse files Browse the repository at this point in the history
  • Loading branch information
henriqueleite42 committed Jan 17, 2024
1 parent c8808d6 commit ab03046
Show file tree
Hide file tree
Showing 13 changed files with 194 additions and 38 deletions.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"@nestjs/platform-express": "^10.2.10",
"@prisma/client": "^5.7.0",
"@techmmunity/utils": "^1.10.1",
"axios": "^1.6.5",
"change-case": "^5.2.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
Expand Down Expand Up @@ -76,14 +77,16 @@
"prepare": "husky install && yarn db:prisma",
"db:prisma": "yarn lint:prisma && prisma generate --generator client",
"db:docs": "yarn lint:prisma && prisma generate --generator dbml && dbdocs build ./prisma/schema.dbml",
"db:migrations": "yarn lint:prisma && prisma migrate dev --name",
"db:gen-migration": "yarn lint:prisma && prisma migrate dev --name",
"db:migrate": "prisma migrate deploy",
"openapi:serve": "redocly preview-docs",
"openapi:postman": "yarn lint:openapi && redocly bundle -o openapi/bundle.yaml && openapi2postmanv2 -s openapi/bundle.yaml -o openapi/postman.json -O folderStrategy=Tags,requestParametersResolution=Example",
"build": "./scripts/build.sh",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
"start:docker": "nest start --watch",
"start:dev": "docker compose up",
"start:db": "docker compose up postgres",
"start:prod": "node main",
"clean:docker": "docker container rm econominhas-api && docker image rm econominhas-api",
"lint:ts": "tsc --project tsconfig.lint.json",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
Warnings:
- You are about to drop the column `rt_bill_id` on the `cards` table. All the data in the column will be lost.
- The primary key for the `configs` table will be changed. If it partially fails, the table could be left without primary key constraint.
- You are about to drop the column `created_at` on the `installments` table. All the data in the column will be lost.
- You are about to drop the column `payment_method` on the `recurrent_transactions` table. All the data in the column will be lost.
- You are about to drop the column `payment_method` on the `transactions` table. All the data in the column will be lost.
- A unique constraint covering the columns `[account_id]` on the table `configs` will be added. If there are existing duplicate values, this will fail.
- Added the required column `id` to the `configs` table without a default value. This is not possible if the table is not empty.
- Added the required column `installment_group_id` to the `installments` table without a default value. This is not possible if the table is not empty.
*/
-- CreateEnum
CREATE TYPE "pay_at_enum" AS ENUM ('STATEMENT', 'DUE');

-- DropForeignKey
ALTER TABLE "accounts" DROP CONSTRAINT "Config_id_fkey";

-- DropForeignKey
ALTER TABLE "accounts" DROP CONSTRAINT "MagicLinkCode_id_fkey";

-- DropForeignKey
ALTER TABLE "cards" DROP CONSTRAINT "cards_rt_bill_id_fkey";

-- DropForeignKey
ALTER TABLE "transactions" DROP CONSTRAINT "transactions_id_fkey";

-- DropIndex
DROP INDEX "cards_rt_bill_id_key";

-- AlterTable
ALTER TABLE "cards" DROP COLUMN "rt_bill_id",
ADD COLUMN "pay_at" "pay_at_enum",
ADD COLUMN "pay_with_id" TEXT;

-- AlterTable
ALTER TABLE "configs" DROP CONSTRAINT "configs_pkey",
ADD COLUMN "id" CHAR(16) NOT NULL,
ADD CONSTRAINT "configs_pkey" PRIMARY KEY ("id");

-- AlterTable
ALTER TABLE "installments" DROP COLUMN "created_at",
ADD COLUMN "card_bill_id" CHAR(16),
ADD COLUMN "installment_group_id" CHAR(16) NOT NULL;

-- AlterTable
ALTER TABLE "recurrent_transactions" DROP COLUMN "payment_method";

-- AlterTable
ALTER TABLE "transactions" DROP COLUMN "payment_method";

-- DropEnum
DROP TYPE "payment_method_enum";

-- CreateTable
CREATE TABLE "card_bills" (
"id" CHAR(16) NOT NULL,
"card_id" CHAR(16) NOT NULL,
"month" DATE NOT NULL,
"start_at" DATE NOT NULL,
"end_at" DATE NOT NULL,
"statement_date" DATE NOT NULL,
"due_date" DATE NOT NULL,
"paid_at" TIMESTAMP,
"payment_transaction_id" TEXT,

CONSTRAINT "card_bills_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "card_bills_payment_transaction_id_key" ON "card_bills"("payment_transaction_id");

-- CreateIndex
CREATE UNIQUE INDEX "card_bills_card_id_month_key" ON "card_bills"("card_id", "month");

-- CreateIndex
CREATE UNIQUE INDEX "configs_account_id_key" ON "configs"("account_id");

-- AddForeignKey
ALTER TABLE "configs" ADD CONSTRAINT "configs_account_id_fkey" FOREIGN KEY ("account_id") REFERENCES "accounts"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "magic_link_codes" ADD CONSTRAINT "MagicLinkCode_id_fkey" FOREIGN KEY ("account_id") REFERENCES "accounts"("id") ON DELETE CASCADE ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "cards" ADD CONSTRAINT "cards_pay_with_id_fkey" FOREIGN KEY ("pay_with_id") REFERENCES "bank_accounts"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "card_bills" ADD CONSTRAINT "card_bills_card_id_fkey" FOREIGN KEY ("card_id") REFERENCES "cards"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "card_bills" ADD CONSTRAINT "card_bills_payment_transaction_id_fkey" FOREIGN KEY ("payment_transaction_id") REFERENCES "transactions"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "installments" ADD CONSTRAINT "installments_transaction_id_fkey" FOREIGN KEY ("transaction_id") REFERENCES "transactions"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE "installments" ADD CONSTRAINT "installments_card_bill_id_fkey" FOREIGN KEY ("card_bill_id") REFERENCES "card_bills"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-- AlterTable
ALTER TABLE "sign_in_providers" ALTER COLUMN "access_token" SET DATA TYPE VARCHAR(250),
ALTER COLUMN "refresh_token" SET DATA TYPE VARCHAR(250);
15 changes: 8 additions & 7 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ model Account {
phone String? @unique @db.VarChar(25)
createdAt DateTime @default(now()) @map("created_at")
config Config @relation(fields: [id], references: [accountId], map: "Config_id_fkey", onDelete: Restrict)
magicLinkCode MagicLinkCode? @relation(fields: [id], references: [accountId], map: "MagicLinkCode_id_fkey", onDelete: Restrict)
config Config?
magicLinkCode MagicLinkCode?
signInProviders SignInProvider[]
refreshTokens RefreshToken[]
userSubscriptions UserSubscription[]
Expand All @@ -59,8 +59,8 @@ model SignInProvider {
accountId String @map("account_id") @db.Char(16)
provider SignInProviderEnum
providerId String @map("provider_id") @db.VarChar(50)
accessToken String @map("access_token") @db.VarChar(150)
refreshToken String @map("refresh_token") @db.VarChar(150)
accessToken String @map("access_token") @db.VarChar(250)
refreshToken String @map("refresh_token") @db.VarChar(250)
expiresAt DateTime @map("expires_at")
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
Expand All @@ -71,12 +71,13 @@ model SignInProvider {

/// Contains user's account config
model Config {
accountId String @id @map("account_id") @db.Char(16)
id String @id @db.Char(16) /// Same as accountId
accountId String @unique @map("account_id") @db.Char(16)
name String? @db.VarChar(20)
currentBudgetId String? @unique @map("current_budget_id") @db.Char(16)
salaryId String? @unique @map("salary_id") @db.Char(16)
account Account?
account Account @relation(fields: [accountId], references: [id], onDelete: Cascade)
currentBudget Budget? @relation(fields: [currentBudgetId], references: [id])
salary RecurrentTransaction? @relation(fields: [salaryId], references: [id])
Expand All @@ -90,7 +91,7 @@ model MagicLinkCode {
isFirstAccess Boolean @map("is_first_access")
createdAt DateTime @default(now()) @map("created_at")
account Account?
account Account? @relation(fields: [accountId], references: [id], map: "MagicLinkCode_id_fkey", onDelete: Cascade)
@@map("magic_link_codes")
}
Expand Down
28 changes: 16 additions & 12 deletions src/adapters/implementations/google/google.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { DateAdapter } from 'adapters/date';
import { DayjsAdapterService } from '../dayjs/dayjs.service';
import { AppConfig } from 'config';
import { ConfigService } from '@nestjs/config';
import axios from 'axios';

interface ExchangeCodeAPIOutput {
access_token: string;
Expand Down Expand Up @@ -41,25 +42,28 @@ export class GoogleAdapterService extends GoogleAdapter {
code,
originUrl,
}: ExchangeCodeInput): Promise<ExchangeCodeOutput> {
// ALERT: The order of the properties is important, don't change it!
const body = new URLSearchParams();
body.append('code', code);
body.append('client_id', this.config.get('GOOGLE_CLIENT_ID'));
body.append('client_secret', this.config.get('GOOGLE_CLIENT_SECRET'));
body.append('grant_type', 'authorization_code');
body.append('code', code);
if (originUrl) {
body.append('redirect_uri', originUrl);
}
body.append('grant_type', 'authorization_code');
// ALERT: The order of the properties is important, don't change it!

const result = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
body,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Accept: 'application/json',
},
})
.then((r) => r.json())
.then((r) => r as ExchangeCodeAPIOutput);
const result = await axios
.post('https://oauth2.googleapis.com/token', body, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
Accept: 'application/json',
},
})
.then((r) => r.data as ExchangeCodeAPIOutput)
.catch((err) => {
throw err?.response?.data;
});

return {
accessToken: result.access_token,
Expand Down
4 changes: 2 additions & 2 deletions src/delivery/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class AuthController {
async createFromGoogleProvider(
@Body()
body: CreateFromGoogleProviderDto,
@Res()
@Res({ passthrough: true })
res: Response,
) {
const { isFirstAccess, ...data } =
Expand Down Expand Up @@ -71,7 +71,7 @@ export class AuthController {
async exchangeCode(
@Body()
body: ExchangeCodeDto,
@Res()
@Res({ passthrough: true })
res: Response,
) {
const { isFirstAccess, ...data } =
Expand Down
1 change: 1 addition & 0 deletions src/models/transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export interface CreateTransferInput {
budgetDateId: string;
description: string;
createdAt: Date;
isSystemManaged: boolean;
}

export abstract class TransactionRepository {
Expand Down
6 changes: 2 additions & 4 deletions src/repositories/postgres/auth/auth-repository.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,11 @@ export class AuthRepositoryService extends AuthRepository {
async create(i: CreateInput): Promise<Account> {
const accountId = this.idAdapter.genId();

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
const baseAccount: Prisma.AccountCreateArgs['data'] = {
id: accountId,
config: {
create: {
accountId,
id: accountId,
},
},
};
Expand Down Expand Up @@ -136,7 +134,7 @@ export class AuthRepositoryService extends AuthRepository {
where: {
OR: [
{
SignInProvider: {
signInProviders: {
every: {
provider,
providerId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
import { TransactionRepository } from 'models/transaction';
import { UIDAdapterService } from 'adapters/implementations/uid/uid.service';
import { IdAdapter } from 'adapters/id';
import { TransactionTypeEnum } from '@prisma/client';

@Injectable()
export class TransactionRepositoryService extends TransactionRepository {
Expand Down Expand Up @@ -131,20 +132,37 @@ export class TransactionRepositoryService extends TransactionRepository {
budgetDateId,
description,
createdAt,
isSystemManaged,
}: CreateTransferInput): Promise<void> {
await this.transactionRepository.create({
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
data: {
id: this.idAdapter.genId(),
accountId,
name,
amount,
bankAccountFromId,
bankAccountToId,
budgetDateId,
description,
createdAt,
isSystemManaged,
type: TransactionTypeEnum.TRANSFER,
account: {
connect: {
id: accountId,
},
},
bankAccountFrom: {
connect: {
id: bankAccountFromId,
},
},
bankAccountTo: {
connect: {
id: bankAccountToId,
},
},
budgetDate: {
connect: {
id: budgetDateId,
},
},
},
});
}
Expand Down
19 changes: 14 additions & 5 deletions src/usecases/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
ConflictException,
Inject,
Injectable,
Logger,
NotFoundException,
} from '@nestjs/common';
import type {
Expand Down Expand Up @@ -42,7 +43,10 @@ interface GenTokensInput {

@Injectable()
export class AuthService extends AuthUseCase {
private readonly requiredGoogleScopes = ['identify', 'email'];
private readonly requiredGoogleScopes = [
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/userinfo.email',
];

constructor(
@Inject(AuthRepositoryService)
Expand Down Expand Up @@ -73,7 +77,9 @@ export class AuthService extends AuthUseCase {
}: CreateWith3rdPartyProviderInput): Promise<AuthOutput> {
const { scopes, ...providerTokens } = await this.googleAdapter
.exchangeCode({ code, originUrl })
.catch(() => {
.catch((err) => {
Logger.error(err);

throw new BadRequestException('Invalid code');
});

Expand Down Expand Up @@ -279,10 +285,13 @@ export class AuthService extends AuthUseCase {
} else {
promises.push({ refreshToken: '' });
}

if (!isFirstAccess) {
this.termsAndPoliciesService.hasAcceptedLatest({
accountId: accountId,
});
promises.push(
this.termsAndPoliciesService.hasAcceptedLatest({
accountId: accountId,
}),
);
} else {
promises.push(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ export class TermsAndPoliciesService extends TermsAndPoliciesUseCase {
this.termsAndPoliciesRepository.getLatest(),
]);

return latestTermsAccepted.semVer === latestTerms.semVer;
return latestTermsAccepted?.semVer === latestTerms?.semVer;
}
}
1 change: 1 addition & 0 deletions src/usecases/transaction/transaction.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ export class TransactionService extends TransactionUseCase {
budgetDateId,
description,
createdAt,
isSystemManaged: false,
});
}
}
Loading

0 comments on commit ab03046

Please sign in to comment.