Skip to content

Commit

Permalink
feat: implement login & logout logic (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
yuler authored Sep 28, 2023
1 parent 0533d0a commit a9f809e
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 9 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@ jobs:
- name: Use Node.js from `.nvmrc`
uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
node-version-file: .nvmrc
# cache: 'pnpm'

- name: Install dependencies & Build
run: |
corepack enable
pnpm install
pnpm run --if-present build
- name: Run ESLint
run: pnpm run lint

- name: Run tests
run: pnpm run --if-present test
4 changes: 2 additions & 2 deletions commitlint.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export default {
extends: ['@commitlint/config-conventional']
}
extends: ['@commitlint/config-conventional'],
}
7 changes: 7 additions & 0 deletions composables/useSessionUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,15 @@ export function useSessionUser() {
return user
}

async function logout(path = '/') {
await $client.protected.logout.mutate()
user.value = null
await navigateTo(path)
}

return {
init,
user,
logout,
}
}
6 changes: 5 additions & 1 deletion pages/dashboard.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup>
const { user } = useSessionUser()
const { user, logout } = useSessionUser()
</script>

<template>
Expand All @@ -10,4 +10,8 @@ const { user } = useSessionUser()
{{ n }}
</NuxtLink>
</div>

<UButton color="red" @click="logout()">
退出
</UButton>
</template>
13 changes: 11 additions & 2 deletions pages/login.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,26 @@ const { $client } = useNuxtApp()
const route = useRoute()
const toast = useToast()
// Check if user is logged in
onMounted(() => {
const { user } = useSessionUser()
if (user.value) {
// TODO: Wrap a utils function
const r = route.query.r as string
navigateTo(decodeURIComponent(r || '/dashboard'))
}
})
// Form
const schema = z.object({
email: z.string(),
password: z.string(),
})
type Schema = z.output<typeof schema>
const state = ref({
email: '[email protected]',
password: 'apibeer',
})
const form = ref<Form<Schema>>()
const submiting = ref(false)
async function onSubmit(event: FormSubmitEvent<Schema>) {
Expand Down
4 changes: 2 additions & 2 deletions prisma/seed.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable no-console */
import process from 'node:process'
import bcrypt from 'bcryptjs'
import { hash } from '~/server/utils/password'
import { prisma } from '~/server/utils/prisma'

async function seed() {
Expand All @@ -20,7 +20,7 @@ async function seedUsers() {
email: '[email protected]',
username: 'apibeer',
password: {
create: { hash: await bcrypt.hash('123456', 10) },
create: { hash: await hash('123456') },
},
},
})
Expand Down
4 changes: 4 additions & 0 deletions server/trpc/routers/protected.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ export const protectedRouter = router({
const user = event.ctx.session.data.user
return user
}),
logout: protectedProcedure
.mutation(async (event) => {
await event.ctx.session.clear()
}),
})
6 changes: 6 additions & 0 deletions server/trpc/routers/public.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { z } from 'zod'
import { publicProcedure, router } from '../trpc'
import { verify } from '~/server/utils/password'

export const publicRouter = router({
login: publicProcedure
Expand All @@ -20,13 +21,18 @@ export const publicRouter = router({
id: true,
email: true,
username: true,
password: { select: { hash: true } },
},
})

// TODO: Wrap unified error
if (!user)
throw new Error('invalid credentials')

// TODO: Skip some env like: (DEMO, Development)
if (!await verify(input.password, user.password!.hash))
throw new Error('invalid credentials')

// Storge session
await ctx.session.update({ user })

Expand Down
20 changes: 20 additions & 0 deletions server/utils/password.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import bcrypt from 'bcryptjs'

/**
* Hashes a raw password using bcrypt.
* @param raw The raw password to hash.
* @returns A Promise that resolves to the hashed password.
*/
export async function hash(raw: string) {
return await bcrypt.hash(raw, 10)
}

/**
* Verifies a raw password against a hashed password using bcrypt.
* @param raw The raw password to verify.
* @param hash The hashed password to compare against.
* @returns A Promise that resolves to a boolean indicating whether the passwords match.
*/
export async function verify(raw: string, hash: string) {
return await bcrypt.compare(raw, hash)
}

0 comments on commit a9f809e

Please sign in to comment.