diff --git a/src/routes/well-known.js b/src/routes/well-known.js index becd1370f8..399668b679 100644 --- a/src/routes/well-known.js +++ b/src/routes/well-known.js @@ -39,8 +39,8 @@ module.exports = function (app, middleware, controllers) { const oneMonthAgo = addMonths(new Date(), -1); const sixMonthsAgo = addMonths(new Date(), -6); - const [{ postCount, userCount }, activeMonth, activeHalfyear] = await Promise.all([ - db.getObjectFields('global', ['postCount', 'userCount']), + const [{ postCount, topicCount, userCount }, activeMonth, activeHalfyear] = await Promise.all([ + db.getObjectFields('global', ['postCount', 'topicCount', 'userCount']), db.sortedSetCount('users:online', oneMonthAgo.getTime(), '+inf'), db.sortedSetCount('users:online', sixMonthsAgo.getTime(), '+inf'), ]); @@ -64,7 +64,8 @@ module.exports = function (app, middleware, controllers) { activeMonth: activeMonth, activeHalfyear: activeHalfyear, }, - localPosts: postCount, + localPosts: topicCount, + localComments: postCount - topicCount, }, openRegistrations: meta.config.registrationType === 'normal', metadata: { diff --git a/src/user/email.js b/src/user/email.js index aec9379f41..c14c9c93fc 100644 --- a/src/user/email.js +++ b/src/user/email.js @@ -36,8 +36,10 @@ UserEmail.remove = async function (uid, sessionId) { email: '', 'email:confirmed': 0, }), - db.sortedSetRemove('email:uid', email.toLowerCase()), - db.sortedSetRemove('email:sorted', `${email.toLowerCase()}:${uid}`), + db.sortedSetRemoveBulk([ + ['email:uid', email.toLowerCase()], + ['email:sorted', `${email.toLowerCase()}:${uid}`], + ]), user.email.expireValidation(uid), sessionId ? user.auth.revokeAllSessions(uid, sessionId) : Promise.resolve(), events.log({ @@ -53,7 +55,7 @@ UserEmail.getEmailForValidation = async (uid) => { let email = ''; // check email from confirmObj const code = await db.get(`confirm:byUid:${uid}`); - const confirmObj = await db.getObject(`confirm:${code}`); + const confirmObj = code ? await db.getObject(`confirm:${code}`) : null; if (confirmObj && confirmObj.email && parseInt(uid, 10) === parseInt(confirmObj.uid, 10)) { email = confirmObj.email; } diff --git a/src/user/profile.js b/src/user/profile.js index c150675d6a..3009d0a3d5 100644 --- a/src/user/profile.js +++ b/src/user/profile.js @@ -282,6 +282,9 @@ module.exports = function (User) { if (oldEmail === newEmail) { return; } + if (await User.email.isValidationPending(uid, newEmail)) { + return; + } // 👉 Looking for email change logic? src/user/email.js (UserEmail.confirmByUid) if (newEmail) { diff --git a/src/views/partials/chats/parent.tpl b/src/views/partials/chats/parent.tpl index 2d2e66bf3b..68f91414c5 100644 --- a/src/views/partials/chats/parent.tpl +++ b/src/views/partials/chats/parent.tpl @@ -4,7 +4,7 @@
{buildAvatar(messages.parent.user, "14px", true, "not-responsive align-middle")} - {messages.parent.user.displayname} + {messages.parent.user.displayname}
diff --git a/src/views/partials/topic/post-parent.tpl b/src/views/partials/topic/post-parent.tpl index cabc6bb36c..38f22da616 100644 --- a/src/views/partials/topic/post-parent.tpl +++ b/src/views/partials/topic/post-parent.tpl @@ -3,7 +3,7 @@
{buildAvatar(./parent.user, "16px", true, "not-responsive align-middle")} - {./parent.user.displayname} + {./parent.user.displayname}
diff --git a/test/activitypub.js b/test/activitypub.js index d2c2334140..d05f50e4e6 100644 --- a/test/activitypub.js +++ b/test/activitypub.js @@ -350,7 +350,7 @@ describe('ActivityPub integration', () => { }); }); - describe.only('Category Actor endpoint', () => { + describe('Category Actor endpoint', () => { let cid; let slug; let description; diff --git a/test/activitypub/notes.js b/test/activitypub/notes.js index 482b706d14..803c345c4b 100644 --- a/test/activitypub/notes.js +++ b/test/activitypub/notes.js @@ -3,6 +3,8 @@ const assert = require('assert'); const db = require('../../src/database'); +const meta = require('../../src/meta'); +const install = require('../../src/install'); const user = require('../../src/user'); const categories = require('../../src/categories'); const topics = require('../../src/topics'); @@ -10,6 +12,62 @@ const activitypub = require('../../src/activitypub'); const utils = require('../../src/utils'); describe('Notes', () => { + describe('Assertion', () => { + const baseUrl = 'https://example.org'; + + before(async () => { + meta.config.activitypubEnabled = 1; + await install.giveWorldPrivileges(); + }); + + it('should pull a remote root-level object by its id and create a new topic', async () => { + const uuid = utils.generateUUID(); + const id = `${baseUrl}/resource/${uuid}`; + activitypub._cache.set(`0;${id}`, { + '@context': 'https://www.w3.org/ns/activitystreams', + id, + url: id, + type: 'Note', + to: ['https://www.w3.org/ns/activitystreams#Public'], + cc: ['https://example.org/user/foobar/followers'], + inReplyTo: null, + attributedTo: 'https://example.org/user/foobar', + name: 'Foo Bar', + content: 'Baz quux', + published: new Date().toISOString(), + }); + + const { tid, count } = await activitypub.notes.assert(0, id, { skipChecks: true }); + assert.strictEqual(count, 1); + + const exists = await topics.exists(tid); + assert(exists); + }); + + it('should assert if the cc property is missing', async () => { + const uuid = utils.generateUUID(); + const id = `${baseUrl}/resource/${uuid}`; + activitypub._cache.set(`0;${id}`, { + '@context': 'https://www.w3.org/ns/activitystreams', + id, + url: id, + type: 'Note', + to: ['https://www.w3.org/ns/activitystreams#Public'], + inReplyTo: null, + attributedTo: 'https://example.org/user/foobar', + name: 'Foo Bar', + content: 'Baz quux', + published: new Date().toISOString(), + }); + + const { tid, count } = await activitypub.notes.assert(0, id, { skipChecks: true }); + assert.strictEqual(count, 1); + + const exists = await topics.exists(tid); + assert(exists); + }); + }); + describe('Inbox Synchronization', () => { let cid; let uid;