Skip to content

feat: handle user permissions #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 11 commits into from
Closed
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ on:
paths-ignore:
- "docs/**"
- "*.md"
- "*.example"
pull_request:
paths-ignore:
- "docs/**"
Expand Down
7 changes: 0 additions & 7 deletions @types/fastify/fastify.d.ts

This file was deleted.

4 changes: 4 additions & 0 deletions migrations/004.do.roles.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CREATE TABLE roles (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL
);
1 change: 1 addition & 0 deletions migrations/004.undo.roles.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE IF EXISTS roles;
7 changes: 7 additions & 0 deletions migrations/005.do.user_roles.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE TABLE user_roles (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
role_id INT NOT NULL,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE
);
1 change: 1 addition & 0 deletions migrations/005.undo.user_roles.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE IF EXISTS user_roles;
12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
"standalone": "node --env-file=.env dist/server.js",
"lint": "eslint --ignore-pattern=dist",
"lint:fix": "npm run lint -- --fix",
"db:migrate": "node --env-file=.env scripts/migrate.js",
"db:seed": "node --env-file=.env scripts/seed-database.js"
"db:create": "node --loader ts-node/esm --env-file=.env src/scripts/create-database.ts",
"db:drop": "node --loader ts-node/esm --env-file=.env src/scripts/drop-database.ts",
"db:migrate": "node --loader ts-node/esm --env-file=.env src/scripts/migrate.ts",
"db:seed": "node --loader ts-node/esm --env-file=.env src/scripts/seed-database.ts"
},
"keywords": [],
"author": "Michelet Jean <jean.antoine.michelet@gmail.com>",
Expand All @@ -29,7 +31,6 @@
"@fastify/env": "^5.0.1",
"@fastify/helmet": "^12.0.0",
"@fastify/jwt": "^9.0.0",
"@fastify/mysql": "^5.0.1",
"@fastify/rate-limit": "^10.0.1",
"@fastify/sensible": "^6.0.1",
"@fastify/swagger": "^9.0.0",
Expand All @@ -41,13 +42,14 @@
"fastify": "^5.0.0",
"fastify-cli": "^7.0.0",
"fastify-plugin": "^5.0.1",
"postgrator": "^7.3.0"
"knex": "^3.1.0",
"postgrator": "^7.3.0",
"ts-node": "^10.9.2"
},
"devDependencies": {
"@types/node": "^22.5.5",
"eslint": "^9.11.0",
"fastify-tsconfig": "^2.0.0",
"mysql2": "^3.11.3",
"neostandard": "^0.11.5",
"tap": "^21.0.1",
"typescript": "^5.6.2"
Expand Down
60 changes: 0 additions & 60 deletions scripts/seed-database.js

This file was deleted.

44 changes: 44 additions & 0 deletions src/plugins/custom/authorization.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import fp from 'fastify-plugin'
import { FastifyReply, FastifyRequest } from 'fastify'
import { Auth } from '../../schemas/auth.js'

declare module 'fastify' {
export interface FastifyInstance {
isModerator: typeof isModerator;
isAdmin: typeof isAdmin;
}
}

function verifyAccess (
request: FastifyRequest,
reply: FastifyReply,
role: string
) {
if (!request.user || !(request.user as Auth).roles.includes(role)) {
reply.status(403).send('You are not authorized to access this resource.')
}
}

async function isModerator (request: FastifyRequest, reply: FastifyReply) {
verifyAccess(request, reply, 'moderator')
}

async function isAdmin (request: FastifyRequest, reply: FastifyReply) {
verifyAccess(request, reply, 'admin')
}

/**
* The use of fastify-plugin is required to be able
* to export the decorators to the outer scope
*
* @see {@link https://github.com/fastify/fastify-plugin}
*/
export default fp(
async function (fastify) {
fastify.decorate('isModerator', isModerator)
fastify.decorate('isAdmin', isAdmin)
},
// You should name your plugins if you want to avoid name collisions
// and/or to perform dependency checks.
{ name: 'authorization' }
)
109 changes: 0 additions & 109 deletions src/plugins/custom/repository.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/plugins/custom/scrypt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const SCRYPT_BLOCK_SIZE = 8
const SCRYPT_PARALLELIZATION = 2
const SCRYPT_MAXMEM = 128 * SCRYPT_COST * SCRYPT_BLOCK_SIZE * 2

async function scryptHash (value: string): Promise<string> {
export async function scryptHash (value: string): Promise<string> {
return new Promise((resolve, reject) => {
const salt = randomBytes(Math.min(16, SCRYPT_KEYLEN / 2))

Expand Down
35 changes: 35 additions & 0 deletions src/plugins/external/knex.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import fp from 'fastify-plugin'
import { FastifyInstance } from 'fastify'
import knex, { Knex } from 'knex'

declare module 'fastify' {
export interface FastifyInstance {
knex: Knex;
}
}

export const autoConfig = (fastify: FastifyInstance) => {
return {
client: 'mysql2',
connection: {
host: fastify.config.MYSQL_HOST,
user: fastify.config.MYSQL_USER,
password: fastify.config.MYSQL_PASSWORD,
database: fastify.config.MYSQL_DATABASE,
port: Number(fastify.config.MYSQL_PORT)
},
pool: { min: 2, max: 10 }
}
}

const knexPlugin = async (fastify: FastifyInstance) => {
const db = knex(autoConfig(fastify))

fastify.decorate('knex', db)

fastify.addHook('onClose', async (instance) => {
await instance.knex.destroy()
})
}

export default fp(knexPlugin, { name: 'knex' })
24 changes: 0 additions & 24 deletions src/plugins/external/mysql.ts

This file was deleted.

8 changes: 2 additions & 6 deletions src/plugins/external/under-pressure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,13 @@ export const autoConfig = (fastify: FastifyInstance) => {
message: 'The server is under pressure, retry later!',
retryAfter: 50,
healthCheck: async () => {
let connection
try {
connection = await fastify.mysql.getConnection()
await connection.query('SELECT 1;')
await fastify.knex.raw('SELECT 1')
return true
/* c8 ignore start */
} catch (err) {
fastify.log.error(err, 'healthCheck has failed')
throw new Error('Database connection is not available')
} finally {
connection?.release()
}
/* c8 ignore stop */
},
Expand All @@ -39,5 +35,5 @@ export const autoConfig = (fastify: FastifyInstance) => {
* @see {@link https://www.youtube.com/watch?v=VI29mUA8n9w}
*/
export default fp(fastifyUnderPressure, {
dependencies: ['mysql']
dependencies: ['knex']
})
Loading
Loading