1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const tslib_1 = require("tslib");
|
4 | const common_1 = require("@nestjs/common");
|
5 | const core_1 = require("@nestjs/core");
|
6 | const common_2 = require("@nestjs/common");
|
7 | const logging_1 = require("../gcloud/logging");
|
8 | const context_1 = require("../datastore/context");
|
9 | const configuration_1 = require("../configuration");
|
10 | const logger = logging_1.createLogger('auth-guard');
|
11 | exports.Roles = (...roles) => common_2.ReflectMetadata('roles', roles);
|
12 | exports.AllowAnonymous = () => common_2.ReflectMetadata('allowAnonymous', true);
|
13 | exports.Task = () => common_2.ReflectMetadata('secure-header', 'x-appengine-taskname');
|
14 | exports.Cron = () => common_2.ReflectMetadata('secure-header', 'x-appengine-cron');
|
15 | exports.System = () => common_2.ReflectMetadata('system', true);
|
16 | const reflectValue = (reflector, key, context, defaultValue) => {
|
17 | const methodValue = reflector.get(key, context.getHandler());
|
18 | if (methodValue !== undefined) {
|
19 | return methodValue;
|
20 | }
|
21 | const classValue = reflector.get(key, context.getClass());
|
22 | if (classValue !== undefined) {
|
23 | return classValue;
|
24 | }
|
25 | return defaultValue;
|
26 | };
|
27 | function isAllowAnonymous(reflector, context) {
|
28 | return reflectValue(reflector, 'allowAnonymous', context, false);
|
29 | }
|
30 | function isUserAllowedAccess(reflector, context, user) {
|
31 | if (!user) {
|
32 | return false;
|
33 | }
|
34 | const roles = reflectValue(reflector, 'roles', context, []);
|
35 | if (!roles.length) {
|
36 | return true;
|
37 | }
|
38 | const { roles: userRoles = [] } = user;
|
39 | const allowed = roles.some(role => userRoles.includes(role));
|
40 | if (!allowed) {
|
41 | logger.warn('User does not have the required role');
|
42 | }
|
43 | return allowed;
|
44 | }
|
45 | function isSystemCall(reflector, context) {
|
46 | return reflectValue(reflector, 'system', context, false);
|
47 | }
|
48 | async function isAuthorizedSystemCall(reflector, context, secret) {
|
49 | const { verify } = await Promise.resolve().then(() => require('jsonwebtoken'));
|
50 | const { headers } = context.switchToHttp().getRequest();
|
51 | if (!headers.authorization) {
|
52 | return false;
|
53 | }
|
54 | const token = headers.authorization.substr(4);
|
55 | return new Promise(resolve => verify(token, secret, {
|
56 | maxAge: '5 min',
|
57 | algorithms: ['HS256'],
|
58 | }, err => {
|
59 | if (err) {
|
60 | logger.error('Error decoding system token', err);
|
61 | resolve(false);
|
62 | }
|
63 | else {
|
64 | resolve(true);
|
65 | }
|
66 | }));
|
67 | }
|
68 | function hasSecureHeader(reflector, context) {
|
69 | const { headers } = context.switchToHttp().getRequest();
|
70 | if (!headers) {
|
71 | return false;
|
72 | }
|
73 | const secureHeader = reflectValue(reflector, 'secure-header', context, undefined);
|
74 | if (secureHeader) {
|
75 | return !!headers[secureHeader];
|
76 | }
|
77 | return false;
|
78 | }
|
79 | function getUser(context) {
|
80 | const request = context.switchToHttp().getRequest();
|
81 | if (request.context && request.context.user) {
|
82 | return request.context.user;
|
83 | }
|
84 | else {
|
85 | const args = context.getArgs();
|
86 | if (args.length > 2) {
|
87 | const ctxt = args[2];
|
88 | if (context_1.isContext(ctxt)) {
|
89 | return ctxt.user;
|
90 | }
|
91 | }
|
92 | }
|
93 | return undefined;
|
94 | }
|
95 | let AuthGuard = class AuthGuard {
|
96 | constructor(reflector, configurationProvider) {
|
97 | this.reflector = reflector;
|
98 | this.configurationProvider = configurationProvider;
|
99 | this.logger = logging_1.createLogger('auth-guard');
|
100 | }
|
101 | canActivate(context) {
|
102 | if (isAllowAnonymous(this.reflector, context)) {
|
103 | return true;
|
104 | }
|
105 | if (isSystemCall(this.reflector, context)) {
|
106 | return isAuthorizedSystemCall(this.reflector, context, this.configurationProvider.systemSecret);
|
107 | }
|
108 | if (hasSecureHeader(this.reflector, context)) {
|
109 | return true;
|
110 | }
|
111 | const user = getUser(context);
|
112 | return isUserAllowedAccess(this.reflector, context, user);
|
113 | }
|
114 | };
|
115 | AuthGuard = tslib_1.__decorate([
|
116 | common_1.Injectable(),
|
117 | tslib_1.__param(1, common_1.Inject(configuration_1.CONFIGURATION)),
|
118 | tslib_1.__metadata("design:paramtypes", [core_1.Reflector, Object])
|
119 | ], AuthGuard);
|
120 | exports.AuthGuard = AuthGuard;
|
121 |
|
\ | No newline at end of file |