@checkfirst/nestjs-outlook 3.0.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -102
- package/dist/controllers/microsoft-auth.controller.d.ts +2 -1
- package/dist/controllers/microsoft-auth.controller.js +14 -12
- package/dist/controllers/microsoft-auth.controller.js.map +1 -1
- package/dist/entities/microsoft-user.entity.d.ts +11 -0
- package/dist/entities/microsoft-user.entity.js +67 -0
- package/dist/entities/microsoft-user.entity.js.map +1 -0
- package/dist/entities/outlook-webhook-subscription.entity.d.ts +0 -2
- package/dist/entities/outlook-webhook-subscription.entity.js +0 -10
- package/dist/entities/outlook-webhook-subscription.entity.js.map +1 -1
- package/dist/{event-types.enum.d.ts → enums/event-types.enum.d.ts} +1 -2
- package/dist/{event-types.enum.js → enums/event-types.enum.js} +1 -2
- package/dist/enums/event-types.enum.js.map +1 -0
- package/dist/enums/permission-scope.enum.d.ts +7 -0
- package/dist/enums/permission-scope.enum.js +12 -0
- package/dist/enums/permission-scope.enum.js.map +1 -0
- package/dist/index.d.ts +8 -5
- package/dist/index.js +8 -5
- package/dist/index.js.map +1 -1
- package/dist/interfaces/config/outlook-config.interface.d.ts +1 -1
- package/dist/interfaces/microsoft-auth/state-object.interface.d.ts +4 -2
- package/dist/microsoft-outlook.module.js +6 -1
- package/dist/microsoft-outlook.module.js.map +1 -1
- package/dist/migrations/1699000000000-AddMicrosoftUserTable.d.ts +5 -0
- package/dist/migrations/1699000000000-AddMicrosoftUserTable.js +104 -0
- package/dist/migrations/1699000000000-AddMicrosoftUserTable.js.map +1 -0
- package/dist/repositories/outlook-webhook-subscription.repository.d.ts +1 -1
- package/dist/repositories/outlook-webhook-subscription.repository.js +1 -4
- package/dist/repositories/outlook-webhook-subscription.repository.js.map +1 -1
- package/dist/services/auth/microsoft-auth.service.d.ts +17 -6
- package/dist/services/auth/microsoft-auth.service.js +197 -69
- package/dist/services/auth/microsoft-auth.service.js.map +1 -1
- package/dist/services/calendar/calendar.service.d.ts +6 -8
- package/dist/services/calendar/calendar.service.js +49 -58
- package/dist/services/calendar/calendar.service.js.map +1 -1
- package/dist/services/email/email.service.d.ts +2 -5
- package/dist/services/email/email.service.js +17 -37
- package/dist/services/email/email.service.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -5
- package/dist/event-types.enum.js.map +0 -1
|
@@ -23,6 +23,7 @@ const csrf_token_entity_1 = require("./entities/csrf-token.entity");
|
|
|
23
23
|
const microsoft_csrf_token_repository_1 = require("./repositories/microsoft-csrf-token.repository");
|
|
24
24
|
const calendar_service_1 = require("./services/calendar/calendar.service");
|
|
25
25
|
const email_service_1 = require("./services/email/email.service");
|
|
26
|
+
const microsoft_user_entity_1 = require("./entities/microsoft-user.entity");
|
|
26
27
|
_a = new common_1.ConfigurableModuleBuilder().setClassMethodName('forRoot').build(), exports.ConfigurableModuleClass = _a.ConfigurableModuleClass, exports.MODULE_OPTIONS_TOKEN = _a.MODULE_OPTIONS_TOKEN;
|
|
27
28
|
let MicrosoftOutlookModule = class MicrosoftOutlookModule extends exports.ConfigurableModuleClass {
|
|
28
29
|
};
|
|
@@ -31,7 +32,11 @@ exports.MicrosoftOutlookModule = MicrosoftOutlookModule = __decorate([
|
|
|
31
32
|
(0, common_1.Module)({
|
|
32
33
|
imports: [
|
|
33
34
|
schedule_1.ScheduleModule.forRoot(),
|
|
34
|
-
typeorm_1.TypeOrmModule.forFeature([
|
|
35
|
+
typeorm_1.TypeOrmModule.forFeature([
|
|
36
|
+
outlook_webhook_subscription_entity_1.OutlookWebhookSubscription,
|
|
37
|
+
csrf_token_entity_1.MicrosoftCsrfToken,
|
|
38
|
+
microsoft_user_entity_1.MicrosoftUser,
|
|
39
|
+
]),
|
|
35
40
|
event_emitter_1.EventEmitterModule.forRoot(),
|
|
36
41
|
],
|
|
37
42
|
controllers: [microsoft_auth_controller_1.MicrosoftAuthController, calendar_controller_1.CalendarController, email_controller_1.EmailController],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"microsoft-outlook.module.js","sourceRoot":"","sources":["../src/microsoft-outlook.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAmE;AACnE,6CAAgD;AAChD,+CAAkD;AAClD,yDAA2D;AAC3D,mFAA8E;AAC9E,uFAAkF;AAClF,2EAAuE;AACvE,qEAAiE;AACjE,wGAA4F;AAC5F,oHAA8G;AAC9G,2CAA+C;AAE/C,oEAAkE;AAClE,oGAA8F;AAC9F,2EAAuE;AACvE,kEAA8D;
|
|
1
|
+
{"version":3,"file":"microsoft-outlook.module.js","sourceRoot":"","sources":["../src/microsoft-outlook.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAmE;AACnE,6CAAgD;AAChD,+CAAkD;AAClD,yDAA2D;AAC3D,mFAA8E;AAC9E,uFAAkF;AAClF,2EAAuE;AACvE,qEAAiE;AACjE,wGAA4F;AAC5F,oHAA8G;AAC9G,2CAA+C;AAE/C,oEAAkE;AAClE,oGAA8F;AAC9F,2EAAuE;AACvE,kEAA8D;AAC9D,4EAAiE;AAEpD,KACX,IAAI,kCAAyB,EAA0B,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EADhF,+BAAuB,+BAAE,4BAAoB,2BACoC;AA+BzF,IAAM,sBAAsB,GAA5B,MAAM,sBAAuB,SAAQ,+BAAuB;CAAG,CAAA;AAAzD,wDAAsB;iCAAtB,sBAAsB;IAzBlC,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,yBAAc,CAAC,OAAO,EAAE;YACxB,uBAAa,CAAC,UAAU,CAAC;gBACvB,gEAA0B;gBAC1B,sCAAkB;gBAClB,qCAAa;aACd,CAAC;YACF,kCAAkB,CAAC,OAAO,EAAE;SAC7B;QACD,WAAW,EAAE,CAAC,mDAAuB,EAAE,wCAAkB,EAAE,kCAAe,CAAC;QAC3E,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,4BAAgB;gBACzB,UAAU,EAAE,CAAC,OAA+B,EAAE,EAAE,CAAC,OAAO;gBACxD,MAAM,EAAE,CAAC,4BAAoB,CAAC;aAC/B;YACD,8EAAoC;YACpC,8DAA4B;YAC5B,kCAAe;YACf,4BAAY;YACZ,6CAAoB;SACrB;QACD,OAAO,EAAE,CAAC,kCAAe,EAAE,4BAAY,EAAE,6CAAoB,CAAC;KAC/D,CAAC;GACW,sBAAsB,CAAmC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AddMicrosoftUserTable1699000000000 = void 0;
|
|
4
|
+
const typeorm_1 = require("typeorm");
|
|
5
|
+
class AddMicrosoftUserTable1699000000000 {
|
|
6
|
+
async up(queryRunner) {
|
|
7
|
+
await queryRunner.createTable(new typeorm_1.Table({
|
|
8
|
+
name: 'microsoft_users',
|
|
9
|
+
columns: [
|
|
10
|
+
{
|
|
11
|
+
name: 'id',
|
|
12
|
+
type: 'INTEGER',
|
|
13
|
+
isPrimary: true,
|
|
14
|
+
isGenerated: true,
|
|
15
|
+
generationStrategy: 'increment',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: 'external_user_id',
|
|
19
|
+
type: 'varchar',
|
|
20
|
+
length: '255',
|
|
21
|
+
isNullable: false,
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: 'access_token',
|
|
25
|
+
type: 'text',
|
|
26
|
+
isNullable: false,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'refresh_token',
|
|
30
|
+
type: 'text',
|
|
31
|
+
isNullable: false,
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'token_expiry',
|
|
35
|
+
type: 'timestamp',
|
|
36
|
+
isNullable: false,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'scopes',
|
|
40
|
+
type: 'text',
|
|
41
|
+
isNullable: false,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'is_active',
|
|
45
|
+
type: 'boolean',
|
|
46
|
+
default: true,
|
|
47
|
+
isNullable: false,
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'created_at',
|
|
51
|
+
type: 'timestamp',
|
|
52
|
+
default: 'now()',
|
|
53
|
+
isNullable: false,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'updated_at',
|
|
57
|
+
type: 'timestamp',
|
|
58
|
+
default: 'now()',
|
|
59
|
+
isNullable: false,
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
}), true);
|
|
63
|
+
await queryRunner.createIndex('microsoft_users', new typeorm_1.TableIndex({
|
|
64
|
+
name: 'IDX_microsoft_users_external_user_id',
|
|
65
|
+
columnNames: ['external_user_id'],
|
|
66
|
+
}));
|
|
67
|
+
const table = await queryRunner.getTable('outlook_webhook_subscriptions');
|
|
68
|
+
if (table) {
|
|
69
|
+
const accessTokenColumn = table.findColumnByName('access_token');
|
|
70
|
+
const refreshTokenColumn = table.findColumnByName('refresh_token');
|
|
71
|
+
if (accessTokenColumn) {
|
|
72
|
+
await queryRunner.dropColumn('outlook_webhook_subscriptions', 'access_token');
|
|
73
|
+
}
|
|
74
|
+
if (refreshTokenColumn) {
|
|
75
|
+
await queryRunner.dropColumn('outlook_webhook_subscriptions', 'refresh_token');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async down(queryRunner) {
|
|
80
|
+
const table = await queryRunner.getTable('outlook_webhook_subscriptions');
|
|
81
|
+
if (table) {
|
|
82
|
+
const accessTokenColumn = table.findColumnByName('access_token');
|
|
83
|
+
const refreshTokenColumn = table.findColumnByName('refresh_token');
|
|
84
|
+
if (!accessTokenColumn) {
|
|
85
|
+
await queryRunner.addColumn('outlook_webhook_subscriptions', new typeorm_1.TableColumn({
|
|
86
|
+
name: 'access_token',
|
|
87
|
+
type: 'text',
|
|
88
|
+
isNullable: true,
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
91
|
+
if (!refreshTokenColumn) {
|
|
92
|
+
await queryRunner.addColumn('outlook_webhook_subscriptions', new typeorm_1.TableColumn({
|
|
93
|
+
name: 'refresh_token',
|
|
94
|
+
type: 'text',
|
|
95
|
+
isNullable: true,
|
|
96
|
+
}));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
await queryRunner.dropIndex('microsoft_users', 'IDX_microsoft_users_external_user_id');
|
|
100
|
+
await queryRunner.dropTable('microsoft_users');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.AddMicrosoftUserTable1699000000000 = AddMicrosoftUserTable1699000000000;
|
|
104
|
+
//# sourceMappingURL=1699000000000-AddMicrosoftUserTable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"1699000000000-AddMicrosoftUserTable.js","sourceRoot":"","sources":["../../src/migrations/1699000000000-AddMicrosoftUserTable.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@ export declare class OutlookWebhookSubscriptionRepository {
|
|
|
5
5
|
constructor(repository: Repository<OutlookWebhookSubscription>);
|
|
6
6
|
saveSubscription(subscription: Partial<OutlookWebhookSubscription>): Promise<OutlookWebhookSubscription>;
|
|
7
7
|
findBySubscriptionId(subscriptionId: string): Promise<OutlookWebhookSubscription | null>;
|
|
8
|
-
updateSubscriptionExpiration(subscriptionId: string, expirationDateTime: Date
|
|
8
|
+
updateSubscriptionExpiration(subscriptionId: string, expirationDateTime: Date): Promise<void>;
|
|
9
9
|
deactivateSubscription(subscriptionId: string): Promise<void>;
|
|
10
10
|
findSubscriptionsNeedingRenewal(hoursUntilExpiration: number): Promise<OutlookWebhookSubscription[]>;
|
|
11
11
|
findActiveSubscriptions(): Promise<OutlookWebhookSubscription[]>;
|
|
@@ -41,14 +41,11 @@ let OutlookWebhookSubscriptionRepository = class OutlookWebhookSubscriptionRepos
|
|
|
41
41
|
async findBySubscriptionId(subscriptionId) {
|
|
42
42
|
return this.repository.findOne({ where: { subscriptionId, isActive: true } });
|
|
43
43
|
}
|
|
44
|
-
async updateSubscriptionExpiration(subscriptionId, expirationDateTime
|
|
44
|
+
async updateSubscriptionExpiration(subscriptionId, expirationDateTime) {
|
|
45
45
|
const update = {
|
|
46
46
|
expirationDateTime,
|
|
47
47
|
updatedAt: new Date(),
|
|
48
48
|
};
|
|
49
|
-
if (accessToken) {
|
|
50
|
-
update.accessToken = accessToken;
|
|
51
|
-
}
|
|
52
49
|
await this.repository.update({ subscriptionId, isActive: true }, update);
|
|
53
50
|
}
|
|
54
51
|
async deactivateSubscription(subscriptionId) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"outlook-webhook-subscription.repository.js","sourceRoot":"","sources":["../../src/repositories/outlook-webhook-subscription.repository.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA4C;AAC5C,6CAAmD;AACnD,qCAAyD;AACzD,yGAA6F;AAGtF,IAAM,oCAAoC,GAA1C,MAAM,oCAAoC;IAC/C,YAEmB,UAAkD;QAAlD,eAAU,GAAV,UAAU,CAAwC;IAClE,CAAC;IAEJ,KAAK,CAAC,gBAAgB,CACpB,YAAiD;QAGjD,IAAI,YAAY,CAAC,cAAc,EAAE,CAAC;YAChC,MAAM,oBAAoB,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;gBACzD,KAAK,EAAE,EAAE,cAAc,EAAE,YAAY,CAAC,cAAc,EAAE;aACvD,CAAC,CAAC;YAEH,IAAI,oBAAoB,EAAE,CAAC;gBAEzB,MAAM,UAAU,GAAG,oBAAoB,CAAC,EAAE,CAAC;gBAC3C,MAAM,CAAC,MAAM,CAAC,oBAAoB,EAAE,YAAY,CAAC,CAAC;gBAClD,oBAAoB,CAAC,EAAE,GAAG,UAAU,CAAC;gBACrC,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QAID,MAAM,qBAAqB,qBAAQ,YAAY,CAAE,CAAC;QAClD,OAAO,qBAAqB,CAAC,EAAE,CAAC;QAChC,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;QAEtE,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,cAAsB;QAC/C,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,cAAc,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IAChF,CAAC;IAED,KAAK,CAAC,4BAA4B,CAChC,cAAsB,EACtB,kBAAwB
|
|
1
|
+
{"version":3,"file":"outlook-webhook-subscription.repository.js","sourceRoot":"","sources":["../../src/repositories/outlook-webhook-subscription.repository.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,35 +2,46 @@ import { EventEmitter2 } from '@nestjs/event-emitter';
|
|
|
2
2
|
import { TokenResponse } from '../../interfaces/outlook/token-response.interface';
|
|
3
3
|
import { CalendarService } from '../calendar/calendar.service';
|
|
4
4
|
import { EmailService } from '../email/email.service';
|
|
5
|
-
import { Subscription } from '@microsoft/microsoft-graph-types';
|
|
6
5
|
import { MicrosoftOutlookConfig } from '../../interfaces/config/outlook-config.interface';
|
|
7
6
|
import { MicrosoftCsrfTokenRepository } from '../../repositories/microsoft-csrf-token.repository';
|
|
8
7
|
import { StateObject } from '../../interfaces/microsoft-auth/state-object.interface';
|
|
8
|
+
import { PermissionScope } from '../../enums/permission-scope.enum';
|
|
9
|
+
import { Repository } from 'typeorm';
|
|
10
|
+
import { MicrosoftUser } from '../../entities/microsoft-user.entity';
|
|
9
11
|
export declare class MicrosoftAuthService {
|
|
10
12
|
private readonly eventEmitter;
|
|
11
13
|
private readonly calendarService;
|
|
12
14
|
private readonly emailService;
|
|
13
15
|
private readonly microsoftConfig;
|
|
14
16
|
private readonly csrfTokenRepository;
|
|
17
|
+
private readonly microsoftUserRepository;
|
|
15
18
|
private readonly logger;
|
|
16
19
|
private readonly clientId;
|
|
17
20
|
private readonly clientSecret;
|
|
18
21
|
private readonly tenantId;
|
|
19
22
|
private readonly redirectUri;
|
|
20
23
|
private readonly tokenEndpoint;
|
|
21
|
-
private readonly
|
|
24
|
+
private readonly requiredScopes;
|
|
25
|
+
private readonly defaultScopes;
|
|
22
26
|
private readonly CSRF_TOKEN_EXPIRY;
|
|
23
27
|
private subscriptionInProgress;
|
|
24
|
-
constructor(eventEmitter: EventEmitter2, calendarService: CalendarService, emailService: EmailService, microsoftConfig: MicrosoftOutlookConfig, csrfTokenRepository: MicrosoftCsrfTokenRepository);
|
|
28
|
+
constructor(eventEmitter: EventEmitter2, calendarService: CalendarService, emailService: EmailService, microsoftConfig: MicrosoftOutlookConfig, csrfTokenRepository: MicrosoftCsrfTokenRepository, microsoftUserRepository: Repository<MicrosoftUser>);
|
|
29
|
+
private mapToMicrosoftScopes;
|
|
25
30
|
private buildRedirectUri;
|
|
26
31
|
cleanupExpiredTokens(): Promise<void>;
|
|
27
32
|
private generateCsrfToken;
|
|
28
33
|
parseState(state: string): StateObject | null;
|
|
29
34
|
validateCsrfToken(token: string, timestamp?: number): Promise<string | null>;
|
|
30
|
-
getLoginUrl(userId: string): Promise<string>;
|
|
35
|
+
getLoginUrl(userId: string, scopes?: PermissionScope[]): Promise<string>;
|
|
36
|
+
private saveMicrosoftUser;
|
|
37
|
+
private getMicrosoftUserTokenInfo;
|
|
38
|
+
getUserAccessTokenByExternalUserId(externalUserId: string): Promise<string>;
|
|
39
|
+
getUserAccessTokenByUserId(internalUserId: number | string): Promise<string>;
|
|
40
|
+
private processTokenInfo;
|
|
31
41
|
exchangeCodeForToken(code: string, state: string): Promise<TokenResponse>;
|
|
32
42
|
private setupSubscriptions;
|
|
33
|
-
refreshAccessToken(refreshToken: string, userId
|
|
34
|
-
|
|
43
|
+
refreshAccessToken(refreshToken: string, userId: number): Promise<string>;
|
|
44
|
+
private hasCalendarPermission;
|
|
45
|
+
private hasEmailPermission;
|
|
35
46
|
isTokenExpired(tokenExpiry: Date, bufferMinutes?: number): boolean;
|
|
36
47
|
}
|
|
@@ -17,23 +17,35 @@ exports.MicrosoftAuthService = void 0;
|
|
|
17
17
|
const common_1 = require("@nestjs/common");
|
|
18
18
|
const event_emitter_1 = require("@nestjs/event-emitter");
|
|
19
19
|
const axios_1 = require("axios");
|
|
20
|
-
const qs = require("querystring");
|
|
21
20
|
const calendar_service_1 = require("../calendar/calendar.service");
|
|
22
21
|
const email_service_1 = require("../email/email.service");
|
|
23
22
|
const constants_1 = require("../../constants");
|
|
24
|
-
const event_types_enum_1 = require("../../event-types.enum");
|
|
23
|
+
const event_types_enum_1 = require("../../enums/event-types.enum");
|
|
25
24
|
const crypto = require("crypto");
|
|
26
25
|
const schedule_1 = require("@nestjs/schedule");
|
|
27
26
|
const microsoft_csrf_token_repository_1 = require("../../repositories/microsoft-csrf-token.repository");
|
|
27
|
+
const permission_scope_enum_1 = require("../../enums/permission-scope.enum");
|
|
28
|
+
const typeorm_1 = require("@nestjs/typeorm");
|
|
29
|
+
const typeorm_2 = require("typeorm");
|
|
30
|
+
const microsoft_user_entity_1 = require("../../entities/microsoft-user.entity");
|
|
28
31
|
let MicrosoftAuthService = MicrosoftAuthService_1 = class MicrosoftAuthService {
|
|
29
|
-
constructor(eventEmitter, calendarService, emailService, microsoftConfig, csrfTokenRepository) {
|
|
32
|
+
constructor(eventEmitter, calendarService, emailService, microsoftConfig, csrfTokenRepository, microsoftUserRepository) {
|
|
30
33
|
this.eventEmitter = eventEmitter;
|
|
31
34
|
this.calendarService = calendarService;
|
|
32
35
|
this.emailService = emailService;
|
|
33
36
|
this.microsoftConfig = microsoftConfig;
|
|
34
37
|
this.csrfTokenRepository = csrfTokenRepository;
|
|
38
|
+
this.microsoftUserRepository = microsoftUserRepository;
|
|
35
39
|
this.logger = new common_1.Logger(MicrosoftAuthService_1.name);
|
|
36
40
|
this.tenantId = 'common';
|
|
41
|
+
this.requiredScopes = ['offline_access', 'User.Read'];
|
|
42
|
+
this.defaultScopes = [
|
|
43
|
+
permission_scope_enum_1.PermissionScope.CALENDAR_READ,
|
|
44
|
+
permission_scope_enum_1.PermissionScope.CALENDAR_WRITE,
|
|
45
|
+
permission_scope_enum_1.PermissionScope.EMAIL_SEND,
|
|
46
|
+
permission_scope_enum_1.PermissionScope.EMAIL_READ,
|
|
47
|
+
permission_scope_enum_1.PermissionScope.EMAIL_WRITE,
|
|
48
|
+
];
|
|
37
49
|
this.CSRF_TOKEN_EXPIRY = 30 * 60 * 1000;
|
|
38
50
|
this.subscriptionInProgress = new Map();
|
|
39
51
|
console.log('MicrosoftAuthService constructor - microsoftConfig:', {
|
|
@@ -45,11 +57,25 @@ let MicrosoftAuthService = MicrosoftAuthService_1 = class MicrosoftAuthService {
|
|
|
45
57
|
this.redirectUri = this.buildRedirectUri(this.microsoftConfig);
|
|
46
58
|
console.log('Redirect URI:', this.redirectUri);
|
|
47
59
|
this.tokenEndpoint = 'https://login.microsoftonline.com/common/oauth2/v2.0/token';
|
|
48
|
-
this.scope = ['offline_access', 'Calendars.ReadWrite', 'Calendars.Read', 'User.Read', 'Mail.Send', 'Mail.ReadWrite', 'Mail.Read'].join(' ');
|
|
49
60
|
this.logger.log(`Microsoft OAuth redirect URI set to: ${this.redirectUri}`);
|
|
50
61
|
}
|
|
62
|
+
mapToMicrosoftScopes(scopes) {
|
|
63
|
+
const scopeMapping = {
|
|
64
|
+
[permission_scope_enum_1.PermissionScope.CALENDAR_READ]: ['Calendars.Read'],
|
|
65
|
+
[permission_scope_enum_1.PermissionScope.CALENDAR_WRITE]: ['Calendars.ReadWrite'],
|
|
66
|
+
[permission_scope_enum_1.PermissionScope.EMAIL_READ]: ['Mail.Read'],
|
|
67
|
+
[permission_scope_enum_1.PermissionScope.EMAIL_WRITE]: ['Mail.ReadWrite'],
|
|
68
|
+
[permission_scope_enum_1.PermissionScope.EMAIL_SEND]: ['Mail.Send'],
|
|
69
|
+
};
|
|
70
|
+
const microsoftScopes = new Set();
|
|
71
|
+
this.requiredScopes.forEach(scope => microsoftScopes.add(scope));
|
|
72
|
+
scopes.forEach(scope => {
|
|
73
|
+
scopeMapping[scope].forEach(mappedScope => microsoftScopes.add(mappedScope));
|
|
74
|
+
});
|
|
75
|
+
return Array.from(microsoftScopes);
|
|
76
|
+
}
|
|
51
77
|
buildRedirectUri(config) {
|
|
52
|
-
if (config.redirectPath
|
|
78
|
+
if (config.redirectPath.startsWith('http')) {
|
|
53
79
|
this.logger.log(`Using complete redirect URI from config: ${config.redirectPath}`);
|
|
54
80
|
return config.redirectPath;
|
|
55
81
|
}
|
|
@@ -114,20 +140,24 @@ let MicrosoftAuthService = MicrosoftAuthService_1 = class MicrosoftAuthService {
|
|
|
114
140
|
}
|
|
115
141
|
return null;
|
|
116
142
|
}
|
|
117
|
-
async getLoginUrl(userId) {
|
|
143
|
+
async getLoginUrl(userId, scopes = this.defaultScopes) {
|
|
118
144
|
const csrf = await this.generateCsrfToken(userId);
|
|
119
145
|
const stateObj = {
|
|
120
146
|
userId,
|
|
121
147
|
csrf,
|
|
122
148
|
timestamp: Date.now(),
|
|
149
|
+
requestedScopes: scopes,
|
|
123
150
|
};
|
|
124
151
|
const stateJson = JSON.stringify(stateObj);
|
|
125
152
|
const state = Buffer.from(stateJson).toString('base64').replace(/=/g, '');
|
|
126
153
|
this.logger.log(`State object: ${JSON.stringify(stateObj)}`);
|
|
154
|
+
const scopeString = this.mapToMicrosoftScopes(scopes).join(' ');
|
|
155
|
+
const encodedScope = encodeURIComponent(scopeString);
|
|
127
156
|
const encodedRedirectUri = encodeURIComponent(this.redirectUri);
|
|
128
|
-
|
|
129
|
-
this.logger.
|
|
130
|
-
this.logger.
|
|
157
|
+
this.logger.debug(`Requested generic scopes: ${scopes.join(', ')}`);
|
|
158
|
+
this.logger.debug(`Mapped to Microsoft scopes: ${scopeString}`);
|
|
159
|
+
this.logger.debug(`Redirect URI (raw): ${this.redirectUri}`);
|
|
160
|
+
this.logger.debug(`Redirect URI (encoded): ${encodedRedirectUri}`);
|
|
131
161
|
const authorizeUrl = `https://login.microsoftonline.com/${this.tenantId}/oauth2/v2.0/authorize` +
|
|
132
162
|
`?client_id=${this.clientId}` +
|
|
133
163
|
`&response_type=code` +
|
|
@@ -138,9 +168,85 @@ let MicrosoftAuthService = MicrosoftAuthService_1 = class MicrosoftAuthService {
|
|
|
138
168
|
this.logger.log(`FINAL MICROSOFT LOGIN URL: ${authorizeUrl}`);
|
|
139
169
|
return authorizeUrl;
|
|
140
170
|
}
|
|
171
|
+
async saveMicrosoftUser(externalUserId, accessToken, refreshToken, expiresIn, scopes) {
|
|
172
|
+
let user = await this.microsoftUserRepository.findOne({
|
|
173
|
+
where: { externalUserId: externalUserId, isActive: true }
|
|
174
|
+
});
|
|
175
|
+
if (!user) {
|
|
176
|
+
user = new microsoft_user_entity_1.MicrosoftUser();
|
|
177
|
+
user.externalUserId = externalUserId;
|
|
178
|
+
}
|
|
179
|
+
user.accessToken = accessToken;
|
|
180
|
+
user.refreshToken = refreshToken;
|
|
181
|
+
user.tokenExpiry = new Date(Date.now() + expiresIn * 1000);
|
|
182
|
+
user.scopes = scopes;
|
|
183
|
+
user.isActive = true;
|
|
184
|
+
await this.microsoftUserRepository.save(user);
|
|
185
|
+
}
|
|
186
|
+
async getMicrosoftUserTokenInfo(externalUserId) {
|
|
187
|
+
const user = await this.microsoftUserRepository.findOne({
|
|
188
|
+
where: { externalUserId: externalUserId, isActive: true }
|
|
189
|
+
});
|
|
190
|
+
if (!user) {
|
|
191
|
+
return null;
|
|
192
|
+
}
|
|
193
|
+
return {
|
|
194
|
+
accessToken: user.accessToken,
|
|
195
|
+
refreshToken: user.refreshToken,
|
|
196
|
+
tokenExpiry: user.tokenExpiry,
|
|
197
|
+
scopes: user.scopes,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
async getUserAccessTokenByExternalUserId(externalUserId) {
|
|
201
|
+
try {
|
|
202
|
+
const userInfo = await this.getMicrosoftUserTokenInfo(externalUserId);
|
|
203
|
+
if (!userInfo) {
|
|
204
|
+
throw new Error(`No token information found for user ${externalUserId}`);
|
|
205
|
+
}
|
|
206
|
+
const user = await this.microsoftUserRepository.findOne({
|
|
207
|
+
where: { externalUserId: externalUserId, isActive: true }
|
|
208
|
+
});
|
|
209
|
+
if (!user) {
|
|
210
|
+
throw new Error(`Could not find user record for ${externalUserId}`);
|
|
211
|
+
}
|
|
212
|
+
return await this.processTokenInfo(userInfo, user.id);
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
this.logger.error(`Error getting access token for user ${externalUserId}:`, error);
|
|
216
|
+
throw new Error(`Failed to get valid access token: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
async getUserAccessTokenByUserId(internalUserId) {
|
|
220
|
+
try {
|
|
221
|
+
const user = await this.microsoftUserRepository.findOne({
|
|
222
|
+
where: { id: typeof internalUserId === 'string' ? parseInt(internalUserId, 10) : internalUserId }
|
|
223
|
+
});
|
|
224
|
+
if (!user) {
|
|
225
|
+
throw new Error(`No Microsoft user found with internal ID ${String(internalUserId)}`);
|
|
226
|
+
}
|
|
227
|
+
return await this.processTokenInfo({
|
|
228
|
+
accessToken: user.accessToken,
|
|
229
|
+
refreshToken: user.refreshToken,
|
|
230
|
+
tokenExpiry: user.tokenExpiry,
|
|
231
|
+
scopes: user.scopes
|
|
232
|
+
}, user.id);
|
|
233
|
+
}
|
|
234
|
+
catch (error) {
|
|
235
|
+
this.logger.error(`Error getting access token for internal user ID ${String(internalUserId)}:`, error);
|
|
236
|
+
throw new Error(`Failed to get valid access token: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async processTokenInfo(tokenInfo, userId) {
|
|
240
|
+
if (!this.isTokenExpired(tokenInfo.tokenExpiry)) {
|
|
241
|
+
return tokenInfo.accessToken;
|
|
242
|
+
}
|
|
243
|
+
this.logger.log(`Access token for user ID ${String(userId)} is expired, refreshing...`);
|
|
244
|
+
const accessToken = await this.refreshAccessToken(tokenInfo.refreshToken, userId);
|
|
245
|
+
return accessToken;
|
|
246
|
+
}
|
|
141
247
|
async exchangeCodeForToken(code, state) {
|
|
142
248
|
const stateData = this.parseState(state);
|
|
143
|
-
if (!stateData ||
|
|
249
|
+
if (!(stateData === null || stateData === void 0 ? void 0 : stateData.userId)) {
|
|
144
250
|
throw new Error('Invalid state parameter - missing user ID');
|
|
145
251
|
}
|
|
146
252
|
const csrfError = await this.validateCsrfToken(stateData.csrf, stateData.timestamp);
|
|
@@ -150,9 +256,12 @@ let MicrosoftAuthService = MicrosoftAuthService_1 = class MicrosoftAuthService {
|
|
|
150
256
|
}
|
|
151
257
|
try {
|
|
152
258
|
this.logger.log(`Exchanging code for token with redirect URI: ${this.redirectUri}`);
|
|
259
|
+
const scopesToUse = stateData.requestedScopes || this.defaultScopes;
|
|
260
|
+
this.logger.log(`Using scopes for token exchange: ${scopesToUse.join(', ')}`);
|
|
261
|
+
const scopeString = this.mapToMicrosoftScopes(scopesToUse).join(' ');
|
|
153
262
|
const postData = new URLSearchParams({
|
|
154
263
|
client_id: this.clientId,
|
|
155
|
-
scope:
|
|
264
|
+
scope: scopeString,
|
|
156
265
|
code: code,
|
|
157
266
|
redirect_uri: this.redirectUri,
|
|
158
267
|
grant_type: 'authorization_code',
|
|
@@ -169,11 +278,12 @@ let MicrosoftAuthService = MicrosoftAuthService_1 = class MicrosoftAuthService {
|
|
|
169
278
|
refresh_token: tokenResponse.data.refresh_token || '',
|
|
170
279
|
expires_in: tokenResponse.data.expires_in,
|
|
171
280
|
};
|
|
172
|
-
await
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
281
|
+
await this.saveMicrosoftUser(stateData.userId, tokenData.access_token, tokenData.refresh_token, tokenData.expires_in, scopeString);
|
|
282
|
+
await Promise.resolve(this.eventEmitter.emit(event_types_enum_1.OutlookEventTypes.USER_AUTHENTICATED, stateData.userId, {
|
|
283
|
+
externalUserId: stateData.userId,
|
|
284
|
+
scopes: scopesToUse
|
|
285
|
+
}));
|
|
286
|
+
await this.setupSubscriptions(stateData.userId, scopesToUse);
|
|
177
287
|
return tokenData;
|
|
178
288
|
}
|
|
179
289
|
catch (error) {
|
|
@@ -181,83 +291,99 @@ let MicrosoftAuthService = MicrosoftAuthService_1 = class MicrosoftAuthService {
|
|
|
181
291
|
throw new Error('Failed to exchange code for token');
|
|
182
292
|
}
|
|
183
293
|
}
|
|
184
|
-
async setupSubscriptions(userId,
|
|
185
|
-
|
|
186
|
-
|
|
294
|
+
async setupSubscriptions(userId, scopes = this.defaultScopes) {
|
|
295
|
+
const userIdNum = parseInt(userId, 10);
|
|
296
|
+
if (this.subscriptionInProgress.get(userIdNum)) {
|
|
297
|
+
this.logger.log(`Subscription setup already in progress for user ${userId}`);
|
|
187
298
|
return;
|
|
188
299
|
}
|
|
189
300
|
try {
|
|
190
|
-
this.subscriptionInProgress.set(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
301
|
+
this.subscriptionInProgress.set(userIdNum, true);
|
|
302
|
+
if (this.hasCalendarPermission(scopes)) {
|
|
303
|
+
try {
|
|
304
|
+
await this.calendarService.createWebhookSubscription(userId);
|
|
305
|
+
this.logger.log(`Successfully created calendar webhook subscription for user ${userId}`);
|
|
306
|
+
}
|
|
307
|
+
catch (calendarError) {
|
|
308
|
+
this.logger.error(`Failed to create calendar webhook subscription: ${calendarError instanceof Error ? calendarError.message : 'Unknown error'}`);
|
|
309
|
+
}
|
|
197
310
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
311
|
+
if (this.hasEmailPermission(scopes)) {
|
|
312
|
+
try {
|
|
313
|
+
await this.emailService.createWebhookSubscription(userId);
|
|
314
|
+
this.logger.log(`Successfully created email webhook subscription for user ${userId}`);
|
|
315
|
+
}
|
|
316
|
+
catch (emailError) {
|
|
317
|
+
this.logger.error(`Failed to create email webhook subscription: ${emailError instanceof Error ? emailError.message : 'Unknown error'}`);
|
|
318
|
+
}
|
|
204
319
|
}
|
|
205
320
|
}
|
|
206
321
|
catch (error) {
|
|
207
322
|
this.logger.error(`Error setting up subscriptions: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
208
323
|
}
|
|
209
324
|
finally {
|
|
210
|
-
this.subscriptionInProgress.set(
|
|
325
|
+
this.subscriptionInProgress.set(userIdNum, false);
|
|
211
326
|
}
|
|
212
327
|
}
|
|
213
|
-
async refreshAccessToken(refreshToken, userId
|
|
328
|
+
async refreshAccessToken(refreshToken, userId) {
|
|
214
329
|
try {
|
|
215
|
-
const
|
|
330
|
+
const user = await this.microsoftUserRepository.findOne({
|
|
331
|
+
where: { id: userId }
|
|
332
|
+
});
|
|
333
|
+
if (!user) {
|
|
334
|
+
throw new Error(`No user found with ID ${String(userId)}`);
|
|
335
|
+
}
|
|
336
|
+
const scopeString = user.scopes;
|
|
337
|
+
this.logger.debug(`Using saved scopes from database: ${scopeString}`);
|
|
338
|
+
this.logger.debug(`Refreshing token for user ID ${String(userId)} with scopes: ${scopeString}`);
|
|
339
|
+
const payload = new URLSearchParams({
|
|
216
340
|
client_id: this.clientId,
|
|
217
341
|
client_secret: this.clientSecret,
|
|
218
342
|
refresh_token: refreshToken,
|
|
219
343
|
grant_type: 'refresh_token',
|
|
220
|
-
scope:
|
|
221
|
-
};
|
|
222
|
-
const response = await axios_1.default.post(this.tokenEndpoint, qs.stringify(payload), {
|
|
223
|
-
headers: {
|
|
224
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
|
225
|
-
},
|
|
344
|
+
scope: scopeString,
|
|
226
345
|
});
|
|
227
|
-
|
|
228
|
-
|
|
346
|
+
try {
|
|
347
|
+
const response = await axios_1.default.post(this.tokenEndpoint, payload.toString(), {
|
|
348
|
+
headers: {
|
|
349
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
350
|
+
},
|
|
351
|
+
});
|
|
352
|
+
if (!response.data.access_token || !response.data.expires_in) {
|
|
353
|
+
throw new Error('Invalid token refresh response from Microsoft');
|
|
354
|
+
}
|
|
355
|
+
const newRefreshToken = response.data.refresh_token || refreshToken;
|
|
356
|
+
const newAccessToken = response.data.access_token;
|
|
357
|
+
user.accessToken = newAccessToken;
|
|
358
|
+
user.refreshToken = newRefreshToken;
|
|
359
|
+
user.tokenExpiry = new Date(Date.now() + response.data.expires_in * 1000);
|
|
360
|
+
await this.microsoftUserRepository.save(user);
|
|
361
|
+
return newAccessToken;
|
|
229
362
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
await Promise.resolve(this.eventEmitter.emit(event_types_enum_1.OutlookEventTypes.AUTH_TOKENS_UPDATE, userIdStr, calendarIdStr, tokenData));
|
|
363
|
+
catch (error) {
|
|
364
|
+
if (axios_1.default.isAxiosError(error) && error.response) {
|
|
365
|
+
this.logger.error(`Microsoft API error refreshing token for user ID ${String(userId)}: Status: ${String(error.response.status)}, Response: ${JSON.stringify(error.response.data)}`);
|
|
366
|
+
const errorData = error.response.data;
|
|
367
|
+
if (errorData.error === 'invalid_grant') {
|
|
368
|
+
throw new Error('Microsoft refresh token is invalid or expired');
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
throw error;
|
|
240
372
|
}
|
|
241
|
-
return tokenData;
|
|
242
373
|
}
|
|
243
374
|
catch (error) {
|
|
244
|
-
this.logger.error(
|
|
375
|
+
this.logger.error(`Error refreshing access token for user ID ${String(userId)}:`, error);
|
|
245
376
|
throw new Error('Failed to refresh access token from Microsoft');
|
|
246
377
|
}
|
|
247
378
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
const tokenResponse = await this.refreshAccessToken(refreshToken);
|
|
257
|
-
return await this.calendarService.renewWebhookSubscription(subscriptionId, tokenResponse.access_token);
|
|
258
|
-
}
|
|
259
|
-
throw error;
|
|
260
|
-
}
|
|
379
|
+
hasCalendarPermission(scopes) {
|
|
380
|
+
return scopes.some(scope => scope === permission_scope_enum_1.PermissionScope.CALENDAR_READ ||
|
|
381
|
+
scope === permission_scope_enum_1.PermissionScope.CALENDAR_WRITE);
|
|
382
|
+
}
|
|
383
|
+
hasEmailPermission(scopes) {
|
|
384
|
+
return scopes.some(scope => scope === permission_scope_enum_1.PermissionScope.EMAIL_READ ||
|
|
385
|
+
scope === permission_scope_enum_1.PermissionScope.EMAIL_WRITE ||
|
|
386
|
+
scope === permission_scope_enum_1.PermissionScope.EMAIL_SEND);
|
|
261
387
|
}
|
|
262
388
|
isTokenExpired(tokenExpiry, bufferMinutes = 5) {
|
|
263
389
|
const currentTimeWithBuffer = new Date(Date.now() + bufferMinutes * 60 * 1000);
|
|
@@ -276,8 +402,10 @@ exports.MicrosoftAuthService = MicrosoftAuthService = MicrosoftAuthService_1 = _
|
|
|
276
402
|
__param(1, (0, common_1.Inject)((0, common_1.forwardRef)(() => calendar_service_1.CalendarService))),
|
|
277
403
|
__param(2, (0, common_1.Inject)((0, common_1.forwardRef)(() => email_service_1.EmailService))),
|
|
278
404
|
__param(3, (0, common_1.Inject)(constants_1.MICROSOFT_CONFIG)),
|
|
405
|
+
__param(5, (0, typeorm_1.InjectRepository)(microsoft_user_entity_1.MicrosoftUser)),
|
|
279
406
|
__metadata("design:paramtypes", [event_emitter_1.EventEmitter2,
|
|
280
407
|
calendar_service_1.CalendarService,
|
|
281
|
-
email_service_1.EmailService, Object, microsoft_csrf_token_repository_1.MicrosoftCsrfTokenRepository
|
|
408
|
+
email_service_1.EmailService, Object, microsoft_csrf_token_repository_1.MicrosoftCsrfTokenRepository,
|
|
409
|
+
typeorm_2.Repository])
|
|
282
410
|
], MicrosoftAuthService);
|
|
283
411
|
//# sourceMappingURL=microsoft-auth.service.js.map
|