From 4da15ff105ca65d9b06f98c04ee72250eff1c710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Malak?= Date: Mon, 18 Oct 2021 22:32:00 +0200 Subject: [PATCH] Database migration to support authentication --- src/db/associateModels.ts | 12 ++++++- src/db/migrations/03_authentication.ts | 50 ++++++++++++++++++++++++++ src/models/Snippet.ts | 5 +++ src/typescript/interfaces/Snippet.ts | 1 + src/utils/createAdmin.ts | 14 ++++++++ src/utils/index.ts | 4 +++ 6 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 src/db/migrations/03_authentication.ts create mode 100644 src/utils/createAdmin.ts diff --git a/src/db/associateModels.ts b/src/db/associateModels.ts index 9ef3314..13253c6 100644 --- a/src/db/associateModels.ts +++ b/src/db/associateModels.ts @@ -1,4 +1,4 @@ -import { TagModel, SnippetModel, Snippet_TagModel } from '../models'; +import { TagModel, SnippetModel, Snippet_TagModel, UserModel } from '../models'; export const associateModels = async () => { TagModel.belongsToMany(SnippetModel, { @@ -12,4 +12,14 @@ export const associateModels = async () => { foreignKey: 'snippet_id', as: 'tags' }); + + UserModel.hasMany(SnippetModel, { + foreignKey: 'createdBy', + as: 'snippets' + }); + + SnippetModel.belongsTo(UserModel, { + foreignKey: 'createdBy', + as: 'user' + }); }; diff --git a/src/db/migrations/03_authentication.ts b/src/db/migrations/03_authentication.ts new file mode 100644 index 0000000..1db806e --- /dev/null +++ b/src/db/migrations/03_authentication.ts @@ -0,0 +1,50 @@ +import { DataTypes, QueryInterface } from 'sequelize'; +import { createAdmin } from '../../utils'; + +const { STRING, INTEGER, DATE } = DataTypes; + +export const up = async (queryInterface: QueryInterface): Promise => { + await queryInterface.createTable('users', { + id: { + type: INTEGER, + allowNull: false, + primaryKey: true, + autoIncrement: true + }, + email: { + type: STRING, + allowNull: false, + unique: true + }, + password: { + type: STRING, + allowNull: false + }, + role: { + type: STRING, + allowNull: true, + defaultValue: 'user' + }, + createdAt: { + type: DATE, + allowNull: false + }, + updatedAt: { + type: DATE, + allowNull: false + } + }); + + await queryInterface.addColumn('snippets', 'createdBy', { + type: INTEGER, + allowNull: false, + defaultValue: 1 + }); + + await createAdmin('admin@local.com', 'snippet-admin'); +}; + +export const down = async (queryInterface: QueryInterface): Promise => { + await queryInterface.dropTable('users'); + await queryInterface.removeColumn('snippets', 'createdBy'); +}; diff --git a/src/models/Snippet.ts b/src/models/Snippet.ts index 0b23780..1195ec7 100644 --- a/src/models/Snippet.ts +++ b/src/models/Snippet.ts @@ -43,6 +43,11 @@ export const SnippetModel = sequelize.define( allowNull: true, defaultValue: 0 }, + createdBy: { + type: INTEGER, + allowNull: false, + defaultValue: 1 + }, createdAt: { type: DATE }, diff --git a/src/typescript/interfaces/Snippet.ts b/src/typescript/interfaces/Snippet.ts index 4feabe1..f63f68c 100644 --- a/src/typescript/interfaces/Snippet.ts +++ b/src/typescript/interfaces/Snippet.ts @@ -9,6 +9,7 @@ export interface Snippet extends Model { docs: string; isPinned: number; tags?: { name: string }[]; + createdBy: number; } export interface SnippetCreationAttributes diff --git a/src/utils/createAdmin.ts b/src/utils/createAdmin.ts new file mode 100644 index 0000000..3ba914d --- /dev/null +++ b/src/utils/createAdmin.ts @@ -0,0 +1,14 @@ +import { UserModel } from '../models'; +import { hashPassword } from '.'; + +export const createAdmin = async ( + email: string, + password: string +): Promise => { + const passwordHash = await hashPassword(password); + await UserModel.create({ + email, + password: passwordHash, + role: 'admin' + }); +}; diff --git a/src/utils/index.ts b/src/utils/index.ts index e9efd2a..5a404b8 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -3,3 +3,7 @@ export * from './ErrorResponse'; export * from './tagParser'; export * from './getTags'; export * from './createTags'; +export * from './createAdmin'; +export * from './hashPassword'; +export * from './signToken'; +export * from './createAdmin';