diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index a901a4ee46..5cf00383ef 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -13,13 +13,14 @@ on: # A workflow run is made up of one or more jobs that can run sequentially or in parallel permissions: contents: read + packages: write jobs: release: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: fetch-depth: 0 @@ -32,14 +33,15 @@ jobs: - name: Login to Docker Hub uses: docker/login-action@v2 with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Docker meta id: meta uses: docker/metadata-action@v4 with: - images: nodebb/docker + images: ghcr.io/${{ github.repository }} tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} diff --git a/CHANGELOG.md b/CHANGELOG.md index 6feab404d2..e07cc91229 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,51 @@ +#### v2.8.10 (2023-03-27) + +##### Chores + +* up composer-default (e9a8e195) +* incrementing version number - v2.8.9 (57f14e41) +* update changelog for v2.8.9 (18b2150e) +* incrementing version number - v2.8.8 (b331b942) +* incrementing version number - v2.8.7 (3f8248d6) +* incrementing version number - v2.8.6 (af6ce447) +* incrementing version number - v2.8.5 (bff5ce2d) +* incrementing version number - v2.8.4 (a46b2bbc) +* incrementing version number - v2.8.3 (c20b20a7) +* incrementing version number - v2.8.2 (050e43f8) +* incrementing version number - v2.8.1 (727f879e) +* incrementing version number - v2.8.0 (8e77673d) +* incrementing version number - v2.7.0 (96cc0617) +* incrementing version number - v2.6.1 (7e52a7a5) +* incrementing version number - v2.6.0 (e7fcf482) +* incrementing version number - v2.5.8 (dec0e7de) +* incrementing version number - v2.5.7 (5836bf4a) +* incrementing version number - v2.5.6 (c7bd7dbf) +* incrementing version number - v2.5.5 (3509ed94) +* incrementing version number - v2.5.4 (e83260ca) +* incrementing version number - v2.5.3 (7e922936) +* incrementing version number - v2.5.2 (babcd17e) +* incrementing version number - v2.5.1 (ce3aa950) +* incrementing version number - v2.5.0 (01d276cb) +* incrementing version number - v2.4.5 (dd3e1a28) +* incrementing version number - v2.4.4 (d5525c87) +* incrementing version number - v2.4.3 (9c647c6c) +* incrementing version number - v2.4.2 (3aa7b855) +* incrementing version number - v2.4.1 (60cbd148) +* incrementing version number - v2.4.0 (4834cde3) +* incrementing version number - v2.3.1 (d2425942) +* incrementing version number - v2.3.0 (046ea120) + +##### Bug Fixes + +* #11403, remove loader.js crash counter logic (830f142b) +* don't crash if event name is not a string (37b48b82) +* closes #11173, move cache clear code (c2961ad4) + +##### Other Changes + +* fix arrow (1aff9cad) +* whitespace (894f392b) + #### v2.8.9 (2023-03-19) ##### Chores diff --git a/src/controllers/authentication.js b/src/controllers/authentication.js index 82dc6b1660..bb6e6bf49f 100644 --- a/src/controllers/authentication.js +++ b/src/controllers/authentication.js @@ -383,7 +383,7 @@ authenticationController.onSuccessfulLogin = async function (req, uid) { }), user.auth.addSession(uid, req.sessionID), user.updateLastOnlineTime(uid), - user.updateOnlineUsers(uid), + user.onUserOnline(uid, Date.now()), analytics.increment('logins'), db.incrObjectFieldBy('global', 'loginCount', 1), ]); diff --git a/src/socket.io/index.js b/src/socket.io/index.js index 30e4e23581..963267ed9a 100644 --- a/src/socket.io/index.js +++ b/src/socket.io/index.js @@ -112,48 +112,49 @@ async function onMessage(socket, payload) { return winston.warn('[socket.io] Empty payload'); } - const eventName = payload.data[0]; + let eventName = payload.data[0]; const params = typeof payload.data[1] === 'function' ? {} : payload.data[1]; const callback = typeof payload.data[payload.data.length - 1] === 'function' ? payload.data[payload.data.length - 1] : function () {}; - if (!eventName) { - return winston.warn('[socket.io] Empty method name'); - } - - if (typeof eventName !== 'string') { - const escapedName = validator.escape(String(eventName)); - return callback({ message: `[[error:invalid-event, ${escapedName}]]` }); - } + try { + if (!eventName) { + return winston.warn('[socket.io] Empty method name'); + } - const parts = eventName.split('.'); - const namespace = parts[0]; - const methodToCall = parts.reduce((prev, cur) => { - if (prev !== null && prev[cur] && (!prev.hasOwnProperty || prev.hasOwnProperty(cur))) { - return prev[cur]; + if (typeof eventName !== 'string') { + eventName = typeof eventName; + const escapedName = validator.escape(eventName); + return callback({ message: `[[error:invalid-event, ${escapedName}]]` }); } - return null; - }, Namespaces); - if (!methodToCall || typeof methodToCall !== 'function') { - if (process.env.NODE_ENV === 'development') { - winston.warn(`[socket.io] Unrecognized message: ${eventName}`); + const parts = eventName.split('.'); + const namespace = parts[0]; + const methodToCall = parts.reduce((prev, cur) => { + if (prev !== null && prev[cur] && (!prev.hasOwnProperty || prev.hasOwnProperty(cur))) { + return prev[cur]; + } + return null; + }, Namespaces); + + if (!methodToCall || typeof methodToCall !== 'function') { + if (process.env.NODE_ENV === 'development') { + winston.warn(`[socket.io] Unrecognized message: ${eventName}`); + } + const escapedName = validator.escape(String(eventName)); + return callback({ message: `[[error:invalid-event, ${escapedName}]]` }); } - const escapedName = validator.escape(String(eventName)); - return callback({ message: `[[error:invalid-event, ${escapedName}]]` }); - } - socket.previousEvents = socket.previousEvents || []; - socket.previousEvents.push(eventName); - if (socket.previousEvents.length > 20) { - socket.previousEvents.shift(); - } + socket.previousEvents = socket.previousEvents || []; + socket.previousEvents.push(eventName); + if (socket.previousEvents.length > 20) { + socket.previousEvents.shift(); + } - if (!eventName.startsWith('admin.') && ratelimit.isFlooding(socket)) { - winston.warn(`[socket.io] Too many emits! Disconnecting uid : ${socket.uid}. Events : ${socket.previousEvents}`); - return socket.disconnect(); - } + if (!eventName.startsWith('admin.') && ratelimit.isFlooding(socket)) { + winston.warn(`[socket.io] Too many emits! Disconnecting uid : ${socket.uid}. Events : ${socket.previousEvents}`); + return socket.disconnect(); + } - try { await checkMaintenance(socket); await validateSession(socket, '[[error:revalidate-failure]]'); diff --git a/src/user/online.js b/src/user/online.js index ffba4c9a94..b7c6b9d45a 100644 --- a/src/user/online.js +++ b/src/user/online.js @@ -27,9 +27,13 @@ module.exports = function (User) { if (now - parseInt(userOnlineTime, 10) < 300000) { return; } - await db.sortedSetAdd('users:online', now, uid); + await User.onUserOnline(uid, now); topics.pushUnreadCount(uid); - plugins.hooks.fire('action:user.online', { uid: uid, timestamp: now }); + }; + + User.onUserOnline = async (uid, timestamp) => { + await db.sortedSetAdd('users:online', timestamp, uid); + plugins.hooks.fire('action:user.online', { uid, timestamp }); }; User.isOnline = async function (uid) { diff --git a/test/socket.io.js b/test/socket.io.js index 110258a0de..3628e3b0d0 100644 --- a/test/socket.io.js +++ b/test/socket.io.js @@ -110,8 +110,7 @@ describe('socket.io', () => { it('should return error for invalid eventName type', (done) => { const eventName = ['topics.loadMoreTags']; io.emit(eventName, (err) => { - const eventAsString = String(eventName); - assert.strictEqual(err.message, `[[error:invalid-event, ${eventAsString}]]`); + assert.strictEqual(err.message, `[[error:invalid-event, object]]`); done(); }); });