mirror of
https://github.com/kremalicious/umami.git
synced 2024-11-22 09:57:00 +01:00
Accounts and login.
This commit is contained in:
parent
f3f0ad15f2
commit
49a55b40b4
5
components/Footer.js
Normal file
5
components/Footer.js
Normal file
@ -0,0 +1,5 @@
|
||||
import React from 'react';
|
||||
|
||||
export default function Footer() {
|
||||
return <footer className="container mt-5 mb-5">umami - deliciously simple web stats</footer>;
|
||||
}
|
14
components/Header.js
Normal file
14
components/Header.js
Normal file
@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function Header() {
|
||||
return (
|
||||
<header className="container">
|
||||
<h1>
|
||||
<Link href="/">
|
||||
<a>umami</a>
|
||||
</Link>
|
||||
</h1>
|
||||
</header>
|
||||
);
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import Head from 'next/head';
|
||||
import Header from 'components/header';
|
||||
import Footer from 'components/footer';
|
||||
import Header from 'components/Header';
|
||||
import Footer from 'components/Footer';
|
||||
|
||||
export default function Layout({ title, children }) {
|
||||
return (
|
||||
@ -13,14 +13,6 @@ export default function Layout({ title, children }) {
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
{typeof window !== 'undefined' && (
|
||||
<script
|
||||
async
|
||||
defer
|
||||
data-website-id="d0059975-b79a-4f83-8926-ed731475fded"
|
||||
src="/umami.js"
|
||||
/>
|
||||
)}
|
||||
</Head>
|
||||
<Header />
|
||||
<main className="container">{children}</main>
|
59
components/Login.js
Normal file
59
components/Login.js
Normal file
@ -0,0 +1,59 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Formik, Form, Field, ErrorMessage } from 'formik';
|
||||
import Router from 'next/router';
|
||||
import { post } from 'lib/web';
|
||||
|
||||
const validate = ({ username, password }) => {
|
||||
const errors = {};
|
||||
|
||||
if (!username) {
|
||||
errors.username = 'Required';
|
||||
}
|
||||
if (!password) {
|
||||
errors.password = 'Required';
|
||||
}
|
||||
|
||||
return errors;
|
||||
};
|
||||
|
||||
export default function Login() {
|
||||
const [message, setMessage] = useState();
|
||||
|
||||
const handleSubmit = async ({ username, password }) => {
|
||||
const response = await post('/api/auth', { username, password });
|
||||
|
||||
if (response?.token) {
|
||||
await Router.push('/admin');
|
||||
} else {
|
||||
setMessage('Incorrect username/password.');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={{
|
||||
username: '',
|
||||
password: '',
|
||||
}}
|
||||
validate={validate}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
{() => (
|
||||
<Form>
|
||||
<h3>{message}</h3>
|
||||
<div>
|
||||
<label htmlFor="username">Username</label>
|
||||
<Field name="username" type="text" />
|
||||
<ErrorMessage name="username" />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="password">Password</label>
|
||||
<Field name="password" type="password" />
|
||||
<ErrorMessage name="password" />
|
||||
</div>
|
||||
<button type="submit">Submit</button>
|
||||
</Form>
|
||||
)}
|
||||
</Formik>
|
||||
);
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
export default function Footer() {
|
||||
return <footer className="container">Footer</footer>;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
export default function Header() {
|
||||
return <header className="container">
|
||||
<h1>umami</h1>
|
||||
</header>;
|
||||
}
|
3
index.js
Normal file
3
index.js
Normal file
@ -0,0 +1,3 @@
|
||||
const { name, version } = require('./package.json');
|
||||
|
||||
console.log(`${name} ${version}`);
|
@ -6,23 +6,19 @@ import { JWT, JWE, JWK } from 'jose';
|
||||
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
||||
const KEY = JWK.asKey(Buffer.from(secret()));
|
||||
|
||||
export function sha256(...args) {
|
||||
return crypto.createHash('sha256').update(args.join('')).digest('hex');
|
||||
export function hash(...args) {
|
||||
return crypto.createHash('sha512').update(args.join('')).digest('hex');
|
||||
}
|
||||
|
||||
export function secret() {
|
||||
return sha256(process.env.HASH_SALT);
|
||||
return hash(process.env.HASH_SALT);
|
||||
}
|
||||
|
||||
export function uuid(...args) {
|
||||
return v5(args.join(''), v5(process.env.HASH_SALT, v5.DNS));
|
||||
}
|
||||
|
||||
export function random(n = 64) {
|
||||
return crypto.randomBytes(n).toString('hex');
|
||||
}
|
||||
|
||||
export function isValidHash(s) {
|
||||
export function isValidId(s) {
|
||||
return UUID_REGEX.test(s);
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { getWebsite, getSession, createSession } from 'lib/db';
|
||||
import { getCountry, getDevice, getIpAddress } from 'lib/utils';
|
||||
import { uuid, isValidHash, verifyToken } from 'lib/crypto';
|
||||
import { uuid, isValidId, verifyToken } from 'lib/crypto';
|
||||
|
||||
export default async req => {
|
||||
const { payload } = req.body;
|
||||
const { website: website_uuid, hostname, screen, language, session } = payload;
|
||||
|
||||
if (!isValidHash(website_uuid)) {
|
||||
if (!isValidId(website_uuid)) {
|
||||
throw new Error(`Invalid website: ${website_uuid}`);
|
||||
}
|
||||
|
||||
|
10
lib/web.js
Normal file
10
lib/web.js
Normal file
@ -0,0 +1,10 @@
|
||||
export const post = (url, params) =>
|
||||
fetch(url, {
|
||||
method: 'post',
|
||||
cache: 'no-cache',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(params),
|
||||
}).then(res => (res.status === 200 ? res.json() : null));
|
14
package.json
14
package.json
@ -1,17 +1,23 @@
|
||||
{
|
||||
"name": "umami",
|
||||
"version": "0.1.0",
|
||||
"description": "Deliciously simple website analytics",
|
||||
"description": "Deliciously simple website stats",
|
||||
"main": "index.js",
|
||||
"author": "Mike Cao <mike@mikecao.com>",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/mikecao/umami",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/mikecao/umami.git"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "next dev -p 8000",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"build-script": "rollup -c",
|
||||
"build-schema": "prisma introspect",
|
||||
"build-client": "prisma generate"
|
||||
"build-client": "prisma generate",
|
||||
"create-account": "node scripts/create-account.js"
|
||||
},
|
||||
"lint-staged": {
|
||||
"**/*.js": [
|
||||
@ -29,7 +35,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@prisma/client": "2.2.2",
|
||||
"base64url": "^3.0.1",
|
||||
"bcrypt": "^5.0.0",
|
||||
"chart.js": "^2.9.3",
|
||||
"classnames": "^2.2.6",
|
||||
@ -38,12 +43,13 @@
|
||||
"date-fns": "^2.14.0",
|
||||
"detect-browser": "^5.1.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"formik": "^2.1.5",
|
||||
"geolite2-redist": "^1.0.7",
|
||||
"is-localhost-ip": "^1.4.0",
|
||||
"jose": "^1.27.2",
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"maxmind": "^4.1.3",
|
||||
"next": "9.3.5",
|
||||
"next-cookies": "^2.0.3",
|
||||
"node-fetch": "^2.6.0",
|
||||
"promise-polyfill": "^8.1.3",
|
||||
"react": "16.13.1",
|
||||
|
@ -1,10 +1,10 @@
|
||||
import React from 'react';
|
||||
import Layout from 'components/layout';
|
||||
import Layout from 'components/Layout';
|
||||
|
||||
export default function Custom404() {
|
||||
return (
|
||||
<Layout title="404 - Page Not Found">
|
||||
<h1>oops</h1>
|
||||
<Layout>
|
||||
<h1>oops! not found</h1>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
36
pages/admin.js
Normal file
36
pages/admin.js
Normal file
@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import cookies from 'next-cookies';
|
||||
import Layout from 'components/Layout';
|
||||
import { verifySecureToken } from 'lib/crypto';
|
||||
|
||||
export default function Admin({ username }) {
|
||||
return (
|
||||
<Layout title="Admin">
|
||||
<h2>
|
||||
You've successfully logged in as <b>{username}</b>.
|
||||
</h2>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
export async function getServerSideProps(context) {
|
||||
const token = cookies(context)['umami.auth'];
|
||||
|
||||
try {
|
||||
const payload = await verifySecureToken(token);
|
||||
|
||||
return {
|
||||
props: {
|
||||
username: payload.username,
|
||||
},
|
||||
};
|
||||
} catch {
|
||||
const { res } = context;
|
||||
|
||||
res.statusCode = 303;
|
||||
res.setHeader('Location', '/');
|
||||
res.end();
|
||||
}
|
||||
|
||||
return { props: {} };
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
import { serialize } from 'cookie';
|
||||
import { checkPassword, createSecureToken } from 'lib/crypto';
|
||||
import { getAccount } from 'lib/db';
|
||||
import { allowPost } from 'lib/middleware';
|
||||
|
||||
export default async (req, res) => {
|
||||
await allowPost(req, res);
|
||||
|
||||
const { username, password } = req.body;
|
||||
|
||||
const account = await getAccount(username);
|
||||
@ -10,13 +13,16 @@ export default async (req, res) => {
|
||||
if (account && (await checkPassword(password, account.password))) {
|
||||
const { user_id, username, is_admin } = account;
|
||||
const token = await createSecureToken({ user_id, username, is_admin });
|
||||
const expires = new Date(Date.now() + 31536000000);
|
||||
const cookie = serialize('umami.auth', token, { expires, httpOnly: true });
|
||||
const cookie = serialize('umami.auth', token, {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
maxAge: 60 * 60 * 24 * 365,
|
||||
});
|
||||
|
||||
res.setHeader('Set-Cookie', [cookie]);
|
||||
|
||||
res.status(200).send({ token });
|
||||
} else {
|
||||
res.status(401).send('');
|
||||
res.status(401).end();
|
||||
}
|
||||
};
|
||||
|
@ -8,25 +8,24 @@ export default async (req, res) => {
|
||||
|
||||
const session = await checkSession(req);
|
||||
|
||||
const token = await createToken(session);
|
||||
const { website_id, session_id } = session;
|
||||
const { type, payload } = req.body;
|
||||
let ok = 1;
|
||||
let ok = false;
|
||||
|
||||
if (type === 'pageview') {
|
||||
const { url, referrer } = payload;
|
||||
await savePageView(website_id, session_id, url, referrer).catch(e => {
|
||||
ok = 0;
|
||||
throw e;
|
||||
});
|
||||
|
||||
await savePageView(website_id, session_id, url, referrer);
|
||||
|
||||
ok = true;
|
||||
} else if (type === 'event') {
|
||||
const { url, event_type, event_value } = payload;
|
||||
await saveEvent(website_id, session_id, url, event_type, event_value).catch(() => {
|
||||
ok = 0;
|
||||
throw e;
|
||||
});
|
||||
}
|
||||
|
||||
const token = await createToken(session);
|
||||
await saveEvent(website_id, session_id, url, event_type, event_value);
|
||||
|
||||
ok = true;
|
||||
}
|
||||
|
||||
res.status(200).json({ ok, session: token });
|
||||
};
|
||||
|
@ -7,6 +7,6 @@ export default async (req, res) => {
|
||||
const payload = await verifySecureToken(token);
|
||||
res.status(200).send(payload);
|
||||
} catch {
|
||||
res.status(400).send('');
|
||||
res.status(400).end();
|
||||
}
|
||||
};
|
||||
|
@ -1,23 +1,17 @@
|
||||
import React from 'react';
|
||||
import Layout from 'components/layout';
|
||||
import Link from 'next/link';
|
||||
import Layout from 'components/Layout';
|
||||
import Login from 'components/Login';
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<Layout>
|
||||
Hello.
|
||||
<br />
|
||||
<Link href="/?q=abc">
|
||||
<a>abc</a>
|
||||
<Login />
|
||||
<p>
|
||||
<Link href="/test">
|
||||
<a>Test page 🡒</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="/?q=123">
|
||||
<a>123</a>
|
||||
</Link>
|
||||
<br />
|
||||
<button id="primary-button" className="otherClass umami--click--primary-button" type="button">
|
||||
Button
|
||||
</button>
|
||||
</p>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
46
pages/test.js
Normal file
46
pages/test.js
Normal file
@ -0,0 +1,46 @@
|
||||
import Head from 'next/head';
|
||||
import Link from 'next/link';
|
||||
import Layout from 'components/Layout';
|
||||
|
||||
export default function Test({ websiteId }) {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
{typeof window !== 'undefined' && (
|
||||
<script async defer data-website-id={websiteId} src="/umami.js" />
|
||||
)}
|
||||
</Head>
|
||||
<Layout>
|
||||
<p>
|
||||
Here you can test if your umami installation works. Open the network tab in your browser's
|
||||
developer console and watch for requests to the url <b>collect</b>. The links below should
|
||||
trigger page views. Clicking on the button should trigger an event.
|
||||
</p>
|
||||
<h2>Page links</h2>
|
||||
<Link href="?q=1">
|
||||
<a>Page One</a>
|
||||
</Link>
|
||||
<br />
|
||||
<Link href="?q=2">
|
||||
<a>Page Two</a>
|
||||
</Link>
|
||||
<h2>Events</h2>
|
||||
<button
|
||||
id="primary-button"
|
||||
className="otherClass umami--click--primary-button"
|
||||
type="button"
|
||||
>
|
||||
Button
|
||||
</button>
|
||||
</Layout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export async function getStaticProps() {
|
||||
return {
|
||||
props: {
|
||||
websiteId: process.env.TEST_WEBSITE_ID,
|
||||
},
|
||||
};
|
||||
}
|
28
scripts/create-account.js
Normal file
28
scripts/create-account.js
Normal file
@ -0,0 +1,28 @@
|
||||
const { PrismaClient } = require('@prisma/client');
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
const exec = async () => {
|
||||
const account = await prisma.account.findOne({
|
||||
where: {
|
||||
username: 'admin',
|
||||
},
|
||||
});
|
||||
|
||||
if (!account) {
|
||||
await prisma.account.create({
|
||||
data: {
|
||||
username: 'admin',
|
||||
password: '$2a$10$BXHPV7APlV1I6WrKJt1igeJAyVsvbhMTaTAi3nHkUJFGPsYmfZq3y',
|
||||
is_admin: true,
|
||||
},
|
||||
});
|
||||
console.log('Account succesfully created.');
|
||||
} else {
|
||||
console.log('Account already exists.');
|
||||
}
|
||||
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
exec();
|
@ -1,5 +1,6 @@
|
||||
import 'promise-polyfill/src/polyfill';
|
||||
import 'unfetch/polyfill';
|
||||
import { post } from 'lib/web';
|
||||
|
||||
((window, sessionKey) => {
|
||||
const {
|
||||
@ -20,19 +21,6 @@ import 'unfetch/polyfill';
|
||||
let currentUrl = `${pathname}${search}`;
|
||||
let currentRef = document.referrer;
|
||||
|
||||
/* Helper methods */
|
||||
|
||||
const post = (url, params) =>
|
||||
fetch(url, {
|
||||
method: 'post',
|
||||
cache: 'no-cache',
|
||||
headers: {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(params),
|
||||
}).then(res => res.json());
|
||||
|
||||
const collect = (type, params) => {
|
||||
const payload = {
|
||||
session: store.getItem(sessionKey),
|
||||
@ -53,7 +41,7 @@ import 'unfetch/polyfill';
|
||||
return post(`${hostUrl}/api/collect`, {
|
||||
type,
|
||||
payload,
|
||||
}).then(({ ok, session }) => ok && session && store.setItem(sessionKey, session));
|
||||
}).then(({ session }) => session && store.setItem(sessionKey, session));
|
||||
};
|
||||
|
||||
const pageView = () => collect('pageview').then(() => setTimeout(loadEvents, 300));
|
||||
|
@ -1,8 +1,8 @@
|
||||
html,
|
||||
body {
|
||||
font-family: Inter, -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
font-size: 17px;
|
||||
font-weight: 300;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
line-height: 1.8;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
@ -23,3 +23,17 @@ body {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
header a {
|
||||
color: #000;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
form label {
|
||||
display: inline-block;
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
form input {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
165
yarn.lock
165
yarn.lock
@ -1361,6 +1361,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
|
||||
integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==
|
||||
|
||||
"@types/cookie@^0.3.3":
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.3.tgz#85bc74ba782fb7aa3a514d11767832b0e3bc6803"
|
||||
integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==
|
||||
|
||||
"@types/eslint-visitor-keys@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
|
||||
@ -1391,6 +1396,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e"
|
||||
integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==
|
||||
|
||||
"@types/object-assign@^4.0.30":
|
||||
version "4.0.30"
|
||||
resolved "https://registry.yarnpkg.com/@types/object-assign/-/object-assign-4.0.30.tgz#8949371d5a99f4381ee0f1df0a9b7a187e07e652"
|
||||
integrity sha1-iUk3HVqZ9Dge4PHfCpt6GH4H5lI=
|
||||
|
||||
"@types/parse-json@^4.0.0":
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
|
||||
@ -1942,11 +1952,6 @@ base64-js@^1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1"
|
||||
integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==
|
||||
|
||||
base64url@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d"
|
||||
integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==
|
||||
|
||||
base@^0.11.1:
|
||||
version "0.11.2"
|
||||
resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
|
||||
@ -2139,11 +2144,6 @@ buble@^0.20.0:
|
||||
minimist "^1.2.5"
|
||||
regexpu-core "4.5.4"
|
||||
|
||||
buffer-equal-constant-time@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
|
||||
integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||
@ -2635,7 +2635,7 @@ convert-source-map@^0.3.3:
|
||||
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-0.3.5.tgz#f1d802950af7dd2631a1febe0596550c86ab3190"
|
||||
integrity sha1-8dgClQr33SYxof6+BZZVDIarMZA=
|
||||
|
||||
cookie@^0.4.1:
|
||||
cookie@^0.4.0, cookie@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1"
|
||||
integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==
|
||||
@ -3040,6 +3040,11 @@ deep-is@^0.1.3, deep-is@~0.1.3:
|
||||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
|
||||
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
|
||||
|
||||
deepmerge@^2.1.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170"
|
||||
integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==
|
||||
|
||||
deepmerge@^4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
|
||||
@ -3217,13 +3222,6 @@ duplexify@^3.4.2, duplexify@^3.6.0:
|
||||
readable-stream "^2.0.0"
|
||||
stream-shift "^1.0.0"
|
||||
|
||||
ecdsa-sig-formatter@1.0.11:
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
|
||||
integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
|
||||
dependencies:
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
electron-to-chromium@^1.3.322, electron-to-chromium@^1.3.488:
|
||||
version "1.3.496"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.496.tgz#3f43d32930481d82ad3663d79658e7c59a58af0b"
|
||||
@ -3860,6 +3858,20 @@ fork-ts-checker-webpack-plugin@3.1.1:
|
||||
tapable "^1.0.0"
|
||||
worker-rpc "^0.1.0"
|
||||
|
||||
formik@^2.1.5:
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/formik/-/formik-2.1.5.tgz#de5bbbe35543fa6d049fe96b8ee329d6cd6892b8"
|
||||
integrity sha512-bWpo3PiqVDYslvrRjTq0Isrm0mFXHiO33D8MS6t6dWcqSFGeYF52nlpCM2xwOJ6tRVRznDkL+zz/iHPL4LDuvQ==
|
||||
dependencies:
|
||||
deepmerge "^2.1.1"
|
||||
hoist-non-react-statics "^3.3.0"
|
||||
lodash "^4.17.14"
|
||||
lodash-es "^4.17.14"
|
||||
react-fast-compare "^2.0.1"
|
||||
scheduler "^0.18.0"
|
||||
tiny-warning "^1.0.2"
|
||||
tslib "^1.10.0"
|
||||
|
||||
fragment-cache@^0.2.1:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19"
|
||||
@ -4171,6 +4183,13 @@ hmac-drbg@^1.0.0:
|
||||
minimalistic-assert "^1.0.0"
|
||||
minimalistic-crypto-utils "^1.0.1"
|
||||
|
||||
hoist-non-react-statics@^3.3.0:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
|
||||
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
|
||||
dependencies:
|
||||
react-is "^16.7.0"
|
||||
|
||||
hosted-git-info@^2.1.4:
|
||||
version "2.8.8"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
|
||||
@ -4814,22 +4833,6 @@ json5@^2.1.0, json5@^2.1.2:
|
||||
dependencies:
|
||||
minimist "^1.2.5"
|
||||
|
||||
jsonwebtoken@^8.5.1:
|
||||
version "8.5.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
|
||||
integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==
|
||||
dependencies:
|
||||
jws "^3.2.2"
|
||||
lodash.includes "^4.3.0"
|
||||
lodash.isboolean "^3.0.3"
|
||||
lodash.isinteger "^4.0.4"
|
||||
lodash.isnumber "^3.0.3"
|
||||
lodash.isplainobject "^4.0.6"
|
||||
lodash.isstring "^4.0.1"
|
||||
lodash.once "^4.0.0"
|
||||
ms "^2.1.1"
|
||||
semver "^5.6.0"
|
||||
|
||||
jsx-ast-utils@^2.4.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz#1114a4c1209481db06c690c2b4f488cc665f657e"
|
||||
@ -4838,23 +4841,6 @@ jsx-ast-utils@^2.4.1:
|
||||
array-includes "^3.1.1"
|
||||
object.assign "^4.1.0"
|
||||
|
||||
jwa@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
|
||||
integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==
|
||||
dependencies:
|
||||
buffer-equal-constant-time "1.0.1"
|
||||
ecdsa-sig-formatter "1.0.11"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
jws@^3.2.2:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
|
||||
integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
|
||||
dependencies:
|
||||
jwa "^1.4.1"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
kind-of@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-2.0.1.tgz#018ec7a4ce7e3a86cb9141be519d24c8faa981b5"
|
||||
@ -5031,41 +5017,16 @@ locate-path@^5.0.0:
|
||||
dependencies:
|
||||
p-locate "^4.1.0"
|
||||
|
||||
lodash-es@^4.17.14:
|
||||
version "4.17.15"
|
||||
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78"
|
||||
integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ==
|
||||
|
||||
lodash._reinterpolate@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
|
||||
integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
|
||||
|
||||
lodash.includes@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
|
||||
integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=
|
||||
|
||||
lodash.isboolean@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
|
||||
integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
|
||||
|
||||
lodash.isinteger@^4.0.4:
|
||||
version "4.0.4"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
|
||||
integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=
|
||||
|
||||
lodash.isnumber@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
|
||||
integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=
|
||||
|
||||
lodash.isplainobject@^4.0.6:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
|
||||
integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
|
||||
|
||||
lodash.isstring@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
|
||||
integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
|
||||
|
||||
lodash.memoize@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
|
||||
@ -5076,11 +5037,6 @@ lodash.merge@^4.6.0:
|
||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||
|
||||
lodash.once@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
|
||||
integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
|
||||
|
||||
lodash.template@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab"
|
||||
@ -5572,6 +5528,13 @@ neo-async@^2.5.0, neo-async@^2.6.1:
|
||||
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
||||
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
||||
|
||||
next-cookies@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/next-cookies/-/next-cookies-2.0.3.tgz#5a3eabcb6afa9b4d4ade69dfaaad749d16cd4a9a"
|
||||
integrity sha512-YVCQzwZx+sz+KqLO4y9niHH9jjz6jajlEQbAKfsYVT6DOfngb/0k5l6vFK4rmpExVug96pGag8OBsdSRL9FZhQ==
|
||||
dependencies:
|
||||
universal-cookie "^4.0.2"
|
||||
|
||||
next-tick@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
|
||||
@ -7092,12 +7055,17 @@ react-dom@16.13.1:
|
||||
prop-types "^15.6.2"
|
||||
scheduler "^0.19.1"
|
||||
|
||||
react-fast-compare@^2.0.1:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
|
||||
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
|
||||
|
||||
react-is@16.8.6:
|
||||
version "16.8.6"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
|
||||
integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
|
||||
|
||||
react-is@^16.8.1:
|
||||
react-is@^16.7.0, react-is@^16.8.1:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
@ -7554,6 +7522,14 @@ sax@^1.2.4, sax@~1.2.4:
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
|
||||
|
||||
scheduler@^0.18.0:
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4"
|
||||
integrity sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
scheduler@^0.19.1:
|
||||
version "0.19.1"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.19.1.tgz#4f3e2ed2c1a7d65681f4c854fa8c5a1ccb40f196"
|
||||
@ -8371,6 +8347,11 @@ tiny-lru@7.0.6:
|
||||
resolved "https://registry.yarnpkg.com/tiny-lru/-/tiny-lru-7.0.6.tgz#b0c3cdede1e5882aa2d1ae21cb2ceccf2a331f24"
|
||||
integrity sha512-zNYO0Kvgn5rXzWpL0y3RS09sMK67eGaQj9805jlK9G6pSadfriTczzLHFXa/xcW4mIRfmlB9HyQ/+SgL0V1uow==
|
||||
|
||||
tiny-warning@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
|
||||
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
|
||||
|
||||
tmp@^0.0.33:
|
||||
version "0.0.33"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
|
||||
@ -8653,6 +8634,16 @@ unist-util-visit@^2.0.0:
|
||||
unist-util-is "^4.0.0"
|
||||
unist-util-visit-parents "^3.0.0"
|
||||
|
||||
universal-cookie@^4.0.2:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/universal-cookie/-/universal-cookie-4.0.3.tgz#c2fa59127260e6ad21ef3e0cdd66ad453cbc41f6"
|
||||
integrity sha512-YbEHRs7bYOBTIWedTR9koVEe2mXrq+xdjTJZcoKJK/pQaE6ni28ak2AKXFpevb+X6w3iU5SXzWDiJkmpDRb9qw==
|
||||
dependencies:
|
||||
"@types/cookie" "^0.3.3"
|
||||
"@types/object-assign" "^4.0.30"
|
||||
cookie "^0.4.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
unquote@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544"
|
||||
|
Loading…
Reference in New Issue
Block a user