mirror of
https://github.com/umami-software/umami.git
synced 2026-02-06 05:37:20 +01:00
Teams refactor: removed team websites.
This commit is contained in:
parent
0d442b751d
commit
f85393f8df
23 changed files with 190 additions and 351 deletions
|
|
@ -17,6 +17,12 @@ export function TeamsTable({ data = [] }: { data: any[] }) {
|
|||
<GridColumn name="owner" label={formatMessage(labels.owner)}>
|
||||
{row => row.teamUser.find(({ role }) => role === ROLES.teamOwner)?.user?.username}
|
||||
</GridColumn>
|
||||
<GridColumn name="websites" label={formatMessage(labels.websites)}>
|
||||
{row => row._count.website}
|
||||
</GridColumn>
|
||||
<GridColumn name="members" label={formatMessage(labels.members)}>
|
||||
{row => row._count.teamUser}
|
||||
</GridColumn>
|
||||
<GridColumn name="action" label=" " alignment="end">
|
||||
{row => {
|
||||
const { id, name, teamUser } = row;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import useApi from 'components/hooks/useApi';
|
||||
import TeamMembersTable from './TeamMembersTable';
|
||||
import useFilterQuery from 'components/hooks/useFilterQuery';
|
||||
import DataTable from 'components/common/DataTable';
|
||||
import useCache from 'store/cache';
|
||||
import TeamMembersTable from './TeamMembersTable';
|
||||
|
||||
export function TeamMembers({ teamId, readOnly }: { teamId: string; readOnly: boolean }) {
|
||||
const { get } = useApi();
|
||||
|
|
@ -18,11 +18,9 @@ export function TeamMembers({ teamId, readOnly }: { teamId: string; readOnly: bo
|
|||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<DataTable queryResult={queryResult}>
|
||||
{({ data }) => <TeamMembersTable data={data} teamId={teamId} readOnly={readOnly} />}
|
||||
</DataTable>
|
||||
</>
|
||||
<DataTable queryResult={queryResult}>
|
||||
{({ data }) => <TeamMembersTable data={data} teamId={teamId} readOnly={readOnly} />}
|
||||
</DataTable>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ export function TeamSettings({ teamId }: { teamId: string }) {
|
|||
return get(`/teams/${teamId}`);
|
||||
}
|
||||
},
|
||||
gcTime: 0,
|
||||
});
|
||||
const canEdit = data?.teamUser?.find(
|
||||
({ userId, role }) => role === ROLES.teamOwner && userId === user.id,
|
||||
|
|
|
|||
|
|
@ -1,79 +0,0 @@
|
|||
import useApi from 'components/hooks/useApi';
|
||||
import { useState } from 'react';
|
||||
import { Button, Form, FormButtons, GridColumn, Loading, SubmitButton, Toggle } from 'react-basics';
|
||||
import useMessages from 'components/hooks/useMessages';
|
||||
import WebsitesDataTable from 'app/(main)/settings/websites/WebsitesDataTable';
|
||||
import Empty from 'components/common/Empty';
|
||||
import { setValue } from 'store/cache';
|
||||
import { useUser } from 'components/hooks';
|
||||
|
||||
export function TeamWebsiteAddForm({
|
||||
teamId,
|
||||
onSave,
|
||||
onClose,
|
||||
}: {
|
||||
teamId: string;
|
||||
onSave: () => void;
|
||||
onClose: () => void;
|
||||
}) {
|
||||
const { user } = useUser();
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { get, post, useQuery, useMutation } = useApi();
|
||||
const { mutate, error } = useMutation({
|
||||
mutationFn: (data: any) => post(`/teams/${teamId}/websites`, data),
|
||||
});
|
||||
const { data: websites, isLoading } = useQuery({
|
||||
queryKey: ['websites'],
|
||||
queryFn: () => get('/websites'),
|
||||
});
|
||||
const [selected, setSelected] = useState([]);
|
||||
const hasData = websites && websites.data.length > 0;
|
||||
|
||||
const handleSubmit = () => {
|
||||
mutate(
|
||||
{ websiteIds: selected },
|
||||
{
|
||||
onSuccess: async () => {
|
||||
setValue('team:websites', Date.now());
|
||||
onSave?.();
|
||||
onClose?.();
|
||||
},
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
const handleSelect = id => {
|
||||
setSelected(state => (state.includes(id) ? state.filter(n => n !== id) : state.concat(id)));
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{isLoading && !hasData && <Loading icon="dots" position="center" />}
|
||||
{!isLoading && !hasData && <Empty />}
|
||||
{hasData && (
|
||||
<Form onSubmit={handleSubmit} error={error}>
|
||||
<WebsitesDataTable userId={user.id} showActions={false}>
|
||||
<GridColumn name="select" label={formatMessage(labels.selectWebsite)} alignment="end">
|
||||
{row => (
|
||||
<Toggle
|
||||
key={row.id}
|
||||
value={row.id}
|
||||
checked={selected?.includes(row.id)}
|
||||
onChange={handleSelect.bind(null, row.id)}
|
||||
/>
|
||||
)}
|
||||
</GridColumn>
|
||||
</WebsitesDataTable>
|
||||
<FormButtons flex>
|
||||
<SubmitButton variant="primary" disabled={selected?.length === 0}>
|
||||
{formatMessage(labels.addWebsite)}
|
||||
</SubmitButton>
|
||||
<Button onClick={onClose}>{formatMessage(labels.cancel)}</Button>
|
||||
</FormButtons>
|
||||
</Form>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default TeamWebsiteAddForm;
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
import useFilterQuery from 'components/hooks/useFilterQuery';
|
||||
import WebsitesTable from 'app/(main)/settings/websites/WebsitesTable';
|
||||
import DataTable from 'components/common/DataTable';
|
||||
import useFilterQuery from 'components/hooks/useFilterQuery';
|
||||
import useApi from 'components/hooks/useApi';
|
||||
import useUser from 'components/hooks/useUser';
|
||||
import useCache from 'store/cache';
|
||||
import WebsitesTable from '../../websites/WebsitesTable';
|
||||
|
||||
export function TeamWebsites({ teamId }: { teamId: string; readOnly: boolean }) {
|
||||
const { user } = useUser();
|
||||
const { get } = useApi();
|
||||
const { user } = useUser();
|
||||
const modified = useCache(state => state?.['team:websites']);
|
||||
const queryResult = useFilterQuery({
|
||||
queryKey: ['team:websites', { teamId, modified }],
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Metadata } from 'next';
|
||||
import TeamsDataTable from './TeamsDataTable';
|
||||
import TeamsHeader from './TeamsHeader';
|
||||
import { Metadata } from 'next';
|
||||
|
||||
export default function () {
|
||||
if (process.env.cloudMode) {
|
||||
|
|
@ -16,5 +16,5 @@ export default function () {
|
|||
}
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Teams Settings | umami',
|
||||
title: 'Teams Settings - Umami',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,10 +3,9 @@ import useApi from 'components/hooks/useApi';
|
|||
import useFilterQuery from 'components/hooks/useFilterQuery';
|
||||
import DataTable from 'components/common/DataTable';
|
||||
import UsersTable from './UsersTable';
|
||||
import UsersHeader from './UsersHeader';
|
||||
import useCache from 'store/cache';
|
||||
|
||||
export function UsersDataTable() {
|
||||
export function UsersDataTable({ showActions }: { showActions: boolean }) {
|
||||
const { get } = useApi();
|
||||
const modified = useCache((state: any) => state?.users);
|
||||
const queryResult = useFilterQuery({
|
||||
|
|
@ -15,10 +14,9 @@ export function UsersDataTable() {
|
|||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<UsersHeader />
|
||||
<DataTable queryResult={queryResult}>{({ data }) => <UsersTable data={data} />}</DataTable>
|
||||
</>
|
||||
<DataTable queryResult={queryResult}>
|
||||
{({ data }) => <UsersTable data={data} showActions={showActions} />}
|
||||
</DataTable>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,13 @@ import useMessages from 'components/hooks/useMessages';
|
|||
import useLocale from 'components/hooks/useLocale';
|
||||
import UserDeleteButton from './UserDeleteButton';
|
||||
|
||||
export function UsersTable({ data = [] }: { data: any[] }) {
|
||||
export function UsersTable({
|
||||
data = [],
|
||||
showActions = true,
|
||||
}: {
|
||||
data: any[];
|
||||
showActions?: boolean;
|
||||
}) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const { dateLocale } = useLocale();
|
||||
const breakpoint = useBreakpoint();
|
||||
|
|
@ -29,24 +35,26 @@ export function UsersTable({ data = [] }: { data: any[] }) {
|
|||
})
|
||||
}
|
||||
</GridColumn>
|
||||
<GridColumn name="action" label=" " alignment="end">
|
||||
{row => {
|
||||
const { id, username } = row;
|
||||
return (
|
||||
<>
|
||||
<Link href={`/settings/users/${id}`}>
|
||||
<Button>
|
||||
<Icon>
|
||||
<Icons.Edit />
|
||||
</Icon>
|
||||
<Text>{formatMessage(labels.edit)}</Text>
|
||||
</Button>
|
||||
</Link>
|
||||
<UserDeleteButton userId={id} username={username} />
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</GridColumn>
|
||||
{showActions && (
|
||||
<GridColumn name="action" label=" " alignment="end">
|
||||
{row => {
|
||||
const { id, username } = row;
|
||||
return (
|
||||
<>
|
||||
<Link href={`/settings/users/${id}`}>
|
||||
<Button>
|
||||
<Icon>
|
||||
<Icons.Edit />
|
||||
</Icon>
|
||||
<Text>{formatMessage(labels.edit)}</Text>
|
||||
</Button>
|
||||
</Link>
|
||||
<UserDeleteButton userId={id} username={username} />
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</GridColumn>
|
||||
)}
|
||||
</GridTable>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
import UsersDataTable from './UsersDataTable';
|
||||
import { Metadata } from 'next';
|
||||
import UsersDataTable from './UsersDataTable';
|
||||
import UsersHeader from './UsersHeader';
|
||||
|
||||
export default function () {
|
||||
return <UsersDataTable />;
|
||||
return (
|
||||
<>
|
||||
<UsersHeader />
|
||||
<UsersDataTable />
|
||||
</>
|
||||
);
|
||||
}
|
||||
export const metadata: Metadata = {
|
||||
title: 'Users | umami',
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ export const labels = defineMessages({
|
|||
deleteWebsite: { id: 'label.delete-website', defaultMessage: 'Delete website' },
|
||||
reset: { id: 'label.reset', defaultMessage: 'Reset' },
|
||||
addWebsite: { id: 'label.add-website', defaultMessage: 'Add website' },
|
||||
addMember: { id: 'label.add-member', defaultMessage: 'Add member' },
|
||||
addDescription: { id: 'label.add-description', defaultMessage: 'Add description' },
|
||||
changePassword: { id: 'label.change-password', defaultMessage: 'Change password' },
|
||||
currentPassword: { id: 'label.current-password', defaultMessage: 'Current password' },
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ export * from 'components/hooks/useTimezone';
|
|||
export * from 'components/hooks/useUser';
|
||||
export * from 'components/hooks/useWebsite';
|
||||
|
||||
export * from 'app/(main)/settings/teams/[id]/TeamWebsiteAddForm';
|
||||
export * from 'app/(main)/settings/teams/[id]/TeamEditForm';
|
||||
export * from 'app/(main)/settings/teams/[id]/TeamMemberRemoveButton';
|
||||
export * from 'app/(main)/settings/teams/[id]/TeamMembers';
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { Report } from '@prisma/client';
|
||||
import debug from 'debug';
|
||||
import redis from '@umami/redis-client';
|
||||
import { PERMISSIONS, ROLE_PERMISSIONS, SHARE_TOKEN_HEADER } from 'lib/constants';
|
||||
import { PERMISSIONS, ROLE_PERMISSIONS, ROLES, SHARE_TOKEN_HEADER } from 'lib/constants';
|
||||
import { secret } from 'lib/crypto';
|
||||
import { createSecureToken, ensureArray, getRandomChars, parseToken } from 'next-basics';
|
||||
import { findTeamWebsiteByUserId, getTeamUser, getTeamWebsite } from 'queries';
|
||||
import { getTeamUser, getWebsiteById } from 'queries';
|
||||
import { loadWebsite } from './load';
|
||||
import { Auth } from './types';
|
||||
import { NextApiRequest } from 'next';
|
||||
|
|
@ -55,8 +55,6 @@ export async function canViewWebsite({ user, shareToken }: Auth, websiteId: stri
|
|||
if (user.id === website?.userId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return !!(await findTeamWebsiteByUserId(websiteId, user.id));
|
||||
}
|
||||
|
||||
export async function canViewAllWebsites({ user }: Auth) {
|
||||
|
|
@ -178,16 +176,12 @@ export async function canDeleteTeamWebsite({ user }: Auth, teamId: string, websi
|
|||
return true;
|
||||
}
|
||||
|
||||
const teamWebsite = await getTeamWebsite(teamId, websiteId);
|
||||
const teamWebsite = await getWebsiteById(websiteId);
|
||||
|
||||
if (teamWebsite?.website?.userId === user.id) {
|
||||
return true;
|
||||
}
|
||||
if (teamWebsite && teamWebsite.teamId === teamId) {
|
||||
const teamUser = await getTeamUser(teamId, user.id);
|
||||
|
||||
if (teamWebsite) {
|
||||
const teamUser = await getTeamUser(teamWebsite.teamId, user.id);
|
||||
|
||||
return hasPermission(teamUser.role, PERMISSIONS.teamUpdate);
|
||||
return teamUser.role === ROLES.teamOwner || teamUser.role === ROLES.teamMember;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -125,6 +125,7 @@ export const ROLES = {
|
|||
viewOnly: 'view-only',
|
||||
teamOwner: 'team-owner',
|
||||
teamMember: 'team-member',
|
||||
teamGuest: 'team-guest',
|
||||
} as const;
|
||||
|
||||
export const PERMISSIONS = {
|
||||
|
|
|
|||
|
|
@ -68,7 +68,12 @@ export default async (
|
|||
});
|
||||
}
|
||||
|
||||
log(`Login from ip ${getIpAddress(req)} with username "${username.replace(/["\r\n]/g, '')}" failed.`);
|
||||
log(
|
||||
`Login from ip ${getIpAddress(req)} with username "${username.replace(
|
||||
/["\r\n]/g,
|
||||
'',
|
||||
)}" failed.`,
|
||||
);
|
||||
|
||||
return unauthorized(res, 'message.incorrect-username-password');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import { pageInfo } from 'lib/schema';
|
|||
import { NextApiResponse } from 'next';
|
||||
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||
import { getWebsitesByTeamId } from 'queries';
|
||||
import { createTeamWebsites } from 'queries/admin/teamWebsite';
|
||||
|
||||
export interface TeamWebsiteRequestQuery extends SearchFilter {
|
||||
id: string;
|
||||
|
|
@ -52,17 +51,5 @@ export default async (
|
|||
return ok(res, websites);
|
||||
}
|
||||
|
||||
if (req.method === 'POST') {
|
||||
if (!(await canViewTeam(req.auth, teamId))) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
const { websiteIds } = req.body;
|
||||
|
||||
const websites = await createTeamWebsites(teamId, websiteIds);
|
||||
|
||||
return ok(res, websites);
|
||||
}
|
||||
|
||||
return methodNotAllowed(res);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@ export interface GetTeamOptions {
|
|||
|
||||
async function getTeam(where: Prisma.TeamWhereInput, options: GetTeamOptions = {}): Promise<Team> {
|
||||
const { includeTeamUser = false } = options;
|
||||
const { client } = prisma;
|
||||
|
||||
return prisma.client.team.findFirst({
|
||||
return client.team.findFirst({
|
||||
where,
|
||||
include: {
|
||||
teamUser: includeTeamUser,
|
||||
|
|
@ -27,14 +28,15 @@ export function getTeamByAccessCode(accessCode: string, options: GetTeamOptions
|
|||
return getTeam({ accessCode }, options);
|
||||
}
|
||||
|
||||
export async function createTeam(data: Prisma.TeamCreateInput, userId: string): Promise<Team> {
|
||||
export async function createTeam(data: Prisma.TeamCreateInput, userId: string): Promise<any> {
|
||||
const { id } = data;
|
||||
const { client, transaction } = prisma;
|
||||
|
||||
return prisma.transaction([
|
||||
prisma.client.team.create({
|
||||
return transaction([
|
||||
client.team.create({
|
||||
data,
|
||||
}),
|
||||
prisma.client.teamUser.create({
|
||||
client.teamUser.create({
|
||||
data: {
|
||||
id: uuid(),
|
||||
teamId: id,
|
||||
|
|
@ -46,7 +48,9 @@ export async function createTeam(data: Prisma.TeamCreateInput, userId: string):
|
|||
}
|
||||
|
||||
export async function updateTeam(teamId: string, data: Prisma.TeamUpdateInput): Promise<Team> {
|
||||
return prisma.client.team.update({
|
||||
const { client } = prisma;
|
||||
|
||||
return client.team.update({
|
||||
where: {
|
||||
id: teamId,
|
||||
},
|
||||
|
|
@ -61,13 +65,22 @@ export async function deleteTeam(
|
|||
teamId: string,
|
||||
): Promise<Promise<[Prisma.BatchPayload, Prisma.BatchPayload, Team]>> {
|
||||
const { client, transaction } = prisma;
|
||||
const cloudMode = process.env.CLOUD_MODE;
|
||||
|
||||
if (cloudMode) {
|
||||
return transaction([
|
||||
client.team.update({
|
||||
data: {
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
where: {
|
||||
id: teamId,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
return transaction([
|
||||
client.teamWebsite.deleteMany({
|
||||
where: {
|
||||
teamId,
|
||||
},
|
||||
}),
|
||||
client.teamUser.deleteMany({
|
||||
where: {
|
||||
teamId,
|
||||
|
|
@ -87,6 +100,7 @@ export async function getTeams(
|
|||
): Promise<FilterResult<Team[]>> {
|
||||
const { userId, query } = filters;
|
||||
const mode = prisma.getQueryMode();
|
||||
const { client } = prisma;
|
||||
|
||||
const where: Prisma.TeamWhereInput = {
|
||||
...(userId && {
|
||||
|
|
@ -123,7 +137,7 @@ export async function getTeams(
|
|||
...filters,
|
||||
});
|
||||
|
||||
const teams = await prisma.client.team.findMany({
|
||||
const teams = await client.team.findMany({
|
||||
where: {
|
||||
...where,
|
||||
},
|
||||
|
|
@ -131,7 +145,7 @@ export async function getTeams(
|
|||
...(options?.include && { include: options?.include }),
|
||||
});
|
||||
|
||||
const count = await prisma.client.team.count({ where });
|
||||
const count = await client.team.count({ where });
|
||||
|
||||
return { data: teams, count, ...getParameters };
|
||||
}
|
||||
|
|
@ -154,6 +168,9 @@ export async function getTeamsByUserId(
|
|||
},
|
||||
},
|
||||
},
|
||||
_count: {
|
||||
select: { website: true, teamUser: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
|
|
|||
|
|
@ -68,14 +68,6 @@ export async function deleteTeamUser(teamId: string, userId: string): Promise<Te
|
|||
const { client, transaction } = prisma;
|
||||
|
||||
return transaction([
|
||||
client.teamWebsite.deleteMany({
|
||||
where: {
|
||||
teamId: teamId,
|
||||
website: {
|
||||
userId: userId,
|
||||
},
|
||||
},
|
||||
}),
|
||||
client.teamUser.deleteMany({
|
||||
where: {
|
||||
teamId,
|
||||
|
|
|
|||
|
|
@ -1,127 +0,0 @@
|
|||
import { Prisma, Team, TeamUser, TeamWebsite, Website } from '@prisma/client';
|
||||
import { ROLES } from 'lib/constants';
|
||||
import { uuid } from 'lib/crypto';
|
||||
import prisma from 'lib/prisma';
|
||||
|
||||
export async function getTeamWebsite(
|
||||
teamId: string,
|
||||
websiteId: string,
|
||||
): Promise<
|
||||
TeamWebsite & {
|
||||
website: Website;
|
||||
}
|
||||
> {
|
||||
return prisma.client.teamWebsite.findFirst({
|
||||
where: {
|
||||
teamId,
|
||||
websiteId,
|
||||
},
|
||||
include: {
|
||||
website: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function findTeamWebsiteByUserId(
|
||||
websiteId: string,
|
||||
userId: string,
|
||||
): Promise<TeamWebsite> {
|
||||
return prisma.client.teamWebsite.findFirst({
|
||||
where: {
|
||||
websiteId,
|
||||
team: {
|
||||
teamUser: {
|
||||
some: {
|
||||
userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function getTeamWebsites(teamId: string): Promise<
|
||||
(TeamWebsite & {
|
||||
team: Team & { teamUser: TeamUser[] };
|
||||
website: Website & {
|
||||
user: { id: string; username: string };
|
||||
};
|
||||
})[]
|
||||
> {
|
||||
return prisma.client.teamWebsite.findMany({
|
||||
where: {
|
||||
teamId,
|
||||
},
|
||||
include: {
|
||||
team: {
|
||||
include: {
|
||||
teamUser: {
|
||||
where: {
|
||||
role: ROLES.teamOwner,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
website: {
|
||||
include: {
|
||||
user: {
|
||||
select: {
|
||||
id: true,
|
||||
username: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
orderBy: [
|
||||
{
|
||||
team: {
|
||||
name: 'asc',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
export async function createTeamWebsite(teamId: string, websiteId: string): Promise<TeamWebsite> {
|
||||
return prisma.client.teamWebsite.create({
|
||||
data: {
|
||||
id: uuid(),
|
||||
teamId,
|
||||
websiteId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function createTeamWebsites(teamId: string, websiteIds: string[]) {
|
||||
const currentTeamWebsites = await getTeamWebsites(teamId);
|
||||
|
||||
// filter out websites that already exists on the team
|
||||
const addWebsites = websiteIds.filter(
|
||||
websiteId => !currentTeamWebsites.some(a => a.websiteId === websiteId),
|
||||
);
|
||||
|
||||
const teamWebsites: Prisma.TeamWebsiteCreateManyInput[] = addWebsites.map(a => {
|
||||
return {
|
||||
id: uuid(),
|
||||
teamId,
|
||||
websiteId: a,
|
||||
};
|
||||
});
|
||||
|
||||
return prisma.client.teamWebsite.createMany({
|
||||
data: teamWebsites,
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteTeamWebsite(
|
||||
teamId: string,
|
||||
websiteId: string,
|
||||
): Promise<Prisma.BatchPayload> {
|
||||
return prisma.client.teamWebsite.deleteMany({
|
||||
where: {
|
||||
teamId,
|
||||
websiteId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
@ -105,6 +105,7 @@ export async function getUsersByTeamId(teamId: string, filter?: UserSearchFilter
|
|||
include: {
|
||||
teamUser: {
|
||||
select: {
|
||||
teamId: true,
|
||||
role: true,
|
||||
},
|
||||
},
|
||||
|
|
@ -188,7 +189,27 @@ export async function deleteUser(
|
|||
|
||||
const teamIds = teams.map(a => a.id);
|
||||
|
||||
return prisma
|
||||
if (cloudMode) {
|
||||
return client.transaction([
|
||||
client.website.updateMany({
|
||||
data: {
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
where: { id: { in: websiteIds } },
|
||||
}),
|
||||
client.user.update({
|
||||
data: {
|
||||
username: getRandomChars(32),
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
return client
|
||||
.transaction([
|
||||
client.eventData.deleteMany({
|
||||
where: { websiteId: { in: websiteIds } },
|
||||
|
|
@ -199,29 +220,6 @@ export async function deleteUser(
|
|||
client.session.deleteMany({
|
||||
where: { websiteId: { in: websiteIds } },
|
||||
}),
|
||||
client.teamWebsite.deleteMany({
|
||||
where: {
|
||||
OR: [
|
||||
{
|
||||
websiteId: {
|
||||
in: websiteIds,
|
||||
},
|
||||
},
|
||||
{
|
||||
teamId: {
|
||||
in: teamIds,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
client.teamWebsite.deleteMany({
|
||||
where: {
|
||||
teamId: {
|
||||
in: teamIds,
|
||||
},
|
||||
},
|
||||
}),
|
||||
client.teamUser.deleteMany({
|
||||
where: {
|
||||
OR: [
|
||||
|
|
@ -257,33 +255,16 @@ export async function deleteUser(
|
|||
],
|
||||
},
|
||||
}),
|
||||
cloudMode
|
||||
? client.website.updateMany({
|
||||
data: {
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
where: { id: { in: websiteIds } },
|
||||
})
|
||||
: client.website.deleteMany({
|
||||
where: { id: { in: websiteIds } },
|
||||
}),
|
||||
cloudMode
|
||||
? client.user.update({
|
||||
data: {
|
||||
username: getRandomChars(32),
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
})
|
||||
: client.user.delete({
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
}),
|
||||
client.website.deleteMany({
|
||||
where: { id: { in: websiteIds } },
|
||||
}),
|
||||
client.user.delete({
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
}),
|
||||
])
|
||||
.then(async data => {
|
||||
.then(async (data: any) => {
|
||||
if (cache.enabled) {
|
||||
const ids = websites.map(a => a.id);
|
||||
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ export async function deleteWebsite(
|
|||
},
|
||||
}),
|
||||
cloudMode
|
||||
? prisma.client.website.update({
|
||||
? client.website.update({
|
||||
data: {
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
export * from './admin/report';
|
||||
export * from './admin/team';
|
||||
export * from './admin/teamUser';
|
||||
export * from './admin/teamWebsite';
|
||||
export * from './admin/user';
|
||||
export * from './admin/website';
|
||||
export * from './analytics/events/getEventMetrics';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue