Skip to content
  • 5 Votes
    1 Posts
    242 Views
    B

    Hi everybody 🌴

    Today I show you how to make a sticky brand header and avatars in Harmony.

    preview

    Step-by-step

    We need modify 6 files: library.js, harmony.json, theme.tpl, harmony.tpl, brand.tpl, post.tpl to add 3 new settings:

    Sticky avatars (user avatars in the posts) Sticky header (brand header) Setting to show sticky header on mobile devices

    First we add a new settings in library.js

    Paste this code after this line stickyAvatars: 'on', stickyHeader: 'off', stickyHeaderMobile: 'off', Paste this code after this line config.stickyAvatars = config.stickyAvatars === 'on'; config.stickyHeader = config.stickyHeader === 'on'; config.stickyHeaderMobile = config.stickyHeaderMobile === 'on';

    Now we need add translation for the new settings in harmony.json

    Paste this code after this line "settings.stickyAvatars": "Sticky user avatars in posts", "settings.stickyHeader": "Sticky header on desktop", "settings.stickyHeaderMobile": "Show sticky header on mobile",

    Next step, create controls of new settings in ACP and user profile in harmony.tpl and theme.tpl

    Paste this code after this line in harmony.tpl <div class="form-check form-switch"> <input type="checkbox" class="form-check-input" id="stickyAvatars" name="stickyAvatars" /> <label for="stickyAvatars" class="form-check-label">settings.stickyAvatars</label> </div> <div class="form-check form-switch"> <input type="checkbox" class="form-check-input" id="stickyHeader" name="stickyHeader" /> <label for="stickyHeader" class="form-check-label">settings.stickyHeader</label> </div> <div class="form-check form-switch"> <input type="checkbox" class="form-check-input" id="stickyHeaderMobile" name="stickyHeaderMobile" /> <label for="stickyHeaderMobile" class="form-check-label">settings.stickyHeaderMobile</label> </div> Paste this code after this line in theme.tpl <div class="form-check mb-3"> <input class="form-check-input" type="checkbox" id="stickyAvatars" name="stickyAvatars" {{{ if config.theme.stickyAvatars }}}checked{{{ end }}}> <label class="form-check-label" for="stickyAvatars">settings.stickyAvatars</label> </div> <div class="form-check mb-3"> <input class="form-check-input" type="checkbox" id="stickyHeader" name="stickyHeader" {{{ if config.theme.stickyHeader }}}checked{{{ end }}}> <label class="form-check-label" for="stickyHeader">settings.stickyHeader</label> </div> <div class="form-check mb-3"> <input class="form-check-input" type="checkbox" id="stickyHeaderMobile" name="stickyHeaderMobile" {{{ if config.theme.stickyHeaderMobile }}}checked{{{ end }}}> <label class="form-check-label" for="stickyHeaderMobile">settings.stickyHeaderMobile</label> </div>

    The finally we modify a theme files post.tpl and brand.tpl

    Replace the code in this line with a new code in post.tpl <div class="icon py-1 bg-body d-none d-sm-block {{{ if config.theme.stickyAvatars }}}position-sticky{{{end}}}" {{{ if config.theme.stickyAvatars }}}style="top:7.5rem;"{{{end}}}> Replace the code in this line with a new code in brand.tpl <div class="container px-md-4 brand-container {{{ if config.theme.stickyHeaderMobile }}}sticky-top{{{end}}} {{{ if config.theme.stickyHeader }}}sticky-lg-top bg-body pt-3{{{end}}}" {{{ if config.theme.stickyHeader }}}style="margin-top:-1rem;"{{{end}}}>

    /.nodebb build

    🖖 Happy Dev

  • 8 Votes
    1 Posts
    294 Views
    barisB

    Since NodeBB 1.18.6 it is possible to create dropdowns in the navigation (https://github.com/NodeBB/NodeBB/issues/9967). Before 1.18.6 to accomplish this you would have to use nodebb-plugin-customize to modify the menu template or use javascript to inject the markup after page load.

    In this tutorial I will show you how to create a dropdown navigation item that replaces the default categories link with a dropdown. The final result will look like this:

    category-dropdown.gif

    First thing to do is to turn the navigation item into a dropdown, to do this head over to yourforum.com/admin/settings/navigation, select the categories navigation item and toggle the dropdown option.

    category-dropdown-1.gif

    Once this is done you can use the text area below the toggle to add your markup. To create a simple dropdown you would just add a list of dropdown items like so:

    <li><a class="dropdown-item" href="/categories">All</a></li> <li><a class="dropdown-item" href="/category/2/general-discussion">General Discussion</a></li>

    Since you can input html here you can create custom dropdowns. To achieve the same dropdown as the first gif use the below html code, no css is necessary.

    <li><a class="dropdown-item" href="/categories">All</a></li> <li class="dropdown-divider"> <li><a class="dropdown-item" href="/category/2/general-discussion">General Discussion</a></li> <li class="d-flex flex-column"> <a class="dropdown-item" href="/category/3/nodebb-development">NodeBB Development</a> <div class="d-flex flex-column px-4"> <div class="d-flex align-items-center gap-1"> <i class="fa fa-fw fa-caret-right text-primary"></i> <a class="btn-ghost-sm text-sm text-nowrap" href="/category/13/nodebb-blog">NodeBB Blog</a> </div> <div class="d-flex align-items-center gap-1"> <i class="fa fa-fw fa-caret-right text-primary"></i> <a class="btn-ghost-sm text-sm text-nowrap" href="/category/5/feature-requests">Feature Requests</a> </div> <div class="d-flex align-items-center gap-1"> <i class="fa fa-fw fa-caret-right text-primary"></i> <a class="btn-ghost-sm text-sm text-nowrap" href="/category/6/bug-reports">Bug Reports</a> </div> <div class="d-flex align-items-center gap-1"> <i class="fa fa-fw fa-caret-right text-primary"></i> <a class="btn-ghost-sm text-sm text-nowrap" href="https://explore.transifex.com/nodebb/nodebb/">NodeBB Localization</a> </div> </div> </li> <li><a class="dropdown-item" href="/category/7/nodebb-plugins">NodeBB Plugins</a></li> <li><a class="dropdown-item" href="#">...add more as needed...</a></li>

    Modify the links to match your forum categories. To create dividers between sections you can use <li class="dropdown-divider">

    Now you can navigate your categories without going to the home/categories page. 🎊

  • 0 Votes
    1 Posts
    959 Views
    gotwfG
    Who Is This Document For?

    Well... like most things.... it depends....

    If one or more of following shoes fits: Just want to get NodeBB up and running with minimum of hassle please I refer you to the tl;dr commentary from my NodeBB Email Options article. Intermediate to advanced Linux user. You can likely get this on your own. May be of some value to those unfamiliar with network and server side aspects of SMTP? Seasoned email administrator? Right. Please do not be too harsh as I'm endeavoring to bridge a gap here... SME commentary welcome. 😉 If, on the other hand: You're attracted to the "Ops" side of DevOps. Like to know how things work. Medium/advanced "beginner" to the Unix/Linux command line and eager to learn. Have the time to invest in that learning (i.e. big boss man or some other urgency not twisting your arm to get this done yesterday) and not afraid to RTFM.

    Then.......

    For Those About to Rock...

    I confess to deploying a Null Client set up for my forums. I thought I'd expand upon this a bit for interested parties not already possessing subject matter expertise but comfortable with the command line and willing to roll up their sleeves. Follows is meant to be a thumbnail sketch to get the DIY inclined pointed in the proper directions rather than exhaustive step by step copy pasta.

    Firstly, let's take a look at some reasons why/when this use case may be a fit:

    Isolation and separation of duties. Some favor an all on one approach. I favor dedicated vm's for dedicated tasks. I'd rather not have my app servers initiating connections with the Big Bad Internet. Incoming http(s), smtp, etc. requests from non local VM's is proxied. Access to prexisting email infrastructure. Security and stability concerns. All software has bugs. Postfix has weathered extensive scrutiny and audit. As such, I expect it is less vulnerable to things like malformed responses. Flexibility moving forward. For e.g. you want a daemon to manage NodeBB's outgoing mail queue - and perhaps that daemon also comes in handy for other duties like emailing various reports or alerts to administrators.

    Presumptions:

    You have a Postfix Null Client configured as outlined in the Postfix Standard Configuration Readme. You have NodeBB configured to utilize such as depicted in my screenshot in my prior article linked above.

    I've mentioned this can get complex in a hurry. Let's see if we give it a little K.I.S.S.

    Incoming!! 💣 📬

    Let's get our biggest hurdle out of the way.

    Null clients do not receive incoming mail. Setting up SMTP relays, IMAP server, virus/malware scanner, etc. ups the ante considerably. We've already got enough on our plates, at least for now, embarking upon this Null Client journey so lets save ourselves some grief and off load those duties to a reputable third party service such as Proton Mail.

    Outgoing

    As always, there's more than one way to do it:

    Null client delivers email directly to one of the servers listed in recipient domains MX records.

    Null client forwards email to a dedicated SMTP relay host, e.g. the folks handling your incoming mail (you may need to coordinate with them to configure some knobs, e.g. which hosts they will relay email from). Advantages to using a relay host include: 1) Undeliverable mail does not get stuck on your NodeBB server, and 2) Our null client is now initiating outgong SMTP connections with only the relayhost(s) rather than the big bad Internet at large.

    Postfix needs to know about your relay host to get this working. Add the following line to your null client's main.cf

    relayhost = your-relay-host.domain.tld

    You may also choose to specify relayhost via alternate parameters, such as IP address. I recommend sticking with hostnames as IP addresses may change from time to time.

    DNS Record Cogs & Widgets âš™

    DNS presents yet another challenge and can have a high price for mistakes. So you're best off offloading this to a third party. Good news is your email provider likely bundles this with their service. Your domain registrar surely does. Consider leveraging that. Submit a request to have forward and SPF records added for your NodeBB instance's hostname.

    Note: I've used traditional Bind zone file syntax in the examples below. Using this syntax in help desk requests helps avoid confusion. Your provider may well offer a web based UI.

    You want records that look similar to the following (mind the trailing periods on fully qualified host names):

    Forward Record

    null-host-name.your-domain.tld. IN A XXX.YYY.WWW.ZZZ

    SPF Record

    The purpose of an SPF record is to provide a list of servers authorized to send email from your domain and must therefore necessarily include your third party provder's servers as well as your null client(s).

    your-domain.tld. IN TXT "v=spf1 ip4:primary-ip, ip4:secondary-ip, ip4:null-host-ip -all"

    MX Records

    Your mailbox provider likely handles configuration of MX records seamlessly but for the sake of completeness....

    RFC's dictate primary and secondary mail exchangers. Get these from your mailbox host.

    @ IN MX 50 primary-mx.domain.tld. @ IN MX 80 secondary-mx.domain.tld.

    Reverse Record

    Your cloud provider is authoritative for reverse records for IP space assigned to them. Set up a PTR record for your NodeBB host using your providers management ui or submit a request ticket for them to create such for you.

    XXX.YYY.WWW.ZZZ.in-addr.arpa. IN PTR null-host-name.your-domain.tld.

    I manage my own DNS servers. DKIM is a royal pita for even seasoned adminstrators and imho an accident waiting to happen. Hence, unless you have a passion for learning about this stuff, I recommend letting your email/IMAP provider handle DNS for you, as it is lots easier to have them add an A or CNAME record as necessary for web servers and such than for you to configure and maintain DKIM. Else avoid DKIM entirely.

    Postmaster

    Other systems expect the existence of a valid postmaster address for communication of issues such as bounced mail, etc. Create "[email protected]", either as a dedicated mailbox or a forward to an existing mailbox, e.g. [email protected] if you prefer not having to check multiple mailboxes. Test this. Don't sweep postmaster mail under the rug lest it come back to haunt you at the most inopportune of times.

    Blacklists

    We need to ensure our newly minted Null Client is not blacklisted. MX Toolbox offers a meta blacklist check. Barracuda Networks will most likely do so before you've sent even a single email and requires jumping thru their hoops to become delisted. And jump ye' shall because their stuff is in wide spread use, particularly corporate side. It behooves you to check these blacklists from time to time, particularly with a newly minted server.

    Bippity Boppity Boo! 🎉

    Put it together and what have we got?

    Robust SMTP daemon relaying outgoing NodeBB email. Robust and reasonably secure IMAP mailboxes sans administration headaches. No worries about third party email plugin breakage between version upgrades.

    While this method adds complexity it's not too difficult to get set up once you understand some underlying concepts, moving pieces involved and what you're targeting. It also serves as a stepping stone to building out your own email infrastructure should you decide this stuff is all just too much fun.

    Enjoy! o/

  • 2 Votes
    1 Posts
    966 Views
    mooredsM

    Hiya,

    I wrote a tutorial about setting up single sign-on for NodeBB.

    Full disclosure, I wrote it using my employers OAuth server (FusionAuth) as the user identity provider.

    But the plugin and steps should work with any OAuth server. The plugin is here: https://github.com/FusionAuth/nodebb-plugin-fusionauth-oidc

  • 8 Votes
    1 Posts
    6k Views
    PitaJP

    This FAQ is applicable for the following situations:

    You're receiving the following error in the Javascript console: WebSocket connection to 'wss://<site>/socket.io/?EIO=3&transport=websocket' failed: Error during WebSocket handshake: Unexpected response code: 400 The "Looks like your connection to NodeBB was lost, please wait while we try to reconnect." alert box and the spinner in the navbar consistently appear You want your users to be able to access NodeBB from multiple subdomains on your site Background

    By default, NodeBB only allows websocket connections from the "url" value in config.json. This is because of what is called Cross-Site Websocket Hijacking. By restricting the origin at which sockets can connect, we prevent this attack from taking place.

    Diagnosis

    To make sure that your issue is in fact caused by an origin mismatch, try this:

    Stop the NodeBB server: ./nodebb stop Start NodeBB in dev mode: ./nodebb dev Visit your site, and see if the issue is resolved. Ctrl+C to exit dev mode

    If the issue disappeared when visiting your site running in dev mode, then your problem is in fact an origin mismatch. If not, it is likely something else, so look around or ask a question here on the forum.

    Solutions

    The easiest solution is to set the "url" value in config.json to exactly the URL at which you access your NodeBB forum. For instance, the configuration for this site is

    { "url": "https://community.nodebb.org", ... }

    If you want your forum to work from multiple origins (like www.yoursite.com and yoursite.com) the preferred option is to just redirect one to the other. For instance, redirect www.yoursite.com to yoursite.com within your reverse proxy.

    If you absolutely must have full access from multiple origins, you can configure the accepted origins directly. As documented here, you can add a socket.io:origins property to config.json.

    For example, to allow accessing the forum sockets from the main NodeBB site, nodebb.org, the following would be added to our config:

    { ... "socket.io": { "origins": "https://community.nodebb.org:* https://nodebb.org:*" } }

    Make sure your original site is included in the new origins property, and that you add :*, otherwise it's invalid.

    Still having issues?

    It's likely a reverse proxy configuration issue. Take a look at the proxy documentation for examples. If you still have issues, ask a question here on the forum.

  • 0 Votes
    1 Posts
    823 Views
    Cyb3rC

    I'll make this as simple as it can be, after importing your forum it might come a problem when you see some of your users avatars broken, here's a simple method to set a placeholder image for missing images.

    First you have to upload your default image anywhere on the public directory, I would suggest in public/uploads/default.png, the full path should be /path/to/nodebb/public/uploads/default.png.

    Now you have to get the default avatar directory for your imported forum, to get this path right click on the avatar of your broken user and click copy image location, paste it in a text file, in my case it was example.com/assets/uploads/xenforo/data/avatars/m/0/84.jpg so the path should be the folder containing all avatars /uploads/xenforo/data/avatars you have to lose the assets folder from the path.

    In your nginx conf add this block under the main block /:

    location /uploads/xenforo/data/avatars { try_files $uri /uploads/xenforo/data/avatars/default.png; }

    Full nginx conf should look something like this:

    upstream nodebb { ip_hash; server 127.0.0.1:4567; } server { server_name example.com www.example.com; root /path/to/nodebb/public; location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; proxy_pass http://nodebb; proxy_redirect off; # Socket.IO Support proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; location /uploads/xenforo/data/avatars { try_files $uri /uploads/xenforo/data/avatars/default.png; } } }

    Hope this helps someone. 🙂

  • 0 Votes
    1 Posts
    672 Views
    J

    Hi All,

    The recommended setup for nvm/npm/nodejs is per user.

    Lets assume you created a user nodebb, installed nodejs under it, and revised .bashrc to set environment variables to point to the latest version (standard procedure):
    export NVM_DIR="$HOME/.nvm"
    [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
    [ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion" #

    Systemctl expects full path to executable. Unfortunately, that path may change when nodejs gets updated.

    So how do we hack systemctl to use a dynamic path?

    Generate the env variables and dump them into a file Load the file into systemctl environment

    See config below:

    [Unit]
    Description=NodeBB Service
    After=system.slice multi-user.target mongod.service syslog.target

    [Service]
    Type=idle
    User=nodebb

    StandardOutput=syslog
    StandardError=syslog
    SyslogIdentifier=nodebb

    ExecStartPre=/bin/bash -c -l '/usr/bin/env > /tmp/tmp_env ; /bin/echo NODE_ENV=production >> /tmp/tmp_env'

    EnvironmentFile=/tmp/tmp_env
    WorkingDirectory=/path_to_nodebb

    ExecStart=/usr/bin/env node loader.js --no-silent --no-daemon
    Restart=always

    [Install]
    WantedBy=multi-user.target

    Pay attention: Type=idle replaces Type=simple.

    Good luck!
    JJ.

  • 1 Votes
    1 Posts
    1k Views
    R

    I want to run 2 different websites in the same vps. 1st is wordpress and 2nd is nodebb. I am a newbie here. Can anyone please guide me with a detailed tutorial?

  • 4 Votes
    1 Posts
    1k Views
    julianJ

    As part of the creation of the Tenor GIF plugin, I needed to add a button to the composer toolbar:

    gif button in composer

    Normally, this is fairly straightforward. filter:composer.formatting is called, and caught with this listener:

    plugin.registerFormatting = function (payload, callback) { payload.options.push({ name: 'gif', className: 'fa fa-tenor-gif', title: 'Insert GIF' }); callback(null, payload); };

    The className denotes a class name (of course), and if you use fa and and corresponding fa-* class, you can select from hundreds of possible icons. Unfortunately for me, there was no "gif" icon, nor one for Tenor GIF.

    So I had to set out to make my own. To do this, you'll see that above, I set the class fa-tenor-gif. This maps to nothing, since the icon doesn't exist. However, it does provide a nice easy way to find and style the button itself.

    Then in my stylesheet, I simply added this styling to create my button via CSS pseudo-elements:

    .fa-tenor-gif::before { content: 'GIF'; font-size: 1rem; font-family: sans; background: #333; color: #fff; padding: 0.25rem 0.5rem; border-radius: 0.5em; position: relative; top: -0.2rem; }

    I wanted to go for a "badge-like" icon, since the text "GIF" fairly easily indicates what its purpose is for, hence the dark background, light text, and slight border radius.

    If you wanted to do something else, like replace the icon with a picture of your own, then you might want to look into using background-image, but that is outside of the scope of this tutorial 😄

  • 1 Votes
    1 Posts
    1k Views
    barisB

    This is a simple widget tutorial to turn a topic into a twitter timeline. The end result will look like this.

    0_1510068225857_81b76a4a-720a-47d4-b7b0-b9e671e52dd8-image.png

    First create a topic that will be the home of the twitter widget and record its topic id.

    Now go to /admin/extend/widgets and place a html widget on topic.tpl/header. The standard twitter timeline widget code only works on cold loads so we have to modify it for NodeBB. You can generate the twitter widget at https://twitter.com/settings/widgets, after you copy that code you have to replace the <script> block with the one provided below.

    <script> !function(d,s,id){ var js,p=/^http:/.test(d.location)?'http':'https'; var el = d.getElementById(id); if (el) { el.parentNode.removeChild(el); } if (!d.getElementById(id)) { js = d.createElement(s); js.id = id; js.src = p + "://platform.twitter.com/widgets.js"; var fjs = d.getElementsByTagName(s)[0]; fjs.parentNode.insertBefore(js,fjs); } }(document,"script","twitter-wjs"); </script>

    Here is the full widget code for NodeBB's twitter timeline. You can copy paste it into your HTML widget and replace every <topic_id> with your own topic id.

    <style> .page-topic-<topic_id> .topic { display: none; } .page-topic .twitter-timeline { display: none !important; width: 100% !important; height: 800px !important; } .page-topic-<topic_id> .twitter-timeline { display: block !important; } </style> <a class="twitter-timeline" href="https://twitter.com/NodeBB" data-widget-id="433016924318883841">Tweets by @NodeBB</a> <script> !function(d,s,id){ var js,p=/^http:/.test(d.location)?'http':'https'; var el = d.getElementById(id); if (el) { el.parentNode.removeChild(el); } if (!d.getElementById(id)) { js = d.createElement(s); js.id = id; js.src = p + "://platform.twitter.com/widgets.js"; var fjs = d.getElementsByTagName(s)[0]; fjs.parentNode.insertBefore(js,fjs); } }(document,"script","twitter-wjs"); </script>

    Once you have the widget, you can customize it with data attributes, for more info you can read https://dev.twitter.com/web/embedded-timelines

  • 0 Votes
    1 Posts
    2k Views
    B

    I have nginx proxying to nodebb, from a /forum/ location.

    I wanted to serve up static contents with nginx - the example here - https://docs.nodebb.org/en/latest/scaling/#use-a-proxy-server-to-serve-static-assets assumes you have the forum running off the root. If running from a subfolder, it can be simplified to this (the public folder is tried first, followed by the proxy if no file exists).

    Here's my config using nginx to serve up the static content (just the locations/configs for nodebb included, I have a wordpress site running of the htdocs root)

    upstream io_nodes { ip_hash; server 127.0.0.1:4567; # upstream nodebb servers here } server { listen 443 default_server ssl; listen [::]:443 default_server ssl; server_name your.site; root /webroot/of/site; index index.html index.php; location /forum { alias /path/to/nodebb/public; try_files $uri @nodebb; } location @nodebb { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $http_host; proxy_set_header X-NginX-Proxy true; proxy_redirect off; # Socket.IO Support proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_pass http://io_nodes; } }
  • Extend invite token validity

    Tutorials
    1
    0 Votes
    1 Posts
    1k Views
    C

    Hi,

    How extend this 24H invite token validity ?

    Thank you 🙂

  • Running nodebb with plesk [tips]

    Tutorials
    1
    3 Votes
    1 Posts
    2k Views
    kenthuiK

    Hi everybody,

    My server have install Plesk, because I want run somethings on my server.

    I install nodebb by command line, and ready to run at localhost:4567

    Pls follow with image to config nodebb on plesk.

    Install htaccess to nginx

    0_1468850536240_1.jpg

    Add package

    0_1468850572040_2.jpg

    Select Apache & nginx Settings

    0_1468850619741_3.jpg

    Copy, paste and enjoy

    0_1468850668048_4.jpg

    Done

  • 2 Votes
    1 Posts
    2k Views
    julianJ
    What is a registration interstitial?

    When a user registers for a new account, they may be presented with an intermediate step (or "intersitial") before the registration is completed. Alternatively, the interstitial can be invoked after registration.

    You may use this opportunity to obtain additional information about the user for your plugin.

    In this tutorial, we'll be updating the Facebook SSO plugin to capture user emails upon registration.

    The filter:register.interstitial hook

    The hook filter:register.interstitial is fired whenever a user registers for a new account. It is also fired if the user session contains a registration object, and in processing the interstitial page itself.

    The hook signature is {data, callback}, and data contains the following:

    userData (Object) The registration data collected so far interstitials (Array) A collection of interstitial objects, which you can append to if necessary. An interstitial object is: template (String) A template served by your plugin that will be included into the interstitial page data (Object) When rendering the above template, any data needed can go here callback (Function [userData, formData, callback]) When the interstitial page is completed, this callback method will be executed, with the form data included in the second parameter

    In the case of Facebook SSO, we want to capture user email addresses because Facebook may not provide the correct email to us (or at all). By looking at the code, we can see that if the email is not present, we create a fake email ending with @facebook.com.

    Step 1: Invoking the interstitial

    Upon completion of SSO registration, we save uid and fbid into req.session.registration. Once this object is set in the user session, NodeBB will automatically forward the user to the registration interstitial:

    // Require collection of email req.session.registration = req.session.registration || {}; req.session.registration.uid = user.uid; req.session.registration.fbid = profile.id; Step 2: filter:register.interstitial listener

    Now, we will create a new listener to the filter:register.interstitial hook, and have it add an interstitial if the email ends with @facebook.com:

    Facebook.prepareInterstitial = function(data, callback) { // Only execute if: // - uid and fbid are set in session // - email ends with "@facebook.com" if (data.userData.hasOwnProperty('uid') && data.userData.hasOwnProperty('fbid')) { user.getUserField(data.userData.uid, 'email', function(err, email) { if (email.endsWith('@facebook.com')) { data.interstitials.push({ template: 'partials/sso-facebook/email.tpl', data: {}, callback: Facebook.storeAdditionalData }); } callback(null, data); }); } else { callback(null, data); } };

    To note, when registering the interstitial (data.interstitials.push...), we define the template as partials/sso-facebook/email.tpl. This tempate is defined in the plugin itself.

    Secondly, the callback calls Facebook.storeAdditionalData. That method is also defined by the Facebook SSO plugin, and handles updating the user email as passed in via the interstitial page.

  • 7 Votes
    1 Posts
    4k Views
    R
    Create & Manage a NodeBB Test/Dev Environment Table of Contents Summary Caveats Webserver Nginx NodeBB PRD -> DEV Adjustments to DEV Upgrading DEV NodeBB Delete DEV Fresh NodeBB with PRD database Summary

    The old saying goes

    Laws are like sausages, it is better not to see them being made.

    Managing NodeBB isn't as bad as that but there could be a bit of a challenge the first few times that you attempt to upgrade your software or install a new feature. Especially on your production system! So what can you do?

    Make a sausage factory of course! In our case the factory is a test/development environment to practice your upgrades or test a new plugin or CSS change. You do not necessarily need to spend additional money on a test/dev server, although you could. You can spin up a copy of your production system right on your production system. This is not very difficult due in part to how well NodeBB, and Node.js, were created.

    Caveats

    For disclosure I am not a developer of NodeBB or any of the supporting applications. These notes are just that, a collection of my notes as I was experimenting and learning. I do have twenty-four years of IT experience, mostly Unix (SunOS, Solaris, AIX, BSD, Linux) which includes twenty-four years of bad habits and ugly kludges. I do hope that in those years I have picked up a few gems and learned a few good traits. I will try to pass along only the best but please do accept the ugly as they come.

    My NodeBB forum runs on a Linux (CentOS) server. I utilize Redis as my NodeBB database and use Nginx as my web server. This document, unless noted otherwise, will reference that environment.

    I am making the assumption that you have a production NodeBB server that is fully operational and you wish to create a dev/test copy of it on the same server.

    And finally, The risk is yours. I do not take responsibility for harm to your system. Please evaluate all of my suggestions as you deem necessary.

    Webserver Nginx

    This addition should only need to be made once. After it is in place you should be able to create and delete dev NodeBB environments from your production without needing to adjust your Nginx configuration.

    You will need to make a new server block in your Nginx domain configuration file. Most likely located in /etc/nginx/sites-available/yourforumdomain.com.conf. This new server block will have the specifics for your dev NodeBB. For example you may create an entry like:

    server { listen 443 ssl; server_name dev.yourforumdomain.com; [...]

    In your location / { location block you will need a proxy_pass entry that directs to the port that your dev NodeBB will listen on:

    location / { [...] proxy_pass http://127.0.0.1:4568; [...]

    Once you have your Nginx configuration adjusted appropriately do not forget to restart it. sudo systemctl restart nginx.

    NodeBB PRD -> DEV

    For my examples the production NodeBB is running under the /opt/nodebb/ directory path and we will be creating a copy into /opt/devNodebb/

    Let's make a copy of production into dev. This can be done "live" without needing to shutdown your production forum.

    mkdir /opt/devNodebb (cd /opt/nodebb; tar cf - .) | (cd /opt/devNodebb; tar xvf -)

    If NodeBB was running when you made the copy you'll need to remove the pidfile. A pidfile typically contains the process id information of the running program. This is useful so that commands such as ./nodebb stop know which program to kill. The pidfile you copied over relates to the process id of your production NodeBB. You don't want to be killing that process when you try to startup your dev NodeBB.

    rm /opt/devNodebb/pidfile

    Since you made a copy of production you have all production information. If you attempted to start your dev NodeBB now you would have problems. You must edit your config.json file and tell it that you want a new instance of NodeBB.

    vi /opt/devNodebb/config.json

    Change your url, port and database entries. For the URL make it the dev domain that you configured your Nginx to listen for. For the port and database numbers I just incremented by one from production.

    "url": "https://dev.yourforumdomain.com", "port": "4568", [...] "database": "1"

    No you aren't ready to start up your dev NodeBB just yet. There isn't a database behind it.

    Let's make a copy of the production Redis database for dev to use. I use redis-copy which is not part of the redis database distribution. I downloaded and built my copy from this Github repository redis-copy.

    The following command makes a copy of the Redis database number 0 (production) to database number 1 (your dev/test). Database number 1 is the database we told the devNodebb config.json file above to use.

    redis-copy localhost/0 localhost/1

    Now we may startup the dev NodeBB instance.

    cd /opt/devNodebb ./nodebb start Adjustments to DEV

    Once your dev forum is running you should make a few administrative adjustments to it. These are not necessarily critical but they will help you to keep track of which system you are working on and may reduce notifications to your users, etc. Keep in mind that you cloned your production system which includes the users. If you do not want them logging into your dev system you should limit their exposure to it.

    You may want to adjust the site and browser title's to reflect a dev forum

    ACP > Settings > General > Site Title > DEV YourForumName ACP > Settings > General > Browser Title > DEV YourForumName

    Disable email subscriptions

    ACP > Settings > Email > Email Subscriptions > Disable subscriber notification emails

    Disable plugins that may cause confusion, such as Google Analytics

    ACP > Extend > Plugins > nodebb-plugin-google-analytics > Deactivate

    There may be other plugins that you wish to disable. Experimenting will lead you to adjust this list appropriately.

    There you have it. You now have a test/dev environment based off of your production system. Changes you make now will only be done in test/dev and your users will happily continue to use the production system until the time comes that you shutdown production to re-play changes or enhancements that you tested in dev.

    Upgrading DEV NodeBB

    So you went through all of the above steps and now you have, well, just a copy of production. Not really useful as it stands but now you have a platform to test upgrading without fear of damaging production.

    Let's upgrade! If you'd like to bring your dev NodeBB up to the current general release of NodeBB the following steps should be adequate.

    Stop your dev NodeBB

    cd /opt/devNodebb ./nodebb stop

    Tell Git to get the newest release information. This sets up NodeBB such that when you issue the upgrade command it will pull down all of the new or changed files as necessary.

    cd /opt/devNodebb git fetch git checkout v1.x.x git merge origin/v1.x.x

    Issue the NodeBB upgrade command

    cd /opt/devNodebb ./nodebb upgrade

    Watch for upgrade errors. Note that any customizations or changes you have made to your theme's CSS may have been undone by a new feature or bug fix. That is why we have this test/dev environment, so you can test and look for problems.

    If the upgrade appears to have worked without errors start up dev NodeBB and then switch into the logging mode so that you may watch the behavior of the system. Pressing ctrl-c will exit the logging mode.

    cd /opt/devNodebb ./nodebb start ./nodebb log Delete DEV

    What if there were problems with your upgrade or you'd like to start this process over with a fresh copy of production? That is not a big problem. A few commands will delete your test/dev environment and then you can start the copy process over again.

    Stop your dev NodeBB

    cd /opt/devNodebb ./nodebb stop

    Let's remove the test/dev software directory tree

    rm -rf /opt/devNodebb

    Delete the test/dev Redis database. This is probably the most dangerous command in this document. Please double check that the database number provided is the one for your test/dev environment and NOT the one for your production environment.

    redis-cli -n 1 flushdb

    And there you have it, test/dev is gone. You may now redo the PRD -> DEV or Fresh NodeBB with PRD database steps if you so desire.

    Fresh NodeBB with PRD database

    There may be times that you want to have a factory fresh NodeBB installation with your database content. You would end up with users, setttings, content, etc., but not files that you may have edited over time or plugins that you installed.

    Run the Delete DEV section to be sure you have no remnants of a previous test/dev environment. Then proceed.

    Tell Git to get the software and where to put it.

    git clone -b v1.x.x https://github.com/NodeBB/NodeBB /opt/devNodebb

    Copy your production config.json file and then edit it as you would have if you were doing the PRD -> DEV section

    cp /opt/nodebb/config.json /opt/devNodebb/config.json vi /opt/devNodebb/config.json

    Change your url, port and database entries.

    "url": "https://dev.yourforumdomain.com", "port": "4568", [...] "database": "1"

    Copy over your Redis database

    redis-copy localhost/0 localhost/1

    Since the config.json has been created and contains the information that the NodeBB setup process would have asked for we can just run the NodeBB upgrade command (as opposed to the setup command). Bypassing the questions about which database to use, etc. Before you run the NodeBB upgrade you have to actually install the NodeBB software. This process was not necessary when we copied PRD to DEV earlier as it was done when you did your initial production NodeBB installation and was brought over in the tar copy process.

    cd /opt/devNodebb npm install ./nodebb upgrade

    Now start it up!

    cd /opt/devNodebb ./nodebb start

    And there you have it. You now have a clean installation of NodeBB with your database content. As noted in the PRD -> DEV section you may wish to make adjustments to your dev forum so that you can easily identify which one you are working in. Ie., change the site and browser title names, etc.

    Contact me https://community.nodebb.org/user/rod Revision 1.2, 2016-APR-08 @645.beats
  • [script] Noembed Embed

    Tutorials
    1
    1 Votes
    1 Posts
    1k Views
    P

    Hello, I see that you guys use magickblock plugin, maybe i'll test it later but I am sharing a script I wrote to automarically embedding noembed supported sites.

    As I don't have patience to maintain a plugin, I just put this in ACP / Appearance / Custom HTML & CSS / Custom Headers.

    <script> $(document).ready(function(){ $('head').append('<link rel="stylesheet" type="text/css" href="https://noembed.com/noembed.css">'); setProviders(); $(window).ajaxComplete(function(){ $("div.post-content > p > a:not(.embedded)").addClass("embedded").each(function(){ noembed(this.href, this.closest("div.post-content")); }); }); }); function setProviders() { //window.embedProviders = new RegExp(); providersArray = []; patternsArray = []; $.ajax({ url: "https://noembed.com/providers", type: "get", success: function(data){ providersArray = JSON.parse(data); while(providersArray.length) { patternsArray.push( providersArray.pop()['patterns'] ); } window.embedProviders = new RegExp(patternsArray.join('|'), 'i'); }, datatype: "json" }); } function testurl(url) { return function(){window.embedProviders.test(url)}; } function noembed(myhref,mydiv) { if(testurl(myhref)) { $.ajax({ url: "https://noembed.com/embed", type: "get", data: {url: myhref}, dataType: "json", success: function(data){ $(mydiv).append(data['html']); } }); } } </script>

    Noembed is an open source perl (plack) app, one can host it's own and it seems the app acts as a hub to the embed.