oidc: use better json based file store for objects
This commit is contained in:
114
src/oidc.js
114
src/oidc.js
@@ -3,6 +3,7 @@
|
||||
exports = module.exports = {
|
||||
start,
|
||||
stop,
|
||||
revokeByUserId,
|
||||
clients: {
|
||||
add: clientsAdd,
|
||||
get: clientsGet,
|
||||
@@ -97,6 +98,69 @@ async function clientsList() {
|
||||
return results;
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// Basic in-memory json file backed based data store
|
||||
// -----------------------------
|
||||
const DATA_STORE = {};
|
||||
|
||||
function load(modelName) {
|
||||
assert.strictEqual(typeof modelName, 'string');
|
||||
|
||||
if (DATA_STORE[modelName]) return;
|
||||
|
||||
const filePath = path.join(paths.OIDC_STORE_DIR, `${modelName}.json`);
|
||||
debug(`load: model ${modelName} based on ${filePath}.`);
|
||||
|
||||
let data = {};
|
||||
try {
|
||||
data = JSON.parse(fs.readFileSync(filePath), 'utf8');
|
||||
} catch (e) {
|
||||
debug(`load: failed to read ${filePath}, start with new one.`, e);
|
||||
}
|
||||
|
||||
DATA_STORE[modelName] = data;
|
||||
}
|
||||
|
||||
function save(modelName) {
|
||||
assert.strictEqual(typeof modelName, 'string');
|
||||
|
||||
if (!DATA_STORE[modelName]) return;
|
||||
|
||||
const filePath = path.join(paths.OIDC_STORE_DIR, `${modelName}.json`);
|
||||
debug(`save: model ${modelName} to ${filePath}.`);
|
||||
|
||||
try {
|
||||
fs.writeFileSync(filePath, JSON.stringify(DATA_STORE[modelName]), 'utf8');
|
||||
} catch (e) {
|
||||
debug(`revokeByUserId: failed to write ${filePath}`, e);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// Session, Grant and Token management
|
||||
// -----------------------------
|
||||
// This is based on the same storage as the below CloudronAdapter
|
||||
async function revokeByUserId(userId) {
|
||||
assert.strictEqual(typeof userId, 'string');
|
||||
|
||||
debug(`revokeByUserId: userId:${userId}`);
|
||||
|
||||
function revokeObjects(modelName) {
|
||||
load(modelName);
|
||||
|
||||
for (let id in DATA_STORE[modelName]) {
|
||||
if (DATA_STORE[modelName][id].payload?.accountId === userId) delete DATA_STORE[modelName][id];
|
||||
}
|
||||
|
||||
save(modelName);
|
||||
}
|
||||
|
||||
revokeObjects('Session');
|
||||
revokeObjects('Grant');
|
||||
revokeObjects('AuthorizationCode');
|
||||
revokeObjects('AccessToken');
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// Generic oidc node module data store model
|
||||
// -----------------------------
|
||||
@@ -115,22 +179,10 @@ class CloudronAdapter {
|
||||
constructor(name) {
|
||||
this.name = name;
|
||||
|
||||
if (this.name === 'Client') {
|
||||
this.store = null;
|
||||
this.fileStorePath = null;
|
||||
} else {
|
||||
this.fileStorePath = path.join(paths.OIDC_STORE_DIR, `${name}.json`);
|
||||
debug(`Creating storage adapter for ${name}`);
|
||||
|
||||
debug(`Creating storage adapter for ${name} backed by ${this.fileStorePath}`);
|
||||
|
||||
let data = {};
|
||||
try {
|
||||
data = JSON.parse(fs.readFileSync(this.fileStorePath), 'utf8');
|
||||
} catch (e) {
|
||||
debug(`filestore for adapter ${name} not found, start with new one`);
|
||||
}
|
||||
|
||||
this.store = data;
|
||||
if (this.name !== 'Client') {
|
||||
load(name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,8 +204,8 @@ class CloudronAdapter {
|
||||
if (this.name === 'Client') {
|
||||
console.log('WARNING!! this should not happen as it is stored in our db');
|
||||
} else {
|
||||
this.store[id] = { id, expiresIn, payload, consumed: false };
|
||||
if (this.fileStorePath) fs.writeFileSync(this.fileStorePath, JSON.stringify(this.store), 'utf8');
|
||||
DATA_STORE[this.name][id] = { id, expiresIn, payload, consumed: false };
|
||||
save(this.name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,11 +243,11 @@ class CloudronAdapter {
|
||||
|
||||
return tmp;
|
||||
} else {
|
||||
if (!this.store[id]) return null;
|
||||
if (!DATA_STORE[this.name][id]) return null;
|
||||
|
||||
debug(`[${this.name}] find id:${id}`, this.store[id]);
|
||||
debug(`[${this.name}] find id:${id}`, DATA_STORE[this.name][id]);
|
||||
|
||||
return this.store[id].payload;
|
||||
return DATA_STORE[this.name][id].payload;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,8 +282,8 @@ class CloudronAdapter {
|
||||
if (this.name === 'Client') {
|
||||
console.log('WARNING!! this should not happen as it is stored in our db');
|
||||
} else {
|
||||
for (let d in this.store) {
|
||||
if (this.store[d].payload.uid === uid) return this.store[d].payload;
|
||||
for (let d in DATA_STORE[this.name]) {
|
||||
if (DATA_STORE[this.name][d].payload.uid === uid) return DATA_STORE[this.name][d].payload;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -255,9 +307,8 @@ class CloudronAdapter {
|
||||
if (this.name === 'Client') {
|
||||
console.log('WARNING!! this should not happen as it is stored in our db');
|
||||
} else {
|
||||
if (this.store[id]) this.store[id].consumed = true;
|
||||
|
||||
if (this.fileStorePath) fs.writeFileSync(this.fileStorePath, JSON.stringify(this.store), 'utf8');
|
||||
if (DATA_STORE[this.name][id]) DATA_STORE[this.name][id].consumed = true;
|
||||
save(this.name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,9 +328,8 @@ class CloudronAdapter {
|
||||
if (this.name === 'Client') {
|
||||
console.log('WARNING!! this should not happen as it is stored in our db');
|
||||
} else {
|
||||
delete this.store[id];
|
||||
|
||||
if (this.fileStorePath) fs.writeFileSync(this.fileStorePath, JSON.stringify(this.store), 'utf8');
|
||||
delete DATA_STORE[this.name][id];
|
||||
save(this.name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -299,10 +349,10 @@ class CloudronAdapter {
|
||||
if (this.name === 'Client') {
|
||||
console.log('WARNING!! this should not happen as it is stored in our db');
|
||||
} else {
|
||||
for (let d in this.store) {
|
||||
if (this.store[d].grantId === grantId) {
|
||||
delete this.store[d];
|
||||
return;
|
||||
for (let d in DATA_STORE[this.name]) {
|
||||
if (DATA_STORE[this.name][d].grantId === grantId) {
|
||||
delete DATA_STORE[this.name][d];
|
||||
return save(this.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user