From a66c2e3252d6cca8958959966f42494ded564023 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 7 May 2021 08:59:59 +0200 Subject: [PATCH] Fix remote actor creation date --- .../custom-validators/activitypub/actor.ts | 39 +++++++++---------- server/initializers/constants.ts | 2 +- .../0645-actor-remote-creation-date.ts | 26 +++++++++++++ server/lib/activitypub/actor.ts | 4 ++ server/models/account/account.ts | 2 - server/models/activitypub/actor.ts | 15 +++++-- server/models/video/video-channel.ts | 2 - .../tests/api/users/users-multiple-servers.ts | 28 +++++++------ server/types/models/account/actor.ts | 2 +- .../models/activitypub/activitypub-actor.ts | 2 + 10 files changed, 80 insertions(+), 42 deletions(-) create mode 100644 server/initializers/migrations/0645-actor-remote-creation-date.ts diff --git a/server/helpers/custom-validators/activitypub/actor.ts b/server/helpers/custom-validators/activitypub/actor.ts index 877345157..675a7b663 100644 --- a/server/helpers/custom-validators/activitypub/actor.ts +++ b/server/helpers/custom-validators/activitypub/actor.ts @@ -1,6 +1,6 @@ import validator from 'validator' import { CONSTRAINTS_FIELDS } from '../../../initializers/constants' -import { exists, isArray } from '../misc' +import { exists, isArray, isDateValid } from '../misc' import { isActivityPubUrlValid, isBaseActivityValid, setValidAttributedTo } from './misc' import { isHostValid } from '../servers' import { peertubeTruncate } from '@server/helpers/core-utils' @@ -47,7 +47,21 @@ function isActorPrivateKeyValid (privateKey: string) { validator.isLength(privateKey, CONSTRAINTS_FIELDS.ACTORS.PRIVATE_KEY) } -function isActorObjectValid (actor: any) { +function isActorFollowingCountValid (value: string) { + return exists(value) && validator.isInt('' + value, { min: 0 }) +} + +function isActorFollowersCountValid (value: string) { + return exists(value) && validator.isInt('' + value, { min: 0 }) +} + +function isActorDeleteActivityValid (activity: any) { + return isBaseActivityValid(activity, 'Delete') +} + +function sanitizeAndCheckActorObject (actor: any) { + normalizeActor(actor) + return exists(actor) && isActivityPubUrlValid(actor.id) && isActorTypeValid(actor.type) && @@ -68,24 +82,6 @@ function isActorObjectValid (actor: any) { (actor.type !== 'Group' || actor.attributedTo.length !== 0) } -function isActorFollowingCountValid (value: string) { - return exists(value) && validator.isInt('' + value, { min: 0 }) -} - -function isActorFollowersCountValid (value: string) { - return exists(value) && validator.isInt('' + value, { min: 0 }) -} - -function isActorDeleteActivityValid (activity: any) { - return isBaseActivityValid(activity, 'Delete') -} - -function sanitizeAndCheckActorObject (object: any) { - normalizeActor(object) - - return isActorObjectValid(object) -} - function normalizeActor (actor: any) { if (!actor) return @@ -95,6 +91,8 @@ function normalizeActor (actor: any) { actor.url = actor.url.href || actor.url.url } + if (!isDateValid(actor.published)) actor.published = undefined + if (actor.summary && typeof actor.summary === 'string') { actor.summary = peertubeTruncate(actor.summary, { length: CONSTRAINTS_FIELDS.USERS.DESCRIPTION.max }) @@ -135,7 +133,6 @@ export { isActorPublicKeyValid, isActorPreferredUsernameValid, isActorPrivateKeyValid, - isActorObjectValid, isActorFollowingCountValid, isActorFollowersCountValid, isActorDeleteActivityValid, diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index d390fd95e..f807a1e58 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts @@ -24,7 +24,7 @@ import { CONFIG, registerConfigChangedHandler } from './config' // --------------------------------------------------------------------------- -const LAST_MIGRATION_VERSION = 640 +const LAST_MIGRATION_VERSION = 645 // --------------------------------------------------------------------------- diff --git a/server/initializers/migrations/0645-actor-remote-creation-date.ts b/server/initializers/migrations/0645-actor-remote-creation-date.ts new file mode 100644 index 000000000..38b3b881c --- /dev/null +++ b/server/initializers/migrations/0645-actor-remote-creation-date.ts @@ -0,0 +1,26 @@ +import * as Sequelize from 'sequelize' + +async function up (utils: { + transaction: Sequelize.Transaction + queryInterface: Sequelize.QueryInterface + sequelize: Sequelize.Sequelize + db: any +}): Promise { + { + const data = { + type: Sequelize.DATE, + defaultValue: null, + allowNull: true + } + await utils.queryInterface.addColumn('actor', 'remoteCreatedAt', data) + } +} + +function down (options) { + throw new Error('Not implemented.') +} + +export { + up, + down +} diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts index eec951d4e..34d53bd52 100644 --- a/server/lib/activitypub/actor.ts +++ b/server/lib/activitypub/actor.ts @@ -154,6 +154,8 @@ async function updateActorInstance (actorInstance: ActorModel, attributes: Activ const followersCount = await fetchActorTotalItems(attributes.followers) const followingCount = await fetchActorTotalItems(attributes.following) + logger.info('coucou', { attributes }) + actorInstance.type = attributes.type actorInstance.preferredUsername = attributes.preferredUsername actorInstance.url = attributes.id @@ -165,6 +167,8 @@ async function updateActorInstance (actorInstance: ActorModel, attributes: Activ actorInstance.followersUrl = attributes.followers actorInstance.followingUrl = attributes.following + if (attributes.published) actorInstance.remoteCreatedAt = new Date(attributes.published) + if (attributes.endpoints?.sharedInbox) { actorInstance.sharedInboxUrl = attributes.endpoints.sharedInbox } diff --git a/server/models/account/account.ts b/server/models/account/account.ts index 312451abe..44be0fd3c 100644 --- a/server/models/account/account.ts +++ b/server/models/account/account.ts @@ -411,8 +411,6 @@ export class AccountModel extends Model { id: this.id, displayName: this.getDisplayName(), description: this.description, - createdAt: this.createdAt, - updatedAt: this.updatedAt, userId: this.userId ? this.userId : undefined } diff --git a/server/models/activitypub/actor.ts b/server/models/activitypub/actor.ts index 19f3f7e04..396a52337 100644 --- a/server/models/activitypub/actor.ts +++ b/server/models/activitypub/actor.ts @@ -69,9 +69,7 @@ export const unusedActorAttributesForAPI = [ 'outboxUrl', 'sharedInboxUrl', 'followersUrl', - 'followingUrl', - 'createdAt', - 'updatedAt' + 'followingUrl' ] @DefaultScope(() => ({ @@ -222,6 +220,10 @@ export class ActorModel extends Model { @Column(DataType.STRING(CONSTRAINTS_FIELDS.ACTORS.URL.max)) followingUrl: string + @AllowNull(true) + @Column + remoteCreatedAt: Date + @CreatedAt createdAt: Date @@ -555,7 +557,7 @@ export class ActorModel extends Model { followingCount: this.followingCount, followersCount: this.followersCount, banner, - createdAt: this.createdAt, + createdAt: this.getCreatedAt(), updatedAt: this.updatedAt }) } @@ -608,6 +610,7 @@ export class ActorModel extends Model { owner: this.url, publicKeyPem: this.publicKey }, + published: this.getCreatedAt().toISOString(), icon, image } @@ -690,4 +693,8 @@ export class ActorModel extends Model { return isOutdated(this, ACTIVITY_PUB.ACTOR_REFRESH_INTERVAL) } + + getCreatedAt (this: MActorAPChannel | MActorAPAccount | MActorFormattable) { + return this.remoteCreatedAt || this.createdAt + } } diff --git a/server/models/video/video-channel.ts b/server/models/video/video-channel.ts index b7ffbd3b1..b627595c9 100644 --- a/server/models/video/video-channel.ts +++ b/server/models/video/video-channel.ts @@ -653,8 +653,6 @@ ON "Account->Actor"."serverId" = "Account->Actor->Server"."id"` description: this.description, support: this.support, isLocal: this.Actor.isOwned(), - createdAt: this.createdAt, - updatedAt: this.updatedAt, ownerAccount: undefined, videosCount, viewsPerDay diff --git a/server/tests/api/users/users-multiple-servers.ts b/server/tests/api/users/users-multiple-servers.ts index dcd03879b..f60c66e4b 100644 --- a/server/tests/api/users/users-multiple-servers.ts +++ b/server/tests/api/users/users-multiple-servers.ts @@ -130,26 +130,32 @@ describe('Test users with multiple servers', function () { }) it('Should have updated my profile on other servers too', async function () { + let createdAt: string | Date + for (const server of servers) { const resAccounts = await getAccountsList(server.url, '-createdAt') - const rootServer1List = resAccounts.body.data.find(a => a.name === 'root' && a.host === 'localhost:' + servers[0].port) as Account - expect(rootServer1List).not.to.be.undefined + const resList = resAccounts.body.data.find(a => a.name === 'root' && a.host === 'localhost:' + servers[0].port) as Account + expect(resList).not.to.be.undefined + + const resAccount = await getAccount(server.url, resList.name + '@' + resList.host) + const account = resAccount.body as Account + + if (!createdAt) createdAt = account.createdAt - const resAccount = await getAccount(server.url, rootServer1List.name + '@' + rootServer1List.host) - const rootServer1Get = resAccount.body as Account - expect(rootServer1Get.name).to.equal('root') - expect(rootServer1Get.host).to.equal('localhost:' + servers[0].port) - expect(rootServer1Get.displayName).to.equal('my super display name') - expect(rootServer1Get.description).to.equal('my super description updated') + expect(account.name).to.equal('root') + expect(account.host).to.equal('localhost:' + servers[0].port) + expect(account.displayName).to.equal('my super display name') + expect(account.description).to.equal('my super description updated') + expect(createdAt).to.equal(account.createdAt) if (server.serverNumber === 1) { - expect(rootServer1Get.userId).to.be.a('number') + expect(account.userId).to.be.a('number') } else { - expect(rootServer1Get.userId).to.be.undefined + expect(account.userId).to.be.undefined } - await testImage(server.url, 'avatar2-resized', rootServer1Get.avatar.path, '.png') + await testImage(server.url, 'avatar2-resized', account.avatar.path, '.png') } }) diff --git a/server/types/models/account/actor.ts b/server/types/models/account/actor.ts index 8f3f30074..0b620872e 100644 --- a/server/types/models/account/actor.ts +++ b/server/types/models/account/actor.ts @@ -150,7 +150,7 @@ export type MActorSummaryFormattable = export type MActorFormattable = MActorSummaryFormattable & - Pick & + Pick & Use<'Server', MServerHost & Partial>> & UseOpt<'Banner', MActorImageFormattable> diff --git a/shared/models/activitypub/activitypub-actor.ts b/shared/models/activitypub/activitypub-actor.ts index c59be3f3b..09d4f7402 100644 --- a/shared/models/activitypub/activitypub-actor.ts +++ b/shared/models/activitypub/activitypub-actor.ts @@ -29,4 +29,6 @@ export interface ActivityPubActor { icon?: ActivityIconObject image?: ActivityIconObject + + published?: string } -- 2.41.0