mirror of https://github.com/buster-so/buster.git
collection and assets queries
This commit is contained in:
parent
1a955d786b
commit
87ea87e963
|
@ -1,43 +1,17 @@
|
|||
import type { User } from '@buster/database';
|
||||
import type {
|
||||
GetReportIndividualResponse,
|
||||
ReportIndividualResponse,
|
||||
} from '@buster/server-shared/reports';
|
||||
import { zValidator } from '@hono/zod-validator';
|
||||
import { getReport } from '@buster/database';
|
||||
import type { GetReportIndividualResponse } from '@buster/server-shared/reports';
|
||||
import { Hono } from 'hono';
|
||||
import { HTTPException } from 'hono/http-exception';
|
||||
|
||||
async function getReportHandler(
|
||||
export async function getReportHandler(
|
||||
reportId: string,
|
||||
user: User
|
||||
user: { id: string }
|
||||
): Promise<GetReportIndividualResponse> {
|
||||
return {
|
||||
id: reportId,
|
||||
name: 'Sales Analysis Q4',
|
||||
file_name: 'sales_analysis_q4.md',
|
||||
description: 'Quarterly sales performance analysis',
|
||||
created_by: user.id,
|
||||
created_at: '2024-01-15T10:00:00Z',
|
||||
updated_at: '2024-01-20T14:30:00Z',
|
||||
deleted_at: null,
|
||||
publicly_accessible: false,
|
||||
content: [
|
||||
{
|
||||
type: 'h1',
|
||||
children: [{ text: 'Sales Analysis Q4' }],
|
||||
},
|
||||
{
|
||||
type: 'p',
|
||||
children: [{ text: 'This report analyzes our Q4 sales performance.' }],
|
||||
},
|
||||
{
|
||||
type: 'metric',
|
||||
metricId: '123',
|
||||
children: [{ text: '' }],
|
||||
caption: [{ text: 'This is a metric' }],
|
||||
},
|
||||
],
|
||||
};
|
||||
const report = await getReport({ reportId, userId: user.id });
|
||||
|
||||
const response: GetReportIndividualResponse = report;
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
const app = new Hono().get('/', async (c) => {
|
||||
|
|
|
@ -1,46 +1,47 @@
|
|||
import type { User } from '@buster/database';
|
||||
import { getUserOrganizationId, updateReport } from '@buster/database';
|
||||
import type { UpdateReportRequest, UpdateReportResponse } from '@buster/server-shared/reports';
|
||||
import { UpdateReportRequestSchema } from '@buster/server-shared/reports';
|
||||
import { zValidator } from '@hono/zod-validator';
|
||||
import { Hono } from 'hono';
|
||||
import { HTTPException } from 'hono/http-exception';
|
||||
import { getReportHandler } from './GET';
|
||||
|
||||
async function updateReportHandler(
|
||||
reportId: string,
|
||||
request: UpdateReportRequest,
|
||||
user: User
|
||||
): Promise<UpdateReportResponse> {
|
||||
const existingReport: UpdateReportResponse = {
|
||||
id: reportId,
|
||||
name: 'Sales Analysis Q4',
|
||||
file_name: 'sales_analysis_q4.md',
|
||||
description: 'Quarterly sales performance analysis',
|
||||
created_by: user.id,
|
||||
created_at: '2024-01-15T10:00:00Z',
|
||||
updated_at: '2024-01-20T14:30:00Z',
|
||||
deleted_at: null,
|
||||
publicly_accessible: false,
|
||||
content: [
|
||||
{
|
||||
type: 'h1' as const,
|
||||
children: [{ text: 'Sales Analysis Q4' }],
|
||||
},
|
||||
{
|
||||
type: 'p' as const,
|
||||
children: [{ text: 'This report analyzes our Q4 sales performance.' }],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
if (!reportId || reportId === 'invalid') {
|
||||
throw new HTTPException(404, { message: 'Report not found' });
|
||||
}
|
||||
|
||||
const updatedReport: UpdateReportResponse = {
|
||||
...existingReport,
|
||||
...(request as Partial<UpdateReportResponse>),
|
||||
updated_at: new Date().toISOString(),
|
||||
};
|
||||
// Get user's organization ID
|
||||
const userOrg = await getUserOrganizationId(user.id);
|
||||
|
||||
if (!userOrg) {
|
||||
throw new HTTPException(403, { message: 'User is not associated with an organization' });
|
||||
}
|
||||
|
||||
const _hasPermissionToEditAsset = true; //DALLIN: Check if user has permission to edit asset
|
||||
|
||||
if (!_hasPermissionToEditAsset) {
|
||||
throw new HTTPException(403, { message: 'User does not have permission to edit asset' });
|
||||
}
|
||||
|
||||
const { name, content } = request;
|
||||
|
||||
// Update the report in the database
|
||||
await updateReport({
|
||||
reportId,
|
||||
organizationId: userOrg.organizationId,
|
||||
userId: user.id,
|
||||
name,
|
||||
content,
|
||||
});
|
||||
|
||||
// Get and return the updated report
|
||||
const updatedReport: UpdateReportResponse = await getReportHandler(reportId, user);
|
||||
|
||||
return updatedReport;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@ import { Hono } from 'hono';
|
|||
import { requireAuth } from '../../../../middleware/auth';
|
||||
import GET from './GET';
|
||||
import PUT from './PUT';
|
||||
import SHARING from './sharing';
|
||||
|
||||
const app = new Hono().route('/', GET).route('/', PUT);
|
||||
const app = new Hono().route('/', GET).route('/', PUT).route('/sharing', SHARING);
|
||||
|
||||
export default app;
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
import { getUserOrganizationId, updateReport } from '@buster/database';
|
||||
import {
|
||||
type ShareUpdateRequest,
|
||||
ShareUpdateRequestSchema,
|
||||
type ShareUpdateResponse,
|
||||
type UpdateReportResponse,
|
||||
} from '@buster/server-shared/reports';
|
||||
import { zValidator } from '@hono/zod-validator';
|
||||
import { Hono } from 'hono';
|
||||
import { HTTPException } from 'hono/http-exception';
|
||||
import { getReportHandler } from '../GET';
|
||||
|
||||
async function updateReportShareHandler(
|
||||
reportId: string,
|
||||
request: ShareUpdateRequest,
|
||||
user: { id: string; organizationId: string }
|
||||
) {
|
||||
const _hasPermissionToEditAssetPermissions = true; //DALLIN: Check if user has permission to edit asset permissions
|
||||
|
||||
if (!_hasPermissionToEditAssetPermissions) {
|
||||
throw new HTTPException(403, {
|
||||
message: 'User does not have permission to edit asset permissions',
|
||||
});
|
||||
}
|
||||
|
||||
const { publicly_accessible, public_expiry_date, public_password, workspace_sharing } = request;
|
||||
|
||||
if (publicly_accessible || public_expiry_date || public_password || workspace_sharing) {
|
||||
//DALLIN: Check if user has permission to edit settings
|
||||
}
|
||||
|
||||
await updateReport({
|
||||
reportId,
|
||||
organizationId: user.organizationId,
|
||||
userId: user.id,
|
||||
publicly_accessible,
|
||||
public_expiry_date,
|
||||
public_password,
|
||||
workspace_sharing,
|
||||
});
|
||||
|
||||
const updatedReport: UpdateReportResponse = await getReportHandler(reportId, user);
|
||||
|
||||
return updatedReport;
|
||||
}
|
||||
|
||||
const app = new Hono().put('/', zValidator('json', ShareUpdateRequestSchema), async (c) => {
|
||||
const reportId = c.req.param('id');
|
||||
const request = c.req.valid('json');
|
||||
const user = c.get('busterUser');
|
||||
|
||||
if (!reportId) {
|
||||
throw new HTTPException(404, { message: 'Report not found' });
|
||||
}
|
||||
|
||||
const userOrg = await getUserOrganizationId(user.id);
|
||||
|
||||
if (!userOrg) {
|
||||
throw new HTTPException(403, { message: 'User is not associated with an organization' });
|
||||
}
|
||||
|
||||
const updatedReport: ShareUpdateResponse = await updateReportShareHandler(reportId, request, {
|
||||
id: user.id,
|
||||
organizationId: userOrg.organizationId,
|
||||
});
|
||||
|
||||
return c.json(updatedReport);
|
||||
});
|
||||
|
||||
export default app;
|
|
@ -0,0 +1,6 @@
|
|||
import { Hono } from 'hono';
|
||||
import PUT from './PUT';
|
||||
|
||||
const app = new Hono().route('/', PUT);
|
||||
|
||||
export default app;
|
|
@ -1 +0,0 @@
|
|||
export * from './shareInterfaces';
|
|
@ -1,14 +0,0 @@
|
|||
import type { ShareRole, WorkspaceShareRole } from '@buster/server-shared/share';
|
||||
|
||||
export type ShareDeleteRequest = string[];
|
||||
|
||||
export type ShareUpdateRequest = {
|
||||
users?: {
|
||||
email: string;
|
||||
role: ShareRole;
|
||||
}[];
|
||||
workspace_sharing?: WorkspaceShareRole | null;
|
||||
publicly_accessible?: boolean;
|
||||
public_password?: string | null;
|
||||
public_expiry_date?: string | null;
|
||||
};
|
|
@ -80,10 +80,11 @@ export async function getReport(input: GetReportInput) {
|
|||
// Individual permissions query - get users with direct permissions to this report
|
||||
const individualPermissionsQuery = db
|
||||
.select({
|
||||
id: users.id,
|
||||
role: assetPermissions.role,
|
||||
email: users.email,
|
||||
name: users.name,
|
||||
avatarUrl: users.avatarUrl,
|
||||
avatar_url: users.avatarUrl,
|
||||
})
|
||||
.from(assetPermissions)
|
||||
.innerJoin(users, eq(users.id, assetPermissions.identityId))
|
||||
|
|
|
@ -35,7 +35,11 @@ export type ReportListItem = {
|
|||
|
||||
/**
|
||||
* Get paginated list of reports for the user's organization
|
||||
* with optional filtering by name, dates, and public accessibility
|
||||
* with optional filtering by name, dates, and public accessibility.
|
||||
*
|
||||
* Security note: When deleted date filters (deleted_after/deleted_before) are provided,
|
||||
* this function returns only deleted reports within that date range.
|
||||
* Otherwise, it returns only non-deleted reports.
|
||||
*/
|
||||
export async function getReportsList(
|
||||
input: GetReportsListInput
|
||||
|
@ -64,20 +68,27 @@ export async function getReportsList(
|
|||
const { organizationId } = userOrg;
|
||||
|
||||
// Build dynamic where conditions
|
||||
// Only include the isNull check if no deleted date filters are provided
|
||||
// Check if deleted date filters are provided
|
||||
const hasDeletedFilters = deleted_after !== undefined || deleted_before !== undefined;
|
||||
|
||||
const whereConditions = and(
|
||||
eq(reportFiles.organizationId, organizationId),
|
||||
// Only exclude deleted reports if no deleted date filters are provided
|
||||
!hasDeletedFilters ? isNull(reportFiles.deletedAt) : undefined,
|
||||
// Security fix: Always apply proper deletion filtering
|
||||
// If deleted date filters are provided, show only deleted reports in that range
|
||||
// Otherwise, show only non-deleted reports
|
||||
hasDeletedFilters
|
||||
? and(
|
||||
// Show only deleted reports within the specified date range
|
||||
deleted_after ? gte(reportFiles.deletedAt, deleted_after) : undefined,
|
||||
deleted_before ? lte(reportFiles.deletedAt, deleted_before) : undefined
|
||||
)
|
||||
: // Show only non-deleted reports
|
||||
isNull(reportFiles.deletedAt),
|
||||
name ? like(reportFiles.name, `%${name}%`) : undefined,
|
||||
created_after ? gte(reportFiles.createdAt, created_after) : undefined,
|
||||
created_before ? lte(reportFiles.createdAt, created_before) : undefined,
|
||||
updated_after ? gte(reportFiles.updatedAt, updated_after) : undefined,
|
||||
updated_before ? lte(reportFiles.updatedAt, updated_before) : undefined,
|
||||
deleted_after ? gte(reportFiles.deletedAt, deleted_after) : undefined,
|
||||
deleted_before ? lte(reportFiles.deletedAt, deleted_before) : undefined,
|
||||
publicly_accessible !== undefined
|
||||
? eq(reportFiles.publiclyAccessible, publicly_accessible)
|
||||
: undefined
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
export * from './get-report-title';
|
||||
export * from './get-reports-list';
|
||||
export * from './get-report';
|
||||
export * from './update-report';
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
import { and, eq, isNull } from 'drizzle-orm';
|
||||
import {} from 'drizzle-zod';
|
||||
import { z } from 'zod';
|
||||
import { db } from '../../connection';
|
||||
import { reportFiles } from '../../schema';
|
||||
import { workspaceSharingEnum } from '../../schema';
|
||||
import { ReportElementSchema, type ReportElements } from '../../schema-types';
|
||||
|
||||
const WorkspaceSharingSchema = z.enum(workspaceSharingEnum.enumValues);
|
||||
|
||||
// Input validation schema for updating a report
|
||||
const UpdateReportInputSchema = z.object({
|
||||
reportId: z.string().uuid('Report ID must be a valid UUID'),
|
||||
organizationId: z.string().uuid('Organization ID must be a valid UUID'),
|
||||
userId: z.string().uuid('User ID must be a valid UUID'),
|
||||
name: z.string().optional(),
|
||||
publicly_accessible: z.boolean().optional(),
|
||||
content: z.lazy(() => z.array(ReportElementSchema)).optional() as z.ZodOptional<
|
||||
z.ZodType<ReportElements>
|
||||
>,
|
||||
public_expiry_date: z.string().optional(),
|
||||
public_password: z.string().optional(),
|
||||
workspace_sharing: WorkspaceSharingSchema.optional(),
|
||||
});
|
||||
|
||||
type UpdateReportInput = z.infer<typeof UpdateReportInputSchema>;
|
||||
|
||||
/**
|
||||
* Updates a report with the provided fields
|
||||
* Only updates fields that are provided in the input
|
||||
* Always updates the updatedAt timestamp
|
||||
*/
|
||||
export const updateReport = async (params: UpdateReportInput): Promise<void> => {
|
||||
// Validate and destructure input
|
||||
const {
|
||||
reportId,
|
||||
organizationId,
|
||||
userId,
|
||||
name,
|
||||
publicly_accessible,
|
||||
content,
|
||||
public_expiry_date,
|
||||
public_password,
|
||||
workspace_sharing,
|
||||
} = UpdateReportInputSchema.parse(params);
|
||||
|
||||
try {
|
||||
// Build update data - only include fields that are provided
|
||||
const updateData: {
|
||||
updatedAt: string;
|
||||
name?: string;
|
||||
publiclyAccessible?: boolean;
|
||||
publiclyEnabledBy?: string | null;
|
||||
content?: ReportElements;
|
||||
publicExpiryDate?: string;
|
||||
publicPassword?: string;
|
||||
workspaceSharing?: 'none' | 'can_view' | 'can_edit' | 'full_access';
|
||||
workspaceSharingEnabledBy?: string | null;
|
||||
workspaceSharingEnabledAt?: string | null;
|
||||
} = {
|
||||
updatedAt: new Date().toISOString(),
|
||||
};
|
||||
|
||||
// Only add fields that are provided
|
||||
if (name !== undefined) {
|
||||
updateData.name = name;
|
||||
}
|
||||
|
||||
if (publicly_accessible !== undefined) {
|
||||
updateData.publiclyAccessible = publicly_accessible;
|
||||
// Set publiclyEnabledBy to userId when enabling, null when disabling
|
||||
updateData.publiclyEnabledBy = publicly_accessible ? userId : null;
|
||||
}
|
||||
|
||||
if (content !== undefined) {
|
||||
updateData.content = content;
|
||||
}
|
||||
|
||||
if (public_expiry_date !== undefined) {
|
||||
updateData.publicExpiryDate = public_expiry_date;
|
||||
}
|
||||
|
||||
if (public_password !== undefined) {
|
||||
updateData.publicPassword = public_password;
|
||||
}
|
||||
|
||||
if (workspace_sharing !== undefined) {
|
||||
updateData.workspaceSharing = workspace_sharing;
|
||||
|
||||
if (workspace_sharing !== 'none') {
|
||||
updateData.workspaceSharingEnabledBy = userId;
|
||||
updateData.workspaceSharingEnabledAt = new Date().toISOString();
|
||||
} else {
|
||||
updateData.workspaceSharingEnabledBy = null;
|
||||
updateData.workspaceSharingEnabledAt = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Update report in database
|
||||
await db
|
||||
.update(reportFiles)
|
||||
.set(updateData)
|
||||
.where(
|
||||
and(
|
||||
eq(reportFiles.id, reportId),
|
||||
eq(reportFiles.organizationId, organizationId),
|
||||
isNull(reportFiles.deletedAt)
|
||||
)
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error updating report:', {
|
||||
reportId,
|
||||
organizationId,
|
||||
error: error instanceof Error ? error.message : error,
|
||||
});
|
||||
|
||||
// Re-throw with more context
|
||||
if (error instanceof Error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
throw new Error('Failed to update report');
|
||||
}
|
||||
};
|
|
@ -0,0 +1,13 @@
|
|||
import { z } from 'zod';
|
||||
|
||||
export const AssetCollectionSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
description: z.string().nullable().optional(),
|
||||
});
|
||||
|
||||
export type AssetCollection = z.infer<typeof AssetCollectionSchema>;
|
||||
|
||||
export const AssetCollectionsSchema = z.array(AssetCollectionSchema);
|
||||
|
||||
export type AssetCollections = z.infer<typeof AssetCollectionsSchema>;
|
|
@ -1,3 +1,4 @@
|
|||
import { ReportElementsSchema } from '@buster/database';
|
||||
import { AutoformatPlugin } from '@platejs/autoformat';
|
||||
import {
|
||||
BaseBasicBlocksPlugin,
|
||||
|
@ -22,7 +23,6 @@ import {
|
|||
BaseUnderlinePlugin,
|
||||
} from '@platejs/basic-nodes';
|
||||
import { createSlateEditor } from 'platejs';
|
||||
import { ReportElementsSchema } from '../../../../database/src/schema-types/report-elements';
|
||||
import { MarkdownPlugin } from './MarkdownPlugin';
|
||||
|
||||
const serverNode = [
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import type { ReportElement } from '../../../database/src/schema-types/report-elements';
|
||||
import type { ReportElement } from '@buster/database';
|
||||
|
||||
export const SAMPLE_REPORT_ELEMENTS = [
|
||||
{
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import type { ReportElement, ReportElements } from '@buster/database';
|
||||
import { ReportElementSchema } from '@buster/database';
|
||||
import type { ReportElements } from '@buster/database';
|
||||
import { z } from 'zod';
|
||||
import { AssetCollectionsSchema } from '../collections/shared-asset-collections';
|
||||
import { IndividualPermissionsSchema } from '../shared-permissions';
|
||||
import { VersionsSchema } from '../version-shared';
|
||||
|
||||
export const ReportListItemSchema = z.object({
|
||||
id: z.string(),
|
||||
|
@ -12,28 +14,20 @@ export const ReportListItemSchema = z.object({
|
|||
publicly_accessible: z.boolean(),
|
||||
});
|
||||
|
||||
export const ReportIndividualResponseSchema: z.ZodType<{
|
||||
id: string;
|
||||
name: string;
|
||||
file_name: string;
|
||||
description: string;
|
||||
created_by: string;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
deleted_at: string | null;
|
||||
publicly_accessible: boolean;
|
||||
content: ReportElement[];
|
||||
}> = z.object({
|
||||
export const ReportIndividualResponseSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
file_name: z.string(),
|
||||
description: z.string(),
|
||||
created_by: z.string(),
|
||||
created_at: z.string(),
|
||||
updated_at: z.string(),
|
||||
deleted_at: z.string().nullable(),
|
||||
created_by_id: z.string(),
|
||||
created_by_name: z.string().nullable(),
|
||||
created_by_avatar: z.string().nullable(),
|
||||
publicly_accessible: z.boolean(),
|
||||
content: z.array(ReportElementSchema) as z.ZodType<ReportElements>,
|
||||
version_number: z.number(),
|
||||
version_history: VersionsSchema,
|
||||
collections: AssetCollectionsSchema,
|
||||
individual_permissions: IndividualPermissionsSchema,
|
||||
content: z.any() as z.ZodType<ReportElements>, //we use any here because we don't know the type of the content, will be validated in the database
|
||||
});
|
||||
|
||||
export type ReportListItem = z.infer<typeof ReportListItemSchema>;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { ReportElementSchema, type ReportElements } from '@buster/database';
|
||||
import type { ReportElements } from '@buster/database';
|
||||
import { z } from 'zod';
|
||||
import { WorkspaceSharingSchema } from '../shared-permissions';
|
||||
import { PaginatedRequestSchema } from '../type-utilities/pagination';
|
||||
|
||||
export const GetReportsListRequestSchema = PaginatedRequestSchema;
|
||||
|
@ -8,13 +9,18 @@ export const GetReportsListRequestSchema = PaginatedRequestSchema;
|
|||
export const UpdateReportRequestSchema = z
|
||||
.object({
|
||||
name: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
publicly_accessible: z.boolean().optional(),
|
||||
content: z.lazy(() => z.array(ReportElementSchema)).optional() as z.ZodOptional<
|
||||
z.ZodType<ReportElements>
|
||||
>,
|
||||
content: z.any().optional() as z.ZodOptional<z.ZodType<ReportElements>>, //we use any here because we don't know the type of the content, will be validated in the database
|
||||
})
|
||||
.partial();
|
||||
|
||||
export type UpdateReportRequest = z.infer<typeof UpdateReportRequestSchema>;
|
||||
export type GetReportsListRequest = z.infer<typeof GetReportsListRequestSchema>;
|
||||
|
||||
export const ShareUpdateRequestSchema = z.object({
|
||||
publicly_accessible: z.boolean().optional(),
|
||||
public_expiry_date: z.string().optional(),
|
||||
public_password: z.string().optional(),
|
||||
workspace_sharing: WorkspaceSharingSchema.optional(),
|
||||
});
|
||||
|
||||
export type ShareUpdateRequest = z.infer<typeof ShareUpdateRequestSchema>;
|
||||
|
|
|
@ -4,7 +4,9 @@ import { ReportIndividualResponseSchema, ReportListItemSchema } from './reports.
|
|||
|
||||
export const GetReportsListResponseSchema = PaginatedResponseSchema(ReportListItemSchema);
|
||||
export const UpdateReportResponseSchema = ReportIndividualResponseSchema;
|
||||
export const ShareUpdateResponseSchema = ReportIndividualResponseSchema;
|
||||
|
||||
export type GetReportsListResponse = z.infer<typeof GetReportsListResponseSchema>;
|
||||
export type UpdateReportResponse = z.infer<typeof UpdateReportResponseSchema>;
|
||||
export type GetReportIndividualResponse = z.infer<typeof ReportIndividualResponseSchema>;
|
||||
export type ShareUpdateResponse = z.infer<typeof ShareUpdateResponseSchema>;
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
import type { assetPermissionRoleEnum, workspaceSharingEnum } from '@buster/database';
|
||||
import { z } from 'zod';
|
||||
|
||||
type AssetPermissionRoleBase = (typeof assetPermissionRoleEnum.enumValues)[number];
|
||||
const AssetPermissionRoleEnums: Record<AssetPermissionRoleBase, AssetPermissionRoleBase> =
|
||||
Object.freeze({
|
||||
owner: 'owner',
|
||||
viewer: 'viewer',
|
||||
full_access: 'full_access',
|
||||
can_edit: 'can_edit',
|
||||
can_filter: 'can_filter',
|
||||
can_view: 'can_view',
|
||||
});
|
||||
|
||||
export const AssetPermissionRoleSchema = z.enum(
|
||||
Object.values(AssetPermissionRoleEnums) as [AssetPermissionRoleBase, ...AssetPermissionRoleBase[]]
|
||||
);
|
||||
|
||||
export const IndividualPermissionSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string().nullable(),
|
||||
email: z.string(),
|
||||
avatar_url: z.string().nullable(),
|
||||
role: AssetPermissionRoleSchema,
|
||||
});
|
||||
|
||||
export type IndividualPermission = z.infer<typeof IndividualPermissionSchema>;
|
||||
|
||||
export const IndividualPermissionsSchema = z.array(IndividualPermissionSchema);
|
||||
|
||||
export type IndividualPermissions = z.infer<typeof IndividualPermissionsSchema>;
|
||||
|
||||
type WorkspaceSharingBase = (typeof workspaceSharingEnum.enumValues)[number];
|
||||
const WorkspaceSharingEnums: Record<WorkspaceSharingBase, WorkspaceSharingBase> = Object.freeze({
|
||||
none: 'none',
|
||||
can_view: 'can_view',
|
||||
can_edit: 'can_edit',
|
||||
full_access: 'full_access',
|
||||
});
|
||||
|
||||
export const WorkspaceSharingSchema = z.enum(
|
||||
Object.values(WorkspaceSharingEnums) as [WorkspaceSharingBase, ...WorkspaceSharingBase[]]
|
||||
);
|
|
@ -0,0 +1,12 @@
|
|||
import { z } from 'zod';
|
||||
|
||||
export const VersionSchema = z.object({
|
||||
version_number: z.number(),
|
||||
updated_at: z.string(),
|
||||
});
|
||||
|
||||
export type Version = z.infer<typeof VersionSchema>;
|
||||
|
||||
export const VersionsSchema = z.array(VersionSchema);
|
||||
|
||||
export type Versions = z.infer<typeof VersionsSchema>;
|
Loading…
Reference in New Issue