remove url from share and add auth (#260)

This commit is contained in:
arkml 2025-09-15 23:44:01 +05:30 committed by GitHub
parent a7abdc43a5
commit 041ab25b7b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 20 additions and 25 deletions

View file

@ -5,6 +5,7 @@ import { nanoid } from "nanoid";
import { Workflow } from "@/app/lib/types/workflow_types"; import { Workflow } from "@/app/lib/types/workflow_types";
import { db } from "@/app/lib/mongodb"; import { db } from "@/app/lib/mongodb";
import { SHARED_WORKFLOWS_COLLECTION } from "@/src/infrastructure/repositories/mongodb.shared-workflows.indexes"; import { SHARED_WORKFLOWS_COLLECTION } from "@/src/infrastructure/repositories/mongodb.shared-workflows.indexes";
import { requireAuth } from "@/app/lib/auth";
const DEFAULT_TTL_SECONDS = 60 * 60 * 24; // 24 hours const DEFAULT_TTL_SECONDS = 60 * 60 * 24; // 24 hours
@ -26,6 +27,8 @@ function validateWorkflowJson(obj: unknown) {
export async function createSharedWorkflowFromJson(json: string): Promise<{ id: string; ttlSeconds: number; }> export async function createSharedWorkflowFromJson(json: string): Promise<{ id: string; ttlSeconds: number; }>
{ {
// Require an authenticated user (respects guest mode when auth is disabled)
await requireAuth();
const obj = JSON.parse(json); const obj = JSON.parse(json);
const workflow = validateWorkflowJson(obj); const workflow = validateWorkflowJson(obj);
@ -38,23 +41,18 @@ export async function createSharedWorkflowFromJson(json: string): Promise<{ id:
return { id, ttlSeconds: DEFAULT_TTL_SECONDS }; return { id, ttlSeconds: DEFAULT_TTL_SECONDS };
} }
export async function loadSharedWorkflow(idOrUrl: string): Promise<z.infer<typeof Workflow>> { /**
// If it's an http(s) URL, fetch JSON and validate * Load a shared workflow by ephemeral share id stored in MongoDB.
const isHttp = idOrUrl.startsWith('http://') || idOrUrl.startsWith('https://'); * Expected when the query param `shared` is present in the UI.
if (isHttp) { */
const resp = await fetch(idOrUrl, { cache: 'no-store' }); export async function loadSharedWorkflow(id: string): Promise<z.infer<typeof Workflow>> {
if (!resp.ok) { // Ensure caller is authenticated (guest allowed when auth disabled)
throw new Error(`Failed to fetch URL: ${resp.status} ${resp.statusText}`); await requireAuth();
}
const text = await resp.text();
const obj = JSON.parse(text);
return validateWorkflowJson(obj);
}
// Otherwise, look up by shared id in MongoDB // Look up by shared id in MongoDB
const coll = db.collection<SharedWorkflowDoc>(SHARED_WORKFLOWS_COLLECTION); const coll = db.collection<SharedWorkflowDoc>(SHARED_WORKFLOWS_COLLECTION);
const doc = await coll.findOne( const doc = await coll.findOne(
{ _id: idOrUrl }, { _id: id },
{ projection: { workflow: 1, expiresAt: 1 } } { projection: { workflow: 1, expiresAt: 1 } }
); );
if (!doc) { if (!doc) {
@ -65,4 +63,3 @@ export async function loadSharedWorkflow(idOrUrl: string): Promise<z.infer<typeo
} }
return validateWorkflowJson(doc.workflow); return validateWorkflowJson(doc.workflow);
} }

View file

@ -301,13 +301,12 @@ export function BuildAssistantSection() {
const urlPrompt = searchParams.get('prompt'); const urlPrompt = searchParams.get('prompt');
const urlTemplate = searchParams.get('template'); const urlTemplate = searchParams.get('template');
const sharedId = searchParams.get('shared'); const sharedId = searchParams.get('shared');
const importUrl = searchParams.get('importUrl');
const run = async () => { const run = async () => {
if (sharedId || importUrl) { if (sharedId) {
try { try {
setAutoCreateLoading(true); setAutoCreateLoading(true);
const workflowObj = await loadSharedWorkflow(sharedId || importUrl!); const workflowObj = await loadSharedWorkflow(sharedId);
await createProjectFromJsonWithOptions({ await createProjectFromJsonWithOptions({
workflowJson: JSON.stringify(workflowObj), workflowJson: JSON.stringify(workflowObj),
router, router,

View file

@ -151,7 +151,6 @@ export function CreateProject({ defaultName, onOpenProjectPane, isProjectPaneOpe
const urlPrompt = searchParams.get('prompt'); const urlPrompt = searchParams.get('prompt');
const urlTemplate = searchParams.get('template'); const urlTemplate = searchParams.get('template');
const sharedId = searchParams.get('shared'); const sharedId = searchParams.get('shared');
const importUrl = searchParams.get('importUrl');
// Add this effect to update name when defaultName changes // Add this effect to update name when defaultName changes
useEffect(() => { useEffect(() => {
@ -168,13 +167,13 @@ export function CreateProject({ defaultName, onOpenProjectPane, isProjectPaneOpe
// Add effect to handle URL parameters for auto-creation // Add effect to handle URL parameters for auto-creation
useEffect(() => { useEffect(() => {
const handleAutoCreate = async () => { const handleAutoCreate = async () => {
// Auto-create from template/prompt, or import from shared/id/url // Auto-create from template/prompt, or import from shared id
if ((urlPrompt || urlTemplate || sharedId || importUrl) && !importLoading && !autoCreateLoading) { if ((urlPrompt || urlTemplate || sharedId) && !importLoading && !autoCreateLoading) {
setAutoCreateLoading(true); setAutoCreateLoading(true);
try { try {
if (sharedId || importUrl) { if (sharedId) {
// Load workflow via server action (supports id or URL) // Load workflow via server action (by id)
const workflowObj = await loadSharedWorkflow(sharedId || importUrl!); const workflowObj = await loadSharedWorkflow(sharedId);
await createProjectFromJsonWithOptions({ await createProjectFromJsonWithOptions({
workflowJson: JSON.stringify(workflowObj), workflowJson: JSON.stringify(workflowObj),
router, router,
@ -203,7 +202,7 @@ export function CreateProject({ defaultName, onOpenProjectPane, isProjectPaneOpe
}; };
handleAutoCreate(); handleAutoCreate();
}, [urlPrompt, urlTemplate, sharedId, importUrl, importLoading, autoCreateLoading, router]); }, [urlPrompt, urlTemplate, sharedId, importLoading, autoCreateLoading, router]);
// Inject glow animation styles // Inject glow animation styles
useEffect(() => { useEffect(() => {