Explorar el Código

chor: add migrations and add new column constraints

poeti8 hace 6 años
padre
commit
8f58452f4c

+ 16 - 0
knexfile.ts

@@ -0,0 +1,16 @@
+import env from "./server/env";
+
+module.exports = {
+  production: {
+    client: "postgresql",
+    connection: {
+      database: env.DB_NAME,
+      user: env.DB_USER,
+      password: env.DB_PASSWORD
+    },
+    migrations: {
+      tableName: "knex_migrations",
+      directory: "server/migrations"
+    }
+  }
+};

+ 3 - 2
package.json

@@ -7,9 +7,10 @@
     "test": "mocha --compilers js:@babel/register ./client/**/__test__/*.js",
     "docker:build": "docker build -t kutt .",
     "docker:run": "docker run -p 3000:3000 --env-file .env -d kutt:latest",
-    "dev": "nodemon server/server.ts",
-    "build": "next build client/ && rimraf production-server && tsc --project tsconfig.json && copyfiles -f \"server/mail/*.html\" production-server/mail",
+    "dev": "npm run migrate && nodemon server/server.ts",
+    "build": "npm run migrate && next build client/ && rimraf production-server && tsc --project tsconfig.json && copyfiles -f \"server/mail/*.html\" production-server/mail",
     "start": "NODE_ENV=production node production-server/server.js",
+    "migrate": "knex migrate:up --env production",
     "lint": "eslint server/ --ext .js,.ts --fix",
     "lint:nofix": "eslint server/ --ext .js,.ts"
   },

+ 0 - 15
server/knex.ts

@@ -1,11 +1,5 @@
 import knex from "knex";
 
-import { createUserTable } from "./models/user";
-import { createDomainTable } from "./models/domain";
-import { createLinkTable } from "./models/link";
-import { createVisitTable } from "./models/visit";
-import { createIPTable } from "./models/ip";
-import { createHostTable } from "./models/host";
 import env from "./env";
 
 const db = knex({
@@ -24,13 +18,4 @@ const db = knex({
   }
 });
 
-export async function initializeDb() {
-  await createUserTable(db);
-  await createIPTable(db);
-  await createDomainTable(db);
-  await createHostTable(db);
-  await createLinkTable(db);
-  await createVisitTable(db);
-}
-
 export default db;

+ 42 - 0
server/migrations/20200211220920_constraints.ts

@@ -0,0 +1,42 @@
+import * as Knex from "knex";
+import * as models from "../models";
+
+export async function up(knex: Knex): Promise<any> {
+  await models.createUserTable(knex);
+  await models.createIPTable(knex);
+  await models.createDomainTable(knex);
+  await models.createHostTable(knex);
+  await models.createLinkTable(knex);
+  await models.createVisitTable(knex);
+
+  await Promise.all([
+    knex.raw(`
+      ALTER TABLE domains
+      DROP CONSTRAINT domains_user_id_foreign,
+      ADD CONSTRAINT domains_user_id_foreign
+        FOREIGN KEY (user_id) 
+        REFERENCES users (id)
+        ON DELETE SET NULL;
+    `),
+    knex.raw(`
+      ALTER TABLE links
+      DROP CONSTRAINT links_user_id_foreign,
+      ADD CONSTRAINT links_user_id_foreign
+        FOREIGN KEY (user_id)
+        REFERENCES users (id)
+        ON DELETE CASCADE;
+    `),
+    knex.raw(`
+      ALTER TABLE visits
+      DROP CONSTRAINT visits_link_id_foreign,
+      ADD CONSTRAINT visits_link_id_foreign
+        FOREIGN KEY (link_Id)
+        REFERENCES links (id)
+        ON DELETE CASCADE;
+    `)
+  ]);
+}
+
+export async function down(knex: Knex): Promise<any> {
+  // do nothing
+}

+ 6 - 0
server/models/index.ts

@@ -0,0 +1,6 @@
+export * from "./domain";
+export * from "./host";
+export * from "./ip";
+export * from "./link";
+export * from "./user";
+export * from "./visit";

+ 2 - 1
server/models/link.ts

@@ -26,7 +26,8 @@ export async function createLinkTable(knex: Knex) {
       table
         .integer("user_id")
         .references("id")
-        .inTable("users");
+        .inTable("users")
+        .onDelete("CASCADE");
       table
         .integer("visit_count")
         .notNullable()

+ 2 - 1
server/models/visit.ts

@@ -15,7 +15,8 @@ export async function createVisitTable(knex: Knex) {
         .integer("link_id")
         .references("id")
         .inTable("links")
-        .notNullable();
+        .notNullable()
+        .onDelete("CASCADE");
       table.jsonb("referrers").defaultTo("{}");
       table
         .integer("total")

+ 0 - 4
server/queries/link.ts

@@ -148,10 +148,6 @@ export const remove = async (match: Partial<Link>) => {
     throw new CustomError("Link was not found.");
   }
 
-  await knex<Visit>("visits")
-    .where("link_id", link.id)
-    .delete();
-
   const deletedLink = await knex<Link>("links")
     .where("id", link.id)
     .delete();

+ 10 - 0
server/queries/user.ts

@@ -73,3 +73,13 @@ export const update = async (match: Match<User>, update: Partial<User>) => {
 
   return users;
 };
+
+export const remove = async (user: User) => {
+  const deletedUser = await knex<User>("users")
+    .where("id", user.id)
+    .delete();
+
+  redis.remove.user(user);
+
+  return !!deletedUser;
+};

+ 12 - 1
server/routes/users.ts

@@ -1,8 +1,10 @@
 import { Router } from "express";
 import asyncHandler from "express-async-handler";
 
-import * as auth from "../handlers/auth";
+import * as validators from "../handlers/validators";
+import * as helpers from "../handlers/helpers";
 import * as user from "../handlers/users";
+import * as auth from "../handlers/auth";
 
 const router = Router();
 
@@ -13,4 +15,13 @@ router.get(
   asyncHandler(user.get)
 );
 
+router.post(
+  "/delete",
+  asyncHandler(auth.apikey),
+  asyncHandler(auth.jwt),
+  validators.deleteUser,
+  asyncHandler(helpers.verify),
+  asyncHandler(user.remove)
+);
+
 export default router;