mirror of https://github.com/buster-so/buster.git
adding the public_password field for chats table
This commit is contained in:
parent
1f4276e6ee
commit
16892fe64e
|
@ -1,12 +1,10 @@
|
||||||
import { checkPermission } from '@buster/access-controls';
|
import { checkPermission } from '@buster/access-controls';
|
||||||
import type { User } from '@buster/database/queries';
|
import type { User } from '@buster/database/queries';
|
||||||
|
import { getChatWithDetails, getMessagesForChatWithUserDetails } from '@buster/database/queries';
|
||||||
import {
|
import {
|
||||||
getChatWithDetails,
|
GetChatRequestParamsSchema,
|
||||||
getMessagesForChatWithUserDetails,
|
GetChatRequestQuerySchema,
|
||||||
} from '@buster/database/queries';
|
|
||||||
import {
|
|
||||||
type GetChatResponse,
|
type GetChatResponse,
|
||||||
GetChatRequestSchema,
|
|
||||||
} from '@buster/server-shared/chats';
|
} from '@buster/server-shared/chats';
|
||||||
import { zValidator } from '@hono/zod-validator';
|
import { zValidator } from '@hono/zod-validator';
|
||||||
import { Hono } from 'hono';
|
import { Hono } from 'hono';
|
||||||
|
@ -17,18 +15,34 @@ import { buildChatWithMessages } from '../services/chat-helpers';
|
||||||
interface GetChatHandlerParams {
|
interface GetChatHandlerParams {
|
||||||
chatId: string;
|
chatId: string;
|
||||||
user: User;
|
user: User;
|
||||||
|
userSuppliedPassword?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const app = new Hono().get('/', zValidator('param', GetChatRequestSchema), async (c) => {
|
const app = new Hono().get(
|
||||||
const { id } = c.req.valid('param');
|
'/',
|
||||||
const user = c.get('busterUser');
|
zValidator('param', GetChatRequestParamsSchema),
|
||||||
|
zValidator('query', GetChatRequestQuerySchema),
|
||||||
|
async (c) => {
|
||||||
|
const { id } = c.req.valid('param');
|
||||||
|
const { password } = c.req.valid('query');
|
||||||
|
const user = c.get('busterUser');
|
||||||
|
|
||||||
console.info(`Processing GET request for chat with ID: ${id}, user_id: ${user.id}`);
|
console.info(`Processing GET request for chat with ID: ${id}, user_id: ${user.id}`);
|
||||||
|
|
||||||
const response: GetChatResponse = await getChatHandler({ chatId: id, user });
|
const getChatHandlerParams: GetChatHandlerParams = {
|
||||||
|
chatId: id,
|
||||||
|
user,
|
||||||
|
};
|
||||||
|
|
||||||
return c.json(response);
|
if (password) {
|
||||||
});
|
getChatHandlerParams.userSuppliedPassword = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response: GetChatResponse = await getChatHandler(getChatHandlerParams);
|
||||||
|
|
||||||
|
return c.json(response);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
export default app;
|
export default app;
|
||||||
|
|
||||||
|
@ -37,7 +51,7 @@ export default app;
|
||||||
* This is the TypeScript equivalent of the Rust get_chat_handler
|
* This is the TypeScript equivalent of the Rust get_chat_handler
|
||||||
*/
|
*/
|
||||||
export async function getChatHandler(params: GetChatHandlerParams): Promise<GetChatResponse> {
|
export async function getChatHandler(params: GetChatHandlerParams): Promise<GetChatResponse> {
|
||||||
const { chatId, user } = params;
|
const { chatId, user, userSuppliedPassword } = params;
|
||||||
|
|
||||||
// Fetch chat with messages and related data
|
// Fetch chat with messages and related data
|
||||||
const chatData = await getChatWithDetails({
|
const chatData = await getChatWithDetails({
|
||||||
|
@ -64,6 +78,8 @@ export async function getChatHandler(params: GetChatHandlerParams): Promise<GetC
|
||||||
workspaceSharing: chat.workspaceSharing || 'none',
|
workspaceSharing: chat.workspaceSharing || 'none',
|
||||||
publiclyAccessible: chat.publiclyAccessible || false,
|
publiclyAccessible: chat.publiclyAccessible || false,
|
||||||
publicExpiryDate: chat.publicExpiryDate ?? undefined,
|
publicExpiryDate: chat.publicExpiryDate ?? undefined,
|
||||||
|
publicPassword: chat.publicPassword ?? undefined,
|
||||||
|
userSuppliedPassword,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!hasAccess || !effectiveRole) {
|
if (!hasAccess || !effectiveRole) {
|
||||||
|
|
|
@ -203,7 +203,7 @@ export async function buildChatWithMessages(
|
||||||
publicly_accessible: chat.publiclyAccessible || false,
|
publicly_accessible: chat.publiclyAccessible || false,
|
||||||
public_expiry_date: chat.publicExpiryDate || null,
|
public_expiry_date: chat.publicExpiryDate || null,
|
||||||
public_enabled_by: publiclyEnabledBy,
|
public_enabled_by: publiclyEnabledBy,
|
||||||
public_password: null, // password not implemented yet
|
public_password: chat.publicPassword || null,
|
||||||
permission,
|
permission,
|
||||||
workspace_sharing: chat.workspaceSharing || 'none',
|
workspace_sharing: chat.workspaceSharing || 'none',
|
||||||
workspace_member_count: workspaceMemberCount,
|
workspace_member_count: workspaceMemberCount,
|
||||||
|
|
|
@ -2,7 +2,7 @@ import type {
|
||||||
DeleteChatsRequest,
|
DeleteChatsRequest,
|
||||||
DuplicateChatRequest,
|
DuplicateChatRequest,
|
||||||
DuplicateChatResponse,
|
DuplicateChatResponse,
|
||||||
GetChatRequest,
|
GetChatRequestParams,
|
||||||
GetChatResponse,
|
GetChatResponse,
|
||||||
GetLogsListRequest,
|
GetLogsListRequest,
|
||||||
GetLogsListResponse,
|
GetLogsListResponse,
|
||||||
|
@ -30,7 +30,7 @@ export const getListLogs = async (params?: GetLogsListRequest): Promise<GetLogsL
|
||||||
.then((res) => res.data);
|
.then((res) => res.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getChat = async ({ id }: GetChatRequest): Promise<GetChatResponse> => {
|
export const getChat = async ({ id }: GetChatRequestParams): Promise<GetChatResponse> => {
|
||||||
return mainApiV2.get<GetChatResponse>(`${CHATS_BASE}/${id}`).then((res) => res.data);
|
return mainApiV2.get<GetChatResponse>(`${CHATS_BASE}/${id}`).then((res) => res.data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,11 @@ export async function checkMetricDashboardAccess(
|
||||||
* Check if a user has access to a metric through any chat that contains it.
|
* Check if a user has access to a metric through any chat that contains it.
|
||||||
* If a user has access to a chat (direct, public, or workspace), they can view the metrics in it.
|
* If a user has access to a chat (direct, public, or workspace), they can view the metrics in it.
|
||||||
*/
|
*/
|
||||||
export async function checkMetricChatAccess(metricId: string, user: User): Promise<boolean> {
|
export async function checkMetricChatAccess(
|
||||||
|
metricId: string,
|
||||||
|
user: User,
|
||||||
|
userSuppliedPassword?: string
|
||||||
|
): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
// Get all chats containing this metric with their workspace sharing info
|
// Get all chats containing this metric with their workspace sharing info
|
||||||
const chats = await checkChatsContainingAsset(metricId, 'metric_file');
|
const chats = await checkChatsContainingAsset(metricId, 'metric_file');
|
||||||
|
@ -82,8 +86,8 @@ export async function checkMetricChatAccess(metricId: string, user: User): Promi
|
||||||
workspaceSharing: (chat.workspaceSharing as WorkspaceSharing) ?? 'none',
|
workspaceSharing: (chat.workspaceSharing as WorkspaceSharing) ?? 'none',
|
||||||
publiclyAccessible: chat.publiclyAccessible,
|
publiclyAccessible: chat.publiclyAccessible,
|
||||||
publicExpiryDate: chat.publicExpiryDate ?? undefined,
|
publicExpiryDate: chat.publicExpiryDate ?? undefined,
|
||||||
publicPassword: undefined, // We don't support passwords on the chats table
|
publicPassword: chat.publicPassword ?? undefined,
|
||||||
userSuppliedPassword: undefined, // We don't support passwords on the chats table
|
userSuppliedPassword: userSuppliedPassword,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (hasAccess) {
|
if (hasAccess) {
|
||||||
|
@ -152,7 +156,11 @@ export async function checkMetricReportAccess(
|
||||||
* Check if a user has access to a dashboard through any chat that contains it.
|
* Check if a user has access to a dashboard through any chat that contains it.
|
||||||
* If a user has access to a chat (direct, public, or workspace), they can view the dashboards in it.
|
* If a user has access to a chat (direct, public, or workspace), they can view the dashboards in it.
|
||||||
*/
|
*/
|
||||||
export async function checkDashboardChatAccess(dashboardId: string, user: User): Promise<boolean> {
|
export async function checkDashboardChatAccess(
|
||||||
|
dashboardId: string,
|
||||||
|
user: User,
|
||||||
|
userSuppliedPassword?: string
|
||||||
|
): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
// Get all chats containing this dashboard with their workspace sharing info
|
// Get all chats containing this dashboard with their workspace sharing info
|
||||||
const chats = await checkChatsContainingAsset(dashboardId, 'dashboard_file');
|
const chats = await checkChatsContainingAsset(dashboardId, 'dashboard_file');
|
||||||
|
@ -172,8 +180,8 @@ export async function checkDashboardChatAccess(dashboardId: string, user: User):
|
||||||
workspaceSharing: (chat.workspaceSharing as WorkspaceSharing) ?? 'none',
|
workspaceSharing: (chat.workspaceSharing as WorkspaceSharing) ?? 'none',
|
||||||
publiclyAccessible: chat.publiclyAccessible,
|
publiclyAccessible: chat.publiclyAccessible,
|
||||||
publicExpiryDate: chat.publicExpiryDate ?? undefined,
|
publicExpiryDate: chat.publicExpiryDate ?? undefined,
|
||||||
publicPassword: undefined, // We don't support passwords on the chats table
|
publicPassword: chat.publicPassword ?? undefined,
|
||||||
userSuppliedPassword: undefined, // We don't support passwords on the chats table
|
userSuppliedPassword: userSuppliedPassword,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (hasAccess) {
|
if (hasAccess) {
|
||||||
|
@ -315,7 +323,11 @@ export async function checkChatCollectionAccess(chatId: string, user: User): Pro
|
||||||
* Check if a user has access to a report through any chat that contains it.
|
* Check if a user has access to a report through any chat that contains it.
|
||||||
* If a user has access to a chat (direct, public, or workspace), they can view the reports in it.
|
* If a user has access to a chat (direct, public, or workspace), they can view the reports in it.
|
||||||
*/
|
*/
|
||||||
export async function checkReportChatAccess(reportId: string, user: User): Promise<boolean> {
|
export async function checkReportChatAccess(
|
||||||
|
reportId: string,
|
||||||
|
user: User,
|
||||||
|
userSuppliedPassword?: string
|
||||||
|
): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
// Get all chats containing this dashboard with their workspace sharing info
|
// Get all chats containing this dashboard with their workspace sharing info
|
||||||
const chats = await checkChatsContainingAsset(reportId, 'report_file');
|
const chats = await checkChatsContainingAsset(reportId, 'report_file');
|
||||||
|
@ -335,8 +347,8 @@ export async function checkReportChatAccess(reportId: string, user: User): Promi
|
||||||
workspaceSharing: (chat.workspaceSharing as WorkspaceSharing) ?? 'none',
|
workspaceSharing: (chat.workspaceSharing as WorkspaceSharing) ?? 'none',
|
||||||
publiclyAccessible: chat.publiclyAccessible,
|
publiclyAccessible: chat.publiclyAccessible,
|
||||||
publicExpiryDate: chat.publicExpiryDate ?? undefined,
|
publicExpiryDate: chat.publicExpiryDate ?? undefined,
|
||||||
publicPassword: undefined, // We don't support passwords on the chats table
|
publicPassword: chat.publicPassword ?? undefined,
|
||||||
userSuppliedPassword: undefined, // We don't support passwords on the chats table
|
userSuppliedPassword: userSuppliedPassword,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (hasAccess) {
|
if (hasAccess) {
|
||||||
|
@ -425,7 +437,7 @@ export async function checkCascadingPermissions(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const chatAccess = await checkMetricChatAccess(assetId, user);
|
const chatAccess = await checkMetricChatAccess(assetId, user, userSuppliedPassword);
|
||||||
if (chatAccess) {
|
if (chatAccess) {
|
||||||
hasAccess = true;
|
hasAccess = true;
|
||||||
break;
|
break;
|
||||||
|
@ -447,7 +459,11 @@ export async function checkCascadingPermissions(
|
||||||
|
|
||||||
case 'dashboard_file': {
|
case 'dashboard_file': {
|
||||||
// Check access through chats and collections
|
// Check access through chats and collections
|
||||||
const dashboardChatAccess = await checkDashboardChatAccess(assetId, user);
|
const dashboardChatAccess = await checkDashboardChatAccess(
|
||||||
|
assetId,
|
||||||
|
user,
|
||||||
|
userSuppliedPassword
|
||||||
|
);
|
||||||
if (dashboardChatAccess) {
|
if (dashboardChatAccess) {
|
||||||
hasAccess = true;
|
hasAccess = true;
|
||||||
break;
|
break;
|
||||||
|
@ -473,7 +489,7 @@ export async function checkCascadingPermissions(
|
||||||
|
|
||||||
case 'report_file': {
|
case 'report_file': {
|
||||||
// Check access through chats and collections
|
// Check access through chats and collections
|
||||||
const reportChatAccess = await checkReportChatAccess(assetId, user);
|
const reportChatAccess = await checkReportChatAccess(assetId, user, userSuppliedPassword);
|
||||||
if (reportChatAccess) {
|
if (reportChatAccess) {
|
||||||
hasAccess = true;
|
hasAccess = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
ALTER TABLE "chats" ADD COLUMN "public_password" text;
|
File diff suppressed because it is too large
Load Diff
|
@ -771,6 +771,13 @@
|
||||||
"when": 1758658933810,
|
"when": 1758658933810,
|
||||||
"tag": "0110_third_ozymandias",
|
"tag": "0110_third_ozymandias",
|
||||||
"breakpoints": true
|
"breakpoints": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idx": 111,
|
||||||
|
"version": "7",
|
||||||
|
"when": 1759167570252,
|
||||||
|
"tag": "0111_happy_peter_quill",
|
||||||
|
"breakpoints": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -9,6 +9,7 @@ export interface ChatWithSharing {
|
||||||
workspaceSharing: WorkspaceSharing | null;
|
workspaceSharing: WorkspaceSharing | null;
|
||||||
publiclyAccessible: boolean;
|
publiclyAccessible: boolean;
|
||||||
publicExpiryDate: string | null;
|
publicExpiryDate: string | null;
|
||||||
|
publicPassword: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function checkChatsContainingAsset(
|
export async function checkChatsContainingAsset(
|
||||||
|
@ -22,6 +23,7 @@ export async function checkChatsContainingAsset(
|
||||||
workspaceSharing: chats.workspaceSharing,
|
workspaceSharing: chats.workspaceSharing,
|
||||||
publiclyAccessible: chats.publiclyAccessible,
|
publiclyAccessible: chats.publiclyAccessible,
|
||||||
publicExpiryDate: chats.publicExpiryDate,
|
publicExpiryDate: chats.publicExpiryDate,
|
||||||
|
publicPassword: chats.publicPassword,
|
||||||
})
|
})
|
||||||
.from(messagesToFiles)
|
.from(messagesToFiles)
|
||||||
.innerJoin(messages, eq(messages.id, messagesToFiles.messageId))
|
.innerJoin(messages, eq(messages.id, messagesToFiles.messageId))
|
||||||
|
|
|
@ -847,6 +847,7 @@ export const chats = pgTable(
|
||||||
withTimezone: true,
|
withTimezone: true,
|
||||||
mode: 'string',
|
mode: 'string',
|
||||||
}),
|
}),
|
||||||
|
publicPassword: text('public_password'),
|
||||||
mostRecentFileId: uuid('most_recent_file_id'),
|
mostRecentFileId: uuid('most_recent_file_id'),
|
||||||
mostRecentFileType: assetTypeEnum('most_recent_file_type'),
|
mostRecentFileType: assetTypeEnum('most_recent_file_type'),
|
||||||
mostRecentVersionNumber: integer('most_recent_version_number'),
|
mostRecentVersionNumber: integer('most_recent_version_number'),
|
||||||
|
|
|
@ -13,11 +13,16 @@ export const GetChatsRequestSchemaV2 = PaginatedRequestSchema;
|
||||||
export type GetChatsRequestV2 = z.infer<typeof GetChatsRequestSchemaV2>;
|
export type GetChatsRequestV2 = z.infer<typeof GetChatsRequestSchemaV2>;
|
||||||
|
|
||||||
// Request for getting a single chat
|
// Request for getting a single chat
|
||||||
export const GetChatRequestSchema = z.object({
|
export const GetChatRequestParamsSchema = z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export type GetChatRequest = z.infer<typeof GetChatRequestSchema>;
|
export const GetChatRequestQuerySchema = z.object({
|
||||||
|
password: z.string().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type GetChatRequestQuery = z.infer<typeof GetChatRequestQuerySchema>;
|
||||||
|
export type GetChatRequestParams = z.infer<typeof GetChatRequestParamsSchema>;
|
||||||
|
|
||||||
// Request for deleting multiple chats
|
// Request for deleting multiple chats
|
||||||
export const DeleteChatsRequestSchema = z.array(z.string());
|
export const DeleteChatsRequestSchema = z.array(z.string());
|
||||||
|
|
Loading…
Reference in New Issue