Compare commits
4 Commits
981117629a
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6e96bd61a | ||
|
|
7925b45d76 | ||
|
|
d8dda59f4c | ||
|
|
541251f065 |
2
Client-Home/dist/bundle.js
vendored
2
Client-Home/dist/bundle.js
vendored
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@
|
||||
// - APP_URL: the URL that should open the *app* (direct entry / dashboard).
|
||||
// - REGISTRATION_URL: the URL to your external registration experience.
|
||||
//
|
||||
// Tip: keep these as full absolute URLs.
|
||||
// Tip: keep these as full absolute
|
||||
|
||||
export const APP_URL = 'https://adpclient.usimdev.com/';
|
||||
export const REGISTRATION_URL = 'https://adpregist.usimdev.com/';
|
||||
export const APP_URL = 'https://client.positivespend.com/';
|
||||
export const REGISTRATION_URL = 'https://register.positivespend.com/';
|
||||
|
||||
2
Client-Registration/dist/bundle.js
vendored
2
Client-Registration/dist/bundle.js
vendored
File diff suppressed because one or more lines are too long
@@ -41,12 +41,17 @@ export function useAuth() {
|
||||
|
||||
// ── Map ID token claims → user object ─────────────────────────────────────
|
||||
function claimsToUser(claims, provider) {
|
||||
const firstName = claims.given_name ?? null;
|
||||
const surname = claims.family_name ?? null;
|
||||
const displayName = claims.name
|
||||
?? [firstName, surname].filter(Boolean).join(' ')
|
||||
?? null;
|
||||
return {
|
||||
entraSubjectId: claims.oid ?? claims.sub ?? null,
|
||||
email: claims.email ?? claims.preferred_username ?? null,
|
||||
displayName: claims.name ?? null,
|
||||
firstName: claims.given_name ?? null,
|
||||
surname: claims.family_name ?? null,
|
||||
displayName,
|
||||
firstName,
|
||||
surname,
|
||||
provider: provider ?? 'unknown',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,12 +6,13 @@ export default function ContactStep() {
|
||||
const { user } = useAuth();
|
||||
const { contactData, setContactData, saveContact, goBack, loading, error } = useRegistration();
|
||||
|
||||
// Pre-fill from auth claims on mount
|
||||
// Pre-fill from CIAM claims on mount
|
||||
useEffect(() => {
|
||||
if (user) {
|
||||
setContactData(prev => ({
|
||||
contactName: prev.contactName || user.displayName || '',
|
||||
contactEmail: prev.contactEmail || user.email || '',
|
||||
firstName: prev.firstName || user.firstName || '',
|
||||
lastName: prev.lastName || user.surname || '',
|
||||
contactEmail: prev.contactEmail || user.email || '',
|
||||
contactPhone: prev.contactPhone || '',
|
||||
}));
|
||||
}
|
||||
@@ -39,7 +40,9 @@ export default function ContactStep() {
|
||||
|
||||
{user && (
|
||||
<div className="info-card">
|
||||
<div className="info-card-primary">{user.displayName}</div>
|
||||
<div className="info-card-primary">
|
||||
{[user.firstName, user.surname].filter(Boolean).join(' ') || user.displayName || user.email}
|
||||
</div>
|
||||
<div className="info-card-secondary">{user.email}</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -47,17 +50,32 @@ export default function ContactStep() {
|
||||
{error && <div className="error-message">{error}</div>}
|
||||
|
||||
<form onSubmit={handleSubmit}>
|
||||
<div className="form-group">
|
||||
<label htmlFor="contactName">Full Name <span className="required">*</span></label>
|
||||
<input
|
||||
type="text"
|
||||
id="contactName"
|
||||
name="contactName"
|
||||
value={contactData.contactName}
|
||||
onChange={handleChange}
|
||||
placeholder="Jane Smith"
|
||||
required
|
||||
/>
|
||||
<div className="form-row">
|
||||
<div className="form-group">
|
||||
<label htmlFor="firstName">First Name <span className="required">*</span></label>
|
||||
<input
|
||||
type="text"
|
||||
id="firstName"
|
||||
name="firstName"
|
||||
value={contactData.firstName || ''}
|
||||
onChange={handleChange}
|
||||
placeholder="Jane"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
<label htmlFor="lastName">Last Name <span className="required">*</span></label>
|
||||
<input
|
||||
type="text"
|
||||
id="lastName"
|
||||
name="lastName"
|
||||
value={contactData.lastName || ''}
|
||||
onChange={handleChange}
|
||||
placeholder="Smith"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="form-group">
|
||||
@@ -66,7 +84,7 @@ export default function ContactStep() {
|
||||
type="email"
|
||||
id="contactEmail"
|
||||
name="contactEmail"
|
||||
value={contactData.contactEmail}
|
||||
value={contactData.contactEmail || ''}
|
||||
onChange={handleChange}
|
||||
placeholder="jane@example.com"
|
||||
required
|
||||
@@ -79,7 +97,7 @@ export default function ContactStep() {
|
||||
type="tel"
|
||||
id="contactPhone"
|
||||
name="contactPhone"
|
||||
value={contactData.contactPhone}
|
||||
value={contactData.contactPhone || ''}
|
||||
onChange={handleChange}
|
||||
placeholder="(555) 123-4567"
|
||||
/>
|
||||
|
||||
@@ -53,7 +53,8 @@ export function RegistrationProvider({ children }) {
|
||||
|
||||
// Form data — maps to RegisterRequest model fields (minus entraSubjectId)
|
||||
const [contactData, setContactData] = useState({
|
||||
contactName: '',
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
contactEmail: '',
|
||||
contactPhone: '',
|
||||
});
|
||||
@@ -83,8 +84,9 @@ export function RegistrationProvider({ children }) {
|
||||
// ─── Validation ─────────────────────────────────────────────────────
|
||||
|
||||
const validateContact = useCallback(() => {
|
||||
if (!contactData.contactName.trim()) return 'Contact name is required';
|
||||
if (!contactData.contactEmail.trim()) return 'Email is required';
|
||||
if (!contactData.firstName?.trim()) return 'First name is required';
|
||||
if (!contactData.lastName?.trim()) return 'Last name is required';
|
||||
if (!contactData.contactEmail?.trim()) return 'Email is required';
|
||||
return null;
|
||||
}, [contactData]);
|
||||
|
||||
@@ -132,6 +134,8 @@ export function RegistrationProvider({ children }) {
|
||||
const request = {
|
||||
...contactData,
|
||||
...businessData,
|
||||
// Combine for server-side contactName field
|
||||
contactName: [contactData.firstName, contactData.lastName].filter(Boolean).join(' '),
|
||||
};
|
||||
|
||||
// Pre-fill email from auth if the user left it blank
|
||||
|
||||
@@ -326,6 +326,16 @@ body {
|
||||
Forms
|
||||
============================================================ */
|
||||
|
||||
.form-row {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.form-row .form-group {
|
||||
flex: 1;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-group {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
2
Client-Tech/dist/bundle.js
vendored
2
Client-Tech/dist/bundle.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,30 +1,17 @@
|
||||
/**
|
||||
* authConfig.js — Tech Client (Staff Plane)
|
||||
*
|
||||
* ┌─────────────────────────────────────────────────────────────────────────┐
|
||||
* │ PRODUCTION MIGRATION — only these values change at handoff: │
|
||||
* │ │
|
||||
* │ STAFF_AUTHORITY → 'https://login.microsoftonline.com/{ORG_TENANT}' │
|
||||
* │ STAFF_TENANT_ID → new company org tenant ID │
|
||||
* │ STAFF_CLIENT_ID → staff app registration in org tenant │
|
||||
* │ │
|
||||
* │ No other code changes required anywhere. │
|
||||
* └─────────────────────────────────────────────────────────────────────────┘
|
||||
*
|
||||
* DEV NOTE: Staff currently authenticate against the CIAM tenant (same as
|
||||
* clients) because no org tenant exists yet. The login screen looks identical
|
||||
* to the client login — this is cosmetic only. API isolation is enforced by
|
||||
* audience: staff tokens are rejected by Gateway, client tokens by Management.
|
||||
*/
|
||||
|
||||
// ── Staff Identity Config ─────────────────────────────────────────────────────
|
||||
|
||||
const STAFF_TENANT_ID = 'f56a3c51-9b5c-4356-920f-b4dcf932a96b';
|
||||
const STAFF_CLIENT_ID = '217928a9-4591-4dff-9f09-5b233824cf4f';
|
||||
const STAFF_TENANT_ID = 'f56a3c51-9b5c-4356-920f-b4dcf932a96b';
|
||||
const STAFF_CLIENT_ID = '217928a9-4591-4dff-9f09-5b233824cf4f';
|
||||
|
||||
// PROD: swap to → 'https://login.microsoftonline.com/' + STAFF_TENANT_ID
|
||||
const STAFF_AUTHORITY = 'https://login.microsoftonline.com/' + STAFF_TENANT_ID;
|
||||
|
||||
// Management Staff API — resource the Tech SPA requests a token for
|
||||
const MGMT_APP_ID = 'af95fa13-2ef4-4911-b137-7acc6a784cfa';
|
||||
|
||||
// ── MSAL Config ───────────────────────────────────────────────────────────────
|
||||
|
||||
export const msalConfig = {
|
||||
@@ -33,10 +20,10 @@ export const msalConfig = {
|
||||
authority: STAFF_AUTHORITY,
|
||||
redirectUri: window.location.origin,
|
||||
postLogoutRedirectUri: window.location.origin,
|
||||
navigateToLoginRequestUrl: true,
|
||||
navigateToLoginRequestUrl: false, // ← was true, caused the loop
|
||||
},
|
||||
cache: {
|
||||
cacheLocation: 'sessionStorage',
|
||||
cacheLocation: 'sessionStorage',
|
||||
storeAuthStateInCookie: false,
|
||||
},
|
||||
system: {
|
||||
@@ -50,19 +37,18 @@ export const msalConfig = {
|
||||
case 3: console.debug(message); break;
|
||||
}
|
||||
},
|
||||
logLevel: 3,
|
||||
logLevel: 1, // warn + error only in prod
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const loginRequest = {
|
||||
scopes: ["api://4e4d69c3-558a-4a27-a689-17bd397175e5/access_as_user"]
|
||||
scopes: [`api://${MGMT_APP_ID}/access_as_user`] // ← fixed
|
||||
};
|
||||
|
||||
// ── API Endpoints ─────────────────────────────────────────────────────────────
|
||||
|
||||
export const API_BASE = 'https://adpapi.usimdev.com'; // Gateway API
|
||||
export const MGMT_BASE = 'https://adpmgmt.usimdev.com'; // Management API
|
||||
export const API_BASE = 'https://portal.positivespend.com'; // ← fixed
|
||||
export const MGMT_BASE = 'https://mgmt.positivespend.com'; // ← fixed
|
||||
|
||||
// Legacy — kept for backward compatibility with apiClient.js
|
||||
export const SESSION_ENDPOINT = `${API_BASE}/api/auth/session`;
|
||||
export const SESSION_ENDPOINT = `${API_BASE}/api/auth/session`;
|
||||
Reference in New Issue
Block a user