@progalaxyelabs/ngx-stonescriptphp-client 1.15.0 → 1.16.1

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.
@@ -27,6 +27,12 @@ class MyEnvironmentModel {
27
27
  * @example { host: 'https://files.progalaxyelabs.com/api/' }
28
28
  */
29
29
  filesServer;
30
+ /**
31
+ * Chat service server configuration.
32
+ * Used by Angular portals to establish authenticated WebSocket connections.
33
+ * @example { host: 'wss://chat.progalaxyelabs.com' }
34
+ */
35
+ chatServer;
30
36
  /**
31
37
  * Authentication configuration.
32
38
  * @default { mode: 'cookie', refreshEndpoint: '/auth/refresh', useCsrf: true }
@@ -417,22 +423,48 @@ class StoneScriptPHPAuth {
417
423
  resolve({ success: false, message: 'Popup blocked. Please allow popups for this site.' });
418
424
  return;
419
425
  }
426
+ const cleanup = () => {
427
+ window.removeEventListener('message', messageHandler);
428
+ clearInterval(checkClosed);
429
+ if (popup && !popup.closed)
430
+ popup.close();
431
+ };
420
432
  const messageHandler = (event) => {
421
433
  if (event.origin !== new URL(accountsUrl).origin)
422
434
  return;
423
- if (event.data.type === 'oauth_success') {
424
- window.removeEventListener('message', messageHandler);
425
- popup.close();
435
+ if (event.data.type === 'oauth_new_identity') {
436
+ cleanup();
437
+ resolve({
438
+ success: true,
439
+ accessToken: event.data.access_token,
440
+ refreshToken: event.data.refresh_token,
441
+ isNewIdentity: true,
442
+ authMethod: event.data.auth_method,
443
+ oauthProvider: event.data.oauth_provider,
444
+ identity: event.data.identity,
445
+ });
446
+ }
447
+ else if (event.data.type === 'oauth_success') {
448
+ cleanup();
426
449
  const rawUser = event.data.user || this.resolveUser(event.data);
427
450
  resolve({
428
451
  success: true,
429
452
  accessToken: event.data.access_token,
430
- user: rawUser ? this.normalizeUser(rawUser) : undefined
453
+ refreshToken: event.data.refresh_token,
454
+ user: rawUser ? this.normalizeUser(rawUser) : undefined,
455
+ membership: event.data.membership,
456
+ });
457
+ }
458
+ else if (event.data.type === 'oauth_tenant_selection') {
459
+ cleanup();
460
+ resolve({
461
+ success: true,
462
+ accessToken: event.data.selection_token,
463
+ memberships: event.data.memberships,
431
464
  });
432
465
  }
433
466
  else if (event.data.type === 'oauth_error') {
434
- window.removeEventListener('message', messageHandler);
435
- popup.close();
467
+ cleanup();
436
468
  resolve({ success: false, message: event.data.message || 'OAuth login failed' });
437
469
  }
438
470
  };
@@ -609,6 +641,26 @@ class StoneScriptPHPAuth {
609
641
  }
610
642
  return response.json();
611
643
  }
644
+ async provisionTenant(storeName, countryCode, accessToken) {
645
+ const apiUrl = this.getPlatformApiUrl();
646
+ const response = await fetch(`${apiUrl}/auth/provision-tenant`, {
647
+ method: 'POST',
648
+ headers: {
649
+ 'Content-Type': 'application/json',
650
+ 'Authorization': `Bearer ${accessToken}`
651
+ },
652
+ credentials: 'include',
653
+ body: JSON.stringify({
654
+ store_name: storeName,
655
+ country_code: countryCode,
656
+ })
657
+ });
658
+ if (!response.ok) {
659
+ const errorData = await response.json();
660
+ throw new Error(errorData.message || 'Failed to provision tenant');
661
+ }
662
+ return response.json();
663
+ }
612
664
  async checkEmail(email) {
613
665
  try {
614
666
  const accountsUrl = this.getAccountsUrl();
@@ -1033,6 +1085,17 @@ class AuthService {
1033
1085
  throw new Error('checkOnboardingStatus not supported');
1034
1086
  return this.plugin.checkOnboardingStatus(identityId);
1035
1087
  }
1088
+ async provisionTenant(storeName, countryCode = 'IN') {
1089
+ if (!this.plugin.provisionTenant) {
1090
+ throw new Error('provisionTenant not supported by the configured auth plugin');
1091
+ }
1092
+ const result = await this.plugin.provisionTenant(storeName, countryCode, this.tokens.getAccessToken());
1093
+ if (result?.access_token) {
1094
+ this.tokens.setAccessToken(result.access_token);
1095
+ this.signinStatus.setSigninStatus(true);
1096
+ }
1097
+ return result;
1098
+ }
1036
1099
  async completeTenantOnboarding(countryCode, tenantName, serverName) {
1037
1100
  if (!this.plugin.completeTenantOnboarding)
1038
1101
  throw new Error('completeTenantOnboarding not supported');
@@ -1781,6 +1844,7 @@ class TenantLoginComponent {
1781
1844
  createTenantLinkAction = 'Create New Organization';
1782
1845
  // Outputs
1783
1846
  tenantSelected = new EventEmitter();
1847
+ needsOnboarding = new EventEmitter();
1784
1848
  createTenant = new EventEmitter();
1785
1849
  // Form Fields
1786
1850
  email = '';
@@ -1868,7 +1932,23 @@ class TenantLoginComponent {
1868
1932
  this.error = result.message || 'OAuth login failed';
1869
1933
  return;
1870
1934
  }
1871
- // Authentication successfulpass result so membership can be reused if present
1935
+ // New identityuser exists but has no tenant membership
1936
+ if (result.isNewIdentity && result.identity) {
1937
+ this.needsOnboarding.emit({
1938
+ auth_method: result.authMethod || 'oauth',
1939
+ oauth_provider: result.oauthProvider,
1940
+ is_new_identity: true,
1941
+ identity: result.identity,
1942
+ });
1943
+ return;
1944
+ }
1945
+ // Multi-tenant selection — user has multiple memberships
1946
+ if (result.memberships && result.memberships.length > 0) {
1947
+ this.memberships = result.memberships;
1948
+ this.showingTenantSelector = true;
1949
+ return;
1950
+ }
1951
+ // Standard success — pass result so membership can be reused if present
1872
1952
  await this.handlePostAuthFlow(result);
1873
1953
  }
1874
1954
  catch (err) {
@@ -1997,7 +2077,7 @@ class TenantLoginComponent {
1997
2077
  this.createTenant.emit();
1998
2078
  }
1999
2079
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TenantLoginComponent, deps: [{ token: AuthService }, { token: ProviderRegistryService }], target: i0.ɵɵFactoryTarget.Component });
2000
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: TenantLoginComponent, isStandalone: true, selector: "lib-tenant-login", inputs: { title: "title", providers: "providers", showTenantSelector: "showTenantSelector", autoSelectSingleTenant: "autoSelectSingleTenant", prefillEmail: "prefillEmail", allowTenantCreation: "allowTenantCreation", tenantSelectorTitle: "tenantSelectorTitle", tenantSelectorDescription: "tenantSelectorDescription", continueButtonText: "continueButtonText", registerLinkText: "registerLinkText", registerLinkAction: "registerLinkAction", createTenantLinkText: "createTenantLinkText", createTenantLinkAction: "createTenantLinkAction" }, outputs: { tenantSelected: "tenantSelected", createTenant: "createTenant" }, ngImport: i0, template: `
2080
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: TenantLoginComponent, isStandalone: true, selector: "lib-tenant-login", inputs: { title: "title", providers: "providers", showTenantSelector: "showTenantSelector", autoSelectSingleTenant: "autoSelectSingleTenant", prefillEmail: "prefillEmail", allowTenantCreation: "allowTenantCreation", tenantSelectorTitle: "tenantSelectorTitle", tenantSelectorDescription: "tenantSelectorDescription", continueButtonText: "continueButtonText", registerLinkText: "registerLinkText", registerLinkAction: "registerLinkAction", createTenantLinkText: "createTenantLinkText", createTenantLinkAction: "createTenantLinkAction" }, outputs: { tenantSelected: "tenantSelected", needsOnboarding: "needsOnboarding", createTenant: "createTenant" }, ngImport: i0, template: `
2001
2081
  <div class="tenant-login-dialog">
2002
2082
  @if (!showingTenantSelector) {
2003
2083
  <!-- Step 1: Authentication -->
@@ -2362,6 +2442,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
2362
2442
  type: Input
2363
2443
  }], tenantSelected: [{
2364
2444
  type: Output
2445
+ }], needsOnboarding: [{
2446
+ type: Output
2365
2447
  }], createTenant: [{
2366
2448
  type: Output
2367
2449
  }] } });
@@ -2812,7 +2894,7 @@ class AuthPageComponent {
2812
2894
  }
2813
2895
  </div>
2814
2896
  </div>
2815
- `, isInline: true, styles: [".auth-container{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px;background:linear-gradient(135deg,#667eea,#764ba2)}.auth-card{background:#fff;border-radius:12px;box-shadow:0 10px 40px #0000001a;padding:40px;width:100%;max-width:480px}.logo{display:block;max-width:200px;max-height:80px;margin:0 auto 24px}.app-name{margin:0 0 12px;font-size:28px;font-weight:600;text-align:center;color:#1a202c}.subtitle{margin:0 0 32px;font-size:16px;text-align:center;color:#718096}:host ::ng-deep .tenant-login-dialog,:host ::ng-deep .register-dialog{padding:0;max-width:none}:host ::ng-deep .login-title,:host ::ng-deep .register-title{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: TenantLoginComponent, selector: "lib-tenant-login", inputs: ["title", "providers", "showTenantSelector", "autoSelectSingleTenant", "prefillEmail", "allowTenantCreation", "tenantSelectorTitle", "tenantSelectorDescription", "continueButtonText", "registerLinkText", "registerLinkAction", "createTenantLinkText", "createTenantLinkAction"], outputs: ["tenantSelected", "createTenant"] }, { kind: "component", type: RegisterComponent, selector: "lib-register", outputs: ["navigateToLogin"] }] });
2897
+ `, isInline: true, styles: [".auth-container{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:20px;background:linear-gradient(135deg,#667eea,#764ba2)}.auth-card{background:#fff;border-radius:12px;box-shadow:0 10px 40px #0000001a;padding:40px;width:100%;max-width:480px}.logo{display:block;max-width:200px;max-height:80px;margin:0 auto 24px}.app-name{margin:0 0 12px;font-size:28px;font-weight:600;text-align:center;color:#1a202c}.subtitle{margin:0 0 32px;font-size:16px;text-align:center;color:#718096}:host ::ng-deep .tenant-login-dialog,:host ::ng-deep .register-dialog{padding:0;max-width:none}:host ::ng-deep .login-title,:host ::ng-deep .register-title{display:none}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: TenantLoginComponent, selector: "lib-tenant-login", inputs: ["title", "providers", "showTenantSelector", "autoSelectSingleTenant", "prefillEmail", "allowTenantCreation", "tenantSelectorTitle", "tenantSelectorDescription", "continueButtonText", "registerLinkText", "registerLinkAction", "createTenantLinkText", "createTenantLinkAction"], outputs: ["tenantSelected", "needsOnboarding", "createTenant"] }, { kind: "component", type: RegisterComponent, selector: "lib-register", outputs: ["navigateToLogin"] }] });
2816
2898
  }
2817
2899
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: AuthPageComponent, decorators: [{
2818
2900
  type: Component,
@@ -3867,7 +3949,7 @@ class TenantLoginDialogComponent {
3867
3949
  (createTenant)="onCreateTenant()">
3868
3950
  </lib-tenant-login>
3869
3951
  </div>
3870
- `, isInline: true, styles: [".dialog-wrapper{padding:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: TenantLoginComponent, selector: "lib-tenant-login", inputs: ["title", "providers", "showTenantSelector", "autoSelectSingleTenant", "prefillEmail", "allowTenantCreation", "tenantSelectorTitle", "tenantSelectorDescription", "continueButtonText", "registerLinkText", "registerLinkAction", "createTenantLinkText", "createTenantLinkAction"], outputs: ["tenantSelected", "createTenant"] }] });
3952
+ `, isInline: true, styles: [".dialog-wrapper{padding:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: TenantLoginComponent, selector: "lib-tenant-login", inputs: ["title", "providers", "showTenantSelector", "autoSelectSingleTenant", "prefillEmail", "allowTenantCreation", "tenantSelectorTitle", "tenantSelectorDescription", "continueButtonText", "registerLinkText", "registerLinkAction", "createTenantLinkText", "createTenantLinkAction"], outputs: ["tenantSelected", "needsOnboarding", "createTenant"] }] });
3871
3953
  }
3872
3954
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TenantLoginDialogComponent, decorators: [{
3873
3955
  type: Component,