Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IS-2300: internarbeidsflate-decorator-v3 #211

Merged
merged 3 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .env.template
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
NODE_ENV=development
SESSION_KEY=dette-er-en-lang-og-sikker-streng-for-signering-av-session-cookies
AUTH_REDIRECT_URI=http://localhost:8080/oauth2/callback
INTERNARBEIDSFLATEDECORATOR_HOST=internarbeidsflatedecorator-q1.dev.intern.nav.no
MODIACONTEXTHOLDER_HOST=modiacontextholder.dev.intern.nav.no
MODIACONTEXTHOLDER_AAD_APP_CLIENT_ID=dev-gcp.personoversikt.modiacontextholder
FASTLEGEREST_HOST=https://fastlegerest.intern.dev.nav.no
Expand Down
5 changes: 0 additions & 5 deletions .nais/naiserator-dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,8 @@ spec:
value: production
- name: REDIS_HOST
value: finnfastlege-redis
- name: FINNFASTLEGE_URL
value: "http://finnfastlege"
- name: AUTH_REDIRECT_URI
value: "https://finnfastlege.intern.dev.nav.no/oauth2/callback"
- name: INTERNARBEIDSFLATEDECORATOR_HOST
value: "internarbeidsflatedecorator-q1.dev-fss-pub.nais.io"
- name: FASTLEGEREST_AAD_APP_CLIENT_ID
value: "dev-gcp.teamsykefravr.fastlegerest"
- name: SYFOPERSON_AAD_APP_CLIENT_ID
Expand All @@ -63,7 +59,6 @@ spec:
outbound:
external:
- host: "login.microsoftonline.com"
- host: "internarbeidsflatedecorator-q1.dev-fss-pub.nais.io"
rules:
- application: fastlegerest
- application: istilgangskontroll
Expand Down
5 changes: 0 additions & 5 deletions .nais/naiserator-prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,8 @@ spec:
value: production
- name: REDIS_HOST
value: finnfastlege-redis
- name: FINNFASTLEGE_URL
value: "http://finnfastlege"
- name: AUTH_REDIRECT_URI
value: "https://finnfastlege.intern.nav.no/oauth2/callback"
- name: INTERNARBEIDSFLATEDECORATOR_HOST
value: "internarbeidsflatedecorator.prod-fss-pub.nais.io"
- name: FASTLEGEREST_AAD_APP_CLIENT_ID
value: "prod-gcp.teamsykefravr.fastlegerest"
- name: SYFOPERSON_AAD_APP_CLIENT_ID
Expand All @@ -63,7 +59,6 @@ spec:
outbound:
external:
- host: "login.microsoftonline.com"
- host: "internarbeidsflatedecorator.prod-fss-pub.nais.io"
rules:
- application: fastlegerest
- application: istilgangskontroll
Expand Down
8 changes: 4 additions & 4 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<% if (process.env.NODE_ENV !== 'development') { %>
<script src="/internarbeidsflatedecorator/v2.1/static/js/head.v2.min.js"></script>
<script src="https://cdn.nav.no/personoversikt/internarbeidsflate-decorator-v3/prod/latest/dist/bundle.js"></script>
<link
rel="stylesheet"
href="/internarbeidsflatedecorator/v2.1/static/css/main.css"
href="https://cdn.nav.no/personoversikt/internarbeidsflate-decorator-v3/prod/latest/dist/index.css"
/>
<% } %> <% if (process.env.NODE_ENV === 'development') { %>
<script src="https://navikt.github.io/internarbeidsflatedecorator/v2.1/static/js/head.v2.min.js"></script>
<script src="https://cdn.nav.no/personoversikt/internarbeidsflate-decorator-v3/dev/latest/dist/bundle.js"></script>
<link
rel="stylesheet"
href="https://navikt.github.io/internarbeidsflatedecorator/v2.1/static/css/main.css"
href="https://cdn.nav.no/personoversikt/internarbeidsflate-decorator-v3/dev/latest/dist/index.css"
/>
<% } %>
</head>
Expand Down
5 changes: 3 additions & 2 deletions server/authUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ async function initJWKSet() {
_remoteJWKSet = await createRemoteJWKSet(new URL(Config.auth.jwksUri));
}

