web: manage version via package.json

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2022-06-27 21:31:54 +02:00
parent ef218ff1ff
commit 022401b60e
10 changed files with 111 additions and 80 deletions

View File

@ -17,4 +17,4 @@ tag_name = version/{new_version}
[bumpversion:file:internal/constants/constants.go] [bumpversion:file:internal/constants/constants.go]
[bumpversion:file:web/src/constants.ts] [bumpversion:file:web/package.json]

View File

@ -4,5 +4,3 @@ node_modules
dist dist
# don't lint nyc coverage output # don't lint nyc coverage output
coverage coverage
# don't lint generated code
api/

View File

@ -4,7 +4,5 @@ node_modules
dist dist
# don't lint nyc coverage output # don't lint nyc coverage output
coverage coverage
# don't lint generated code
api/
# Import order matters # Import order matters
poly.ts poly.ts

View File

@ -1,6 +1,6 @@
{ {
"name": "authentik-web", "name": "@goauthentik/web",
"version": "0.0.0", "version": "2022.6.3",
"private": true, "private": true,
"license": "GNU GPLv3", "license": "GNU GPLv3",
"scripts": { "scripts": {

View File

@ -7,6 +7,8 @@ import copy from "rollup-plugin-copy";
import cssimport from "rollup-plugin-cssimport"; import cssimport from "rollup-plugin-cssimport";
import { terser } from "rollup-plugin-terser"; import { terser } from "rollup-plugin-terser";
import pkg from "./package.json";
const extensions = [".js", ".jsx", ".ts", ".tsx"]; const extensions = [".js", ".jsx", ".ts", ".tsx"];
export const resources = [ export const resources = [
@ -73,6 +75,12 @@ export const defaultOptions = {
plugins: [ plugins: [
cssimport(), cssimport(),
markdown(), markdown(),
replace({
"process.env.NODE_ENV": JSON.stringify(isProdBuild ? "production" : "development"),
"process.env.AK_API_BASE_PATH": JSON.stringify(apiBasePath),
"process.env.AK_VERSION": JSON.stringify(pkg.version),
"preventAssignment": true,
}),
nodeResolve({ extensions, browser: true }), nodeResolve({ extensions, browser: true }),
commonjs(), commonjs(),
babel({ babel({
@ -80,11 +88,6 @@ export const defaultOptions = {
babelHelpers: "runtime", babelHelpers: "runtime",
include: ["src/**/*"], include: ["src/**/*"],
}), }),
replace({
"process.env.NODE_ENV": JSON.stringify(isProdBuild ? "production" : "development"),
"process.env.AK_API_BASE_PATH": JSON.stringify(apiBasePath),
"preventAssignment": true,
}),
isProdBuild && terser(), isProdBuild && terser(),
].filter((p) => p), ].filter((p) => p),
watch: { watch: {

View File

@ -1,20 +1,29 @@
import { Config, Configuration, CoreApi, CurrentTenant, FetchParams, Middleware, RequestContext, ResponseContext, RootApi } from "@goauthentik/api";
import { getCookie } from "@goauthentik/web/utils";
import { APIMiddleware } from "@goauthentik/web/elements/notifications/APIDrawer";
import { MessageMiddleware } from "@goauthentik/web/elements/messages/Middleware";
import { VERSION } from "@goauthentik/web/constants"; import { VERSION } from "@goauthentik/web/constants";
import { MessageMiddleware } from "@goauthentik/web/elements/messages/Middleware";
import { APIMiddleware } from "@goauthentik/web/elements/notifications/APIDrawer";
import { getCookie } from "@goauthentik/web/utils";
import {
Config,
Configuration,
CoreApi,
CurrentTenant,
FetchParams,
Middleware,
RequestContext,
ResponseContext,
RootApi,
} from "@goauthentik/api";
export class LoggingMiddleware implements Middleware { export class LoggingMiddleware implements Middleware {
post(context: ResponseContext): Promise<Response | void> { post(context: ResponseContext): Promise<Response | void> {
tenant().then(tenant => { tenant().then((tenant) => {
let msg = `authentik/api[${tenant.matchedDomain}]: `; let msg = `authentik/api[${tenant.matchedDomain}]: `;
msg += `${context.response.status} ${context.init.method} ${context.url}`; msg += `${context.response.status} ${context.init.method} ${context.url}`;
console.debug(msg); console.debug(msg);
}); });
return Promise.resolve(context.response); return Promise.resolve(context.response);
} }
} }
let globalConfigPromise: Promise<Config>; let globalConfigPromise: Promise<Config>;
@ -28,23 +37,27 @@ export function config(): Promise<Config> {
let globalTenantPromise: Promise<CurrentTenant>; let globalTenantPromise: Promise<CurrentTenant>;
export function tenant(): Promise<CurrentTenant> { export function tenant(): Promise<CurrentTenant> {
if (!globalTenantPromise) { if (!globalTenantPromise) {
globalTenantPromise = new CoreApi(DEFAULT_CONFIG).coreTenantsCurrentRetrieve().then(tenant => { globalTenantPromise = new CoreApi(DEFAULT_CONFIG)
/** .coreTenantsCurrentRetrieve()
* <link rel="icon" href="/static/dist/assets/icons/icon.png"> .then((tenant) => {
* <link rel="shortcut icon" href="/static/dist/assets/icons/icon.png"> /**
*/ * <link rel="icon" href="/static/dist/assets/icons/icon.png">
const rels = ["icon", "shortcut icon"]; * <link rel="shortcut icon" href="/static/dist/assets/icons/icon.png">
rels.forEach(rel => { */
let relIcon = document.head.querySelector<HTMLLinkElement>(`link[rel='${rel}']`); const rels = ["icon", "shortcut icon"];
if (!relIcon) { rels.forEach((rel) => {
relIcon = document.createElement('link'); let relIcon = document.head.querySelector<HTMLLinkElement>(
relIcon.rel = rel; `link[rel='${rel}']`,
document.getElementsByTagName('head')[0].appendChild(relIcon); );
} if (!relIcon) {
relIcon.href = tenant.brandingFavicon; relIcon = document.createElement("link");
}) relIcon.rel = rel;
return tenant; document.getElementsByTagName("head")[0].appendChild(relIcon);
}); }
relIcon.href = tenant.brandingFavicon;
});
return tenant;
});
} }
return globalTenantPromise; return globalTenantPromise;
} }

View File

@ -74,10 +74,10 @@ export class PlexAPIClient {
headers: headers, headers: headers,
}); });
if (pinResponse.status > 200) { if (pinResponse.status > 200) {
throw new SentryIgnoredError("Invalid response code") throw new SentryIgnoredError("Invalid response code");
} }
const pin: PlexPinResponse = await pinResponse.json(); const pin: PlexPinResponse = await pinResponse.json();
console.debug(`authentik/plex: polling Pin`); console.debug("authentik/plex: polling Pin");
return pin.authToken; return pin.authToken;
} }

View File

@ -1,11 +1,13 @@
import { SentryIgnoredError } from "@goauthentik/web/common/errors";
import { VERSION } from "@goauthentik/web/constants";
import * as Sentry from "@sentry/browser"; import * as Sentry from "@sentry/browser";
import { Integrations } from "@sentry/tracing"; import { Integrations } from "@sentry/tracing";
import { VERSION } from "@goauthentik/web/constants";
import { SentryIgnoredError } from "@goauthentik/web/common/errors";
import { me } from "./Users";
import { config } from "./Config";
import { Config } from "@goauthentik/api"; import { Config } from "@goauthentik/api";
import { config } from "./Config";
import { me } from "./Users";
export const TAG_SENTRY_COMPONENT = "authentik.component"; export const TAG_SENTRY_COMPONENT = "authentik.component";
export const TAG_SENTRY_CAPABILITIES = "authentik.capabilities"; export const TAG_SENTRY_CAPABILITIES = "authentik.capabilities";
@ -15,13 +17,13 @@ export function configureSentry(canDoPpi = false): Promise<Config> {
Sentry.init({ Sentry.init({
dsn: "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8", dsn: "https://a579bb09306d4f8b8d8847c052d3a1d3@sentry.beryju.org/8",
ignoreErrors: [ ignoreErrors: [
/network/ig, /network/gi,
/fetch/ig, /fetch/gi,
// Error on edge on ios, // Error on edge on ios,
// https://stackoverflow.com/questions/69261499/what-is-instantsearchsdkjsbridgeclearhighlight // https://stackoverflow.com/questions/69261499/what-is-instantsearchsdkjsbridgeclearhighlight
/instantSearchSDKJSBridgeClearHighlight/ig, /instantSearchSDKJSBridgeClearHighlight/gi,
// Seems to be an issue in Safari and Firefox // Seems to be an issue in Safari and Firefox
/MutationObserver.observe/ig, /MutationObserver.observe/gi,
], ],
release: `authentik@${VERSION}`, release: `authentik@${VERSION}`,
tunnel: "/api/v3/sentry/", tunnel: "/api/v3/sentry/",
@ -32,14 +34,20 @@ export function configureSentry(canDoPpi = false): Promise<Config> {
], ],
tracesSampleRate: config.errorReporting.tracesSampleRate, tracesSampleRate: config.errorReporting.tracesSampleRate,
environment: config.errorReporting.environment, environment: config.errorReporting.environment,
beforeSend: async (event: Sentry.Event, hint: Sentry.EventHint | undefined): Promise<Sentry.Event | null> => { beforeSend: async (
event: Sentry.Event,
hint: Sentry.EventHint | undefined,
): Promise<Sentry.Event | null> => {
if (!hint) { if (!hint) {
return event; return event;
} }
if (hint.originalException instanceof SentryIgnoredError) { if (hint.originalException instanceof SentryIgnoredError) {
return null; return null;
} }
if (hint.originalException instanceof Response || hint.originalException instanceof DOMException) { if (
hint.originalException instanceof Response ||
hint.originalException instanceof DOMException
) {
return null; return null;
} }
return event; return event;
@ -48,10 +56,12 @@ export function configureSentry(canDoPpi = false): Promise<Config> {
Sentry.setTag(TAG_SENTRY_CAPABILITIES, config.capabilities.join(",")); Sentry.setTag(TAG_SENTRY_CAPABILITIES, config.capabilities.join(","));
if (window.location.pathname.includes("if/")) { if (window.location.pathname.includes("if/")) {
Sentry.setTag(TAG_SENTRY_COMPONENT, `web/${currentInterface()}`); Sentry.setTag(TAG_SENTRY_COMPONENT, `web/${currentInterface()}`);
Sentry.configureScope((scope) => scope.setTransactionName(`authentik.web.if.${currentInterface()}`)); Sentry.configureScope((scope) =>
scope.setTransactionName(`authentik.web.if.${currentInterface()}`),
);
} }
if (config.errorReporting.sendPii && canDoPpi) { if (config.errorReporting.sendPii && canDoPpi) {
me().then(user => { me().then((user) => {
Sentry.setUser({ email: user.user.email }); Sentry.setUser({ email: user.user.email });
console.debug("authentik/config: Sentry with PII enabled."); console.debug("authentik/config: Sentry with PII enabled.");
}); });

View File

@ -1,5 +1,7 @@
import { CoreApi, ResponseError, SessionUser } from "@goauthentik/api";
import { activateLocale } from "@goauthentik/web/interfaces/locale"; import { activateLocale } from "@goauthentik/web/interfaces/locale";
import { CoreApi, ResponseError, SessionUser } from "@goauthentik/api";
import { DEFAULT_CONFIG } from "./Config"; import { DEFAULT_CONFIG } from "./Config";
let globalMePromise: Promise<SessionUser> | undefined; let globalMePromise: Promise<SessionUser> | undefined;
@ -11,35 +13,40 @@ export function refreshMe(): Promise<SessionUser> {
export function me(): Promise<SessionUser> { export function me(): Promise<SessionUser> {
if (!globalMePromise) { if (!globalMePromise) {
globalMePromise = new CoreApi(DEFAULT_CONFIG).coreUsersMeRetrieve().then((user) => { globalMePromise = new CoreApi(DEFAULT_CONFIG)
if (!user.user.settings || !("locale" in user.user.settings)) { .coreUsersMeRetrieve()
return user; .then((user) => {
} if (!user.user.settings || !("locale" in user.user.settings)) {
const locale = user.user.settings.locale; return user;
if (locale && locale !== "") {
console.debug(`authentik/locale: Activating user's configured locale '${locale}'`);
activateLocale(locale);
}
return user;
}).catch((ex: ResponseError) => {
const defaultUser: SessionUser = {
user: {
pk: -1,
isSuperuser: false,
isActive: true,
groups: [],
avatar: "",
uid: "",
username: "",
name: "",
settings: {},
} }
}; const locale = user.user.settings.locale;
if (ex.response.status === 401 || ex.response.status === 403) { if (locale && locale !== "") {
window.location.assign("/"); console.debug(
} `authentik/locale: Activating user's configured locale '${locale}'`,
return defaultUser; );
}); activateLocale(locale);
}
return user;
})
.catch((ex: ResponseError) => {
const defaultUser: SessionUser = {
user: {
pk: -1,
isSuperuser: false,
isActive: true,
groups: [],
avatar: "",
uid: "",
username: "",
name: "",
settings: {},
},
};
if (ex.response.status === 401 || ex.response.status === 403) {
window.location.assign("/");
}
return defaultUser;
});
} }
return globalMePromise; return globalMePromise;
} }

View File

@ -1,9 +1,11 @@
// Placeholder, replaced by rollup;
export const VERSION = process.env.AK_VERSION;
export const SECONDARY_CLASS = "pf-m-secondary"; export const SECONDARY_CLASS = "pf-m-secondary";
export const SUCCESS_CLASS = "pf-m-success"; export const SUCCESS_CLASS = "pf-m-success";
export const ERROR_CLASS = "pf-m-danger"; export const ERROR_CLASS = "pf-m-danger";
export const PROGRESS_CLASS = "pf-m-in-progress"; export const PROGRESS_CLASS = "pf-m-in-progress";
export const CURRENT_CLASS = "pf-m-current"; export const CURRENT_CLASS = "pf-m-current";
export const VERSION = "2022.6.3";
export const TITLE_DEFAULT = "authentik"; export const TITLE_DEFAULT = "authentik";
export const ROUTE_SEPARATOR = ";"; export const ROUTE_SEPARATOR = ";";