Skip to content

Commit

Permalink
Merge pull request #11 from Open-SGF/feat/auth-endpoints
Browse files Browse the repository at this point in the history
WIP auth endpoints
  • Loading branch information
glitchedmob authored Jan 11, 2022
2 parents 64d2647 + 7a3004f commit 43be2bf
Show file tree
Hide file tree
Showing 14 changed files with 446 additions and 280 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ DB_USER=
DB_PASSWORD=
DB_NAME=portal_to_work
DB_LOGGING=true
GOOGLE_RECAPTCHA_SECRET_KEY=
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
node_modules
build
.env
.idea/
.idea
.vscode
574 changes: 323 additions & 251 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"dependencies": {
"@bull-board/fastify": "^3.7.0",
"bull": "^4.1.1",
"cross-fetch": "^3.1.4",
"dotenv": "^10.0.0",
"fastify": "^3.24.0",
"fastify-typeorm-plugin": "^2.2.0",
Expand Down
2 changes: 2 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import fastifyTypeorm from 'fastify-typeorm-plugin';

import { dbConfig } from './database';
import { jobs } from './routes/jobs';
import { auth } from './routes/auth';

export function build(opts: FastifyServerOptions = {}): FastifyInstance {
const app = fastify(opts);

app.register(fastifyTypeorm, dbConfig);

app.register(jobs, { prefix: '/jobs' });
app.register(auth, { prefix: '/auth' });

return app;
}
1 change: 1 addition & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ export const DB_LOGGING = process.env.DB_LOGGING === 'true';
export const REDIS_HOST = process.env.REDIS_HOST || 'localhost';
export const REDIS_PORT = parseNumber(process.env.REDIS_PORT) || 6379;
export const REDIS_PASSWORD = process.env.REDIS_PASSWORD || '';
export const GOOGLE_RECAPTCHA_SECRET_KEY = process.env.GOOGLE_RECAPTCHA_SECRET_KEY || '';
9 changes: 8 additions & 1 deletion src/entities/Company.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Column, Entity, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, OneToMany } from 'typeorm';
import {
Column,
Entity,
PrimaryGeneratedColumn,
CreateDateColumn,
UpdateDateColumn,
OneToMany,
} from 'typeorm';
import { Event } from './Event';
import { Job } from './Job';

