Vadim 7 сар өмнө
parent
commit
66ba7b94af

+ 30 - 3
src/api/companies-management-api.ts

@@ -2,7 +2,7 @@ import { z } from "zod";
 
 class companyManagementApi {
   // /companies-management/create-company
-  public ZCreateCompany = {
+  ZCreateCompany = {
     req: z
       .object({
         name: z.string(),
@@ -14,8 +14,8 @@ class companyManagementApi {
     }),
   };
 
-  // /companies-management/get-companies
-  public ZGetUserCompanies = {
+  // /companies-management/get-user-companies
+  ZGetUserCompanies = {
     res: z.object({
       code: z.enum(["success"]),
       companies: z.array(
@@ -28,6 +28,33 @@ class companyManagementApi {
       ),
     }),
   };
+
+  ZGetCompany = {
+    req: z
+      .object({
+        companyId: z.string().uuid(),
+      })
+      .strict(),
+    res: z.object({
+      code: z.enum(["success"]),
+      company: z.object({
+        company_id: z.string(),
+        name: z.string(),
+        owner_id: z.string(),
+        timezone: z.string(),
+
+        events: z.array(
+          z.object({
+            event_id: z.string(),
+            local_name: z.string(),
+            timezone: z.string(),
+            company_id: z.string(),
+            dates: z.array(z.date()),
+          }),
+        ),
+      }),
+    }),
+  };
 }
 
 export const CompanyManagementApi = new companyManagementApi();

+ 0 - 19
src/api/events-management-api.ts

@@ -1,25 +1,6 @@
 import { z } from "zod";
 
 class eventsManagementApi {
-  ZGetCompanyEvents = {
-    req: z
-      .object({
-        companyId: z.string(),
-      })
-      .strict(),
-    res: z.object({
-      code: z.enum(["success"]),
-      events: z.array(
-        z.object({
-          event_id: z.string(),
-          local_name: z.string(),
-          timezone: z.string(),
-          dates: z.array(z.date()),
-        }),
-      ),
-    }),
-  };
-
   ZCreateEvent = {
     req: z
       .object({

+ 20 - 13
src/db/db-shema.ts

@@ -9,13 +9,6 @@ const ZDbShema = {
       company_id: z.string(),
     },
 
-    companies: {
-      company_id: z.string(),
-      name: z.string(),
-      owner_id: z.string(),
-      timezone: z.string(),
-    },
-
     event_dates: {
       event_id: z.string(),
       date: z.date(),
@@ -33,6 +26,20 @@ const ZDbShema = {
     },
   },
 
+  companies_management: {
+    companies: {
+      company_id: z.string(),
+      name: z.string(),
+      owner_id: z.string(),
+      timezone: z.string(),
+    },
+
+    company_users: {
+      company_id: z.string(),
+      user_id: z.string(),
+    },
+  },
+
   tasks_management: {
     tasks: {
       task_id: z.string(),
@@ -62,7 +69,7 @@ const ZDbShema = {
     locations: {
       location_id: z.string(),
       name: z.string(),
-      company_id: z.string(),
+      event_id: z.string(),
     },
 
     rooms: {
@@ -106,12 +113,11 @@ const ZDbShema = {
       role_id: z.string(),
     },
 
-    role_entity_permission: {
-      role_id: z.string(),
+    non_default_roles_overrides: {
       entity_id: z.string(),
+      role_id: z.string(),
       permission_id: z.string(),
       permission_value_id: z.string(),
-      is_preset: z.boolean(),
     },
 
     roles: {
@@ -120,7 +126,7 @@ const ZDbShema = {
       description: z.string(),
       entity_id: z.string().nullable(),
       entity_type_id: z.string(),
-      is_default: z.boolean(),
+      is_system: z.boolean(),
     },
 
     permissions: {
@@ -144,7 +150,7 @@ const ZDbShema = {
       permission_value_id: z.string(),
     },
 
-    default_roles_permissions: {
+    default_roles_overrides: {
       role_id: z.string(),
       permission_id: z.string(),
       permission_value_id: z.string(),
@@ -155,6 +161,7 @@ const ZDbShema = {
     entities: {
       entity_id: z.string(),
       entity_type_id: z.string(),
+      parent_id: z.string().nullable(),
     },
 
     entity_types: {

+ 6 - 2
src/main.ts

@@ -1,3 +1,5 @@
+logger.info("Start server");
+
 import "./plugins/dotenv.js";
 
 import express from "express";
@@ -42,11 +44,13 @@ import authRouter from "./modules/users-management/auth/routers/auth-router.js";
 app.use("/api/auth/", authRouter);
 
 // events-management
-import CompaniesRouter from "./modules/events-management/companies-router.js";
-app.use("/api/events-management/", authMiddleware(), CompaniesRouter);
 import EventsRouter from "./modules/events-management/events-router.js";
 app.use("/api/events-management/", authMiddleware(), EventsRouter);
 
+// companies-management
+import CompaniesRouter from "./modules/companies-management/companies-router.js";
+app.use("/api/companies-management/", authMiddleware(), CompaniesRouter);
+
 // locations-management
 import LocationsRouter from "./modules/locations-management/locations-router.js";
 app.use("/api/locations-management/", authMiddleware(), LocationsRouter);

+ 2 - 0
src/middlewares/auth-middleware.ts

@@ -1,6 +1,7 @@
 import { ApiError } from "../exceptions/api-error.js";
 import tokenService from "#modules/users-management/auth/services/token-service.js";
 import type { NextFunction, Request, Response } from "express";
+import { logger } from "#plugins/logger.js";
 
 export default function () {
   return function (req: Request, res: Response, next: NextFunction) {
@@ -25,6 +26,7 @@ export default function () {
       req.user = userData;
       next();
     } catch (e) {
+      logger.silly(e);
       return next(ApiError.UnauthorizedError());
     }
   };

+ 188 - 0
src/modules/companies-management/companies-router.ts

@@ -0,0 +1,188 @@
+// router
+import express from "express";
+const router = express.Router();
+export default router;
+
+// db
+import { db } from "#db";
+import { ZDbShema } from "#db-shema";
+import { sql } from "slonik";
+
+// api
+import { CompanyManagementApi } from "#api/companies-management-api.js";
+
+// error
+// import { ApiError } from "#exceptions/api-error.ts";
+
+// dayjs
+import dayjs from "dayjs";
+import utc from "dayjs/plugin/utc.js";
+dayjs.extend(utc);
+import timezone from "dayjs/plugin/timezone.js";
+dayjs.extend(timezone);
+
+// other
+import { z } from "zod";
+
+import { v7 as uuidv7 } from "uuid";
+// import { logger } from "#logger";
+import { UserUtils } from "#utils/user-utils.js";
+import { EntityesService } from "#modules/entities-management/entityes-service.js";
+import { RouterUtils } from "#utils/router-utils.js";
+import { ApiError } from "#exceptions/api-error.js";
+import { CompaniesService } from "./companies-service.js";
+import { CheckPermissionsService } from "#modules/permissions-management/check-permissions-service.js";
+
+dayjs.extend(utc);
+
+// TODO транзакции
+router.post("/create-company", async (req, res, next) => {
+  try {
+    // валидация запроса
+    const { name, timezone } = CompanyManagementApi.ZCreateCompany.req.parse(
+      req.body,
+    );
+
+    const userId = UserUtils.getUserFromReq(req).userId;
+
+    const companyId = uuidv7();
+
+    // entity
+    await EntityesService.createEntity(companyId, "company");
+
+    // company
+    await db.query(
+      sql.unsafe`
+      insert into companies_management.companies
+        (company_id, name, owner_id, timezone)
+      values
+        (${companyId}, ${name}, ${userId}, ${timezone})`,
+    );
+
+    // add user to company
+    await db.query(
+      sql.unsafe`
+      insert into companies_management.company_users
+        (company_id, user_id)
+      values
+        (${companyId}, ${userId})`,
+    );
+
+    // permissions
+    const MANAGER_ROLE_ID = process.env.COMPANY_DEFAULT_ROLE_MANAGER_ID;
+    if (!MANAGER_ROLE_ID) {
+      throw Error("COMPANY_DEFAULT_ROLE_MANAGER_ID is not defined");
+    }
+
+    // TODO сделать триггер для проверка entity_id и is_defaul в БД при создании роли.
+    await db.query(
+      sql.unsafe`
+      insert into permissions_management.user_roles
+        (user_id, role_id, entity_id)
+      values
+        (${userId}, ${MANAGER_ROLE_ID}, ${companyId})`,
+    );
+
+    RouterUtils.validAndSendResponse(
+      CompanyManagementApi.ZCreateCompany.res,
+      res,
+      { code: "success" },
+    );
+  } catch (e) {
+    next(e);
+  }
+});
+
+router.post("/get-user-companies", async (req, res, next) => {
+  try {
+    const userId = UserUtils.getUserFromReq(req).userId;
+
+    const companies = await db.any(
+      sql.type(
+        z.object({
+          company_id: ZDbShema.companies_management.companies.company_id,
+          name: ZDbShema.companies_management.companies.name,
+          owner_id: ZDbShema.companies_management.companies.owner_id,
+          timezone: ZDbShema.companies_management.companies.timezone,
+        }),
+      )`
+        select
+          c.company_id,
+          c."name",
+          c.owner_id,
+          c.timezone
+        from
+          companies_management.companies c
+        join companies_management.company_users cu on
+          c.company_id = cu.company_id
+        where
+          cu.user_id = ${userId}
+        `,
+    );
+
+    RouterUtils.validAndSendResponse(
+      CompanyManagementApi.ZGetUserCompanies.res,
+      res,
+      { code: "success", companies: [...companies] },
+    );
+  } catch (e) {
+    next(e);
+  }
+});
+
+router.post("/get-company", async (req, res, next) => {
+  try {
+    // валидация запроса
+    const { companyId } = CompanyManagementApi.ZGetCompany.req.parse(req.body);
+
+    const userId = UserUtils.getUserFromReq(req).userId;
+
+    await CheckPermissionsService.checkEntityPermission(
+      companyId,
+      userId,
+      "view_company",
+      "view_company_true",
+    );
+
+    const company = await db.maybeOne(
+      sql.type(
+        z.object({
+          company_id: ZDbShema.companies_management.companies.company_id,
+          name: ZDbShema.companies_management.companies.name,
+          owner_id: ZDbShema.companies_management.companies.owner_id,
+          timezone: ZDbShema.companies_management.companies.timezone,
+        }),
+      )`
+        select
+          c.company_id,
+          c."name",
+          c.owner_id,
+          c.timezone
+        from
+          companies_management.companies c
+        where
+          c.company_id = ${companyId}
+        `,
+    );
+
+    if (!company) {
+      throw ApiError.BadRequest("Company not found", "Компания не найдена");
+    }
+
+    const REQUIRED_PERMISSION = "view_event_true";
+
+    const events = await CompaniesService.getUserCompanyEvents(
+      userId,
+      company.company_id,
+      REQUIRED_PERMISSION,
+    );
+
+    RouterUtils.validAndSendResponse(
+      CompanyManagementApi.ZGetCompany.res,
+      res,
+      { code: "success", company: { ...company, events: [...events] } },
+    );
+  } catch (e) {
+    next(e);
+  }
+});

+ 58 - 0
src/modules/companies-management/companies-service.ts

@@ -0,0 +1,58 @@
+// types
+
+import { db } from "#db";
+import { sql } from "slonik";
+import { z } from "zod";
+import { ZDbShema } from "#db/db-shema.js";
+
+class companiesService {
+  async getUserCompanyEvents(
+    userId: string,
+    companyId: string,
+    requiredPermission: string,
+  ) {
+    const DbEventsTypes = ZDbShema.events_management.events;
+    const events = await db.any(
+      sql.type(
+        z.object({
+          event_id: DbEventsTypes.event_id,
+          local_name: DbEventsTypes.event_id,
+          timezone: DbEventsTypes.timezone,
+          company_id: DbEventsTypes.company_id,
+          dates: z.array(ZDbShema.events_management.event_dates.date),
+        }),
+      )`
+            select
+              e.event_id,
+              e.local_name,
+              e.timezone,
+              e.company_id,
+              ARRAY_AGG(ed."date") as dates
+            from
+              events_management.events e
+            join 
+              permissions_management.cached_user_permissions cup 
+            on
+              e.company_id = cup.entity_id
+            left join 
+              events_management.event_dates ed 
+            on
+              e.event_id = ed.event_id
+            where
+              e.company_id = ${companyId}
+              and
+              cup.user_id = ${userId}
+              and cup.permission_value_id = ${requiredPermission}
+            group by
+              e.event_id,
+              e.local_name,
+              e.timezone,
+              e.company_id;
+            `,
+    );
+
+    return events;
+  }
+}
+
+export const CompaniesService = new companiesService();

+ 1 - 1
src/modules/entities-management/entityes-service.ts

@@ -8,7 +8,7 @@ class entityesService {
   ) {
     await db.query(
       sql.unsafe`
-      insert into entity_management.entities 
+      insert into entities_management.entities 
         (entity_id, entity_type_id)
       values 
         (${entityId}, ${entityTypeId})`,

+ 0 - 120
src/modules/events-management/companies-router.ts

@@ -1,120 +0,0 @@
-// router
-import express from "express";
-const router = express.Router();
-export default router;
-
-// db
-import { db } from "#db";
-import { ZDbShema } from "#db-shema";
-import { sql } from "slonik";
-
-// api
-import { CompanyManagementApi } from "#api/companies-management-api.js";
-
-// error
-// import { ApiError } from "#exceptions/api-error.ts";
-
-// dayjs
-import dayjs from "dayjs";
-import utc from "dayjs/plugin/utc.js";
-dayjs.extend(utc);
-import timezone from "dayjs/plugin/timezone.js";
-dayjs.extend(timezone);
-
-// other
-import { z } from "zod";
-
-import { v7 as uuidv7 } from "uuid";
-// import { logger } from "#logger";
-import { UserUtils } from "#utils/user-utils.js";
-import { EntityesService } from "#modules/entities-management/entityes-service.js";
-import { RouterUtils } from "#utils/router-utils.js";
-
-dayjs.extend(utc);
-
-router.post("/create-company", async (req, res, next) => {
-  try {
-    // валидация запроса
-    const { name, timezone } = CompanyManagementApi.ZCreateCompany.req.parse(
-      req.body,
-    );
-
-    const userId = UserUtils.getUserFromReq(req).userId;
-
-    const companyId = uuidv7();
-
-    // entity
-    await EntityesService.createEntity(companyId, "company");
-
-    // company
-    await db.query(
-      sql.unsafe`
-      insert into events_management.companies
-        (company_id, name, owner_id, timezone)
-      values
-        (${companyId}, ${name}, ${userId}, ${timezone})`,
-    );
-
-    // permissions
-    const MANAGER_ROLE_ID = process.env.COMPANY_MANAGER_ROLE_ID;
-    if (!MANAGER_ROLE_ID) {
-      throw Error("COMPANY_MANAGER_ROLE_ID is not defined");
-    }
-
-    await db.query(
-      sql.unsafe`
-      insert into permissions_management.user_roles
-        (user_id, role_id)
-      values
-        (${userId}, ${MANAGER_ROLE_ID})`,
-    );
-
-    RouterUtils.validAndSendResponse(
-      CompanyManagementApi.ZCreateCompany.res,
-      res,
-      { code: "success" },
-    );
-  } catch (e) {
-    next(e);
-  }
-});
-
-router.post("/get-user-companies", async (req, res, next) => {
-  try {
-    const userId = UserUtils.getUserFromReq(req).userId;
-
-    const REQUIRED_PERMISSION = "company_view_true";
-
-    const companies = await db.any(
-      sql.type(
-        z.object({
-          company_id: ZDbShema.events_management.companies.company_id,
-          name: ZDbShema.events_management.companies.name,
-          owner_id: ZDbShema.events_management.companies.owner_id,
-          timezone: ZDbShema.events_management.companies.timezone,
-        }),
-      )`
-        select
-          c.company_id,
-          c."name",
-          c.owner_id,
-          c.timezone
-        from
-          events_management.companies c
-        join permissions_management.cached_user_permissions cup on
-          c.company_id = cup.entity_id
-        where 
-          cup.user_id = ${userId}
-          and cup.permission_value_id = ${REQUIRED_PERMISSION}
-        `,
-    );
-
-    RouterUtils.validAndSendResponse(
-      CompanyManagementApi.ZGetUserCompanies.res,
-      res,
-      { code: "success", companies: [...companies] },
-    );
-  } catch (e) {
-    next(e);
-  }
-});

+ 9 - 61
src/modules/events-management/events-router.ts

@@ -33,65 +33,6 @@ import { RouterUtils } from "#utils/router-utils.js";
 
 dayjs.extend(utc);
 
-router.post("/get-company-events", async (req, res, next) => {
-  try {
-    // валидация запроса
-    const { companyId } = EventsManagementApi.ZGetCompanyEvents.req.parse(
-      req.body,
-    );
-
-    // const nowWithUzerTz = dayjs.utc().startOf("day");
-    const userId = UserUtils.getUserFromReq(req).userId;
-
-    const DbEventsTypes = ZDbShema.events_management.events;
-    const events = await db.any(
-      sql.type(
-        z.object({
-          event_id: DbEventsTypes.event_id,
-          local_name: DbEventsTypes.event_id,
-          timezone: DbEventsTypes.timezone,
-          dates: z.array(ZDbShema.events_management.event_dates.date),
-        }),
-      )`
-        select
-          e.event_id,
-          e.local_name,
-          e.timezone,
-          e.company_id,
-          ARRAY_AGG(ed."date") as dates
-        from
-          events_management.events e
-        join 
-          permissions_management.cached_user_permissions cup 
-        on
-          e.company_id = cup.entity_id
-        left join 
-          events_management.event_dates ed 
-        on
-          e.event_id = ed.event_id
-        where
-          e.company_id = ${companyId}
-          and
-          cup.user_id = ${userId}
-          and cup.permission_value_id = 'view_event_true'
-        group by
-          e.event_id,
-          e.local_name,
-          e.timezone,
-          e.company_id;
-        `,
-    );
-
-    RouterUtils.validAndSendResponse(
-      EventsManagementApi.ZGetCompanyEvents.res,
-      res,
-      { code: "success", events: [...events] },
-    );
-  } catch (e) {
-    next(e);
-  }
-});
-
 router.post("/create-event", async (req, res, next) => {
   try {
     // валидация запроса
@@ -104,6 +45,7 @@ router.post("/create-event", async (req, res, next) => {
     await CheckPermissionsService.checkEntityPermission(
       companyId,
       userId,
+      "create_event",
       "create_event_true",
     );
 
@@ -114,13 +56,13 @@ router.post("/create-event", async (req, res, next) => {
         await db.one(
           sql.type(
             z.object({
-              timezone: ZDbShema.events_management.companies.timezone,
+              timezone: ZDbShema.companies_management.companies.timezone,
             }),
           )`
           select 
             timezone 
           from 
-            events_management.companies 
+            companies_management.companies 
           where 
             company_id = ${companyId}`,
         )
@@ -193,6 +135,7 @@ router.post("/get-event", async (req, res, next) => {
     await CheckPermissionsService.checkEntityPermission(
       eventId,
       userId,
+      "view_event",
       "view_event_true",
     );
 
@@ -313,6 +256,7 @@ router.post("/create-program-point", async (req, res, next) => {
     await CheckPermissionsService.checkEntityPermission(
       eventId,
       userId,
+      "create_program_point",
       "create_program_point_true",
     );
 
@@ -351,6 +295,7 @@ router.post("/update-event", async (req, res, next) => {
       await CheckPermissionsService.checkEntityPermission(
         eventId,
         userId,
+        "edit_event_name",
         "edit_event_name_true",
       );
     }
@@ -360,6 +305,7 @@ router.post("/update-event", async (req, res, next) => {
       await CheckPermissionsService.checkEntityPermission(
         eventId,
         userId,
+        "edit_event_timezone",
         "edit_event_timezone_true",
       );
     }
@@ -390,6 +336,7 @@ router.post("/update-event", async (req, res, next) => {
       await CheckPermissionsService.checkEntityPermission(
         eventId,
         userId,
+        "edit_event_dates",
         "edit_event_dates_true",
       );
 
@@ -454,6 +401,7 @@ router.post("/update-program-point", async (req, res, next) => {
     await CheckPermissionsService.checkEntityPermission(
       eventId,
       userId,
+      "edit_event_program_points",
       "edit_event_program_points_true",
     );
 

+ 5 - 1
src/modules/locations-management/locations-router.ts

@@ -42,6 +42,7 @@ router.post("/create-location", async (req, res, next) => {
     await CheckPermissionsService.checkEntityPermission(
       companyId,
       userId,
+      "create_location",
       "create_location_true",
     );
 
@@ -68,6 +69,7 @@ router.post("/create-location", async (req, res, next) => {
   }
 });
 
+// TODO заменить на ивент
 router.post("/get-company-locations", async (req, res, next) => {
   try {
     // валидация запроса
@@ -83,7 +85,7 @@ router.post("/get-company-locations", async (req, res, next) => {
           location_id: ZDbShema.locations_management.locations.location_id,
           name: ZDbShema.locations_management.locations.name,
         }),
-      )`
+      )` 
               select
                 l.location_id,
                 l.name
@@ -146,6 +148,7 @@ router.post("/create-room", async (req, res, next) => {
     await CheckPermissionsService.checkEntityPermission(
       companyId,
       userId,
+      "create_room",
       "create_room_true",
     );
 
@@ -203,6 +206,7 @@ router.post("/get-location-rooms", async (req, res, next) => {
     await CheckPermissionsService.checkEntityPermission(
       companyId,
       userId,
+      "locations_view",
       "locations_view_true",
     );
 

+ 3 - 2
src/modules/permissions-management/check-permissions-service.ts

@@ -3,25 +3,26 @@
 import { ApiError } from "#exceptions/api-error.js";
 import { db } from "#db";
 import { sql } from "slonik";
-import { AllPermissionsValues } from "./permissions-types.js";
+import { AllPermissions, AllPermissionsValues } from "./permissions-types.js";
 
 class checkPermissionsService {
   async checkEntityPermission(
     entityId: string,
     userId: string,
+    requiredPermission: AllPermissions,
     requiredPermissionValues: AllPermissionsValues | AllPermissionsValues[],
   ) {
     if (typeof requiredPermissionValues === "string") {
       requiredPermissionValues = [requiredPermissionValues];
     }
 
-    // TODO добавить проверку родителя
     const isFound = await db.exists(sql.unsafe`
     select * from
       permissions_management.cached_user_permissions
     where
       entity_id = ${entityId} and
       user_id = ${userId} and
+      permission_id = ${requiredPermission} and
       permission_value IN (${sql.join(
         requiredPermissionValues.map((value) => sql.unsafe`${value}`),
         sql.fragment`, `,

+ 27 - 7
src/modules/permissions-management/permissions-types.ts

@@ -7,17 +7,24 @@ export const PERMISSIONS = {
     entityType: "company",
     values: ["create_event_true", "create_event_false"],
   },
-  create_location: {
+  edit_company_name: {
     entityType: "company",
-    values: ["create_location_true", "create_location_false"],
+    values: ["edit_company_name_true", "edit_company_name_false"],
   },
-  locations_view: {
+
+  edit_company_timezone: {
     entityType: "company",
-    values: ["locations_view_true", "locations_view_false"],
+    values: ["edit_company_timezone_true", "edit_company_timezone_false"],
   },
-  create_room: {
-    entityType: "location",
-    values: ["create_room_true", "create_room_false"],
+
+  add_users_to_company: {
+    entityType: "company",
+    values: ["add_users_to_company_true", "add_users_to_company_false"],
+  },
+
+  delete_company: {
+    entityType: "company",
+    values: ["delete_company_true", "delete_company_false"],
   },
 
   // event
@@ -52,6 +59,18 @@ export const PERMISSIONS = {
     entityType: "event",
     values: ["create_task_block_true", "create_task_block_false"],
   },
+  create_location: {
+    entityType: "event",
+    values: ["create_location_true", "create_location_false"],
+  },
+  locations_view: {
+    entityType: "event",
+    values: ["locations_view_true", "locations_view_false"],
+  },
+  create_room: {
+    entityType: "event",
+    values: ["create_room_true", "create_room_false"],
+  },
 
   // task block
   edit_task_block: {
@@ -72,3 +91,4 @@ export const PERMISSIONS = {
 
 export type AllPermissionsValues =
   (typeof PERMISSIONS)[keyof typeof PERMISSIONS]["values"][number];
+export type AllPermissions = keyof typeof PERMISSIONS;

+ 2 - 0
src/modules/tasks-management/task-blocks-router.ts

@@ -47,6 +47,7 @@ router.post("/create-task-block", async (req, res, next) => {
     await CheckPermissionsService.checkEntityPermission(
       eventId,
       userId,
+      "create_task_block",
       "create_task_block_true",
     );
 
@@ -106,6 +107,7 @@ router.post("/update-task-block", async (req, res, next) => {
     await CheckPermissionsService.checkEntityPermission(
       eventId,
       userId,
+      "edit_task_block",
       "edit_task_block_true",
     );
 

+ 2 - 0
src/modules/tasks-management/tasks-router.ts

@@ -54,6 +54,7 @@ router.post("/create-task", async (req, res, next) => {
     await CheckPermissionsService.checkEntityPermission(
       taskBlockId,
       userId,
+      "create_task",
       "create_task_true",
     );
 
@@ -108,6 +109,7 @@ router.post("/update-task", async (req, res, next) => {
     await CheckPermissionsService.checkEntityPermission(
       taskId,
       userId,
+      "edit_task",
       "edit_task_true",
     );
 

+ 37 - 14
src/modules/users-management/auth/routers/auth-router.ts

@@ -187,17 +187,27 @@ router.post("/login", async (req, res, next) => {
         email = ${email}`,
     );
     if (!user) {
-      RouterUtils.validAndSendResponse(AuthApi.ZLogin.res, res, {
-        code: "userNotFound",
-      });
+      RouterUtils.validAndSendResponse(
+        AuthApi.ZLogin.res,
+        res,
+        {
+          code: "userNotFound",
+        },
+        400,
+      );
       return;
     }
 
     // если количество попыток превышено
     if (user.wrong_pass_tries > Number(process.env.PASSWORD_MAX_TRIES) - 1) {
-      RouterUtils.validAndSendResponse(AuthApi.ZLogin.res, res, {
-        code: "tooManyTries",
-      });
+      RouterUtils.validAndSendResponse(
+        AuthApi.ZLogin.res,
+        res,
+        {
+          code: "tooManyTries",
+        },
+        400,
+      );
       return;
     }
 
@@ -208,10 +218,15 @@ router.post("/login", async (req, res, next) => {
       const triesRemained =
         Number(process.env.PASSWORD_MAX_TRIES) - 1 - user.wrong_pass_tries;
 
-      RouterUtils.validAndSendResponse(AuthApi.ZLogin.res, res, {
-        code: "passIsWrong",
-        triesRemained,
-      });
+      RouterUtils.validAndSendResponse(
+        AuthApi.ZLogin.res,
+        res,
+        {
+          code: "passIsWrong",
+          triesRemained,
+        },
+        400,
+      );
       return;
     }
 
@@ -230,10 +245,15 @@ router.post("/login", async (req, res, next) => {
       // secure: true, //после включения https
     });
 
-    RouterUtils.validAndSendResponse(AuthApi.ZLogin.res, res, {
-      code: "success",
-      userData: { email, accessToken, refreshToken, userId: user.user_id },
-    });
+    RouterUtils.validAndSendResponse(
+      AuthApi.ZLogin.res,
+      res,
+      {
+        code: "success",
+        userData: { email, accessToken, refreshToken, userId: user.user_id },
+      },
+      200,
+    );
   } catch (e) {
     next(e);
   }
@@ -277,6 +297,7 @@ router.get("/refresh", async (req, res, next) => {
     const { refreshToken } = req.cookies;
 
     if (!refreshToken) throw ApiError.UnauthorizedError();
+
     const userData = tokenService.validateRefreshToken(refreshToken);
     const tokenIsExist = await tokenService.findToken(
       userData.userId,
@@ -284,6 +305,7 @@ router.get("/refresh", async (req, res, next) => {
     );
 
     if (!userData || !tokenIsExist) {
+      res.clearCookie("refreshToken");
       throw ApiError.UnauthorizedError();
     }
 
@@ -306,6 +328,7 @@ router.get("/refresh", async (req, res, next) => {
 
     await tokenService.updateRefreshToken(
       userData.userId,
+      refreshToken,
       newTokens.refreshToken,
     );
     res.cookie("refreshToken", newTokens.refreshToken, {

+ 14 - 4
src/modules/users-management/auth/services/token-service.ts

@@ -11,16 +11,21 @@ import { z } from "zod";
 const JWT_ACCESS_SECRET = process.env.JWT_ACCESS_SECRET || "";
 const JWT_REFRESH_SECRET = process.env.JWT_REFRESH_SECRET || "";
 
+const ACCESS_TOKEN_LIFETIME_MINS =
+  process.env.ACCESS_TOKEN_LIFETIME_MINS || "15";
+const REFRESH_TOKEN_LIFETIME_DAYS =
+  process.env.REFRESH_TOKEN_LIFETIME_DAYS || "30";
+
 class TokenService {
   generateTokens(payload: z.infer<typeof ZTokenPayload>): {
     accessToken: string;
     refreshToken: string;
   } {
     const accessToken = jwt.sign(payload, JWT_ACCESS_SECRET, {
-      expiresIn: "15m",
+      expiresIn: ACCESS_TOKEN_LIFETIME_MINS + "m",
     });
     const refreshToken = jwt.sign(payload, JWT_REFRESH_SECRET, {
-      expiresIn: "30d",
+      expiresIn: REFRESH_TOKEN_LIFETIME_DAYS + "d",
     });
 
     return {
@@ -40,7 +45,11 @@ class TokenService {
     );
   }
 
-  async updateRefreshToken(userId: string, newRefreshToken: string) {
+  async updateRefreshToken(
+    userId: string,
+    oldRefreshToken: string,
+    newRefreshToken: string,
+  ) {
     await db.query(
       sql.unsafe`
       update
@@ -48,7 +57,8 @@ class TokenService {
       set
         refresh_token = ${newRefreshToken}
       where
-        user_id = ${userId}
+        user_id = ${userId} and 
+        refresh_token = ${oldRefreshToken}
   `,
     );
   }

+ 0 - 1
src/plugins/dayjs.ts

@@ -1,4 +1,3 @@
-type dayjsInput = string | number | dayjs.Dayjs | Date | null | undefined;
 type Dayjs = dayjs.Dayjs;
 
 //  plugins

+ 14 - 3
src/plugins/logger.ts

@@ -1,9 +1,18 @@
 import { createLogger, format, transports } from "winston";
-
 import path from "path";
 
 const __dirname = path.resolve();
 
+// Функция для форматирования вложенных объектов
+const formatNestedObjects = (obj: unknown): string => {
+  if (typeof obj !== "object" || obj === null) {
+    return String(obj);
+  }
+
+  // Преобразуем объект в форматированный JSON и заменяем \n на реальные переносы
+  return JSON.stringify(obj, null, 2).replace(/\\n/g, "\n");
+};
+
 // Форматирование логов
 const customFormat = format.combine(
   format.timestamp({ format: "DD.MM.YYYY HH:mm:ss" }), // Добавление временной метки
@@ -16,14 +25,16 @@ const customFormat = format.combine(
 
     // Форматирование вложенных объектов
     const additionalData = Object.keys(rest).length
-      ? `\nAdditional Info: ${JSON.stringify(rest, null, 2)}`
+      ? `\nAdditional Info:\n${formatNestedObjects(rest)}`
       : "";
 
     // Извлечение информации о файле и строке из стека
     const stackInfo = stackString ? stackString.split("\n")[1]?.trim() : "";
-    return `[${timestamp}] [${level}]: ${message} ${additionalData} ${stackInfo} `;
+
+    return `[${timestamp}] [${level}]: ${message}${additionalData}${stackInfo ? `\nStack Info: ${stackInfo}` : ""}`;
   }),
 );
+
 // Логгер Winston
 export const logger = createLogger({
   level: process.env.LOGS_LEVEL || "error", // Уровень логирования