@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.
Files changed (41) hide show
  1. package/README.md +82 -102
  2. package/dist/controllers/microsoft-auth.controller.d.ts +2 -1
  3. package/dist/controllers/microsoft-auth.controller.js +14 -12
  4. package/dist/controllers/microsoft-auth.controller.js.map +1 -1
  5. package/dist/entities/microsoft-user.entity.d.ts +11 -0
  6. package/dist/entities/microsoft-user.entity.js +67 -0
  7. package/dist/entities/microsoft-user.entity.js.map +1 -0
  8. package/dist/entities/outlook-webhook-subscription.entity.d.ts +0 -2
  9. package/dist/entities/outlook-webhook-subscription.entity.js +0 -10
  10. package/dist/entities/outlook-webhook-subscription.entity.js.map +1 -1
  11. package/dist/{event-types.enum.d.ts → enums/event-types.enum.d.ts} +1 -2
  12. package/dist/{event-types.enum.js → enums/event-types.enum.js} +1 -2
  13. package/dist/enums/event-types.enum.js.map +1 -0
  14. package/dist/enums/permission-scope.enum.d.ts +7 -0
  15. package/dist/enums/permission-scope.enum.js +12 -0
  16. package/dist/enums/permission-scope.enum.js.map +1 -0
  17. package/dist/index.d.ts +8 -5
  18. package/dist/index.js +8 -5
  19. package/dist/index.js.map +1 -1
  20. package/dist/interfaces/config/outlook-config.interface.d.ts +1 -1
  21. package/dist/interfaces/microsoft-auth/state-object.interface.d.ts +4 -2
  22. package/dist/microsoft-outlook.module.js +6 -1
  23. package/dist/microsoft-outlook.module.js.map +1 -1
  24. package/dist/migrations/1699000000000-AddMicrosoftUserTable.d.ts +5 -0
  25. package/dist/migrations/1699000000000-AddMicrosoftUserTable.js +104 -0
  26. package/dist/migrations/1699000000000-AddMicrosoftUserTable.js.map +1 -0
  27. package/dist/repositories/outlook-webhook-subscription.repository.d.ts +1 -1
  28. package/dist/repositories/outlook-webhook-subscription.repository.js +1 -4
  29. package/dist/repositories/outlook-webhook-subscription.repository.js.map +1 -1
  30. package/dist/services/auth/microsoft-auth.service.d.ts +17 -6
  31. package/dist/services/auth/microsoft-auth.service.js +197 -69
  32. package/dist/services/auth/microsoft-auth.service.js.map +1 -1
  33. package/dist/services/calendar/calendar.service.d.ts +6 -8
  34. package/dist/services/calendar/calendar.service.js +49 -58
  35. package/dist/services/calendar/calendar.service.js.map +1 -1
  36. package/dist/services/email/email.service.d.ts +2 -5
  37. package/dist/services/email/email.service.js +17 -37
  38. package/dist/services/email/email.service.js.map +1 -1
  39. package/dist/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +6 -5
  41. 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([outlook_webhook_subscription_entity_1.OutlookWebhookSubscription, csrf_token_entity_1.MicrosoftCsrfToken]),
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;AAEjD,KACX,IAAI,kCAAyB,EAA0B,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EADhF,+BAAuB,+BAAE,4BAAoB,2BACoC;AA2BzF,IAAM,sBAAsB,GAA5B,MAAM,sBAAuB,SAAQ,+BAAuB;CAAG,CAAA;AAAzD,wDAAsB;iCAAtB,sBAAsB;IArBlC,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,yBAAc,CAAC,OAAO,EAAE;YACxB,uBAAa,CAAC,UAAU,CAAC,CAAC,gEAA0B,EAAE,sCAAkB,CAAC,CAAC;YAC1E,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"}
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,5 @@
1
+ import { MigrationInterface, QueryRunner } from 'typeorm';
2
+ export declare class AddMicrosoftUserTable1699000000000 implements MigrationInterface {
3
+ up(queryRunner: QueryRunner): Promise<void>;
4
+ down(queryRunner: QueryRunner): Promise<void>;
5
+ }
@@ -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, accessToken?: string): Promise<void>;
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, accessToken) {
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":"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"}
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 scope;
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?: number, calendarId?: string): Promise<TokenResponse>;
34
- renewWebhookSubscription(subscriptionId: string, accessToken: string, refreshToken: string): Promise<Subscription>;
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 && config.redirectPath.startsWith('http')) {
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
- const encodedScope = encodeURIComponent(this.scope);
129
- this.logger.log(`Redirect URI (raw): ${this.redirectUri}`);
130
- this.logger.log(`Redirect URI (encoded): ${encodedRedirectUri}`);
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 || !stateData.userId) {
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: this.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 Promise.resolve(this.eventEmitter.emit(event_types_enum_1.OutlookEventTypes.AUTH_TOKENS_SAVE, stateData.userId, tokenData));
173
- const userId = Number(stateData.userId);
174
- const accessToken = tokenData.access_token;
175
- const refreshToken = tokenData.refresh_token;
176
- await this.setupSubscriptions(userId, accessToken, refreshToken);
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, accessToken, refreshToken) {
185
- if (this.subscriptionInProgress.get(userId)) {
186
- this.logger.log(`Subscription setup already in progress for user ${String(userId)}`);
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(userId, true);
191
- try {
192
- await this.calendarService.createWebhookSubscription(userId, accessToken, refreshToken);
193
- this.logger.log(`Successfully created calendar webhook subscription for user ${String(userId)}`);
194
- }
195
- catch (calendarError) {
196
- this.logger.error(`Failed to create calendar webhook subscription: ${calendarError instanceof Error ? calendarError.message : 'Unknown error'}`);
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
- try {
199
- await this.emailService.createWebhookSubscription(userId, accessToken, refreshToken);
200
- this.logger.log(`Successfully created email webhook subscription for user ${String(userId)}`);
201
- }
202
- catch (emailError) {
203
- this.logger.error(`Failed to create email webhook subscription: ${emailError instanceof Error ? emailError.message : 'Unknown error'}`);
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(userId, false);
325
+ this.subscriptionInProgress.set(userIdNum, false);
211
326
  }
212
327
  }
213
- async refreshAccessToken(refreshToken, userId, calendarId) {
328
+ async refreshAccessToken(refreshToken, userId) {
214
329
  try {
215
- const payload = {
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: this.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
- if (!response.data.access_token || !response.data.expires_in) {
228
- throw new Error('Invalid token refresh response from Microsoft');
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
- const newRefreshToken = response.data.refresh_token || refreshToken;
231
- const tokenData = {
232
- access_token: response.data.access_token,
233
- refresh_token: newRefreshToken,
234
- expires_in: response.data.expires_in,
235
- };
236
- if (userId !== undefined && calendarId) {
237
- const userIdStr = String(userId);
238
- const calendarIdStr = String(calendarId);
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('Error refreshing access token:', 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
- async renewWebhookSubscription(subscriptionId, accessToken, refreshToken) {
249
- var _a;
250
- try {
251
- return await this.calendarService.renewWebhookSubscription(subscriptionId, accessToken);
252
- }
253
- catch (error) {
254
- if (axios_1.default.isAxiosError(error) && ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 401) {
255
- this.logger.log('Access token expired during webhook renewal, refreshing token...');
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