Add pagination to /me/sessions endpoint & sessions account page table

This commit is contained in:
advplyr 2026-07-26 17:11:03 -05:00
parent 71c5d27ea5
commit a7b380cd7a
2 changed files with 42 additions and 6 deletions

View file

@ -98,6 +98,11 @@
</td> </td>
</tr> </tr>
</table> </table>
<div v-if="authSessionsNumPages > 1" class="flex items-center justify-end py-1">
<ui-icon-btn icon="arrow_back_ios_new" :size="7" icon-font-size="1rem" class="mx-1" :disabled="loadingAuthSessions || authSessionsPage === 0" @click="prevAuthSessionsPage" />
<p class="text-sm mx-1">{{ $getString('LabelPaginationPageXOfY', [authSessionsPage + 1, authSessionsNumPages]) }}</p>
<ui-icon-btn icon="arrow_forward_ios" :size="7" icon-font-size="1rem" class="mx-1" :disabled="loadingAuthSessions || authSessionsPage >= authSessionsNumPages - 1" @click="nextAuthSessionsPage" />
</div>
</app-settings-content> </app-settings-content>
</div> </div>
@ -122,6 +127,10 @@ export default {
changingPassword: false, changingPassword: false,
loggingOut: false, loggingOut: false,
authSessions: [], authSessions: [],
authSessionsPage: 0,
authSessionsNumPages: 0,
authSessionsItemsPerPage: 10,
loadingAuthSessions: false,
selectedLanguage: '', selectedLanguage: '',
newEReaderDevice: { newEReaderDevice: {
name: '', name: '',
@ -285,15 +294,33 @@ export default {
ereaderDevicesUpdated(ereaderDevices) { ereaderDevicesUpdated(ereaderDevices) {
this.ereaderDevices = ereaderDevices this.ereaderDevices = ereaderDevices
}, },
loadAuthSessions() { loadAuthSessions(page = 0) {
if (this.loadingAuthSessions) return
if (page < 0) return
if (this.authSessionsNumPages > 0 && page > this.authSessionsNumPages - 1) return
this.loadingAuthSessions = true
this.$axios this.$axios
.$get('/api/me/sessions') .$get(`/api/me/sessions?page=${page}&itemsPerPage=${this.authSessionsItemsPerPage}`)
.then((data) => { .then((data) => {
this.authSessions = data.sessions || [] this.authSessions = data.sessions || []
this.authSessionsPage = data.page ?? page
this.authSessionsNumPages = data.numPages ?? 0
}) })
.catch((error) => { .catch((error) => {
console.error('Failed to load sessions', error) console.error('Failed to load sessions', error)
}) })
.finally(() => {
this.loadingAuthSessions = false
})
},
prevAuthSessionsPage() {
if (this.authSessionsPage <= 0) return
this.loadAuthSessions(this.authSessionsPage - 1)
},
nextAuthSessionsPage() {
if (this.authSessionsPage >= this.authSessionsNumPages - 1) return
this.loadAuthSessions(this.authSessionsPage + 1)
}, },
getSessionDeviceLabel(session) { getSessionDeviceLabel(session) {
const deviceInfo = session.deviceInfo const deviceInfo = session.deviceInfo

View file

@ -35,21 +35,30 @@ class MeController {
* @param {Response} res * @param {Response} res
*/ */
async getSessions(req, res) { async getSessions(req, res) {
const page = Math.max(0, toNumber(req.query.page, 0))
const itemsPerPage = Math.max(1, toNumber(req.query.itemsPerPage, 10))
if (req.user.isGuest) { if (req.user.isGuest) {
return res.json({ sessions: [] }) return res.json({ sessions: [], total: 0, numPages: 0, page, itemsPerPage })
} }
const refreshToken = req.cookies.refresh_token || req.headers['x-refresh-token'] const refreshToken = req.cookies.refresh_token || req.headers['x-refresh-token']
const sessions = await Database.sessionModel.findAll({ const { rows, count } = await Database.sessionModel.findAndCountAll({
where: { where: {
userId: req.user.id, userId: req.user.id,
expiresAt: { [Op.gt]: new Date() } expiresAt: { [Op.gt]: new Date() }
}, },
order: [['updatedAt', 'DESC']] order: [['updatedAt', 'DESC']],
limit: itemsPerPage,
offset: itemsPerPage * page
}) })
res.json({ res.json({
sessions: sessions.map((session) => ({ total: count,
numPages: Math.ceil(count / itemsPerPage),
page,
itemsPerPage,
sessions: rows.map((session) => ({
id: session.id, id: session.id,
ipAddress: session.ipAddress, ipAddress: session.ipAddress,
userAgent: session.userAgent, userAgent: session.userAgent,