mirror of
https://github.com/Unleash/unleash.git
synced 2024-10-18 20:09:08 +02:00
121 lines
3.2 KiB
TypeScript
121 lines
3.2 KiB
TypeScript
|
import { EventEmitter } from 'events';
|
||
|
import { Knex } from 'knex';
|
||
|
import metricsHelper from '../metrics-helper';
|
||
|
import { DB_TIME } from '../events';
|
||
|
import { Logger, LogProvider } from '../logger';
|
||
|
import NotFoundError from '../error/notfound-error';
|
||
|
|
||
|
const TABLE = 'api_tokens';
|
||
|
|
||
|
interface ITokenTable {
|
||
|
id: number;
|
||
|
secret: string;
|
||
|
username: string;
|
||
|
type: ApiTokenType;
|
||
|
expires_at?: Date;
|
||
|
created_at: Date;
|
||
|
seen_at?: Date;
|
||
|
}
|
||
|
|
||
|
export enum ApiTokenType {
|
||
|
CLIENT = 'client',
|
||
|
ADMIN = 'admin',
|
||
|
}
|
||
|
|
||
|
export interface IApiTokenCreate {
|
||
|
secret: string;
|
||
|
username: string;
|
||
|
type: ApiTokenType;
|
||
|
expiresAt?: Date;
|
||
|
}
|
||
|
|
||
|
export interface IApiToken extends IApiTokenCreate {
|
||
|
createdAt: Date;
|
||
|
seenAt?: 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 {
|
||
|
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', '>', new Date())
|
||
|
.orWhere('expires_at', 'IS', null);
|
||
|
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 };
|
||
|
}
|
||
|
|
||
|
async delete(secret: string): Promise<void> {
|
||
|
return this.db<ITokenTable>(TABLE)
|
||
|
.where({ secret })
|
||
|
.del();
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
}
|