1
0
Fork 0

Limit associations fetch when loading token

This commit is contained in:
Chocobozzz 2018-09-20 10:13:13 +02:00
parent fcc7c06037
commit 91411dba92
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
11 changed files with 75 additions and 80 deletions

View File

@ -267,15 +267,9 @@ async function updateUser (req: express.Request, res: express.Response, next: ex
const user = await userToUpdate.save() const user = await userToUpdate.save()
// Destroy user token to refresh rights // Destroy user token to refresh rights
if (roleChanged) { if (roleChanged) await OAuthTokenModel.deleteUserToken(userToUpdate.id)
await OAuthTokenModel.deleteUserToken(userToUpdate.id)
}
auditLogger.update( auditLogger.update(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON()), oldUserAuditView)
getAuditIdFromRes(res),
new UserAuditView(user.toFormattedJSON()),
oldUserAuditView
)
// Don't need to send this update to followers, these attributes are not propagated // Don't need to send this update to followers, these attributes are not propagated
@ -343,9 +337,5 @@ async function changeUserBlock (res: express.Response, user: UserModel, block: b
await Emailer.Instance.addUserBlockJob(user, block, reason) await Emailer.Instance.addUserBlockJob(user, block, reason)
auditLogger.update( auditLogger.update(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON()), oldUserAuditView)
getAuditIdFromRes(res),
new UserAuditView(user.toFormattedJSON()),
oldUserAuditView
)
} }

View File

@ -38,6 +38,7 @@ import { VideoFilter } from '../../../../shared/models/videos/video-query.type'
import { ActorFollowModel } from '../../../models/activitypub/actor-follow' import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
import { JobQueue } from '../../../lib/job-queue' import { JobQueue } from '../../../lib/job-queue'
import { logger } from '../../../helpers/logger' import { logger } from '../../../helpers/logger'
import { AccountModel } from '../../../models/account/account'
const auditLogger = auditLoggerFactory('users-me') const auditLogger = auditLoggerFactory('users-me')
@ -329,19 +330,17 @@ async function updateMe (req: express.Request, res: express.Response, next: expr
if (body.autoPlayVideo !== undefined) user.autoPlayVideo = body.autoPlayVideo if (body.autoPlayVideo !== undefined) user.autoPlayVideo = body.autoPlayVideo
await sequelizeTypescript.transaction(async t => { await sequelizeTypescript.transaction(async t => {
const userAccount = await AccountModel.load(user.Account.id)
await user.save({ transaction: t }) await user.save({ transaction: t })
if (body.displayName !== undefined) user.Account.name = body.displayName if (body.displayName !== undefined) userAccount.name = body.displayName
if (body.description !== undefined) user.Account.description = body.description if (body.description !== undefined) userAccount.description = body.description
await user.Account.save({ transaction: t }) await userAccount.save({ transaction: t })
await sendUpdateActor(user.Account, t) await sendUpdateActor(userAccount, t)
auditLogger.update( auditLogger.update(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON()), oldUserAuditView)
getAuditIdFromRes(res),
new UserAuditView(user.toFormattedJSON()),
oldUserAuditView
)
}) })
return res.sendStatus(204) return res.sendStatus(204)
@ -351,15 +350,12 @@ async function updateMyAvatar (req: express.Request, res: express.Response, next
const avatarPhysicalFile = req.files[ 'avatarfile' ][ 0 ] const avatarPhysicalFile = req.files[ 'avatarfile' ][ 0 ]
const user: UserModel = res.locals.oauth.token.user const user: UserModel = res.locals.oauth.token.user
const oldUserAuditView = new UserAuditView(user.toFormattedJSON()) const oldUserAuditView = new UserAuditView(user.toFormattedJSON())
const account = user.Account
const avatar = await updateActorAvatarFile(avatarPhysicalFile, account.Actor, account) const userAccount = await AccountModel.load(user.Account.id)
auditLogger.update( const avatar = await updateActorAvatarFile(avatarPhysicalFile, userAccount.Actor, userAccount)
getAuditIdFromRes(res),
new UserAuditView(user.toFormattedJSON()), auditLogger.update(getAuditIdFromRes(res), new UserAuditView(user.toFormattedJSON()), oldUserAuditView)
oldUserAuditView
)
return res.json({ avatar: avatar.toFormattedJSON() }) return res.json({ avatar: avatar.toFormattedJSON() })
} }

View File

