mirror of
https://github.com/kremalicious/umami.git
synced 2025-02-14 21:10:34 +01:00
Updated useConfig. Added SSO page.
This commit is contained in:
parent
f10c8ba9e2
commit
c58e037a7e
@ -2,7 +2,7 @@ import { useEffect } from 'react';
|
|||||||
import useStore, { setConfig } from 'store/app';
|
import useStore, { setConfig } from 'store/app';
|
||||||
import useApi from 'hooks/useApi';
|
import useApi from 'hooks/useApi';
|
||||||
|
|
||||||
let fetched = false;
|
let loading = false;
|
||||||
|
|
||||||
export default function useConfig() {
|
export default function useConfig() {
|
||||||
const { config } = useStore();
|
const { config } = useStore();
|
||||||
@ -10,12 +10,13 @@ export default function useConfig() {
|
|||||||
|
|
||||||
async function loadConfig() {
|
async function loadConfig() {
|
||||||
const { data } = await get('/config');
|
const { data } = await get('/config');
|
||||||
|
loading = false;
|
||||||
setConfig(data);
|
setConfig(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!config && !fetched) {
|
if (!config && !loading) {
|
||||||
fetched = true;
|
loading = true;
|
||||||
loadConfig();
|
loadConfig();
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
15
lib/auth.js
15
lib/auth.js
@ -1,22 +1,26 @@
|
|||||||
import { parseSecureToken, parseToken } from 'next-basics';
|
import { parseSecureToken, parseToken } from 'next-basics';
|
||||||
import { getAccount, getWebsite } from 'queries';
|
import { getAccount, getWebsite } from 'queries';
|
||||||
|
import debug from 'debug';
|
||||||
import { SHARE_TOKEN_HEADER, TYPE_ACCOUNT, TYPE_WEBSITE } from 'lib/constants';
|
import { SHARE_TOKEN_HEADER, TYPE_ACCOUNT, TYPE_WEBSITE } from 'lib/constants';
|
||||||
import { secret } from 'lib/crypto';
|
import { secret } from 'lib/crypto';
|
||||||
|
|
||||||
export function getAuthToken(req) {
|
const log = debug('umami:auth');
|
||||||
|
|
||||||
|
export function parseAuthToken(req) {
|
||||||
try {
|
try {
|
||||||
const token = req.headers.authorization;
|
const token = req.headers.authorization;
|
||||||
|
|
||||||
return parseSecureToken(token.split(' ')[1], secret());
|
return parseSecureToken(token.split(' ')[1], secret());
|
||||||
} catch {
|
} catch (e) {
|
||||||
|
log(e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getShareToken(req) {
|
export function parseShareToken(req) {
|
||||||
try {
|
try {
|
||||||
return parseToken(req.headers[SHARE_TOKEN_HEADER], secret());
|
return parseToken(req.headers[SHARE_TOKEN_HEADER], secret());
|
||||||
} catch {
|
} catch (e) {
|
||||||
|
log(e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,6 +33,7 @@ export function isValidToken(token, validation) {
|
|||||||
return validation(token);
|
return validation(token);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
log(e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,11 +9,11 @@ export function secret() {
|
|||||||
export function salt() {
|
export function salt() {
|
||||||
const ROTATING_SALT = hash(startOfMonth(new Date()).toUTCString());
|
const ROTATING_SALT = hash(startOfMonth(new Date()).toUTCString());
|
||||||
|
|
||||||
return hash([secret(), ROTATING_SALT]);
|
return hash(secret(), ROTATING_SALT);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function uuid(...args) {
|
export function uuid(...args) {
|
||||||
if (!args.length) return v4();
|
if (!args.length) return v4();
|
||||||
|
|
||||||
return v5(hash([...args, salt()]), v5.DNS);
|
return v5(hash(...args, salt()), v5.DNS);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { createMiddleware, unauthorized, badRequest, serverError } from 'next-basics';
|
import { createMiddleware, unauthorized, badRequest, serverError } from 'next-basics';
|
||||||
import cors from 'cors';
|
import cors from 'cors';
|
||||||
import { getSession } from './session';
|
import { getSession } from './session';
|
||||||
import { getAuthToken, getShareToken } from './auth';
|
import { parseAuthToken, parseShareToken } from './auth';
|
||||||
|
|
||||||
export const useCors = createMiddleware(cors());
|
export const useCors = createMiddleware(cors());
|
||||||
|
|
||||||
@ -26,8 +26,8 @@ export const useSession = createMiddleware(async (req, res, next) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const useAuth = createMiddleware(async (req, res, next) => {
|
export const useAuth = createMiddleware(async (req, res, next) => {
|
||||||
const token = await getAuthToken(req);
|
const token = await parseAuthToken(req);
|
||||||
const shareToken = await getShareToken(req);
|
const shareToken = await parseShareToken(req);
|
||||||
|
|
||||||
if (!token && !shareToken) {
|
if (!token && !shareToken) {
|
||||||
return unauthorized(res);
|
return unauthorized(res);
|
||||||
|
@ -84,7 +84,7 @@
|
|||||||
"maxmind": "^4.3.6",
|
"maxmind": "^4.3.6",
|
||||||
"moment-timezone": "^0.5.35",
|
"moment-timezone": "^0.5.35",
|
||||||
"next": "^12.3.1",
|
"next": "^12.3.1",
|
||||||
"next-basics": "^0.18.0",
|
"next-basics": "^0.20.0",
|
||||||
"node-fetch": "^3.2.8",
|
"node-fetch": "^3.2.8",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
|
@ -2,34 +2,27 @@ import Head from 'next/head';
|
|||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { IntlProvider } from 'react-intl';
|
import { IntlProvider } from 'react-intl';
|
||||||
import useLocale from 'hooks/useLocale';
|
import useLocale from 'hooks/useLocale';
|
||||||
|
import useConfig from 'hooks/useConfig';
|
||||||
import 'styles/variables.css';
|
import 'styles/variables.css';
|
||||||
import 'styles/bootstrap-grid.css';
|
import 'styles/bootstrap-grid.css';
|
||||||
import 'styles/index.css';
|
import 'styles/index.css';
|
||||||
import '@fontsource/inter/400.css';
|
import '@fontsource/inter/400.css';
|
||||||
import '@fontsource/inter/600.css';
|
import '@fontsource/inter/600.css';
|
||||||
|
|
||||||
const Intl = ({ children }) => {
|
|
||||||
const { locale, messages } = useLocale();
|
|
||||||
|
|
||||||
const Wrapper = ({ children }) => <span className={locale}>{children}</span>;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<IntlProvider locale={locale} messages={messages[locale]} textComponent={Wrapper}>
|
|
||||||
{children}
|
|
||||||
</IntlProvider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function App({ Component, pageProps }) {
|
export default function App({ Component, pageProps }) {
|
||||||
|
const { locale, messages } = useLocale();
|
||||||
const { basePath } = useRouter();
|
const { basePath } = useRouter();
|
||||||
const { dir } = useLocale();
|
const { dir } = useLocale();
|
||||||
|
useConfig();
|
||||||
|
|
||||||
|
const Wrapper = ({ children }) => <span className={locale}>{children}</span>;
|
||||||
|
|
||||||
if (process.env.uiDisabled) {
|
if (process.env.uiDisabled) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Intl>
|
<IntlProvider locale={locale} messages={messages[locale]} textComponent={Wrapper}>
|
||||||
<Head>
|
<Head>
|
||||||
<link rel="icon" href={`${basePath}/favicon.ico`} />
|
<link rel="icon" href={`${basePath}/favicon.ico`} />
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href={`${basePath}/apple-touch-icon.png`} />
|
<link rel="apple-touch-icon" sizes="180x180" href={`${basePath}/apple-touch-icon.png`} />
|
||||||
@ -45,6 +38,6 @@ export default function App({ Component, pageProps }) {
|
|||||||
<div className="container" dir={dir}>
|
<div className="container" dir={dir}>
|
||||||
<Component {...pageProps} />
|
<Component {...pageProps} />
|
||||||
</div>
|
</div>
|
||||||
</Intl>
|
</IntlProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
38
pages/sso.js
Normal file
38
pages/sso.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
import debug from 'debug';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import { setItem } from 'next-basics';
|
||||||
|
import { AUTH_TOKEN } from 'lib/constants';
|
||||||
|
import useApi from 'hooks/useApi';
|
||||||
|
import { setUser } from 'store/app';
|
||||||
|
|
||||||
|
const log = debug('umami:sso');
|
||||||
|
|
||||||
|
export default function SingleSignOnPage() {
|
||||||
|
const router = useRouter();
|
||||||
|
const { get } = useApi();
|
||||||
|
const { token, url } = router.query;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function verify() {
|
||||||
|
setItem(AUTH_TOKEN, token);
|
||||||
|
|
||||||
|
const { ok, data } = await get('/auth/verify');
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
log(data);
|
||||||
|
setUser(data);
|
||||||
|
|
||||||
|
if (url) {
|
||||||
|
await router.push(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (token) {
|
||||||
|
verify();
|
||||||
|
}
|
||||||
|
}, [token]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
@ -5244,10 +5244,10 @@ natural-compare@^1.4.0:
|
|||||||
resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
|
resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
|
||||||
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=
|
||||||
|
|
||||||
next-basics@^0.18.0:
|
next-basics@^0.20.0:
|
||||||
version "0.18.0"
|
version "0.20.0"
|
||||||
resolved "https://registry.yarnpkg.com/next-basics/-/next-basics-0.18.0.tgz#7683ec67d562fb57a6f3fb346c989802157450d1"
|
resolved "https://registry.yarnpkg.com/next-basics/-/next-basics-0.20.0.tgz#f88791dcc538438b5044695e37d58b4fdccc6dd8"
|
||||||
integrity sha512-KJZjAHahQ++YYaSPuJVAY0wH9QYXVq85ZUGW5mBMq+qDfL8ZVG4nTWc8GhuI8EYLLR+oZp/eInvoqYgiW/dbhg==
|
integrity sha512-KPqVVSzkKUvu9shvZt5Bp7Xv1nZ2xJRRqwqQ+a6a5JjsdE10Q3p07VLrT2ykl+v/CvR4sz98c0n+MaWpgO3Ckw==
|
||||||
dependencies:
|
dependencies:
|
||||||
base-x "^4.0.0"
|
base-x "^4.0.0"
|
||||||
bcryptjs "^2.4.3"
|
bcryptjs "^2.4.3"
|
||||||
|
Loading…
Reference in New Issue
Block a user