feat: board access group permissions (#422)
* fix: cache is not exportet from react * fix: format issue * wip: add usage of group permissions * feat: show inherited groups and add manage group * refactor: improve board access management * chore: address pull request feedback * fix: type issues * fix: migrations * test: add unit tests for board permissions, permissions and board router * test: add unit tests for board router and get current user permissions method * fix: format issues * fix: deepsource issue
This commit is contained in:
@@ -22,11 +22,18 @@ CREATE TABLE `app` (
|
||||
CONSTRAINT `app_id` PRIMARY KEY(`id`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `boardPermission` (
|
||||
CREATE TABLE `boardGroupPermission` (
|
||||
`board_id` text NOT NULL,
|
||||
`group_id` text NOT NULL,
|
||||
`permission` text NOT NULL,
|
||||
CONSTRAINT `boardGroupPermission_board_id_group_id_permission_pk` PRIMARY KEY(`board_id`,`group_id`,`permission`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `boardUserPermission` (
|
||||
`board_id` text NOT NULL,
|
||||
`user_id` text NOT NULL,
|
||||
`permission` text NOT NULL,
|
||||
CONSTRAINT `boardPermission_board_id_user_id_permission_pk` PRIMARY KEY(`board_id`,`user_id`,`permission`)
|
||||
CONSTRAINT `boardUserPermission_board_id_user_id_permission_pk` PRIMARY KEY(`board_id`,`user_id`,`permission`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `board` (
|
||||
@@ -152,8 +159,10 @@ CREATE INDEX `integration_secret__updated_at_idx` ON `integrationSecret` (`updat
|
||||
CREATE INDEX `integration__kind_idx` ON `integration` (`kind`);--> statement-breakpoint
|
||||
CREATE INDEX `user_id_idx` ON `session` (`userId`);--> statement-breakpoint
|
||||
ALTER TABLE `account` ADD CONSTRAINT `account_userId_user_id_fk` FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `boardPermission` ADD CONSTRAINT `boardPermission_board_id_board_id_fk` FOREIGN KEY (`board_id`) REFERENCES `board`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `boardPermission` ADD CONSTRAINT `boardPermission_user_id_user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `boardGroupPermission` ADD CONSTRAINT `boardGroupPermission_board_id_board_id_fk` FOREIGN KEY (`board_id`) REFERENCES `board`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `boardGroupPermission` ADD CONSTRAINT `boardGroupPermission_group_id_group_id_fk` FOREIGN KEY (`group_id`) REFERENCES `group`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `boardUserPermission` ADD CONSTRAINT `boardUserPermission_board_id_board_id_fk` FOREIGN KEY (`board_id`) REFERENCES `board`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `boardUserPermission` ADD CONSTRAINT `boardUserPermission_user_id_user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `board` ADD CONSTRAINT `board_creator_id_user_id_fk` FOREIGN KEY (`creator_id`) REFERENCES `user`(`id`) ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `groupMember` ADD CONSTRAINT `groupMember_groupId_group_id_fk` FOREIGN KEY (`groupId`) REFERENCES `group`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
ALTER TABLE `groupMember` ADD CONSTRAINT `groupMember_userId_user_id_fk` FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": "5",
|
||||
"dialect": "mysql",
|
||||
"id": "d0a05e9e-107f-4bed-ac54-a4a41369f0da",
|
||||
"id": "47dc6887-a308-480d-8125-183412fe7fa7",
|
||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||
"tables": {
|
||||
"account": {
|
||||
@@ -160,8 +160,62 @@
|
||||
},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"boardPermission": {
|
||||
"name": "boardPermission",
|
||||
"boardGroupPermission": {
|
||||
"name": "boardGroupPermission",
|
||||
"columns": {
|
||||
"board_id": {
|
||||
"name": "board_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"group_id": {
|
||||
"name": "group_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"permission": {
|
||||
"name": "permission",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"boardGroupPermission_board_id_board_id_fk": {
|
||||
"name": "boardGroupPermission_board_id_board_id_fk",
|
||||
"tableFrom": "boardGroupPermission",
|
||||
"tableTo": "board",
|
||||
"columnsFrom": ["board_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"boardGroupPermission_group_id_group_id_fk": {
|
||||
"name": "boardGroupPermission_group_id_group_id_fk",
|
||||
"tableFrom": "boardGroupPermission",
|
||||
"tableTo": "group",
|
||||
"columnsFrom": ["group_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"boardGroupPermission_board_id_group_id_permission_pk": {
|
||||
"name": "boardGroupPermission_board_id_group_id_permission_pk",
|
||||
"columns": ["board_id", "group_id", "permission"]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"boardUserPermission": {
|
||||
"name": "boardUserPermission",
|
||||
"columns": {
|
||||
"board_id": {
|
||||
"name": "board_id",
|
||||
@@ -187,18 +241,18 @@
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"boardPermission_board_id_board_id_fk": {
|
||||
"name": "boardPermission_board_id_board_id_fk",
|
||||
"tableFrom": "boardPermission",
|
||||
"boardUserPermission_board_id_board_id_fk": {
|
||||
"name": "boardUserPermission_board_id_board_id_fk",
|
||||
"tableFrom": "boardUserPermission",
|
||||
"tableTo": "board",
|
||||
"columnsFrom": ["board_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"boardPermission_user_id_user_id_fk": {
|
||||
"name": "boardPermission_user_id_user_id_fk",
|
||||
"tableFrom": "boardPermission",
|
||||
"boardUserPermission_user_id_user_id_fk": {
|
||||
"name": "boardUserPermission_user_id_user_id_fk",
|
||||
"tableFrom": "boardUserPermission",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": ["user_id"],
|
||||
"columnsTo": ["id"],
|
||||
@@ -207,8 +261,8 @@
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"boardPermission_board_id_user_id_permission_pk": {
|
||||
"name": "boardPermission_board_id_user_id_permission_pk",
|
||||
"boardUserPermission_board_id_user_id_permission_pk": {
|
||||
"name": "boardUserPermission_board_id_user_id_permission_pk",
|
||||
"columns": ["board_id", "user_id", "permission"]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "5",
|
||||
"when": 1714414260766,
|
||||
"tag": "0000_chubby_darkhawk",
|
||||
"when": 1714817536714,
|
||||
"tag": "0000_hot_mandrill",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
|
||||
@@ -22,7 +22,16 @@ CREATE TABLE `app` (
|
||||
`href` text
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `boardPermission` (
|
||||
CREATE TABLE `boardGroupPermission` (
|
||||
`board_id` text NOT NULL,
|
||||
`group_id` text NOT NULL,
|
||||
`permission` text NOT NULL,
|
||||
PRIMARY KEY(`board_id`, `group_id`, `permission`),
|
||||
FOREIGN KEY (`board_id`) REFERENCES `board`(`id`) ON UPDATE no action ON DELETE cascade,
|
||||
FOREIGN KEY (`group_id`) REFERENCES `group`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `boardUserPermission` (
|
||||
`board_id` text NOT NULL,
|
||||
`user_id` text NOT NULL,
|
||||
`permission` text NOT NULL,
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": "5",
|
||||
"dialect": "sqlite",
|
||||
"id": "e3ff4a97-d357-4a64-989b-78668b36c82d",
|
||||
"id": "116fcd87-09c7-4c7c-b590-0ed5681ffdc5",
|
||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||
"tables": {
|
||||
"account": {
|
||||
@@ -155,8 +155,62 @@
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"boardPermission": {
|
||||
"name": "boardPermission",
|
||||
"boardGroupPermission": {
|
||||
"name": "boardGroupPermission",
|
||||
"columns": {
|
||||
"board_id": {
|
||||
"name": "board_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"group_id": {
|
||||
"name": "group_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"permission": {
|
||||
"name": "permission",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"boardGroupPermission_board_id_board_id_fk": {
|
||||
"name": "boardGroupPermission_board_id_board_id_fk",
|
||||
"tableFrom": "boardGroupPermission",
|
||||
"tableTo": "board",
|
||||
"columnsFrom": ["board_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"boardGroupPermission_group_id_group_id_fk": {
|
||||
"name": "boardGroupPermission_group_id_group_id_fk",
|
||||
"tableFrom": "boardGroupPermission",
|
||||
"tableTo": "group",
|
||||
"columnsFrom": ["group_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"boardGroupPermission_board_id_group_id_permission_pk": {
|
||||
"columns": ["board_id", "group_id", "permission"],
|
||||
"name": "boardGroupPermission_board_id_group_id_permission_pk"
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"boardUserPermission": {
|
||||
"name": "boardUserPermission",
|
||||
"columns": {
|
||||
"board_id": {
|
||||
"name": "board_id",
|
||||
@@ -182,18 +236,18 @@
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"boardPermission_board_id_board_id_fk": {
|
||||
"name": "boardPermission_board_id_board_id_fk",
|
||||
"tableFrom": "boardPermission",
|
||||
"boardUserPermission_board_id_board_id_fk": {
|
||||
"name": "boardUserPermission_board_id_board_id_fk",
|
||||
"tableFrom": "boardUserPermission",
|
||||
"tableTo": "board",
|
||||
"columnsFrom": ["board_id"],
|
||||
"columnsTo": ["id"],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
},
|
||||
"boardPermission_user_id_user_id_fk": {
|
||||
"name": "boardPermission_user_id_user_id_fk",
|
||||
"tableFrom": "boardPermission",
|
||||
"boardUserPermission_user_id_user_id_fk": {
|
||||
"name": "boardUserPermission_user_id_user_id_fk",
|
||||
"tableFrom": "boardUserPermission",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": ["user_id"],
|
||||
"columnsTo": ["id"],
|
||||
@@ -202,9 +256,9 @@
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"boardPermission_board_id_user_id_permission_pk": {
|
||||
"boardUserPermission_board_id_user_id_permission_pk": {
|
||||
"columns": ["board_id", "permission", "user_id"],
|
||||
"name": "boardPermission_board_id_user_id_permission_pk"
|
||||
"name": "boardUserPermission_board_id_user_id_permission_pk"
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "5",
|
||||
"when": 1714414359385,
|
||||
"tag": "0000_abnormal_kree",
|
||||
"when": 1714817544524,
|
||||
"tag": "0000_premium_forgotten_one",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
"migration:sqlite:generate": "drizzle-kit generate:sqlite --config ./sqlite.config.ts",
|
||||
"migration:run": "tsx ./migrate.ts",
|
||||
"migration:mysql:generate": "drizzle-kit generate:mysql --config ./mysql.config.ts",
|
||||
"push": "drizzle-kit push:sqlite",
|
||||
"studio": "drizzle-kit studio",
|
||||
"push": "drizzle-kit push:sqlite --config ./sqlite.config.ts",
|
||||
"studio": "drizzle-kit studio --config ./sqlite.config.ts",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -201,8 +201,8 @@ export const boards = mysqlTable("board", {
|
||||
columnCount: int("column_count").default(10).notNull(),
|
||||
});
|
||||
|
||||
export const boardPermissions = mysqlTable(
|
||||
"boardPermission",
|
||||
export const boardUserPermissions = mysqlTable(
|
||||
"boardUserPermission",
|
||||
{
|
||||
boardId: text("board_id")
|
||||
.notNull()
|
||||
@@ -219,6 +219,24 @@ export const boardPermissions = mysqlTable(
|
||||
}),
|
||||
);
|
||||
|
||||
export const boardGroupPermissions = mysqlTable(
|
||||
"boardGroupPermission",
|
||||
{
|
||||
boardId: text("board_id")
|
||||
.notNull()
|
||||
.references(() => boards.id, { onDelete: "cascade" }),
|
||||
groupId: text("group_id")
|
||||
.notNull()
|
||||
.references(() => groups.id, { onDelete: "cascade" }),
|
||||
permission: text("permission").$type<BoardPermission>().notNull(),
|
||||
},
|
||||
(table) => ({
|
||||
compoundKey: primaryKey({
|
||||
columns: [table.boardId, table.groupId, table.permission],
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
export const sections = mysqlTable("section", {
|
||||
id: varchar("id", { length: 256 }).notNull().primaryKey(),
|
||||
boardId: varchar("board_id", { length: 256 })
|
||||
@@ -277,7 +295,7 @@ export const accountRelations = relations(accounts, ({ one }) => ({
|
||||
export const userRelations = relations(users, ({ many }) => ({
|
||||
accounts: many(accounts),
|
||||
boards: many(boards),
|
||||
boardPermissions: many(boardPermissions),
|
||||
boardPermissions: many(boardUserPermissions),
|
||||
groups: many(groupMembers),
|
||||
ownedGroups: many(groups),
|
||||
invites: many(invites),
|
||||
@@ -310,6 +328,7 @@ export const groupMemberRelations = relations(groupMembers, ({ one }) => ({
|
||||
|
||||
export const groupRelations = relations(groups, ({ one, many }) => ({
|
||||
permissions: many(groupPermissions),
|
||||
boardPermissions: many(boardGroupPermissions),
|
||||
members: many(groupMembers),
|
||||
owner: one(users, {
|
||||
fields: [groups.ownerId],
|
||||
@@ -327,15 +346,29 @@ export const groupPermissionRelations = relations(
|
||||
}),
|
||||
);
|
||||
|
||||
export const boardPermissionRelations = relations(
|
||||
boardPermissions,
|
||||
export const boardUserPermissionRelations = relations(
|
||||
boardUserPermissions,
|
||||
({ one }) => ({
|
||||
user: one(users, {
|
||||
fields: [boardPermissions.userId],
|
||||
fields: [boardUserPermissions.userId],
|
||||
references: [users.id],
|
||||
}),
|
||||
board: one(boards, {
|
||||
fields: [boardPermissions.boardId],
|
||||
fields: [boardUserPermissions.boardId],
|
||||
references: [boards.id],
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
export const boardGroupPermissionRelations = relations(
|
||||
boardGroupPermissions,
|
||||
({ one }) => ({
|
||||
group: one(groups, {
|
||||
fields: [boardGroupPermissions.groupId],
|
||||
references: [groups.id],
|
||||
}),
|
||||
board: one(boards, {
|
||||
fields: [boardGroupPermissions.boardId],
|
||||
references: [boards.id],
|
||||
}),
|
||||
}),
|
||||
@@ -362,7 +395,8 @@ export const boardRelations = relations(boards, ({ many, one }) => ({
|
||||
fields: [boards.creatorId],
|
||||
references: [users.id],
|
||||
}),
|
||||
permissions: many(boardPermissions),
|
||||
userPermissions: many(boardUserPermissions),
|
||||
groupPermissions: many(boardGroupPermissions),
|
||||
}));
|
||||
|
||||
export const sectionRelations = relations(sections, ({ many, one }) => ({
|
||||
|
||||
@@ -198,8 +198,8 @@ export const boards = sqliteTable("board", {
|
||||
columnCount: int("column_count").default(10).notNull(),
|
||||
});
|
||||
|
||||
export const boardPermissions = sqliteTable(
|
||||
"boardPermission",
|
||||
export const boardUserPermissions = sqliteTable(
|
||||
"boardUserPermission",
|
||||
{
|
||||
boardId: text("board_id")
|
||||
.notNull()
|
||||
@@ -216,6 +216,24 @@ export const boardPermissions = sqliteTable(
|
||||
}),
|
||||
);
|
||||
|
||||
export const boardGroupPermissions = sqliteTable(
|
||||
"boardGroupPermission",
|
||||
{
|
||||
boardId: text("board_id")
|
||||
.notNull()
|
||||
.references(() => boards.id, { onDelete: "cascade" }),
|
||||
groupId: text("group_id")
|
||||
.notNull()
|
||||
.references(() => groups.id, { onDelete: "cascade" }),
|
||||
permission: text("permission").$type<BoardPermission>().notNull(),
|
||||
},
|
||||
(table) => ({
|
||||
compoundKey: primaryKey({
|
||||
columns: [table.boardId, table.groupId, table.permission],
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
export const sections = sqliteTable("section", {
|
||||
id: text("id").notNull().primaryKey(),
|
||||
boardId: text("board_id")
|
||||
@@ -274,7 +292,7 @@ export const accountRelations = relations(accounts, ({ one }) => ({
|
||||
export const userRelations = relations(users, ({ many }) => ({
|
||||
accounts: many(accounts),
|
||||
boards: many(boards),
|
||||
boardPermissions: many(boardPermissions),
|
||||
boardPermissions: many(boardUserPermissions),
|
||||
groups: many(groupMembers),
|
||||
ownedGroups: many(groups),
|
||||
invites: many(invites),
|
||||
@@ -307,6 +325,7 @@ export const groupMemberRelations = relations(groupMembers, ({ one }) => ({
|
||||
|
||||
export const groupRelations = relations(groups, ({ one, many }) => ({
|
||||
permissions: many(groupPermissions),
|
||||
boardPermissions: many(boardGroupPermissions),
|
||||
members: many(groupMembers),
|
||||
owner: one(users, {
|
||||
fields: [groups.ownerId],
|
||||
@@ -324,15 +343,29 @@ export const groupPermissionRelations = relations(
|
||||
}),
|
||||
);
|
||||
|
||||
export const boardPermissionRelations = relations(
|
||||
boardPermissions,
|
||||
export const boardUserPermissionRelations = relations(
|
||||
boardUserPermissions,
|
||||
({ one }) => ({
|
||||
user: one(users, {
|
||||
fields: [boardPermissions.userId],
|
||||
fields: [boardUserPermissions.userId],
|
||||
references: [users.id],
|
||||
}),
|
||||
board: one(boards, {
|
||||
fields: [boardPermissions.boardId],
|
||||
fields: [boardUserPermissions.boardId],
|
||||
references: [boards.id],
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
export const boardGroupPermissionRelations = relations(
|
||||
boardGroupPermissions,
|
||||
({ one }) => ({
|
||||
group: one(groups, {
|
||||
fields: [boardGroupPermissions.groupId],
|
||||
references: [groups.id],
|
||||
}),
|
||||
board: one(boards, {
|
||||
fields: [boardGroupPermissions.boardId],
|
||||
references: [boards.id],
|
||||
}),
|
||||
}),
|
||||
@@ -359,7 +392,8 @@ export const boardRelations = relations(boards, ({ many, one }) => ({
|
||||
fields: [boards.creatorId],
|
||||
references: [users.id],
|
||||
}),
|
||||
permissions: many(boardPermissions),
|
||||
userPermissions: many(boardUserPermissions),
|
||||
groupPermissions: many(boardGroupPermissions),
|
||||
}));
|
||||
|
||||
export const sectionRelations = relations(sections, ({ many, one }) => ({
|
||||
|
||||
Reference in New Issue
Block a user