mirror of
https://github.com/kremalicious/umami.git
synced 2024-12-24 02:06:19 +01:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
b40630f9d4
@ -287,10 +287,10 @@ INSERT INTO "user" (user_id, username, password) VALUES ('41e2b680-648e-4b09-bcd
|
||||
|
||||
-- Add Roles
|
||||
INSERT INTO "role" ("role_id", "name", "description") VALUES (gen_random_uuid(), 'Admin', 'System Admin.');
|
||||
INSERT INTO "role" ("role_id", "name", "description") (gen_random_uuid(), 'Member', 'Create and maintain websites.');
|
||||
INSERT INTO "role" ("role_id", "name", "description") (gen_random_uuid(), 'Team Owner', 'Create and maintain the team, memberships, websites, and responsible for billing.');
|
||||
INSERT INTO "role" ("role_id", "name", "description") (gen_random_uuid(), 'Team Member', 'Create and maintain websites.');
|
||||
INSERT INTO "role" ("role_id", "name", "description") (gen_random_uuid(), 'Team Guest', 'View Websites.');
|
||||
INSERT INTO "role" ("role_id", "name", "description") VALUES (gen_random_uuid(), 'Member', 'Create and maintain websites.');
|
||||
INSERT INTO "role" ("role_id", "name", "description") VALUES (gen_random_uuid(), 'Team Owner', 'Create and maintain the team, memberships, websites, and responsible for billing.');
|
||||
INSERT INTO "role" ("role_id", "name", "description") VALUES (gen_random_uuid(), 'Team Member', 'Create and maintain websites.');
|
||||
INSERT INTO "role" ("role_id", "name", "description") VALUES (gen_random_uuid(), 'Team Guest', 'View Websites.');
|
||||
|
||||
-- Add Permissions
|
||||
INSERT INTO "permission" ("permission_id", "name", "description") VALUES (gen_random_uuid(), 'admin', 'System Admin');
|
||||
|
@ -14,11 +14,9 @@ model User {
|
||||
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||
isDeleted Boolean @default(false) @map("is_deleted")
|
||||
|
||||
groupRole GroupRole[]
|
||||
groupUser GroupUser[]
|
||||
userRole UserRole[]
|
||||
teamUser TeamUser[]
|
||||
Website Website[]
|
||||
userRole UserRole[]
|
||||
teamUser TeamUser[]
|
||||
Website Website[]
|
||||
|
||||
@@map("user")
|
||||
}
|
||||
@ -78,96 +76,16 @@ model WebsiteEvent {
|
||||
@@map("website_event")
|
||||
}
|
||||
|
||||
model Group {
|
||||
id String @id() @unique() @map("group_id") @db.Uuid
|
||||
name String @unique() @db.VarChar(255)
|
||||
description String? @db.VarChar(255)
|
||||
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||
isDeleted Boolean @default(false) @map("is_deleted")
|
||||
|
||||
groupRoles GroupRole[]
|
||||
groupUsers GroupUser[]
|
||||
|
||||
@@map("group")
|
||||
}
|
||||
|
||||
model GroupRole {
|
||||
id String @id() @unique() @map("group_role_id") @db.Uuid
|
||||
groupId String @map("group_id") @db.Uuid
|
||||
roleId String @map("role_id") @db.Uuid
|
||||
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||
isDeleted Boolean @default(false) @map("is_deleted")
|
||||
|
||||
group Group @relation(fields: [groupId], references: [id])
|
||||
role Role @relation(fields: [roleId], references: [id])
|
||||
user User? @relation(fields: [userId], references: [id])
|
||||
userId String? @db.Uuid
|
||||
|
||||
@@map("group_role")
|
||||
}
|
||||
|
||||
model GroupUser {
|
||||
id String @id() @unique() @map("group_user_id") @db.Uuid
|
||||
groupId String @map("group_id") @db.Uuid
|
||||
userId String @map("user_id") @db.Uuid
|
||||
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||
isDeleted Boolean @default(false) @map("is_deleted")
|
||||
|
||||
group Group @relation(fields: [groupId], references: [id])
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
|
||||
@@map("group_user")
|
||||
}
|
||||
|
||||
model Permission {
|
||||
id String @id() @unique() @map("permission_id") @db.Uuid
|
||||
name String @unique() @db.VarChar(255)
|
||||
description String? @db.VarChar(255)
|
||||
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||
RolePermission RolePermission[]
|
||||
|
||||
@@map("permission")
|
||||
}
|
||||
|
||||
model Role {
|
||||
id String @id() @unique() @map("role_id") @db.Uuid
|
||||
name String @unique() @db.VarChar(255)
|
||||
description String? @db.VarChar(255)
|
||||
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||
|
||||
groupRoles GroupRole[]
|
||||
userRoles UserRole[]
|
||||
RolePermission RolePermission[]
|
||||
TeamUser TeamUser[]
|
||||
|
||||
@@map("role")
|
||||
}
|
||||
|
||||
model RolePermission {
|
||||
id String @id() @unique() @map("role_permission_id") @db.Uuid
|
||||
roleId String @map("role_id") @db.Uuid
|
||||
permissionId String @map("permission_id") @db.Uuid
|
||||
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||
isDeleted Boolean @default(false) @map("is_deleted")
|
||||
|
||||
role Role @relation(fields: [roleId], references: [id])
|
||||
permission Permission @relation(fields: [permissionId], references: [id])
|
||||
|
||||
@@unique([roleId, permissionId])
|
||||
@@map("role_permission")
|
||||
}
|
||||
|
||||
model UserRole {
|
||||
id String @id() @unique() @map("user_role_id") @db.Uuid
|
||||
roleId String @map("role_id") @db.Uuid
|
||||
role String @map("role") @db.VarChar(100)
|
||||
userId String @map("user_id") @db.Uuid
|
||||
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||
isDeleted Boolean @default(false) @map("is_deleted")
|
||||
|
||||
role Role @relation(fields: [roleId], references: [id])
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
|
||||
@@unique([roleId, userId])
|
||||
@@unique([role, userId])
|
||||
@@map("user_role")
|
||||
}
|
||||
|
||||
@ -187,13 +105,12 @@ model TeamUser {
|
||||
id String @id() @unique() @map("team_user_id") @db.Uuid
|
||||
teamId String @map("team_id") @db.Uuid
|
||||
userId String @map("user_id") @db.Uuid
|
||||
roleId String @map("role_id") @db.Uuid
|
||||
role String @map("role") @db.VarChar(100)
|
||||
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
|
||||
isDeleted Boolean @default(false) @map("is_deleted")
|
||||
|
||||
team Team @relation(fields: [teamId], references: [id])
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
role Role @relation(fields: [roleId], references: [id])
|
||||
|
||||
@@map("team_user")
|
||||
}
|
||||
|
181
lib/auth.ts
181
lib/auth.ts
@ -1,10 +1,10 @@
|
||||
import { UserRole } from '@prisma/client';
|
||||
import debug from 'debug';
|
||||
import { NextApiRequestAuth } from 'interface/api/nextApi';
|
||||
import cache from 'lib/cache';
|
||||
import { SHARE_TOKEN_HEADER, UmamiApi } from 'lib/constants';
|
||||
import { secret } from 'lib/crypto';
|
||||
import { parseSecureToken, parseToken } from 'next-basics';
|
||||
import { getPermissionsByUserId, getTeamUser, getUser } from 'queries';
|
||||
import { getTeamUser, getUserRoles } from 'queries';
|
||||
|
||||
const log = debug('umami:auth');
|
||||
|
||||
@ -34,13 +34,6 @@ export function parseShareToken(req) {
|
||||
}
|
||||
}
|
||||
|
||||
export function hasPermission(
|
||||
value: UmamiApi.Role | UmamiApi.Permission,
|
||||
permissions: UmamiApi.Role[] | UmamiApi.Permission[],
|
||||
) {
|
||||
return permissions.some(a => a === value);
|
||||
}
|
||||
|
||||
export function isValidToken(token, validation) {
|
||||
try {
|
||||
if (typeof validation === 'object') {
|
||||
@ -56,71 +49,6 @@ export function isValidToken(token, validation) {
|
||||
return false;
|
||||
}
|
||||
|
||||
export async function allowQuery(
|
||||
req: NextApiRequestAuth,
|
||||
type: UmamiApi.AuthType,
|
||||
typeId?: string,
|
||||
) {
|
||||
const { id } = req.query as { id: string };
|
||||
|
||||
const { user, shareToken } = req.auth;
|
||||
|
||||
if (shareToken) {
|
||||
return isValidToken(shareToken, { id });
|
||||
}
|
||||
|
||||
if (user?.id) {
|
||||
if (type === UmamiApi.AuthType.Website) {
|
||||
const website = await cache.fetchWebsite(typeId ?? id);
|
||||
|
||||
if (website && website.userId === user.id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (website.teamId) {
|
||||
const teamUser = getTeamUser({ userId: user.id, teamId: website.teamId, isDeleted: false });
|
||||
|
||||
return teamUser;
|
||||
}
|
||||
|
||||
return false;
|
||||
} else if (type === UmamiApi.AuthType.User) {
|
||||
const user = await getUser({ id });
|
||||
|
||||
return user && user.id === id;
|
||||
} else if (type === UmamiApi.AuthType.Team) {
|
||||
const teamUser = await getTeamUser({
|
||||
userId: user.id,
|
||||
teamId: typeId ?? id,
|
||||
});
|
||||
|
||||
return teamUser;
|
||||
} else if (type === UmamiApi.AuthType.TeamOwner) {
|
||||
const teamUser = await getTeamUser({
|
||||
userId: user.id,
|
||||
teamId: typeId ?? id,
|
||||
});
|
||||
|
||||
return (
|
||||
teamUser &&
|
||||
(teamUser.roleId === UmamiApi.Role.TeamOwner || teamUser.roleId === UmamiApi.Role.Admin)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export async function checkPermission(req: NextApiRequestAuth, type: UmamiApi.Permission) {
|
||||
const {
|
||||
user: { id: userId },
|
||||
} = req.auth;
|
||||
|
||||
const userRole = await getPermissionsByUserId(userId, type);
|
||||
|
||||
return userRole.length > 0;
|
||||
}
|
||||
|
||||
export async function canViewWebsite(userId: string, websiteId: string) {
|
||||
const website = await cache.fetchWebsite(websiteId);
|
||||
|
||||
@ -128,7 +56,13 @@ export async function canViewWebsite(userId: string, websiteId: string) {
|
||||
return userId === website.userId;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (website.teamId) {
|
||||
const teamUser = await getTeamUser({ userId, teamId: website.teamId });
|
||||
|
||||
checkPermission(UmamiApi.Permission.websiteUpdate, teamUser.role as keyof UmamiApi.Roles);
|
||||
}
|
||||
|
||||
return checkAdmin(userId);
|
||||
}
|
||||
|
||||
export async function canUpdateWebsite(userId: string, websiteId: string) {
|
||||
@ -138,5 +72,100 @@ export async function canUpdateWebsite(userId: string, websiteId: string) {
|
||||
return userId === website.userId;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (website.teamId) {
|
||||
const teamUser = await getTeamUser({ userId, teamId: website.teamId });
|
||||
|
||||
checkPermission(UmamiApi.Permission.websiteUpdate, teamUser.role as keyof UmamiApi.Roles);
|
||||
}
|
||||
|
||||
return checkAdmin(userId);
|
||||
}
|
||||
|
||||
export async function canDeleteWebsite(userId: string, websiteId: string) {
|
||||
const website = await cache.fetchWebsite(websiteId);
|
||||
|
||||
if (website.userId) {
|
||||
return userId === website.userId;
|
||||
}
|
||||
|
||||
if (website.teamId) {
|
||||
const teamUser = await getTeamUser({ userId, teamId: website.teamId });
|
||||
|
||||
if (checkPermission(UmamiApi.Permission.websiteDelete, teamUser.role as keyof UmamiApi.Roles)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return checkAdmin(userId);
|
||||
}
|
||||
|
||||
// To-do: Implement when payments are setup.
|
||||
export async function canCreateTeam(userId: string) {
|
||||
return !!userId;
|
||||
}
|
||||
|
||||
// To-do: Implement when payments are setup.
|
||||
export async function canViewTeam(userId: string, teamId) {
|
||||
const teamUser = await getTeamUser({ userId, teamId });
|
||||
return !!teamUser;
|
||||
}
|
||||
|
||||
export async function canUpdateTeam(userId: string, teamId: string) {
|
||||
const teamUser = await getTeamUser({ userId, teamId });
|
||||
|
||||
if (checkPermission(UmamiApi.Permission.teamUpdate, teamUser.role as keyof UmamiApi.Roles)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export async function canDeleteTeam(userId: string, teamId: string) {
|
||||
const teamUser = await getTeamUser({ userId, teamId });
|
||||
|
||||
if (checkPermission(UmamiApi.Permission.teamDelete, teamUser.role as keyof UmamiApi.Roles)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
export async function canCreateUser(userId: string) {
|
||||
return checkAdmin(userId);
|
||||
}
|
||||
|
||||
export async function canViewUser(userId: string, viewedUserId: string) {
|
||||
if (userId === viewedUserId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return checkAdmin(userId);
|
||||
}
|
||||
|
||||
export async function canViewUsers(userId: string) {
|
||||
return checkAdmin(userId);
|
||||
}
|
||||
|
||||
export async function canUpdateUser(userId: string, viewedUserId: string) {
|
||||
if (userId === viewedUserId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return checkAdmin(userId);
|
||||
}
|
||||
|
||||
export async function canUpdateUserRole(userId: string) {
|
||||
return checkAdmin(userId);
|
||||
}
|
||||
|
||||
export async function canDeleteUser(userId: string) {
|
||||
return checkAdmin(userId);
|
||||
}
|
||||
|
||||
export async function checkPermission(permission: UmamiApi.Permission, role: keyof UmamiApi.Roles) {
|
||||
return UmamiApi.Roles[role].permissions.some(a => a === permission);
|
||||
}
|
||||
|
||||
export async function checkAdmin(userId: string, userRoles?: UserRole[]) {
|
||||
if (!userRoles) {
|
||||
userRoles = await getUserRoles({ userId });
|
||||
}
|
||||
|
||||
return userRoles.some(a => a.role === UmamiApi.Role.Admin);
|
||||
}
|
||||
|
@ -9,52 +9,56 @@ export namespace UmamiApi {
|
||||
Website,
|
||||
User,
|
||||
Team,
|
||||
TeamOwner,
|
||||
}
|
||||
|
||||
export enum Permission {
|
||||
Admin = 'Admin',
|
||||
WebsiteCreate = 'website:create',
|
||||
WebsiteRead = 'website:read',
|
||||
WebsiteUpdate = 'website:update',
|
||||
WebsiteReset = 'website:reset',
|
||||
WebsiteDelete = 'website:delete',
|
||||
TeamCreate = 'team:create',
|
||||
TeamUpdate = 'team:update',
|
||||
TeamDelete = 'team:delete',
|
||||
TeamAddUser = 'team:add-user',
|
||||
TeamRemoveUser = 'team:remove-user',
|
||||
all = 'all',
|
||||
websiteCreate = 'website:create',
|
||||
websiteUpdate = 'website:update',
|
||||
websiteDelete = 'website:delete',
|
||||
teamCreate = 'team:create',
|
||||
teamUpdate = 'team:update',
|
||||
teamDelete = 'team:delete',
|
||||
}
|
||||
|
||||
export enum Role {
|
||||
Admin = 'Admin',
|
||||
Member = 'Member',
|
||||
TeamOwner = 'Team Owner',
|
||||
TeamMember = 'Team Member',
|
||||
TeamGuest = 'Team Guest,',
|
||||
Admin = 'admin',
|
||||
User = 'user',
|
||||
TeamOwner = 'team-owner',
|
||||
TeamMember = 'team-member',
|
||||
TeamGuest = 'team-guest',
|
||||
}
|
||||
|
||||
export const Roles = {
|
||||
admin: { name: Role.Admin, permissions: [Permission.all] },
|
||||
member: {
|
||||
name: Role.User,
|
||||
permissions: [
|
||||
Permission.websiteCreate,
|
||||
Permission.websiteUpdate,
|
||||
Permission.websiteDelete,
|
||||
Permission.teamCreate,
|
||||
],
|
||||
},
|
||||
teamOwner: {
|
||||
name: Role.TeamOwner,
|
||||
permissions: [
|
||||
Permission.teamUpdate,
|
||||
Permission.teamDelete,
|
||||
Permission.websiteCreate,
|
||||
Permission.websiteUpdate,
|
||||
Permission.websiteDelete,
|
||||
],
|
||||
},
|
||||
teamMember: {
|
||||
name: Role.TeamMember,
|
||||
permissions: [Permission.websiteCreate, Permission.websiteUpdate, Permission.websiteDelete],
|
||||
},
|
||||
teamGuest: { name: Role.TeamGuest, permissions: [] },
|
||||
};
|
||||
|
||||
export type Roles = typeof Roles;
|
||||
}
|
||||
|
||||
export const PERMISSIONS = {
|
||||
all: 'all',
|
||||
websiteCreate: 'website:create',
|
||||
websiteUpdate: 'website:update',
|
||||
websiteDelete: 'website:delete',
|
||||
teamCreate: 'team:create',
|
||||
teamUpdate: 'team:update',
|
||||
teamDelete: 'team:delete',
|
||||
};
|
||||
|
||||
export const ROLES = {
|
||||
admin: { name: 'admin', permissions: [PERMISSIONS.all] },
|
||||
teamOwner: { name: 'team-owner', permissions: [PERMISSIONS.teamUpdate, PERMISSIONS.teamDelete] },
|
||||
teamMember: {
|
||||
name: 'team-member',
|
||||
permissions: [PERMISSIONS.websiteCreate, PERMISSIONS.websiteUpdate, PERMISSIONS.websiteDelete],
|
||||
},
|
||||
teamGuest: { name: 'team-guest' },
|
||||
};
|
||||
|
||||
export const CURRENT_VERSION = process.env.currentVersion;
|
||||
export const AUTH_TOKEN = 'umami.auth';
|
||||
export const LOCALE_CONFIG = 'umami.locale';
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Team } from '@prisma/client';
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { allowQuery } from 'lib/auth';
|
||||
import { UmamiApi } from 'lib/constants';
|
||||
import { canDeleteTeam, canUpdateTeam, canViewTeam } from 'lib/auth';
|
||||
import { useAuth } from 'lib/middleware';
|
||||
import { NextApiResponse } from 'next';
|
||||
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||
@ -21,12 +20,16 @@ export default async (
|
||||
) => {
|
||||
await useAuth(req, res);
|
||||
|
||||
const {
|
||||
user: { id: userId },
|
||||
} = req.auth;
|
||||
const { id: teamId } = req.query;
|
||||
|
||||
if (req.method === 'GET') {
|
||||
if (!(await allowQuery(req, UmamiApi.AuthType.Team))) {
|
||||
if (await canViewTeam(userId, teamId)) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
const user = await getTeam({ id: teamId });
|
||||
|
||||
return ok(res, user);
|
||||
@ -35,7 +38,7 @@ export default async (
|
||||
if (req.method === 'POST') {
|
||||
const { name } = req.body;
|
||||
|
||||
if (!(await allowQuery(req, UmamiApi.AuthType.TeamOwner))) {
|
||||
if (await canUpdateTeam(userId, teamId)) {
|
||||
return unauthorized(res, 'You must be the owner of this team.');
|
||||
}
|
||||
|
||||
@ -45,7 +48,7 @@ export default async (
|
||||
}
|
||||
|
||||
if (req.method === 'DELETE') {
|
||||
if (!(await allowQuery(req, UmamiApi.AuthType.TeamOwner))) {
|
||||
if (await canDeleteTeam(userId, teamId)) {
|
||||
return unauthorized(res, 'You must be the owner of this team.');
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { allowQuery } from 'lib/auth';
|
||||
import { UmamiApi } from 'lib/constants';
|
||||
import { canUpdateTeam, canViewTeam } from 'lib/auth';
|
||||
import { useAuth } from 'lib/middleware';
|
||||
import { NextApiResponse } from 'next';
|
||||
import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||
@ -22,10 +21,13 @@ export default async (
|
||||
) => {
|
||||
await useAuth(req, res);
|
||||
|
||||
const {
|
||||
user: { id: userId },
|
||||
} = req.auth;
|
||||
const { id: teamId } = req.query;
|
||||
|
||||
if (req.method === 'GET') {
|
||||
if (!(await allowQuery(req, UmamiApi.AuthType.Team))) {
|
||||
if (await canViewTeam(userId, teamId)) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
@ -35,7 +37,7 @@ export default async (
|
||||
}
|
||||
|
||||
if (req.method === 'POST') {
|
||||
if (!(await allowQuery(req, UmamiApi.AuthType.TeamOwner))) {
|
||||
if (await canUpdateTeam(userId, teamId)) {
|
||||
return unauthorized(res, 'You must be the owner of this team.');
|
||||
}
|
||||
|
||||
@ -54,7 +56,7 @@ export default async (
|
||||
}
|
||||
|
||||
if (req.method === 'DELETE') {
|
||||
if (!(await allowQuery(req, UmamiApi.AuthType.TeamOwner))) {
|
||||
if (await canUpdateTeam(userId, teamId)) {
|
||||
return unauthorized(res, 'You must be the owner of this team.');
|
||||
}
|
||||
const { team_user_id } = req.body;
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { allowQuery } from 'lib/auth';
|
||||
import { UmamiApi } from 'lib/constants';
|
||||
import { canViewTeam } from 'lib/auth';
|
||||
import { useAuth } from 'lib/middleware';
|
||||
import { NextApiResponse } from 'next';
|
||||
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||
@ -21,10 +20,13 @@ export default async (
|
||||
) => {
|
||||
await useAuth(req, res);
|
||||
|
||||
const {
|
||||
user: { id: userId },
|
||||
} = req.auth;
|
||||
const { id: teamId } = req.query;
|
||||
|
||||
if (req.method === 'GET') {
|
||||
if (!(await allowQuery(req, UmamiApi.AuthType.Team))) {
|
||||
if (await canViewTeam(userId, teamId)) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { Team } from '@prisma/client';
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { canCreateTeam } from 'lib/auth';
|
||||
import { uuid } from 'lib/crypto';
|
||||
import { useAuth } from 'lib/middleware';
|
||||
import { NextApiResponse } from 'next';
|
||||
import { badRequest, methodNotAllowed, ok } from 'next-basics';
|
||||
import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||
import { createTeam, getTeam, getTeamsByUserId } from 'queries';
|
||||
export interface TeamsRequestBody {
|
||||
name: string;
|
||||
@ -17,16 +18,20 @@ export default async (
|
||||
await useAuth(req, res);
|
||||
|
||||
const {
|
||||
user: { id },
|
||||
user: { id: userId },
|
||||
} = req.auth;
|
||||
|
||||
if (req.method === 'GET') {
|
||||
const teams = await getTeamsByUserId(id);
|
||||
const teams = await getTeamsByUserId(userId);
|
||||
|
||||
return ok(res, teams);
|
||||
}
|
||||
|
||||
if (req.method === 'POST') {
|
||||
if (await canCreateTeam(userId)) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
const { name } = req.body;
|
||||
|
||||
const team = await getTeam({ name });
|
||||
@ -36,7 +41,7 @@ export default async (
|
||||
}
|
||||
|
||||
const created = await createTeam({
|
||||
id: id || uuid(),
|
||||
id: uuid(),
|
||||
name,
|
||||
});
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { checkPermission } from 'lib/auth';
|
||||
import { UmamiApi } from 'lib/constants';
|
||||
import { canDeleteUser, canUpdateUser, canViewUser, checkAdmin } from 'lib/auth';
|
||||
import { useAuth } from 'lib/middleware';
|
||||
import { NextApiResponse } from 'next';
|
||||
import { badRequest, hashPassword, methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||
@ -27,7 +26,7 @@ export default async (
|
||||
const { id } = req.query;
|
||||
|
||||
if (req.method === 'GET') {
|
||||
if (id !== userId) {
|
||||
if (await canViewUser(userId, id)) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
@ -37,12 +36,12 @@ export default async (
|
||||
}
|
||||
|
||||
if (req.method === 'POST') {
|
||||
const { username, password } = req.body;
|
||||
|
||||
if (id !== userId) {
|
||||
if (await canUpdateUser(userId, id)) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
const { username, password } = req.body;
|
||||
|
||||
const user = await getUser({ id });
|
||||
|
||||
const data: any = {};
|
||||
@ -52,7 +51,7 @@ export default async (
|
||||
}
|
||||
|
||||
// Only admin can change these fields
|
||||
if (!(await checkPermission(req, UmamiApi.Permission.Admin))) {
|
||||
if (username && (await checkAdmin(userId))) {
|
||||
data.username = username;
|
||||
}
|
||||
|
||||
@ -71,12 +70,12 @@ export default async (
|
||||
}
|
||||
|
||||
if (req.method === 'DELETE') {
|
||||
if (id === userId) {
|
||||
return badRequest(res, 'You cannot delete your own user.');
|
||||
if (canDeleteUser(userId)) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
if (!(await checkPermission(req, UmamiApi.Permission.Admin))) {
|
||||
return unauthorized(res);
|
||||
if (id === userId) {
|
||||
return badRequest(res, 'You cannot delete your own user.');
|
||||
}
|
||||
|
||||
await deleteUser(id);
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { allowQuery } from 'lib/auth';
|
||||
import { UmamiApi } from 'lib/constants';
|
||||
import { canUpdateUser } from 'lib/auth';
|
||||
import { useAuth } from 'lib/middleware';
|
||||
import { NextApiResponse } from 'next';
|
||||
import {
|
||||
@ -30,12 +29,15 @@ export default async (
|
||||
|
||||
const { current_password, new_password } = req.body;
|
||||
const { id } = req.query;
|
||||
|
||||
if (!(await allowQuery(req, UmamiApi.AuthType.User))) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
const {
|
||||
user: { id: userId },
|
||||
} = req.auth;
|
||||
|
||||
if (req.method === 'POST') {
|
||||
if (canUpdateUser(userId, id)) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
const user = await getUser({ id });
|
||||
|
||||
if (!checkPassword(current_password, user.password)) {
|
||||
|
@ -1,20 +1,17 @@
|
||||
import { UserRole } from '@prisma/client';
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { checkPermission } from 'lib/auth';
|
||||
import { canUpdateUserRole } from 'lib/auth';
|
||||
import { UmamiApi } from 'lib/constants';
|
||||
import { uuid } from 'lib/crypto';
|
||||
import { useAuth } from 'lib/middleware';
|
||||
import { NextApiResponse } from 'next';
|
||||
import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||
import { createUserRole, deleteUserRole, getUserRole, getUserRoles } from 'queries';
|
||||
import { deleteUserRole, getUserRole, getUserRoles, updateUserRole } from 'queries';
|
||||
|
||||
export interface UserRoleRequestQuery {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface UserRoleRequestBody {
|
||||
roleId: string;
|
||||
teamId?: string;
|
||||
role: UmamiApi.Role;
|
||||
userRoleId?: string;
|
||||
}
|
||||
|
||||
@ -29,7 +26,7 @@ export default async (
|
||||
} = req.auth;
|
||||
const { id } = req.query;
|
||||
|
||||
if (id !== userId || !(await checkPermission(req, UmamiApi.Permission.Admin))) {
|
||||
if (await canUpdateUserRole(userId)) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
@ -40,17 +37,17 @@ export default async (
|
||||
}
|
||||
|
||||
if (req.method === 'POST') {
|
||||
const { roleId, teamId } = req.body;
|
||||
const { role } = req.body;
|
||||
|
||||
const userRole = getUserRole({ userId: id, roleId, teamId });
|
||||
const userRole = await getUserRole({ userId: id });
|
||||
|
||||
if (userRole) {
|
||||
if (userRole && userRole.role === role) {
|
||||
return badRequest(res, 'Role already exists for User.');
|
||||
} else {
|
||||
const updated = await updateUserRole({ role }, { id: userRole.id });
|
||||
|
||||
return ok(res, updated);
|
||||
}
|
||||
|
||||
const updated = await createUserRole({ id: uuid(), userId: id, roleId, teamId });
|
||||
|
||||
return ok(res, updated);
|
||||
}
|
||||
|
||||
if (req.method === 'DELETE') {
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { checkPermission } from 'lib/auth';
|
||||
import { UmamiApi } from 'lib/constants';
|
||||
import { canCreateUser, canViewUsers } from 'lib/auth';
|
||||
import { uuid } from 'lib/crypto';
|
||||
import { useAuth } from 'lib/middleware';
|
||||
import { NextApiResponse } from 'next';
|
||||
@ -19,17 +18,25 @@ export default async (
|
||||
) => {
|
||||
await useAuth(req, res);
|
||||
|
||||
if (!(await checkPermission(req, UmamiApi.Permission.Admin))) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
const {
|
||||
user: { id: userId },
|
||||
} = req.auth;
|
||||
|
||||
if (req.method === 'GET') {
|
||||
if (canViewUsers(userId)) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
const users = await getUsers();
|
||||
|
||||
return ok(res, users);
|
||||
}
|
||||
|
||||
if (req.method === 'POST') {
|
||||
if (canCreateUser(userId)) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
const { username, password, id } = req.body;
|
||||
|
||||
const user = await getUser({ username });
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { WebsiteActive } from 'interface/api/models';
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { allowQuery } from 'lib/auth';
|
||||
import { UmamiApi } from 'lib/constants';
|
||||
import { canViewWebsite } from 'lib/auth';
|
||||
import { useAuth, useCors } from 'lib/middleware';
|
||||
import { NextApiResponse } from 'next';
|
||||
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||
@ -18,13 +17,16 @@ export default async (
|
||||
await useCors(req, res);
|
||||
await useAuth(req, res);
|
||||
|
||||
const {
|
||||
user: { id: userId },
|
||||
} = req.auth;
|
||||
const { id: websiteId } = req.query;
|
||||
|
||||
if (req.method === 'GET') {
|
||||
if (!(await allowQuery(req, UmamiApi.AuthType.Website))) {
|
||||
if (await canViewWebsite(userId, websiteId)) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
const { id: websiteId } = req.query;
|
||||
|
||||
const result = await getActiveVisitors(websiteId);
|
||||
|
||||
return ok(res, result);
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { WebsiteMetric } from 'interface/api/models';
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { allowQuery } from 'lib/auth';
|
||||
import { UmamiApi } from 'lib/constants';
|
||||
import { canViewWebsite } from 'lib/auth';
|
||||
import { useAuth, useCors } from 'lib/middleware';
|
||||
import { NextApiResponse } from 'next';
|
||||
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||
@ -26,13 +25,16 @@ export default async (
|
||||
await useCors(req, res);
|
||||
await useAuth(req, res);
|
||||
|
||||
const {
|
||||
user: { id: userId },
|
||||
} = req.auth;
|
||||
const { id: websiteId } = req.query;
|
||||
|
||||
if (req.method === 'POST') {
|
||||
if (!(await allowQuery(req, UmamiApi.AuthType.Website))) {
|
||||
if (canViewWebsite(userId, websiteId)) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
const { id: websiteId } = req.query;
|
||||
|
||||
const { start_at, end_at, event_name: eventName, columns, filters } = req.body;
|
||||
|
||||
const startDate = new Date(+start_at);
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { WebsiteMetric } from 'interface/api/models';
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { allowQuery } from 'lib/auth';
|
||||
import { UmamiApi } from 'lib/constants';
|
||||
import { canViewWebsite } from 'lib/auth';
|
||||
import { useAuth, useCors } from 'lib/middleware';
|
||||
import moment from 'moment-timezone';
|
||||
import { NextApiResponse } from 'next';
|
||||
@ -27,13 +26,16 @@ export default async (
|
||||
await useCors(req, res);
|
||||
await useAuth(req, res);
|
||||
|
||||
const {
|
||||
user: { id: userId },
|
||||
} = req.auth;
|
||||
const { id: websiteId, start_at, end_at, unit, tz, url, event_name } = req.query;
|
||||
|
||||
if (req.method === 'GET') {
|
||||
if (!(await allowQuery(req, UmamiApi.AuthType.Website))) {
|
||||
if (canViewWebsite(userId, websiteId)) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
const { id: websiteId, start_at, end_at, unit, tz, url, event_name } = req.query;
|
||||
|
||||
if (!moment.tz.zone(tz) || !unitTypes.includes(unit)) {
|
||||
return badRequest(res);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Website } from 'interface/api/models';
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { canViewWebsite, canUpdateWebsite } from 'lib/auth';
|
||||
import { canViewWebsite, canUpdateWebsite, canDeleteWebsite } from 'lib/auth';
|
||||
import { useAuth, useCors } from 'lib/middleware';
|
||||
import { NextApiResponse } from 'next';
|
||||
import { methodNotAllowed, ok, serverError, unauthorized } from 'next-basics';
|
||||
@ -23,10 +23,13 @@ export default async (
|
||||
await useCors(req, res);
|
||||
await useAuth(req, res);
|
||||
|
||||
const {
|
||||
user: { id: userId },
|
||||
} = req.auth;
|
||||
const { id: websiteId } = req.query;
|
||||
|
||||
if (req.method === 'GET') {
|
||||
if (!(await canViewWebsite(req.auth.user.id, websiteId))) {
|
||||
if (!(await canViewWebsite(userId, websiteId))) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
@ -36,7 +39,7 @@ export default async (
|
||||
}
|
||||
|
||||
if (req.method === 'POST') {
|
||||
if (!(await canUpdateWebsite(req.auth.user.id, websiteId))) {
|
||||
if (!(await canUpdateWebsite(userId, websiteId))) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
@ -54,6 +57,10 @@ export default async (
|
||||
}
|
||||
|
||||
if (req.method === 'DELETE') {
|
||||
if (!(await canDeleteWebsite(userId, websiteId))) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
await deleteWebsite(websiteId);
|
||||
|
||||
return ok(res);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { WebsiteMetric } from 'interface/api/models';
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { allowQuery } from 'lib/auth';
|
||||
import { FILTER_IGNORED, UmamiApi } from 'lib/constants';
|
||||
import { canViewWebsite } from 'lib/auth';
|
||||
import { FILTER_IGNORED } from 'lib/constants';
|
||||
import { useAuth, useCors } from 'lib/middleware';
|
||||
import { NextApiResponse } from 'next';
|
||||
import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||
@ -56,24 +56,27 @@ export default async (
|
||||
await useCors(req, res);
|
||||
await useAuth(req, res);
|
||||
|
||||
const {
|
||||
user: { id: userId },
|
||||
} = req.auth;
|
||||
const {
|
||||
id: websiteId,
|
||||
type,
|
||||
start_at,
|
||||
end_at,
|
||||
url,
|
||||
referrer,
|
||||
os,
|
||||
browser,
|
||||
device,
|
||||
country,
|
||||
} = req.query;
|
||||
|
||||
if (req.method === 'GET') {
|
||||
if (!(await allowQuery(req, UmamiApi.AuthType.Website))) {
|
||||
if (!(await canViewWebsite(userId, websiteId))) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
const {
|
||||
id: websiteId,
|
||||
type,
|
||||
start_at,
|
||||
end_at,
|
||||
url,
|
||||
referrer,
|
||||
os,
|
||||
browser,
|
||||
device,
|
||||
country,
|
||||
} = req.query;
|
||||
|
||||
const startDate = new Date(+start_at);
|
||||
const endDate = new Date(+end_at);
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { WebsitePageviews } from 'interface/api/models';
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { allowQuery } from 'lib/auth';
|
||||
import { UmamiApi } from 'lib/constants';
|
||||
import { canViewWebsite } from 'lib/auth';
|
||||
import { useAuth, useCors } from 'lib/middleware';
|
||||
import moment from 'moment-timezone';
|
||||
import { NextApiResponse } from 'next';
|
||||
@ -32,25 +31,28 @@ export default async (
|
||||
await useCors(req, res);
|
||||
await useAuth(req, res);
|
||||
|
||||
const {
|
||||
user: { id: userId },
|
||||
} = req.auth;
|
||||
const {
|
||||
id: websiteId,
|
||||
start_at,
|
||||
end_at,
|
||||
unit,
|
||||
tz,
|
||||
url,
|
||||
referrer,
|
||||
os,
|
||||
browser,
|
||||
device,
|
||||
country,
|
||||
} = req.query;
|
||||
|
||||
if (req.method === 'GET') {
|
||||
if (!(await allowQuery(req, UmamiApi.AuthType.Website))) {
|
||||
if (!(await canViewWebsite(userId, websiteId))) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
const {
|
||||
id: websiteId,
|
||||
start_at,
|
||||
end_at,
|
||||
unit,
|
||||
tz,
|
||||
url,
|
||||
referrer,
|
||||
os,
|
||||
browser,
|
||||
device,
|
||||
country,
|
||||
} = req.query;
|
||||
|
||||
const startDate = new Date(+start_at);
|
||||
const endDate = new Date(+end_at);
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { allowQuery } from 'lib/auth';
|
||||
import { UmamiApi } from 'lib/constants';
|
||||
import { canViewWebsite } from 'lib/auth';
|
||||
import { useAuth, useCors } from 'lib/middleware';
|
||||
import { NextApiResponse } from 'next';
|
||||
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||
@ -17,10 +16,13 @@ export default async (
|
||||
await useCors(req, res);
|
||||
await useAuth(req, res);
|
||||
|
||||
const {
|
||||
user: { id: userId },
|
||||
} = req.auth;
|
||||
const { id: websiteId } = req.query;
|
||||
|
||||
if (req.method === 'POST') {
|
||||
if (!(await allowQuery(req, UmamiApi.AuthType.Website))) {
|
||||
if (!(await canViewWebsite(userId, websiteId))) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { WebsiteStats } from 'interface/api/models';
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { allowQuery } from 'lib/auth';
|
||||
import { UmamiApi } from 'lib/constants';
|
||||
import { canViewWebsite } from 'lib/auth';
|
||||
import { useAuth, useCors } from 'lib/middleware';
|
||||
import { NextApiResponse } from 'next';
|
||||
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||
@ -27,23 +26,26 @@ export default async (
|
||||
await useCors(req, res);
|
||||
await useAuth(req, res);
|
||||
|
||||
const {
|
||||
user: { id: userId },
|
||||
} = req.auth;
|
||||
const {
|
||||
id: websiteId,
|
||||
start_at,
|
||||
end_at,
|
||||
url,
|
||||
referrer,
|
||||
os,
|
||||
browser,
|
||||
device,
|
||||
country,
|
||||
} = req.query;
|
||||
|
||||
if (req.method === 'GET') {
|
||||
if (!(await allowQuery(req, UmamiApi.AuthType.Website))) {
|
||||
if (!(await canViewWebsite(userId, websiteId))) {
|
||||
return unauthorized(res);
|
||||
}
|
||||
|
||||
const {
|
||||
id: websiteId,
|
||||
start_at,
|
||||
end_at,
|
||||
url,
|
||||
referrer,
|
||||
os,
|
||||
browser,
|
||||
device,
|
||||
country,
|
||||
} = req.query;
|
||||
|
||||
const startDate = new Date(+start_at);
|
||||
const endDate = new Date(+end_at);
|
||||
|
||||
|
@ -1,12 +1,11 @@
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { NextApiRequestQueryBody } from 'interface/api/nextApi';
|
||||
import { checkAdmin } from 'lib/auth';
|
||||
import { uuid } from 'lib/crypto';
|
||||
import { useAuth, useCors } from 'lib/middleware';
|
||||
import { NextApiResponse } from 'next';
|
||||
import { methodNotAllowed, ok } from 'next-basics';
|
||||
import { createWebsite, getAllWebsites, getWebsitesByUserId } from 'queries';
|
||||
import { checkPermission } from 'lib/auth';
|
||||
import { UmamiApi } from 'lib/constants';
|
||||
|
||||
export interface WebsitesRequestQuery {
|
||||
include_all?: boolean;
|
||||
@ -33,7 +32,7 @@ export default async (
|
||||
if (req.method === 'GET') {
|
||||
const { include_all } = req.query;
|
||||
|
||||
const isAdmin = await checkPermission(req, UmamiApi.Permission.Admin);
|
||||
const isAdmin = await checkAdmin(userId);
|
||||
|
||||
const websites =
|
||||
isAdmin && include_all ? await getAllWebsites() : await getWebsitesByUserId(userId);
|
||||
@ -44,7 +43,7 @@ export default async (
|
||||
if (req.method === 'POST') {
|
||||
const { name, domain, shareId, teamId } = req.body;
|
||||
|
||||
const data: Prisma.WebsiteCreateInput = {
|
||||
const data: Prisma.WebsiteUncheckedCreateInput = {
|
||||
id: uuid(),
|
||||
name,
|
||||
domain,
|
||||
|
@ -1,83 +0,0 @@
|
||||
import { Prisma, Permission } from '@prisma/client';
|
||||
import prisma from 'lib/prisma';
|
||||
|
||||
export async function createPermission(data: Prisma.PermissionCreateInput): Promise<Permission> {
|
||||
return prisma.client.permission.create({
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export async function getPermission(where: Prisma.PermissionWhereUniqueInput): Promise<Permission> {
|
||||
return prisma.client.permission.findUnique({
|
||||
where,
|
||||
});
|
||||
}
|
||||
|
||||
export async function getPermissions(where: Prisma.PermissionWhereInput): Promise<Permission[]> {
|
||||
return prisma.client.permission.findMany({
|
||||
where,
|
||||
});
|
||||
}
|
||||
|
||||
export async function getPermissionsByUserId(userId, name?: string): Promise<Permission[]> {
|
||||
return prisma.client.permission.findMany({
|
||||
where: {
|
||||
...(name ? { name } : {}),
|
||||
RolePermission: {
|
||||
every: {
|
||||
role: {
|
||||
is: {
|
||||
userRoles: {
|
||||
every: {
|
||||
userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function getPermissionsByTeamId(teamId, name?: string): Promise<Permission[]> {
|
||||
return prisma.client.permission.findMany({
|
||||
where: {
|
||||
...(name ? { name } : {}),
|
||||
RolePermission: {
|
||||
every: {
|
||||
role: {
|
||||
is: {
|
||||
TeamUser: {
|
||||
every: {
|
||||
teamId,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function updatePermission(
|
||||
data: Prisma.PermissionUpdateInput,
|
||||
where: Prisma.PermissionWhereUniqueInput,
|
||||
): Promise<Permission> {
|
||||
return prisma.client.permission.update({
|
||||
data,
|
||||
where,
|
||||
});
|
||||
}
|
||||
|
||||
export async function deletePermission(permissionId: string): Promise<Permission> {
|
||||
return prisma.client.permission.update({
|
||||
data: {
|
||||
isDeleted: true,
|
||||
},
|
||||
where: {
|
||||
id: permissionId,
|
||||
},
|
||||
});
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
import { Prisma, Role } from '@prisma/client';
|
||||
import prisma from 'lib/prisma';
|
||||
|
||||
export async function createRole(data: {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
}): Promise<Role> {
|
||||
return prisma.client.role.create({
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export async function getRole(where: Prisma.RoleWhereUniqueInput): Promise<Role> {
|
||||
return prisma.client.role.findUnique({
|
||||
where,
|
||||
});
|
||||
}
|
||||
|
||||
export async function getRoles(where: Prisma.RoleWhereInput): Promise<Role[]> {
|
||||
return prisma.client.role.findMany({
|
||||
where,
|
||||
});
|
||||
}
|
||||
|
||||
export async function getRolesByUserId(userId: string): Promise<Role[]> {
|
||||
return prisma.client.role.findMany({
|
||||
where: {
|
||||
userRoles: {
|
||||
every: {
|
||||
userId,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateRole(
|
||||
data: Prisma.RoleUpdateInput,
|
||||
where: Prisma.RoleWhereUniqueInput,
|
||||
): Promise<Role> {
|
||||
return prisma.client.role.update({
|
||||
data,
|
||||
where,
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteRole(roleId: string): Promise<Role> {
|
||||
return prisma.client.role.update({
|
||||
data: {
|
||||
isDeleted: true,
|
||||
},
|
||||
where: {
|
||||
id: roleId,
|
||||
},
|
||||
});
|
||||
}
|
@ -5,14 +5,14 @@ import prisma from 'lib/prisma';
|
||||
export async function createTeamUser(
|
||||
userId: string,
|
||||
teamId: string,
|
||||
roleId: string,
|
||||
role: string,
|
||||
): Promise<TeamUser> {
|
||||
return prisma.client.teamUser.create({
|
||||
data: {
|
||||
id: uuid(),
|
||||
userId,
|
||||
teamId,
|
||||
roleId,
|
||||
role,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -36,9 +36,7 @@ export async function getUser(
|
||||
id: true,
|
||||
username: true,
|
||||
userRole: {
|
||||
include: {
|
||||
role: true,
|
||||
},
|
||||
select: { role: true },
|
||||
},
|
||||
password: includePassword,
|
||||
},
|
||||
|
@ -19,7 +19,10 @@ export async function createWebsite(
|
||||
});
|
||||
}
|
||||
|
||||
export async function updateWebsite(websiteId, data: Prisma.WebsiteUpdateInput): Promise<Website> {
|
||||
export async function updateWebsite(
|
||||
websiteId,
|
||||
data: Prisma.WebsiteUpdateInput | Prisma.WebsiteUncheckedUpdateInput,
|
||||
): Promise<Website> {
|
||||
return prisma.client.website.update({
|
||||
where: {
|
||||
id: websiteId,
|
||||
@ -97,7 +100,9 @@ export async function deleteWebsite(websiteId: string) {
|
||||
});
|
||||
}
|
||||
|
||||
async function deleteWebsiteRelationalQuery(websiteId,): Promise<[Prisma.BatchPayload, Prisma.BatchPayload, Website]> {
|
||||
async function deleteWebsiteRelationalQuery(
|
||||
websiteId,
|
||||
): Promise<[Prisma.BatchPayload, Prisma.BatchPayload, Website]> {
|
||||
const { client, transaction } = prisma;
|
||||
|
||||
return transaction([
|
||||
|
@ -1,5 +1,3 @@
|
||||
export * from './admin/permission';
|
||||
export * from './admin/role';
|
||||
export * from './admin/team';
|
||||
export * from './admin/teamUser';
|
||||
export * from './admin/user';
|
||||
|
Loading…
Reference in New Issue
Block a user