This commit is contained in:
Tutur33
2023-11-24 22:35:41 +01:00
parent 3c0b507a93
commit 7644b2a0f7
45165 changed files with 4803356 additions and 3 deletions
@@ -0,0 +1,43 @@
import { DatabaseContract, QueryClientContract } from '@ioc:Adonis/Lucid/Database';
import { TokenProviderContract, ProviderTokenContract, DatabaseTokenProviderConfig } from '@ioc:Adonis/Addons/Auth';
import { ProviderToken } from '../../Tokens/ProviderToken';
/**
* Database backend tokens provider
*/
export declare class TokenDatabaseProvider implements TokenProviderContract {
private config;
private db;
constructor(config: DatabaseTokenProviderConfig, db: DatabaseContract);
/**
* Custom connection or query client
*/
private connection?;
/**
* Returns the query client for database queries
*/
private getQueryClient;
/**
* The foreign key column
*/
private foreignKey;
/**
* Returns the builder query for a given token + type
*/
private getLookupQuery;
/**
* Define custom connection
*/
setConnection(connection: string | QueryClientContract): this;
/**
* Reads the token using the lookup token id
*/
read(tokenId: string, tokenHash: string, tokenType: string): Promise<ProviderTokenContract | null>;
/**
* Saves the token and returns the persisted token lookup id.
*/
write(token: ProviderToken): Promise<string>;
/**
* Removes a given token
*/
destroy(tokenId: string, tokenType: string): Promise<void>;
}
+126
View File
@@ -0,0 +1,126 @@
"use strict";
/*
* @adonisjs/auth
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.TokenDatabaseProvider = void 0;
const luxon_1 = require("luxon");
const helpers_1 = require("@poppinss/utils/build/helpers");
const ProviderToken_1 = require("../../Tokens/ProviderToken");
/**
* Database backend tokens provider
*/
class TokenDatabaseProvider {
constructor(config, db) {
this.config = config;
this.db = db;
/**
* The foreign key column
*/
this.foreignKey = this.config.foreignKey || 'user_id';
}
/**
* Returns the query client for database queries
*/
getQueryClient() {
if (!this.connection) {
return this.db.connection(this.config.connection);
}
return typeof this.connection === 'string'
? this.db.connection(this.connection)
: this.connection;
}
/**
* Returns the builder query for a given token + type
*/
getLookupQuery(tokenId, tokenType) {
return this.getQueryClient()
.from(this.config.table)
.where('id', tokenId)
.where('type', tokenType);
}
/**
* Define custom connection
*/
setConnection(connection) {
this.connection = connection;
return this;
}
/**
* Reads the token using the lookup token id
*/
async read(tokenId, tokenHash, tokenType) {
const client = this.getQueryClient();
/**
* Find token using id
*/
const tokenRow = await this.getLookupQuery(tokenId, tokenType).first();
if (!tokenRow || !tokenRow.token) {
return null;
}
/**
* Ensure hash of the user provided value is same as the one inside
* the database
*/
if (!(0, helpers_1.safeEqual)(tokenRow.token, tokenHash)) {
return null;
}
const { name, [this.foreignKey]: userId, token: value, expires_at: expiresAt, type, ...meta } = tokenRow;
let normalizedExpiryDate;
/**
* Parse dialect date to an instance of Luxon
*/
if (expiresAt instanceof Date) {
normalizedExpiryDate = luxon_1.DateTime.fromJSDate(expiresAt);
}
else if (expiresAt && typeof expiresAt === 'string') {
normalizedExpiryDate = luxon_1.DateTime.fromFormat(expiresAt, client.dialect.dateTimeFormat);
}
else if (expiresAt && typeof expiresAt === 'number') {
normalizedExpiryDate = luxon_1.DateTime.fromMillis(expiresAt);
}
/**
* Ensure token isn't expired
*/
if (normalizedExpiryDate &&
normalizedExpiryDate.diff(luxon_1.DateTime.local(), 'milliseconds').milliseconds <= 0) {
return null;
}
const token = new ProviderToken_1.ProviderToken(name, value, userId, type);
token.expiresAt = expiresAt;
token.meta = meta;
return token;
}
/**
* Saves the token and returns the persisted token lookup id.
*/
async write(token) {
const client = this.getQueryClient();
/**
* Payload to save to the database
*/
const payload = {
[this.foreignKey]: token.userId,
name: token.name,
token: token.tokenHash,
type: token.type,
expires_at: token.expiresAt ? token.expiresAt.toFormat(client.dialect.dateTimeFormat) : null,
created_at: luxon_1.DateTime.local().toFormat(client.dialect.dateTimeFormat),
...token.meta,
};
const [row] = await client.table(this.config.table).insert(payload).returning('id');
return String(typeof row === 'number' ? row : row.id);
}
/**
* Removes a given token
*/
async destroy(tokenId, tokenType) {
await this.getLookupQuery(tokenId, tokenType).delete();
}
}
exports.TokenDatabaseProvider = TokenDatabaseProvider;
+44
View File
@@ -0,0 +1,44 @@
import { RedisManagerContract, RedisConnectionContract, RedisClusterConnectionContract } from '@ioc:Adonis/Addons/Redis';
import { TokenProviderContract, ProviderTokenContract, RedisTokenProviderConfig } from '@ioc:Adonis/Addons/Auth';
import { ProviderToken } from '../../Tokens/ProviderToken';
/**
* Redis backed tokens provider.
*/
export declare class TokenRedisProvider implements TokenProviderContract {
private config;
private redis;
constructor(config: RedisTokenProviderConfig, redis: RedisManagerContract);
/**
* Custom connection or query client
*/
private connection?;
/**
* Returns the singleton instance of the redis connection
*/
private getRedisConnection;
/**
* The foreign key column
*/
private foreignKey;
/**
* Parse the stringified redis token value to an object
*/
private parseToken;
/**
* Define custom connection
*/
setConnection(connection: string | RedisConnectionContract | RedisClusterConnectionContract): this;
/**
* Reads the token using the lookup token id
*/
read(tokenId: string, tokenHash: string, tokenType: string): Promise<ProviderTokenContract | null>;
/**
* Saves the token and returns the persisted token lookup id, which
* is a cuid.
*/
write(token: ProviderToken): Promise<string>;
/**
* Removes a given token
*/
destroy(tokenId: string, tokenType: string): Promise<void>;
}
+129
View File
@@ -0,0 +1,129 @@
"use strict";
/*
* @adonisjs/auth
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.TokenRedisProvider = void 0;
const utils_1 = require("@poppinss/utils");
const helpers_1 = require("@poppinss/utils/build/helpers");
const ProviderToken_1 = require("../../Tokens/ProviderToken");
/**
* Redis backed tokens provider.
*/
class TokenRedisProvider {
constructor(config, redis) {
this.config = config;
this.redis = redis;
/**
* The foreign key column
*/
this.foreignKey = this.config.foreignKey || 'user_id';
}
/**
* Returns the singleton instance of the redis connection
*/
getRedisConnection() {
/**
* Use custom connection if defined
*/
if (this.connection) {
return typeof this.connection === 'string'
? this.redis.connection(this.connection)
: this.connection;
}
/**
* Config must have a connection defined
*/
if (!this.config.redisConnection) {
throw new utils_1.Exception('Missing "redisConnection" property for auth redis provider inside "config/auth" file', 500, 'E_INVALID_AUTH_REDIS_CONFIG');
}
return this.redis.connection(this.config.redisConnection);
}
/**
* Parse the stringified redis token value to an object
*/
parseToken(token) {
if (!token) {
return null;
}
try {
const tokenRow = JSON.parse(token);
if (!tokenRow.token || !tokenRow.name || !tokenRow[this.foreignKey]) {
return null;
}
return tokenRow;
}
catch {
return null;
}
}
/**
* Define custom connection
*/
setConnection(connection) {
this.connection = connection;
return this;
}
/**
* Reads the token using the lookup token id
*/
async read(tokenId, tokenHash, tokenType) {
/**
* Find token using id
*/
const tokenRow = this.parseToken(await this.getRedisConnection().get(`${tokenType}:${tokenId}`));
if (!tokenRow) {
return null;
}
/**
* Ensure hash of the user provided value is same as the one inside
* the database
*/
if (!(0, helpers_1.safeEqual)(tokenRow.token, tokenHash)) {
return null;
}
const { name, [this.foreignKey]: userId, token: value, ...meta } = tokenRow;
const token = new ProviderToken_1.ProviderToken(name, value, userId, tokenType);
token.meta = meta;
return token;
}
/**
* Saves the token and returns the persisted token lookup id, which
* is a cuid.
*/
async write(token) {
/**
* Payload to save to the database
*/
const payload = {
[this.foreignKey]: token.userId,
name: token.name,
token: token.tokenHash,
...token.meta,
};
const ttl = token.expiresAt ? Math.ceil(token.expiresAt.diffNow('seconds').seconds) : 0;
const tokenId = (0, helpers_1.cuid)();
if (token.expiresAt && ttl <= 0) {
throw new utils_1.Exception('The expiry date/time should be in the future', 500, 'E_INVALID_TOKEN_EXPIRY');
}
if (token.expiresAt) {
await this.getRedisConnection().setex(`${token.type}:${tokenId}`, ttl, JSON.stringify(payload));
}
else {
await this.getRedisConnection().set(`${token.type}:${tokenId}`, JSON.stringify(payload));
}
return tokenId;
}
/**
* Removes a given token
*/
async destroy(tokenId, tokenType) {
await this.getRedisConnection().del(`${tokenType}:${tokenId}`);
}
}
exports.TokenRedisProvider = TokenRedisProvider;