feat: add notification api
This commit is contained in:
parent
72e3753503
commit
b6a26d8777
@ -28,8 +28,9 @@ model Workspace {
|
|||||||
createdAt DateTime? @default(now()) @db.Timestamptz(6)
|
createdAt DateTime? @default(now()) @db.Timestamptz(6)
|
||||||
updatedAt DateTime? @updatedAt @db.Timestamptz(6)
|
updatedAt DateTime? @updatedAt @db.Timestamptz(6)
|
||||||
|
|
||||||
users WorkspacesOnUsers[]
|
users WorkspacesOnUsers[]
|
||||||
websites Website[]
|
websites Website[]
|
||||||
|
notifications Notification[]
|
||||||
|
|
||||||
// for user currentWorkspace
|
// for user currentWorkspace
|
||||||
selectedUsers User[]
|
selectedUsers User[]
|
||||||
@ -193,7 +194,7 @@ model TelemetryEvent {
|
|||||||
id String @id() @default(uuid()) @db.Uuid
|
id String @id() @default(uuid()) @db.Uuid
|
||||||
sessionId String @db.Uuid
|
sessionId String @db.Uuid
|
||||||
workspaceId String @db.Uuid
|
workspaceId String @db.Uuid
|
||||||
eventName String? @db.VarChar(100)
|
eventName String? @db.VarChar(100)
|
||||||
urlOrigin String @db.VarChar(500)
|
urlOrigin String @db.VarChar(500)
|
||||||
urlPath String @db.VarChar(500)
|
urlPath String @db.VarChar(500)
|
||||||
createdAt DateTime? @default(now()) @db.Timestamptz(6)
|
createdAt DateTime? @default(now()) @db.Timestamptz(6)
|
||||||
@ -205,3 +206,16 @@ model TelemetryEvent {
|
|||||||
@@index([workspaceId])
|
@@index([workspaceId])
|
||||||
@@index([workspaceId, createdAt])
|
@@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])
|
||||||
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { Handler } from 'express';
|
import { Handler } from 'express';
|
||||||
import { getWorkspaceUser } from '../model/workspace';
|
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) => {
|
return async (req, res, next) => {
|
||||||
const workspaceId =
|
const workspaceId =
|
||||||
req.body.workspaceId ?? req.query.workspaceId ?? req.params.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 (Array.isArray(roles) && roles.length > 0) {
|
||||||
if (!roles.includes(info.role)) {
|
if (!roles.includes(info.role as ROLES)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Workspace roles not has this permission, need ${roles}`
|
`Workspace roles not has this permission, need ${roles}`
|
||||||
);
|
);
|
||||||
|
27
src/server/model/notification.ts
Normal file
27
src/server/model/notification.ts
Normal 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;
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
import { prisma } from './_client';
|
import { prisma } from './_client';
|
||||||
import bcryptjs from 'bcryptjs';
|
import bcryptjs from 'bcryptjs';
|
||||||
import { ROLES } from '../utils/const';
|
import { ROLES, SYSTEM_ROLES } from '../utils/const';
|
||||||
import { jwtVerify } from '../middleware/auth';
|
import { jwtVerify } from '../middleware/auth';
|
||||||
|
|
||||||
async function hashPassword(password: string) {
|
async function hashPassword(password: string) {
|
||||||
@ -59,7 +59,7 @@ export async function createAdminUser(username: string, password: string) {
|
|||||||
data: {
|
data: {
|
||||||
username,
|
username,
|
||||||
password: await hashPassword(password),
|
password: await hashPassword(password),
|
||||||
role: ROLES.admin,
|
role: SYSTEM_ROLES.admin,
|
||||||
workspaces: {
|
workspaces: {
|
||||||
create: [
|
create: [
|
||||||
{
|
{
|
||||||
@ -106,7 +106,7 @@ export async function createUser(username: string, password: string) {
|
|||||||
data: {
|
data: {
|
||||||
username,
|
username,
|
||||||
password: await hashPassword(password),
|
password: await hashPassword(password),
|
||||||
role: ROLES.user,
|
role: SYSTEM_ROLES.user,
|
||||||
workspaces: {
|
workspaces: {
|
||||||
create: [
|
create: [
|
||||||
{
|
{
|
||||||
|
@ -195,7 +195,7 @@ export async function getWorkspaceWebsiteSession(
|
|||||||
export async function getWorkspaceWebsiteStats(
|
export async function getWorkspaceWebsiteStats(
|
||||||
websiteId: string,
|
websiteId: string,
|
||||||
filters: QueryFilters
|
filters: QueryFilters
|
||||||
): any {
|
): Promise<any> {
|
||||||
const { filterQuery, joinSession, params } = await parseFilters(websiteId, {
|
const { filterQuery, joinSession, params } = await parseFilters(websiteId, {
|
||||||
...filters,
|
...filters,
|
||||||
});
|
});
|
||||||
|
47
src/server/router/notification.ts
Normal file
47
src/server/router/notification.ts
Normal 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 });
|
||||||
|
}
|
||||||
|
);
|
@ -1,12 +1,12 @@
|
|||||||
export const ROLES = {
|
export enum SYSTEM_ROLES {
|
||||||
// System Role
|
admin = 'admin',
|
||||||
admin: 'admin',
|
user = 'user',
|
||||||
user: 'user',
|
}
|
||||||
|
|
||||||
// Workspace Role
|
export enum ROLES {
|
||||||
owner: 'owner',
|
owner = 'owner',
|
||||||
readOnly: 'readOnly',
|
readOnly = 'readOnly',
|
||||||
} as const;
|
}
|
||||||
|
|
||||||
export const HOSTNAME_REGEX =
|
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])$/;
|
/^(([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])$/;
|
||||||
|
Loading…
Reference in New Issue
Block a user