User profile controls that hide non-sales features from users outside sales
This commit is contained in:
43
dist/chromium/background.js
vendored
43
dist/chromium/background.js
vendored
@@ -14,6 +14,7 @@ function createMessageTypes() {
|
||||
requestInstallBase: "opportunitiesExtension.requestInstallBase",
|
||||
requestCustomerServiceRequest: "opportunitiesExtension.requestCustomerServiceRequest",
|
||||
requestWlActions: "opportunitiesExtension.requestWlActions",
|
||||
requestCurrentUser: "opportunitiesExtension.requestCurrentUser",
|
||||
requestConsumptionTrend: "opportunitiesExtension.requestConsumptionTrend",
|
||||
requestConsumptionPlanDetail: "opportunitiesExtension.requestConsumptionPlanDetail",
|
||||
requestRatecardByPlan: "opportunitiesExtension.requestRatecardByPlan"
|
||||
@@ -643,6 +644,35 @@ function createSpaWorkloadActions({ fetchJson }) {
|
||||
return { requestWlActions };
|
||||
}
|
||||
|
||||
// Source: src/services/spa/current-user.js
|
||||
function createSpaCurrentUser({ fetchJson }) {
|
||||
async function requestCurrentUser() {
|
||||
const debugRequests = [];
|
||||
let user = null;
|
||||
try {
|
||||
const result = await fetchJson("https://spa.oracle.com/oalcrm/web/api/identity-management/users/current", {
|
||||
method: "GET", credentials: "include", cache: "no-store", headers: { Accept: "application/json" }
|
||||
}, "requestCurrentUser", debugRequests);
|
||||
if (!result?.user || !Array.isArray(result.user.roles) || result.user.roles.some(role => typeof role !== "string")) {
|
||||
throw new Error("requestCurrentUser returned invalid user roles.");
|
||||
}
|
||||
user = { id: result.user.id, name: result.user.name, roles: result.user.roles };
|
||||
return { ok: true, user, debugRequests };
|
||||
} catch (error) {
|
||||
for (const entry of debugRequests) { entry.status = "failed"; entry.error = error.message; }
|
||||
error.debugRequests = debugRequests;
|
||||
throw error;
|
||||
} finally {
|
||||
// The identity token is not needed by content scripts or debug, including on failures.
|
||||
for (const entry of debugRequests) {
|
||||
entry.responseBody = JSON.stringify(user ? { user, token: "(redacted)" } : { error: "Identity response omitted." }, null, 2);
|
||||
entry.responseBodyTruncated = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return { requestCurrentUser };
|
||||
}
|
||||
|
||||
// Source: src/services/spa/consumption.js
|
||||
function createSpaConsumption({
|
||||
CONSUMPTION_TREND_REQUESTS,
|
||||
@@ -1696,6 +1726,7 @@ function registerBackgroundMessages({
|
||||
requestInstallBase,
|
||||
requestCustomerServiceRequest,
|
||||
requestWlActions,
|
||||
requestCurrentUser,
|
||||
requestConsumerTokenService,
|
||||
requestConsumptionTrend,
|
||||
requestConsumptionPlanDetail,
|
||||
@@ -1777,6 +1808,14 @@ runtimeApi.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (message.type === messageTypes.requestCurrentUser) {
|
||||
requestCurrentUser().then(sendResponse).catch(error => sendResponse({
|
||||
ok: false, error: error.message || "Unable to load current user.",
|
||||
debugRequests: Array.isArray(error.debugRequests) ? error.debugRequests : []
|
||||
}));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (message.type === messageTypes.requestWlActions) {
|
||||
requestWlActions(message).then(sendResponse).catch(error => sendResponse({
|
||||
ok: false, error: error.message || "Unable to load workload actions.",
|
||||
@@ -1859,6 +1898,8 @@ function createBackgroundApplication(overrides = {}) {
|
||||
...overrides
|
||||
};
|
||||
const messageTypes = createMessageTypes();
|
||||
const spaCurrentUser = createSpaCurrentUser({ fetchJson: (...args) => httpBackgroundJson.fetchJson(...args) });
|
||||
const requestCurrentUser = () => spaCurrentUser.requestCurrentUser();
|
||||
const contracts = createBackgroundContracts();
|
||||
const productsCacheState = createProductsCacheState();
|
||||
const authConsumerSession = createAuthConsumerSession({
|
||||
@@ -1973,7 +2014,7 @@ function createBackgroundApplication(overrides = {}) {
|
||||
const requestOpptyProducts = (...args) => productsBackgroundJobs.requestOpptyProducts(...args);
|
||||
const runtimeApi = environment.browser || environment.chrome;
|
||||
function start() {
|
||||
startBackgroundApplication({ messageTypes, getXsrfTokenCookie, refreshXsrfCookie, requestAccountPlans, requestInstallBase, requestCustomerServiceRequest, requestWlActions, requestConsumerTokenService, requestConsumptionTrend, requestConsumptionPlanDetail, requestRatecardByPlan, requestOpptyProducts, runtimeApi });
|
||||
startBackgroundApplication({ messageTypes, requestCurrentUser, getXsrfTokenCookie, refreshXsrfCookie, requestAccountPlans, requestInstallBase, requestCustomerServiceRequest, requestWlActions, requestConsumerTokenService, requestConsumptionTrend, requestConsumptionPlanDetail, requestRatecardByPlan, requestOpptyProducts, runtimeApi });
|
||||
}
|
||||
return {
|
||||
start, contracts,
|
||||
|
||||
61
dist/chromium/content.js
vendored
61
dist/chromium/content.js
vendored
@@ -15,6 +15,7 @@ function createMessageTypes() {
|
||||
requestInstallBase: "opportunitiesExtension.requestInstallBase",
|
||||
requestCustomerServiceRequest: "opportunitiesExtension.requestCustomerServiceRequest",
|
||||
requestWlActions: "opportunitiesExtension.requestWlActions",
|
||||
requestCurrentUser: "opportunitiesExtension.requestCurrentUser",
|
||||
requestConsumptionTrend: "opportunitiesExtension.requestConsumptionTrend",
|
||||
requestConsumptionPlanDetail: "opportunitiesExtension.requestConsumptionPlanDetail",
|
||||
requestRatecardByPlan: "opportunitiesExtension.requestRatecardByPlan"
|
||||
@@ -470,6 +471,7 @@ function createContentModal({
|
||||
resetWorkloadActions,
|
||||
reopenWorkloadActions,
|
||||
requestTokenRelayOnce,
|
||||
ensureCurrentUser,
|
||||
resetCustomerAndOwnerFiltersForPeriod,
|
||||
resetOpportunitiesTable,
|
||||
restoreFilterPreferences,
|
||||
@@ -496,11 +498,16 @@ function createContentModal({
|
||||
|
||||
if (existingModal) {
|
||||
existingModal.hidden = false;
|
||||
reopenWorkloadActions();
|
||||
existingModal.querySelector("select").focus();
|
||||
document.documentElement.classList.add("opportunities-extension-scroll-lock");
|
||||
ensureEscapeKeyHandler();
|
||||
requestTokenRelayOnce().then(token => loadCrmServiceRequests(token, opportunitiesQueryState.periodRequestVersion))
|
||||
ensureCurrentUser().then(() => {
|
||||
if (existingModal.hidden) return;
|
||||
reopenWorkloadActions();
|
||||
return requestTokenRelayOnce().then(token => {
|
||||
if (!existingModal.hidden) return loadCrmServiceRequests(token, opportunitiesQueryState.periodRequestVersion);
|
||||
});
|
||||
})
|
||||
.then(() => renderOpportunitiesTable()).catch(() => {});
|
||||
return;
|
||||
}
|
||||
@@ -1186,6 +1193,25 @@ function createAuthContentSession({
|
||||
return { requestTokenRelayOnce, requestConsumerTokenServiceOnce };
|
||||
}
|
||||
|
||||
// Source: src/auth/current-user.js
|
||||
function createCurrentUser({ sendRuntimeMessage, appendBackgroundRequestLog, messageTypes }) {
|
||||
let pending = null;
|
||||
let allowed = false;
|
||||
function ensure() {
|
||||
if (!pending) {
|
||||
pending = sendRuntimeMessage({ type: messageTypes.requestCurrentUser }).then(response => {
|
||||
appendBackgroundRequestLog(response?.debugRequests);
|
||||
const roles = response?.user?.roles;
|
||||
allowed = response?.ok === true && Array.isArray(roles)
|
||||
&& roles.every(role => typeof role === "string") && !roles.includes("SALES_REP");
|
||||
return allowed;
|
||||
}).catch(() => { allowed = false; return false; });
|
||||
}
|
||||
return pending;
|
||||
}
|
||||
return { ensure, allowsCrmActivities: () => allowed };
|
||||
}
|
||||
|
||||
// Source: src/auth/sales-common.js
|
||||
function createAuthSalesCommon({
|
||||
TOKEN_RELAY_URL,
|
||||
@@ -1568,11 +1594,14 @@ function createOpportunitiesController({
|
||||
resetWorkloadActions,
|
||||
requestOpptyProductsInBackground,
|
||||
requestTokenRelayOnce,
|
||||
ensureCurrentUser,
|
||||
setOpportunitiesTableState
|
||||
}) {
|
||||
async function requestOpportunitiesForPeriod(period) {
|
||||
const dateRange = getFiscalPeriodRange(period, new Date());
|
||||
const requestVersion = ++opportunitiesQueryState.periodRequestVersion;
|
||||
await ensureCurrentUser();
|
||||
if (!isCurrentPeriodRequest(requestVersion)) return;
|
||||
|
||||
if (preferencesState.selectedOpportunityTypeValues.size === 0) {
|
||||
setOpportunitiesTableState({
|
||||
@@ -1933,14 +1962,14 @@ function createFusionCrmServiceRequests({ isCurrentPeriodRequest,
|
||||
}
|
||||
|
||||
// Source: src/features/opportunities/crm-service-requests.js
|
||||
function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurrentPeriodRequest, bindPopover, closePopover, environment }) {
|
||||
function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurrentPeriodRequest, bindPopover, closePopover, allowsCrmActivities, environment }) {
|
||||
let status = "idle";
|
||||
let byOpportunity = new Map();
|
||||
let pending = null;
|
||||
let generation = 0;
|
||||
function reset() { closePopover(); generation += 1; pending = null; status = "idle"; byOpportunity = new Map(); }
|
||||
function load(token, version) {
|
||||
if (!isCurrentPeriodRequest(version)) return;
|
||||
if (!allowsCrmActivities() || !isCurrentPeriodRequest(version)) return;
|
||||
if (!pending) pending = run(token, version, generation);
|
||||
return pending;
|
||||
}
|
||||
@@ -1965,7 +1994,7 @@ function createOpportunityCrmServiceRequests({ requestCrmServiceRequest, isCurre
|
||||
}
|
||||
}
|
||||
function createBadge(optyNumber) {
|
||||
if (!optyNumber || status === "idle" || status === "loading") return null;
|
||||
if (!allowsCrmActivities() || !optyNumber || status === "idle" || status === "loading") return null;
|
||||
const items = byOpportunity.get(String(optyNumber)) || [];
|
||||
const badge = environment.document.createElement(items.length && status === "ready" ? "button" : "span");
|
||||
badge.className = "opportunities-extension-crm-sr-badge";
|
||||
@@ -2123,7 +2152,7 @@ function createCrmSrPopover({ MODAL_ID, createCopyButton, createCloseIcon, envir
|
||||
}
|
||||
|
||||
// Source: src/features/opportunities/workload-actions.js
|
||||
function createOpportunityWorkloadActions({ authSessionState, requestConsumerTokenServiceOnce, sendRuntimeMessage,
|
||||
function createOpportunityWorkloadActions({ authSessionState, allowsCrmActivities, requestConsumerTokenServiceOnce, sendRuntimeMessage,
|
||||
appendBackgroundRequestLog, queueProductsTableRender, productsContentState, messageTypes, environment }) {
|
||||
let session = newSession();
|
||||
function newSession() { return { enabled: true, records: new Map(), queue: [], running: 0 }; }
|
||||
@@ -2137,7 +2166,7 @@ function createOpportunityWorkloadActions({ authSessionState, requestConsumerTok
|
||||
return [...new Set((products?.items || []).map(item => String(item?.RevnId ?? "").trim()).filter(Boolean))];
|
||||
}
|
||||
function loadProducts(products) {
|
||||
if (!session.enabled) return;
|
||||
if (!session.enabled || !allowsCrmActivities()) return;
|
||||
for (const revnId of idsFor(products)) {
|
||||
if (session.records.has(revnId)) continue;
|
||||
const record = { status: "loading", actions: [], hasNext: false };
|
||||
@@ -2161,9 +2190,9 @@ function createOpportunityWorkloadActions({ authSessionState, requestConsumerTok
|
||||
async function run(current, { revnId, record }) {
|
||||
try {
|
||||
const authorizations = await requestConsumerTokenServiceOnce();
|
||||
if (!current.enabled || current !== session) return;
|
||||
if (!current.enabled || current !== session || !allowsCrmActivities()) return;
|
||||
const result = await sendRuntimeMessage({ type: messageTypes.requestWlActions, revnId, authorization: authorizations?.workloadActions });
|
||||
if (!current.enabled || current !== session) return;
|
||||
if (!current.enabled || current !== session || !allowsCrmActivities()) return;
|
||||
appendBackgroundRequestLog(result?.debugRequests);
|
||||
if (!result?.ok) throw new Error(result?.error || "Unable to load workload actions.");
|
||||
record.actions = result.actions;
|
||||
@@ -2178,7 +2207,7 @@ function createOpportunityWorkloadActions({ authSessionState, requestConsumerTok
|
||||
}
|
||||
}
|
||||
function createBadge(optyNumber) {
|
||||
if (!session.enabled || !optyNumber) return null;
|
||||
if (!session.enabled || !allowsCrmActivities() || !optyNumber) return null;
|
||||
const products = productsContentState.opptyProductsByNumber.get(String(optyNumber));
|
||||
if (!products) return null;
|
||||
const ids = idsFor(products);
|
||||
@@ -6463,7 +6492,7 @@ function createDebugContentView({
|
||||
let returnFocus = null;
|
||||
|
||||
function getRequestCategory(entry) {
|
||||
if (/^request(?:TokenRelay|ConsumerTokenService|CustomerTokenService)/.test(entry.name)) return "authentication";
|
||||
if (/^request(?:CurrentUser|TokenRelay|ConsumerTokenService|CustomerTokenService)/.test(entry.name)) return "authentication";
|
||||
if (entry.name === "requestOpportunities") return "opportunities";
|
||||
if (entry.name === "requestOpptyProducts") return "products";
|
||||
if (entry.name === "requestWlActions") return "actions";
|
||||
@@ -6826,6 +6855,11 @@ function createContentApplication(overrides = {}) {
|
||||
...overrides
|
||||
};
|
||||
const messageTypes = createMessageTypes();
|
||||
const currentUser = createCurrentUser({
|
||||
messageTypes,
|
||||
sendRuntimeMessage: (...args) => platformContentMessages.sendRuntimeMessage(...args),
|
||||
appendBackgroundRequestLog: (...args) => debugContentLog.appendBackgroundRequestLog(...args)
|
||||
});
|
||||
const contracts = createContentContracts();
|
||||
const authSessionState = createAuthSessionState(contracts);
|
||||
const authSalesCommonState = createAuthSalesCommonState();
|
||||
@@ -6857,6 +6891,7 @@ function createContentApplication(overrides = {}) {
|
||||
environment
|
||||
});
|
||||
const contentModal = createContentModal({
|
||||
ensureCurrentUser: () => currentUser.ensure(),
|
||||
ACCOUNT_PLANS_MODAL_ID: contracts.ACCOUNT_PLANS_MODAL_ID,
|
||||
AUTH_STATUS: contracts.AUTH_STATUS,
|
||||
CUSTOMER_FILTER_BUTTON_ID: contracts.CUSTOMER_FILTER_BUTTON_ID,
|
||||
@@ -6975,6 +7010,7 @@ function createContentApplication(overrides = {}) {
|
||||
environment
|
||||
});
|
||||
const opportunitiesController = createOpportunitiesController({
|
||||
ensureCurrentUser: () => currentUser.ensure(),
|
||||
resetWorkloadActions: (...args) => opportunityWorkloadActions.reset(...args),
|
||||
STAGE_OPTIONS: contracts.STAGE_OPTIONS,
|
||||
STATUS_OPTIONS: contracts.STATUS_OPTIONS,
|
||||
@@ -7023,6 +7059,7 @@ function createContentApplication(overrides = {}) {
|
||||
createCloseIcon: (...args) => contentIcons.createCloseIcon(...args), environment
|
||||
});
|
||||
const opportunityCrmServiceRequests = createOpportunityCrmServiceRequests({
|
||||
allowsCrmActivities: () => currentUser.allowsCrmActivities(),
|
||||
bindPopover: (...args) => crmSrPopover.bind(...args),
|
||||
closePopover: (...args) => crmSrPopover.close(...args),
|
||||
requestCrmServiceRequest: (...args) => fusionCrmServiceRequests.requestCrmServiceRequest(...args),
|
||||
@@ -7143,6 +7180,7 @@ function createContentApplication(overrides = {}) {
|
||||
environment
|
||||
});
|
||||
const opportunityWorkloadActions = createOpportunityWorkloadActions({
|
||||
allowsCrmActivities: () => currentUser.allowsCrmActivities(),
|
||||
authSessionState,
|
||||
requestConsumerTokenServiceOnce: (...args) => authContentSession.requestConsumerTokenServiceOnce(...args),
|
||||
sendRuntimeMessage: (...args) => platformContentMessages.sendRuntimeMessage(...args),
|
||||
@@ -7335,6 +7373,7 @@ function createContentApplication(overrides = {}) {
|
||||
contentIcons,
|
||||
contentStyles,
|
||||
authContentSession,
|
||||
currentUser,
|
||||
authSalesCommon,
|
||||
authTokenRelay,
|
||||
authXsrfContent,
|
||||
|
||||
Reference in New Issue
Block a user