Add last login date to users

pull/2732/head
Chocobozzz 2020-05-07 10:39:09 +02:00
parent ee8e602ef9
commit 3cc665f48f
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
10 changed files with 107 additions and 9 deletions

View File

@ -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)

View File

@ -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
}

View File

@ -14,7 +14,7 @@ import { CONFIG, registerConfigChangedHandler } from './config'
// ---------------------------------------------------------------------------
const LAST_MIGRATION_VERSION = 500
const LAST_MIGRATION_VERSION = 505
// ---------------------------------------------------------------------------

View 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
}

View File

@ -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 })
}

View File

@ -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) {

View File

@ -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)
})

View File

@ -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
})

View File

@ -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

View File

@ -52,6 +52,8 @@ export interface User {
createdAt: Date
pluginAuth: string | null
lastLoginDate: Date | null
}
export interface MyUserSpecialPlaylist {