From 15b9522e661429f0dcc9924bd2a0be5c3fa34708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20D=C3=B6ll?= Date: Thu, 18 Jan 2024 09:48:06 +0000 Subject: [PATCH] chore: add checkPermissions --- packages/app/src/app/dashboard/page.tsx | 1 + .../src/components/teams/new-form.action.tsx | 8 +-- packages/app/src/db/config/config.ts | 4 ++ .../20231120145740-added_new_auth.js | 54 +++++++++++++++++-- packages/app/src/db/models/teams.ts | 5 -- .../app/src/db/models/users-permissions.ts | 44 +++++++++++++++ packages/app/src/db/models/users-roles.ts | 4 +- packages/app/src/db/models/users-teams.ts | 38 +++++++++++++ packages/app/src/db/models/users.ts | 8 ++- packages/app/src/db/schemas/permissions.ts | 8 +++ packages/app/src/db/services/permissions.ts | 5 ++ packages/app/src/db/services/teams.ts | 19 ++++--- packages/app/src/server/routers/_app.ts | 3 ++ .../src/server/routers/actions/permissions.ts | 7 +++ .../src/server/routers/schemas/permissions.ts | 8 +++ 15 files changed, 185 insertions(+), 31 deletions(-) create mode 100644 packages/app/src/db/models/users-permissions.ts create mode 100644 packages/app/src/db/models/users-teams.ts create mode 100644 packages/app/src/db/schemas/permissions.ts create mode 100644 packages/app/src/db/services/permissions.ts create mode 100644 packages/app/src/server/routers/actions/permissions.ts create mode 100644 packages/app/src/server/routers/schemas/permissions.ts diff --git a/packages/app/src/app/dashboard/page.tsx b/packages/app/src/app/dashboard/page.tsx index ea2a5cbf..08f39493 100644 --- a/packages/app/src/app/dashboard/page.tsx +++ b/packages/app/src/app/dashboard/page.tsx @@ -13,6 +13,7 @@ import TotalSolutionsCard from './components/total-solutions-card' import LoadingCard from './components/loading-card' import { Main } from '@/components/main' import WorkloadsListCard from '@/components/dashboard/workloads-card' +import { api } from '@/trpc/server-http' export const metadata: Metadata = { title: 'Dashboard', diff --git a/packages/app/src/components/teams/new-form.action.tsx b/packages/app/src/components/teams/new-form.action.tsx index 659afcf7..9991a12c 100644 --- a/packages/app/src/components/teams/new-form.action.tsx +++ b/packages/app/src/components/teams/new-form.action.tsx @@ -2,14 +2,8 @@ import 'server-only' import { createAction, protectedProcedure } from '@/server/trpc' -import { createTeam } from '@/db/services/teams' import { TeamsCreateSchema } from '@/server/routers/schemas/teams' export const rhfAction = createAction( - protectedProcedure - .input(TeamsCreateSchema) - .mutation( - async opts => - await createTeam({ ...opts.input, userId: opts.ctx.session.user.id }) - ) + protectedProcedure.input(TeamsCreateSchema).mutation(async opts => {}) ) diff --git a/packages/app/src/db/config/config.ts b/packages/app/src/db/config/config.ts index 3aa38d31..64d61d54 100644 --- a/packages/app/src/db/config/config.ts +++ b/packages/app/src/db/config/config.ts @@ -26,6 +26,8 @@ import { Role } from '../models/roles' import { Permission } from '../models/permissions' import { RolePermission } from '../models/roles-permissions' import { UserRole } from '../models/users-roles' +import { UserTeam } from '../models/users-teams' +import { UserPermission } from '../models/users-permissions' const env = process.env.NODE_ENV || 'development' const isProduction = env === 'production' @@ -52,7 +54,9 @@ const models = [ SolutionTemplate, Team, User, + UserPermission, UserRole, + UserTeam, Workload, WorkloadEnvironment, WorkloadLens, diff --git a/packages/app/src/db/migrations/20231120145740-added_new_auth.js b/packages/app/src/db/migrations/20231120145740-added_new_auth.js index 197a9c7c..66b89c51 100644 --- a/packages/app/src/db/migrations/20231120145740-added_new_auth.js +++ b/packages/app/src/db/migrations/20231120145740-added_new_auth.js @@ -102,13 +102,13 @@ module.exports = { image: { type: Sequelize.STRING }, - createdAt: { + created_at: { type: Sequelize.DATE }, - updatedAt: { + updated_at: { type: Sequelize.DATE }, - deletedAt: { + deleted_at: { type: Sequelize.DATE } }) @@ -237,6 +237,15 @@ module.exports = { onUpdate: 'CASCADE', onDelete: 'CASCADE' }, + roleId: { + type: Sequelize.BIGINT, + references: { + model: 'roles', + key: 'id' + }, + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }, teamId: { type: Sequelize.UUID, references: { @@ -246,10 +255,37 @@ module.exports = { onUpdate: 'CASCADE', onDelete: 'CASCADE' }, - roleId: { + createdAt: { + type: Sequelize.DATE + }, + updatedAt: { + type: Sequelize.DATE + }, + deletedAt: { + type: Sequelize.DATE + } + }) + + await queryInterface.createTable('users-teams', { + id: { type: Sequelize.BIGINT, + autoIncrement: true, + allowNull: false, + primaryKey: true + }, + userId: { + type: Sequelize.UUID, references: { - model: 'roles', + model: 'users', + key: 'id' + }, + onUpdate: 'CASCADE', + onDelete: 'CASCADE' + }, + teamId: { + type: Sequelize.UUID, + references: { + model: 'teams', key: 'id' }, onUpdate: 'CASCADE', @@ -265,13 +301,21 @@ module.exports = { type: Sequelize.DATE } }) + + await queryInterface.sequelize.query( + 'CREATE VIEW vw_user_teams_permissions AS SELECT A."userId", A."teamId", C.slug as permission FROM "users-roles" AS A LEFT JOIN "roles-permissions" AS B ON A."roleId" = B."roleId" LEFT JOIN "permissions" AS C on B."permissionId" = C.id;' + ) }, async down(queryInterface, Sequelize) { await queryInterface.dropTable('verification_token') await queryInterface.dropTable('accounts') await queryInterface.dropTable('sessions') + await queryInterface.sequelize.query( + 'DROP VIEW IF EXISTS vw_user_teams_permissions' + ) await queryInterface.dropTable('users-roles', { cascade: true }) + await queryInterface.dropTable('users-teams', { cascade: true }) await queryInterface.dropTable('roles-permissions', { cascade: true }) await queryInterface.dropTable('permissions', { cascade: true }) await queryInterface.dropTable('roles', { cascade: true }) diff --git a/packages/app/src/db/models/teams.ts b/packages/app/src/db/models/teams.ts index 40106e66..e8236164 100644 --- a/packages/app/src/db/models/teams.ts +++ b/packages/app/src/db/models/teams.ts @@ -14,8 +14,6 @@ import { AllowNull, Default } from 'sequelize-typescript' -import { User } from './users' -import { TeamMembers } from './team-members' export interface TeamAttributes { id: string @@ -54,9 +52,6 @@ export class Team extends Model { @Column description?: string - @BelongsToMany(() => User, () => TeamMembers, 'teamId', 'userId') - members?: User[] - @CreatedAt @Column createdAt?: Date diff --git a/packages/app/src/db/models/users-permissions.ts b/packages/app/src/db/models/users-permissions.ts new file mode 100644 index 00000000..bd46b5ee --- /dev/null +++ b/packages/app/src/db/models/users-permissions.ts @@ -0,0 +1,44 @@ +import { + Table, + Model, + Column, + PrimaryKey, + DataType, + AutoIncrement, + ForeignKey, + Unique, + Default, + BelongsToMany, + AllowNull +} from 'sequelize-typescript' + +export interface UserPermissionAttributes { + id: bigint + userId: string + teamId: string + permission: string +} + +export type UserPermissionCreationAttributes = Omit< + UserPermissionAttributes, + 'id' +> + +@Table({ + tableName: 'vw_user_teams_permissions' +}) +export class UserPermission extends Model< + UserPermissionAttributes, + UserPermissionCreationAttributes +> { + @AllowNull(false) + @Column(DataType.UUIDV4) + userId?: string + + @AllowNull(false) + @Column(DataType.UUIDV4) + teamId?: bigint + + @Column + permission?: string +} diff --git a/packages/app/src/db/models/users-roles.ts b/packages/app/src/db/models/users-roles.ts index b5b5b6ba..eb490e85 100644 --- a/packages/app/src/db/models/users-roles.ts +++ b/packages/app/src/db/models/users-roles.ts @@ -25,9 +25,7 @@ export interface UserRoleAttributes { export type UserRoleCreationAttributes = Omit @Table({ - tableName: 'users', - timestamps: false, - underscored: true + tableName: 'users-roles' }) export class UserRole extends Model< UserRoleAttributes, diff --git a/packages/app/src/db/models/users-teams.ts b/packages/app/src/db/models/users-teams.ts new file mode 100644 index 00000000..7df23d29 --- /dev/null +++ b/packages/app/src/db/models/users-teams.ts @@ -0,0 +1,38 @@ +import { + Table, + Model, + Column, + PrimaryKey, + DataType, + AutoIncrement, + ForeignKey +} from 'sequelize-typescript' +import { User } from './users' +import { Team } from './teams' + +export interface UserTeamAttributes { + id: string +} + +export type UserRoleCreationAttributes = Omit + +@Table({ + tableName: 'users-teams' +}) +export class UserTeam extends Model< + UserTeamAttributes, + UserRoleCreationAttributes +> { + @PrimaryKey + @AutoIncrement + @Column(DataType.BIGINT) + id!: bigint + + @ForeignKey(() => User) + @Column(DataType.UUIDV4) + userId?: string + + @ForeignKey(() => Team) + @Column(DataType.UUIDV4) + teamId?: bigint +} diff --git a/packages/app/src/db/models/users.ts b/packages/app/src/db/models/users.ts index 6aa24e5f..b2e196e5 100644 --- a/packages/app/src/db/models/users.ts +++ b/packages/app/src/db/models/users.ts @@ -9,8 +9,11 @@ import { Default, CreatedAt, DeletedAt, - UpdatedAt + UpdatedAt, + BelongsToMany } from 'sequelize-typescript' +import { UserTeam } from './users-teams' +import { Team } from './teams' export interface UserAttributes { id: string @@ -47,6 +50,9 @@ export class User extends Model { @Column image?: string + @BelongsToMany(() => Team, () => UserTeam, 'userId', 'teamId') + teams?: Team[] + @CreatedAt @Column createdAt?: Date diff --git a/packages/app/src/db/schemas/permissions.ts b/packages/app/src/db/schemas/permissions.ts new file mode 100644 index 00000000..99cbd2f6 --- /dev/null +++ b/packages/app/src/db/schemas/permissions.ts @@ -0,0 +1,8 @@ +import { z } from 'zod' + +export const FindOnePermissionSchema = z.object({ + userId: z.string().uuid(), + teamId: z.string().uuid(), + permission: z.string() +}) +export type FindOnePermissionSchema = z.infer diff --git a/packages/app/src/db/services/permissions.ts b/packages/app/src/db/services/permissions.ts new file mode 100644 index 00000000..fee7a712 --- /dev/null +++ b/packages/app/src/db/services/permissions.ts @@ -0,0 +1,5 @@ +import type { FindOnePermissionSchema } from '../schemas/permissions' +import { UserPermission } from '../models/users-permissions' + +export const findOnePermission = async (opts: FindOnePermissionSchema) => + await UserPermission.count({ where: { ...opts } }) diff --git a/packages/app/src/db/services/teams.ts b/packages/app/src/db/services/teams.ts index cb613fbf..58a60364 100644 --- a/packages/app/src/db/services/teams.ts +++ b/packages/app/src/db/services/teams.ts @@ -7,23 +7,22 @@ import { } from '../schemas/teams' import { z } from 'zod' import sequelize from '@/db/config/config' -import { TeamMembers } from '../models/team-members' export type Pagination = { offset?: number limit?: number } -export const createTeam = async (opts: z.infer) => - sequelize.transaction(async transaction => { - const team = await Team.create({ ...opts }, { transaction }) - await TeamMembers.create( - { userId: opts.userId, teamId: team.id }, - { transaction } - ) +// export const createTeam = async (opts: z.infer) => +// sequelize.transaction(async transaction => { +// const team = await Team.create({ ...opts }, { transaction }) +// await TeamMembers.create( +// { userId: opts.userId, teamId: team.id }, +// { transaction } +// ) - return team.dataValues - }) +// return team.dataValues +// }) export const findOneTeam = async (opts: z.infer) => await Team.findOne({ diff --git a/packages/app/src/server/routers/_app.ts b/packages/app/src/server/routers/_app.ts index f27d3d96..47f178ef 100644 --- a/packages/app/src/server/routers/_app.ts +++ b/packages/app/src/server/routers/_app.ts @@ -23,6 +23,7 @@ import { totalSolutions, deleteSolutionTemplate } from './actions/solutions' +import { checkPermission } from './actions/permissions' import { lensRouter } from '@/server/routers/actions/lenses' import { solutionsRouter } from './actions/solutions' import { profilesRouter } from './actions/profiles' @@ -41,6 +42,8 @@ export const appRouter = router({ return `hello ${opts.input.text} - ${Math.random()}` }), + checkPermission: checkPermission, + secret: publicProcedure.query(async opts => { if (!opts.ctx.session) { return 'You are not authenticated' diff --git a/packages/app/src/server/routers/actions/permissions.ts b/packages/app/src/server/routers/actions/permissions.ts new file mode 100644 index 00000000..af9088f1 --- /dev/null +++ b/packages/app/src/server/routers/actions/permissions.ts @@ -0,0 +1,7 @@ +import { PermissionGetSchema } from '../schemas/permissions' +import { protectedProcedure } from '../../trpc' +import { findOnePermission } from '@/db/services/permissions' + +export const checkPermission = protectedProcedure + .input(PermissionGetSchema) + .query(async opts => findOnePermission(opts.input)) diff --git a/packages/app/src/server/routers/schemas/permissions.ts b/packages/app/src/server/routers/schemas/permissions.ts new file mode 100644 index 00000000..897bb31a --- /dev/null +++ b/packages/app/src/server/routers/schemas/permissions.ts @@ -0,0 +1,8 @@ +import { z } from 'zod' + +export const PermissionGetSchema = z.object({ + userId: z.string().uuid(), + teamId: z.string().uuid(), + permission: z.string() +}) +export type PermissionGetSchema = z.infer