feat: add notification api

This commit is contained in:
moonrailgun 2023-09-26 14:45:28 +08:00
parent 72e3753503
commit b6a26d8777
7 changed files with 106 additions and 17 deletions

View File

@ -28,8 +28,9 @@ model Workspace {
createdAt DateTime? @default(now()) @db.Timestamptz(6)
updatedAt DateTime? @updatedAt @db.Timestamptz(6)
users WorkspacesOnUsers[]
websites Website[]
users WorkspacesOnUsers[]
websites Website[]
notifications Notification[]
// for user currentWorkspace
selectedUsers User[]
@ -193,7 +194,7 @@ model TelemetryEvent {
id String @id() @default(uuid()) @db.Uuid
sessionId String @db.Uuid
workspaceId String @db.Uuid
eventName String? @db.VarChar(100)
eventName String? @db.VarChar(100)
urlOrigin String @db.VarChar(500)
urlPath String @db.VarChar(500)
createdAt DateTime? @default(now()) @db.Timestamptz(6)
@ -205,3 +206,16 @@ model TelemetryEvent {
@@index([workspaceId])
@@index([workspaceId, createdAt])
}
model Notification {
id String @id() @default(uuid()) @db.Uuid
workspaceId String @db.Uuid
name String @db.VarChar(100)
type String @db.VarChar(100)
payload Json @db.Json
createdAt DateTime? @default(now()) @db.Timestamptz(6)
workspace Workspace @relation(fields: [workspaceId], references: [id])
@@index([workspaceId])
}

View File

@ -1,7 +1,8 @@
import { Handler } from 'express';
import { getWorkspaceUser } from '../model/workspace';
import { ROLES } from '../utils/const';
export function workspacePermission(roles: string[] = []): Handler {
export function workspacePermission(roles: ROLES[] = []): Handler {
return async (req, res, next) => {
const workspaceId =
req.body.workspaceId ?? req.query.workspaceId ?? req.params.workspaceId;
@ -23,7 +24,7 @@ export function workspacePermission(roles: string[] = []): Handler {
}
if (Array.isArray(roles) && roles.length > 0) {
if (!roles.includes(info.role)) {
if (!roles.includes(info.role as ROLES)) {
throw new Error(
`Workspace roles not has this permission, need ${roles}`
);

View File

@ -0,0 +1,27 @@
import { prisma } from './_client';
export function getWorkspaceNotifications(workspaceId: string) {
return prisma.notification.findMany({
where: {
workspaceId,
},
});
}
export async function createWorkspaceNotification(
workspaceId: string,
name: string,
type: string,
payload: Record<string, any>
) {
const notification = await prisma.notification.create({
data: {
workspaceId,
name,
type,
payload,
},
});
return notification;
}

View File

@ -1,6 +1,6 @@
import { prisma } from './_client';
import bcryptjs from 'bcryptjs';
import { ROLES } from '../utils/const';
import { ROLES, SYSTEM_ROLES } from '../utils/const';
import { jwtVerify } from '../middleware/auth';
async function hashPassword(password: string) {
@ -59,7 +59,7 @@ export async function createAdminUser(username: string, password: string) {
data: {
username,
password: await hashPassword(password),
role: ROLES.admin,
role: SYSTEM_ROLES.admin,
workspaces: {
create: [
{
@ -106,7 +106,7 @@ export async function createUser(username: string, password: string) {
data: {
username,
password: await hashPassword(password),
role: ROLES.user,
role: SYSTEM_ROLES.user,
workspaces: {
create: [
{

View File

@ -195,7 +195,7 @@ export async function getWorkspaceWebsiteSession(
export async function getWorkspaceWebsiteStats(
websiteId: string,
filters: QueryFilters
): any {
): Promise<any> {
const { filterQuery, joinSession, params } = await parseFilters(websiteId, {
...filters,
});

View File

@ -0,0 +1,47 @@
import { Router } from 'express';
import { auth } from '../middleware/auth';
import { body, param, validate } from '../middleware/validate';
import { workspacePermission } from '../middleware/workspace';
import {
createWorkspaceNotification,
getWorkspaceNotifications,
} from '../model/notification';
import { ROLES } from '../utils/const';
export const notificationRouter = Router();
notificationRouter.get(
'/list',
validate(param('workspaceId').isUUID()),
auth(),
workspacePermission(),
async (req, res) => {
const list = await getWorkspaceNotifications(req.params.workspaceId);
res.json({ list });
}
);
notificationRouter.post(
'/create',
validate(
param('workspaceId').isUUID(),
body('name').isString(),
body('type').isString(),
body('payload').isObject()
),
auth(),
workspacePermission([ROLES.owner]),
async (req, res) => {
const workspaceId = req.params.workspaceId;
const { name, type, payload } = req.body;
const notification = await createWorkspaceNotification(
workspaceId,
name,
type,
payload
);
res.json({ notification });
}
);

View File

@ -1,12 +1,12 @@
export const ROLES = {
// System Role
admin: 'admin',
user: 'user',
export enum SYSTEM_ROLES {
admin = 'admin',
user = 'user',
}
// Workspace Role
owner: 'owner',
readOnly: 'readOnly',
} as const;
export enum ROLES {
owner = 'owner',
readOnly = 'readOnly',
}
export const HOSTNAME_REGEX =
/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9])$/;