@ -29,6 +29,7 @@ import { updateAvatarValidator } from '../../middlewares/validators/avatar'
import { updateActorAvatarFile } from '../../lib/avatar' import { updateActorAvatarFile } from '../../lib/avatar'
import { auditLoggerFactory, getAuditIdFromRes, VideoChannelAuditView } from '../../helpers/audit-logger' import { auditLoggerFactory, getAuditIdFromRes, VideoChannelAuditView } from '../../helpers/audit-logger'
import { resetSequelizeInstance } from '../../helpers/database-utils' import { resetSequelizeInstance } from '../../helpers/database-utils'
import { UserModel } from '../../models/account/user'
const auditLogger = auditLoggerFactory('channels') const auditLogger = auditLoggerFactory('channels')
const reqAvatarFile = createReqFiles([ 'avatarfile' ], IMAGE_MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.AVATARS_DIR }) const reqAvatarFile = createReqFiles([ 'avatarfile' ], IMAGE_MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.AVATARS_DIR })
@ -123,19 +124,17 @@ async function updateVideoChannelAvatar (req: express.Request, res: express.Resp
async function addVideoChannel (req: express.Request, res: express.Response) { async function addVideoChannel (req: express.Request, res: express.Response) {
const videoChannelInfo: VideoChannelCreate = req.body const videoChannelInfo: VideoChannelCreate = req.body
const account: AccountModel = res.locals.oauth.token.User.Account
const videoChannelCreated: VideoChannelModel = await sequelizeTypescript.transaction(async t => { const videoChannelCreated: VideoChannelModel = await sequelizeTypescript.transaction(async t => {
const account = await AccountModel.load((res.locals.oauth.token.User as UserModel).Account.id, t)
return createVideoChannel(videoChannelInfo, account, t) return createVideoChannel(videoChannelInfo, account, t)
}) })
setAsyncActorKeys(videoChannelCreated.Actor) setAsyncActorKeys(videoChannelCreated.Actor)
.catch(err => logger.error('Cannot set async actor keys for account %s.', videoChannelCreated.Actor.uuid, { err })) .catch(err => logger.error('Cannot set async actor keys for account %s.', videoChannelCreated.Actor.uuid, { err }))
auditLogger.create( auditLogger.create(getAuditIdFromRes(res), new VideoChannelAuditView(videoChannelCreated.toFormattedJSON()))
getAuditIdFromRes(res),
new VideoChannelAuditView(videoChannelCreated.toFormattedJSON())
)
logger.info('Video channel with uuid %s created.', videoChannelCreated.Actor.uuid) logger.info('Video channel with uuid %s created.', videoChannelCreated.Actor.uuid)
return res.json({ return res.json({

View File

@ -21,6 +21,7 @@ import { AccountModel } from '../../../models/account/account'
import { VideoModel } from '../../../models/video/video' import { VideoModel } from '../../../models/video/video'
import { VideoAbuseModel } from '../../../models/video/video-abuse' import { VideoAbuseModel } from '../../../models/video/video-abuse'
import { auditLoggerFactory, VideoAbuseAuditView } from '../../../helpers/audit-logger' import { auditLoggerFactory, VideoAbuseAuditView } from '../../../helpers/audit-logger'
import { UserModel } from '../../../models/account/user'
const auditLogger = auditLoggerFactory('abuse') const auditLogger = auditLoggerFactory('abuse')
const abuseVideoRouter = express.Router() const abuseVideoRouter = express.Router()
@ -95,17 +96,18 @@ async function deleteVideoAbuse (req: express.Request, res: express.Response) {
async function reportVideoAbuse (req: express.Request, res: express.Response) { async function reportVideoAbuse (req: express.Request, res: express.Response) {
const videoInstance = res.locals.video as VideoModel const videoInstance = res.locals.video as VideoModel
const reporterAccount = res.locals.oauth.token.User.Account as AccountModel
const body: VideoAbuseCreate = req.body const body: VideoAbuseCreate = req.body
const abuseToCreate = {
reporterAccountId: reporterAccount.id,
reason: body.reason,
videoId: videoInstance.id,
state: VideoAbuseState.PENDING
}
const videoAbuse: VideoAbuseModel = await sequelizeTypescript.transaction(async t => { const videoAbuse: VideoAbuseModel = await sequelizeTypescript.transaction(async t => {
const reporterAccount = await AccountModel.load((res.locals.oauth.token.User as UserModel).Account.id, t)
const abuseToCreate = {
reporterAccountId: reporterAccount.id,
reason: body.reason,
videoId: videoInstance.id,
state: VideoAbuseState.PENDING
}
const videoAbuseInstance = await VideoAbuseModel.create(abuseToCreate, { transaction: t }) const videoAbuseInstance = await VideoAbuseModel.create(abuseToCreate, { transaction: t })
videoAbuseInstance.Video = videoInstance videoAbuseInstance.Video = videoInstance
videoAbuseInstance.Account = reporterAccount videoAbuseInstance.Account = reporterAccount
@ -121,7 +123,6 @@ async function reportVideoAbuse (req: express.Request, res: express.Response) {
}) })
logger.info('Abuse report for video %s created.', videoInstance.name) logger.info('Abuse report for video %s created.', videoInstance.name)
return res.json({
videoAbuse: videoAbuse.toFormattedJSON() return res.json({ videoAbuse: videoAbuse.toFormattedJSON() }).end()
}).end()
} }

View File

@ -24,6 +24,8 @@ import {
import { VideoModel } from '../../../models/video/video' import { VideoModel } from '../../../models/video/video'
import { VideoCommentModel } from '../../../models/video/video-comment' import { VideoCommentModel } from '../../../models/video/video-comment'
import { auditLoggerFactory, CommentAuditView, getAuditIdFromRes } from '../../../helpers/audit-logger' import { auditLoggerFactory, CommentAuditView, getAuditIdFromRes } from '../../../helpers/audit-logger'
import { AccountModel } from '../../../models/account/account'
import { UserModel } from '../../../models/account/user'
const auditLogger = auditLoggerFactory('comments') const auditLogger = auditLoggerFactory('comments')
const videoCommentRouter = express.Router() const videoCommentRouter = express.Router()
@ -101,11 +103,13 @@ async function addVideoCommentThread (req: express.Request, res: express.Respons
const videoCommentInfo: VideoCommentCreate = req.body const videoCommentInfo: VideoCommentCreate = req.body
const comment = await sequelizeTypescript.transaction(async t => { const comment = await sequelizeTypescript.transaction(async t => {
const account = await AccountModel.load((res.locals.oauth.token.User as UserModel).Account.id, t)
return createVideoComment({ return createVideoComment({
text: videoCommentInfo.text, text: videoCommentInfo.text,
inReplyToComment: null, inReplyToComment: null,
video: res.locals.video, video: res.locals.video,
account: res.locals.oauth.token.User.Account account
}, t) }, t)
}) })
@ -120,19 +124,19 @@ async function addVideoCommentReply (req: express.Request, res: express.Response
const videoCommentInfo: VideoCommentCreate = req.body const videoCommentInfo: VideoCommentCreate = req.body
const comment = await sequelizeTypescript.transaction(async t => { const comment = await sequelizeTypescript.transaction(async t => {
const account = await AccountModel.load((res.locals.oauth.token.User as UserModel).Account.id, t)
return createVideoComment({ return createVideoComment({
text: videoCommentInfo.text, text: videoCommentInfo.text,
inReplyToComment: res.locals.videoComment, inReplyToComment: res.locals.videoComment,
video: res.locals.video, video: res.locals.video,
account: res.locals.oauth.token.User.Account account
}, t) }, t)
}) })
auditLogger.create(getAuditIdFromRes(res), new CommentAuditView(comment.toFormattedJSON())) auditLogger.create(getAuditIdFromRes(res), new CommentAuditView(comment.toFormattedJSON()))
return res.json({ return res.json({ comment: comment.toFormattedJSON() }).end()
comment: comment.toFormattedJSON()
}).end()
} }
async function removeVideoComment (req: express.Request, res: express.Response) { async function removeVideoComment (req: express.Request, res: express.Response) {

View File

@ -19,6 +19,7 @@ import { VideoChannelModel } from '../../../models/video/video-channel'
import { getFormattedObjects } from '../../../helpers/utils' import { getFormattedObjects } from '../../../helpers/utils'
import { changeVideoChannelShare } from '../../../lib/activitypub' import { changeVideoChannelShare } from '../../../lib/activitypub'
import { sendUpdateVideo } from '../../../lib/activitypub/send' import { sendUpdateVideo } from '../../../lib/activitypub/send'
import { UserModel } from '../../../models/account/user'
const ownershipVideoRouter = express.Router() const ownershipVideoRouter = express.Router()
@ -58,26 +59,25 @@ export {
async function giveVideoOwnership (req: express.Request, res: express.Response) { async function giveVideoOwnership (req: express.Request, res: express.Response) {
const videoInstance = res.locals.video as VideoModel const videoInstance = res.locals.video as VideoModel
const initiatorAccount = res.locals.oauth.token.User.Account as AccountModel const initiatorAccountId = (res.locals.oauth.token.User as UserModel).Account.id
const nextOwner = res.locals.nextOwner as AccountModel const nextOwner = res.locals.nextOwner as AccountModel
await sequelizeTypescript.transaction(t => { await sequelizeTypescript.transaction(t => {
return VideoChangeOwnershipModel.findOrCreate({ return VideoChangeOwnershipModel.findOrCreate({
where: { where: {
initiatorAccountId: initiatorAccount.id, initiatorAccountId,
nextOwnerAccountId: nextOwner.id, nextOwnerAccountId: nextOwner.id,
videoId: videoInstance.id, videoId: videoInstance.id,
status: VideoChangeOwnershipStatus.WAITING status: VideoChangeOwnershipStatus.WAITING
}, },
defaults: { defaults: {
initiatorAccountId: initiatorAccount.id, initiatorAccountId,
nextOwnerAccountId: nextOwner.id, nextOwnerAccountId: nextOwner.id,
videoId: videoInstance.id, videoId: videoInstance.id,
status: VideoChangeOwnershipStatus.WAITING status: VideoChangeOwnershipStatus.WAITING
}, },
transaction: t transaction: t
}) })
}) })
logger.info('Ownership change for video %s created.', videoInstance.name) logger.info('Ownership change for video %s created.', videoInstance.name)
@ -85,9 +85,10 @@ async function giveVideoOwnership (req: express.Request, res: express.Response)
} }
async function listVideoOwnership (req: express.Request, res: express.Response) { async function listVideoOwnership (req: express.Request, res: express.Response) {
const currentAccount = res.locals.oauth.token.User.Account as AccountModel const currentAccountId = (res.locals.oauth.token.User as UserModel).Account.id
const resultList = await VideoChangeOwnershipModel.listForApi( const resultList = await VideoChangeOwnershipModel.listForApi(
currentAccount.id, currentAccountId,
req.query.start || 0, req.query.start || 0,
req.query.count || 10, req.query.count || 10,
req.query.sort || 'createdAt' req.query.sort || 'createdAt'

View File

@ -28,10 +28,11 @@ async function rateVideo (req: express.Request, res: express.Response) {
const body: UserVideoRateUpdate = req.body const body: UserVideoRateUpdate = req.body
const rateType = body.rating const rateType = body.rating
const videoInstance: VideoModel = res.locals.video const videoInstance: VideoModel = res.locals.video
const accountInstance: AccountModel = res.locals.oauth.token.User.Account
await sequelizeTypescript.transaction(async t => { await sequelizeTypescript.transaction(async t => {
const sequelizeOptions = { transaction: t } const sequelizeOptions = { transaction: t }
const accountInstance = await AccountModel.load(res.locals.oauth.token.User.Account.id, t)
const previousRate = await AccountVideoRateModel.load(accountInstance.id, videoInstance.id, t) const previousRate = await AccountVideoRateModel.load(accountInstance.id, videoInstance.id, t)
let likesToIncrement = 0 let likesToIncrement = 0
@ -47,10 +48,10 @@ async function rateVideo (req: express.Request, res: express.Response) {
else if (previousRate.type === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement-- else if (previousRate.type === VIDEO_RATE_TYPES.DISLIKE) dislikesToIncrement--
if (rateType === 'none') { // Destroy previous rate if (rateType === 'none') { // Destroy previous rate
await previousRate.destroy({ transaction: t }) await previousRate.destroy(sequelizeOptions)
} else { // Update previous rate } else { // Update previous rate
previousRate.type = rateType previousRate.type = rateType
await previousRate.save({ transaction: t }) await previousRate.save(sequelizeOptions)
} }
} else if (rateType !== 'none') { // There was not a previous rate, insert a new one if there is a rate } else if (rateType !== 'none') { // There was not a previous rate, insert a new one if there is a rate
const query = { const query = {
@ -70,9 +71,9 @@ async function rateVideo (req: express.Request, res: express.Response) {
await videoInstance.increment(incrementQuery, sequelizeOptions) await videoInstance.increment(incrementQuery, sequelizeOptions)
await sendVideoRateChange(accountInstance, videoInstance, likesToIncrement, dislikesToIncrement, t) await sendVideoRateChange(accountInstance, videoInstance, likesToIncrement, dislikesToIncrement, t)
})
logger.info('Account video rate for video %s of account %s updated.', videoInstance.name, accountInstance.name) logger.info('Account video rate for video %s of account %s updated.', videoInstance.name, accountInstance.name)
})
return res.type('json').status(204).end() return res.type('json').status(204).end()
} }

View File

@ -354,11 +354,11 @@ async function refreshVideoIfNeeded (options: {
syncParam: SyncParam, syncParam: SyncParam,
refreshViews: boolean refreshViews: boolean
}): Promise<VideoModel> { }): Promise<VideoModel> {
if (!options.video.isOutdated()) return options.video
// We need more attributes if the argument video was fetched with not enough joints // We need more attributes if the argument video was fetched with not enough joints
const video = options.fetchedType === 'all' ? options.video : await VideoModel.loadByUrlAndPopulateAccount(options.video.url) const video = options.fetchedType === 'all' ? options.video : await VideoModel.loadByUrlAndPopulateAccount(options.video.url)
if (!video.isOutdated()) return video
try { try {
const { response, videoObject } = await fetchRemoteVideo(video.url) const { response, videoObject } = await fetchRemoteVideo(video.url)
if (response.statusCode === 404) { if (response.statusCode === 404) {

View File

@ -1,12 +1,5 @@
import { AbstractScheduler } from './abstract-scheduler' import { AbstractScheduler } from './abstract-scheduler'
import { SCHEDULER_INTERVALS_MS } from '../../initializers' import { SCHEDULER_INTERVALS_MS } from '../../initializers'
import { logger } from '../../helpers/logger'
import * as request from 'request'
import { createWriteStream, ensureDir, writeFile } from 'fs-extra'
import { join } from 'path'
import { root } from '../../helpers/core-utils'
import { updateYoutubeDLBinary } from '../../helpers/youtube-dl' import { updateYoutubeDLBinary } from '../../helpers/youtube-dl'
export class YoutubeDlUpdateScheduler extends AbstractScheduler { export class YoutubeDlUpdateScheduler extends AbstractScheduler {

View File

@ -134,8 +134,8 @@ export class AccountModel extends Model<AccountModel> {
return undefined return undefined
} }
static load (id: number) { static load (id: number, transaction?: Sequelize.Transaction) {
return AccountModel.findById(id) return AccountModel.findById(id, { transaction })
} }
static loadByUUID (uuid: string) { static loadByUUID (uuid: string) {

View File

@ -1,9 +1,10 @@
import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript' import { AllowNull, BelongsTo, Column, CreatedAt, ForeignKey, Model, Scopes, Table, UpdatedAt } from 'sequelize-typescript'
import { logger } from '../../helpers/logger' import { logger } from '../../helpers/logger'
import { AccountModel } from '../account/account'
import { UserModel } from '../account/user' import { UserModel } from '../account/user'
import { OAuthClientModel } from './oauth-client' import { OAuthClientModel } from './oauth-client'
import { Transaction } from 'sequelize' import { Transaction } from 'sequelize'
import { AccountModel } from '../account/account'
import { ActorModel } from '../activitypub/actor'
export type OAuthTokenInfo = { export type OAuthTokenInfo = {
refreshToken: string refreshToken: string
@ -17,18 +18,27 @@ export type OAuthTokenInfo = {
} }
enum ScopeNames { enum ScopeNames {
WITH_ACCOUNT = 'WITH_ACCOUNT' WITH_USER = 'WITH_USER'
} }
@Scopes({ @Scopes({
[ScopeNames.WITH_ACCOUNT]: { [ScopeNames.WITH_USER]: {
include: [ include: [
{ {
model: () => UserModel, model: () => UserModel.unscoped(),
required: true,
include: [ include: [
{ {
model: () => AccountModel, attributes: [ 'id' ],
required: true model: () => AccountModel.unscoped(),
required: true,
include: [
{
attributes: [ 'id' ],
model: () => ActorModel.unscoped(),
required: true
}
]
} }
] ]
} }
@ -138,7 +148,7 @@ export class OAuthTokenModel extends Model<OAuthTokenModel> {
} }
} }
return OAuthTokenModel.scope(ScopeNames.WITH_ACCOUNT).findOne(query).then(token => { return OAuthTokenModel.scope(ScopeNames.WITH_USER).findOne(query).then(token => {
if (token) token['user'] = token.User if (token) token['user'] = token.User
return token return token
@ -152,7 +162,7 @@ export class OAuthTokenModel extends Model<OAuthTokenModel> {
} }
} }
return OAuthTokenModel.scope(ScopeNames.WITH_ACCOUNT) return OAuthTokenModel.scope(ScopeNames.WITH_USER)
.findOne(query) .findOne(query)
.then(token => { .then(token => {
if (token) { if (token) {