Expand Down
8 changes: 7 additions & 1 deletion src/entities/User.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import {Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn} from "typeorm";
import {
Column,
CreateDateColumn,
Entity,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';

@Entity({ name: 'users' })
export class User {
Expand Down
9 changes: 5 additions & 4 deletions src/migrations/1638839975840-AddOccupations.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import {MigrationInterface, QueryRunner} from "typeorm";
import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddOccupations1638839975840 implements MigrationInterface {
name = 'AddOccupations1638839975840'
name = 'AddOccupations1638839975840';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "occupations" ("id" SERIAL NOT NULL, "title" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_0bf09083dd897df1e8ebb96b5c1" PRIMARY KEY ("id"))`);
await queryRunner.query(
`CREATE TABLE "occupations" ("id" SERIAL NOT NULL, "title" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), CONSTRAINT "PK_0bf09083dd897df1e8ebb96b5c1" PRIMARY KEY ("id"))`,
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`DROP TABLE "occupations"`);
}

}
33 changes: 23 additions & 10 deletions src/migrations/1638841344534-AddJobs.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
import {MigrationInterface, QueryRunner} from "typeorm";
import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddJobs1638841344534 implements MigrationInterface {
name = 'AddJobs1638841344534'
name = 'AddJobs1638841344534';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "jobs" ("id" SERIAL NOT NULL, "title" character varying NOT NULL, "description" text NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "occupationId" integer, "companyId" integer, "locationId" integer, CONSTRAINT "PK_cf0a6c42b72fcc7f7c237def345" PRIMARY KEY ("id"))`);
await queryRunner.query(`ALTER TABLE "jobs" ADD CONSTRAINT "FK_7157538b49480e6f51a61c35bb1" FOREIGN KEY ("occupationId") REFERENCES "occupations"("id") ON DELETE SET NULL ON UPDATE CASCADE`);
await queryRunner.query(`ALTER TABLE "jobs" ADD CONSTRAINT "FK_6ce4483dc65ed9d2e171269d801" FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
await queryRunner.query(`ALTER TABLE "jobs" ADD CONSTRAINT "FK_5dbffa782dc6074a7e4cb39150d" FOREIGN KEY ("locationId") REFERENCES "locations"("id") ON DELETE SET NULL ON UPDATE CASCADE`);
await queryRunner.query(
`CREATE TABLE "jobs" ("id" SERIAL NOT NULL, "title" character varying NOT NULL, "description" text NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "occupationId" integer, "companyId" integer, "locationId" integer, CONSTRAINT "PK_cf0a6c42b72fcc7f7c237def345" PRIMARY KEY ("id"))`,
);
await queryRunner.query(
`ALTER TABLE "jobs" ADD CONSTRAINT "FK_7157538b49480e6f51a61c35bb1" FOREIGN KEY ("occupationId") REFERENCES "occupations"("id") ON DELETE SET NULL ON UPDATE CASCADE`,
);
await queryRunner.query(
`ALTER TABLE "jobs" ADD CONSTRAINT "FK_6ce4483dc65ed9d2e171269d801" FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
await queryRunner.query(
`ALTER TABLE "jobs" ADD CONSTRAINT "FK_5dbffa782dc6074a7e4cb39150d" FOREIGN KEY ("locationId") REFERENCES "locations"("id") ON DELETE SET NULL ON UPDATE CASCADE`,
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "jobs" DROP CONSTRAINT "FK_5dbffa782dc6074a7e4cb39150d"`);
await queryRunner.query(`ALTER TABLE "jobs" DROP CONSTRAINT "FK_6ce4483dc65ed9d2e171269d801"`);
await queryRunner.query(`ALTER TABLE "jobs" DROP CONSTRAINT "FK_7157538b49480e6f51a61c35bb1"`);
await queryRunner.query(
`ALTER TABLE "jobs" DROP CONSTRAINT "FK_5dbffa782dc6074a7e4cb39150d"`,
);
await queryRunner.query(
`ALTER TABLE "jobs" DROP CONSTRAINT "FK_6ce4483dc65ed9d2e171269d801"`,
);
await queryRunner.query(
`ALTER TABLE "jobs" DROP CONSTRAINT "FK_7157538b49480e6f51a61c35bb1"`,
);
await queryRunner.query(`DROP TABLE "jobs"`);
}

}
25 changes: 17 additions & 8 deletions src/migrations/1638841899720-AddEvents.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import {MigrationInterface, QueryRunner} from "typeorm";
import { MigrationInterface, QueryRunner } from 'typeorm';

export class AddEvents1638841899720 implements MigrationInterface {
name = 'AddEvents1638841899720'
name = 'AddEvents1638841899720';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`CREATE TABLE "events" ("id" SERIAL NOT NULL, "title" character varying NOT NULL, "description" text NOT NULL, "link" character varying, "startAt" TIMESTAMP NOT NULL, "endAt" TIMESTAMP NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "companyId" integer, "locationId" integer, CONSTRAINT "PK_40731c7151fe4be3116e45ddf73" PRIMARY KEY ("id"))`);
await queryRunner.query(`ALTER TABLE "events" ADD CONSTRAINT "FK_b42eb62a0da91cc26d953db93cd" FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE CASCADE ON UPDATE CASCADE`);
await queryRunner.query(`ALTER TABLE "events" ADD CONSTRAINT "FK_55ad94f5c1b4c97960d6d7dc115" FOREIGN KEY ("locationId") REFERENCES "locations"("id") ON DELETE SET NULL ON UPDATE CASCADE`);
await queryRunner.query(
`CREATE TABLE "events" ("id" SERIAL NOT NULL, "title" character varying NOT NULL, "description" text NOT NULL, "link" character varying, "startAt" TIMESTAMP NOT NULL, "endAt" TIMESTAMP NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "companyId" integer, "locationId" integer, CONSTRAINT "PK_40731c7151fe4be3116e45ddf73" PRIMARY KEY ("id"))`,
);
await queryRunner.query(
`ALTER TABLE "events" ADD CONSTRAINT "FK_b42eb62a0da91cc26d953db93cd" FOREIGN KEY ("companyId") REFERENCES "companies"("id") ON DELETE CASCADE ON UPDATE CASCADE`,
);
await queryRunner.query(
`ALTER TABLE "events" ADD CONSTRAINT "FK_55ad94f5c1b4c97960d6d7dc115" FOREIGN KEY ("locationId") REFERENCES "locations"("id") ON DELETE SET NULL ON UPDATE CASCADE`,
);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "events" DROP CONSTRAINT "FK_55ad94f5c1b4c97960d6d7dc115"`);
await queryRunner.query(`ALTER TABLE "events" DROP CONSTRAINT "FK_b42eb62a0da91cc26d953db93cd"`);
await queryRunner.query(
`ALTER TABLE "events" DROP CONSTRAINT "FK_55ad94f5c1b4c97960d6d7dc115"`,
);
await queryRunner.query(
`ALTER TABLE "events" DROP CONSTRAINT "FK_b42eb62a0da91cc26d953db93cd"`,
);
await queryRunner.query(`DROP TABLE "events"`);
}

}
2 changes: 1 addition & 1 deletion src/queue-handlers/jobs-import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ const jobsImport: ProcessPromiseFunction<null> = async (job) => {
}

await db.manager.find(Job);
}
};

export default jobsImport;
7 changes: 4 additions & 3 deletions src/queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ const redisConfig = {
port: REDIS_PORT,
host: REDIS_HOST,
password: REDIS_PASSWORD,
}
};

export const queues = {
jobsImport: new Queue('jobs-import', { redis: redisConfig })
jobsImport: new Queue('jobs-import', { redis: redisConfig }),
} as const;

export function setupQueueProcessors(): void {
Expand All @@ -27,7 +27,7 @@ export function setupRepeatingJobs(): void {
export function setupQueueUi(app: FastifyInstance): void {
const serverAdapter = new FastifyAdapter();

const adaptedQueues = Object.values(queues).map(queue => new BullAdapter(queue));
const adaptedQueues = Object.values(queues).map((queue) => new BullAdapter(queue));

createBullBoard({
queues: adaptedQueues,
Expand All @@ -36,6 +36,7 @@ export function setupQueueUi(app: FastifyInstance): void {

serverAdapter.setBasePath('/queue');

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
app.register(serverAdapter.registerPlugin(), { prefix: '/queue' });
}
Expand Down
51 changes: 51 additions & 0 deletions src/routes/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import type { FastifyPluginAsync } from 'fastify';
import { FromSchema } from 'json-schema-to-ts';
import fetch from 'cross-fetch';
import { GOOGLE_RECAPTCHA_SECRET_KEY } from '../config';

const authBodyParams = {
type: 'object',
properties: {
'g-recaptcha-token': { type: 'string' },
},
required: ['g-recaptcha-token'],
} as const;

const recaptchaVerifyUrl = 'https://www.google.com/recaptcha/api/siteverify';

export interface IRecaptchaResponse {
success: boolean;
challenge_ts?: string;
hostname?: string;
error_codes?: string[];
}

export const auth: FastifyPluginAsync = async (app) => {
app.route<{ Body: FromSchema<typeof authBodyParams> }>({
url: '/',
method: 'POST',
schema: { body: authBodyParams },
handler: async (req, reply) => {
const token = req.body['g-recaptcha-token'];

const res = await fetch(recaptchaVerifyUrl, {
method: 'POST',
body: new URLSearchParams({
secret: GOOGLE_RECAPTCHA_SECRET_KEY,
response: token,
}),
});

const recaptchaRes = (await res.json()) as IRecaptchaResponse;

if (!recaptchaRes.success) {
reply.code(401);
return;
}

return {
token: 'test',
};
},
});
};

0 comments on commit 43be2bf

Please sign in to comment.