|
|
@@ -12,7 +12,7 @@ import type { Scope } from '~/interfaces/scope';
|
|
|
import loggerFactory from '~/utils/logger';
|
|
|
|
|
|
import { getOrCreateModel } from '../util/mongoose-utils';
|
|
|
-import { extractScopes } from '../util/scope-utils';
|
|
|
+import { extractAllScope, extractScopes } from '../util/scope-utils';
|
|
|
|
|
|
const logger = loggerFactory('growi:models:access-token');
|
|
|
|
|
|
@@ -22,7 +22,7 @@ type GenerateTokenResult = {
|
|
|
token: string,
|
|
|
_id: Types.ObjectId,
|
|
|
expiredAt: Date,
|
|
|
- scope?: Scope[],
|
|
|
+ scopes?: Scope[],
|
|
|
description?: string,
|
|
|
}
|
|
|
|
|
|
@@ -30,7 +30,7 @@ export type IAccessToken = {
|
|
|
user: Ref<IUserHasId>,
|
|
|
tokenHash: string,
|
|
|
expiredAt: Date,
|
|
|
- scope?: Scope[],
|
|
|
+ scopes?: Scope[],
|
|
|
description?: string,
|
|
|
}
|
|
|
|
|
|
@@ -39,7 +39,7 @@ export interface IAccessTokenDocument extends IAccessToken, Document {
|
|
|
}
|
|
|
|
|
|
export interface IAccessTokenModel extends Model<IAccessTokenDocument> {
|
|
|
- generateToken: (userId: Types.ObjectId | string, expiredAt: Date, scope?: Scope[], description?: string,) => Promise<GenerateTokenResult>
|
|
|
+ generateToken: (userId: Types.ObjectId | string, expiredAt: Date, scopes?: Scope[], description?: string,) => Promise<GenerateTokenResult>
|
|
|
deleteToken: (token: string) => Promise<void>
|
|
|
deleteTokenById: (tokenId: Types.ObjectId | string) => Promise<void>
|
|
|
deleteAllTokensByUserId: (userId: Types.ObjectId | string) => Promise<void>
|
|
|
@@ -55,27 +55,27 @@ const accessTokenSchema = new Schema<IAccessTokenDocument, IAccessTokenModel>({
|
|
|
},
|
|
|
tokenHash: { type: String, required: true, unique: true },
|
|
|
expiredAt: { type: Date, required: true, index: true },
|
|
|
- scope: [{ type: String, default: '' }],
|
|
|
+ scopes: [{ type: String, default: '' }],
|
|
|
description: { type: String, default: '' },
|
|
|
});
|
|
|
|
|
|
accessTokenSchema.plugin(mongoosePaginate);
|
|
|
accessTokenSchema.plugin(uniqueValidator);
|
|
|
|
|
|
-accessTokenSchema.statics.generateToken = async function(userId: Types.ObjectId | string, expiredAt: Date, scope?: Scope[], description?: string) {
|
|
|
+accessTokenSchema.statics.generateToken = async function(userId: Types.ObjectId | string, expiredAt: Date, scopes?: Scope[], description?: string) {
|
|
|
|
|
|
- const extractedScopes = extractScopes(scope ?? []);
|
|
|
+ const extractedScopes = extractScopes(scopes ?? []);
|
|
|
const token = crypto.randomBytes(32).toString('hex');
|
|
|
const tokenHash = generateTokenHash(token);
|
|
|
|
|
|
try {
|
|
|
const { _id } = await this.create({
|
|
|
- user: userId, tokenHash, expiredAt, scope: extractedScopes, description,
|
|
|
+ user: userId, tokenHash, expiredAt, scopes: extractedScopes, description,
|
|
|
});
|
|
|
|
|
|
logger.debug('Token generated');
|
|
|
return {
|
|
|
- token, _id, expiredAt, scope: extractedScopes, description,
|
|
|
+ token, _id, expiredAt, scopes: extractedScopes, description,
|
|
|
};
|
|
|
}
|
|
|
catch (err) {
|
|
|
@@ -106,20 +106,21 @@ accessTokenSchema.statics.findUserIdByToken = async function(token: string, requ
|
|
|
const tokenHash = generateTokenHash(token);
|
|
|
const now = new Date();
|
|
|
if (requiredScopes != null && requiredScopes.length > 0) {
|
|
|
- return this.findOne({ tokenHash, expiredAt: { $gt: now }, scope: { $all: requiredScopes } }).select('user');
|
|
|
+ const extractedScopes = requiredScopes.map(scope => extractAllScope(scope)).flat();
|
|
|
+ return this.findOne({ tokenHash, expiredAt: { $gt: now }, scopes: { $all: extractedScopes } }).select('user');
|
|
|
}
|
|
|
return this.findOne({ tokenHash, expiredAt: { $gt: now } }).select('user');
|
|
|
};
|
|
|
|
|
|
accessTokenSchema.statics.findTokenByUserId = async function(userId: Types.ObjectId | string) {
|
|
|
const now = new Date();
|
|
|
- return this.find({ user: userId, expiredAt: { $gt: now } }).select('_id expiredAt scope description');
|
|
|
+ return this.find({ user: userId, expiredAt: { $gt: now } }).select('_id expiredAt scopes description');
|
|
|
};
|
|
|
|
|
|
accessTokenSchema.statics.validateTokenScopes = async function(token: string, requiredScopes: Scope[]) {
|
|
|
const tokenHash = generateTokenHash(token);
|
|
|
const now = new Date();
|
|
|
- const tokenData = await this.findOne({ tokenHash, expiredAt: { $gt: now }, scope: { $all: requiredScopes } });
|
|
|
+ const tokenData = await this.findOne({ tokenHash, expiredAt: { $gt: now }, scopes: { $all: requiredScopes } });
|
|
|
return tokenData != null;
|
|
|
};
|
|
|
|