Skip to content

Commit

Permalink
Fix rest source client: create user before registering
Browse files Browse the repository at this point in the history
  • Loading branch information
mpgxvii committed Oct 14, 2024
1 parent c896c88 commit b4d2ef2
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 41 deletions.
23 changes: 12 additions & 11 deletions pages/fitbit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,27 +35,28 @@ const Fitbit: NextPage = () => {
return restSourceClient.redirectToAuthRequestLink()
}

useEffect(() => {
ory.toSession().then(({ data }) => {
const traits = data?.identity?.traits
setTraits(traits)
setProjects(traits.projects) //

})
}, [flowId, router, router.isReady, returnTo])

useEffect(() => {
const handleToken = async () => {
if (!router.isReady) return
if (!router.isReady || !projects.length) return

const token = await restSourceClient.getAccessTokenFromRedirect()
if (token) {
localStorage.setItem("access_token", token)
await restSourceClient.redirectToRestSourceAuthLink(token)
await restSourceClient.redirectToRestSourceAuthLink(token, projects[0])
}
}

handleToken()
}, [router.isReady])

useEffect(() => {
ory.toSession().then(({ data }) => {
const traits = data?.identity?.traits
setTraits(traits)
setProjects(traits.projects)
})
}, [flowId, router, router.isReady, returnTo])
}, [router.isReady, projects])

return (
<>
Expand Down
117 changes: 87 additions & 30 deletions services/rest-source-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,45 @@ export class RestSourceClient {
private readonly GRANT_TYPE = "authorization_code"
private readonly CLIENT_ID = `${publicRuntimeConfig.frontEndClientId}`
private readonly CLIENT_SECRET = `${publicRuntimeConfig.frontEndClientSecret}`
private readonly REGISTRATION_ENDPOINT = `${publicRuntimeConfig.restSourceRegistrationEndpoint}/registrations`
private readonly USER_ENDPOINT = `${publicRuntimeConfig.restSourceRegistrationEndpoint}/users`
private readonly REGISTRATION_ENDPOINT = `${publicRuntimeConfig.restSourceBackendEndpoint}/registrations`
private readonly USER_ENDPOINT = `${publicRuntimeConfig.restSourceBackendEndpoint}/users`
private readonly FRONTEND_ENDPOINT = `${publicRuntimeConfig.restSourceFrontendEndpoint}`
private readonly SOURCE_TYPE = "Oura"

async getRestSourceUser(accessToken: string, project: any): Promise<string | null> {
try {
const response = await fetch(this.USER_ENDPOINT, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({
userId: project.userId,
projectId: project.id,
sourceType: this.SOURCE_TYPE,
startDate: new Date().toISOString(),
}),
})

if (!response.ok) {
const data = await response.json()
if (response.status === 409 && data.user) {
console.warn("User already exists:", data.message)
return data.user.id
} else {
throw new Error(`Failed to create user: ${data.message || response.statusText}`)
}
}

const userDto = await response.json()
return userDto.id

} catch (error) {
console.error(error)
return null
}
}

async getAccessToken(
code: string,
Expand All @@ -23,14 +59,23 @@ export class RestSourceClient {
client_secret: this.CLIENT_SECRET,
})

const response = await fetch(`${this.AUTH_BASE_URL}/token`, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: bodyParams,
})
try {
const response = await fetch(`${this.AUTH_BASE_URL}/token`, {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: bodyParams,
})

if (!response.ok) {
throw new Error(`Failed to retrieve access token: ${response.statusText}`)
}

const data = await response.json()
return data.access_token || null
const data = await response.json()
return data.access_token || null
} catch (error) {
console.error(error)
return null
}
}

async getAccessTokenFromRedirect(): Promise<string | null> {
Expand Down Expand Up @@ -60,32 +105,44 @@ export class RestSourceClient {
window.location.href = authUrl
}

// Make a POST request to the registration endpoint to retrieve the authorization link
async getRestSourceAuthLink(accessToken: string): Promise<string | null> {
const response = await fetch(this.REGISTRATION_ENDPOINT, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({
userId: "4",
persistent: true,
}),
})
async getRestSourceAuthLink(accessToken: string, project: any): Promise<string | null> {
try {
const userId = await this.getRestSourceUser(accessToken, project)
if (!userId) {
throw new Error("Failed to retrieve or create user")
}

const response = await fetch(this.REGISTRATION_ENDPOINT, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${accessToken}`,
},
body: JSON.stringify({
userId,
persistent: false,
}),
})

const data = await response.json()
if (!data.token || !data.secret) {
console.error("Failed to retrieve auth link")
if (!response.ok) {
throw new Error(`Failed to retrieve registration token: ${response.statusText}`)
}

const data = await response.json()
if (!data.token || !data.secret) {
throw new Error("Failed to retrieve auth link")
}

return `${this.FRONTEND_ENDPOINT}/users:auth?token=${data.token}&secret=${data.secret}`

} catch (error) {
console.error(error)
return null
}

return `${this.FRONTEND_ENDPOINT}/users:auth?token=${data.token}&secret=${data.secret}`
}

// Redirect user to the authorization link for the rest source
async redirectToRestSourceAuthLink(accessToken: string): Promise<void> {
const url = await this.getRestSourceAuthLink(accessToken)
async redirectToRestSourceAuthLink(accessToken: string, project: any): Promise<void> {
const url = await this.getRestSourceAuthLink(accessToken, project)
if (url) {
console.log("Redirecting to: ", url)
window.location.href = url
Expand Down

0 comments on commit b4d2ef2

Please sign in to comment.