mirror of https://github.com/buster-so/buster.git
Merge pull request #1204 from buster-so/wells-bus-1987-add-public-password-field-to-chats-table
adding the public_password field for chats table
This commit is contained in:
commit
a61fe804c2
|
@ -1,12 +1,10 @@
|
|||
import { checkPermission } from '@buster/access-controls';
|
||||
import type { User } from '@buster/database/queries';
|
||||
import { getChatWithDetails, getMessagesForChatWithUserDetails } from '@buster/database/queries';
|
||||
import {
|
||||
getChatWithDetails,
|
||||
getMessagesForChatWithUserDetails,
|
||||
} from '@buster/database/queries';
|
||||
import {
|
||||
GetChatRequestParamsSchema,
|
||||
GetChatRequestQuerySchema,
|
||||
type GetChatResponse,
|
||||
GetChatRequestSchema,
|
||||
} from '@buster/server-shared/chats';
|
||||
import { zValidator } from '@hono/zod-validator';
|
||||
import { Hono } from 'hono';
|
||||
|
@ -17,18 +15,34 @@ import { buildChatWithMessages } from '../services/chat-helpers';
|
|||
interface GetChatHandlerParams {
|
||||
chatId: string;
|
||||
user: User;
|
||||
userSuppliedPassword?: string;
|
||||
}
|
||||
|
||||
const app = new Hono().get('/', zValidator('param', GetChatRequestSchema), async (c) => {
|
||||
const { id } = c.req.valid('param');
|
||||
const user = c.get('busterUser');
|
||||
const app = new Hono().get(
|
||||
'/',
|
||||
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;
|
||||
|
||||
|
@ -37,7 +51,7 @@ export default app;
|
|||
* This is the TypeScript equivalent of the Rust get_chat_handler
|
||||
*/
|
||||
export async function getChatHandler(params: GetChatHandlerParams): Promise<GetChatResponse> {
|
||||
const { chatId, user } = params;
|
||||
const { chatId, user, userSuppliedPassword } = params;
|
||||
|
||||
// Fetch chat with messages and related data
|
||||
const chatData = await getChatWithDetails({
|
||||
|
@ -64,6 +78,8 @@ export async function getChatHandler(params: GetChatHandlerParams): Promise<GetC
|
|||
workspaceSharing: chat.workspaceSharing || 'none',
|
||||
publiclyAccessible: chat.publiclyAccessible || false,
|
||||
publicExpiryDate: chat.publicExpiryDate ?? undefined,
|
||||
publicPassword: chat.publicPassword ?? undefined,
|
||||
userSuppliedPassword,
|
||||
});
|
||||
|
||||
if (!hasAccess || !effectiveRole) {
|
||||
|
|
|
@ -203,7 +203,7 @@ export async function buildChatWithMessages(
|
|||
publicly_accessible: chat.publiclyAccessible || false,
|
||||
public_expiry_date: chat.publicExpiryDate || null,
|
||||
public_enabled_by: publiclyEnabledBy,
|
||||
public_password: null, // password not implemented yet
|
||||
public_password: chat.publicPassword || null,
|
||||
permission,
|
||||
workspace_sharing: chat.workspaceSharing || 'none',
|
||||
workspace_member_count: workspaceMemberCount,
|
||||
|
|
|
@ -2,7 +2,7 @@ import type {
|
|||
DeleteChatsRequest,
|
||||
DuplicateChatRequest,
|
||||
DuplicateChatResponse,
|
||||
GetChatRequest,
|
||||
GetChatRequestParams,
|
||||
GetChatResponse,
|
||||
GetLogsListRequest,
|
||||
GetLogsListResponse,
|
||||
|
@ -30,7 +30,7 @@ export const getListLogs = async (params?: GetLogsListRequest): Promise<GetLogsL
|
|||
.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);
|
||||
};
|
||||
|
||||
|
|
|
@ -62,7 +62,11 @@ export async function checkMetricDashboardAccess(
|
|||
* 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.
|
||||
*/
|
||||
export async function checkMetricChatAccess(metricId: string, user: User): Promise<boolean> {
|
||||
export async function checkMetricChatAccess(
|
||||
metricId: string,
|
||||
user: User,
|
||||
userSuppliedPassword?: string
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
// Get all chats containing this metric with their workspace sharing info
|
||||
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',
|
||||
publiclyAccessible: chat.publiclyAccessible,
|
||||
publicExpiryDate: chat.publicExpiryDate ?? undefined,
|
||||
publicPassword: undefined, // We don't support passwords on the chats table
|
||||
userSuppliedPassword: undefined, // We don't support passwords on the chats table
|
||||
publicPassword: chat.publicPassword ?? undefined,
|
||||
userSuppliedPassword: userSuppliedPassword,
|
||||
});
|
||||
|
||||
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.
|
||||
* 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 {
|
||||
// Get all chats containing this dashboard with their workspace sharing info
|
||||
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',
|
||||
publiclyAccessible: chat.publiclyAccessible,
|
||||
publicExpiryDate: chat.publicExpiryDate ?? undefined,
|
||||
publicPassword: undefined, // We don't support passwords on the chats table
|
||||
userSuppliedPassword: undefined, // We don't support passwords on the chats table
|
||||
publicPassword: chat.publicPassword ?? undefined,
|
||||
userSuppliedPassword: userSuppliedPassword,
|
||||
});
|
||||
|
||||
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.
|
||||
* 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 {
|
||||
// Get all chats containing this dashboard with their workspace sharing info
|
||||
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',
|
||||
publiclyAccessible: chat.publiclyAccessible,
|
||||
publicExpiryDate: chat.publicExpiryDate ?? undefined,
|
||||
publicPassword: undefined, // We don't support passwords on the chats table
|
||||
userSuppliedPassword: undefined, // We don't support passwords on the chats table
|
||||
publicPassword: chat.publicPassword ?? undefined,
|
||||
userSuppliedPassword: userSuppliedPassword,
|
||||
});
|
||||
|
||||
if (hasAccess) {
|
||||
|
@ -425,7 +437,7 @@ export async function checkCascadingPermissions(
|
|||
break;
|
||||
}
|
||||
|
||||
const chatAccess = await checkMetricChatAccess(assetId, user);
|
||||
const chatAccess = await checkMetricChatAccess(assetId, user, userSuppliedPassword);
|
||||
if (chatAccess) {
|
||||
hasAccess = true;
|
||||
break;
|
||||
|
@ -447,7 +459,11 @@ export async function checkCascadingPermissions(
|
|||
|
||||
case 'dashboard_file': {
|
||||
// Check access through chats and collections
|
||||
const dashboardChatAccess = await checkDashboardChatAccess(assetId, user);
|
||||
const dashboardChatAccess = await checkDashboardChatAccess(
|
||||
assetId,
|
||||
user,
|
||||
userSuppliedPassword
|
||||
);
|
||||
if (dashboardChatAccess) {
|
||||
hasAccess = true;
|
||||
break;
|
||||
|
@ -473,7 +489,7 @@ export async function checkCascadingPermissions(
|
|||
|
||||
case 'report_file': {
|
||||
// Check access through chats and collections
|
||||
const reportChatAccess = await checkReportChatAccess(assetId, user);
|
||||
const reportChatAccess = await checkReportChatAccess(assetId, user, userSuppliedPassword);
|
||||
if (reportChatAccess) {
|
||||
hasAccess = true;
|
||||
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,
|
||||
"tag": "0110_third_ozymandias",
|
||||
"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;
|
||||
publiclyAccessible: boolean;
|
||||
publicExpiryDate: string | null;
|
||||
publicPassword: string | null;
|
||||
}
|
||||
|
||||
export async function checkChatsContainingAsset(
|
||||
|
@ -22,6 +23,7 @@ export async function checkChatsContainingAsset(
|
|||
workspaceSharing: chats.workspaceSharing,
|
||||
publiclyAccessible: chats.publiclyAccessible,
|
||||
publicExpiryDate: chats.publicExpiryDate,
|
||||
publicPassword: chats.publicPassword,
|
||||
})
|
||||
.from(messagesToFiles)
|
||||
.innerJoin(messages, eq(messages.id, messagesToFiles.messageId))
|
||||
|
|
|
@ -847,6 +847,7 @@ export const chats = pgTable(
|
|||
withTimezone: true,
|
||||
mode: 'string',
|
||||
}),
|
||||
publicPassword: text('public_password'),
|
||||
mostRecentFileId: uuid('most_recent_file_id'),
|
||||
mostRecentFileType: assetTypeEnum('most_recent_file_type'),
|
||||
mostRecentVersionNumber: integer('most_recent_version_number'),
|
||||
|
|
|
@ -13,11 +13,16 @@ export const GetChatsRequestSchemaV2 = PaginatedRequestSchema;
|
|||
export type GetChatsRequestV2 = z.infer<typeof GetChatsRequestSchemaV2>;
|
||||
|
||||
// Request for getting a single chat
|
||||
export const GetChatRequestSchema = z.object({
|
||||
export const GetChatRequestParamsSchema = z.object({
|
||||
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
|
||||
export const DeleteChatsRequestSchema = z.array(z.string());
|
||||
|
|
Loading…
Reference in New Issue