11import { User } from "@/features/auth/types" ;
2- import { useQuery } from "@tanstack/react-query" ;
32import { useRouter } from "next/router" ;
4- import { useState } from "react" ;
3+ import { useEffect , useState } from "react" ;
54import { matrixUserStore } from "../stores/matrixUserStore" ;
5+ import { MatrixUserInterface } from "../types" ;
66import {
77 completeOidcLogin ,
88 getOIDCAuthUrl ,
@@ -11,77 +11,94 @@ import {
1111import { fetchHomeserverForEmail } from "../utils/autodiscovery" ;
1212
1313const OIDC_HS = 'oidc_hs' ;
14- const OIDC_RESPONSE_MODE = 'oidc_response_mode' ;
1514
1615export const useMatrixChatUser = ( user : User | null | undefined ) => {
1716 const router = useRouter ( ) ;
17+ const [ chatUser , setChatUser ] = useState < MatrixUserInterface | null > ( null ) ;
1818 const [ isProcessingCallback , setIsProcessingCallback ] = useState ( false ) ;
19+ const [ isStartOidcFlow , setisStartOidcFlow ] = useState ( false ) ;
1920
20- const { data : chatUser = null } = useQuery ( {
21- queryKey : [ 'useMatrixChatUser' , user ] , // Refetch when chatUser changes
22- queryFn : async ( ) => {
21+ useEffect ( ( ) => {
22+ if ( ! user ) return ;
23+
24+ const initializeUser = async ( ) => {
2325 const currentUser = matrixUserStore . getUser ( ) ;
26+ let currentHomeserverSelected = sessionStorage . getItem ( OIDC_HS ) ;
27+
2428 if ( currentUser ) {
2529 console . log ( '**** already has user' ) ;
2630 return currentUser ;
2731 }
28- let currentHomeserverSelected = sessionStorage . get ( OIDC_HS ) ;
29- // Check if we're in OIDC callback
30- const { code, state } = router . query ;
31- if ( code && state ) {
32- console . log ( '**** Processing OIDC callback' ) ;
33- setIsProcessingCallback ( true ) ;
34- const responseMode = sessionStorage . get ( OIDC_RESPONSE_MODE ) || 'fragment' ;
35- const oidcResult = await completeOidcLogin ( { code, state } , responseMode ) ;
36- const {
37- user_id : userId ,
38- device_id : deviceId ,
39- is_guest : isGuest ,
40- } = await getUserIdFromAccessToken ( oidcResult . accessToken , currentHomeserverSelected ) ;
41-
42- const matrixUser = {
32+
33+ console . log ( '**** No user found, fetching new user' ) ;
34+ setisStartOidcFlow ( true ) ;
35+ // Find correct homeserver url
36+ // TODO Should use user?.email, for now only using hardcoded email
37+ let email = user ?. email || '' ;
38+ if ( process . env . NODE_ENV === 'development' ) {
39+ email = 'marc3@tchap.beta.gouv.fr' ;
40+ }
41+ if ( ! currentHomeserverSelected ) {
42+ const hs = await fetchHomeserverForEmail ( email ) ;
43+ currentHomeserverSelected = hs ! . base_url ;
44+ sessionStorage . setItem ( OIDC_HS , hs ! . base_url ) ;
45+ }
46+ const authUrl = await getOIDCAuthUrl ( currentHomeserverSelected , email ) ;
47+ setisStartOidcFlow ( false ) ;
48+ // start oidc flow in tchap MAS
49+ window . location . href = authUrl ;
50+ }
51+
52+ initializeUser ( ) ;
53+
54+ } , [ user ] ) ;
55+
56+ // Effect 1: Handle OIDC callback (independent of user prop)
57+ useEffect ( ( ) => {
58+ if ( ! router . isReady ) return ;
59+ const { code, state } = router . query ;
60+ console . log ( "*** code, state" , code , state ) ;
61+ if ( ! code || ! state || typeof code !== 'string' || typeof state !== 'string' ) return ;
62+ console . log ( "*** processing callback oidc" ) ;
63+
64+ const processCallback = async ( ) => {
65+ setIsProcessingCallback ( true ) ;
66+ try {
67+ const currentHomeserverSelected = sessionStorage . getItem ( OIDC_HS ) ;
68+ const oidcResult = await completeOidcLogin ( { code, state } ) ;
69+
70+ if ( ! currentHomeserverSelected ) {
71+ throw new Error ( "No homeserver was set" ) ;
72+ }
73+
74+ const { user_id : userId , device_id : deviceId , is_guest : isGuest } =
75+ await getUserIdFromAccessToken ( oidcResult . accessToken , currentHomeserverSelected ) ;
76+
77+ const matrixUser : MatrixUserInterface = {
4378 homeserverUrl : currentHomeserverSelected ,
4479 mxId : userId ,
4580 deviceId : deviceId ,
4681 accessToken : oidcResult . accessToken ,
4782 refreshToken : oidcResult . refreshToken ,
4883 guest : isGuest ,
4984 } ;
85+
5086 matrixUserStore . saveUser ( matrixUser ) ;
5187 matrixUserStore . persistOIDC (
5288 oidcResult . clientId ,
5389 oidcResult . issuer ,
5490 oidcResult . idToken ,
5591 ) ;
56- // Clean up URL params
92+
93+ setChatUser ( matrixUser ) ;
5794 router . replace ( router . pathname , undefined , { shallow : true } ) ;
95+ } finally {
5896 setIsProcessingCallback ( false ) ;
59- return matrixUser ;
6097 }
98+ } ;
6199
62- console . log ( '**** No user found, fetching new user' ) ;
63- // Find correct homeserver url
64- // TODO Should use user?.email, for now only using hardcoded email
65- let email = user ?. email || '' ;
66- if ( process . env . NODE_ENV === 'development' ) {
67- email = 'marc3@tchap.beta.gouv.fr' ;
68- }
69- if ( ! currentHomeserverSelected ) {
70- const hs = await fetchHomeserverForEmail ( email ) ;
71- currentHomeserverSelected = hs ! . base_url ;
72- sessionStorage . setItem ( OIDC_HS , hs ! . base_url ) ;
73- }
74- const { authUrl, responseMode } = await getOIDCAuthUrl ( currentHomeserverSelected , email ) ;
75- sessionStorage . setItem ( OIDC_RESPONSE_MODE , responseMode ) ;
100+ processCallback ( ) ;
101+ } , [ router . isReady , router . query . code , router . query . state , router . pathname ] ) ;
76102
77- // start oidc flow in tchap MAS
78- window . location . href = authUrl ;
79- return null ;
80- } ,
81- enabled : ! ! user , // Only run query when user exists
82- staleTime : Infinity , // Client doesn't stale
83- retry : 1 ,
84- } ) ;
85-
86- return { chatUser, isProcessingCallback } ;
103+ return { chatUser, isProcessingCallback, isStartOidcFlow } ;
87104} ;
0 commit comments