From 194d656bb47bb2fd5c213ea0d8b731b26cad726c Mon Sep 17 00:00:00 2001
From: Kagami Sascha Rosylight <saschanaz@outlook.com>
Date: Fri, 17 Feb 2023 09:06:31 +0100
Subject: [PATCH 1/2] fix: normalize empty value of `name` into an absent value

---
 .../backend/src/core/activitypub/models/ApPersonService.ts     | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index a1fdd7a198..d06958da0c 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -164,6 +164,9 @@ export class ApPersonService implements OnModuleInit {
 				throw new Error('invalid Actor: wrong name');
 			}
 			x.name = truncate(x.name, nameLength);
+		} else if (x.name === '') {
+			// Mastodon emits empty string when the name is not set.
+			x.name = undefined;
 		}
 		if (x.summary) {
 			if (!(typeof x.summary === 'string' && x.summary.length > 0)) {

From 8c64f999dca32a781adfa4ddec2bf8fa63dc1abd Mon Sep 17 00:00:00 2001
From: Kagami Sascha Rosylight <saschanaz@outlook.com>
Date: Sun, 19 Feb 2023 09:49:18 +0100
Subject: [PATCH 2/2] Add test

---
 packages/backend/test/unit/activitypub.ts | 68 +++++++++++++----------
 1 file changed, 38 insertions(+), 30 deletions(-)

diff --git a/packages/backend/test/unit/activitypub.ts b/packages/backend/test/unit/activitypub.ts
index 3d0032507e..5335dff6d5 100644
--- a/packages/backend/test/unit/activitypub.ts
+++ b/packages/backend/test/unit/activitypub.ts
@@ -11,8 +11,25 @@ import { GlobalModule } from '@/GlobalModule.js';
 import { CoreModule } from '@/core/CoreModule.js';
 import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
 import { LoggerService } from '@/core/LoggerService.js';
+import type { IActor } from '@/core/activitypub/type.js';
 import { MockResolver } from '../misc/mock-resolver.js';
 
+const host = 'https://host1.test';
+
+function createRandomActor(): IActor & { id: string } {
+	const preferredUsername = `${rndstr('A-Z', 4)}${rndstr('a-z', 4)}`;
+	const actorId = `${host}/users/${preferredUsername.toLowerCase()}`;
+
+	return {
+		'@context': 'https://www.w3.org/ns/activitystreams',
+		id: actorId,
+		type: 'Person',
+		preferredUsername,
+		inbox: `${actorId}/inbox`,
+		outbox: `${actorId}/outbox`,
+	};
+}
+
 describe('ActivityPub', () => {
 	let noteService: ApNoteService;
 	let personService: ApPersonService;
@@ -36,18 +53,7 @@ describe('ActivityPub', () => {
 	});
 
 	describe('Parse minimum object', () => {
-		const host = 'https://host1.test';
-		const preferredUsername = `${rndstr('A-Z', 4)}${rndstr('a-z', 4)}`;
-		const actorId = `${host}/users/${preferredUsername.toLowerCase()}`;
-
-		const actor = {
-			'@context': 'https://www.w3.org/ns/activitystreams',
-			id: actorId,
-			type: 'Person',
-			preferredUsername,
-			inbox: `${actorId}/inbox`,
-			outbox: `${actorId}/outbox`,
-		};
+		const actor = createRandomActor();
 
 		const post = {
 			'@context': 'https://www.w3.org/ns/activitystreams',
@@ -80,29 +86,31 @@ describe('ActivityPub', () => {
 		});
 	});
 
-	describe('Truncate long name', () => {
-		const host = 'https://host1.test';
-		const preferredUsername = `${rndstr('A-Z', 4)}${rndstr('a-z', 4)}`;
-		const actorId = `${host}/users/${preferredUsername.toLowerCase()}`;
+	describe('Name field', () => {
+		test('Truncate long name', async () => {
+			const actor = {
+				...createRandomActor(),
+				name: rndstr('0-9a-z', 129),
+			};
 
-		const name = rndstr('0-9a-z', 129);
-
-		const actor = {
-			'@context': 'https://www.w3.org/ns/activitystreams',
-			id: actorId,
-			type: 'Person',
-			preferredUsername,
-			name,
-			inbox: `${actorId}/inbox`,
-			outbox: `${actorId}/outbox`,
-		};
-
-		test('Actor', async () => {
 			resolver._register(actor.id, actor);
 
 			const user = await personService.createPerson(actor.id, resolver);
 
-			assert.deepStrictEqual(user.name, actor.name.substr(0, 128));
+			assert.deepStrictEqual(user.name, actor.name.slice(0, 128));
+		});
+
+		test('Normalize empty name', async () => {
+			const actor = {
+				...createRandomActor(),
+				name: '',
+			};
+
+			resolver._register(actor.id, actor);
+
+			const user = await personService.createPerson(actor.id, resolver);
+
+			assert.strictEqual(user.name, null);
 		});
 	});
 });