112 lines
3.3 KiB
JavaScript
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");
|