05e00d2c5c
* chore(acc): put permission gql in correct place * feat(acc): swap to new rvt import * fix(acc): add oda secrets * feat(acc): auth cookies * feat(acc): introduce integrations as workspace setting * feat(acc): create sync item from models * fix(acc): bump * fix(acc): naming lost in merge * feat(acc): no acc tab - table under settings * chore(acc): new sync but will disapper * feat(acc): see statuses over model list * chore(acc): fix return type * chore(acc): type saga * chore(acc): status badge * chore(acc): refactor acc gql (#5556) * checkpoint * fix(acc): refactor gql items * feat(acc): double button * chore(acc): gqlgen * fix(acc): model ids are not project ids * chore(acc): bump function version * chore(acc): split up clients * feat(acc): more-optimised gql folder fetching schema * feat(acc): acc folder contents gql impl * feat(acc): apollo cache optimisations * chore(acc): gqlgen * fix(acc): return something for * fix(acc): handle null values correctly * chore(acc): specify prod functions --------- Co-authored-by: Chuck Driesler <chuck@speckle.systems>
116 lines
3.3 KiB
TypeScript
116 lines
3.3 KiB
TypeScript
/* eslint-disable camelcase */
|
|
|
|
import {
|
|
buildAuthorizeUrl,
|
|
exchangeCodeForTokens,
|
|
exchangeRefreshTokenForTokens,
|
|
generateCodeVerifier
|
|
} from '@/modules/acc/clients/autodesk/tokens'
|
|
import { sessionMiddlewareFactory } from '@/modules/auth/middleware'
|
|
import { corsMiddlewareFactory } from '@/modules/core/configs/cors'
|
|
import {
|
|
getAutodeskIntegrationClientId,
|
|
getAutodeskIntegrationClientSecret,
|
|
getServerOrigin
|
|
} from '@/modules/shared/helpers/envHelper'
|
|
import { logger } from '@/observability/logging'
|
|
import type { Express } from 'express'
|
|
|
|
export const setupAccOidcEndpoints = (app: Express) => {
|
|
const corsMiddleware = corsMiddlewareFactory()
|
|
const sessionMiddleware = sessionMiddlewareFactory()
|
|
|
|
app.post(
|
|
'/api/v1/acc/auth/login',
|
|
corsMiddleware,
|
|
sessionMiddleware,
|
|
async (req, res) => {
|
|
const { callbackEndpoint } = req.body
|
|
req.session.callbackEndpoint = callbackEndpoint
|
|
|
|
const { codeVerifier, codeChallenge } = generateCodeVerifier()
|
|
req.session.codeVerifier = codeVerifier
|
|
|
|
const redirectUri = `${getServerOrigin()}/api/v1/acc/auth/callback`
|
|
|
|
const authorizeUrl = buildAuthorizeUrl({
|
|
clientId: getAutodeskIntegrationClientId(),
|
|
redirectUri,
|
|
codeChallenge,
|
|
scopes: ['user-profile:read', 'data:read', 'viewables:read', 'openid']
|
|
})
|
|
|
|
return res.json({ authorizeUrl })
|
|
}
|
|
)
|
|
|
|
app.get(
|
|
'/api/v1/acc/auth/callback',
|
|
corsMiddleware,
|
|
sessionMiddleware,
|
|
async (req, res) => {
|
|
const { code } = req.query
|
|
const codeVerifier = req.session.codeVerifier
|
|
|
|
if (!code || !codeVerifier) {
|
|
return res.status(400).send({ error: 'Missing code or verifier' })
|
|
}
|
|
|
|
try {
|
|
const tokens = await exchangeCodeForTokens({
|
|
code: String(code),
|
|
codeVerifier,
|
|
clientId: getAutodeskIntegrationClientId(),
|
|
clientSecret: getAutodeskIntegrationClientSecret(),
|
|
redirectUri: `${getServerOrigin()}/api/v1/acc/auth/callback`
|
|
})
|
|
|
|
req.session.accTokens = tokens
|
|
|
|
logger.warn(req.session)
|
|
|
|
if (!req.session.callbackEndpoint) {
|
|
return res.status(500)
|
|
}
|
|
|
|
return res.redirect(req.session.callbackEndpoint)
|
|
} catch (error) {
|
|
console.error('Token exchange failed:', error)
|
|
return res.status(500).send({ error: 'Token exchange failed' })
|
|
}
|
|
}
|
|
)
|
|
|
|
app.get('/api/v1/acc/auth/status', corsMiddleware, sessionMiddleware, (req, res) => {
|
|
try {
|
|
if (!req.session.accTokens) {
|
|
return res.status(404).send({ error: 'No ACC tokens found' })
|
|
}
|
|
res.send(req.session.accTokens)
|
|
} finally {
|
|
req.session.accTokens = undefined // we wanna return it just once
|
|
}
|
|
})
|
|
|
|
app.post(
|
|
'/api/v1/acc/auth/refresh',
|
|
corsMiddleware,
|
|
sessionMiddleware,
|
|
async (req, res) => {
|
|
const { refresh_token } = req.body || {}
|
|
if (!refresh_token) {
|
|
return res.status(401).json({ error: 'No refresh token found' })
|
|
}
|
|
|
|
try {
|
|
const newTokens = await exchangeRefreshTokenForTokens({ refresh_token })
|
|
req.session.accTokens = newTokens
|
|
res.json(newTokens)
|
|
} catch (error) {
|
|
console.error('Error refreshing token:', error)
|
|
res.status(500).json({ error })
|
|
}
|
|
}
|
|
)
|
|
}
|