Merge branch 'master' into develop

This commit is contained in:
Barış Soner Uşaklı
2025-02-26 11:52:18 -05:00
7 changed files with 73 additions and 9 deletions

View File

@@ -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: {

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -4,7 +4,7 @@
<div><i class="fa fa-sm fa-reply opacity-50"></i></div>
<div class="d-flex flex-nowrap gap-1 align-items-center">
<a href="{config.relative_path}/user/{messages.parent.user.userslug}" class="text-decoration-none lh-1">{buildAvatar(messages.parent.user, "14px", true, "not-responsive align-middle")}</a>
<a class="chat-user fw-semibold" href="{config.relative_path}/user/{messages.parent.user.userslug}">{messages.parent.user.displayname}</a>
<a class="chat-user fw-semibold text-truncate" style="max-width: 150px;" href="{config.relative_path}/user/{messages.parent.user.userslug}">{messages.parent.user.displayname}</a>
</div>
<span class="chat-timestamp text-muted timeago text-nowrap hidden" title="{messages.parent.timestampISO}"></span>
</div>

View File

@@ -3,7 +3,7 @@
<div><i class="fa fa-fw fa-reply opacity-50"></i></div>
<div class="d-flex flex-nowrap gap-1 align-items-center">
<a href="{config.relative_path}/user/{./parent.user.userslug}" class="text-decoration-none lh-1">{buildAvatar(./parent.user, "16px", true, "not-responsive align-middle")}</a>
<a class="fw-semibold" href="{config.relative_path}/user/{./parent.user.userslug}">{./parent.user.displayname}</a>
<a class="fw-semibold text-truncate" style="max-width: 150px;" href="{config.relative_path}/user/{./parent.user.userslug}">{./parent.user.displayname}</a>
</div>
<a href="{config.relative_path}/post/{./parent.pid}" class="text-muted timeago text-nowrap hidden" title="{./parent.timestampISO}"></a>

View File

@@ -350,7 +350,7 @@ describe('ActivityPub integration', () => {
});
});
describe.only('Category Actor endpoint', () => {
describe('Category Actor endpoint', () => {
let cid;
let slug;
let description;

View File

@@ -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: '<b>Baz quux</b>',
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: '<b>Baz quux</b>',
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;