@powerportalspro/react 6.1.0 → 7.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/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { ChangeEvent, ReactNode } from 'react';
3
- import { components, TableMetadata as TableMetadata$1, ViewMetadata, CurrentUserInfo, Transport, AuthClient, PowerPortalsProClient, LoginRequest, LoginResponse, SwitchIdentityResponse, PowerPortalsProError, TableRecord, RetrieveRecordsResponse, GridDataRequest, GridDataResponse, GridFilterBase, ChartAggregation, ColumnSort, ResolvedColumn, TableSecurityPermission, ChartData, OrganizationRequest } from '@powerportalspro/core';
3
+ import { components, TableMetadata as TableMetadata$1, ViewMetadata, CurrentUserInfo, Transport, AuthClient, PowerPortalsProClient, LoginRequest, LoginResponse, SwitchIdentityResponse, ImpersonateResponse, StopImpersonationResponse, ImpersonationSearchResponse, PowerPortalsProError, TableRecord, RetrieveRecordsResponse, GridDataRequest, GridDataResponse, GridFilterBase, ChartAggregation, ColumnSort, ResolvedColumn, TableSecurityPermission, ChartData, OrganizationRequest } from '@powerportalspro/core';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
 
6
6
  /**
@@ -343,6 +343,29 @@ interface PowerPortalsProContextValue {
343
343
  * alt id is read from the cookie's claims server-side.
344
344
  */
345
345
  readonly switchIdentity: () => Promise<SwitchIdentityResponse>;
346
+ /**
347
+ * Starts impersonating a portal contact, swapping the auth cookie for theirs. Permitted
348
+ * server-side only for internal users holding the `SystemAdmin` role, and only ever resolves a
349
+ * contact — so it can never be used to assume another staff identity.
350
+ *
351
+ * On `ImpersonateResult.Started` the auth state is refreshed from `/api/auth/me` and now
352
+ * describes the CONTACT: `user.userId`, `user.roles` and `user.portalUserType` are theirs, with
353
+ * `user.isImpersonating` and `user.impersonatorName` the only trace of who is behind it. Other
354
+ * outcomes leave the state untouched so the caller can surface a message.
355
+ */
356
+ readonly impersonate: (targetUserId: string) => Promise<ImpersonateResponse>;
357
+ /**
358
+ * Ends an impersonation session and restores the internal user. Takes no parameters — the
359
+ * identity to return to is read from the session's claims server-side. On
360
+ * `StopImpersonationResult.Stopped` the auth state is refreshed.
361
+ */
362
+ readonly stopImpersonation: () => Promise<StopImpersonationResponse>;
363
+ /**
364
+ * Searches contacts the current user may impersonate. Returns an empty result — never an
365
+ * error — when the caller isn't permitted to impersonate or the query is under three
366
+ * characters, so a picker can render "no matches" without branching on why.
367
+ */
368
+ readonly searchImpersonationTargets: (query: string) => Promise<ImpersonationSearchResponse>;
346
369
  }
347
370
  declare const PowerPortalsProContext: react.Context<PowerPortalsProContextValue | null>;
348
371
 
@@ -482,6 +505,27 @@ type UseAuthResult = AuthState & {
482
505
  * On `Switched`, the in-memory auth state is refreshed automatically.
483
506
  */
484
507
  switchIdentity: () => Promise<SwitchIdentityResponse>;
508
+ /**
509
+ * Starts impersonating a portal contact. Allowed server-side only for internal users holding
510
+ * the `SystemAdmin` role, and only ever resolves a contact — never another staff account.
511
+ *
512
+ * On `ImpersonateResult.Started` the auth state refreshes and `auth.user` becomes the CONTACT:
513
+ * their id, their roles, their user type. `auth.user.isImpersonating` and
514
+ * `auth.user.impersonatorName` are the only fields that say otherwise, which is what makes the
515
+ * impersonated session an honest rehearsal of what that contact actually sees.
516
+ */
517
+ impersonate: (targetUserId: string) => Promise<ImpersonateResponse>;
518
+ /**
519
+ * Ends an impersonation session and restores the internal user. Takes no parameters — the
520
+ * identity to return to comes from the session's own claims, so the client can't pick it.
521
+ */
522
+ stopImpersonation: () => Promise<StopImpersonationResponse>;
523
+ /**
524
+ * Searches contacts the current user may impersonate — by name, email, or exact user id.
525
+ * Returns an empty result rather than an error when the caller isn't permitted or the query is
526
+ * too short, so a picker renders "no matches" without branching on why.
527
+ */
528
+ searchImpersonationTargets: (query: string) => Promise<ImpersonationSearchResponse>;
485
529
  };
