/
tenant-context.middleware.ts
68 lines (65 loc) · 2.18 KB
/
tenant-context.middleware.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
// Copyright (c) 2023 Sourcefuse Technologies
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
import {
Context,
InvocationResult,
Provider,
ValueOrPromise,
globalInterceptor,
inject,
} from '@loopback/core';
import {Middleware, MiddlewareContext, RequestContext} from '@loopback/rest';
import {AuthenticationBindings} from 'loopback4-authentication';
import {IAuthUserWithPermissions} from '../components/bearer-verifier';
import {SFCoreBindings} from '../keys';
import {CoreConfig, TenantIdEncryptionFn} from '../types';
@globalInterceptor()
export class TenantContextMiddlewareInterceptorProvider
implements Provider<Middleware>
{
constructor(
@inject(AuthenticationBindings.CURRENT_USER)
protected currentUser: IAuthUserWithPermissions,
@inject(SFCoreBindings.config, {optional: true})
private readonly coreConfig: CoreConfig,
@inject(SFCoreBindings.TENANTID_ENCRYPTION_PROVIDER)
private readonly tenantIdEncryptionProvider: TenantIdEncryptionFn,
) {}
value() {
return this.intercept.bind(this);
}
/**
* The intercept function checks for a request context, encrypts the tenant ID, and adds it to the
* request headers if the current user has a tenant ID and a secret key is available.
*/
async intercept(
context: MiddlewareContext,
next: () => ValueOrPromise<InvocationResult>,
) {
let request, response;
if (this.isRequestContext(context.parent)) {
request = context.parent.request;
response = context.parent.response;
}
if (request && response && this.currentUser?.tenantId) {
if (!this.coreConfig.tenantContextEncryptionKey) {
request.headers['tenant-id'] = this.currentUser.tenantId;
} else {
const encryptedTenantId = await this.tenantIdEncryptionProvider(
this.coreConfig.tenantContextEncryptionKey,
this.currentUser.tenantId,
);
request.headers['tenant-id'] = encryptedTenantId;
}
}
return next();
}
private isRequestContext(context?: Context): context is RequestContext {
return !!(
(context as RequestContext).request &&
(context as RequestContext).response
);
}
}