diff --git a/src/app/(main)/reports/ReportsHeader.tsx b/src/app/(main)/reports/ReportsHeader.tsx index 068c0369..92f538ea 100644 --- a/src/app/(main)/reports/ReportsHeader.tsx +++ b/src/app/(main)/reports/ReportsHeader.tsx @@ -1,20 +1,25 @@ import PageHeader from 'components/layout/PageHeader'; import { Icon, Icons, Text } from 'react-basics'; -import { useMessages, useTeamUrl } from 'components/hooks'; +import { useLogin, useMessages, useTeamUrl } from 'components/hooks'; import LinkButton from 'components/common/LinkButton'; +import { ROLES } from 'lib/constants'; export function ReportsHeader() { const { formatMessage, labels } = useMessages(); const { renderTeamUrl } = useTeamUrl(); + const { user } = useLogin(); + const canEdit = user.role !== ROLES.viewOnly; return ( - - - - - {formatMessage(labels.createReport)} - + {canEdit && ( + + + + + {formatMessage(labels.createReport)} + + )} ); } diff --git a/src/app/(main)/settings/teams/[teamId]/members/TeamMembersPage.tsx b/src/app/(main)/settings/teams/[teamId]/members/TeamMembersPage.tsx index a8159891..3c166826 100644 --- a/src/app/(main)/settings/teams/[teamId]/members/TeamMembersPage.tsx +++ b/src/app/(main)/settings/teams/[teamId]/members/TeamMembersPage.tsx @@ -11,9 +11,9 @@ export function TeamMembersPage({ teamId }: { teamId: string }) { const { user } = useLogin(); const { formatMessage, labels } = useMessages(); - const canEdit = team?.teamUser?.find( - ({ userId, role }) => role === ROLES.teamOwner && userId === user.id, - ); + const canEdit = + team?.teamUser?.find(({ userId, role }) => role === ROLES.teamOwner && userId === user.id) && + user.role !== ROLES.viewOnly; return ( <> diff --git a/src/app/(main)/settings/teams/[teamId]/team/TeamDetails.tsx b/src/app/(main)/settings/teams/[teamId]/team/TeamDetails.tsx index 0ce43fec..9d8ea529 100644 --- a/src/app/(main)/settings/teams/[teamId]/team/TeamDetails.tsx +++ b/src/app/(main)/settings/teams/[teamId]/team/TeamDetails.tsx @@ -15,9 +15,9 @@ export function TeamDetails({ teamId }: { teamId: string }) { const { user } = useLogin(); const [tab, setTab] = useState('details'); - const canEdit = !!team?.teamUser?.find( - ({ userId, role }) => role === ROLES.teamOwner && userId === user.id, - ); + const canEdit = + !!team?.teamUser?.find(({ userId, role }) => role === ROLES.teamOwner && userId === user.id) && + user.role !== ROLES.viewOnly; return ( diff --git a/src/app/(main)/settings/teams/[teamId]/websites/TeamWebsitesPage.tsx b/src/app/(main)/settings/teams/[teamId]/websites/TeamWebsitesPage.tsx index c5092c8b..882ef8ec 100644 --- a/src/app/(main)/settings/teams/[teamId]/websites/TeamWebsitesPage.tsx +++ b/src/app/(main)/settings/teams/[teamId]/websites/TeamWebsitesPage.tsx @@ -12,16 +12,17 @@ export function TeamWebsitesPage({ teamId }: { teamId: string }) { const { formatMessage, labels } = useMessages(); const { user } = useLogin(); - const allowEdit = !!team?.teamUser?.find( - ({ userId, role }) => userId === user.id && role !== ROLES.teamViewOnly, - ); + const canEdit = + !!team?.teamUser?.find( + ({ userId, role }) => userId === user.id && role !== ROLES.teamViewOnly, + ) && user.role !== ROLES.viewOnly; return ( <> - {allowEdit && } + {canEdit && } - + ); } diff --git a/src/app/(main)/settings/teams/[teamId]/websites/TeamWebsitesTable.tsx b/src/app/(main)/settings/teams/[teamId]/websites/TeamWebsitesTable.tsx index 086cc03a..dc6760a6 100644 --- a/src/app/(main)/settings/teams/[teamId]/websites/TeamWebsitesTable.tsx +++ b/src/app/(main)/settings/teams/[teamId]/websites/TeamWebsitesTable.tsx @@ -13,12 +13,15 @@ export function TeamWebsitesTable({ allowEdit?: boolean; }) { const { user } = useLogin(); - const { formatMessage, labels } = useMessages(); + return ( + + {row => row?.createUser?.username} + {row => { const { id: websiteId } = row; diff --git a/src/app/(main)/settings/websites/WebsitesSettingsPage.tsx b/src/app/(main)/settings/websites/WebsitesSettingsPage.tsx index 14411da1..ff0938d1 100644 --- a/src/app/(main)/settings/websites/WebsitesSettingsPage.tsx +++ b/src/app/(main)/settings/websites/WebsitesSettingsPage.tsx @@ -1,11 +1,16 @@ 'use client'; +import { useLogin } from 'components/hooks'; import WebsitesDataTable from './WebsitesDataTable'; import WebsitesHeader from './WebsitesHeader'; +import { ROLES } from 'lib/constants'; export default function WebsitesSettingsPage({ teamId }: { teamId: string }) { + const { user } = useLogin(); + const canCreate = user.role !== ROLES.viewOnly; + return ( <> - + ); diff --git a/src/app/(main)/websites/WebsitesPage.tsx b/src/app/(main)/websites/WebsitesPage.tsx index 75776c4c..8d8ee2e2 100644 --- a/src/app/(main)/websites/WebsitesPage.tsx +++ b/src/app/(main)/websites/WebsitesPage.tsx @@ -1,14 +1,11 @@ 'use client'; import WebsitesHeader from 'app/(main)/settings/websites/WebsitesHeader'; import WebsitesDataTable from 'app/(main)/settings/websites/WebsitesDataTable'; -import { useLogin } from 'components/hooks'; - -export default function WebsitesPage({ teamId }: { teamId: string; userId: string }) { - const { user } = useLogin(); +export default function WebsitesPage({ teamId }: { teamId: string }) { return ( <> - + ); diff --git a/src/components/messages.ts b/src/components/messages.ts index 2710e99d..0487004a 100644 --- a/src/components/messages.ts +++ b/src/components/messages.ts @@ -26,6 +26,7 @@ export const labels = defineMessages({ myWebsites: { id: 'label.my-websites', defaultMessage: 'My websites' }, teamWebsites: { id: 'label.team-websites', defaultMessage: 'Team websites' }, created: { id: 'label.created', defaultMessage: 'Created' }, + createdBy: { id: 'label.created-by', defaultMessage: 'Created By' }, edit: { id: 'label.edit', defaultMessage: 'Edit' }, name: { id: 'label.name', defaultMessage: 'Name' }, member: { id: 'label.member', defaultMessage: 'Member' }, diff --git a/src/lib/data.ts b/src/lib/data.ts index 47023bb4..5b502c5d 100644 --- a/src/lib/data.ts +++ b/src/lib/data.ts @@ -1,4 +1,4 @@ -import { isValid, parseISO } from 'date-fns'; +import { isValid } from 'date-fns'; import { DATA_TYPE } from './constants'; import { DynamicDataType } from './types'; @@ -28,7 +28,7 @@ export function flattenJSON( export function getDataType(value: any): string { let type: string = typeof value; - if ((type === 'string' && isValid(value)) || isValid(parseISO(value))) { + if ((type === 'string' && isValid(value)) || isValid(new Date(value))) { type = 'date'; } diff --git a/src/pages/api/reports/index.ts b/src/pages/api/reports/index.ts index b5478018..701ef649 100644 --- a/src/pages/api/reports/index.ts +++ b/src/pages/api/reports/index.ts @@ -6,7 +6,7 @@ import { NextApiResponse } from 'next'; import { methodNotAllowed, ok, unauthorized } from 'next-basics'; import { createReport, getReports } from 'queries'; import * as yup from 'yup'; -import { canViewTeam, canViewWebsite } from 'lib/auth'; +import { canUpdateWebsite, canViewTeam, canViewWebsite } from 'lib/auth'; export interface ReportRequestBody { websiteId: string; @@ -89,6 +89,10 @@ export default async ( if (req.method === 'POST') { const { websiteId, type, name, description, parameters } = req.body; + if (!(await canUpdateWebsite(req.auth, websiteId))) { + return unauthorized(res); + } + const result = await createReport({ id: uuid(), userId, diff --git a/src/pages/api/websites/index.ts b/src/pages/api/websites/index.ts index eb574415..0b7826ac 100644 --- a/src/pages/api/websites/index.ts +++ b/src/pages/api/websites/index.ts @@ -62,6 +62,7 @@ export default async ( const data: any = { id: uuid(), + createdBy: userId, name, domain, shareId, diff --git a/src/queries/admin/website.ts b/src/queries/admin/website.ts index 01d52019..cef7f15d 100644 --- a/src/queries/admin/website.ts +++ b/src/queries/admin/website.ts @@ -87,7 +87,7 @@ export async function getTeamWebsites( teamId, }, include: { - user: { + createUser: { select: { id: true, username: true,