@@ -276,11 +276,14 @@ function OrganizationList({provisioningApiUrl, onConnect}: OrganizationListProps
276276 throw new Error ( 'Invalid login response' ) ;
277277 }
278278
279+ console . log ( '[org-setup] login response headers:' , JSON . stringify ( loginRes . headers ) ) ;
280+ console . log ( '[org-setup] token extracted:' , token ? `${ token . substring ( 0 , 8 ) } ...` : 'NONE' ) ;
281+
279282 if ( ! token ) {
280283 throw new Error ( 'Login succeeded but no auth token received' ) ;
281284 }
282285
283- // 3. Create team ( or get existing)
286+ // 3. Create team or join existing one
284287 const teamName = sanitizeTeamName ( resolvedOrg . name ) ;
285288 let teamId : string ;
286289
@@ -301,19 +304,38 @@ function OrganizationList({provisioningApiUrl, onConnect}: OrganizationListProps
301304 const team = JSON . parse ( createTeamRes . body ) ;
302305 teamId = team . id ;
303306 } else {
304- // Team may already exist (409) or user lacks permission to create (403) — try to join existing
305- const getTeamRes = await proxyFetch ( `${ serverUrl } /api/v4/teams/name/ ${ teamName } ` , {
307+ // Team already exists — get all teams user can join and find it
308+ const allTeamsRes = await proxyFetch ( `${ serverUrl } /api/v4/teams?page=0&per_page=200 ` , {
306309 headers : { 'Authorization' : `Bearer ${ token } ` } ,
307310 } ) ;
308- if ( ! getTeamRes . ok ) {
309- throw new Error ( 'Failed to find existing team' ) ;
311+
312+ if ( ! allTeamsRes . ok ) {
313+ throw new Error ( 'Failed to list teams' ) ;
314+ }
315+
316+ const allTeams = JSON . parse ( allTeamsRes . body ) ;
317+ const match = allTeams . find ( ( t : { name : string } ) => t . name === teamName ) ;
318+
319+ if ( match ) {
320+ teamId = match . id ;
321+ } else {
322+ // Last resort: extract team ID from the detailed_error in the create response
323+ try {
324+ const err = JSON . parse ( createTeamRes . body ) ;
325+ const idMatch = err . detailed_error ?. match ( / i d = ( [ a - z 0 - 9 ] + ) / ) ;
326+ if ( idMatch ) {
327+ teamId = idMatch [ 1 ] ;
328+ } else {
329+ throw new Error ( 'Could not find team' ) ;
330+ }
331+ } catch {
332+ throw new Error ( 'Team exists but could not be found. Ask an admin to invite you.' ) ;
333+ }
310334 }
311- const team = JSON . parse ( getTeamRes . body ) ;
312- teamId = team . id ;
313335 }
314336
315337 // 4. Join team
316- await proxyFetch ( `${ serverUrl } /api/v4/teams/${ teamId } /members` , {
338+ const joinRes = await proxyFetch ( `${ serverUrl } /api/v4/teams/${ teamId } /members` , {
317339 method : 'POST' ,
318340 headers : {
319341 'Content-Type' : 'application/json' ,
@@ -325,11 +347,46 @@ function OrganizationList({provisioningApiUrl, onConnect}: OrganizationListProps
325347 } ) ,
326348 } ) ;
327349
350+ console . log ( '[org-setup] join team response:' , joinRes . status ) ;
351+
328352 // 5. Set auth cookie so the Mattermost web app loads already logged in
329353 await window . desktop . setServerAuthCookie ( serverUrl , token , user . id ) ;
330354
331- // 6. Done
332- onConnect ( { url : serverUrl , name : resolvedOrg . name } ) ;
355+ // 6. Skip all Mattermost onboarding/landing pages via preferences API
356+ const authHeaders = {
357+ 'Content-Type' : 'application/json' ,
358+ 'Authorization' : `Bearer ${ token } ` ,
359+ } ;
360+
361+ // Mark tutorial as completed, skip "tips", skip landing page
362+ await proxyFetch ( `${ serverUrl } /api/v4/users/${ user . id } /preferences` , {
363+ method : 'PUT' ,
364+ headers : authHeaders ,
365+ body : JSON . stringify ( [
366+ { user_id : user . id , category : 'tutorial_step' , name : user . id , value : '999' } ,
367+ { user_id : user . id , category : 'insights' , name : 'insights_tutorial_state' , value : '{"insights_modal_viewed":true}' } ,
368+ { user_id : user . id , category : 'recommended_next_steps' , name : 'hide' , value : 'true' } ,
369+ { user_id : user . id , category : 'drafts' , name : 'drafts_tour_tip_showed' , value : '{"drafts_tour_tip_showed":true}' } ,
370+ { user_id : user . id , category : 'crt_thread_pane_step' , name : user . id , value : '999' } ,
371+ ] ) ,
372+ } ) ;
373+
374+ // Also complete onboarding via the dedicated endpoint
375+ await proxyFetch ( `${ serverUrl } /api/v4/users/${ user . id } /preferences` , {
376+ method : 'PUT' ,
377+ headers : authHeaders ,
378+ body : JSON . stringify ( [
379+ { user_id : user . id , category : 'system_notice' , name : 'GMasDM' , value : 'true' } ,
380+ { user_id : user . id , category : 'onboarding_task_list' , name : 'onboarding_task_list_show' , value : 'false' } ,
381+ { user_id : user . id , category : 'onboarding_task_list' , name : 'onboarding_task_list_open' , value : 'false' } ,
382+ ] ) ,
383+ } ) ;
384+
385+ // 7. Store auto-login credentials so the server view can log in automatically
386+ await window . desktop . storeAutoLogin ( serverUrl , email , HARDCODED_PASSWORD ) ;
387+
388+ // 8. Done — pass server URL and initial path to skip Mattermost landing pages
389+ onConnect ( { url : serverUrl , name : resolvedOrg . name , initialPath : `/${ teamName } /channels/town-square` } ) ;
333390 } catch ( err ) {
334391 setSetupError ( err instanceof Error ? err . message : 'Something went wrong' ) ;
335392 setStep ( 'username' ) ;
0 commit comments