Skip to content

Commit

Permalink
IS-2300: internarbeidsflate-decorator-v3
Browse files Browse the repository at this point in the history
  • Loading branch information
geir-waagboe committed Sep 16, 2024
1 parent 3af9dfc commit d826743
Show file tree
Hide file tree
Showing 16 changed files with 171 additions and 128 deletions.
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, {
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: (enhetId?: string | null, enhet?: Enhet) => 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

0 comments on commit d826743

Please sign in to comment.