X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fmodels%2Factivitypub%2Factor.ts;h=05de1905d57a1eb6401bb98e498660089adfb73f;hb=8424c4026afd7304880a4ce8138a04ffb3d8c938;hp=dda57a8ba172264933a03fee9bf9723c40debb05;hpb=88108880bbdba473cfe36ecbebc1c3c4f972e102;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/models/activitypub/actor.ts b/server/models/activitypub/actor.ts index dda57a8ba..05de1905d 100644 --- a/server/models/activitypub/actor.ts +++ b/server/models/activitypub/actor.ts @@ -7,13 +7,11 @@ import { Column, CreatedAt, DataType, - Default, DefaultScope, ForeignKey, HasMany, HasOne, Is, - IsUUID, Model, Scopes, Table, @@ -30,14 +28,25 @@ import { isActorPublicKeyValid } from '../../helpers/custom-validators/activitypub/actor' import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' -import { ACTIVITY_PUB, ACTIVITY_PUB_ACTOR_TYPES, CONFIG, CONSTRAINTS_FIELDS } from '../../initializers' +import { ACTIVITY_PUB, ACTIVITY_PUB_ACTOR_TYPES, CONSTRAINTS_FIELDS, WEBSERVER } from '../../initializers/constants' import { AccountModel } from '../account/account' import { AvatarModel } from '../avatar/avatar' import { ServerModel } from '../server/server' -import { throwIfNotValid } from '../utils' +import { isOutdated, throwIfNotValid } from '../utils' import { VideoChannelModel } from '../video/video-channel' import { ActorFollowModel } from './actor-follow' import { VideoModel } from '../video/video' +import { + MActor, + MActorAccountChannelId, + MActorAP, + MActorFormattable, + MActorFull, + MActorHost, + MActorServer, + MActorSummaryFormattable +} from '../../typings/models' +import * as Bluebird from 'bluebird' enum ScopeNames { FULL = 'FULL' @@ -56,46 +65,46 @@ export const unusedActorAttributesForAPI = [ 'updatedAt' ] -@DefaultScope({ +@DefaultScope(() => ({ include: [ { - model: () => ServerModel, + model: ServerModel, required: false }, { - model: () => AvatarModel, + model: AvatarModel, required: false } ] -}) -@Scopes({ +})) +@Scopes(() => ({ [ScopeNames.FULL]: { include: [ { - model: () => AccountModel.unscoped(), + model: AccountModel.unscoped(), required: false }, { - model: () => VideoChannelModel.unscoped(), + model: VideoChannelModel.unscoped(), required: false, include: [ { - model: () => AccountModel, + model: AccountModel, required: true } ] }, { - model: () => ServerModel, + model: ServerModel, required: false }, { - model: () => AvatarModel, + model: AvatarModel, required: false } ] } -}) +})) @Table({ tableName: 'actor', indexes: [ @@ -119,10 +128,6 @@ export const unusedActorAttributesForAPI = [ { fields: [ 'avatarId' ] }, - { - fields: [ 'uuid' ], - unique: true - }, { fields: [ 'followersUrl' ] } @@ -131,15 +136,9 @@ export const unusedActorAttributesForAPI = [ export class ActorModel extends Model { @AllowNull(false) - @Column(DataType.ENUM(values(ACTIVITY_PUB_ACTOR_TYPES))) + @Column(DataType.ENUM(...values(ACTIVITY_PUB_ACTOR_TYPES))) type: ActivityPubActorType - @AllowNull(false) - @Default(DataType.UUIDV4) - @IsUUID(4) - @Column(DataType.UUID) - uuid: string - @AllowNull(false) @Is('ActorPreferredUsername', value => throwIfNotValid(value, isActorPreferredUsernameValid, 'actor preferred username')) @Column @@ -151,12 +150,12 @@ export class ActorModel extends Model { url: string @AllowNull(true) - @Is('ActorPublicKey', value => throwIfNotValid(value, isActorPublicKeyValid, 'public key')) + @Is('ActorPublicKey', value => throwIfNotValid(value, isActorPublicKeyValid, 'public key', true)) @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.PUBLIC_KEY.max)) publicKey: string @AllowNull(true) - @Is('ActorPublicKey', value => throwIfNotValid(value, isActorPrivateKeyValid, 'private key')) + @Is('ActorPublicKey', value => throwIfNotValid(value, isActorPrivateKeyValid, 'private key', true)) @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.PRIVATE_KEY.max)) privateKey: string @@ -175,8 +174,8 @@ export class ActorModel extends Model { @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max)) inboxUrl: string - @AllowNull(false) - @Is('ActorOutboxUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'outbox url')) + @AllowNull(true) + @Is('ActorOutboxUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'outbox url', true)) @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max)) outboxUrl: string @@ -185,13 +184,13 @@ export class ActorModel extends Model { @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max)) sharedInboxUrl: string - @AllowNull(false) - @Is('ActorFollowersUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'followers url')) + @AllowNull(true) + @Is('ActorFollowersUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'followers url', true)) @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max)) followersUrl: string - @AllowNull(false) - @Is('ActorFollowingUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'following url')) + @AllowNull(true) + @Is('ActorFollowingUrl', value => throwIfNotValid(value, isActivityPubUrlValid, 'following url', true)) @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max)) followingUrl: string @@ -264,11 +263,15 @@ export class ActorModel extends Model { }) VideoChannel: VideoChannelModel - static load (id: number) { - return ActorModel.unscoped().findById(id) + static load (id: number): Bluebird { + return ActorModel.unscoped().findByPk(id) } - static loadAccountActorByVideoId (videoId: number, transaction: Sequelize.Transaction) { + static loadFull (id: number): Bluebird { + return ActorModel.scope(ScopeNames.FULL).findByPk(id) + } + + static loadFromAccountByVideoId (videoId: number, transaction: Sequelize.Transaction): Bluebird { const query = { include: [ { @@ -280,14 +283,16 @@ export class ActorModel extends Model { attributes: [ 'id' ], model: VideoChannelModel.unscoped(), required: true, - include: { - attributes: [ 'id' ], - model: VideoModel.unscoped(), - required: true, - where: { - id: videoId + include: [ + { + attributes: [ 'id' ], + model: VideoModel.unscoped(), + required: true, + where: { + id: videoId + } } - } + ] } ] } @@ -295,7 +300,7 @@ export class ActorModel extends Model { transaction } - return ActorModel.unscoped().findOne(query as any) // FIXME: typings + return ActorModel.unscoped().findOne(query) } static isActorUrlExist (url: string) { @@ -310,7 +315,7 @@ export class ActorModel extends Model { .then(a => !!a) } - static listByFollowersUrls (followersUrls: string[], transaction?: Sequelize.Transaction) { + static listByFollowersUrls (followersUrls: string[], transaction?: Sequelize.Transaction): Bluebird { const query = { where: { followersUrl: { @@ -323,7 +328,7 @@ export class ActorModel extends Model { return ActorModel.scope(ScopeNames.FULL).findAll(query) } - static loadLocalByName (preferredUsername: string, transaction?: Sequelize.Transaction) { + static loadLocalByName (preferredUsername: string, transaction?: Sequelize.Transaction): Bluebird { const query = { where: { preferredUsername, @@ -335,7 +340,7 @@ export class ActorModel extends Model { return ActorModel.scope(ScopeNames.FULL).findOne(query) } - static loadByNameAndHost (preferredUsername: string, host: string) { + static loadByNameAndHost (preferredUsername: string, host: string): Bluebird { const query = { where: { preferredUsername @@ -354,7 +359,7 @@ export class ActorModel extends Model { return ActorModel.scope(ScopeNames.FULL).findOne(query) } - static loadByUrl (url: string, transaction?: Sequelize.Transaction) { + static loadByUrl (url: string, transaction?: Sequelize.Transaction): Bluebird { const query = { where: { url @@ -377,7 +382,7 @@ export class ActorModel extends Model { return ActorModel.unscoped().findOne(query) } - static loadByUrlAndPopulateAccountAndChannel (url: string, transaction?: Sequelize.Transaction) { + static loadByUrlAndPopulateAccountAndChannel (url: string, transaction?: Sequelize.Transaction): Bluebird { const query = { where: { url @@ -389,8 +394,7 @@ export class ActorModel extends Model { } static incrementFollows (id: number, column: 'followersCount' | 'followingCount', by: number) { - // FIXME: typings - return (ActorModel as any).increment(column, { + return ActorModel.increment(column, { by, where: { id @@ -398,36 +402,35 @@ export class ActorModel extends Model { }) } - toFormattedJSON () { + toFormattedSummaryJSON (this: MActorSummaryFormattable) { let avatar: Avatar = null if (this.Avatar) { avatar = this.Avatar.toFormattedJSON() } return { - id: this.id, url: this.url, - uuid: this.uuid, name: this.preferredUsername, host: this.getHost(), + avatar + } + } + + toFormattedJSON (this: MActorFormattable) { + const base = this.toFormattedSummaryJSON() + + return Object.assign(base, { + id: this.id, hostRedundancyAllowed: this.getRedundancyAllowed(), followingCount: this.followingCount, followersCount: this.followersCount, - avatar, createdAt: this.createdAt, updatedAt: this.updatedAt - } + }) } - toActivityPubObject (name: string, type: 'Account' | 'Application' | 'VideoChannel') { + toActivityPubObject (this: MActorAP, name: string) { let activityPubType - if (type === 'Account') { - activityPubType = 'Person' as 'Person' - } else if (type === 'Application') { - activityPubType = 'Application' as 'Application' - } else { // VideoChannel - activityPubType = 'Group' as 'Group' - } let icon = undefined if (this.avatarId) { @@ -440,10 +443,11 @@ export class ActorModel extends Model { } const json = { - type: activityPubType, + type: this.type, id: this.url, following: this.getFollowingUrl(), followers: this.getFollowersUrl(), + playlists: this.getPlaylistsUrl(), inbox: this.inboxUrl, outbox: this.outboxUrl, preferredUsername: this.preferredUsername, @@ -452,7 +456,6 @@ export class ActorModel extends Model { endpoints: { sharedInbox: this.sharedInboxUrl }, - uuid: this.uuid, publicKey: { id: this.getPublicKeyUrl(), owner: this.url, @@ -494,6 +497,10 @@ export class ActorModel extends Model { return this.url + '/followers' } + getPlaylistsUrl () { + return this.url + '/playlists' + } + getPublicKeyUrl () { return this.url + '#main-key' } @@ -502,7 +509,7 @@ export class ActorModel extends Model { return this.serverId === null } - getWebfingerUrl () { + getWebfingerUrl (this: MActorServer) { return 'acct:' + this.preferredUsername + '@' + this.getHost() } @@ -510,8 +517,8 @@ export class ActorModel extends Model { return this.Server ? `${this.preferredUsername}@${this.Server.host}` : this.preferredUsername } - getHost () { - return this.Server ? this.Server.host : CONFIG.WEBSERVER.HOST + getHost (this: MActorHost) { + return this.Server ? this.Server.host : WEBSERVER.HOST } getRedundancyAllowed () { @@ -521,17 +528,12 @@ export class ActorModel extends Model { getAvatarUrl () { if (!this.avatarId) return undefined - return CONFIG.WEBSERVER.URL + this.Avatar.getWebserverPath() + return WEBSERVER.URL + this.Avatar.getStaticPath() } isOutdated () { if (this.isOwned()) return false - const now = Date.now() - const createdAtTime = this.createdAt.getTime() - const updatedAtTime = this.updatedAt.getTime() - - return (now - createdAtTime) > ACTIVITY_PUB.ACTOR_REFRESH_INTERVAL && - (now - updatedAtTime) > ACTIVITY_PUB.ACTOR_REFRESH_INTERVAL + return isOutdated(this, ACTIVITY_PUB.ACTOR_REFRESH_INTERVAL) } }