X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fmodels%2Faccount%2Faccount.ts;h=466d6258e1cdafce825adab256c83c38bb92aa6f;hb=d95d15598847c7f020aa056e7e6e0c02d2bbf732;hp=2b04acd863743d3a6e8c69462165741d83350ece;hpb=97567dd81f508dd6295ac4d73d849aa2ce0a6549;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/models/account/account.ts b/server/models/account/account.ts index 2b04acd86..466d6258e 100644 --- a/server/models/account/account.ts +++ b/server/models/account/account.ts @@ -3,7 +3,8 @@ import { BeforeDestroy, BelongsTo, Column, - CreatedAt, DataType, + CreatedAt, + DataType, Default, DefaultScope, ForeignKey, @@ -26,13 +27,25 @@ import { VideoCommentModel } from '../video/video-comment' import { UserModel } from './user' import { AvatarModel } from '../avatar/avatar' import { VideoPlaylistModel } from '../video/video-playlist' -import { CONSTRAINTS_FIELDS, WEBSERVER } from '../../initializers/constants' -import { Op, Transaction, WhereOptions } from 'sequelize' +import { CONSTRAINTS_FIELDS, SERVER_ACTOR_NAME, WEBSERVER } from '../../initializers/constants' +import { FindOptions, IncludeOptions, Op, Transaction, WhereOptions } from 'sequelize' +import { AccountBlocklistModel } from './account-blocklist' +import { ServerBlocklistModel } from '../server/server-blocklist' +import { ActorFollowModel } from '../activitypub/actor-follow' +import { MAccountActor, MAccountAP, MAccountDefault, MAccountFormattable, MAccountSummaryFormattable, MAccount } from '../../types/models' +import * as Bluebird from 'bluebird' +import { ModelCache } from '@server/models/model-cache' +import { VideoModel } from '../video/video' export enum ScopeNames { SUMMARY = 'SUMMARY' } +export type SummaryOptions = { + whereActor?: WhereOptions + withAccountBlockerIds?: number[] +} + @DefaultScope(() => ({ include: [ { @@ -42,21 +55,26 @@ export enum ScopeNames { ] })) @Scopes(() => ({ - [ ScopeNames.SUMMARY ]: (whereActor?: WhereOptions) => { - return { + [ScopeNames.SUMMARY]: (options: SummaryOptions = {}) => { + const whereActor = options.whereActor || undefined + + const serverInclude: IncludeOptions = { + attributes: [ 'host' ], + model: ServerModel.unscoped(), + required: false + } + + const query: FindOptions = { attributes: [ 'id', 'name' ], include: [ { - attributes: [ 'id', 'uuid', 'preferredUsername', 'url', 'serverId', 'avatarId' ], + attributes: [ 'id', 'preferredUsername', 'url', 'serverId', 'avatarId' ], model: ActorModel.unscoped(), required: true, where: whereActor, include: [ - { - attributes: [ 'host' ], - model: ServerModel.unscoped(), - required: false - }, + serverInclude, + { model: AvatarModel.unscoped(), required: false @@ -65,6 +83,35 @@ export enum ScopeNames { } ] } + + if (options.withAccountBlockerIds) { + query.include.push({ + attributes: [ 'id' ], + model: AccountBlocklistModel.unscoped(), + as: 'BlockedAccounts', + required: false, + where: { + accountId: { + [Op.in]: options.withAccountBlockerIds + } + } + }) + + serverInclude.include = [ + { + attributes: [ 'id' ], + model: ServerBlocklistModel.unscoped(), + required: false, + where: { + accountId: { + [Op.in]: options.withAccountBlockerIds + } + } + } + ] + } + + return query } })) @Table({ @@ -156,19 +203,30 @@ export class AccountModel extends Model { @HasMany(() => VideoCommentModel, { foreignKey: { - allowNull: false + allowNull: true }, onDelete: 'cascade', hooks: true }) VideoComments: VideoCommentModel[] + @HasMany(() => AccountBlocklistModel, { + foreignKey: { + name: 'targetAccountId', + allowNull: false + }, + as: 'BlockedAccounts', + onDelete: 'CASCADE' + }) + BlockedAccounts: AccountBlocklistModel[] + @BeforeDestroy static async sendDeleteIfOwned (instance: AccountModel, options) { if (!instance.Actor) { - instance.Actor = await instance.$get('Actor', { transaction: options.transaction }) as ActorModel + instance.Actor = await instance.$get('Actor', { transaction: options.transaction }) } + await ActorFollowModel.removeFollowsOf(instance.Actor.id, options.transaction) if (instance.isOwned()) { return sendDeleteActor(instance.Actor, options.transaction) } @@ -176,27 +234,11 @@ export class AccountModel extends Model { return undefined } - static load (id: number, transaction?: Transaction) { + static load (id: number, transaction?: Transaction): Bluebird { return AccountModel.findByPk(id, { transaction }) } - static loadByUUID (uuid: string) { - const query = { - include: [ - { - model: ActorModel, - required: true, - where: { - uuid - } - } - ] - } - - return AccountModel.findOne(query) - } - - static loadByNameWithHost (nameWithHost: string) { + static loadByNameWithHost (nameWithHost: string): Bluebird { const [ accountName, host ] = nameWithHost.split('@') if (!host || host === WEBSERVER.HOST) return AccountModel.loadLocalByName(accountName) @@ -204,37 +246,47 @@ export class AccountModel extends Model { return AccountModel.loadByNameAndHost(accountName, host) } - static loadLocalByName (name: string) { - const query = { - where: { - [ Op.or ]: [ - { - userId: { - [ Op.ne ]: null + static loadLocalByName (name: string): Bluebird { + const fun = () => { + const query = { + where: { + [Op.or]: [ + { + userId: { + [Op.ne]: null + } + }, + { + applicationId: { + [Op.ne]: null + } } - }, + ] + }, + include: [ { - applicationId: { - [ Op.ne ]: null + model: ActorModel, + required: true, + where: { + preferredUsername: name } } ] - }, - include: [ - { - model: ActorModel, - required: true, - where: { - preferredUsername: name - } - } - ] + } + + return AccountModel.findOne(query) } - return AccountModel.findOne(query) + return ModelCache.Instance.doCache({ + cacheType: 'local-account-name', + key: name, + fun, + // The server actor never change, so we can easily cache it + whitelist: () => name === SERVER_ACTOR_NAME + }) } - static loadByNameAndHost (name: string, host: string) { + static loadByNameAndHost (name: string, host: string): Bluebird { const query = { include: [ { @@ -259,7 +311,7 @@ export class AccountModel extends Model { return AccountModel.findOne(query) } - static loadByUrl (url: string, transaction?: Transaction) { + static loadByUrl (url: string, transaction?: Transaction): Bluebird { const query = { include: [ { @@ -292,7 +344,30 @@ export class AccountModel extends Model { }) } - static listLocalsForSitemap (sort: string) { + static loadAccountIdFromVideo (videoId: number): Bluebird { + const query = { + include: [ + { + attributes: [ 'id', 'accountId' ], + model: VideoChannelModel.unscoped(), + required: true, + include: [ + { + attributes: [ 'id', 'channelId' ], + model: VideoModel.unscoped(), + where: { + id: videoId + } + } + ] + } + ] + } + + return AccountModel.findOne(query) + } + + static listLocalsForSitemap (sort: string): Bluebird { const query = { attributes: [ ], offset: 0, @@ -313,7 +388,11 @@ export class AccountModel extends Model { .findAll(query) } - toFormattedJSON (): Account { + getClientUrl () { + return WEBSERVER.URL + '/accounts/' + this.Actor.getIdentifier() + } + + toFormattedJSON (this: MAccountFormattable): Account { const actor = this.Actor.toFormattedJSON() const account = { id: this.id, @@ -327,12 +406,11 @@ export class AccountModel extends Model { return Object.assign(actor, account) } - toFormattedSummaryJSON (): AccountSummary { - const actor = this.Actor.toFormattedJSON() + toFormattedSummaryJSON (this: MAccountSummaryFormattable): AccountSummary { + const actor = this.Actor.toFormattedSummaryJSON() return { id: this.id, - uuid: actor.uuid, name: actor.name, displayName: this.getDisplayName(), url: actor.url, @@ -341,8 +419,8 @@ export class AccountModel extends Model { } } - toActivityPubObject () { - const obj = this.Actor.toActivityPubObject(this.name, 'Account') + toActivityPubObject (this: MAccountAP) { + const obj = this.Actor.toActivityPubObject(this.name) return Object.assign(obj, { summary: this.description @@ -360,4 +438,8 @@ export class AccountModel extends Model { getDisplayName () { return this.name } + + isBlocked () { + return this.BlockedAccounts && this.BlockedAccounts.length !== 0 + } }