Skip to content

Commit

Permalink
feat: support resource token
Browse files Browse the repository at this point in the history
  • Loading branch information
JingBh committed Sep 6, 2024
1 parent 6052209 commit 93af4b6
Show file tree
Hide file tree
Showing 11 changed files with 112 additions and 49 deletions.
3 changes: 1 addition & 2 deletions src/components/PaginatedList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { watchThrottled } from '@vueuse/core'
import type { ListInstance } from 'vant'
import { useAxiosInstance } from '../lib/axios.ts'
import type { CursorPagination } from '../types/pagination.ts'
import type { CursorPagination } from '../types/misc.ts'
const props = defineProps<{
modelValue: T[]
Expand Down Expand Up @@ -37,7 +37,6 @@ const onLoad = (): void => {
}
}).then(({ data }) => {
emit('update:modelValue', [
...(data.pinned ?? []),
...props.modelValue,
...data.data
])
Expand Down
2 changes: 2 additions & 0 deletions src/lib/axios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export const useAxiosInstance = (): AxiosInstance => {

if (store.token) {
config.headers.Authorization = `Bearer ${store.token}`
} else if (store.tokenSecondary) {
config.headers.Authorization = `Bearer ${store.tokenSecondary}`
}

return config
Expand Down
11 changes: 7 additions & 4 deletions src/lib/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,7 @@ const routes: RouteRecordRaw[] = [
path: '/questions/:id',
component: QuestionShow,
meta: {
title: '反馈详情',
auth: true
title: '反馈详情'
}
},
{
Expand Down Expand Up @@ -167,8 +166,7 @@ const routes: RouteRecordRaw[] = [
history: true
},
meta: {
title: '我的反馈历史',
auth: true
title: '我的反馈历史'
}
},
{
Expand Down Expand Up @@ -205,6 +203,11 @@ router.beforeEach(async () => {
store.logout()
}

if (store.tokenSecondary && store.tokenSecondaryExpiry !== -1 && store.tokenSecondaryExpiry < Date.now()) {
// token expired
store.logoutSecondary()
}

if (store.token && !store.user) {
await store.fetchUser()
}
Expand Down
46 changes: 33 additions & 13 deletions src/lib/store.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { computed, ref } from 'vue'
import { defineStore } from 'pinia'
import { useLocalStorage } from '@vueuse/core'
import { useAxios } from '@vueuse/integrations/useAxios'
import { showToast } from 'vant'

import { useAxiosInstance } from './axios.ts'
Expand All @@ -11,30 +12,46 @@ export const useStore = defineStore('app', () => {
const isWeixin = ref<boolean>(browsers.isWeixin())

const token = useLocalStorage('token', '')

const tokenExpiry = useLocalStorage('token_expiry', -1)

const user = ref<User | null>(null)
const roles = ref<string[]>([])
const tokenSecondary = useLocalStorage('token_secondary', '')

const loggedIn = computed<boolean>(() => !!user.value)
const isAdmin = computed<boolean>(() => roles.value.includes('ADMIN'))
const tokenSecondaryExpiry = useLocalStorage('token_secondary_expiry', -1)

const fetchUser = async (): Promise<void> => {
try {
const { data } = await useAxiosInstance().get<UserPrincipal>('user')
user.value = data.user
roles.value = data.authorities.map((auth) => auth.authority)
} catch (e) {
const {
data: userPrincipal,
execute: fetchUser
} = useAxios<UserPrincipal>('user', useAxiosInstance(), {
immediate: false,
initialData: null,
onError: (e) => {
console.error(e)
showToast('加载用户信息失败')
}
}
})

const user = computed<User | null>(() => {
return userPrincipal.value?.user ?? null
})

const roles = computed<string[]>(() => {
return userPrincipal.value?.authorities.map((auth) => auth.authority) ?? []
})

const loggedIn = computed<boolean>(() => !!userPrincipal.value)

const isAdmin = computed<boolean>(() => roles.value.includes('ADMIN'))

const logout = (): void => {
token.value = ''
tokenExpiry.value = -1
user.value = null
roles.value = []
userPrincipal.value = undefined
}

const logoutSecondary = (): void => {
tokenSecondary.value = ''
tokenSecondaryExpiry.value = -1
}

return {
Expand All @@ -43,9 +60,12 @@ export const useStore = defineStore('app', () => {
isWeixin,
loggedIn,
logout,
logoutSecondary,
roles,
token,
tokenExpiry,
tokenSecondary,
tokenSecondaryExpiry,
user
}
})
21 changes: 19 additions & 2 deletions src/pages/AnnouncementShow.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<script setup lang="ts">
import { onMounted } from 'vue'
import { onBeforeRouteUpdate, useRoute } from 'vue-router'
import { onBeforeRouteUpdate, useRoute, useRouter } from 'vue-router'
import { useAxios } from '@vueuse/integrations/useAxios'
import { showToast } from 'vant'
import { useAxiosInstance } from '../lib/axios.ts'
import AnnouncementShowComponent from '../components/AnnouncementShow.vue'
Expand All @@ -10,12 +11,28 @@ import type { Announcement } from '../types/announcement.ts'
const route = useRoute()
const router = useRouter()
const {
data: announcement,
isLoading,
execute: fetchData
} = useAxios<Announcement>('', useAxiosInstance(), {
immediate: false
immediate: false,
onError: (e: any) => {
console.error(e)
if (e?.response?.status && e.response.status >= 400) {
router.replace('/not-found')
} else {
showToast({
type: 'fail',
message: '加载失败',
onClose: () => {
router.back()
}
})
}
}
})
onBeforeRouteUpdate((to, from) => {
Expand Down
15 changes: 13 additions & 2 deletions src/pages/QuestionCreate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useStore } from '../lib/store.ts'
import AttachmentUpload from '../components/AttachmentUpload.vue'
import CampusSelect from '../components/CampusSelect.vue'
import type { Attachment } from '../types/attachment.ts'
import type { ResourceTokenResponse } from '../types/misc.ts'
import type { Question } from '../types/question.ts'
interface Form {
Expand Down Expand Up @@ -45,7 +46,7 @@ const errors = ref<Record<string, string>>({})
const {
isLoading,
execute
} = useAxios<Question>('questions', {
} = useAxios<ResourceTokenResponse<Question>>('questions', {
method: 'POST'
}, useAxiosInstance(), {
immediate: false
Expand Down Expand Up @@ -77,7 +78,11 @@ const submit = (): void => {
}
}).then(({ data }) => {
draft.value = form.value = initialForm()
router.replace(`/questions/create/success?id=${data.value?.id}`)
if (data.value?.resource_token) {
store.tokenSecondary = data.value.resource_token.access_token
store.tokenSecondaryExpiry = Date.now() + data.value.resource_token.expires_in * 1000
}
router.replace(`/questions/create/success?id=${data.value?.data?.id}`)
}).catch((e: AxiosError) => {
showToast({
type: 'fail',
Expand Down Expand Up @@ -119,6 +124,12 @@ onBeforeUnmount(() => {
>
若不填,则无法查看已提交的反馈内容
</p>
<p
v-else
class="text-xs mt-1"
>
若要匿名反馈,请先退出登录
</p>
</template>
<van-field
v-model="uid"
Expand Down
21 changes: 14 additions & 7 deletions src/pages/QuestionShow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,21 @@ const fetchData = (): void => {
useAxiosInstance().get<Question>(`questions/${route.params.id}`)
.then(({ data }) => {
question.value = data
useAxiosInstance().get<number[]>('questions/liked-answers')
.then(({ data: data1 }) => {
liked.value = data1.includes(data.answer?.id ?? -1)
})
.catch(console.error)
.finally(() => (loading.value = false))
if (store.loggedIn) {
useAxiosInstance().get<number[]>('questions/liked-answers')
.then(({ data: data1 }) => {
liked.value = data1.includes(data.answer?.id ?? -1)
})
.catch(console.error)
.finally(() => (loading.value = false))
} else {
loading.value = false
}
})
.catch((e: AxiosError) => {
console.error(e)
loading.value = false
if (e?.response?.status === 404 || e?.response?.status === 401) {
if (e?.response?.status && e.response.status >= 400) {
router.replace('/not-found')
} else {
showToast({
Expand All @@ -60,6 +64,9 @@ const onLike = (): void => {
}
const onUnlike = (): void => {
if (!store.loggedIn) {
return
}
if (question.value?.answer) {
question.value.answer.likesCount--
if (question.value.answer.likesCount < 0) {
Expand Down
7 changes: 3 additions & 4 deletions src/pages/UserIndex.vue
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,10 @@ const { data: count } = useAxios<{
icon-prefix="bi"
icon="clock-history"
title="我的历史反馈"
:value="store.loggedIn ? (count?.history || '') : '登录后可查看'"
:value="count?.history || ''"
center
:is-link="store.loggedIn"
:to="store.loggedIn ? '/user/history' : ''"
:aria-disabled="!store.loggedIn"
is-link
to="/user/history"
/>
</van-cell-group>

Expand Down
15 changes: 5 additions & 10 deletions src/pages/UserLogin.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useRouter } from 'vue-router'
import { useSchool } from '../lib/school.ts'
import { useAxiosInstance } from '../lib/axios.ts'
import { useStore } from '../lib/store.ts'
import type { TokenResponse } from '../types/misc.ts'
const school = useSchool()
Expand All @@ -30,20 +31,14 @@ const submit = (): void => {
return
}
useAxiosInstance().post<{
access_token: string
expires_in: number
token_type: 'Bearer'
}>('token', form, {
useAxiosInstance().post<TokenResponse>('token', form, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
'Content-Type': 'application/x-www-form-urlencoded',
'X-Merge-Token': store.tokenSecondary ?? undefined
}
}).then(({ data }) => {
store.token = data.access_token
if (data.expires_in) {
store.tokenExpiry = Date.now() + data.expires_in * 1000
}
store.tokenExpiry = Date.now() + data.expires_in * 1000
const url = sessionStorage.getItem('intendedUrl') ?? '/user'
sessionStorage.removeItem('intendedUrl')
Expand Down
15 changes: 15 additions & 0 deletions src/types/misc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export interface TokenResponse {
access_token: string
expires_in: number
token_type: string
}

export interface ResourceTokenResponse<T> {
resource_token: TokenResponse
data: T | null
}

export interface CursorPagination<T> {
data: T[]
cursor: string | null
}
5 changes: 0 additions & 5 deletions src/types/pagination.ts

This file was deleted.

0 comments on commit 93af4b6

Please sign in to comment.