diff --git a/src/client/pages/Status.tsx b/src/client/pages/Status.tsx
index 58ba197..3034f34 100644
--- a/src/client/pages/Status.tsx
+++ b/src/client/pages/Status.tsx
@@ -1,24 +1,28 @@
import React from 'react';
import { useParams } from 'react-router';
import { trpc } from '../api/trpc';
-import { Empty } from 'antd';
+import { Button, Empty } from 'antd';
import { MonitorHealthBar } from '../components/monitor/MonitorHealthBar';
-import { useUserStore } from '../store/user';
+import { useUserInfo } from '../store/user';
+import { ROLES } from '../../shared';
export const StatusPage: React.FC = React.memo(() => {
const { slug } = useParams<{ slug: string }>();
- useUserStore();
const { data: info } = trpc.monitor.getPageInfo.useQuery({
slug: slug!,
});
+ const allowEdit = useAllowEdit(info?.workspaceId);
+
const monitorList = info?.monitorList ?? [];
return (
{info?.title}
+
{allowEdit && }
+
Services
{info && (
@@ -44,3 +48,19 @@ export const StatusPage: React.FC = React.memo(() => {
);
});
StatusPage.displayName = 'StatusPage';
+
+function useAllowEdit(workspaceId?: string): boolean {
+ const userInfo = useUserInfo();
+
+ const { data: role } = trpc.workspace.getUserWorkspaceRole.useQuery(
+ {
+ workspaceId: workspaceId!,
+ userId: userInfo?.id!,
+ },
+ {
+ enabled: !!userInfo?.id && !!workspaceId,
+ }
+ );
+
+ return role === ROLES.owner;
+}
diff --git a/src/server/middleware/workspace.ts b/src/server/middleware/workspace.ts
index aee1a8f..547ea85 100644
--- a/src/server/middleware/workspace.ts
+++ b/src/server/middleware/workspace.ts
@@ -1,6 +1,6 @@
import { Handler } from 'express';
import { getWorkspaceUser } from '../model/workspace';
-import { ROLES } from '../utils/const';
+import { ROLES } from '../../shared';
export function workspacePermission(roles: ROLES[] = []): Handler {
return async (req, res, next) => {
diff --git a/src/server/model/user.ts b/src/server/model/user.ts
index eef7cad..9b96c18 100644
--- a/src/server/model/user.ts
+++ b/src/server/model/user.ts
@@ -1,6 +1,6 @@
import { prisma } from './_client';
import bcryptjs from 'bcryptjs';
-import { ROLES, SYSTEM_ROLES } from '../utils/const';
+import { ROLES, SYSTEM_ROLES } from '../../shared';
import { jwtVerify } from '../middleware/auth';
import { TRPCError } from '@trpc/server';
import { Prisma } from '@prisma/client';
diff --git a/src/server/router/website.ts b/src/server/router/website.ts
index bf2e56b..a8921e1 100644
--- a/src/server/router/website.ts
+++ b/src/server/router/website.ts
@@ -1,13 +1,14 @@
import { Router } from 'express';
import { body, validate } from '../middleware/validate';
import * as yup from 'yup';
-import { COLLECTION_TYPE, HOSTNAME_REGEX } from '../utils/const';
+import { COLLECTION_TYPE } from '../utils/const';
import {
findSession,
saveWebsiteEvent,
saveWebsiteSessionData,
} from '../model/website';
import { createToken } from '../utils/common';
+import { hostnameRegex } from '../../shared';
export const websiteRouter = Router();
@@ -23,7 +24,7 @@ websiteRouter.post(
.object()
.shape({
data: yup.object(),
- hostname: yup.string().matches(HOSTNAME_REGEX).max(100),
+ hostname: yup.string().matches(hostnameRegex).max(100),
language: yup.string().max(35),
referrer: yup.string().max(500),
screen: yup.string().max(11),
diff --git a/src/server/router/workspace.ts b/src/server/router/workspace.ts
index 6594a6a..10373c9 100644
--- a/src/server/router/workspace.ts
+++ b/src/server/router/workspace.ts
@@ -12,8 +12,8 @@ import {
getWorkspaceWebsiteStats,
} from '../model/workspace';
import { parseDateRange } from '../utils/common';
-import { ROLES } from '../utils/const';
import { QueryFilters } from '../utils/prisma';
+import { ROLES } from '../../shared';
export const workspaceRouter = Router();
diff --git a/src/server/trpc/routers/workspace.ts b/src/server/trpc/routers/workspace.ts
index 74cd96f..1c11b20 100644
--- a/src/server/trpc/routers/workspace.ts
+++ b/src/server/trpc/routers/workspace.ts
@@ -1,10 +1,32 @@
-import { router, workspaceOwnerProcedure } from '../trpc';
+import { publicProcedure, router, workspaceOwnerProcedure } from '../trpc';
import { z } from 'zod';
import { prisma } from '../../model/_client';
import { workspaceDashboardLayoutSchema } from '../../model/_schema';
import { Prisma } from '@prisma/client';
export const workspaceRouter = router({
+ getUserWorkspaceRole: publicProcedure
+ .input(
+ z.object({
+ userId: z.string(),
+ workspaceId: z.string(),
+ })
+ )
+ .output(z.string().nullable())
+ .query(async ({ input }) => {
+ const { userId, workspaceId } = input;
+
+ const relation = await prisma.workspacesOnUsers.findUnique({
+ where: {
+ userId_workspaceId: {
+ workspaceId,
+ userId,
+ },
+ },
+ });
+
+ return relation?.role ?? null;
+ }),
updateDashboardOrder: workspaceOwnerProcedure
.input(
z.object({
diff --git a/src/server/trpc/trpc.ts b/src/server/trpc/trpc.ts
index 0509f75..f009d60 100644
--- a/src/server/trpc/trpc.ts
+++ b/src/server/trpc/trpc.ts
@@ -3,7 +3,7 @@ import _ from 'lodash';
import { z } from 'zod';
import { jwtVerify } from '../middleware/auth';
import { getWorkspaceUser } from '../model/workspace';
-import { ROLES, SYSTEM_ROLES } from '../utils/const';
+import { ROLES, SYSTEM_ROLES } from '../../shared';
import type { IncomingMessage } from 'http';
import { OpenApiMeta } from 'trpc-openapi';
diff --git a/src/server/utils/const.ts b/src/server/utils/const.ts
index 74fa3b3..75ade12 100644
--- a/src/server/utils/const.ts
+++ b/src/server/utils/const.ts
@@ -1,16 +1,3 @@
-export enum SYSTEM_ROLES {
- admin = 'admin',
- user = 'user',
-}
-
-export enum ROLES {
- owner = 'owner',
- readOnly = 'readOnly',
-}
-
-export const HOSTNAME_REGEX =
- /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9])$/;
-
export const COLLECTION_TYPE = {
event: 'event',
identify: 'identify',
diff --git a/src/server/utils/screenshot/website.ts b/src/server/utils/screenshot/website.ts
index a006e94..907a8a4 100644
--- a/src/server/utils/screenshot/website.ts
+++ b/src/server/utils/screenshot/website.ts
@@ -1,6 +1,6 @@
import puppeteer from 'puppeteer';
import { jwtSign } from '../../middleware/auth';
-import { SYSTEM_ROLES } from '../const';
+import { SYSTEM_ROLES } from '../../../shared';
import { settings } from '../settings';
/**
diff --git a/src/shared/index.ts b/src/shared/index.ts
index 842b65e..cd36ae7 100644
--- a/src/shared/index.ts
+++ b/src/shared/index.ts
@@ -1,3 +1,4 @@
export * from './date';
export * from './server';
export * from './regex';
+export * from './role';
diff --git a/src/shared/regex.ts b/src/shared/regex.ts
index 044ffa9..1f60db9 100644
--- a/src/shared/regex.ts
+++ b/src/shared/regex.ts
@@ -1,4 +1,4 @@
export const hostnameRegex =
- /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]).)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9])$/;
+ /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9])$/;
export const slugRegex = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
diff --git a/src/shared/role.ts b/src/shared/role.ts
new file mode 100644
index 0000000..2939236
--- /dev/null
+++ b/src/shared/role.ts
@@ -0,0 +1,9 @@
+export enum SYSTEM_ROLES {
+ admin = 'admin',
+ user = 'user',
+}
+
+export enum ROLES {
+ owner = 'owner',
+ readOnly = 'readOnly',
+}