mirror of
https://github.com/kremalicious/umami.git
synced 2024-11-15 09:45:04 +01:00
Merge branch 'dev' of https://github.com/umami-software/umami into dev
# Conflicts: # pages/api/account/index.js
This commit is contained in:
commit
d784b2a8db
@ -11,7 +11,7 @@ import useDateRange from 'hooks/useDateRange';
|
|||||||
function RefreshButton({ websiteId }) {
|
function RefreshButton({ websiteId }) {
|
||||||
const [dateRange] = useDateRange(websiteId);
|
const [dateRange] = useDateRange(websiteId);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const selector = useCallback(state => state[`/website/${websiteId}/stats`], [websiteId]);
|
const selector = useCallback(state => state[`/websites/${websiteId}/stats`], [websiteId]);
|
||||||
const completed = useStore(selector);
|
const completed = useStore(selector);
|
||||||
|
|
||||||
function handleClick() {
|
function handleClick() {
|
||||||
|
@ -34,7 +34,7 @@ export default function AccountEditForm({ values, onSave, onClose }) {
|
|||||||
|
|
||||||
const handleSubmit = async values => {
|
const handleSubmit = async values => {
|
||||||
const { user_id } = values;
|
const { user_id } = values;
|
||||||
const { ok, data } = await post(user_id ? `/account/${user_id}` : '/account', values);
|
const { ok, data } = await post(user_id ? `/accounts/${user_id}` : '/accounts', values);
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
onSave();
|
onSave();
|
||||||
|
@ -9,6 +9,7 @@ import FormLayout, {
|
|||||||
FormRow,
|
FormRow,
|
||||||
} from 'components/layout/FormLayout';
|
} from 'components/layout/FormLayout';
|
||||||
import useApi from 'hooks/useApi';
|
import useApi from 'hooks/useApi';
|
||||||
|
import useUser from '../../hooks/useUser';
|
||||||
|
|
||||||
const initialValues = {
|
const initialValues = {
|
||||||
current_password: '',
|
current_password: '',
|
||||||
@ -39,9 +40,10 @@ const validate = ({ current_password, new_password, confirm_password }) => {
|
|||||||
export default function ChangePasswordForm({ values, onSave, onClose }) {
|
export default function ChangePasswordForm({ values, onSave, onClose }) {
|
||||||
const { post } = useApi();
|
const { post } = useApi();
|
||||||
const [message, setMessage] = useState();
|
const [message, setMessage] = useState();
|
||||||
|
const { user } = useUser();
|
||||||
|
|
||||||
const handleSubmit = async values => {
|
const handleSubmit = async values => {
|
||||||
const { ok, data } = await post('/account/password', values);
|
const { ok, data } = await post(`/accounts/${user.user_id}/password`, values);
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
onSave();
|
onSave();
|
||||||
|
@ -38,7 +38,6 @@ const validate = ({ name, domain }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const OwnerDropDown = ({ user, accounts }) => {
|
const OwnerDropDown = ({ user, accounts }) => {
|
||||||
console.info(styles);
|
|
||||||
const { setFieldValue, values } = useFormikContext();
|
const { setFieldValue, values } = useFormikContext();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -79,7 +78,8 @@ export default function WebsiteEditForm({ values, onSave, onClose }) {
|
|||||||
const [message, setMessage] = useState();
|
const [message, setMessage] = useState();
|
||||||
|
|
||||||
const handleSubmit = async values => {
|
const handleSubmit = async values => {
|
||||||
const { ok, data } = await post('/website', values);
|
const { website_id } = values;
|
||||||
|
const { ok, data } = await post(website_id ? `/websites/${website_id}` : '/websites', values);
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
onSave();
|
onSave();
|
||||||
@ -137,6 +137,7 @@ export default function WebsiteEditForm({ values, onSave, onClose }) {
|
|||||||
defaultMessage="Enable share URL"
|
defaultMessage="Enable share URL"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
value={null}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Field>
|
</Field>
|
||||||
|
@ -6,7 +6,7 @@ import Dot from 'components/common/Dot';
|
|||||||
import styles from './ActiveUsers.module.css';
|
import styles from './ActiveUsers.module.css';
|
||||||
|
|
||||||
export default function ActiveUsers({ websiteId, className, value, interval = 60000 }) {
|
export default function ActiveUsers({ websiteId, className, value, interval = 60000 }) {
|
||||||
const url = websiteId ? `/website/${websiteId}/active` : null;
|
const url = websiteId ? `/websites/${websiteId}/active` : null;
|
||||||
const { data } = useFetch(url, {
|
const { data } = useFetch(url, {
|
||||||
interval,
|
interval,
|
||||||
});
|
});
|
||||||
|
@ -16,7 +16,7 @@ export default function EventsChart({ websiteId, className, token }) {
|
|||||||
} = usePageQuery();
|
} = usePageQuery();
|
||||||
|
|
||||||
const { data, loading } = useFetch(
|
const { data, loading } = useFetch(
|
||||||
`/website/${websiteId}/events`,
|
`/websites/${websiteId}/events`,
|
||||||
{
|
{
|
||||||
params: {
|
params: {
|
||||||
start_at: +startDate,
|
start_at: +startDate,
|
||||||
|
@ -19,7 +19,7 @@ export default function MetricsBar({ websiteId, className }) {
|
|||||||
} = usePageQuery();
|
} = usePageQuery();
|
||||||
|
|
||||||
const { data, error, loading } = useFetch(
|
const { data, error, loading } = useFetch(
|
||||||
`/website/${websiteId}/stats`,
|
`/websites/${websiteId}/stats`,
|
||||||
{
|
{
|
||||||
params: {
|
params: {
|
||||||
start_at: +startDate,
|
start_at: +startDate,
|
||||||
|
@ -38,7 +38,7 @@ export default function MetricsTable({
|
|||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
const { data, loading, error } = useFetch(
|
const { data, loading, error } = useFetch(
|
||||||
`/website/${websiteId}/metrics`,
|
`/websites/${websiteId}/metrics`,
|
||||||
{
|
{
|
||||||
params: {
|
params: {
|
||||||
type,
|
type,
|
||||||
|
@ -35,7 +35,7 @@ export default function WebsiteChart({
|
|||||||
const { get } = useApi();
|
const { get } = useApi();
|
||||||
|
|
||||||
const { data, loading, error } = useFetch(
|
const { data, loading, error } = useFetch(
|
||||||
`/website/${websiteId}/pageviews`,
|
`/websites/${websiteId}/pageviews`,
|
||||||
{
|
{
|
||||||
params: {
|
params: {
|
||||||
start_at: +startDate,
|
start_at: +startDate,
|
||||||
@ -70,7 +70,7 @@ export default function WebsiteChart({
|
|||||||
|
|
||||||
async function handleDateChange(value) {
|
async function handleDateChange(value) {
|
||||||
if (value === 'all') {
|
if (value === 'all') {
|
||||||
const { data, ok } = await get(`/website/${websiteId}`);
|
const { data, ok } = await get(`/websites/${websiteId}`);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
setDateRange({ value, ...getDateRangeValues(new Date(data.created_at), Date.now()) });
|
setDateRange({ value, ...getDateRangeValues(new Date(data.created_at), Date.now()) });
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@ export default function WebsiteHeader({ websiteId, title, domain, showLink = fal
|
|||||||
<Favicon domain={domain} />
|
<Favicon domain={domain} />
|
||||||
<Link
|
<Link
|
||||||
className={styles.titleLink}
|
className={styles.titleLink}
|
||||||
href="/website/[...id]"
|
href="/websites/[...id]"
|
||||||
as={`/website/${websiteId}/${title}`}
|
as={`/websites/${websiteId}/${title}`}
|
||||||
>
|
>
|
||||||
<OverflowText tooltipId={`${websiteId}-title`}>{title}</OverflowText>
|
<OverflowText tooltipId={`${websiteId}-title`}>{title}</OverflowText>
|
||||||
</Link>
|
</Link>
|
||||||
@ -41,8 +41,8 @@ export default function WebsiteHeader({ websiteId, title, domain, showLink = fal
|
|||||||
<RefreshButton websiteId={websiteId} />
|
<RefreshButton websiteId={websiteId} />
|
||||||
{showLink && (
|
{showLink && (
|
||||||
<Link
|
<Link
|
||||||
href="/website/[...id]"
|
href="/websites/[...id]"
|
||||||
as={`/website/${websiteId}/${title}`}
|
as={`/websites/${websiteId}/${title}`}
|
||||||
className={styles.link}
|
className={styles.link}
|
||||||
icon={<Arrow />}
|
icon={<Arrow />}
|
||||||
size="small"
|
size="small"
|
||||||
|
@ -52,7 +52,7 @@ const views = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function WebsiteDetails({ websiteId }) {
|
export default function WebsiteDetails({ websiteId }) {
|
||||||
const { data } = useFetch(`/website/${websiteId}`);
|
const { data } = useFetch(`/websites/${websiteId}`);
|
||||||
const [chartLoaded, setChartLoaded] = useState(false);
|
const [chartLoaded, setChartLoaded] = useState(false);
|
||||||
const [countryData, setCountryData] = useState();
|
const [countryData, setCountryData] = useState();
|
||||||
const [eventsData, setEventsData] = useState();
|
const [eventsData, setEventsData] = useState();
|
||||||
|
@ -86,8 +86,8 @@ export default function WebsiteSettings() {
|
|||||||
const DetailsLink = ({ website_id, name, domain }) => (
|
const DetailsLink = ({ website_id, name, domain }) => (
|
||||||
<Link
|
<Link
|
||||||
className={styles.detailLink}
|
className={styles.detailLink}
|
||||||
href="/website/[...id]"
|
href="/websites/[...id]"
|
||||||
as={`/website/${website_id}/${name}`}
|
as={`/websites/${website_id}/${name}`}
|
||||||
>
|
>
|
||||||
<Favicon domain={domain} />
|
<Favicon domain={domain} />
|
||||||
<OverflowText tooltipId={`${website_id}-name`}>{name}</OverflowText>
|
<OverflowText tooltipId={`${website_id}-name`}>{name}</OverflowText>
|
||||||
|
11
db/mysql/migrations/04_account_uuid/migration.sql
Normal file
11
db/mysql/migrations/04_account_uuid/migration.sql
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE `account` ADD COLUMN `account_uuid` VARCHAR(36);
|
||||||
|
|
||||||
|
-- Backfill UUID
|
||||||
|
UPDATE `account` SET account_uuid=(SELECT uuid());
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE `account` MODIFY `account_uuid` VARCHAR(36) NOT NULL;
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX `account_account_uuid_key` ON `account`(`account_uuid`);
|
@ -14,6 +14,7 @@ model account {
|
|||||||
is_admin Boolean @default(false)
|
is_admin Boolean @default(false)
|
||||||
created_at DateTime? @default(now()) @db.Timestamp(0)
|
created_at DateTime? @default(now()) @db.Timestamp(0)
|
||||||
updated_at DateTime? @default(now()) @db.Timestamp(0)
|
updated_at DateTime? @default(now()) @db.Timestamp(0)
|
||||||
|
account_uuid String @unique() @db.VarChar(36)
|
||||||
website website[]
|
website website[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
db/postgresql/migrations/04_account_uuid/migration.sql
Normal file
12
db/postgresql/migrations/04_account_uuid/migration.sql
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "account" ADD COLUMN "account_uuid" UUID NULL;
|
||||||
|
|
||||||
|
-- Backfill UUID
|
||||||
|
UPDATE "account" SET account_uuid = gen_random_uuid();
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "account" ALTER COLUMN "account_uuid" SET NOT NULL;
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "account_account_uuid_key" ON "account"("account_uuid");
|
@ -14,6 +14,7 @@ model account {
|
|||||||
is_admin Boolean @default(false)
|
is_admin Boolean @default(false)
|
||||||
created_at DateTime? @default(now()) @db.Timestamptz(6)
|
created_at DateTime? @default(now()) @db.Timestamptz(6)
|
||||||
updated_at DateTime? @default(now()) @db.Timestamptz(6)
|
updated_at DateTime? @default(now()) @db.Timestamptz(6)
|
||||||
|
account_uuid String @unique @db.Uuid
|
||||||
website website[]
|
website website[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,27 +0,0 @@
|
|||||||
import { ok, unauthorized, methodNotAllowed, badRequest, hashPassword } from 'next-basics';
|
|
||||||
import { getAccountByUsername, createAccount } from 'queries';
|
|
||||||
import { useAuth } from 'lib/middleware';
|
|
||||||
|
|
||||||
export default async (req, res) => {
|
|
||||||
if (req.method === 'POST') {
|
|
||||||
await useAuth(req, res);
|
|
||||||
|
|
||||||
if (!req.auth.is_admin) {
|
|
||||||
return unauthorized(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
const { username, password } = req.body;
|
|
||||||
|
|
||||||
const accountByUsername = await getAccountByUsername(username);
|
|
||||||
|
|
||||||
if (accountByUsername) {
|
|
||||||
return badRequest(res, 'Account already exists');
|
|
||||||
}
|
|
||||||
|
|
||||||
const created = await createAccount({ username, password: hashPassword(password) });
|
|
||||||
|
|
||||||
return ok(res, created);
|
|
||||||
}
|
|
||||||
|
|
||||||
return methodNotAllowed(res);
|
|
||||||
};
|
|
@ -12,24 +12,25 @@ import {
|
|||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
await useAuth(req, res);
|
await useAuth(req, res);
|
||||||
|
|
||||||
const { user_id: auth_user_id, is_admin } = req.auth;
|
const { user_id: currentUserId, is_admin: currentUserIsAdmin } = req.auth;
|
||||||
const { user_id, current_password, new_password } = req.body;
|
const { current_password, new_password } = req.body;
|
||||||
|
const { id } = req.query;
|
||||||
|
const userId = +id;
|
||||||
|
|
||||||
if (!is_admin && user_id !== auth_user_id) {
|
if (!currentUserIsAdmin && userId !== currentUserId) {
|
||||||
return unauthorized(res);
|
return unauthorized(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.method === 'POST') {
|
if (req.method === 'POST') {
|
||||||
const account = await getAccountById(user_id);
|
const account = await getAccountById(userId);
|
||||||
const valid = checkPassword(current_password, account.password);
|
|
||||||
|
|
||||||
if (!valid) {
|
if (!checkPassword(current_password, account.password)) {
|
||||||
return badRequest(res, 'Current password is incorrect');
|
return badRequest(res, 'Current password is incorrect');
|
||||||
}
|
}
|
||||||
|
|
||||||
const password = hashPassword(new_password);
|
const password = hashPassword(new_password);
|
||||||
|
|
||||||
const updated = await updateAccount(user_id, { password });
|
const updated = await updateAccount(userId, { password });
|
||||||
|
|
||||||
return ok(res, updated);
|
return ok(res, updated);
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import { getAccounts } from 'queries';
|
import { ok, unauthorized, methodNotAllowed, badRequest, hashPassword } from 'next-basics';
|
||||||
import { useAuth } from 'lib/middleware';
|
import { useAuth } from 'lib/middleware';
|
||||||
import { ok, unauthorized, methodNotAllowed } from 'next-basics';
|
import { uuid } from 'lib/crypto';
|
||||||
|
import { createAccount, getAccountByUsername, getAccounts } from 'queries';
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
await useAuth(req, res);
|
await useAuth(req, res);
|
||||||
@ -17,5 +18,29 @@ export default async (req, res) => {
|
|||||||
return ok(res, accounts);
|
return ok(res, accounts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (req.method === 'POST') {
|
||||||
|
await useAuth(req, res);
|
||||||
|
|
||||||
|
if (!req.auth.is_admin) {
|
||||||
|
return unauthorized(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
const { username, password } = req.body;
|
||||||
|
|
||||||
|
const accountByUsername = await getAccountByUsername(username);
|
||||||
|
|
||||||
|
if (accountByUsername) {
|
||||||
|
return badRequest(res, 'Account already exists');
|
||||||
|
}
|
||||||
|
|
||||||
|
const created = await createAccount({
|
||||||
|
username,
|
||||||
|
password: hashPassword(password),
|
||||||
|
account_uuid: uuid(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return ok(res, created);
|
||||||
|
}
|
||||||
|
|
||||||
return methodNotAllowed(res);
|
return methodNotAllowed(res);
|
||||||
};
|
};
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
import { methodNotAllowed, ok, unauthorized } from 'next-basics';
|
|
||||||
import { deleteWebsite, getWebsiteById } from 'queries';
|
|
||||||
import { allowQuery } from 'lib/auth';
|
|
||||||
import { useCors } from 'lib/middleware';
|
|
||||||
|
|
||||||
export default async (req, res) => {
|
|
||||||
const { id } = req.query;
|
|
||||||
|
|
||||||
const websiteId = +id;
|
|
||||||
|
|
||||||
if (req.method === 'GET') {
|
|
||||||
await useCors(req, res);
|
|
||||||
|
|
||||||
if (!(await allowQuery(req))) {
|
|
||||||
return unauthorized(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
const website = await getWebsiteById(websiteId);
|
|
||||||
|
|
||||||
return ok(res, website);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req.method === 'DELETE') {
|
|
||||||
if (!(await allowQuery(req, true))) {
|
|
||||||
return unauthorized(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
await deleteWebsite(websiteId);
|
|
||||||
|
|
||||||
return ok(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
return methodNotAllowed(res);
|
|
||||||
};
|
|
@ -1,44 +0,0 @@
|
|||||||
import { ok, unauthorized, methodNotAllowed, getRandomChars } from 'next-basics';
|
|
||||||
import { updateWebsite, createWebsite, getWebsiteById } from 'queries';
|
|
||||||
import { useAuth } from 'lib/middleware';
|
|
||||||
import { uuid } from 'lib/crypto';
|
|
||||||
|
|
||||||
export default async (req, res) => {
|
|
||||||
await useAuth(req, res);
|
|
||||||
|
|
||||||
const { user_id, is_admin } = req.auth;
|
|
||||||
const { website_id, enable_share_url } = req.body;
|
|
||||||
|
|
||||||
if (req.method === 'POST') {
|
|
||||||
const { name, domain, owner } = req.body;
|
|
||||||
const website_owner = parseInt(owner);
|
|
||||||
|
|
||||||
if (website_id) {
|
|
||||||
const website = await getWebsiteById(website_id);
|
|
||||||
|
|
||||||
if (website.user_id !== user_id && !is_admin) {
|
|
||||||
return unauthorized(res);
|
|
||||||
}
|
|
||||||
|
|
||||||
let { share_id } = website;
|
|
||||||
|
|
||||||
if (enable_share_url) {
|
|
||||||
share_id = share_id ? share_id : getRandomChars(8);
|
|
||||||
} else {
|
|
||||||
share_id = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
await updateWebsite(website_id, { name, domain, share_id, user_id: website_owner });
|
|
||||||
|
|
||||||
return ok(res);
|
|
||||||
} else {
|
|
||||||
const website_uuid = uuid();
|
|
||||||
const share_id = enable_share_url ? getRandomChars(8) : null;
|
|
||||||
const website = await createWebsite(website_owner, { website_uuid, name, domain, share_id });
|
|
||||||
|
|
||||||
return ok(res, website);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return methodNotAllowed(res);
|
|
||||||
};
|
|
59
pages/api/websites/[id]/index.js
Normal file
59
pages/api/websites/[id]/index.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { getRandomChars, methodNotAllowed, ok, unauthorized } from 'next-basics';
|
||||||
|
import { deleteWebsite, getWebsiteById, updateWebsite } from 'queries';
|
||||||
|
import { allowQuery } from 'lib/auth';
|
||||||
|
import { useAuth, useCors } from 'lib/middleware';
|
||||||
|
|
||||||
|
export default async (req, res) => {
|
||||||
|
const { id } = req.query;
|
||||||
|
|
||||||
|
const websiteId = +id;
|
||||||
|
|
||||||
|
if (req.method === 'GET') {
|
||||||
|
await useCors(req, res);
|
||||||
|
|
||||||
|
if (!(await allowQuery(req))) {
|
||||||
|
return unauthorized(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
const website = await getWebsiteById(websiteId);
|
||||||
|
|
||||||
|
return ok(res, website);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.method === 'POST') {
|
||||||
|
await useAuth(req, res);
|
||||||
|
|
||||||
|
const { is_admin: currentUserIsAdmin, user_id: currentUserId } = req.auth;
|
||||||
|
const { name, domain, owner, enable_share_url } = req.body;
|
||||||
|
|
||||||
|
const website = await getWebsiteById(websiteId);
|
||||||
|
|
||||||
|
if (website.user_id !== currentUserId && !currentUserIsAdmin) {
|
||||||
|
return unauthorized(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
let { share_id } = website;
|
||||||
|
|
||||||
|
if (enable_share_url) {
|
||||||
|
share_id = share_id ? share_id : getRandomChars(8);
|
||||||
|
} else {
|
||||||
|
share_id = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
await updateWebsite(websiteId, { name, domain, share_id, user_id: +owner });
|
||||||
|
|
||||||
|
return ok(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.method === 'DELETE') {
|
||||||
|
if (!(await allowQuery(req, true))) {
|
||||||
|
return unauthorized(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
await deleteWebsite(websiteId);
|
||||||
|
|
||||||
|
return ok(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
return methodNotAllowed(res);
|
||||||
|
};
|
@ -1,6 +1,7 @@
|
|||||||
import { getAllWebsites, getUserWebsites } from 'queries';
|
import { createWebsite, getAllWebsites, getUserWebsites } from 'queries';
|
||||||
|
import { ok, methodNotAllowed, unauthorized, getRandomChars } from 'next-basics';
|
||||||
import { useAuth } from 'lib/middleware';
|
import { useAuth } from 'lib/middleware';
|
||||||
import { ok, methodNotAllowed, unauthorized } from 'next-basics';
|
import { uuid } from 'lib/crypto';
|
||||||
|
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
await useAuth(req, res);
|
await useAuth(req, res);
|
||||||
@ -22,5 +23,24 @@ export default async (req, res) => {
|
|||||||
return ok(res, websites);
|
return ok(res, websites);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (req.method === 'POST') {
|
||||||
|
await useAuth(req, res);
|
||||||
|
|
||||||
|
const { is_admin: currentUserIsAdmin, user_id: currentUserId } = req.auth;
|
||||||
|
const { name, domain, owner, enable_share_url } = req.body;
|
||||||
|
|
||||||
|
const website_owner = +owner;
|
||||||
|
|
||||||
|
if (website_owner !== currentUserId && !currentUserIsAdmin) {
|
||||||
|
return unauthorized(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
const website_uuid = uuid();
|
||||||
|
const share_id = enable_share_url ? getRandomChars(8) : null;
|
||||||
|
const website = await createWebsite(website_owner, { website_uuid, name, domain, share_id });
|
||||||
|
|
||||||
|
return ok(res, website);
|
||||||
|
}
|
||||||
|
|
||||||
return methodNotAllowed(res);
|
return methodNotAllowed(res);
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
require('dotenv').config();
|
require('dotenv').config();
|
||||||
const { PrismaClient } = require('@prisma/client');
|
const { PrismaClient } = require('@prisma/client');
|
||||||
const chalk = require('chalk');
|
const chalk = require('chalk');
|
||||||
@ -39,7 +40,7 @@ async function checkConnection() {
|
|||||||
|
|
||||||
async function checkTables() {
|
async function checkTables() {
|
||||||
try {
|
try {
|
||||||
await prisma.account.findFirst();
|
await prisma.$queryRaw`select * from account limit 1`;
|
||||||
|
|
||||||
success('Database tables found.');
|
success('Database tables found.');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
Loading…
Reference in New Issue
Block a user