Skip to content

NodeBB Plugins

Discussion regarding NodeBB Plugin development.

1.8k Topics 15.2k Posts
Most Voted Plugins

Subcategories


  • Have a question about building a plugin? Ask here
    444 Topics
    2k Posts
    Sky FoxxS
    Perfect! Does the job super elegantly thank you
  • Need a plugin developed? Ask here!
    226 Topics
    1k Posts
    juseJ
    like this [image: 1732282083034-snipaste_2024-11-22_21-27-43.png] or [image: 1732282134821-snipaste_2024-11-22_21-28-46.png]
  • What plugin does this with links

    3
    0 Votes
    3 Posts
    781 Views
    J
    @PitaJ said in What plugin does this with links: That doesn't seem right. It's the iframely plugin, I don't know why it's using window.open instead of just target=_blank. Maybe some kind of tracking thing? Well I don’t use that plugin. So, not sure where to look to isolate for a bug report.
  • [nodebb-plugin-prometheus] Prometheus Monitoring for NodeBB

    19
    7 Votes
    19 Posts
    4k Views
    D
    I just release version 0.3.0 of this plugin. The following changes have been implemented: Using action:analytics.increment for analytics counter (better performance and accuracy) Added label viewer to page view that can have the values user, guest, or bot (inspired by an upcoming change in 1.11, you get it early here) Added new metric nodebb_online_guests Added new metric nodebb_eventloop_lag_seconds. This is measured by NodeBB which has a smoothing factored compared to what is measured by NodeJS and provided via nodejs_eventloop_lag_seconds Added new metric nodebb_eventloop_maxlag_seconds. This is the maximum allowed lag for NodeBB. If the lag is getting closer to this value NodeBB will start to issue 503 error codes. The chance a user is getting a 503 is calculate by this formula: (lag - maxLage) / maxLag. @Per0x Sorry it took a while but your metric for online guests is now finally available.
  • Is the official blog avaible to use?

    3
    0 Votes
    3 Posts
    1k Views
    0
    Thank you @baris It's good to know that. Use this together with NodeBB seems awesome.
  • nodebb-plugin-write-api - add custom user fields

    5
    0 Votes
    5 Posts
    2k Views
    barisB
    @hearsedriver Glad you figured it out
  • image over mouse over active links?

    1
    0 Votes
    1 Posts
    365 Views
    DemerzelD
    Hello I would like to display an image over mouse over active links? thx
  • This topic is deleted!

    2
    0 Votes
    2 Posts
    377 Views
  • Category notifications

    1
    0 Votes
    1 Posts
    454 Views
    G
    I'd like to allow for configuring notifications on category level. Is the nodebb-plugin-category-notifications the only option to achieve this? Installing + activation works on my otherwise flawless Nodebb 1.10.1 installation. However hitting Dashboard --> Plugins --> Category Notifications just endlessly shows a spinner. I've filed an issue at https://github.com/NodeBB/nodebb-plugin-category-notifications/issues/9 but received yet no reply. For clarification: Users should receive notifications whenever a new post / reply appears within a given category. Happy to see an other way achieving this.
  • [nodebb-plugin-alignment] and [nodebb-plugin-simple-spoiler]

    1
    1 Votes
    1 Posts
    575 Views
    am1cableA
    here https://www.npmjs.com/package/nodebb-plugin-alignment and https://www.npmjs.com/package/nodebb-plugin-simple-spoiler Text and image alignment in the first one, a simple spoiler that allows you to name them and stack them inside each other in the second. Both built for default composer and super plain so you can style them as you like. same as other plugins - they're for my personal site so no guaranteed support.
  • [nodebb-widget-game-server-query]

    3
    5 Votes
    3 Posts
    1k Views
    yariplusY
    Updated to 1.1.0 Fixes a crash with newer node versions. Added the query protocol to the game dropdown.
  • How to properly change username ?

    4
    0 Votes
    4 Posts
    1k Views
    barisB
    calling ajaxify.refresh() should refresh the page.
  • NodeBB Android App

    79
    11 Votes
    79 Posts
    59k Views
    A
    @Rootzilla be more precise.
  • solr search not working

    1
    0 Votes
    1 Posts
    447 Views
    instkffffI
    Search Plugin installed Solr connection OK Solr Indexing Enabled all checked but when i search error: /api/search SolrError at IncomingMessage.<anonymous> (/home/NodeBB-1.10.1/node_modules/solr-client/lib/solr.js:991:19) at emitNone (events.js:111:20) at IncomingMessage.emit (events.js:208:7) at endReadableNT (_stream_readable.js:1064:12) at _combinedTickCallback (internal/process/next_tick.js:139:11) at process._tickCallback (internal/process/next_tick.js:181:9) Who can help with it, Thanks.
  • How to extend markdown / editor

    9
    0 Votes
    9 Posts
    2k Views
    J
    Hi @John-Cole and @Atayz Take a look here: https://community.nodebb.org/topic/12856/nodebb-plugin-composer-quill-wysiwyg-alternative-to-redactor All the best, JJ.
  • Slack integration

    14
    0 Votes
    14 Posts
    5k Views
    theportablegeekT
    Is the Slack Extended Plugin only one-way (i.e. sends from Nodebb to Slack but not the other way)?
  • nodebb-plugin-slack-extended updated for NodeBB v1.x.x

    2
    2 Votes
    2 Posts
    2k Views
    theportablegeekT
    @pichalite From my limited experience with your plugin the communication with slack is only one way (I.e. Nodebb to Slack.) Is it possible to recieve as well?
  • nodebb-plugin-sso-saml do not working

    1
    0 Votes
    1 Posts
    549 Views
    torresfengT
    nodebb v1.10.1 code: (function(module) { "use strict"; var user = module.parent.require('./user'), meta = module.parent.require('./meta'), db = module.parent.require('../src/database'), passport = module.parent.require('passport'), passportSAML = require('passport-saml').Strategy, fs = module.parent.require('fs'), path = module.parent.require('path'), nconf = module.parent.require('nconf'), async = module.parent.require('async'), winston = require('winston'); var constants = Object.freeze({ 'name': "SAML", 'admin': { 'route': '/plugins/sso-saml', 'icon': 'fa-university' } }); var SAML = {}; var samlObj; if (meta.config['sso:saml:idpentrypoint'] && meta.config['sso:saml:callbackpath']&& meta.config["sso:saml:metadata"] && meta.config["sso:saml:issuer"]) { console.log(nconf.get('url')); samlObj = new passportSAML({ path: meta.config['sso:saml:callbackpath'], entryPoint: meta.config['sso:saml:idpentrypoint'], issuer: meta.config['sso:saml:issuer'], callbackUrl: nconf.get('url') + meta.config['sso:saml:callbackpath'], disableRequestedAuthnContext: true, identifierFormat: null }, function(profile, done) { console.log(profile,'zheli'); var user = { nameID: profile.nameID, nameIDFormat: profile.nameIDFormat, sn: profile['urn:oid:2.5.4.4'], // sn //sn: profile.sn, cn: profile['urn:oid:2.5.4.42'], // givenname //cn: profile.cn, //mail: profile.mail, //eduPersonAffiliation: profile.eduPersonAffiliation, email: profile.mail, //email: profile.email, username: profile['urn:oid:1.3.6.1.4.1.5923.1.1.1.2'], // eduPersonNickname //username: profile.eduPersonNickname }; SAML.login(user,function(err, user) { if (err) { return done(err); } done(null, user); }); } ); } else{ console.log("No config info") console.log(meta.config); } SAML.init = function(params,callback) { // app, middleware, controllers, callback var app = params.router; var middleware = params.middleware; var controllers = params.controllers; function render(req, res, next) { res.render('admin/plugins/sso-saml', {}); } app.get('/admin/plugins/sso-saml', middleware.admin.buildHeader, render); app.get('/api/admin/plugins/sso-saml', render); console.log(456); console.log(samlObj); if (samlObj){ if (meta.config["sso:saml:metadata"]) { app.get(meta.config["sso:saml:metadata"], function(req, res) { console.log(123); if (meta.config["sso:saml:servercrt"]){ var cert = fs.readFileSync(meta.config["sso:saml:servercrt"], 'utf-8'); res.header("Content-Type", "application/xml"); res.send(samlObj.generateServiceProviderMetadata(cert)) } else{ res.send("No servercrt specified. Please enter it at nodebb admin panel."); } }); } app.post(meta.config['sso:saml:callbackpath'], passport.authenticate('saml'), function(req, res, next){ if (meta.config['sso:saml:loginsuccessredirecturl']){ res.redirect(meta.config['sso:saml:loginsuccessredirecturl']); } else{ res.redirect("/"); } } ); if (meta.config['sso:saml:logouturl']) { app.get(meta.config['sso:saml:logouturl'],function(req,res){ if (req.user && parseInt(req.user.uid, 10) > 0) { winston.info('[Auth] Session ' + req.sessionID + ' logout (uid: ' + req.user.uid + ')'); var ws = module.parent.require('./socket.io'); ws.logoutUser(req.user.uid); req.logout(); if (meta.config['sso:saml:logoutredirecturl']){ res.redirect(meta.config['sso:saml:logoutredirecturl']); } else{ res.redirect("/"); } } }); } } callback(); }; SAML.getStrategy = function(strategies, callback) { console.log("filter:auth.init..."); console.log(strategies); if (samlObj){ passport.use(samlObj); strategies.push({ name: 'saml', url: '/auth/saml', callbackURL: meta.config['sso:saml:callbackpath'], icon: constants.admin.icon, scope: '' }); } callback(null, strategies); }; SAML.login = function(userdata, callback) { SAML.getUidBySAMLId(userdata.username, function(err, uid) { if(err) { return callback(err); } if (uid !== null) { // Existing User callback(null, { uid: uid }); } else { console.log(userdata); // New User user.create({ username: userdata.username, email: userdata.email, fullname : userdata.first_name + " " + userdata.last_name }, function(err, uid) { if(err) { return callback(err); } user.setUserField(uid, 'samlid', userdata.username); db.setObjectField('samlid:uid', userdata.username, uid); callback(null, { uid: uid }); }); } }); }; SAML.getUidBySAMLId = function(samlid, callback) { db.getObjectField('samlid:uid', samlid, function(err, uid) { if (err) { return callback(err); } callback(null, uid); }); }; SAML.addMenuItem = function(custom_header, callback) { custom_header.authentication.push({ "route": constants.admin.route, "icon": constants.admin.icon, "name": constants.name }); callback(null, custom_header); }; SAML.deleteUserData = function(uid, callback) { async.waterfall([ async.apply(user.getUserField, uid, 'samlid'), function(idToDelete, next) { db.deleteObjectField('samlid:uid', idToDelete, next); } ], function(err) { if (err) { winston.error('[sso-saml] Could not remove user data for uid ' + uid + '. Error: ' + err); return callback(err); } callback(null, uid); }); }; module.exports = SAML; }(module));
  • Plugin for authenticate users using SAML

    3
    1 Votes
    3 Posts
    2k Views
    torresfengT
    Error 'no configuration information' NodeBB V.1.10.1 I see it has no recent commit. Can it still be used?
  • Integration with Wiki.js?

    3
    0 Votes
    3 Posts
    782 Views
    Giorgio TaveG
  • Charts/training diary

    2
    0 Votes
    2 Posts
    544 Views
    PitaJP
    You can do pretty much anything you want if you're willing to put in the work to make a plugin. Without that, though, no there's no way to configure NodeBB core to do that.
  • my plugins do not update !?!

    Solved
    3
    0 Votes
    3 Posts
    671 Views
    The WormsT
    ok, tks