mirror of
https://github.com/tale/headplane.git
synced 2026-07-27 08:08:56 +00:00
41 lines
1.2 KiB
TypeScript
41 lines
1.2 KiB
TypeScript
import type { User } from "~/types/User";
|
|
|
|
/**
|
|
* Extracts the OIDC subject from a Headscale user's providerId.
|
|
* Headscale stores providerId as a URL where the last path segment
|
|
* is the subject (e.g. "https://idp.example.com/<uuid>"). This is
|
|
* the ONLY place this parsing should occur — all other code should
|
|
* use the stable headscale_user_id link on the Headplane user record.
|
|
*/
|
|
export function getOidcSubject(user: User): string | undefined {
|
|
if (user.provider !== "oidc" || !user.providerId) {
|
|
return;
|
|
}
|
|
|
|
const segment = user.providerId.split("/").pop();
|
|
return segment ? decodeURIComponent(segment) : segment;
|
|
}
|
|
|
|
/**
|
|
* Finds the Headscale user matching the given OIDC identity.
|
|
* Tries subject match first (providerId last segment), then falls
|
|
* back to email match. The fallback is needed because some IDPs
|
|
* issue different subjects per client application.
|
|
*/
|
|
export function findHeadscaleUserBySubject(
|
|
users: User[],
|
|
subject: string,
|
|
email?: string,
|
|
): User | undefined {
|
|
const bySubject = users.find((u) => getOidcSubject(u) === subject);
|
|
if (bySubject) {
|
|
return bySubject;
|
|
}
|
|
|
|
if (!email) {
|
|
return;
|
|
}
|
|
|
|
return users.find((u) => u.email === email);
|
|
}
|