486
530
  declare function useAuth(): UseAuthResult;
487
531
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import { ChangeEvent, ReactNode } from 'react';
3
- import { components, TableMetadata as TableMetadata$1, ViewMetadata, CurrentUserInfo, Transport, AuthClient, PowerPortalsProClient, LoginRequest, LoginResponse, SwitchIdentityResponse, PowerPortalsProError, TableRecord, RetrieveRecordsResponse, GridDataRequest, GridDataResponse, GridFilterBase, ChartAggregation, ColumnSort, ResolvedColumn, TableSecurityPermission, ChartData, OrganizationRequest } from '@powerportalspro/core';
3
+ import { components, TableMetadata as TableMetadata$1, ViewMetadata, CurrentUserInfo, Transport, AuthClient, PowerPortalsProClient, LoginRequest, LoginResponse, SwitchIdentityResponse, ImpersonateResponse, StopImpersonationResponse, ImpersonationSearchResponse, PowerPortalsProError, TableRecord, RetrieveRecordsResponse, GridDataRequest, GridDataResponse, GridFilterBase, ChartAggregation, ColumnSort, ResolvedColumn, TableSecurityPermission, ChartData, OrganizationRequest } from '@powerportalspro/core';
4
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
5
5
 
6
6
  /**
@@ -343,6 +343,29 @@ interface PowerPortalsProContextValue {
343
343
  * alt id is read from the cookie's claims server-side.
344
344
  */
345
345
  readonly switchIdentity: () => Promise<SwitchIdentityResponse>;
346
+ /**
347
+ * Starts impersonating a portal contact, swapping the auth cookie for theirs. Permitted
348
+ * server-side only for internal users holding the `SystemAdmin` role, and only ever resolves a
349
+ * contact — so it can never be used to assume another staff identity.
350
+ *
351
+ * On `ImpersonateResult.Started` the auth state is refreshed from `/api/auth/me` and now
352
+ * describes the CONTACT: `user.userId`, `user.roles` and `user.portalUserType` are theirs, with
353
+ * `user.isImpersonating` and `user.impersonatorName` the only trace of who is behind it. Other
354
+ * outcomes leave the state untouched so the caller can surface a message.
355
+ */
356
+ readonly impersonate: (targetUserId: string) => Promise<ImpersonateResponse>;
357
+ /**
358
+ * Ends an impersonation session and restores the internal user. Takes no parameters — the
359
+ * identity to return to is read from the session's claims server-side. On
360
+ * `StopImpersonationResult.Stopped` the auth state is refreshed.
361
+ */
362
+ readonly stopImpersonation: () => Promise<StopImpersonationResponse>;
363
+ /**
364
+ * Searches contacts the current user may impersonate. Returns an empty result — never an
365
+ * error — when the caller isn't permitted to impersonate or the query is under three
366
+ * characters, so a picker can render "no matches" without branching on why.
367
+ */
368
+ readonly searchImpersonationTargets: (query: string) => Promise<ImpersonationSearchResponse>;
346
369
  }
347
370
  declare const PowerPortalsProContext: react.Context<PowerPortalsProContextValue | null>;
348
371
 
@@ -482,6 +505,27 @@ type UseAuthResult = AuthState & {
482
505
  * On `Switched`, the in-memory auth state is refreshed automatically.
483
506
  */
484
507
  switchIdentity: () => Promise<SwitchIdentityResponse>;
508
+ /**
509
+ * Starts impersonating a portal contact. Allowed server-side only for internal users holding
510
+ * the `SystemAdmin` role, and only ever resolves a contact — never another staff account.
511
+ *
512
+ * On `ImpersonateResult.Started` the auth state refreshes and `auth.user` becomes the CONTACT:
513
+ * their id, their roles, their user type. `auth.user.isImpersonating` and
514
+ * `auth.user.impersonatorName` are the only fields that say otherwise, which is what makes the
515
+ * impersonated session an honest rehearsal of what that contact actually sees.
516
+ */
517
+ impersonate: (targetUserId: string) => Promise<ImpersonateResponse>;
518
+ /**
519
+ * Ends an impersonation session and restores the internal user. Takes no parameters — the
520
+ * identity to return to comes from the session's own claims, so the client can't pick it.
521
+ */
522
+ stopImpersonation: () => Promise<StopImpersonationResponse>;
523
+ /**
524
+ * Searches contacts the current user may impersonate — by name, email, or exact user id.
525
+ * Returns an empty result rather than an error when the caller isn't permitted or the query is
526
+ * too short, so a picker renders "no matches" without branching on why.
527
+ */
528
+ searchImpersonationTargets: (query: string) => Promise<ImpersonationSearchResponse>;
485
529
  };
