diff --git a/client/pages/account.vue b/client/pages/account.vue
index 8323772a5..398a21c88 100644
--- a/client/pages/account.vue
+++ b/client/pages/account.vue
@@ -98,6 +98,11 @@
+
+
+
{{ $getString('LabelPaginationPageXOfY', [authSessionsPage + 1, authSessionsNumPages]) }}
+
+
@@ -122,6 +127,10 @@ export default {
changingPassword: false,
loggingOut: false,
authSessions: [],
+ authSessionsPage: 0,
+ authSessionsNumPages: 0,
+ authSessionsItemsPerPage: 10,
+ loadingAuthSessions: false,
selectedLanguage: '',
newEReaderDevice: {
name: '',
@@ -285,15 +294,33 @@ export default {
ereaderDevicesUpdated(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
- .$get('/api/me/sessions')
+ .$get(`/api/me/sessions?page=${page}&itemsPerPage=${this.authSessionsItemsPerPage}`)
.then((data) => {
this.authSessions = data.sessions || []
+ this.authSessionsPage = data.page ?? page
+ this.authSessionsNumPages = data.numPages ?? 0
})
.catch((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) {
const deviceInfo = session.deviceInfo
diff --git a/server/controllers/MeController.js b/server/controllers/MeController.js
index b8f378bfa..cdf3034a1 100644
--- a/server/controllers/MeController.js
+++ b/server/controllers/MeController.js
@@ -35,21 +35,30 @@ class MeController {
* @param {Response} 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) {
- 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 sessions = await Database.sessionModel.findAll({
+ const { rows, count } = await Database.sessionModel.findAndCountAll({
where: {
userId: req.user.id,
expiresAt: { [Op.gt]: new Date() }
},
- order: [['updatedAt', 'DESC']]
+ order: [['updatedAt', 'DESC']],
+ limit: itemsPerPage,
+ offset: itemsPerPage * page
})
res.json({
- sessions: sessions.map((session) => ({
+ total: count,
+ numPages: Math.ceil(count / itemsPerPage),
+ page,
+ itemsPerPage,
+ sessions: rows.map((session) => ({
id: session.id,
ipAddress: session.ipAddress,
userAgent: session.userAgent,