diff --git a/assets/arrow-right.svg b/assets/arrow-right.svg
index 6fc93909..efc5d74a 100644
--- a/assets/arrow-right.svg
+++ b/assets/arrow-right.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/arrow-up-right-from-square.svg b/assets/arrow-up-right-from-square.svg
index 90ad457f..8f6de672 100644
--- a/assets/arrow-up-right-from-square.svg
+++ b/assets/arrow-up-right-from-square.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/bars.svg b/assets/bars.svg
index fdb2d6e4..ba383fa4 100644
--- a/assets/bars.svg
+++ b/assets/bars.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/chart-bar.svg b/assets/chart-bar.svg
index d1d72fdc..36820b76 100644
--- a/assets/chart-bar.svg
+++ b/assets/chart-bar.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/check.svg b/assets/check.svg
index 1a7abdce..65810c19 100644
--- a/assets/check.svg
+++ b/assets/check.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/chevron-down.svg b/assets/chevron-down.svg
index cb9d8fe1..69add632 100644
--- a/assets/chevron-down.svg
+++ b/assets/chevron-down.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/code.svg b/assets/code.svg
index cd29765e..0f8e0814 100644
--- a/assets/code.svg
+++ b/assets/code.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/external-link.svg b/assets/external-link.svg
index ed09306f..e24896b0 100644
--- a/assets/external-link.svg
+++ b/assets/external-link.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/gear.svg b/assets/gear.svg
index ab97a693..47805d46 100644
--- a/assets/gear.svg
+++ b/assets/gear.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/logo.svg b/assets/logo.svg
index f0e52261..d2c71326 100644
--- a/assets/logo.svg
+++ b/assets/logo.svg
@@ -1,2 +1 @@
-
-
+
\ No newline at end of file
diff --git a/assets/moon.svg b/assets/moon.svg
index 6c8955ae..638286fd 100644
--- a/assets/moon.svg
+++ b/assets/moon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/pen.svg b/assets/pen.svg
index 426c520c..b2979420 100644
--- a/assets/pen.svg
+++ b/assets/pen.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/sun.svg b/assets/sun.svg
index ebc20eb2..3e487291 100644
--- a/assets/sun.svg
+++ b/assets/sun.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/times.svg b/assets/times.svg
index c528bcdd..261bb277 100644
--- a/assets/times.svg
+++ b/assets/times.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/user.svg b/assets/user.svg
index c0094666..62df2c42 100644
--- a/assets/user.svg
+++ b/assets/user.svg
@@ -1 +1 @@
-Asset 1
\ No newline at end of file
+
\ No newline at end of file
diff --git a/assets/xmark.svg b/assets/xmark.svg
index 340f479e..83bd5740 100644
--- a/assets/xmark.svg
+++ b/assets/xmark.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/components/layout/Layout.js b/components/layout/Layout.js
index 2c097e41..0e4b2b61 100644
--- a/components/layout/Layout.js
+++ b/components/layout/Layout.js
@@ -1,4 +1,3 @@
-import React from 'react';
import Head from 'next/head';
import Header from 'components/layout/Header';
import Footer from 'components/layout/Footer';
@@ -10,9 +9,8 @@ export default function Layout({ title, children, header = true, footer = true }
return (
<>
- umami{title && ` - ${title}`}
+ {title ? `${title} | umami` : 'umami'}
-
{header && }
{children}
{footer && }
diff --git a/components/pages/WebsiteDetails.js b/components/pages/WebsiteDetails.js
index b40bc9ee..d4127f7f 100644
--- a/components/pages/WebsiteDetails.js
+++ b/components/pages/WebsiteDetails.js
@@ -8,7 +8,6 @@ import GridLayout, { GridRow, GridColumn } from 'components/layout/GridLayout';
import MenuLayout from 'components/layout/MenuLayout';
import Link from 'components/common/Link';
import Loading from 'components/common/Loading';
-import Arrow from 'assets/arrow-right.svg';
import PagesTable from 'components/metrics/PagesTable';
import ReferrersTable from 'components/metrics/ReferrersTable';
import BrowsersTable from 'components/metrics/BrowsersTable';
@@ -20,11 +19,12 @@ import EventsTable from 'components/metrics/EventsTable';
import EventsChart from 'components/metrics/EventsChart';
import ScreenTable from 'components/metrics/ScreenTable';
import QueryParametersTable from 'components/metrics/QueryParametersTable';
+import EventDataButton from 'components/common/EventDataButton';
import useFetch from 'hooks/useFetch';
import usePageQuery from 'hooks/usePageQuery';
import { DEFAULT_ANIMATION_DURATION } from 'lib/constants';
+import Arrow from 'assets/arrow-right.svg';
import styles from './WebsiteDetails.module.css';
-import EventDataButton from 'components/common/EventDataButton';
const messages = defineMessages({
pages: { id: 'metrics.pages', defaultMessage: 'Pages' },
diff --git a/interface/api/auth.d.ts b/interface/api/auth.d.ts
deleted file mode 100644
index 6e4e3494..00000000
--- a/interface/api/auth.d.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface Auth {
- user: {
- id: string;
- username: string;
- isAdmin: boolean;
- };
- shareToken: string;
-}
diff --git a/interface/api/models.d.ts b/interface/api/models.d.ts
deleted file mode 100644
index 3359a651..00000000
--- a/interface/api/models.d.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-export interface Website {
- id: string;
- userId: string;
- revId: number;
- name: string;
- domain: string;
- shareId: string;
- createdAt: Date;
-}
-
-export interface Share {
- id: string;
- token: string;
-}
-
-export interface Empty {}
-
-export interface WebsiteActive {
- x: number;
-}
-
-export interface WebsiteEventDataMetric {
- [key: string]: number;
-}
-
-export interface WebsiteMetric {
- x: string;
- y: number;
-}
-
-export interface WebsiteEventMetric {
- x: string;
- t: string;
- y: number;
-}
-
-export interface WebsitePageviews {
- pageviews: {
- t: string;
- y: number;
- };
- sessions: {
- t: string;
- y: number;
- };
-}
-
-export interface WebsiteStats {
- pageviews: { value: number; change: number };
- uniques: { value: number; change: number };
- bounces: { value: number; change: number };
- totalTime: { value: number; change: number };
-}
-
-export interface RealtimeInit {
- websites: Website[];
- token: string;
- data: RealtimeUpdate;
-}
-
-export interface RealtimeUpdate {
- pageviews: any[];
- sessions: any[];
- events: any[];
- timestamp: number;
-}
diff --git a/interface/api/nextApi.d.ts b/interface/api/nextApi.d.ts
deleted file mode 100644
index c5a54515..00000000
--- a/interface/api/nextApi.d.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { NextApiRequest } from 'next';
-import { Auth } from './auth';
-
-export interface NextApiRequestQueryBody extends NextApiRequest {
- auth?: Auth;
- query: TQuery & { [key: string]: string | string[] };
- body: TBody;
- headers: any;
-}
-
-export interface NextApiRequestAuth extends NextApiRequest {
- auth?: Auth;
- headers: any;
-}
diff --git a/interface/index.d.ts b/interface/index.d.ts
deleted file mode 100644
index e69de29b..00000000
diff --git a/lib/auth.ts b/lib/auth.ts
index 90515f85..7ba778c7 100644
--- a/lib/auth.ts
+++ b/lib/auth.ts
@@ -1,11 +1,9 @@
-import { parseSecureToken, parseToken } from 'next-basics';
-import { UserRole } from '@prisma/client';
+import { parseSecureToken, parseToken, ensureArray } from 'next-basics';
import debug from 'debug';
import cache from 'lib/cache';
-import { SHARE_TOKEN_HEADER } from 'lib/constants';
+import { SHARE_TOKEN_HEADER, PERMISSIONS, ROLE_PERMISSIONS } from 'lib/constants';
import { secret } from 'lib/crypto';
-import { Permission, Roles } from 'lib/types';
-import { getTeamUser, getUserRoles } from 'queries';
+import { getTeamUser } from 'queries';
const log = debug('umami:auth');
@@ -58,12 +56,10 @@ export async function canViewWebsite(userId: string, websiteId: string) {
}
if (website.teamId) {
- const teamUser = await getTeamUser({ userId, teamId: website.teamId });
-
- checkPermission(Permission.websiteUpdate, teamUser.role);
+ return getTeamUser(website.teamId, userId);
}
- return checkAdmin(userId);
+ return false;
}
export async function canUpdateWebsite(userId: string, websiteId: string) {
@@ -74,12 +70,12 @@ export async function canUpdateWebsite(userId: string, websiteId: string) {
}
if (website.teamId) {
- const teamUser = await getTeamUser({ userId, teamId: website.teamId });
+ const teamUser = await getTeamUser(website.teamId, userId);
- checkPermission(Permission.websiteUpdate, teamUser.role);
+ return hasPermission(teamUser.role, PERMISSIONS.websiteUpdate);
}
- return checkAdmin(userId);
+ return false;
}
export async function canDeleteWebsite(userId: string, websiteId: string) {
@@ -90,14 +86,12 @@ export async function canDeleteWebsite(userId: string, websiteId: string) {
}
if (website.teamId) {
- const teamUser = await getTeamUser({ userId, teamId: website.teamId });
+ const teamUser = await getTeamUser(website.teamId, userId);
- if (checkPermission(Permission.websiteDelete, teamUser.role)) {
- return true;
- }
+ return hasPermission(teamUser.role, PERMISSIONS.websiteDelete);
}
- return checkAdmin(userId);
+ return false;
}
// To-do: Implement when payments are setup.
@@ -107,66 +101,29 @@ export async function canCreateTeam(userId: string) {
// To-do: Implement when payments are setup.
export async function canViewTeam(userId: string, teamId) {
- const teamUser = await getTeamUser({ userId, teamId });
- return !!teamUser;
+ return getTeamUser(teamId, userId);
}
export async function canUpdateTeam(userId: string, teamId: string) {
- const teamUser = await getTeamUser({ userId, teamId });
+ const teamUser = await getTeamUser(teamId, userId);
- if (checkPermission(Permission.teamUpdate, teamUser.role)) {
- return true;
- }
+ return hasPermission(teamUser.role, PERMISSIONS.teamUpdate);
}
export async function canDeleteTeam(userId: string, teamId: string) {
- const teamUser = await getTeamUser({ userId, teamId });
+ const teamUser = await getTeamUser(teamId, userId);
- if (checkPermission(Permission.teamDelete, teamUser.role)) {
- return true;
- }
-}
-
-export async function canCreateUser(userId: string) {
- return checkAdmin(userId);
+ return hasPermission(teamUser.role, PERMISSIONS.teamDelete);
}
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);
+ return userId === viewedUserId;
}
export async function canUpdateUser(userId: string, viewedUserId: string) {
- if (userId === viewedUserId) {
- return true;
- }
-
- return checkAdmin(userId);
+ return userId === viewedUserId;
}
-export async function canUpdateUserRole(userId: string) {
- return checkAdmin(userId);
-}
-
-export async function canDeleteUser(userId: string) {
- return checkAdmin(userId);
-}
-
-export async function checkPermission(permission: Permission, role: string) {
- return 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 === Roles.admin.name);
+export async function hasPermission(role: string, permission: string | string[]) {
+ return ensureArray(permission).some(e => ROLE_PERMISSIONS[role]?.includes(e));
}
diff --git a/lib/constants.ts b/lib/constants.ts
index e766791b..54933d53 100644
--- a/lib/constants.ts
+++ b/lib/constants.ts
@@ -22,6 +22,52 @@ export const DEFAULT_WEBSITE_LIMIT = 10;
export const REALTIME_RANGE = 30;
export const REALTIME_INTERVAL = 3000;
+export const EVENT_TYPE = {
+ pageView: 1,
+ customEvent: 2,
+};
+
+export const ROLES = {
+ admin: 'admin',
+ user: 'user',
+ teamOwner: 'team-owner',
+ teamMember: 'team-member',
+ teamGuest: 'team-guest',
+};
+
+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 ROLE_PERMISSIONS = {
+ [ROLES.admin]: [PERMISSIONS.all],
+ [ROLES.user]: [
+ PERMISSIONS.websiteCreate,
+ PERMISSIONS.websiteUpdate,
+ PERMISSIONS.websiteDelete,
+ PERMISSIONS.teamCreate,
+ ],
+ [ROLES.teamOwner]: [
+ PERMISSIONS.teamUpdate,
+ PERMISSIONS.teamDelete,
+ PERMISSIONS.websiteCreate,
+ PERMISSIONS.websiteUpdate,
+ PERMISSIONS.websiteDelete,
+ ],
+ [ROLES.teamMember]: [
+ PERMISSIONS.websiteCreate,
+ PERMISSIONS.websiteUpdate,
+ PERMISSIONS.websiteDelete,
+ ],
+ [ROLES.teamGuest]: [],
+};
+
export const THEME_COLORS = {
light: {
primary: '#2680eb',
diff --git a/lib/middleware.js b/lib/middleware.js
index 5bdad75d..9d1498c7 100644
--- a/lib/middleware.js
+++ b/lib/middleware.js
@@ -6,6 +6,7 @@ import { findSession } from 'lib/session';
import { getAuthToken, parseShareToken } from 'lib/auth';
import { secret } from 'lib/crypto';
import redis from 'lib/redis';
+import { ROLES } from 'lib/constants';
import { getUser } from '../queries';
const log = debug('umami:middleware');
@@ -45,6 +46,10 @@ export const useAuth = createMiddleware(async (req, res, next) => {
return unauthorized(res);
}
+ if (user) {
+ user.isAdmin = user.role === ROLES.admin;
+ }
+
req.auth = { user, token, shareToken, key };
next();
});
diff --git a/lib/redis.js b/lib/redis.js
index fe236feb..02eb9424 100644
--- a/lib/redis.js
+++ b/lib/redis.js
@@ -32,8 +32,6 @@ async function get(key) {
const data = await redis.get(key);
- log({ key, data });
-
try {
return JSON.parse(data);
} catch {
diff --git a/lib/session.js b/lib/session.js
index ad9f75b8..153b524c 100644
--- a/lib/session.js
+++ b/lib/session.js
@@ -40,7 +40,7 @@ export async function findSession(req) {
website = await getWebsite({ id: websiteId });
}
- if (!website || website.isDeleted) {
+ if (!website || website.deletedAt) {
throw new Error(`Website not found: ${websiteId}`);
}
diff --git a/lib/types.ts b/lib/types.ts
index 425b5442..007d6fdb 100644
--- a/lib/types.ts
+++ b/lib/types.ts
@@ -1,57 +1,90 @@
-/* eslint-disable no-unused-vars */
-export enum EventType {
- Pageview = 1,
- Event = 2,
+import { NextApiRequest } from 'next';
+
+export interface Auth {
+ user?: {
+ id: string;
+ username: string;
+ role: string;
+ isAdmin: boolean;
+ };
+ shareToken?: string;
}
-export enum AuthType {
- Website,
- User,
- Team,
+export interface NextApiRequestQueryBody extends NextApiRequest {
+ auth?: Auth;
+ query: TQuery & { [key: string]: string | string[] };
+ body: TBody;
+ headers: any;
}
-export enum Permission {
- all = 'all',
- websiteCreate = 'website:create',
- websiteUpdate = 'website:update',
- websiteDelete = 'website:delete',
- teamCreate = 'team:create',
- teamUpdate = 'team:update',
- teamDelete = 'team:delete',
+export interface NextApiRequestAuth extends NextApiRequest {
+ auth?: Auth;
+ headers: any;
}
-export enum Role {
- Admin = 'admin',
- User = 'user',
- TeamOwner = 'team-owner',
- TeamMember = 'team-member',
- TeamGuest = 'team-guest',
+export interface Website {
+ id: string;
+ userId: string;
+ revId: number;
+ name: string;
+ domain: string;
+ shareId: string;
+ createdAt: Date;
}
-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 interface Share {
+ id: string;
+ token: string;
+}
+
+export interface Empty {}
+
+export interface WebsiteActive {
+ x: number;
+}
+
+export interface WebsiteEventDataMetric {
+ [key: string]: number;
+}
+
+export interface WebsiteMetric {
+ x: string;
+ y: number;
+}
+
+export interface WebsiteEventMetric {
+ x: string;
+ t: string;
+ y: number;
+}
+
+export interface WebsitePageviews {
+ pageviews: {
+ t: string;
+ y: number;
+ };
+ sessions: {
+ t: string;
+ y: number;
+ };
+}
+
+export interface WebsiteStats {
+ pageviews: { value: number; change: number };
+ uniques: { value: number; change: number };
+ bounces: { value: number; change: number };
+ totalTime: { value: number; change: number };
+}
+
+export interface RealtimeInit {
+ websites: Website[];
+ token: string;
+ data: RealtimeUpdate;
+}
+
+export interface RealtimeUpdate {
+ pageviews: any[];
+ sessions: any[];
+ events: any[];
+ timestamp: number;
+}
diff --git a/pages/api/auth/login.ts b/pages/api/auth/login.ts
index e23415a9..3e94a1c9 100644
--- a/pages/api/auth/login.ts
+++ b/pages/api/auth/login.ts
@@ -10,7 +10,7 @@ import {
import { getUser, User } from 'queries';
import { secret } from 'lib/crypto';
import redis from 'lib/redis';
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
+import { NextApiRequestQueryBody } from 'lib/types';
import { NextApiResponse } from 'next';
export interface LoginRequestBody {
diff --git a/pages/api/auth/verify.ts b/pages/api/auth/verify.ts
index 024cd96a..9eb9ea48 100644
--- a/pages/api/auth/verify.ts
+++ b/pages/api/auth/verify.ts
@@ -1,4 +1,4 @@
-import { NextApiRequestAuth } from 'interface/api/nextApi';
+import { NextApiRequestAuth } from 'lib/types';
import { useAuth } from 'lib/middleware';
import { NextApiResponse } from 'next';
import { ok } from 'next-basics';
diff --git a/pages/api/realtime/init.ts b/pages/api/realtime/init.ts
index 70aab0eb..5b399af5 100644
--- a/pages/api/realtime/init.ts
+++ b/pages/api/realtime/init.ts
@@ -1,6 +1,6 @@
import { subMinutes } from 'date-fns';
-import { RealtimeInit } from 'interface/api/models';
-import { NextApiRequestAuth } from 'interface/api/nextApi';
+import { RealtimeInit } from 'lib/types';
+import { NextApiRequestAuth } from 'lib/types';
import { secret } from 'lib/crypto';
import { useAuth } from 'lib/middleware';
import { NextApiResponse } from 'next';
diff --git a/pages/api/realtime/update.ts b/pages/api/realtime/update.ts
index 239ab1e6..9b99a282 100644
--- a/pages/api/realtime/update.ts
+++ b/pages/api/realtime/update.ts
@@ -3,9 +3,9 @@ import { useAuth } from 'lib/middleware';
import { getRealtimeData } from 'queries';
import { SHARE_TOKEN_HEADER } from 'lib/constants';
import { secret } from 'lib/crypto';
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
+import { NextApiRequestQueryBody } from 'lib/types';
import { NextApiResponse } from 'next';
-import { RealtimeUpdate } from 'interface/api/models';
+import { RealtimeUpdate } from 'lib/types';
export interface InitUpdateRequestQuery {
start_at: string;
diff --git a/pages/api/share/[id].ts b/pages/api/share/[id].ts
index 51385bee..b8a37e25 100644
--- a/pages/api/share/[id].ts
+++ b/pages/api/share/[id].ts
@@ -1,4 +1,4 @@
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
+import { NextApiRequestQueryBody } from 'lib/types';
import { secret } from 'lib/crypto';
import { NextApiResponse } from 'next';
import { createToken, methodNotAllowed, notFound, ok } from 'next-basics';
diff --git a/pages/api/teams/[id]/index.ts b/pages/api/teams/[id]/index.ts
index 65a344c5..a3ccd0b6 100644
--- a/pages/api/teams/[id]/index.ts
+++ b/pages/api/teams/[id]/index.ts
@@ -1,5 +1,5 @@
import { Team } from '@prisma/client';
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
+import { NextApiRequestQueryBody } from 'lib/types';
import { canDeleteTeam, canUpdateTeam, canViewTeam } from 'lib/auth';
import { useAuth } from 'lib/middleware';
import { NextApiResponse } from 'next';
@@ -26,7 +26,7 @@ export default async (
const { id: teamId } = req.query;
if (req.method === 'GET') {
- if (await canViewTeam(userId, teamId)) {
+ if (!(await canViewTeam(userId, teamId))) {
return unauthorized(res);
}
@@ -38,7 +38,7 @@ export default async (
if (req.method === 'POST') {
const { name } = req.body;
- if (await canUpdateTeam(userId, teamId)) {
+ if (!(await canUpdateTeam(userId, teamId))) {
return unauthorized(res, 'You must be the owner of this team.');
}
@@ -48,7 +48,7 @@ export default async (
}
if (req.method === 'DELETE') {
- if (await canDeleteTeam(userId, teamId)) {
+ if (!(await canDeleteTeam(userId, teamId))) {
return unauthorized(res, 'You must be the owner of this team.');
}
diff --git a/pages/api/teams/[id]/user.ts b/pages/api/teams/[id]/users.ts
similarity index 81%
rename from pages/api/teams/[id]/user.ts
rename to pages/api/teams/[id]/users.ts
index 8b6aaf30..f0e34165 100644
--- a/pages/api/teams/[id]/user.ts
+++ b/pages/api/teams/[id]/users.ts
@@ -1,9 +1,9 @@
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
+import { NextApiRequestQueryBody } from 'lib/types';
import { canUpdateTeam, canViewTeam } from 'lib/auth';
import { useAuth } from 'lib/middleware';
import { NextApiResponse } from 'next';
import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics';
-import { createTeamUser, deleteTeamUser, getUser, getUsersByTeamId } from 'queries';
+import { createTeamUser, deleteTeamUser, getUser, getTeamUsers } from 'queries';
export interface TeamUserRequestQuery {
id: string;
@@ -27,17 +27,17 @@ export default async (
const { id: teamId } = req.query;
if (req.method === 'GET') {
- if (await canViewTeam(userId, teamId)) {
+ if (!(await canViewTeam(userId, teamId))) {
return unauthorized(res);
}
- const user = await getUsersByTeamId({ teamId });
+ const users = await getTeamUsers(teamId);
- return ok(res, user);
+ return ok(res, users);
}
if (req.method === 'POST') {
- if (await canUpdateTeam(userId, teamId)) {
+ if (!(await canUpdateTeam(userId, teamId))) {
return unauthorized(res, 'You must be the owner of this team.');
}
diff --git a/pages/api/teams/[id]/website.ts b/pages/api/teams/[id]/websites.ts
similarity index 78%
rename from pages/api/teams/[id]/website.ts
rename to pages/api/teams/[id]/websites.ts
index 3d959e70..d1f22da8 100644
--- a/pages/api/teams/[id]/website.ts
+++ b/pages/api/teams/[id]/websites.ts
@@ -1,9 +1,9 @@
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
-import { canViewTeam } from 'lib/auth';
-import { useAuth } from 'lib/middleware';
import { NextApiResponse } from 'next';
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
-import { getWebsitesByTeamId } from 'queries';
+import { NextApiRequestQueryBody } from 'lib/types';
+import { canViewTeam } from 'lib/auth';
+import { useAuth } from 'lib/middleware';
+import { getTeamWebsites } from 'queries/admin/team';
export interface TeamWebsiteRequestQuery {
id: string;
@@ -30,9 +30,9 @@ export default async (
return unauthorized(res);
}
- const website = await getWebsitesByTeamId({ teamId });
+ const websites = await getTeamWebsites(teamId);
- return ok(res, website);
+ return ok(res, websites);
}
return methodNotAllowed(res);
diff --git a/pages/api/teams/index.ts b/pages/api/teams/index.ts
index 2831d07d..46cf65a9 100644
--- a/pages/api/teams/index.ts
+++ b/pages/api/teams/index.ts
@@ -1,14 +1,14 @@
import { Team } from '@prisma/client';
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
+import { NextApiRequestQueryBody } from 'lib/types';
import { canCreateTeam } from 'lib/auth';
import { uuid } from 'lib/crypto';
import { useAuth } from 'lib/middleware';
import { NextApiResponse } from 'next';
-import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics';
-import { createTeam, getTeam, getTeamsByUserId } from 'queries';
+import { methodNotAllowed, ok, unauthorized } from 'next-basics';
+import { createTeam, getUserTeams } from 'queries';
+
export interface TeamsRequestBody {
name: string;
- description: string;
}
export default async (
@@ -22,27 +22,22 @@ export default async (
} = req.auth;
if (req.method === 'GET') {
- const teams = await getTeamsByUserId(userId);
+ const teams = await getUserTeams(userId);
return ok(res, teams);
}
if (req.method === 'POST') {
- if (await canCreateTeam(userId)) {
+ if (!(await canCreateTeam(userId))) {
return unauthorized(res);
}
const { name } = req.body;
- const team = await getTeam({ name });
-
- if (team) {
- return badRequest(res, 'Team already exists');
- }
-
const created = await createTeam({
id: uuid(),
name,
+ userId,
});
return ok(res, created);
diff --git a/pages/api/users/[id]/index.ts b/pages/api/users/[id]/index.ts
index d5215f23..cd0332d5 100644
--- a/pages/api/users/[id]/index.ts
+++ b/pages/api/users/[id]/index.ts
@@ -1,5 +1,5 @@
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
-import { canDeleteUser, canUpdateUser, canViewUser, checkAdmin } from 'lib/auth';
+import { NextApiRequestQueryBody } from 'lib/types';
+import { canUpdateUser, canViewUser } from 'lib/auth';
import { useAuth } from 'lib/middleware';
import { NextApiResponse } from 'next';
import { badRequest, hashPassword, methodNotAllowed, ok, unauthorized } from 'next-basics';
@@ -21,7 +21,7 @@ export default async (
await useAuth(req, res);
const {
- user: { id: userId },
+ user: { id: userId, isAdmin },
} = req.auth;
const { id } = req.query;
@@ -51,7 +51,7 @@ export default async (
}
// Only admin can change these fields
- if (username && (await checkAdmin(userId))) {
+ if (username && isAdmin) {
data.username = username;
}
@@ -70,7 +70,7 @@ export default async (
}
if (req.method === 'DELETE') {
- if (canDeleteUser(userId)) {
+ if (isAdmin) {
return unauthorized(res);
}
diff --git a/pages/api/users/[id]/password.ts b/pages/api/users/[id]/password.ts
index 5727cfbd..7a37d044 100644
--- a/pages/api/users/[id]/password.ts
+++ b/pages/api/users/[id]/password.ts
@@ -1,4 +1,4 @@
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
+import { NextApiRequestQueryBody } from 'lib/types';
import { canUpdateUser } from 'lib/auth';
import { useAuth } from 'lib/middleware';
import { NextApiResponse } from 'next';
diff --git a/pages/api/users/[id]/role.ts b/pages/api/users/[id]/role.ts
deleted file mode 100644
index 61238077..00000000
--- a/pages/api/users/[id]/role.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { UserRole } from '@prisma/client';
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
-import { canUpdateUserRole } from 'lib/auth';
-import { Role } from 'lib/types';
-import { useAuth } from 'lib/middleware';
-import { NextApiResponse } from 'next';
-import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics';
-import { deleteUserRole, getUserRole, getUserRoles, updateUserRole } from 'queries';
-
-export interface UserRoleRequestQuery {
- id: string;
-}
-export interface UserRoleRequestBody {
- role: Role;
- userRoleId?: string;
-}
-
-export default async (
- req: NextApiRequestQueryBody,
- res: NextApiResponse,
-) => {
- await useAuth(req, res);
-
- const {
- user: { id: userId },
- } = req.auth;
- const { id } = req.query;
-
- if (await canUpdateUserRole(userId)) {
- return unauthorized(res);
- }
-
- if (req.method === 'GET') {
- const userRole = await getUserRoles({ userId: id });
-
- return ok(res, userRole);
- }
-
- if (req.method === 'POST') {
- const { role } = req.body;
-
- const userRole = await getUserRole({ userId: id });
-
- 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);
- }
- }
-
- if (req.method === 'DELETE') {
- const { userRoleId } = req.body;
-
- const updated = await deleteUserRole(userRoleId);
-
- return ok(res, updated);
- }
-
- return methodNotAllowed(res);
-};
diff --git a/pages/api/users/[id]/websites.ts b/pages/api/users/[id]/websites.ts
new file mode 100644
index 00000000..bc79f91a
--- /dev/null
+++ b/pages/api/users/[id]/websites.ts
@@ -0,0 +1,57 @@
+import { Prisma } from '@prisma/client';
+import { NextApiRequestQueryBody } from 'lib/types';
+import { uuid } from 'lib/crypto';
+import { useAuth, useCors } from 'lib/middleware';
+import { NextApiResponse } from 'next';
+import { methodNotAllowed, ok } from 'next-basics';
+import { createWebsite, getUserWebsites } from 'queries';
+
+export interface WebsitesRequestQuery {}
+
+export interface WebsitesRequestBody {
+ name: string;
+ domain: string;
+ shareId: string;
+ teamId?: string;
+}
+
+export default async (
+ req: NextApiRequestQueryBody,
+ res: NextApiResponse,
+) => {
+ await useCors(req, res);
+ await useAuth(req, res);
+
+ const {
+ user: { id: userId },
+ } = req.auth;
+
+ if (req.method === 'GET') {
+ const websites = await getUserWebsites(userId);
+
+ return ok(res, websites);
+ }
+
+ if (req.method === 'POST') {
+ const { name, domain, shareId, teamId } = req.body;
+
+ const data: Prisma.WebsiteUncheckedCreateInput = {
+ id: uuid(),
+ name,
+ domain,
+ shareId,
+ };
+
+ if (teamId) {
+ data.teamId = teamId;
+ } else {
+ data.userId = userId;
+ }
+
+ const website = await createWebsite(data);
+
+ return ok(res, website);
+ }
+
+ return methodNotAllowed(res);
+};
diff --git a/pages/api/users/index.ts b/pages/api/users/index.ts
index b64c51ac..09f901c0 100644
--- a/pages/api/users/index.ts
+++ b/pages/api/users/index.ts
@@ -1,7 +1,7 @@
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
-import { canCreateUser, canViewUsers } from 'lib/auth';
+import { NextApiRequestQueryBody } from 'lib/types';
import { uuid } from 'lib/crypto';
import { useAuth } from 'lib/middleware';
+import { ROLES } from 'lib/constants';
import { NextApiResponse } from 'next';
import { badRequest, hashPassword, methodNotAllowed, ok, unauthorized } from 'next-basics';
import { createUser, getUser, getUsers, User } from 'queries';
@@ -19,11 +19,11 @@ export default async (
await useAuth(req, res);
const {
- user: { id: userId },
+ user: { isAdmin },
} = req.auth;
if (req.method === 'GET') {
- if (canViewUsers(userId)) {
+ if (isAdmin) {
return unauthorized(res);
}
@@ -33,15 +33,15 @@ export default async (
}
if (req.method === 'POST') {
- if (canCreateUser(userId)) {
+ if (isAdmin) {
return unauthorized(res);
}
const { username, password, id } = req.body;
- const user = await getUser({ username });
+ const existingUser = await getUser({ username });
- if (user) {
+ if (existingUser) {
return badRequest(res, 'User already exists');
}
@@ -49,6 +49,7 @@ export default async (
id: id || uuid(),
username,
password: hashPassword(password),
+ role: ROLES.user,
});
return ok(res, created);
diff --git a/pages/api/websites/[id]/active.ts b/pages/api/websites/[id]/active.ts
index 66b02d1d..1d007f7f 100644
--- a/pages/api/websites/[id]/active.ts
+++ b/pages/api/websites/[id]/active.ts
@@ -1,5 +1,5 @@
-import { WebsiteActive } from 'interface/api/models';
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
+import { WebsiteActive } from 'lib/types';
+import { NextApiRequestQueryBody } from 'lib/types';
import { canViewWebsite } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
import { NextApiResponse } from 'next';
diff --git a/pages/api/websites/[id]/eventdata.ts b/pages/api/websites/[id]/eventdata.ts
index e9df136f..1f884279 100644
--- a/pages/api/websites/[id]/eventdata.ts
+++ b/pages/api/websites/[id]/eventdata.ts
@@ -1,5 +1,5 @@
-import { WebsiteMetric } from 'interface/api/models';
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
+import { WebsiteMetric } from 'lib/types';
+import { NextApiRequestQueryBody } from 'lib/types';
import { canViewWebsite } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
import { NextApiResponse } from 'next';
diff --git a/pages/api/websites/[id]/events.ts b/pages/api/websites/[id]/events.ts
index c2c6a8cc..07880c21 100644
--- a/pages/api/websites/[id]/events.ts
+++ b/pages/api/websites/[id]/events.ts
@@ -1,5 +1,5 @@
-import { WebsiteMetric } from 'interface/api/models';
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
+import { WebsiteMetric } from 'lib/types';
+import { NextApiRequestQueryBody } from 'lib/types';
import { canViewWebsite } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
import moment from 'moment-timezone';
diff --git a/pages/api/websites/[id]/index.ts b/pages/api/websites/[id]/index.ts
index 9274d953..f160a8ab 100644
--- a/pages/api/websites/[id]/index.ts
+++ b/pages/api/websites/[id]/index.ts
@@ -1,5 +1,5 @@
-import { Website } from 'interface/api/models';
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
+import { Website } from 'lib/types';
+import { NextApiRequestQueryBody } from 'lib/types';
import { canViewWebsite, canUpdateWebsite, canDeleteWebsite } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
import { NextApiResponse } from 'next';
diff --git a/pages/api/websites/[id]/metrics.ts b/pages/api/websites/[id]/metrics.ts
index e84ff1fe..89ba12bf 100644
--- a/pages/api/websites/[id]/metrics.ts
+++ b/pages/api/websites/[id]/metrics.ts
@@ -1,5 +1,5 @@
-import { WebsiteMetric } from 'interface/api/models';
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
+import { WebsiteMetric } from 'lib/types';
+import { NextApiRequestQueryBody } from 'lib/types';
import { canViewWebsite } from 'lib/auth';
import { FILTER_IGNORED } from 'lib/constants';
import { useAuth, useCors } from 'lib/middleware';
diff --git a/pages/api/websites/[id]/pageviews.ts b/pages/api/websites/[id]/pageviews.ts
index 37ad891f..ea6c5df4 100644
--- a/pages/api/websites/[id]/pageviews.ts
+++ b/pages/api/websites/[id]/pageviews.ts
@@ -1,5 +1,4 @@
-import { WebsitePageviews } from 'interface/api/models';
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
+import { NextApiRequestQueryBody, WebsitePageviews } from 'lib/types';
import { canViewWebsite } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
import moment from 'moment-timezone';
diff --git a/pages/api/websites/[id]/reset.ts b/pages/api/websites/[id]/reset.ts
index d6c049df..292672ae 100644
--- a/pages/api/websites/[id]/reset.ts
+++ b/pages/api/websites/[id]/reset.ts
@@ -1,4 +1,4 @@
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
+import { NextApiRequestQueryBody } from 'lib/types';
import { canViewWebsite } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
import { NextApiResponse } from 'next';
diff --git a/pages/api/websites/[id]/stats.ts b/pages/api/websites/[id]/stats.ts
index f326db30..85c4f254 100644
--- a/pages/api/websites/[id]/stats.ts
+++ b/pages/api/websites/[id]/stats.ts
@@ -1,5 +1,5 @@
-import { WebsiteStats } from 'interface/api/models';
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
+import { WebsiteStats } from 'lib/types';
+import { NextApiRequestQueryBody } from 'lib/types';
import { canViewWebsite } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware';
import { NextApiResponse } from 'next';
diff --git a/pages/api/websites/index.ts b/pages/api/websites/index.ts
index 8e4408bc..bc79f91a 100644
--- a/pages/api/websites/index.ts
+++ b/pages/api/websites/index.ts
@@ -1,15 +1,12 @@
import { Prisma } from '@prisma/client';
-import { NextApiRequestQueryBody } from 'interface/api/nextApi';
-import { checkAdmin } from 'lib/auth';
+import { NextApiRequestQueryBody } from 'lib/types';
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 { createWebsite, getUserWebsites } from 'queries';
-export interface WebsitesRequestQuery {
- include_all?: boolean;
-}
+export interface WebsitesRequestQuery {}
export interface WebsitesRequestBody {
name: string;
@@ -30,12 +27,7 @@ export default async (
} = req.auth;
if (req.method === 'GET') {
- const { include_all } = req.query;
-
- const isAdmin = await checkAdmin(userId);
-
- const websites =
- isAdmin && include_all ? await getAllWebsites() : await getWebsitesByUserId(userId);
+ const websites = await getUserWebsites(userId);
return ok(res, websites);
}
diff --git a/queries/admin/team.ts b/queries/admin/team.ts
index 2ea81e0a..1bebcadb 100644
--- a/queries/admin/team.ts
+++ b/queries/admin/team.ts
@@ -1,14 +1,8 @@
import { Prisma, Team } from '@prisma/client';
import prisma from 'lib/prisma';
-
-export async function createTeam(
- data: Prisma.TeamCreateInput,
- searchDeleted = false,
-): Promise {
- return prisma.client.team.create({
- data: { ...data, isDeleted: searchDeleted ? null : false },
- });
-}
+import { uuid } from 'lib/crypto';
+import { ROLES } from 'lib/constants';
+import { Website } from 'lib/types';
export async function getTeam(where: Prisma.TeamWhereInput): Promise {
return prisma.client.team.findFirst({
@@ -22,19 +16,35 @@ export async function getTeams(where: Prisma.TeamWhereInput): Promise {
});
}
-export async function getTeamsByUserId(userId: string): Promise {
- return prisma.client.teamUser
- .findMany({
- where: {
+export async function getTeamWebsites(teamId: string): Promise {
+ return prisma.client.website.findMany({
+ where: {
+ teamId,
+ },
+ orderBy: [
+ {
+ name: 'asc',
+ },
+ ],
+ });
+}
+
+export async function createTeam(data: Prisma.TeamCreateInput): Promise {
+ const { id, userId } = data;
+
+ return prisma.transaction([
+ prisma.client.team.create({
+ data,
+ }),
+ prisma.client.teamUser.create({
+ data: {
+ id: uuid(),
+ teamId: id,
userId,
+ role: ROLES.teamOwner,
},
- include: {
- team: true,
- },
- })
- .then(data => {
- return data.map(a => a.team);
- });
+ }),
+ ]);
}
export async function updateTeam(
@@ -42,7 +52,10 @@ export async function updateTeam(
where: Prisma.TeamWhereUniqueInput,
): Promise {
return prisma.client.team.update({
- data,
+ data: {
+ ...data,
+ updatedAt: new Date(),
+ },
where,
});
}
@@ -50,7 +63,7 @@ export async function updateTeam(
export async function deleteTeam(teamId: string): Promise {
return prisma.client.team.update({
data: {
- isDeleted: true,
+ deletedAt: new Date(),
},
where: {
id: teamId,
diff --git a/queries/admin/teamUser.ts b/queries/admin/teamUser.ts
index e88fa5e1..13090031 100644
--- a/queries/admin/teamUser.ts
+++ b/queries/admin/teamUser.ts
@@ -2,6 +2,23 @@ import { Prisma, TeamUser } from '@prisma/client';
import { uuid } from 'lib/crypto';
import prisma from 'lib/prisma';
+export async function getTeamUser(teamId: string, userId: string): Promise {
+ return prisma.client.teamUser.findFirst({
+ where: {
+ teamId,
+ userId,
+ },
+ });
+}
+
+export async function getTeamUsers(teamId: string): Promise {
+ return prisma.client.teamUser.findMany({
+ where: {
+ teamId,
+ },
+ });
+}
+
export async function createTeamUser(
userId: string,
teamId: string,
@@ -17,18 +34,6 @@ export async function createTeamUser(
});
}
-export async function getTeamUser(where: Prisma.TeamUserWhereInput): Promise {
- return prisma.client.teamUser.findFirst({
- where,
- });
-}
-
-export async function getTeamUsers(where: Prisma.TeamUserWhereInput): Promise {
- return prisma.client.teamUser.findMany({
- where,
- });
-}
-
export async function updateTeamUser(
data: Prisma.TeamUserUpdateInput,
where: Prisma.TeamUserWhereUniqueInput,
@@ -42,7 +47,7 @@ export async function updateTeamUser(
export async function deleteTeamUser(teamUserId: string): Promise {
return prisma.client.teamUser.update({
data: {
- isDeleted: true,
+ deletedAt: new Date(),
},
where: {
id: teamUserId,
diff --git a/queries/admin/user.ts b/queries/admin/user.ts
index 81727b16..a1cfd901 100644
--- a/queries/admin/user.ts
+++ b/queries/admin/user.ts
@@ -1,6 +1,7 @@
-import { Prisma } from '@prisma/client';
+import { Prisma, Team } from '@prisma/client';
import cache from 'lib/cache';
import prisma from 'lib/prisma';
+import { Website } from 'lib/types';
export interface User {
id: string;
@@ -9,36 +10,19 @@ export interface User {
createdAt?: Date;
}
-export async function createUser(data: {
- id: string;
- username: string;
- password: string;
-}): Promise<{
- id: string;
- username: string;
-}> {
- return prisma.client.user.create({
- data,
- select: {
- id: true,
- username: true,
- },
- });
-}
-
export async function getUser(
where: Prisma.UserWhereUniqueInput,
- includePassword = false,
+ options: { includePassword?: boolean } = {},
): Promise {
+ const { includePassword = false } = options;
+
return prisma.client.user.findUnique({
where,
select: {
id: true,
username: true,
- userRole: {
- select: { role: true },
- },
password: includePassword,
+ role: true,
},
});
}
@@ -53,24 +37,56 @@ export async function getUsers(): Promise {
select: {
id: true,
username: true,
+ role: true,
createdAt: true,
},
});
}
-export async function getUsersByTeamId(teamId): Promise {
- return prisma.client.user.findMany({
- where: {
- teamUser: {
- every: {
- teamId,
- },
+export async function getUserTeams(userId: string): Promise {
+ return prisma.client.teamUser
+ .findMany({
+ where: {
+ userId,
},
+ include: {
+ team: true,
+ },
+ })
+ .then(data => {
+ return data.map(a => a.team);
+ });
+}
+
+export async function getUserWebsites(userId: string): Promise {
+ return prisma.client.website.findMany({
+ where: {
+ userId,
},
+ orderBy: [
+ {
+ name: 'asc',
+ },
+ ],
+ });
+}
+
+export async function createUser(data: {
+ id: string;
+ username: string;
+ password: string;
+ role: string;
+}): Promise<{
+ id: string;
+ username: string;
+ role: string;
+}> {
+ return prisma.client.user.create({
+ data,
select: {
id: true,
username: true,
- createdAt: true,
+ role: true,
},
});
}
@@ -85,8 +101,8 @@ export async function updateUser(
select: {
id: true,
username: true,
+ role: true,
createdAt: true,
- userRole: true,
},
});
}
@@ -106,8 +122,8 @@ export async function deleteUser(
websiteIds = websites.map(a => a.id);
}
- return client
- .$transaction([
+ return prisma
+ .transaction([
client.websiteEvent.deleteMany({
where: { websiteId: { in: websiteIds } },
}),
@@ -116,13 +132,13 @@ export async function deleteUser(
}),
client.website.updateMany({
data: {
- isDeleted: true,
+ deletedAt: new Date(),
},
where: { id: { in: websiteIds } },
}),
client.user.update({
data: {
- isDeleted: true,
+ deletedAt: new Date(),
},
where: {
id: userId,
diff --git a/queries/admin/userRole.ts b/queries/admin/userRole.ts
deleted file mode 100644
index a5c24d8f..00000000
--- a/queries/admin/userRole.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import { Prisma, UserRole } from '@prisma/client';
-import prisma from 'lib/prisma';
-
-export async function createUserRole(
- data: Prisma.UserRoleCreateInput | Prisma.UserRoleUncheckedCreateInput,
-): Promise {
- return prisma.client.userRole.create({
- data,
- });
-}
-
-export async function getUserRole(where: Prisma.UserRoleWhereInput): Promise {
- return prisma.client.userRole.findFirst({
- where,
- });
-}
-
-export async function getUserRoles(where: Prisma.UserRoleWhereInput): Promise {
- return prisma.client.userRole.findMany({
- where,
- });
-}
-
-export async function getUserRolesByUserId(userId: string): Promise {
- return prisma.client.userRole.findMany({
- where: {
- userId,
- },
- });
-}
-
-export async function updateUserRole(
- data: Prisma.UserRoleUpdateInput,
- where: Prisma.UserRoleWhereUniqueInput,
-): Promise {
- return prisma.client.userRole.update({
- data,
- where,
- });
-}
-
-export async function deleteUserRole(userRoleId: string): Promise {
- return prisma.client.userRole.update({
- data: {
- isDeleted: true,
- },
- where: {
- id: userRoleId,
- },
- });
-}
diff --git a/queries/admin/website.ts b/queries/admin/website.ts
index c2ed683b..cf2425a3 100644
--- a/queries/admin/website.ts
+++ b/queries/admin/website.ts
@@ -3,6 +3,20 @@ import cache from 'lib/cache';
import prisma from 'lib/prisma';
import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
+export async function getWebsite(where: Prisma.WebsiteWhereUniqueInput): Promise {
+ return prisma.client.website.findUnique({
+ where,
+ });
+}
+
+export async function getWebsites(): Promise {
+ return prisma.client.website.findMany({
+ orderBy: {
+ name: 'asc',
+ },
+ });
+}
+
export async function createWebsite(
data: Prisma.WebsiteCreateInput | Prisma.WebsiteUncheckedCreateInput,
): Promise {
@@ -55,44 +69,6 @@ export async function resetWebsite(
});
}
-export async function getWebsite(where: Prisma.WebsiteWhereUniqueInput): Promise {
- return prisma.client.website.findUnique({
- where,
- });
-}
-
-export async function getWebsitesByUserId(userId): Promise {
- return prisma.client.website.findMany({
- where: {
- userId,
- },
- orderBy: {
- name: 'asc',
- },
- });
-}
-
-export async function getWebsitesByTeamId(teamId): Promise {
- return prisma.client.website.findMany({
- where: {
- teamId,
- },
- orderBy: {
- name: 'asc',
- },
- });
-}
-
-export async function getAllWebsites(): Promise {
- return await prisma.client.website.findMany({
- orderBy: [
- {
- name: 'asc',
- },
- ],
- });
-}
-
export async function deleteWebsite(websiteId: string) {
return runQuery({
[PRISMA]: () => deleteWebsiteRelationalQuery(websiteId),
@@ -127,7 +103,7 @@ async function deleteWebsiteRelationalQuery(
async function deleteWebsiteClickhouseQuery(websiteId): Promise {
return prisma.client.website.update({
data: {
- isDeleted: true,
+ deletedAt: new Date(),
},
where: { id: websiteId },
});
diff --git a/queries/analytics/event/getEventData.ts b/queries/analytics/event/getEventData.ts
index b6942685..ae8b8503 100644
--- a/queries/analytics/event/getEventData.ts
+++ b/queries/analytics/event/getEventData.ts
@@ -2,8 +2,8 @@ import clickhouse from 'lib/clickhouse';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import prisma from 'lib/prisma';
import cache from 'lib/cache';
-import { WebsiteMetric } from 'interface/api/models';
-import { EventType } from 'lib/types';
+import { WebsiteMetric } from 'lib/types';
+import { EVENT_TYPE } from 'lib/constants';
export async function getEventData(
...args: [
@@ -47,7 +47,7 @@ async function relationalQuery(
from website_event
where website_id ='${websiteId}'
and created_at between $1 and $2
- and event_type = ${EventType.Event}
+ and event_type = ${EVENT_TYPE.customEvent}
${eventName ? `and eventName = ${eventName}` : ''}
${
Object.keys(filters).length > 0
@@ -80,7 +80,7 @@ async function clickhouseQuery(
from event
where website_id = $1
and rev_id = $2
- and event_type = ${EventType.Event}
+ and event_type = ${EVENT_TYPE.customEvent}
${eventName ? `and eventName = ${eventName}` : ''}
and ${getBetweenDates('created_at', startDate, endDate)}
${
diff --git a/queries/analytics/event/getEventMetrics.ts b/queries/analytics/event/getEventMetrics.ts
index a7557091..0440cb3f 100644
--- a/queries/analytics/event/getEventMetrics.ts
+++ b/queries/analytics/event/getEventMetrics.ts
@@ -2,8 +2,8 @@ import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
import cache from 'lib/cache';
-import { WebsiteEventMetric } from 'interface/api/models';
-import { EventType } from 'lib/types';
+import { WebsiteEventMetric } from 'lib/types';
+import { EVENT_TYPE } from 'lib/constants';
export async function getEventMetrics(
...args: [
@@ -56,7 +56,7 @@ async function relationalQuery(
from website_event
where website_id='${websiteId}'
and created_at between $1 and $2
- and event_type = ${EventType.Event}
+ and event_type = ${EVENT_TYPE.customEvent}
${getFilterQuery(filters, params)}
group by 1, 2
order by 2`,
@@ -95,7 +95,7 @@ async function clickhouseQuery(
from event
where website_id = $1
and rev_id = $2
- and event_type = ${EventType.Event}
+ and event_type = ${EVENT_TYPE.customEvent}
and ${getBetweenDates('created_at', startDate, endDate)}
${getFilterQuery(filters, params)}
group by x, t
diff --git a/queries/analytics/event/saveEvent.ts b/queries/analytics/event/saveEvent.ts
index 3cfa8902..430ffd63 100644
--- a/queries/analytics/event/saveEvent.ts
+++ b/queries/analytics/event/saveEvent.ts
@@ -1,10 +1,9 @@
-import { EVENT_NAME_LENGTH, URL_LENGTH } from 'lib/constants';
+import { EVENT_NAME_LENGTH, URL_LENGTH, EVENT_TYPE } from 'lib/constants';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import kafka from 'lib/kafka';
import prisma from 'lib/prisma';
import { uuid } from 'lib/crypto';
import cache from 'lib/cache';
-import { EventType } from 'lib/types';
export async function saveEvent(args: {
id: string;
@@ -43,7 +42,7 @@ async function relationalQuery(data: {
sessionId,
url: url?.substring(0, URL_LENGTH),
referrer: referrer?.substring(0, URL_LENGTH),
- eventType: EventType.Event,
+ eventType: EVENT_TYPE.customEvent,
eventName: eventName?.substring(0, EVENT_NAME_LENGTH),
eventData,
};
@@ -77,7 +76,7 @@ async function clickhouseQuery(data: {
session_id: sessionId,
event_id: uuid(),
url: url?.substring(0, URL_LENGTH),
- event_type: EventType.Event,
+ event_type: EVENT_TYPE.customEvent,
event_name: eventName?.substring(0, EVENT_NAME_LENGTH),
event_data: eventData ? JSON.stringify(eventData) : null,
rev_id: website?.revId || 0,
diff --git a/queries/analytics/pageview/getPageviewMetrics.ts b/queries/analytics/pageview/getPageviewMetrics.ts
index 402f6eb1..28a47b45 100644
--- a/queries/analytics/pageview/getPageviewMetrics.ts
+++ b/queries/analytics/pageview/getPageviewMetrics.ts
@@ -3,7 +3,7 @@ import clickhouse from 'lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
import cache from 'lib/cache';
import { Prisma } from '@prisma/client';
-import { EventType } from 'lib/types';
+import { EVENT_TYPE } from 'lib/constants';
export async function getPageviewMetrics(
...args: [
@@ -43,7 +43,7 @@ async function relationalQuery(
${joinSession}
where website_id='${websiteId}'
and website_event.created_at between $1 and $2
- and event_type = ${EventType.Pageview}
+ and event_type = ${EVENT_TYPE.pageView}
${filterQuery}
group by 1
order by 2 desc`,
@@ -71,9 +71,9 @@ async function clickhouseQuery(
from event
where website_id = $1
and rev_id = $2
- and event_type = ${EventType.Pageview}
+ and event_type = ${EVENT_TYPE.pageView}
${column !== 'event_name' ? `and event_name = ''` : `and event_name != ''`}
- and ${getBetweenDates('created_at', startDate, endDate)}
+ and ${getBetweenDates('created_at', startDate, endDate)}n
${filterQuery}
group by x
order by y desc`,
diff --git a/queries/analytics/pageview/getPageviewStats.ts b/queries/analytics/pageview/getPageviewStats.ts
index ab23cb15..b23f782b 100644
--- a/queries/analytics/pageview/getPageviewStats.ts
+++ b/queries/analytics/pageview/getPageviewStats.ts
@@ -2,7 +2,7 @@ import cache from 'lib/cache';
import clickhouse from 'lib/clickhouse';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import prisma from 'lib/prisma';
-import { EventType } from 'lib/types';
+import { EVENT_TYPE } from 'lib/constants';
export async function getPageviewStats(
...args: [
@@ -56,7 +56,7 @@ async function relationalQuery(
${joinSession}
where website.website_id='${websiteId}'
and pageview.created_at between $1 and $2
- and event_type = ${EventType.Pageview}
+ and event_type = ${EVENT_TYPE.pageView}
${filterQuery}
group by 1`,
params,
@@ -92,7 +92,7 @@ async function clickhouseQuery(
from event
where website_id = $1
and rev_id = $2
- and event_type = ${EventType.Pageview}
+ and event_type = ${EVENT_TYPE.pageView}
and ${getBetweenDates('created_at', startDate, endDate)}
${filterQuery}
group by t) g
diff --git a/queries/analytics/pageview/savePageView.ts b/queries/analytics/pageview/savePageView.ts
index 7e8c3b37..ae702211 100644
--- a/queries/analytics/pageview/savePageView.ts
+++ b/queries/analytics/pageview/savePageView.ts
@@ -1,10 +1,9 @@
-import { URL_LENGTH } from 'lib/constants';
+import { URL_LENGTH, EVENT_TYPE } from 'lib/constants';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import kafka from 'lib/kafka';
import prisma from 'lib/prisma';
import cache from 'lib/cache';
import { uuid } from 'lib/crypto';
-import { EventType } from 'lib/types';
export async function savePageView(args: {
id: string;
@@ -40,7 +39,7 @@ async function relationalQuery(data: {
sessionId,
url: url?.substring(0, URL_LENGTH),
referrer: referrer?.substring(0, URL_LENGTH),
- eventType: EventType.Pageview,
+ eventType: EVENT_TYPE.pageView,
},
});
}
@@ -58,7 +57,7 @@ async function clickhouseQuery(data) {
rev_id: website?.revId || 0,
created_at: getDateFormat(new Date()),
country: country ? country : null,
- event_type: EventType.Pageview,
+ event_type: EVENT_TYPE.pageView,
...args,
};
diff --git a/queries/index.js b/queries/index.js
index f1f03375..2d1931ee 100644
--- a/queries/index.js
+++ b/queries/index.js
@@ -1,7 +1,6 @@
export * from './admin/team';
export * from './admin/teamUser';
export * from './admin/user';
-export * from './admin/userRole';
export * from './admin/website';
export * from './analytics/event/getEventMetrics';
export * from './analytics/event/getEvents';