From f4ca353b5c68750bf391e5874f19c609b9c421ef Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Tue, 11 Aug 2020 22:24:41 -0700 Subject: [PATCH] Refactor database queries. --- components/AccountSettings.js | 32 ++-- components/ProfileSettings.js | 6 +- components/WebsiteDetails.js | 14 +- components/WebsiteList.js | 17 +- components/WebsiteSettings.js | 47 +++--- components/forms/LoginForm.js | 15 +- components/forms/LoginForm.module.css | 11 ++ lib/date.js | 2 - lib/db.js | 218 ------------------------- lib/queries.js | 223 +++++++++++++++++++++++++- lib/session.js | 6 +- pages/api/account.js | 26 ++- pages/api/account/[id].js | 4 +- pages/api/account/password.js | 4 +- pages/api/accounts.js | 21 +++ pages/api/auth/login.js | 4 +- pages/api/collect.js | 2 +- pages/api/website.js | 10 +- pages/api/website/[id]/index.js | 6 +- pages/api/website/[id]/metrics.js | 2 +- pages/api/website/[id]/pageviews.js | 6 +- pages/api/website/[id]/rankings.js | 2 +- pages/api/websites.js | 17 ++ pages/login.js | 5 +- 24 files changed, 371 insertions(+), 329 deletions(-) create mode 100644 components/forms/LoginForm.module.css create mode 100644 pages/api/accounts.js create mode 100644 pages/api/websites.js diff --git a/components/AccountSettings.js b/components/AccountSettings.js index 4d44f62d..4878b407 100644 --- a/components/AccountSettings.js +++ b/components/AccountSettings.js @@ -5,7 +5,6 @@ import Button from 'components/common/Button'; import Icon from 'components/common/Icon'; import Table from 'components/common/Table'; import Modal from 'components/common/Modal'; -import WebsiteEditForm from 'components/forms/WebsiteEditForm'; import AccountEditForm from 'components/forms/AccountEditForm'; import Pen from 'assets/pen.svg'; import Plus from 'assets/plus.svg'; @@ -16,33 +15,36 @@ import styles from './AccountSettings.module.css'; import DeleteForm from './forms/DeleteForm'; export default function AccountSettings() { - const user = useSelector(state => state.user); const [data, setData] = useState(); const [addAccount, setAddAccount] = useState(); const [editAccount, setEditAccount] = useState(); const [deleteAccount, setDeleteAccount] = useState(); const [saved, setSaved] = useState(0); + const Checkmark = ({ is_admin }) => (is_admin ? } size="medium" /> : null); + + const Buttons = row => + row.username !== 'admin' ? ( + <> + + + + ) : null; + const columns = [ { key: 'username', label: 'Username' }, { key: 'is_admin', label: 'Administrator', - render: ({ is_admin }) => (is_admin ? } size="medium" /> : null), + render: Checkmark, }, { className: styles.buttons, - render: row => - row.username !== 'admin' ? ( - <> - - - - ) : null, + render: Buttons, }, ]; @@ -58,7 +60,7 @@ export default function AccountSettings() { } async function loadData() { - setData(await get(`/api/account`)); + setData(await get(`/api/accounts`)); } useEffect(() => { diff --git a/components/ProfileSettings.js b/components/ProfileSettings.js index de38a4e8..a3b8fdf0 100644 --- a/components/ProfileSettings.js +++ b/components/ProfileSettings.js @@ -1,9 +1,9 @@ import React, { useState } from 'react'; import { useSelector } from 'react-redux'; -import PageHeader from './layout/PageHeader'; -import Button from './common/Button'; +import PageHeader from 'components/layout/PageHeader'; +import Button from 'components/common/Button'; import ChangePasswordForm from './forms/ChangePasswordForm'; -import Modal from './common/Modal'; +import Modal from 'components/common/Modal'; export default function ProfileSettings() { const user = useSelector(state => state.user); diff --git a/components/WebsiteDetails.js b/components/WebsiteDetails.js index b446d34f..bb29f2dd 100644 --- a/components/WebsiteDetails.js +++ b/components/WebsiteDetails.js @@ -1,12 +1,12 @@ import React, { useEffect, useState } from 'react'; import classNames from 'classnames'; -import WebsiteChart from './charts/WebsiteChart'; -import RankingsChart from './charts/RankingsChart'; -import WorldMap from './common/WorldMap'; -import Page from './layout/Page'; -import PageHeader from './layout/PageHeader'; -import MenuLayout from './layout/MenuLayout'; -import Button from './common/Button'; +import WebsiteChart from 'components/charts/WebsiteChart'; +import RankingsChart from 'components/charts/RankingsChart'; +import WorldMap from 'components/common/WorldMap'; +import Page from 'components/layout/Page'; +import PageHeader from 'components/layout/PageHeader'; +import MenuLayout from 'components/layout/MenuLayout'; +import Button from 'components/common/Button'; import { getDateRange } from 'lib/date'; import { get } from 'lib/web'; import { browserFilter, urlFilter, refFilter, deviceFilter, countryFilter } from 'lib/filters'; diff --git a/components/WebsiteList.js b/components/WebsiteList.js index 9ff80756..1b74ace8 100644 --- a/components/WebsiteList.js +++ b/components/WebsiteList.js @@ -1,22 +1,21 @@ import React, { useState, useEffect } from 'react'; import { useRouter } from 'next/router'; -import { get } from 'lib/web'; -import Link from './common/Link'; -import WebsiteChart from './charts/WebsiteChart'; -import Page from './layout/Page'; -import Icon from './common/Icon'; -import Button from './common/Button'; -import PageHeader from './layout/PageHeader'; +import Link from 'components/common/Link'; +import WebsiteChart from 'components/charts/WebsiteChart'; +import Page from 'components/layout/Page'; +import Button from 'components/common/Button'; +import PageHeader from 'components/layout/PageHeader'; +import EmptyPlaceholder from 'components/common/EmptyPlaceholder'; import Arrow from 'assets/arrow-right.svg'; +import { get } from 'lib/web'; import styles from './WebsiteList.module.css'; -import EmptyPlaceholder from './common/EmptyPlaceholder'; export default function WebsiteList() { const [data, setData] = useState(); const router = useRouter(); async function loadData() { - setData(await get(`/api/website`)); + setData(await get(`/api/websites`)); } useEffect(() => { diff --git a/components/WebsiteSettings.js b/components/WebsiteSettings.js index 6235ee24..83f3ad5e 100644 --- a/components/WebsiteSettings.js +++ b/components/WebsiteSettings.js @@ -1,19 +1,18 @@ import React, { useState, useEffect } from 'react'; -import Table from './common/Table'; -import Button from './common/Button'; -import PageHeader from './layout/PageHeader'; +import Table from 'components/common/Table'; +import Button from 'components/common/Button'; +import PageHeader from 'components/layout/PageHeader'; +import Modal from 'components/common/Modal'; +import WebsiteEditForm from './forms/WebsiteEditForm'; +import DeleteForm from './forms/DeleteForm'; +import WebsiteCodeForm from './forms/WebsiteCodeForm'; +import EmptyPlaceholder from 'components/common/EmptyPlaceholder'; import Pen from 'assets/pen.svg'; import Trash from 'assets/trash.svg'; import Plus from 'assets/plus.svg'; import Code from 'assets/code.svg'; import { get } from 'lib/web'; -import Modal from './common/Modal'; -import WebsiteEditForm from './forms/WebsiteEditForm'; -import DeleteForm from './forms/DeleteForm'; -import WebsiteCodeForm from './forms/WebsiteCodeForm'; import styles from './WebsiteSettings.module.css'; -import EmptyPlaceholder from './common/EmptyPlaceholder'; -import Arrow from '../assets/arrow-right.svg'; export default function WebsiteSettings() { const [data, setData] = useState(); @@ -23,25 +22,27 @@ export default function WebsiteSettings() { const [showCode, setShowCode] = useState(); const [saved, setSaved] = useState(0); + const Buttons = row => ( + <> + + + + + ); + const columns = [ { key: 'name', label: 'Name', className: styles.col }, { key: 'domain', label: 'Domain', className: styles.col }, { key: 'action', className: styles.buttons, - render: row => ( - <> - - - - - ), + render: Buttons, }, ]; @@ -58,7 +59,7 @@ export default function WebsiteSettings() { } async function loadData() { - setData(await get(`/api/website`)); + setData(await get(`/api/websites`)); } useEffect(() => { diff --git a/components/forms/LoginForm.js b/components/forms/LoginForm.js index 216f7337..00f45a37 100644 --- a/components/forms/LoginForm.js +++ b/components/forms/LoginForm.js @@ -2,8 +2,16 @@ import React, { useState } from 'react'; import { Formik, Form, Field } from 'formik'; import Router from 'next/router'; import { post } from 'lib/web'; -import Button from '../common/Button'; -import FormLayout, { FormButtons, FormError, FormMessage, FormRow } from '../layout/FormLayout'; +import Button from 'components/common/Button'; +import FormLayout, { + FormButtons, + FormError, + FormMessage, + FormRow, +} from 'components/layout/FormLayout'; +import Icon from 'components/common/Icon'; +import Logo from 'assets/logo.svg'; +import styles from './LoginForm.module.css'; const validate = ({ username, password }) => { const errors = {}; @@ -32,7 +40,7 @@ export default function LoginForm() { }; return ( - + {() => (
+ } size="xlarge" className={styles.icon} />

umami

diff --git a/components/forms/LoginForm.module.css b/components/forms/LoginForm.module.css new file mode 100644 index 00000000..381c9865 --- /dev/null +++ b/components/forms/LoginForm.module.css @@ -0,0 +1,11 @@ +.login { + display: flex; + flex-direction: column; + margin-top: 80px; +} + +.icon { + display: flex; + justify-content: center; + margin: 0 auto; +} diff --git a/lib/date.js b/lib/date.js index 20ed5097..f53521b9 100644 --- a/lib/date.js +++ b/lib/date.js @@ -111,7 +111,5 @@ export function getDateArray(data, startDate, endDate, unit) { arr.push({ t, y }); } - console.log({ unit, arr }); - return arr; } diff --git a/lib/db.js b/lib/db.js index 31fc07e4..48371da4 100644 --- a/lib/db.js +++ b/lib/db.js @@ -1,6 +1,5 @@ import { PrismaClient } from '@prisma/client'; import chalk from 'chalk'; -import { getMetricsQuery, getPageviewsQuery, getRankingsQuery } from 'lib/queries'; const options = { log: [ @@ -39,220 +38,3 @@ export async function runQuery(query) { throw e; }); } - -export async function getWebsite({ website_id, website_uuid }) { - return runQuery( - prisma.website.findOne({ - where: { - ...(website_id && { website_id }), - ...(website_uuid && { website_uuid }), - }, - }), - ); -} - -export async function getWebsites(user_id) { - return runQuery( - prisma.website.findMany({ - where: { - user_id, - }, - orderBy: { - name: 'asc', - }, - }), - ); -} - -export async function createWebsite(user_id, data) { - return runQuery( - prisma.website.create({ - data: { - account: { - connect: { - user_id, - }, - }, - ...data, - }, - }), - ); -} - -export async function updateWebsite(website_id, data) { - return runQuery( - prisma.website.update({ - where: { - website_id, - }, - data, - }), - ); -} - -export async function deleteWebsite(website_id) { - return runQuery( - /* Prisma bug, does not cascade on non-nullable foreign keys - prisma.website.delete({ - where: { - website_id, - }, - }), - */ - prisma.queryRaw(`delete from website where website_id=$1`, website_id), - ); -} - -export async function createSession(website_id, data) { - return runQuery( - prisma.session.create({ - data: { - website: { - connect: { - website_id, - }, - }, - ...data, - }, - select: { - session_id: true, - }, - }), - ); -} - -export async function getSession({ session_id, session_uuid }) { - return runQuery( - prisma.session.findOne({ - where: { - session_id, - session_uuid, - }, - }), - ); -} - -export async function savePageView(website_id, session_id, url, referrer) { - return runQuery( - prisma.pageview.create({ - data: { - website: { - connect: { - website_id, - }, - }, - session: { - connect: { - session_id, - }, - }, - url, - referrer, - }, - }), - ); -} - -export async function saveEvent(website_id, session_id, url, event_type, event_value) { - return runQuery( - prisma.event.create({ - data: { - website: { - connect: { - website_id, - }, - }, - session: { - connect: { - session_id, - }, - }, - url, - event_type, - event_value, - }, - }), - ); -} - -export async function getAccounts() { - return runQuery(prisma.account.findMany()); -} - -export async function getAccount({ user_id, username }) { - return runQuery( - prisma.account.findOne({ - where: { - username, - user_id, - }, - }), - ); -} - -export async function updateAccount(user_id, data) { - return runQuery( - prisma.account.update({ - where: { - user_id, - }, - data, - }), - ); -} - -export async function deleteAccount(user_id) { - return runQuery( - /* Prisma bug, does not cascade on non-nullable foreign keys - prisma.account.delete({ - where: { - user_id, - }, - }), - */ - prisma.queryRaw(`delete from account where user_id=$1`, user_id), - ); -} - -export async function createAccount(data) { - return runQuery( - prisma.account.create({ - data, - }), - ); -} - -export async function getPageviews(website_id, start_at, end_at) { - return runQuery( - prisma.pageview.findMany({ - where: { - website_id, - created_at: { - gte: start_at, - lte: end_at, - }, - }, - }), - ); -} - -export async function getRankings(website_id, start_at, end_at, type, table) { - return getRankingsQuery(prisma, { website_id, start_at, end_at, type, table }); -} - -export async function getPageviewData( - website_id, - start_at, - end_at, - timezone = 'utc', - unit = 'day', - count = '*', -) { - return runQuery( - getPageviewsQuery(prisma, { website_id, start_at, end_at, timezone, unit, count }), - ); -} - -export async function getMetrics(website_id, start_at, end_at) { - return getMetricsQuery(prisma, { website_id, start_at, end_at }); -} diff --git a/lib/queries.js b/lib/queries.js index 1a6e91ca..dc598c11 100644 --- a/lib/queries.js +++ b/lib/queries.js @@ -1,4 +1,5 @@ import moment from 'moment-timezone'; +import prisma, { runQuery } from 'lib/db'; const POSTGRESQL = 'postgresql'; const MYSQL = 'mysql'; @@ -7,7 +8,216 @@ export function getDatabase() { return process.env.DATABASE_URL.split(':')[0]; } -export function getMetricsQuery(prisma, { website_id, start_at, end_at }) { +export async function getWebsiteById(website_id) { + return runQuery( + prisma.website.findOne({ + where: { + website_id, + }, + }), + ); +} + +export async function getWebsiteByUuid(website_uuid) { + return runQuery( + prisma.website.findOne({ + where: { + website_uuid, + }, + }), + ); +} + +export async function getUserWebsites(user_id) { + return runQuery( + prisma.website.findMany({ + where: { + user_id, + }, + orderBy: { + name: 'asc', + }, + }), + ); +} + +export async function createWebsite(user_id, data) { + return runQuery( + prisma.website.create({ + data: { + account: { + connect: { + user_id, + }, + }, + ...data, + }, + }), + ); +} + +export async function updateWebsite(website_id, data) { + return runQuery( + prisma.website.update({ + where: { + website_id, + }, + data, + }), + ); +} + +export async function deleteWebsite(website_id) { + return runQuery( + /* Prisma bug, does not cascade on non-nullable foreign keys + prisma.website.delete({ + where: { + website_id, + }, + }), + */ + prisma.$queryRaw`delete from website where website_id=${website_id}`, + ); +} + +export async function createSession(website_id, data) { + return runQuery( + prisma.session.create({ + data: { + website: { + connect: { + website_id, + }, + }, + ...data, + }, + select: { + session_id: true, + }, + }), + ); +} + +export async function getSessionById(session_id) { + return runQuery( + prisma.session.findOne({ + where: { + session_id, + }, + }), + ); +} + +export async function getSessionByUuid(session_uuid) { + return runQuery( + prisma.session.findOne({ + where: { + session_uuid, + }, + }), + ); +} + +export async function savePageView(website_id, session_id, url, referrer) { + return runQuery( + prisma.pageview.create({ + data: { + website: { + connect: { + website_id, + }, + }, + session: { + connect: { + session_id, + }, + }, + url, + referrer, + }, + }), + ); +} + +export async function saveEvent(website_id, session_id, url, event_type, event_value) { + return runQuery( + prisma.event.create({ + data: { + website: { + connect: { + website_id, + }, + }, + session: { + connect: { + session_id, + }, + }, + url, + event_type, + event_value, + }, + }), + ); +} + +export async function getAccounts() { + return runQuery(prisma.account.findMany()); +} + +export async function getAccountById(user_id) { + return runQuery( + prisma.account.findOne({ + where: { + user_id, + }, + }), + ); +} + +export async function getAccountByUsername(username) { + return runQuery( + prisma.account.findOne({ + where: { + username, + }, + }), + ); +} + +export async function updateAccount(user_id, data) { + return runQuery( + prisma.account.update({ + where: { + user_id, + }, + data, + }), + ); +} + +export async function deleteAccount(user_id) { + return runQuery( + /* Prisma bug, does not cascade on non-nullable foreign keys + prisma.account.delete({ + where: { + user_id, + }, + }), + */ + prisma.$queryRaw`delete from account where user_id=${user_id}`, + ); +} + +export async function createAccount(data) { + return runQuery( + prisma.account.create({ + data, + }), + ); +} + +export function getMetrics(website_id, start_at, end_at) { const db = getDatabase(); if (db === POSTGRESQL) { @@ -61,7 +271,14 @@ export function getMetricsQuery(prisma, { website_id, start_at, end_at }) { return Promise.resolve({}); } -export function getPageviewsQuery(prisma, { website_id, start_at, end_at, unit, timezone, count }) { +export function getPageviews( + website_id, + start_at, + end_at, + timezone = 'utc', + unit = 'day', + count = '*', +) { const db = getDatabase(); if (db === POSTGRESQL) { @@ -102,7 +319,7 @@ export function getPageviewsQuery(prisma, { website_id, start_at, end_at, unit, return Promise.resolve([]); } -export function getRankingsQuery(prisma, { website_id, start_at, end_at, type, table }) { +export function getRankings(website_id, start_at, end_at, type, table) { const db = getDatabase(); if (db === POSTGRESQL) { diff --git a/lib/session.js b/lib/session.js index 696d2bed..940decd9 100644 --- a/lib/session.js +++ b/lib/session.js @@ -1,4 +1,4 @@ -import { getWebsite, getSession, createSession } from 'lib/db'; +import { getWebsiteByUuid, getSessionByUuid, createSession } from 'lib/queries'; import { getClientInfo } from 'lib/request'; import { uuid, isValidId, parseToken } from 'lib/crypto'; @@ -19,7 +19,7 @@ export async function verifySession(req) { if (!token || token.website_uuid !== website_uuid) { const { userAgent, browser, os, ip, country, device } = await getClientInfo(req, payload); - const website = await getWebsite({ website_uuid }); + const website = await getWebsiteByUuid(website_uuid); if (!website) { throw new Error(`Website not found: ${website_uuid}`); @@ -28,7 +28,7 @@ export async function verifySession(req) { const { website_id } = website; const session_uuid = uuid(website_id, hostname, ip, userAgent, os); - let session = await getSession({ session_uuid }); + let session = await getSessionByUuid(session_uuid); if (!session) { session = await createSession(website_id, { diff --git a/pages/api/account.js b/pages/api/account.js index ef63607a..8fbf1e28 100644 --- a/pages/api/account.js +++ b/pages/api/account.js @@ -1,6 +1,6 @@ -import { getAccounts, getAccount, updateAccount, createAccount } from 'lib/db'; +import { getAccountById, getAccountByUsername, updateAccount, createAccount } from 'lib/queries'; import { useAuth } from 'lib/middleware'; -import { hashPassword, uuid } from 'lib/crypto'; +import { hashPassword } from 'lib/crypto'; import { ok, unauthorized, methodNotAllowed, badRequest } from 'lib/response'; export default async (req, res) => { @@ -8,24 +8,18 @@ export default async (req, res) => { const { user_id: current_user_id, is_admin: current_user_is_admin } = req.auth; - if (req.method === 'GET') { - if (current_user_is_admin) { - const accounts = await getAccounts(); - - return ok(res, accounts); - } - - return unauthorized(res); - } - if (req.method === 'POST') { const { user_id, username, password, is_admin } = req.body; if (user_id) { - const account = await getAccount({ user_id }); + const account = await getAccountById(user_id); if (account.user_id === current_user_id || current_user_is_admin) { - const data = { password: password ? await hashPassword(password) : undefined }; + const data = {}; + + if (password) { + data.password = await hashPassword(password); + } // Only admin can change these fields if (current_user_is_admin) { @@ -37,7 +31,7 @@ export default async (req, res) => { } if (data.username && account.username !== data.username) { - const accountByUsername = await getAccount({ username }); + const accountByUsername = await getAccountByUsername(username); if (accountByUsername) { return badRequest(res, 'Account already exists'); @@ -51,7 +45,7 @@ export default async (req, res) => { return unauthorized(res); } else { - const accountByUsername = await getAccount({ username }); + const accountByUsername = await getAccountByUsername(username); if (accountByUsername) { return badRequest(res, 'Account already exists'); diff --git a/pages/api/account/[id].js b/pages/api/account/[id].js index f9cfe0a2..b8fe2245 100644 --- a/pages/api/account/[id].js +++ b/pages/api/account/[id].js @@ -1,4 +1,4 @@ -import { getAccount, deleteAccount } from 'lib/db'; +import { getAccountById, deleteAccount } from 'lib/queries'; import { useAuth } from 'lib/middleware'; import { methodNotAllowed, ok, unauthorized } from 'lib/response'; @@ -11,7 +11,7 @@ export default async (req, res) => { if (req.method === 'GET') { if (is_admin) { - const account = await getAccount({ user_id }); + const account = await getAccountById(user_id); return ok(res, account); } diff --git a/pages/api/account/password.js b/pages/api/account/password.js index 8a7df5b9..32f87960 100644 --- a/pages/api/account/password.js +++ b/pages/api/account/password.js @@ -1,4 +1,4 @@ -import { getAccount, updateAccount } from 'lib/db'; +import { getAccountById, updateAccount } from 'lib/queries'; import { useAuth } from 'lib/middleware'; import { badRequest, methodNotAllowed, ok } from 'lib/response'; import { checkPassword, hashPassword } from 'lib/crypto'; @@ -10,7 +10,7 @@ export default async (req, res) => { const { current_password, new_password } = req.body; if (req.method === 'POST') { - const account = await getAccount({ user_id }); + const account = await getAccountById(user_id); const valid = await checkPassword(current_password, account.password); if (!valid) { diff --git a/pages/api/accounts.js b/pages/api/accounts.js new file mode 100644 index 00000000..c5a41dff --- /dev/null +++ b/pages/api/accounts.js @@ -0,0 +1,21 @@ +import { getAccounts } from 'lib/queries'; +import { useAuth } from 'lib/middleware'; +import { ok, unauthorized, methodNotAllowed } from 'lib/response'; + +export default async (req, res) => { + await useAuth(req, res); + + const { is_admin: current_user_is_admin } = req.auth; + + if (req.method === 'GET') { + if (current_user_is_admin) { + const accounts = await getAccounts(); + + return ok(res, accounts); + } + + return unauthorized(res); + } + + return methodNotAllowed(res); +}; diff --git a/pages/api/auth/login.js b/pages/api/auth/login.js index 2cf688f3..ce9474aa 100644 --- a/pages/api/auth/login.js +++ b/pages/api/auth/login.js @@ -1,13 +1,13 @@ import { serialize } from 'cookie'; import { checkPassword, createSecureToken } from 'lib/crypto'; -import { getAccount } from 'lib/db'; +import { getAccountByUsername } from 'lib/queries'; import { AUTH_COOKIE_NAME } from 'lib/constants'; import { ok, unauthorized } from 'lib/response'; export default async (req, res) => { const { username, password } = req.body; - const account = await getAccount({ username }); + const account = await getAccountByUsername(username); if (account && (await checkPassword(password, account.password))) { const { user_id, username, is_admin } = account; diff --git a/pages/api/collect.js b/pages/api/collect.js index 86d25b63..07e513d4 100644 --- a/pages/api/collect.js +++ b/pages/api/collect.js @@ -1,4 +1,4 @@ -import { savePageView, saveEvent } from 'lib/db'; +import { savePageView, saveEvent } from 'lib/queries'; import { useCors, useSession } from 'lib/middleware'; import { createToken } from 'lib/crypto'; import { ok, badRequest } from 'lib/response'; diff --git a/pages/api/website.js b/pages/api/website.js index 910d613c..9d3fa3ae 100644 --- a/pages/api/website.js +++ b/pages/api/website.js @@ -1,4 +1,4 @@ -import { getWebsites, updateWebsite, createWebsite, getWebsite } from 'lib/db'; +import { updateWebsite, createWebsite, getWebsiteById } from 'lib/queries'; import { useAuth } from 'lib/middleware'; import { uuid } from 'lib/crypto'; import { ok, unauthorized, methodNotAllowed } from 'lib/response'; @@ -9,17 +9,11 @@ export default async (req, res) => { const { user_id, is_admin } = req.auth; const { website_id } = req.body; - if (req.method === 'GET') { - const websites = await getWebsites(user_id); - - return ok(res, websites); - } - if (req.method === 'POST') { const { name, domain } = req.body; if (website_id) { - const website = getWebsite(website_id); + const website = getWebsiteById(website_id); if (website.user_id === user_id || is_admin) { await updateWebsite(website_id, { name, domain }); diff --git a/pages/api/website/[id]/index.js b/pages/api/website/[id]/index.js index ff1c219b..ac4c348c 100644 --- a/pages/api/website/[id]/index.js +++ b/pages/api/website/[id]/index.js @@ -1,4 +1,4 @@ -import { deleteWebsite, getWebsite } from 'lib/db'; +import { deleteWebsite, getWebsiteById } from 'lib/queries'; import { useAuth } from 'lib/middleware'; import { methodNotAllowed, ok, unauthorized } from 'lib/response'; @@ -10,13 +10,13 @@ export default async (req, res) => { const website_id = +id; if (req.method === 'GET') { - const website = await getWebsite({ website_id }); + const website = await getWebsiteById(website_id); return ok(res, website); } if (req.method === 'DELETE') { - const website = await getWebsite({ website_id }); + const website = await getWebsiteById(website_id); if (website.user_id === user_id || is_admin) { await deleteWebsite(website_id); diff --git a/pages/api/website/[id]/metrics.js b/pages/api/website/[id]/metrics.js index 5f4a43fe..3ed98764 100644 --- a/pages/api/website/[id]/metrics.js +++ b/pages/api/website/[id]/metrics.js @@ -1,4 +1,4 @@ -import { getMetrics } from 'lib/db'; +import { getMetrics } from 'lib/queries'; import { useAuth } from 'lib/middleware'; import { ok } from 'lib/response'; diff --git a/pages/api/website/[id]/pageviews.js b/pages/api/website/[id]/pageviews.js index 68311e3e..0aec91e9 100644 --- a/pages/api/website/[id]/pageviews.js +++ b/pages/api/website/[id]/pageviews.js @@ -1,5 +1,5 @@ import moment from 'moment-timezone'; -import { getPageviewData } from 'lib/db'; +import { getPageviews } from 'lib/queries'; import { useAuth } from 'lib/middleware'; import { ok, badRequest } from 'lib/response'; @@ -18,8 +18,8 @@ export default async (req, res) => { const end = new Date(+end_at); const [pageviews, uniques] = await Promise.all([ - getPageviewData(+id, start, end, tz, unit, '*'), - getPageviewData(+id, start, end, tz, unit, 'distinct session_id'), + getPageviews(+id, start, end, tz, unit, '*'), + getPageviews(+id, start, end, tz, unit, 'distinct session_id'), ]); return ok(res, { pageviews, uniques }); diff --git a/pages/api/website/[id]/rankings.js b/pages/api/website/[id]/rankings.js index aa58b359..20c4e7b5 100644 --- a/pages/api/website/[id]/rankings.js +++ b/pages/api/website/[id]/rankings.js @@ -1,4 +1,4 @@ -import { getRankings } from 'lib/db'; +import { getRankings } from 'lib/queries'; import { useAuth } from 'lib/middleware'; import { ok, badRequest } from 'lib/response'; diff --git a/pages/api/websites.js b/pages/api/websites.js new file mode 100644 index 00000000..af83c13e --- /dev/null +++ b/pages/api/websites.js @@ -0,0 +1,17 @@ +import { getUserWebsites } from 'lib/queries'; +import { useAuth } from 'lib/middleware'; +import { ok, methodNotAllowed } from 'lib/response'; + +export default async (req, res) => { + await useAuth(req, res); + + const { user_id } = req.auth; + + if (req.method === 'GET') { + const websites = await getUserWebsites(user_id); + + return ok(res, websites); + } + + return methodNotAllowed(res); +}; diff --git a/pages/login.js b/pages/login.js index 4c8228b9..cf976eca 100644 --- a/pages/login.js +++ b/pages/login.js @@ -1,13 +1,10 @@ import React from 'react'; import Layout from 'components/layout/Layout'; import LoginForm from 'components/forms/LoginForm'; -import Icon from 'components/common/Icon'; -import Logo from 'assets/logo.svg'; export default function LoginPage() { return ( - - } size="xlarge" /> + );