77 createTaskShareSchema ,
88 shareIdSchema ,
99} from '@/types' ;
10- import type { SharedByUser } from '@/types' ;
10+ import type { SharedByUser } from '@/types/task-sharing' ;
11+ import { TaskShareVisibility } from '@/types/task-sharing' ;
1112import { type TaskShare , AuditLogTargetType } from '@/db' ;
1213import { client as db , taskShares , users } from '@/db/server' ;
1314import { handleError , generateShareToken } from '@/lib/server' ;
@@ -41,6 +42,7 @@ export async function canShareTask(taskId: string): Promise<{
4142 orgRole ?: string ;
4243} > {
4344 try {
45+ // Get authentication info
4446 const authResult = await authorize ( ) ;
4547
4648 if ( ! authResult . success ) {
@@ -56,6 +58,7 @@ export async function canShareTask(taskId: string): Promise<{
5658 orgId,
5759 allowCrossUserAccess : true ,
5860 } ) ;
61+
5962 const task = tasks [ 0 ] ;
6063
6164 if ( ! task ) {
@@ -100,7 +103,11 @@ export async function createTaskShare(data: CreateTaskShareRequest) {
100103 return { success : false , error : 'Invalid request data' } ;
101104 }
102105
103- const { taskId, expirationDays } = result . data ;
106+ const {
107+ taskId,
108+ expirationDays,
109+ visibility = TaskShareVisibility . ORGANIZATION ,
110+ } = result . data ;
104111
105112 const orgSettingsData = await getOrganizationSettings ( ) ;
106113
@@ -142,6 +149,7 @@ export async function createTaskShare(data: CreateTaskShareRequest) {
142149 orgId,
143150 createdByUserId : userId ,
144151 shareToken,
152+ visibility,
145153 expiresAt,
146154 } )
147155 . returning ( ) ;
@@ -158,11 +166,12 @@ export async function createTaskShare(data: CreateTaskShareRequest) {
158166 newValue : {
159167 action : 'created' ,
160168 shareId : insertedShare [ 0 ] . id ,
169+ visibility,
161170 expiresAt : expiresAt . toISOString ( ) ,
162171 taskOwnerId : task . userId ,
163172 sharedByAdmin : orgRole === 'org:admin' && task . userId !== userId ,
164173 } ,
165- description : `Created task share for task ${ taskId } ${
174+ description : `Created ${ visibility } task share for task ${ taskId } ${
166175 orgRole === 'org:admin' && task . userId !== userId
167176 ? ` (admin sharing task created by ${ task . user . name } )`
168177 : ''
@@ -182,8 +191,8 @@ export async function createTaskShare(data: CreateTaskShareRequest) {
182191
183192 return {
184193 success : true ,
185- message : 'Task share created successfully' ,
186194 data : { shareUrl, shareId : newShare . id , expiresAt } ,
195+ message : 'Task share created successfully' ,
187196 } ;
188197 } catch ( error ) {
189198 return handleError ( error , 'task_sharing' ) ;
@@ -198,18 +207,14 @@ export async function getTaskByShareToken(token: string): Promise<{
198207 messages : Message [ ] ;
199208 sharedBy : SharedByUser ;
200209 sharedAt : Date ;
210+ visibility : string ;
201211} | null > {
202212 try {
203- const authResult = await authorize ( ) ;
204-
205- if ( ! authResult . success ) {
206- throw new Error ( 'Authentication required' ) ;
207- }
208-
209213 if ( ! isValidShareToken ( token ) ) {
210214 return null ;
211215 }
212216
217+ // First, get the share without auth check to determine visibility
213218 const [ shareWithUser ] = await db
214219 . select ( {
215220 share : taskShares ,
@@ -221,12 +226,7 @@ export async function getTaskByShareToken(token: string): Promise<{
221226 } )
222227 . from ( taskShares )
223228 . innerJoin ( users , eq ( taskShares . createdByUserId , users . id ) )
224- . where (
225- and (
226- eq ( taskShares . shareToken , token ) ,
227- eq ( taskShares . orgId , authResult . orgId ) ,
228- ) ,
229- )
229+ . where ( eq ( taskShares . shareToken , token ) )
230230 . limit ( 1 ) ;
231231
232232 if ( ! shareWithUser ) {
@@ -239,12 +239,25 @@ export async function getTaskByShareToken(token: string): Promise<{
239239 return null ;
240240 }
241241
242+ // Check visibility and auth requirements
243+ if ( share . visibility === TaskShareVisibility . ORGANIZATION ) {
244+ const authResult = await authorize ( ) ;
245+ const userId = authResult . success ? authResult . userId : null ;
246+ const orgId = authResult . success ? authResult . orgId : null ;
247+
248+ if ( ! userId || ! orgId || orgId !== share . orgId ) {
249+ throw new Error ( 'Authentication required for organization shares' ) ;
250+ }
251+ }
252+ // For public shares, no auth check needed
253+
254+ // Get task data based on visibility
242255 const tasks = await getTasks ( {
243256 taskId : share . taskId ,
244257 orgId : share . orgId ,
245258 allowCrossUserAccess : true ,
259+ skipAuth : share . visibility === TaskShareVisibility . PUBLIC , // Skip auth for public shares
246260 } ) ;
247-
248261 const task = tasks [ 0 ] ;
249262
250263 if ( ! task ) {
@@ -258,6 +271,7 @@ export async function getTaskByShareToken(token: string): Promise<{
258271 messages,
259272 sharedBy : sharedByUser ,
260273 sharedAt : share . createdAt ,
274+ visibility : share . visibility ,
261275 } ;
262276 } catch ( error ) {
263277 console . error (
@@ -281,6 +295,7 @@ export async function deleteTaskShare(shareId: string) {
281295 }
282296
283297 const { userId, orgId, orgRole } = authResult ;
298+
284299 const shareIdResult = shareIdSchema . safeParse ( shareId ) ;
285300
286301 if ( ! shareIdResult . success ) {
0 commit comments