@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 === '
|
|
424
|
-
|
|
425
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
1935
|
+
// New identity — user 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,
|