diff --git a/prisma/migrations/15_add_share/migration.sql b/prisma/migrations/15_add_share/migration.sql index 3971b54c5..d9f1e7cf7 100644 --- a/prisma/migrations/15_add_share/migration.sql +++ b/prisma/migrations/15_add_share/migration.sql @@ -3,7 +3,6 @@ CREATE TABLE "share" ( "share_id" UUID NOT NULL, "entity_id" UUID NOT NULL, "share_type" INTEGER NOT NULL, - "name" VARCHAR(200) NOT NULL, "slug" VARCHAR(100) NOT NULL, "parameters" JSONB NOT NULL, "created_at" TIMESTAMPTZ(6) DEFAULT CURRENT_TIMESTAMP, @@ -22,10 +21,9 @@ CREATE UNIQUE INDEX "share_slug_key" ON "share"("slug"); CREATE INDEX "share_entity_id_idx" ON "share"("entity_id"); -- MigrateData -INSERT INTO "share" (share_id, entity_id, name, share_type, slug, parameters, created_at) +INSERT INTO "share" (share_id, entity_id, share_type, slug, parameters, created_at) SELECT gen_random_uuid(), website_id, - name, 1, share_id, '{}'::jsonb, diff --git a/prisma/schema.prisma b/prisma/schema.prisma index e58ebd0b0..4da354068 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -342,7 +342,6 @@ model Board { model Share { id String @id() @map("share_id") @db.Uuid entityId String @map("entity_id") @db.Uuid - name String @db.VarChar(200) shareType Int @map("share_type") @db.Integer slug String @unique() @db.VarChar(100) parameters Json diff --git a/src/app/(main)/admin/users/UserAddForm.tsx b/src/app/(main)/admin/users/UserAddForm.tsx index 84b8399cd..6c365510c 100644 --- a/src/app/(main)/admin/users/UserAddForm.tsx +++ b/src/app/(main)/admin/users/UserAddForm.tsx @@ -10,7 +10,6 @@ import { TextField, } from '@umami/react-zen'; import { useMessages, useUpdateQuery } from '@/components/hooks'; -import { messages } from '@/components/messages'; import { ROLES } from '@/lib/constants'; export function UserAddForm({ onSave, onClose }) { @@ -38,10 +37,7 @@ export function UserAddForm({ onSave, onClose }) { diff --git a/src/app/api/auth/logout/route.ts b/src/app/api/auth/logout/route.ts index 153f1f523..7bf0a8137 100644 --- a/src/app/api/auth/logout/route.ts +++ b/src/app/api/auth/logout/route.ts @@ -1,14 +1,7 @@ import redis from '@/lib/redis'; -import { parseRequest } from '@/lib/request'; import { ok } from '@/lib/response'; export async function POST(request: Request) { - const { error } = await parseRequest(request); - - if (error) { - return error(); - } - if (redis.enabled) { const token = request.headers.get('authorization')?.split(' ')?.[1]; diff --git a/src/app/api/auth/sso/route.ts b/src/app/api/auth/sso/route.ts index f82228695..bba3dde30 100644 --- a/src/app/api/auth/sso/route.ts +++ b/src/app/api/auth/sso/route.ts @@ -1,7 +1,7 @@ import { saveAuth } from '@/lib/auth'; import redis from '@/lib/redis'; import { parseRequest } from '@/lib/request'; -import { json, serverError } from '@/lib/response'; +import { json } from '@/lib/response'; export async function POST(request: Request) { const { auth, error } = await parseRequest(request); @@ -10,13 +10,9 @@ export async function POST(request: Request) { return error(); } - if (!redis.enabled) { - return serverError({ - message: 'Redis is disabled', - }); + if (redis.enabled) { + const token = await saveAuth({ userId: auth.user.id }, 86400); + + return json({ user: auth.user, token }); } - - const token = await saveAuth({ userId: auth.user.id }, 86400); - - return json({ user: auth.user, token }); } diff --git a/src/app/api/users/[userId]/route.ts b/src/app/api/users/[userId]/route.ts index e642fe3c1..aade8aa8d 100644 --- a/src/app/api/users/[userId]/route.ts +++ b/src/app/api/users/[userId]/route.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; import { hashPassword } from '@/lib/password'; import { parseRequest } from '@/lib/request'; -import { badRequest, json, notFound, ok, unauthorized } from '@/lib/response'; +import { badRequest, json, ok, unauthorized } from '@/lib/response'; import { userRoleParam } from '@/lib/schema'; import { canDeleteUser, canUpdateUser, canViewUser } from '@/permissions'; import { deleteUser, getUser, getUserByUsername, updateUser } from '@/queries/prisma'; @@ -27,7 +27,7 @@ export async function GET(request: Request, { params }: { params: Promise<{ user export async function POST(request: Request, { params }: { params: Promise<{ userId: string }> }) { const schema = z.object({ username: z.string().max(255).optional(), - password: z.string().min(8).max(255).optional(), + password: z.string().max(255).optional(), role: userRoleParam.optional(), }); @@ -47,10 +47,6 @@ export async function POST(request: Request, { params }: { params: Promise<{ use const user = await getUser(userId); - if (!user) { - return notFound(); - } - const data: any = {}; if (password) { diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts index 4335c33fb..dbb114cf7 100644 --- a/src/app/api/users/route.ts +++ b/src/app/api/users/route.ts @@ -4,7 +4,6 @@ import { uuid } from '@/lib/crypto'; import { hashPassword } from '@/lib/password'; import { parseRequest } from '@/lib/request'; import { badRequest, json, unauthorized } from '@/lib/response'; -import { userRoleParam } from '@/lib/schema'; import { canCreateUser } from '@/permissions'; import { createUser, getUserByUsername } from '@/queries/prisma'; @@ -12,8 +11,8 @@ export async function POST(request: Request) { const schema = z.object({ id: z.uuid().optional(), username: z.string().max(255), - password: z.string().min(8).max(255), - role: userRoleParam, + password: z.string(), + role: z.string().regex(/admin|user|view-only/i), }); const { auth, body, error } = await parseRequest(request, schema); diff --git a/src/app/api/websites/[websiteId]/segments/route.ts b/src/app/api/websites/[websiteId]/segments/route.ts index 10d47a81c..45927656c 100644 --- a/src/app/api/websites/[websiteId]/segments/route.ts +++ b/src/app/api/websites/[websiteId]/segments/route.ts @@ -2,7 +2,7 @@ import { z } from 'zod'; import { uuid } from '@/lib/crypto'; import { getQueryFilters, parseRequest } from '@/lib/request'; import { json, unauthorized } from '@/lib/response'; -import { searchParams, segmentParametersSchema, segmentTypeParam } from '@/lib/schema'; +import { anyObjectParam, searchParams, segmentTypeParam } from '@/lib/schema'; import { canUpdateWebsite, canViewWebsite } from '@/permissions'; import { createSegment, getWebsiteSegments } from '@/queries/prisma'; @@ -42,7 +42,7 @@ export async function POST( const schema = z.object({ type: segmentTypeParam, name: z.string().max(200), - parameters: segmentParametersSchema, + parameters: anyObjectParam, }); const { auth, body, error } = await parseRequest(request, schema); diff --git a/src/lib/auth.ts b/src/lib/auth.ts index 832dfb600..ba6d8b09f 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -1,6 +1,7 @@ import debug from 'debug'; import { ROLE_PERMISSIONS, ROLES, SHARE_TOKEN_HEADER } from '@/lib/constants'; -import { createAuthKey, secret } from '@/lib/crypto'; +import { secret } from '@/lib/crypto'; +import { getRandomChars } from '@/lib/generate'; import { createSecureToken, parseSecureToken, parseToken } from '@/lib/jwt'; import redis from '@/lib/redis'; import { ensureArray } from '@/lib/utils'; @@ -52,7 +53,7 @@ export async function checkAuth(request: Request) { } export async function saveAuth(data: any, expire = 0) { - const authKey = `auth:${createAuthKey()}`; + const authKey = `auth:${getRandomChars(32)}`; if (redis.enabled) { await redis.client.set(authKey, data); diff --git a/src/lib/crypto.ts b/src/lib/crypto.ts index ee4c977fe..a6d912b82 100644 --- a/src/lib/crypto.ts +++ b/src/lib/crypto.ts @@ -63,7 +63,3 @@ export function uuid(...args: any) { return process.env.USE_UUIDV7 ? v7() : v4(); } - -export function createAuthKey() { - return crypto.randomBytes(16).toString('hex'); -} diff --git a/src/lib/schema.ts b/src/lib/schema.ts index addce3a25..c860cee89 100644 --- a/src/lib/schema.ts +++ b/src/lib/schema.ts @@ -104,23 +104,6 @@ export const reportTypeParam = z.enum([ 'utm', ]); -export const operatorParam = z.enum([ - 'eq', - 'neq', - 's', - 'ns', - 'c', - 'dnc', - 't', - 'f', - 'gt', - 'lt', - 'gte', - 'lte', - 'bf', - 'af', -]); - export const goalReportSchema = z.object({ type: z.literal('goal'), parameters: z @@ -174,7 +157,7 @@ export const retentionReportSchema = z.object({ parameters: z.object({ startDate: z.coerce.date(), endDate: z.coerce.date(), - timezone: timezoneParam.optional(), + timezone: z.string().optional(), }), }); @@ -192,7 +175,7 @@ export const revenueReportSchema = z.object({ startDate: z.coerce.date(), endDate: z.coerce.date(), unit: unitParam.optional(), - timezone: timezoneParam.optional(), + timezone: z.string().optional(), currency: z.string(), }), }); @@ -248,22 +231,3 @@ export const reportResultSchema = z.intersection( ); export const segmentTypeParam = z.enum(['segment', 'cohort']); - -export const segmentParametersSchema = z.object({ - filters: z - .array( - z.object({ - name: z.string(), - operator: operatorParam, - value: z.string(), - }), - ) - .optional(), - dateRange: z.string().optional(), - action: z - .object({ - type: z.string(), - value: z.string(), - }) - .optional(), -}); diff --git a/src/permissions/team.ts b/src/permissions/team.ts index 784dbe4bb..0f07c1a4f 100644 --- a/src/permissions/team.ts +++ b/src/permissions/team.ts @@ -16,7 +16,7 @@ export async function canCreateTeam({ user }: Auth) { return true; } - return hasPermission(user.role, PERMISSIONS.teamCreate); + return !!user; } export async function canUpdateTeam({ user }: Auth, teamId: string) { diff --git a/src/queries/prisma/user.ts b/src/queries/prisma/user.ts index 467ea1e02..14376fc26 100644 --- a/src/queries/prisma/user.ts +++ b/src/queries/prisma/user.ts @@ -18,7 +18,7 @@ async function findUser(criteria: Prisma.UserFindUniqueArgs, options: GetUserOpt ...criteria, where: { ...criteria.where, - ...(showDeleted ? {} : { deletedAt: null }), + ...(showDeleted && { deletedAt: null }), }, select: { id: true,