mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2024-11-28 11:34:01 -06:00
Add last login date to users
This commit is contained in:
parent
ee8e602ef9
commit
3cc665f48f
@ -71,6 +71,8 @@ export class User implements UserServerModel {
|
||||
|
||||
pluginAuth: string | null
|
||||
|
||||
lastLoginDate: Date | null
|
||||
|
||||
createdAt: Date
|
||||
|
||||
constructor (hash: Partial<UserServerModel>) {
|
||||
@ -115,6 +117,7 @@ export class User implements UserServerModel {
|
||||
this.createdAt = hash.createdAt
|
||||
|
||||
this.pluginAuth = hash.pluginAuth
|
||||
this.lastLoginDate = hash.lastLoginDate
|
||||
|
||||
if (hash.account !== undefined) {
|
||||
this.account = new Account(hash.account)
|
||||
|
@ -22,7 +22,7 @@ statsRouter.get('/stats',
|
||||
async function getStats (req: express.Request, res: express.Response) {
|
||||
const { totalLocalVideos, totalLocalVideoViews, totalVideos } = await VideoModel.getStats()
|
||||
const { totalLocalVideoComments, totalVideoComments } = await VideoCommentModel.getStats()
|
||||
const { totalUsers } = await UserModel.getStats()
|
||||
const { totalUsers, totalDailyActiveUsers, totalWeeklyActiveUsers, totalMonthlyActiveUsers } = await UserModel.getStats()
|
||||
const { totalInstanceFollowers, totalInstanceFollowing } = await ActorFollowModel.getStats()
|
||||
const { totalLocalVideoFilesSize } = await VideoFileModel.getStats()
|
||||
|
||||
@ -48,9 +48,15 @@ async function getStats (req: express.Request, res: express.Response) {
|
||||
totalLocalVideoComments,
|
||||
totalVideos,
|
||||
totalVideoComments,
|
||||
|
||||
totalUsers,
|
||||
totalDailyActiveUsers,
|
||||
totalWeeklyActiveUsers,
|
||||
totalMonthlyActiveUsers,
|
||||
|
||||
totalInstanceFollowers,
|
||||
totalInstanceFollowing,
|
||||
|
||||
videosRedundancy: videosRedundancyStats
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ import { CONFIG, registerConfigChangedHandler } from './config'
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const LAST_MIGRATION_VERSION = 500
|
||||
const LAST_MIGRATION_VERSION = 505
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
|
26
server/initializers/migrations/0505-user-last-login-date.ts
Normal file
26
server/initializers/migrations/0505-user-last-login-date.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import * as Sequelize from 'sequelize'
|
||||
|
||||
async function up (utils: {
|
||||
transaction: Sequelize.Transaction
|
||||
queryInterface: Sequelize.QueryInterface
|
||||
sequelize: Sequelize.Sequelize
|
||||
}): Promise<void> {
|
||||
|
||||
{
|
||||
const field = {
|
||||
type: Sequelize.DATE,
|
||||
allowNull: true
|
||||
}
|
||||
await utils.queryInterface.addColumn('user', 'lastLoginDate', field)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function down (options) {
|
||||
throw new Error('Not implemented.')
|
||||
}
|
||||
|
||||
export {
|
||||
up,
|
||||
down
|
||||
}
|
@ -180,6 +180,10 @@ async function saveToken (token: TokenInfo, client: OAuthClientModel, user: User
|
||||
}
|
||||
|
||||
const tokenCreated = await OAuthTokenModel.create(tokenToCreate)
|
||||
|
||||
user.lastLoginDate = new Date()
|
||||
await user.save()
|
||||
|
||||
return Object.assign(tokenCreated, { client, user })
|
||||
}
|
||||
|
||||
|
@ -353,6 +353,11 @@ export class UserModel extends Model<UserModel> {
|
||||
@Column
|
||||
pluginAuth: string
|
||||
|
||||
@AllowNull(true)
|
||||
@Default(null)
|
||||
@Column
|
||||
lastLoginDate: Date
|
||||
|
||||
@CreatedAt
|
||||
createdAt: Date
|
||||
|
||||
@ -691,10 +696,28 @@ export class UserModel extends Model<UserModel> {
|
||||
}
|
||||
|
||||
static async getStats () {
|
||||
function getActiveUsers (days: number) {
|
||||
const query = {
|
||||
where: {
|
||||
[Op.and]: [
|
||||
literal(`"lastLoginDate" > NOW() - INTERVAL '${days}d'`)
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
return UserModel.count(query)
|
||||
}
|
||||
|
||||
const totalUsers = await UserModel.count()
|
||||
const totalDailyActiveUsers = await getActiveUsers(1)
|
||||
const totalWeeklyActiveUsers = await getActiveUsers(7)
|
||||
const totalMonthlyActiveUsers = await getActiveUsers(30)
|
||||
|
||||
return {
|
||||
totalUsers
|
||||
totalUsers,
|
||||
totalDailyActiveUsers,
|
||||
totalWeeklyActiveUsers,
|
||||
totalMonthlyActiveUsers
|
||||
}
|
||||
}
|
||||
|
||||
@ -808,7 +831,9 @@ export class UserModel extends Model<UserModel> {
|
||||
|
||||
createdAt: this.createdAt,
|
||||
|
||||
pluginAuth: this.pluginAuth
|
||||
pluginAuth: this.pluginAuth,
|
||||
|
||||
lastLoginDate: this.lastLoginDate
|
||||
}
|
||||
|
||||
if (parameters.withAdminFlags) {
|
||||
|
@ -12,7 +12,8 @@ import {
|
||||
ServerInfo, unfollow,
|
||||
uploadVideo,
|
||||
viewVideo,
|
||||
wait
|
||||
wait,
|
||||
userLogin
|
||||
} from '../../../../shared/extra-utils'
|
||||
import { setAccessTokensToServers } from '../../../../shared/extra-utils/index'
|
||||
import { getStats } from '../../../../shared/extra-utils/server/stats'
|
||||
@ -23,6 +24,10 @@ const expect = chai.expect
|
||||
|
||||
describe('Test stats (excluding redundancy)', function () {
|
||||
let servers: ServerInfo[] = []
|
||||
const user = {
|
||||
username: 'user1',
|
||||
password: 'super_password'
|
||||
}
|
||||
|
||||
before(async function () {
|
||||
this.timeout(60000)
|
||||
@ -31,10 +36,6 @@ describe('Test stats (excluding redundancy)', function () {
|
||||
|
||||
await doubleFollow(servers[0], servers[1])
|
||||
|
||||
const user = {
|
||||
username: 'user1',
|
||||
password: 'super_password'
|
||||
}
|
||||
await createUser({ url: servers[0].url, accessToken: servers[0].accessToken, username: user.username, password: user.password })
|
||||
|
||||
const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { fixture: 'video_short.webm' })
|
||||
@ -96,6 +97,8 @@ describe('Test stats (excluding redundancy)', function () {
|
||||
})
|
||||
|
||||
it('Should have the correct total videos stats after an unfollow', async function () {
|
||||
this.timeout(15000)
|
||||
|
||||
await unfollow(servers[2].url, servers[2].accessToken, servers[0])
|
||||
await waitJobs(servers)
|
||||
|
||||
@ -105,6 +108,28 @@ describe('Test stats (excluding redundancy)', function () {
|
||||
expect(data.totalVideos).to.equal(0)
|
||||
})
|
||||
|
||||
it('Should have the correct active users stats', async function () {
|
||||
const server = servers[0]
|
||||
|
||||
{
|
||||
const res = await getStats(server.url)
|
||||
const data: ServerStats = res.body
|
||||
expect(data.totalDailyActiveUsers).to.equal(1)
|
||||
expect(data.totalWeeklyActiveUsers).to.equal(1)
|
||||
expect(data.totalMonthlyActiveUsers).to.equal(1)
|
||||
}
|
||||
|
||||
{
|
||||
await userLogin(server, user)
|
||||
|
||||
const res = await getStats(server.url)
|
||||
const data: ServerStats = res.body
|
||||
expect(data.totalDailyActiveUsers).to.equal(2)
|
||||
expect(data.totalWeeklyActiveUsers).to.equal(2)
|
||||
expect(data.totalMonthlyActiveUsers).to.equal(2)
|
||||
}
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await cleanupTests(servers)
|
||||
})
|
||||
|
@ -418,6 +418,9 @@ describe('Test users', function () {
|
||||
expect(rootUser.email).to.equal('admin' + server.internalServerNumber + '@example.com')
|
||||
expect(user.nsfwPolicy).to.equal('display')
|
||||
|
||||
expect(rootUser.lastLoginDate).to.exist
|
||||
expect(user.lastLoginDate).to.exist
|
||||
|
||||
userId = user.id
|
||||
})
|
||||
|
||||
|
@ -2,6 +2,10 @@ import { VideoRedundancyStrategyWithManual } from '../redundancy'
|
||||
|
||||
export interface ServerStats {
|
||||
totalUsers: number
|
||||
totalDailyActiveUsers: number
|
||||
totalWeeklyActiveUsers: number
|
||||
totalMonthlyActiveUsers: number
|
||||
|
||||
totalLocalVideos: number
|
||||
totalLocalVideoViews: number
|
||||
totalLocalVideoComments: number
|
||||
|
@ -52,6 +52,8 @@ export interface User {
|
||||
createdAt: Date
|
||||
|
||||
pluginAuth: string | null
|
||||
|
||||
lastLoginDate: Date | null
|
||||
}
|
||||
|
||||
export interface MyUserSpecialPlaylist {
|
||||
|
Loading…
Reference in New Issue
Block a user