unleash-server
Version:
Unleash is an enterprise ready feature flag service. It provides different strategies for handling feature flags.
121 lines • 4.07 kB
JavaScript
import metricsHelper from '../../util/metrics-helper.js';
import { DB_TIME } from '../../metric-events.js';
import { ApiTokenType, } from '../../types/index.js';
import { scopeHash } from './edge-tokens.js';
import { ulid } from 'ulidx';
const T = {
apiTokens: 'api_tokens',
edgeApiTokens: 'edge_api_tokens',
edgeHmacClients: 'edge_hmac_clients',
edgeHmacNonces: 'edge_hmac_nonces',
};
export class EdgeTokenStore {
constructor(db, eventBus, { getLogger }) {
this.db = db;
this.timer = (action) => metricsHelper.wrapTimer(eventBus, DB_TIME, {
store: 'edge-store',
action,
});
}
async registerNonce(clientId, nonce, expiresAt) {
const stop = this.timer('check_nonce');
await this.db(T.edgeHmacNonces).insert({
client_id: clientId,
nonce,
expires_at: expiresAt,
});
stop();
}
async saveToken(clientId, apiToken) {
const stop = this.timer('save_token');
const hash = scopeHash(apiToken.environment, apiToken.projects);
await this.db(T.edgeApiTokens).insert({
id: ulid(),
client_id: clientId,
environment: apiToken.environment,
projects: JSON.stringify(apiToken.projects),
scope_hash: hash,
token_value: apiToken.secret,
});
stop();
}
async getToken(clientId, environment, projects) {
const stop = this.timer('get_token');
const hash = scopeHash(environment, projects);
const tokens = await this.db(T.edgeApiTokens)
.where('client_id', clientId)
.andWhere('scope_hash', hash)
.leftJoin(T.apiTokens, 'token_value', `${T.apiTokens}.secret`)
.select([
`${T.edgeApiTokens}.environment`,
`${T.edgeApiTokens}.projects`,
`${T.edgeApiTokens}.token_value`,
`${T.edgeApiTokens}.created_at`,
`${T.apiTokens}.token_name`,
]);
stop();
if (tokens && tokens.length > 0) {
const token = tokens[0];
return {
createdAt: token.created_at,
projects: token.projects,
project: '',
environment: token.environment,
secret: token.token_value,
type: ApiTokenType.BACKEND,
tokenName: token.token_name,
};
}
return undefined;
}
async loadClient(clientId) {
const stop = this.timer('load_client');
const client = await this.db(T.edgeHmacClients)
.where({ id: clientId })
.select('id', 'secret_enc');
stop();
if (client && client.length > 0) {
return client[0];
}
return undefined;
}
async saveClient(clientId, secretEnc) {
const stop = this.timer('save_client');
await this.db(T.edgeHmacClients)
.insert({
id: clientId,
secret_enc: secretEnc,
})
.onConflict(['id'])
.merge({ secret_enc: secretEnc, created_at: new Date() });
stop();
}
async cleanExpiredNonces() {
const stop = this.timer('clean_expired_nonces');
await this.db(T.edgeHmacNonces)
.where('expires_at', '<', new Date())
.delete();
stop();
}
async delete(tokenValue) {
const stop = this.timer('delete_token');
await this.db(T.edgeApiTokens)
.where('token_value', tokenValue)
.delete();
stop();
}
async deleteAll() {
const stop = this.timer('delete_all_tokens');
await this.db.raw(`
WITH deleted_edge AS (
DELETE FROM ${T.edgeApiTokens}
RETURNING token_value)
DELETE
FROM ${T.apiTokens} t
USING deleted_edge d
WHERE t.secret = d.token_value
`);
stop();
}
}
//# sourceMappingURL=edge-token-store.js.map