Autologin via `?hash=xxx` parameter in url
parent
2575cbfc11
commit
6bd01aaa45
|
@ -27,11 +27,25 @@ const validate = ({ username, password }) => {
|
|||
return errors;
|
||||
};
|
||||
|
||||
export default function LoginForm() {
|
||||
export default function LoginForm({ hash = null }) {
|
||||
const post = usePost();
|
||||
const router = useRouter();
|
||||
const [message, setMessage] = useState();
|
||||
|
||||
const handleAutologin = async ({ hash }) => {
|
||||
const autologin = await post('/api/auth/hash', {
|
||||
hash,
|
||||
});
|
||||
|
||||
if (autologin.ok) {
|
||||
return router.push('/');
|
||||
}
|
||||
};
|
||||
|
||||
if (hash) {
|
||||
handleAutologin({ hash });
|
||||
}
|
||||
|
||||
const handleSubmit = async ({ username, password }) => {
|
||||
const { ok, status, data } = await post('/api/auth/login', {
|
||||
username,
|
||||
|
|
|
@ -223,6 +223,16 @@ export async function getAccountById(user_id) {
|
|||
);
|
||||
}
|
||||
|
||||
export async function getAccountByHash(hash) {
|
||||
return runQuery(
|
||||
prisma.account.findUnique({
|
||||
where: {
|
||||
hash,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export async function getAccountByUsername(username) {
|
||||
return runQuery(
|
||||
prisma.account.findUnique({
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
import { serialize } from 'cookie';
|
||||
import { createSecureToken } from 'lib/crypto';
|
||||
import { getAccountByHash } from 'lib/queries';
|
||||
import { AUTH_COOKIE_NAME } from 'lib/constants';
|
||||
import { ok, unauthorized, badRequest } from 'lib/response';
|
||||
|
||||
export default async (req, res) => {
|
||||
const { hash } = req.body;
|
||||
|
||||
if (!hash) {
|
||||
return badRequest(res);
|
||||
}
|
||||
|
||||
const account = await getAccountByHash(hash);
|
||||
|
||||
if (account) {
|
||||
const { user_id, username, is_admin } = account;
|
||||
const token = await createSecureToken({ user_id, username, is_admin });
|
||||
const cookie = serialize(AUTH_COOKIE_NAME, token, {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
sameSite: true,
|
||||
maxAge: 60 * 60 * 24 * 365,
|
||||
});
|
||||
|
||||
res.setHeader('Set-Cookie', [cookie]);
|
||||
|
||||
return ok(res, { token });
|
||||
}
|
||||
|
||||
return unauthorized(res);
|
||||
};
|
|
@ -15,7 +15,7 @@ export default function DashboardPage() {
|
|||
}
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Layout header={false} footer={false}>
|
||||
<WebsiteList userId={userId} />
|
||||
</Layout>
|
||||
);
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
import React from 'react';
|
||||
import Layout from 'components/layout/Layout';
|
||||
import LoginForm from 'components/forms/LoginForm';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
export default function LoginPage() {
|
||||
const { query } = useRouter();
|
||||
return (
|
||||
<Layout title="login" header={false} footer={false} center>
|
||||
<LoginForm />
|
||||
<LoginForm hash={query.hash} />
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ export default function DetailsPage() {
|
|||
const [websiteId] = id;
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<Layout header={false} footer={false}>
|
||||
<WebsiteDetails websiteId={websiteId} />
|
||||
</Layout>
|
||||
);
|
||||
|
|
|
@ -11,6 +11,7 @@ model account {
|
|||
user_id Int @id @default(autoincrement()) @db.UnsignedInt
|
||||
username String @unique @db.VarChar(255)
|
||||
password String @db.VarChar(60)
|
||||
hash String @unique @db.VarChar(512)
|
||||
is_admin Boolean @default(false)
|
||||
created_at DateTime? @default(now()) @db.Timestamp(0)
|
||||
updated_at DateTime? @default(now()) @db.Timestamp(0)
|
||||
|
|
|
@ -11,6 +11,7 @@ model account {
|
|||
user_id Int @id @default(autoincrement())
|
||||
username String @unique @db.VarChar(255)
|
||||
password String @db.VarChar(60)
|
||||
hash String @unique @db.VarChar(512)
|
||||
is_admin Boolean @default(false)
|
||||
created_at DateTime? @default(now()) @db.Timestamptz(6)
|
||||
updated_at DateTime? @default(now()) @db.Timestamptz(6)
|
||||
|
|
Loading…
Reference in New Issue