Files
homarr/apps/workshop/tests/workshop-oauth-hook.mjs
T

112 lines
3.3 KiB
JavaScript

import { createRequire } from "node:module";
import { readFile } from "node:fs/promises";
import vm from "node:vm";
const nodeRequire = createRequire(import.meta.url);
const workshopUtils = nodeRequire("../pb_hooks/workshop-utils.js");
const hookSource = await readFile("apps/workshop/pb_hooks/workshop.pb.js", "utf8");
let oauthHook;
const ignoreHook = () => {};
vm.runInNewContext(hookSource, {
__hooks: "/pb_hooks",
console: { log: () => {} },
onBootstrap: ignoreHook,
onRecordAfterCreateSuccess: ignoreHook,
onRecordCreateRequest: ignoreHook,
onRecordDeleteRequest: ignoreHook,
onRecordUpdateRequest: ignoreHook,
onRecordAuthWithOAuth2Request: (handler, collection) => {
if (collection !== "users") throw new Error(`OAuth hook targets unexpected collection: ${collection}`);
oauthHook = handler;
},
require: (specifier) => {
if (specifier !== "/pb_hooks/workshop-utils.js") {
throw new Error(`OAuth hook loaded unexpected dependency: ${specifier}`);
}
return workshopUtils;
},
});
if (typeof oauthHook !== "function") throw new Error("Workshop OAuth request hook was not registered");
const oauth2User = {
id: "provider-user-123",
name: "Octo Cat",
username: "octocat",
avatarURL: "https://avatars.githubusercontent.com/u/1?v=4",
rawUser: {},
};
const createData = {};
let createNextCalls = 0;
oauthHook({
app: { save: () => Promise.reject(new Error("New OAuth users must not be saved before PocketBase creates them")) },
createData,
next: () => {
createNextCalls += 1;
},
oauth2User,
providerName: "github",
record: null,
});
if (
createNextCalls !== 1 ||
createData.displayName !== "Octo Cat" ||
createData.avatarUrl !== "https://avatars.githubusercontent.com/u/1?v=4" ||
createData.githubUsername !== "octocat" ||
createData.githubProfileUrl !== "https://github.com/octocat"
) {
throw new Error(`First GitHub OAuth login did not synchronize trusted identity: ${JSON.stringify(createData)}`);
}
const returningValues = new Map();
const returningRecord = {
id: "returning-user-123",
set: (name, value) => returningValues.set(name, value),
};
let savedRecord;
let returningNextCalls = 0;
oauthHook({
app: {
save: (record) => {
savedRecord = record;
},
},
createData: {},
next: () => {
returningNextCalls += 1;
},
oauth2User,
providerName: "github",
record: returningRecord,
});
if (
savedRecord !== returningRecord ||
returningNextCalls !== 1 ||
returningValues.get("displayName") !== "Octo Cat" ||
returningValues.get("avatar") !== "" ||
returningValues.get("avatarUrl") !== "https://avatars.githubusercontent.com/u/1?v=4" ||
returningValues.get("githubUsername") !== "octocat" ||
returningValues.get("githubProfileUrl") !== "https://github.com/octocat"
) {
throw new Error("Returning GitHub OAuth login did not refresh trusted identity");
}
const ignoredCreateData = {};
let ignoredNextCalls = 0;
oauthHook({
app: {},
createData: ignoredCreateData,
next: () => {
ignoredNextCalls += 1;
},
oauth2User,
providerName: "oidc",
record: null,
});
if (ignoredNextCalls !== 1 || Object.keys(ignoredCreateData).length !== 0) {
throw new Error("Non-GitHub OAuth providers must pass through without GitHub identity synchronization");
}
console.log("Workshop OAuth hook contract passed");