const retrieveToken = async (
const retrieveAndValidateToken = async (
req: Request,
azureAdIssuer: OpenIdClient.Issuer<any>
): Promise<string | undefined> => {
Expand Down Expand Up @@ -95,7 +95,7 @@ export const getOrRefreshOnBehalfOfToken = async (
req: Request,
clientId: string
): Promise<OboToken | undefined> => {
const token = await retrieveToken(req, issuer);
const token = await retrieveAndValidateToken(req, issuer);
if (!token) {
throw Error(
"Could not get on-behalf-of token because the token was undefined"
Expand All @@ -104,6 +104,7 @@ export const getOrRefreshOnBehalfOfToken = async (
if (req.session.tokenCache === undefined) {
req.session.tokenCache = {};
}

let cachedOboToken = req.session.tokenCache[clientId];
if (cachedOboToken && isNotExpired(cachedOboToken)) {
return cachedOboToken.token;
Expand Down
15 changes: 1 addition & 14 deletions server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,6 @@ export interface ExternalAppConfig {
export const server = {
host: envVar({ name: "HOST", defaultValue: "localhost" }),
port: Number.parseInt(envVar({ name: "PORT", defaultValue: "8080" })),
finnfastlegeUrl: envVar({
name: "FINNFASTLEGE_URL",
defaultValue: "http://localhost:8080",
}),

frontendDir: envVar({
name: "FRONTEND_DIR",
defaultValue: path.join(__dirname, "frontend"),
}),

sessionKey: envVar({ name: "SESSION_KEY" }),
sessionCookieName: envVar({
name: "SESSION_COOKIE_NAME",
Expand Down Expand Up @@ -109,10 +99,6 @@ export const auth = {
responseMode: "query",
tokenEndpointAuthSigningAlg: "RS256",

internarbeidsflatedecoratorHost: envVar({
name: "INTERNARBEIDSFLATEDECORATOR_HOST",
}),

modiacontextholder: {
applicationName: "modiacontextholder",
clientId: envVar({
Expand All @@ -121,6 +107,7 @@ export const auth = {
host: envVar({
name: "MODIACONTEXTHOLDER_HOST",
}),
removePathPrefix: true,
},

fastlegerest: {
Expand Down
23 changes: 0 additions & 23 deletions server/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,28 +168,5 @@ export const setupProxy = (
);
}
);

router.use(
"/internarbeidsflatedecorator",
expressHttpProxy(Config.auth.internarbeidsflatedecoratorHost, {
https: true,
proxyReqPathResolver: (req) => {
return `/internarbeidsflatedecorator${req.url}`;
},
proxyErrorHandler: (err, res, next) => {
console.log(
`Error in proxy for internarbeidsflatedecorator ${err.message}, ${err.code}`
);
if (err && err.code === "ECONNREFUSED") {
console.log("proxyErrorHandler: Got ECONNREFUSED");
return res
.status(503)
.send({ message: `Could not contact internarbeidsflatedecorator` });
}
next(err);
},
})
);

return router;
};
20 changes: 20 additions & 0 deletions src/api/axios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,23 @@ export const get = <ResponseData>(
}
});
};

export const post = <ResponseData>(
url: string,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: Record<string, any> | Record<string, any>[],
personIdent?: string
): Promise<ResponseData> => {
return axios
.post(url, data, {
headers: defaultRequestHeaders(personIdent),
})
.then((response) => response.data)
.catch(function (error) {
if (axios.isAxiosError(error)) {
handleAxiosError(error);
} else {
throw new ApiErrorException(generalError(error), error.code);
}
});
};
1 change: 1 addition & 0 deletions src/api/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const MODIACONTEXTHOLDER_ROOT = "/modiacontextholder/api";
export const SYFOPERSON_ROOT = "/syfoperson/api/v2";
export const FASTLEGEREST_ROOT = "/fastlegerest/api/v2";
export const TILGANGSKONTROLL_AD_PATH =
Expand Down
14 changes: 14 additions & 0 deletions src/data/modiacontext/useAktivBruker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { post } from "@/api/axios";
import { MODIACONTEXTHOLDER_ROOT } from "@/api/constants";
import { useMutation } from "@tanstack/react-query";

const NY_AKTIV_BRUKER = "NY_AKTIV_BRUKER";

export const useAktivBruker = () =>
useMutation({
mutationFn: (fnr: string) =>
post(`${MODIACONTEXTHOLDER_ROOT}/context`, {
verdi: fnr,
eventType: NY_AKTIV_BRUKER,
}),
});
15 changes: 11 additions & 4 deletions src/decorator/Decorator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,23 @@ import NAVSPA from "@navikt/navspa";
import { DecoratorProps } from "./decoratorProps";
import decoratorConfig from "./decoratorconfig";
import { fullNaisUrlDefault } from "@/utils/miljoUtil";
import { useAktivBruker } from "@/data/modiacontext/useAktivBruker";

const InternflateDecorator = NAVSPA.importer<DecoratorProps>(
"internarbeidsflatefs"
"internarbeidsflate-decorator-v3"
);

const Decorator = () => {
const aktivBruker = useAktivBruker();

const handlePersonsokSubmit = (nyttFnr: string) => {
const host = "syfomodiaperson";
const path = `/sykefravaer/${nyttFnr}`;
window.location.href = fullNaisUrlDefault(host, path);
aktivBruker.mutate(nyttFnr, {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tror dette har vært brukket en stund (men kanskje ikke så mange som hopper til syfomodiaperson fra finnfastlege).

onSuccess: () => {
const host = "syfomodiaperson";
const path = `/sykefravaer`;
window.location.href = fullNaisUrlDefault(host, path);
},
});
};

const config = useCallback(decoratorConfig, [handlePersonsokSubmit])(
Expand Down
87 changes: 53 additions & 34 deletions src/decorator/decoratorProps.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,67 @@
interface TogglesConfig {
visVeileder: boolean;
export interface DecoratorProps {
enhet?: string | undefined; // Konfigurasjon av enhet-kontekst
accessToken?: string | undefined; // Manuell innsending av JWT, settes som Authorization-header. Om null sendes cookies vha credentials: 'include'
fnr?: string | undefined; // Konfigurasjon av fødselsnummer-kontekst
userKey?: string | undefined; // Om man ikke ønsker å bruke fnr i urler, kan andre apper kalle contextholder for å generere en midlertidig kode. Hvis App A skal navigere til App B som har dekoratøren, må App A først sende en post request til /fnr-code/generate med {fnr: string} i bodyen, dette returnerer {fnr: string, code: string} til App A. App A kan så navigere til App B og sende med denne koden. App B kan så sende den koden inn til dekoratøren i userKey propen og så henter dekoratøren fnr for den koden fra contextholderen.
enableHotkeys?: boolean | undefined; // Aktivere hurtigtaster
fetchActiveEnhetOnMount?: boolean | undefined; // Om enhet er undefined fra container appen, og denne er satt til true, henter den sist aktiv enhet og bruker denne.
fetchActiveUserOnMount?: boolean | undefined; // Om fnr er undefined fra container appen, og denne er satt til true for at den skal hente siste aktiv fnr.
onEnhetChanged: () => void; // Kalles når enheten endres
onFnrChanged: (fnr?: string | null) => void; // Kalles når fnr enheten endres
onLinkClick?: (link: { text: string; url: string }) => void; // Kan brukes for å legge til callbacks ved klikk på lenker i menyen. Merk at callbacken ikke kan awaites og man må selv håndtere at siden lukkes. Nyttig for å f.eks tracke navigasjon events i amplitude
appName: string; // Navn på applikasjonen
hotkeys?: Hotkey[]; // Konfigurasjon av hurtigtaster
markup?: Markup; // Egen HTML
showEnheter: boolean; // Vis enheter
showSearchArea: boolean; // Vis søkefelt
showHotkeys: boolean; // Vis hurtigtaster
environment: Environment; // Miljø som skal brukes.
urlFormat: UrlFormat; // URL format
proxy?: string | undefined; // Manuell overstyring av urlene til BFFs. Gjør alle kall til relativt path hvis true, og bruker verdien som domene om satt til en string. Default: false
}

interface Markup {
etterSokefelt?: string;
export interface Markup {
etterSokefelt?: string; // Gir muligheten for sende inn egen html som blir en del av dekoratøren
}

export interface ControlledContextvalue<T> extends BaseContextvalue<T> {
value?: string;
}
interface UncontrolledContextvalue<T> extends BaseContextvalue<T> {
initialValue?: string;
export interface Enhet {
readonly enhetId: string;
readonly navn: string;
}

interface BaseContextvalue<T> {
display: T;
onChange(value?: string): void;
skipModal?: boolean;
ignoreWsEvents?: boolean;
}
// Miljø
export type Environment =
| "q0"
| "q1"
| "q2"
| "q3"
| "q4"
| "prod"
| "local"
| "mock";

export type Contextvalue<T> =
| ControlledContextvalue<T>
| UncontrolledContextvalue<T>;
export type UrlFormat = "LOCAL" | "NAV_NO" | "ANSATT"; // UrlFormat. Brukes om proxy ikke er satt & i url til websocket.

export enum EnhetDisplay {
ENHET = "ENHET",
ENHET_VALG = "ENHET_VALG",
export interface HotkeyObject {
char: string;
altKey?: boolean;
ctrlKey?: boolean;
metaKey?: boolean;
shiftKey?: boolean;
}

export enum FnrDisplay {
SOKEFELT = "SOKEFELT",
export interface HotkeyDescription {
key: HotkeyObject;
description: string;
forceOverride?: boolean;
}

type EnhetContextvalue = Contextvalue<EnhetDisplay>;
type FnrContextvalue = Contextvalue<FnrDisplay>;
type ProxyConfig = boolean | string;
export interface ActionHotKey extends HotkeyDescription {
action(event: KeyboardEvent): void;
}

export interface DecoratorProps {
appname: string;
fnr?: FnrContextvalue;
enhet?: EnhetContextvalue;
toggles?: TogglesConfig;
markup?: Markup;
useProxy?: ProxyConfig;
accessToken?: string;
export interface DocumentingHotKey extends HotkeyDescription {
documentationOnly: boolean;
}

export type Hotkey = ActionHotKey | DocumentingHotKey;
Loading
Loading