|
|
@ -1,5 +1,8 @@ |
|
|
|
import { Inject, Injectable } from '@nestjs/common'; |
|
|
|
import { Inject, Injectable } from '@nestjs/common'; |
|
|
|
|
|
|
|
import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context-host'; |
|
|
|
import { AuthGuard } from '@nestjs/passport'; |
|
|
|
import { AuthGuard } from '@nestjs/passport'; |
|
|
|
|
|
|
|
import passport from 'passport'; |
|
|
|
|
|
|
|
import { lastValueFrom, Observable } from 'rxjs'; |
|
|
|
import { JwtStrategy } from '../../strategies/jwt.strategy'; |
|
|
|
import { JwtStrategy } from '../../strategies/jwt.strategy'; |
|
|
|
import type { ExecutionContext } from '@nestjs/common'; |
|
|
|
import type { ExecutionContext } from '@nestjs/common'; |
|
|
|
|
|
|
|
|
|
|
@ -12,25 +15,83 @@ export class GlobalGuard extends AuthGuard(['jwt']) { |
|
|
|
async canActivate(context: ExecutionContext) { |
|
|
|
async canActivate(context: ExecutionContext) { |
|
|
|
let result; |
|
|
|
let result; |
|
|
|
try { |
|
|
|
try { |
|
|
|
result = (await super.canActivate(context)) as boolean; |
|
|
|
result = await this.extractBoolVal(super.canActivate(context)); |
|
|
|
} catch (e) { |
|
|
|
} catch (e) { |
|
|
|
console.log(e); |
|
|
|
console.log(e); |
|
|
|
} |
|
|
|
} |
|
|
|
if (!result) { |
|
|
|
|
|
|
|
// If JWT authentication fails, use the fallback strategy to set a default user
|
|
|
|
|
|
|
|
const req = context.switchToHttp().getRequest(); |
|
|
|
const req = context.switchToHttp().getRequest(); |
|
|
|
const user = await this.fallbackAuthenticate(req); |
|
|
|
|
|
|
|
req.user = user; |
|
|
|
if (result && !req.headers['xc-shared-base-id']) { |
|
|
|
return true; |
|
|
|
if ( |
|
|
|
|
|
|
|
req.path.indexOf('/user/me') === -1 && |
|
|
|
|
|
|
|
req.header('xc-preview') && |
|
|
|
|
|
|
|
['owner', 'creator'].some((role) => req.user.roles?.[role]) |
|
|
|
|
|
|
|
) { |
|
|
|
|
|
|
|
return this.authenticate({ |
|
|
|
|
|
|
|
...req.user, |
|
|
|
|
|
|
|
isAuthorized: true, |
|
|
|
|
|
|
|
roles: req.header('xc-preview'), |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (req.headers['xc-token']) { |
|
|
|
|
|
|
|
let canActivate = false; |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
const guard = new (AuthGuard('authtoken'))(context); |
|
|
|
|
|
|
|
canActivate = await this.extractBoolVal(guard.canActivate(context)); |
|
|
|
|
|
|
|
} catch {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (canActivate) { |
|
|
|
|
|
|
|
return this.authenticate({ |
|
|
|
|
|
|
|
...req.user, |
|
|
|
|
|
|
|
isAuthorized: true, |
|
|
|
|
|
|
|
roles: req.user.roles === 'owner' ? 'owner,creator' : req.user.roles, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else if (req.headers['xc-shared-base-id']) { |
|
|
|
|
|
|
|
let canActivate = false; |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
const guard = new (AuthGuard('base-view'))(context); |
|
|
|
|
|
|
|
canActivate = await this.extractBoolVal(guard.canActivate(context)); |
|
|
|
|
|
|
|
} catch {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (canActivate) { |
|
|
|
|
|
|
|
return this.authenticate({ |
|
|
|
|
|
|
|
...req.user, |
|
|
|
|
|
|
|
isAuthorized: true, |
|
|
|
|
|
|
|
isPublicBase: true, |
|
|
|
|
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private async fallbackAuthenticate(req: any): Promise<any> { |
|
|
|
// If JWT authentication fails, use the fallback strategy to set a default user
|
|
|
|
return this.jwtStrategy.validate(req, { |
|
|
|
return await this.authenticate(req); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private async authenticate( |
|
|
|
|
|
|
|
req: any, |
|
|
|
|
|
|
|
user: any = { |
|
|
|
roles: { |
|
|
|
roles: { |
|
|
|
guest: true, |
|
|
|
guest: true, |
|
|
|
}, |
|
|
|
}, |
|
|
|
}); |
|
|
|
}, |
|
|
|
|
|
|
|
): Promise<any> { |
|
|
|
|
|
|
|
const u = this.jwtStrategy.validate(req, user); |
|
|
|
|
|
|
|
req.user = user; |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async extractBoolVal( |
|
|
|
|
|
|
|
canActivate: boolean | Promise<boolean> | Observable<boolean>, |
|
|
|
|
|
|
|
) { |
|
|
|
|
|
|
|
if (canActivate instanceof Observable) { |
|
|
|
|
|
|
|
return lastValueFrom(canActivate); |
|
|
|
|
|
|
|
} else if ( |
|
|
|
|
|
|
|
typeof canActivate === 'boolean' || |
|
|
|
|
|
|
|
canActivate instanceof Promise |
|
|
|
|
|
|
|
) { |
|
|
|
|
|
|
|
return canActivate; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|