diff --git a/src/client/api/model/website.ts b/src/client/api/model/website.ts index 9b22395..94a797c 100644 --- a/src/client/api/model/website.ts +++ b/src/client/api/model/website.ts @@ -53,6 +53,15 @@ export async function updateWorkspaceWebsiteInfo( queryClient.resetQueries(['websites', workspaceId]); } +export async function deleteWorkspaceWebsite( + workspaceId: string, + websiteId: string +) { + await request.delete(`/api/workspace/${workspaceId}/website/${websiteId}`); + + queryClient.resetQueries(['websites', workspaceId]); +} + export function useWorspaceWebsites(workspaceId: string) { const { data: websites = [], isLoading } = useQuery( ['websites', workspaceId], diff --git a/src/client/api/request.ts b/src/client/api/request.ts index 38e58bf..9d809f8 100644 --- a/src/client/api/request.ts +++ b/src/client/api/request.ts @@ -9,10 +9,7 @@ function createRequest() { const ins = axios.create(); ins.interceptors.request.use(async (val) => { - if ( - ['post', 'get'].includes(String(val.method).toLowerCase()) && - !val.headers.Authorization - ) { + if (!val.headers.Authorization) { val.headers.Authorization = `Bearer ${getJWT()}`; } diff --git a/src/client/components/WebsiteInfo.tsx b/src/client/components/WebsiteInfo.tsx index 465b927..25a2a88 100644 --- a/src/client/components/WebsiteInfo.tsx +++ b/src/client/components/WebsiteInfo.tsx @@ -1,7 +1,8 @@ -import { Button, Form, Input, message } from 'antd'; +import { Button, Form, Input, message, Popconfirm, Tabs } from 'antd'; import React from 'react'; -import { useParams } from 'react-router'; +import { useNavigate, useParams } from 'react-router'; import { + deleteWorkspaceWebsite, updateWorkspaceWebsiteInfo, useWorkspaceWebsiteInfo, } from '../api/model/website'; @@ -20,6 +21,7 @@ export const WebsiteInfo: React.FC = React.memo(() => { currentWorkspaceId!, websiteId! ); + const navigate = useNavigate(); const [, handleSave] = useRequest( async (values: { name: string; domain: string }) => { @@ -32,6 +34,14 @@ export const WebsiteInfo: React.FC = React.memo(() => { } ); + const [, handleDeleteWebsite] = useRequest(async () => { + await deleteWorkspaceWebsite(currentWorkspaceId!, websiteId!); + + message.success('Delete Success'); + + navigate('/settings/websites'); + }); + if (!currentWorkspaceId) { return ; } @@ -55,31 +65,50 @@ export const WebsiteInfo: React.FC = React.memo(() => {
-
- - - - - - - - - + + + + + + + + + + + + - - - - + + + + + + + + handleDeleteWebsite()} + > + + + +
); diff --git a/src/client/pages/Settings.tsx b/src/client/pages/Settings.tsx index 3f955df..abc9b4a 100644 --- a/src/client/pages/Settings.tsx +++ b/src/client/pages/Settings.tsx @@ -34,7 +34,6 @@ export const Settings: React.FC = React.memo(() => { mode="vertical" items={items} /> - {pathname}
diff --git a/src/server/middleware/workspace.ts b/src/server/middleware/workspace.ts index 79bc259..0375e78 100644 --- a/src/server/middleware/workspace.ts +++ b/src/server/middleware/workspace.ts @@ -1,7 +1,7 @@ import { Handler } from 'express'; -import { checkIsWorkspaceUser } from '../model/workspace'; +import { getWorkspaceUser } from '../model/workspace'; -export function workspacePermission(): Handler { +export function workspacePermission(roles: string[] = []): Handler { return async (req, res, next) => { const workspaceId = req.body.workspaceId ?? req.query.workspaceId ?? req.params.workspaceId; @@ -16,12 +16,20 @@ export function workspacePermission(): Handler { throw new Error('This middleware should be use after auth()'); } - const isWorkspaceUser = await checkIsWorkspaceUser(workspaceId, userId); + const info = await getWorkspaceUser(workspaceId, userId); - if (!isWorkspaceUser) { + if (!info) { throw new Error('Is not workspace user'); } + if (Array.isArray(roles) && roles.length > 0) { + if (!roles.includes(info.role)) { + throw new Error( + `Workspace roles not has this permission, need ${roles}` + ); + } + } + next(); }; } diff --git a/src/server/model/workspace.ts b/src/server/model/workspace.ts index 509d3e4..8b3e4a6 100644 --- a/src/server/model/workspace.ts +++ b/src/server/model/workspace.ts @@ -1,21 +1,23 @@ import { prisma } from './_client'; +export async function getWorkspaceUser(workspaceId: string, userId: string) { + const info = await prisma.workspacesOnUsers.findFirst({ + where: { + workspaceId, + userId, + }, + }); + + return info; +} + export async function checkIsWorkspaceUser( workspaceId: string, userId: string ) { - const workspace = await prisma.workspace.findUnique({ - where: { - id: workspaceId, - users: { - some: { - userId, - }, - }, - }, - }); + const info = await getWorkspaceUser(workspaceId, userId); - if (workspace) { + if (info) { return true; } else { return false; @@ -84,3 +86,17 @@ export async function addWorkspaceWebsite( return website; } + +export async function deleteWorkspaceWebsite( + workspaceId: string, + websiteId: string +) { + const website = await prisma.website.delete({ + where: { + id: websiteId, + workspaceId, + }, + }); + + return website; +} diff --git a/src/server/router/workspace.ts b/src/server/router/workspace.ts index c462b58..6374eb2 100644 --- a/src/server/router/workspace.ts +++ b/src/server/router/workspace.ts @@ -4,10 +4,12 @@ import { body, param, query, validate } from '../middleware/validate'; import { workspacePermission } from '../middleware/workspace'; import { addWorkspaceWebsite, + deleteWorkspaceWebsite, getWorkspaceWebsiteInfo, getWorkspaceWebsites, updateWorkspaceWebsiteInfo, } from '../model/workspace'; +import { ROLES } from '../utils/const'; export const workspaceRouter = Router(); @@ -128,3 +130,29 @@ workspaceRouter.post( res.json({ website }); } ); + +workspaceRouter.delete( + '/:workspaceId/website/:websiteId', + validate( + param('workspaceId') + .isString() + .withMessage('workspaceId should be string') + .isUUID() + .withMessage('workspaceId should be UUID'), + param('websiteId') + .isString() + .withMessage('workspaceId should be string') + .isUUID() + .withMessage('workspaceId should be UUID') + ), + auth(), + workspacePermission([ROLES.owner]), + async (req, res) => { + const workspaceId = req.params.workspaceId; + const websiteId = req.params.websiteId; + + const website = await deleteWorkspaceWebsite(workspaceId, websiteId); + + res.json({ website }); + } +);