486
530
  declare function useAuth(): UseAuthResult;
487
531
 
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createContext, useRef, useState, useEffect, useLayoutEffect, useCallback, useContext, useMemo, useSyncExternalStore, useReducer, useId } from 'react';
2
- import { Transport, AuthClient, PowerPortalsProClient, LoginResult, SwitchIdentityResult } from '@powerportalspro/core';
2
+ import { Transport, AuthClient, PowerPortalsProClient, LoginResult, SwitchIdentityResult, ImpersonateResult, StopImpersonationResult } from '@powerportalspro/core';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
 
5
5
  // src/masking/reformat.ts
@@ -1057,6 +1057,24 @@ function PowerPortalsProProvider({
1057
1057
  }
1058
1058
  return response;
1059
1059
  }, [auth, refreshAuth]);
1060
+ const impersonate = useCallback(async (targetUserId) => {
1061
+ const response = await auth.impersonateAsync(targetUserId);
1062
+ if (response.result === ImpersonateResult.Started) {
1063
+ await refreshAuth();
1064
+ }
1065
+ return response;
1066
+ }, [auth, refreshAuth]);
1067
+ const stopImpersonation = useCallback(async () => {
1068
+ const response = await auth.stopImpersonationAsync();
1069
+ if (response.result === StopImpersonationResult.Stopped || response.result === StopImpersonationResult.ImpersonatorNotFound) {
1070
+ await refreshAuth();
1071
+ }
1072
+ return response;
1073
+ }, [auth, refreshAuth]);
1074
+ const searchImpersonationTargets = useCallback(
1075
+ (query) => auth.searchImpersonationTargetsAsync(query),
1076
+ [auth]
1077
+ );
1060
1078
  useEffect(() => {
1061
1079
  refreshAuth();
1062
1080
  }, [refreshAuth]);
@@ -1073,7 +1091,10 @@ function PowerPortalsProProvider({
1073
1091
  refreshAuth,
1074
1092
  login,
1075
1093
  logout,
1076
- switchIdentity
1094
+ switchIdentity,
1095
+ impersonate,
1096
+ stopImpersonation,
1097
+ searchImpersonationTargets
1077
1098
  }),
1078
1099
  [
1079
1100
  transportInstance,
@@ -1087,7 +1108,10 @@ function PowerPortalsProProvider({
1087
1108
  refreshAuth,
1088
1109
  login,
1089
1110
  logout,
1090
- switchIdentity
1111
+ switchIdentity,
1112
+ impersonate,
1113
+ stopImpersonation,
1114
+ searchImpersonationTargets
1091
1115
  ]
1092
1116
  );
1093
1117
  let localizationContent;
@@ -1141,13 +1165,25 @@ function CacheLocaleSync() {
1141
1165
 
1142
1166
  // src/use-auth.ts
1143
1167
  function useAuth() {
1144
- const { authState, refreshAuth, login, logout, switchIdentity } = usePowerPortalsPro();
1168
+ const {
1169
+ authState,
1170
+ refreshAuth,
1171
+ login,
1172
+ logout,
1173
+ switchIdentity,
1174
+ impersonate,
1175
+ stopImpersonation,
1176
+ searchImpersonationTargets
1177
+ } = usePowerPortalsPro();
1145
1178
  return {
1146
1179
  ...authState,
1147
1180
  refresh: refreshAuth,
1148
1181
  login,
1149
1182
  logout,
1150
- switchIdentity
1183
+ switchIdentity,
1184
+ impersonate,
1185
+ stopImpersonation,
1186
+ searchImpersonationTargets
1151
1187
  };
1152
1188
  }
1153
1189
  function AuthorizedView({ children, roles, fallback = null }) {