mirror of
https://github.com/kremalicious/umami.git
synced 2025-02-14 21:10:34 +01:00
Teams refactor: removed team websites.
This commit is contained in:
parent
0d442b751d
commit
f85393f8df
@ -67,7 +67,7 @@
|
||||
"@prisma/extension-read-replicas": "^0.3.0",
|
||||
"@react-spring/web": "^9.7.3",
|
||||
"@tanstack/react-query": "^5.12.2",
|
||||
"@umami/prisma-client": "^0.8.0",
|
||||
"@umami/prisma-client": "^0.13.0",
|
||||
"@umami/redis-client": "^0.18.0",
|
||||
"chalk": "^4.1.1",
|
||||
"chart.js": "^4.2.1",
|
||||
|
@ -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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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,6 +35,7 @@ export function UsersTable({ data = [] }: { data: any[] }) {
|
||||
})
|
||||
}
|
||||
</GridColumn>
|
||||
{showActions && (
|
||||
<GridColumn name="action" label=" " alignment="end">
|
||||
{row => {
|
||||
const { id, username } = row;
|
||||
@ -47,6 +54,7 @@ export function UsersTable({ data = [] }: { data: any[] }) {
|
||||
);
|
||||
}}
|
||||
</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.teamWebsite.deleteMany({
|
||||
client.team.update({
|
||||
data: {
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
where: {
|
||||
teamId,
|
||||
id: teamId,
|
||||
},
|
||||
}),
|
||||
]);
|
||||
}
|
||||
|
||||
return transaction([
|
||||
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({
|
||||
client.website.deleteMany({
|
||||
where: { id: { in: websiteIds } },
|
||||
}),
|
||||
cloudMode
|
||||
? client.user.update({
|
||||
data: {
|
||||
username: getRandomChars(32),
|
||||
deletedAt: new Date(),
|
||||
},
|
||||
where: {
|
||||
id: userId,
|
||||
},
|
||||
})
|
||||
: client.user.delete({
|
||||
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';
|
||||
|
64
yarn.lock
64
yarn.lock
@ -2597,13 +2597,15 @@
|
||||
"@typescript-eslint/types" "6.14.0"
|
||||
eslint-visitor-keys "^3.4.1"
|
||||
|
||||
"@umami/prisma-client@^0.8.0":
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@umami/prisma-client/-/prisma-client-0.8.0.tgz#9f866c813b15b7ab0e7632506316bf1e5d2e74cc"
|
||||
integrity sha512-ix3/75CO3eVlf1Rg0cUIjoHDFJV7nxx5sSh1NnvbjyGn8EsTpZ7fVYF874w8+ENQsaKFIMftUSGGiwvgxaZN3g==
|
||||
"@umami/prisma-client@^0.13.0":
|
||||
version "0.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@umami/prisma-client/-/prisma-client-0.13.0.tgz#00ed90adf36e8e8cb7301ab557ad617dd946188f"
|
||||
integrity sha512-HkhwTH7cxkbqlxw6LK8QGbEaIl0aYZeVf5bUwncv68C/RaQrQ0/g9x6TzHo6uKlSgk2LtavnGwxYmjxD1fdGQw==
|
||||
dependencies:
|
||||
"@prisma/extension-read-replicas" "^0.3.0"
|
||||
chalk "^4.1.2"
|
||||
debug "^4.3.4"
|
||||
sql-formatter "^15.1.2"
|
||||
|
||||
"@umami/redis-client@^0.18.0":
|
||||
version "0.18.0"
|
||||
@ -3377,7 +3379,7 @@ commander@11.0.0:
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-11.0.0.tgz#43e19c25dbedc8256203538e8d7e9346877a6f67"
|
||||
integrity sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==
|
||||
|
||||
commander@2, commander@^2.20.0, commander@^2.20.3:
|
||||
commander@2, commander@^2.19.0, commander@^2.20.0, commander@^2.20.3:
|
||||
version "2.20.3"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||
@ -3933,6 +3935,11 @@ dir-glob@^3.0.1:
|
||||
dependencies:
|
||||
path-type "^4.0.0"
|
||||
|
||||
discontinuous-range@1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
|
||||
integrity sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==
|
||||
|
||||
doctrine@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
|
||||
@ -4793,6 +4800,11 @@ get-port-please@^3.1.1:
|
||||
resolved "https://registry.yarnpkg.com/get-port-please/-/get-port-please-3.1.1.tgz#2556623cddb4801d823c0a6a15eec038abb483be"
|
||||
integrity sha512-3UBAyM3u4ZBVYDsxOQfJDxEa6XTbpBDrOjp4mf7ExFRt5BKs/QywQQiJsh2B+hxcZLSapWqCRvElUe8DnKcFHA==
|
||||
|
||||
get-stdin@=8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53"
|
||||
integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==
|
||||
|
||||
get-stream@^6.0.0, get-stream@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
|
||||
@ -6308,6 +6320,11 @@ moment-timezone@^0.5.35:
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
|
||||
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
|
||||
|
||||
moo@^0.5.0:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.2.tgz#f9fe82473bc7c184b0d32e2215d3f6e67278733c"
|
||||
integrity sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==
|
||||
|
||||
mri@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b"
|
||||
@ -6353,6 +6370,16 @@ natural-compare@^1.4.0:
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
||||
|
||||
nearley@^2.20.1:
|
||||
version "2.20.1"
|
||||
resolved "https://registry.yarnpkg.com/nearley/-/nearley-2.20.1.tgz#246cd33eff0d012faf197ff6774d7ac78acdd474"
|
||||
integrity sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==
|
||||
dependencies:
|
||||
commander "^2.19.0"
|
||||
moo "^0.5.0"
|
||||
railroad-diagrams "^1.0.0"
|
||||
randexp "0.4.6"
|
||||
|
||||
next-basics@^0.39.0:
|
||||
version "0.39.0"
|
||||
resolved "https://registry.yarnpkg.com/next-basics/-/next-basics-0.39.0.tgz#1ec448a1c12966a82067445bfb9319b7e883dd6a"
|
||||
@ -7507,6 +7534,19 @@ raf-schd@^4.0.2:
|
||||
resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a"
|
||||
integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==
|
||||
|
||||
railroad-diagrams@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz#eb7e6267548ddedfb899c1b90e57374559cddb7e"
|
||||
integrity sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==
|
||||
|
||||
randexp@0.4.6:
|
||||
version "0.4.6"
|
||||
resolved "https://registry.yarnpkg.com/randexp/-/randexp-0.4.6.tgz#e986ad5e5e31dae13ddd6f7b3019aa7c87f60ca3"
|
||||
integrity sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==
|
||||
dependencies:
|
||||
discontinuous-range "1.0.0"
|
||||
ret "~0.1.10"
|
||||
|
||||
randombytes@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
|
||||
@ -7883,6 +7923,11 @@ restore-cursor@^4.0.0:
|
||||
onetime "^5.1.0"
|
||||
signal-exit "^3.0.2"
|
||||
|
||||
ret@~0.1.10:
|
||||
version "0.1.15"
|
||||
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
|
||||
integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
|
||||
|
||||
reusify@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||
@ -8280,6 +8325,15 @@ sprintf-js@~1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||
integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==
|
||||
|
||||
sql-formatter@^15.1.2:
|
||||
version "15.1.2"
|
||||
resolved "https://registry.yarnpkg.com/sql-formatter/-/sql-formatter-15.1.2.tgz#86df2592eedf6d422244e10e00a74380c22791b7"
|
||||
integrity sha512-zBrLBclCNurCsQaO6yMvkXzHvv7eJPjiF8LIEQ5HdBV/x6UuWIZwqss3mlZ/6HLj+VYhFKeHpQnyLuZWG2agKQ==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
get-stdin "=8.0.0"
|
||||
nearley "^2.20.1"
|
||||
|
||||
stable@^0.1.8:
|
||||
version "0.1.8"
|
||||
resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
|
||||
|
Loading…
Reference in New Issue
Block a user