Skip to content

Commit

Permalink
Merge pull request #23 from samuliasmala/antti/login
Browse files Browse the repository at this point in the history
Valmis, mergetään!
  • Loading branch information
anttiasmala authored May 17, 2024
2 parents cf2d4dc + 57a8e30 commit cece9d9
Show file tree
Hide file tree
Showing 33 changed files with 3,123 additions and 1,248 deletions.
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1 +1 @@
DATABASE_URL="postgresql://databaseusername:databasepassword@localhost:5432/mydb?schema=public"
DATABASE_URL="postgresql://databaseusername:databasepassword@localhost:5432/mydb?schema=public" # README.md's section "Setting the environment variables" will help with this
72 changes: 72 additions & 0 deletions backend/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { PrismaAdapter } from '@lucia-auth/adapter-prisma';
import type { IncomingMessage, ServerResponse } from 'http';
import { Lucia, TimeSpan } from 'lucia';
import prisma from '~/prisma';
import type { PrismaUser, User } from '~/shared/types';
import type { Session, User as LuciaUser } from 'lucia';

export const adapter = new PrismaAdapter(prisma.session, prisma.user);

export const lucia = new Lucia(adapter, {
sessionExpiresIn: new TimeSpan(1, 'h'),
sessionCookie: {
attributes: {
secure: process.env.NODE_ENV === 'production',
},
},
getUserAttributes(user): User {
const { uuid, firstName, lastName, email, createdAt, updatedAt } = user;
return { uuid, firstName, lastName, email, createdAt, updatedAt };
},
});

export const luciaLongSession = new Lucia(adapter, {
sessionExpiresIn: new TimeSpan(30, 'd'),
sessionCookie: {
attributes: {
secure: process.env.NODE_ENV === 'production',
},
},
getUserAttributes(user): User {
const { uuid, firstName, lastName, email, createdAt, updatedAt } = user;
return { uuid, firstName, lastName, email, createdAt, updatedAt };
},
});

declare module 'lucia' {
interface Register {
Lucia: typeof lucia;
DatabaseUserAttributes: PrismaUser;
DatabaseSessionAttributes: { userUUID: string };
}
}

export async function validateRequest(
req: IncomingMessage,
res: ServerResponse,
): Promise<
{ user: LuciaUser; session: Session } | { user: null; session: null }
> {
const sessionId = lucia.readSessionCookie(req.headers.cookie ?? '');
if (!sessionId) {
return {
user: null,
session: null,
};
}
const result = await lucia.validateSession(sessionId);
if (result.session && result.session.fresh) {
res.appendHeader(
'Set-Cookie',
lucia.createSessionCookie(result.session.id).serialize(),
);
}
if (!result.session) {
res.appendHeader(
'Set-Cookie',
lucia.createBlankSessionCookie().serialize(),
);
}

return result;
}
15 changes: 15 additions & 0 deletions backend/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { compare as bcryptCompare, hash } from 'bcrypt';

export async function verifyPassword(
givenPassword: string,
hashedPassword: string,
): Promise<boolean> {
const isMatch = await bcryptCompare(givenPassword, hashedPassword);
return isMatch;
}

export async function hashPassword(password: string): Promise<string> {
const saltRounds = 10;
const hashedPassword = await hash(password, saltRounds);
return hashedPassword;
}
20 changes: 20 additions & 0 deletions icons/arrow_right_start_on_rectangle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { SVGProps } from 'react';

const SvgArrowRightStartOnRectangle = (props: SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
stroke="currentColor"
strokeWidth={1.5}
className="arrow-right-start-on-rectangle_svg__w-6 arrow-right-start-on-rectangle_svg__h-6"
viewBox="0 0 24 24"
{...props}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15.75 9V5.25A2.25 2.25 0 0 0 13.5 3h-6a2.25 2.25 0 0 0-2.25 2.25v13.5A2.25 2.25 0 0 0 7.5 21h6a2.25 2.25 0 0 0 2.25-2.25V15m3 0 3-3m0 0-3-3m3 3H9"
/>
</svg>
);
export default SvgArrowRightStartOnRectangle;
25 changes: 25 additions & 0 deletions icons/eye_open.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { SVGProps } from 'react';

const SvgEyeOpen = (props: SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
stroke="currentColor"
strokeWidth={1.5}
className="eye_open_svg__w-6 eye_open_svg__h-6"
viewBox="0 0 24 24"
{...props}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M2.036 12.322a1 1 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z"
/>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0"
/>
</svg>
);
export default SvgEyeOpen;
20 changes: 20 additions & 0 deletions icons/eye_slash.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { SVGProps } from 'react';

const SvgEyeSlash = (props: SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
stroke="currentColor"
strokeWidth={1.5}
className="eye_slash_svg__w-6 eye_slash_svg__h-6"
viewBox="0 0 24 24"
{...props}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M3.98 8.223A10.5 10.5 0 0 0 1.934 12c1.292 4.338 5.31 7.5 10.066 7.5.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0 1 12 4.5c4.756 0 8.773 3.162 10.065 7.498a10.52 10.52 0 0 1-4.293 5.774M6.228 6.228 3 3m3.228 3.228 3.65 3.65m7.894 7.894L21 21m-3.228-3.228-3.65-3.65m0 0a3 3 0 1 0-4.243-4.243m4.242 4.242L9.88 9.88"
/>
</svg>
);
export default SvgEyeSlash;
4 changes: 4 additions & 0 deletions icons/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { default as ArrowRightStartOnRectangle } from './arrow_right_start_on_rectangle';
export { default as EyeOpen } from './eye_open';
export { default as EyeSlash } from './eye_slash';
export { default as User } from './user';
20 changes: 20 additions & 0 deletions icons/user.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { SVGProps } from 'react';

const SvgUser = (props: SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
stroke="currentColor"
strokeWidth={1.5}
className="user_svg__w-6 user_svg__h-6"
viewBox="0 0 24 24"
{...props}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0M4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.9 17.9 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632"
/>
</svg>
);
export default SvgUser;
21 changes: 21 additions & 0 deletions middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { verifyRequestOrigin } from 'lucia';
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';

//eslint-disable-next-line
export async function middleware(req: NextRequest): Promise<NextResponse> {
if (req.method === 'GET') {
return NextResponse.next();
}
const originHeader = req.headers.get('Origin');
const hostHeader = req.headers.get('Host');

if (
!originHeader ||
!hostHeader ||
!verifyRequestOrigin(originHeader, [hostHeader])
) {
return new NextResponse(null, { status: 403 });
}
return NextResponse.next();
}
Loading

0 comments on commit cece9d9

Please sign in to comment.