88 lines
2.7 KiB
JavaScript
88 lines
2.7 KiB
JavaScript
// Single-table storage adapter for oidc-provider, backed by _idp_oidc_store.
|
|
// oidc-provider instantiates one adapter per model (`new SaltcornAdapter(name)`).
|
|
// Rows are tenant-scoped because db.* runs in the request's tenant context.
|
|
// oidc-provider validates expiry/consumed itself from the payload, so find()
|
|
// returns the stored payload as-is; consume() records `consumed` inside it.
|
|
|
|
const db = require("@saltcorn/data/db");
|
|
|
|
const clients = require("../clients");
|
|
|
|
const { TABLE_OIDC_STORE } = require("../constants");
|
|
|
|
|
|
const epoch = () => {
|
|
return Math.floor(Date.now() / 1000);
|
|
};
|
|
|
|
|
|
class SaltcornAdapter {
|
|
constructor(name) {
|
|
this.name = name;
|
|
}
|
|
|
|
|
|
async upsert(id, payload, expiresIn) {
|
|
const row = {
|
|
model: this.name,
|
|
id: id,
|
|
payload: JSON.stringify(payload),
|
|
uid: payload.uid || null,
|
|
grant_id: payload.grantId || null,
|
|
user_code: payload.userCode || null,
|
|
expires_at: expiresIn ? epoch() + expiresIn : null
|
|
};
|
|
const existing = await db.selectMaybeOne(TABLE_OIDC_STORE, { model: this.name, id: id });
|
|
if (existing) {
|
|
await db.updateWhere(TABLE_OIDC_STORE, row, { model: this.name, id: id });
|
|
} else {
|
|
await db.insert(TABLE_OIDC_STORE, row, { noid: true });
|
|
}
|
|
}
|
|
|
|
|
|
async find(id) {
|
|
if (this.name === "Client") {
|
|
const row = await clients.getClient(id);
|
|
return row ? clients.toOidcMetadata(row) : undefined;
|
|
}
|
|
const row = await db.selectMaybeOne(TABLE_OIDC_STORE, { model: this.name, id: id });
|
|
return row ? JSON.parse(row.payload) : undefined;
|
|
}
|
|
|
|
|
|
async findByUid(uid) {
|
|
const row = await db.selectMaybeOne(TABLE_OIDC_STORE, { model: this.name, uid: uid });
|
|
return row ? JSON.parse(row.payload) : undefined;
|
|
}
|
|
|
|
|
|
async findByUserCode(userCode) {
|
|
const row = await db.selectMaybeOne(TABLE_OIDC_STORE, { model: this.name, user_code: userCode });
|
|
return row ? JSON.parse(row.payload) : undefined;
|
|
}
|
|
|
|
|
|
async consume(id) {
|
|
const row = await db.selectMaybeOne(TABLE_OIDC_STORE, { model: this.name, id: id });
|
|
if (!row) {
|
|
return;
|
|
}
|
|
const payload = JSON.parse(row.payload);
|
|
payload.consumed = epoch();
|
|
await db.updateWhere(TABLE_OIDC_STORE, { payload: JSON.stringify(payload) }, { model: this.name, id: id });
|
|
}
|
|
|
|
|
|
async destroy(id) {
|
|
await db.deleteWhere(TABLE_OIDC_STORE, { model: this.name, id: id });
|
|
}
|
|
|
|
|
|
async revokeByGrantId(grantId) {
|
|
await db.deleteWhere(TABLE_OIDC_STORE, { grant_id: grantId });
|
|
}
|
|
}
|
|
|
|
|
|
module.exports = SaltcornAdapter;
|