-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Setup AsyncLocalStoreage
context for Express.User throughout the callstack
#2199
Changes from all commits
5e069db
ab0a604
872891b
cf780b1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,13 @@ | ||
import { CoreDomainClient } from "@opensystemslab/planx-core"; | ||
import { userContext } from "../modules/auth/middleware"; | ||
import { ServerError } from "../errors"; | ||
|
||
/** | ||
* core doesn't expose a graphql interface like the graphql/hasura clients do | ||
* instead, they encapsulates query and business logic to only expose declarative interfaces | ||
* @deprecated This client's permissions set are higher than required. | ||
* Should only be used by trusted service-to-service calls (e.g Hasura -> API). | ||
* Calls made by users should be directed through $public or the role-scoped getClient(). | ||
* | ||
* Consider removing this and replacing with an "api" role using "backend-only" operations in Hasura | ||
*/ | ||
export const $admin = new CoreDomainClient({ | ||
auth: { adminSecret: process.env.HASURA_GRAPHQL_ADMIN_SECRET! }, | ||
|
@@ -11,3 +17,26 @@ export const $admin = new CoreDomainClient({ | |
export const $public = new CoreDomainClient({ | ||
targetURL: process.env.HASURA_GRAPHQL_URL!, | ||
}); | ||
|
||
/** | ||
* Get a planx-core client with permissions scoped to the current user. | ||
* This client instance ensures that all operations are restricted | ||
* to the permissions of the user who initiated the request. | ||
*/ | ||
export const getClient = () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not thrilled on the naming here - feels a little generic and meaningless. Something like No strong opinions here on naming, but if we move to a future where the API only calls a |
||
const store = userContext.getStore(); | ||
if (!store) | ||
throw new ServerError({ | ||
status: 500, | ||
message: "Missing user context", | ||
}); | ||
|
||
const client = new CoreDomainClient({ | ||
targetURL: process.env.HASURA_GRAPHQL_URL!, | ||
auth: { | ||
jwt: store.user.jwt, | ||
}, | ||
}); | ||
|
||
return client; | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { RequestHandler } from "express"; | ||
import { getClient } from "../../client"; | ||
import { userContext } from "../auth/middleware"; | ||
import { ServerError } from "../../errors"; | ||
|
||
export const getLoggedInUserDetails: RequestHandler = async ( | ||
_req, | ||
res, | ||
next, | ||
) => { | ||
try { | ||
const $client = getClient(); | ||
|
||
const email = userContext.getStore()?.user.email; | ||
if (!email) | ||
throw new ServerError({ | ||
message: "User email missing from request", | ||
status: 400, | ||
}); | ||
|
||
const user = await $client.user.getByEmail(email); | ||
if (!user) | ||
throw new ServerError({ | ||
message: `Unable to locate user with email ${email}`, | ||
status: 400, | ||
}); | ||
|
||
res.json(user); | ||
} catch (error) { | ||
next(error); | ||
} | ||
}; | ||
|
||
export const healthCheck: RequestHandler = (_req, res) => | ||
res.json({ hello: "world" }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
➕