1
0
mirror of https://github.com/Unleash/unleash.git synced 2024-10-18 20:09:08 +02:00
unleash.unleash/src/lib/db/api-token-store.ts

128 lines
3.5 KiB
TypeScript
Raw Normal View History

2021-03-29 19:58:11 +02:00
import { EventEmitter } from 'events';
import { Knex } from 'knex';
2021-05-02 21:11:17 +02:00
import metricsHelper from '../util/metrics-helper';
2021-04-29 10:21:29 +02:00
import { DB_TIME } from '../metric-events';
2021-03-29 19:58:11 +02:00
import { Logger, LogProvider } from '../logger';
import NotFoundError from '../error/notfound-error';
import {
ApiTokenType,
IApiToken,
IApiTokenCreate,
IApiTokenStore,
} from '../types/stores/api-token-store';
2021-03-29 19:58:11 +02:00
const TABLE = 'api_tokens';
interface ITokenTable {
id: number;
secret: string;
username: string;
type: ApiTokenType;
expires_at?: Date;
created_at: Date;
seen_at?: Date;
}
const toRow = (newToken: IApiTokenCreate) => ({
username: newToken.username,
secret: newToken.secret,
type: newToken.type,
expires_at: newToken.expiresAt,
});
const toToken = (row: ITokenTable): IApiToken => ({
secret: row.secret,
username: row.username,
type: row.type,
expiresAt: row.expires_at,
createdAt: row.created_at,
});
export class ApiTokenStore implements IApiTokenStore {
2021-03-29 19:58:11 +02:00
private logger: Logger;
private timer: Function;
private db: Knex;
constructor(db: Knex, eventBus: EventEmitter, getLogger: LogProvider) {
this.db = db;
this.logger = getLogger('api-tokens.js');
this.timer = (action: string) =>
metricsHelper.wrapTimer(eventBus, DB_TIME, {
store: 'api-tokens',
action,
});
}
async getAll(): Promise<IApiToken[]> {
const stopTimer = this.timer('getAll');
const rows = await this.db<ITokenTable>(TABLE);
stopTimer();
return rows.map(toToken);
}
async getAllActive(): Promise<IApiToken[]> {
const stopTimer = this.timer('getAllActive');
const rows = await this.db<ITokenTable>(TABLE)
.where('expires_at', 'IS', null)
.orWhere('expires_at', '>', 'now()');
2021-03-29 19:58:11 +02:00
stopTimer();
return rows.map(toToken);
}
async insert(newToken: IApiTokenCreate): Promise<IApiToken> {
const [row] = await this.db<ITokenTable>(TABLE).insert(
toRow(newToken),
['created_at'],
);
return { ...newToken, createdAt: row.created_at };
}
destroy(): void {}
async exists(secret: string): Promise<boolean> {
const result = await this.db.raw(
`SELECT EXISTS (SELECT 1 FROM ${TABLE} WHERE secret = ?) AS present`,
[secret],
);
const { present } = result.rows[0];
return present;
}
async get(key: string): Promise<IApiToken> {
const row = await this.db(TABLE).where('secret', key).first();
return toToken(row);
}
2021-03-29 19:58:11 +02:00
async delete(secret: string): Promise<void> {
return this.db<ITokenTable>(TABLE).where({ secret }).del();
2021-03-29 19:58:11 +02:00
}
async deleteAll(): Promise<void> {
return this.db<ITokenTable>(TABLE).del();
}
2021-03-29 19:58:11 +02:00
async setExpiry(secret: string, expiresAt: Date): Promise<IApiToken> {
const rows = await this.db<ITokenTable>(TABLE)
.update({ expires_at: expiresAt })
.where({ secret })
.returning('*');
if (rows.length > 0) {
return toToken(rows[0]);
}
throw new NotFoundError('Could not find api-token.');
}
async markSeenAt(secrets: string[]): Promise<void> {
const now = new Date();
try {
await this.db(TABLE)
.whereIn('secrets', secrets)
.update({ seen_at: now });
} catch (err) {
this.logger.error('Could not update lastSeen, error: ', err);
}
}
}