:fa_bullhorn: The sound of AN ANNOUNCEMENT BEING MADE (or: Request for Comments: Comments)



  • @PJH what's going to happen to Turn Left?



  • Or the Lounge for that matter. Do I need to save a certain thread so I can use later?



  • I was thinking trust level 3 could become manually managed, especially because groups can have multiple non-admin owners. It's just that NodeBB doesn't have a concept of "global moderator but with stupid arbitrary restrictions".



  • Does it have groups that have access to boards/categories without being "moderators"? If so, no problem.



  • There are no global moderators. Users can either be admin (and therefore have every permission on every category) or be given any of these permissions, possibly via a group they are a member of:

    • Find category
    • Access & Read
    • Create Topics
    • Reply to Topics
    • Purge
    • Moderate

    Groups include registered-users, guests, and any admin-defined groups.



  • Also, a very small group of topics failed to import. Among them is this one:

    https://what.thedailywtf.com/t/topic/52193 (invalid title)

    and this one:

    https://what.thedailywtf.com/t/cant-delete-this-category-because-topic-count-is-1/2079 (category not imported)

    All of the topics that failed are in the same category and have the same failure reason as one of those two.


    Also, I fixed a bug that caused all Discourse replies to be skipped completely.


    Edit: Just saw this:

    [nodebb-plugin-import] importer.warn [2016-02-23T06:11:42.212Z] [process-count-at: 5480] skipping post: 12373:tid:11589:_tid:1159:uid:67:_uid:72 MongoError: E11000 duplicate key error index: 0.objects.$key_1_value-1 dup key: { : "user:67", : null }

    [nodebb-plugin-import] importer.warn [2016-02-23T06:11:48.581Z] [process-count-at: 5904] skipping post: 13255:tid:11619:_tid:1261:uid:681:_uid:707 MongoError: E11000 duplicate key error index: 0.objects.$key_1_value-1 dup key: { : "user:681", : null }

    [nodebb-plugin-import] importer.warn [2016-02-23T06:12:01.508Z] [process-count-at: 6669] skipping post: 14861:tid:11634:_tid:1313:uid:709:_uid:747 MongoError: E11000 duplicate key error index: 0.objects.$key_1_value-1 dup key: { : "user:709", : null }

    Investigating in the morning.


  • Discourse touched me in a no-no place

    @ben_lubar said:

    https://what.thedailywtf.com/t/topic/52193 (invalid title)

    Because it's empty. Arguably a DC bug in that it shouldn't have been allowed.

    https://what.thedailywtf.com/t/cant-delete-this-category-because-topic-count-is-1/2079 (category not imported)

    Because it's not actually in a category. Not a DC bug in that they are allowed in principle, bug in that I disabled that 'feature' ages ago, and yet it still allows admins to create them. Then again, the URL for that second one gives the reason for that post's existence - and possibly why, even though it's shown as uncategorized, it actually does have one behind the scenes...


  • Discourse touched me in a no-no place

    @ben_lubar said:

    @PJH what's going to happen to Turn Left?

    Groups, manually assigned to begin with, I suspect.



  • @PJH said:

    Because it's not actually in a category.

    From what I can tell, it's in a nonexistent category.

    Which is different from being in uncategorized, a category that exists.



  • @ben_lubar said:

    I was thinking trust level 3 could become manually managed, especially because groups can have multiple non-admin owners. It's just that NodeBB doesn't have a concept of "global moderator but with stupid arbitrary restrictions".

    We [staff/forum] would probably decide on automatic promotion rules. No one wants to manually track and manage this sort of thing.


  • Discourse touched me in a no-no place

    @ben_lubar said:

    From what I can tell, it's in a now nonexistent category.

    @PJH said:

    and possibly why, even though it's shown as uncategorized, it actually does have one behind the scenes

    Hence the reason for the post existing to begin with.



  • Do I smell a SockBot? @accalia, do you think you could write a bot that manages TL3?


  • FoxDev

    @ben_lubar said:

    @accalia, do you think you could write a bot that manages TL3?

    i see no reason why that couldn't be automated, given sufficient time.


  • ♿ (Parody)

    There are some NodeBB features that I think can make a user a member of a group based on some sort of criteria. It's less involved than discourse, but there's something already there.



  • "Rewards", I believe they are called.



  • Ok, I updated docker-engine and it shut down the container, but the part that wasn't working that I fixed worked in the test, so I'm going to get rid of the containers and run through the setup steps to make sure everything I wrote down is correct.

    I think I'll also write a script that can be pasted into MongoDB that will set up the category permissions and site settings for WTDWTF. I won't try to make a general importer for that stuff because that would be significantly harder and significantly more likely to break.



    • nodebb-plugin-soundpack-default (included by default, user-configurable)
    • nodebb-plugin-emoji-extended (included by default)
    • nodebb-plugin-markdown (included by default, needed for Discourse posts to work)
    • nodebb-rewards-essentials (included by default)
    • nodebb-plugin-composer-default (included by default)
    • nodebb-theme-lavender (included by default, user-configurable)
    • nodebb-widget-essentials (included by default)
    • nodebb-plugin-mentions (included by default, one of Discourse's few good features)
    • nodebb-plugin-spam-be-gone (included by default)
    • nodebb-theme-vanilla (included by default, user-configurable)
    • nodebb-theme-persona (included by default, user-configurable)
    • nodebb-plugin-dbsearch (included by default)
    • nodebb-plugin-import-tdwtf (redirects for Discourse and Community Server URLs)
    • nodebb-plugin-ns-login (used by the front page code)
    • nodebb-plugin-sanitizehtml (needed for Discourse and Community Server posts to work while not having XSS vulnerabilities)
    • nodebb-plugin-google-analytics (front page uses Google Analytics, so why not?)
    • nodebb-plugin-gravatar (opt-in per-user)
    • nodebb-plugin-ns-custom-fields (sex/gender from profiles, not yet imported)
    • nodebb-plugin-poll (polls, not yet imported)
    • nodebb-plugin-category-notifications (one of Discourse's few good features)
    • nodebb-plugin-sso-{facebook,github,google,twitter} (onefour of Discourse's few good features)
    • nodebb-plugin-write-api (possibly useful for SockBot)

    Can anyone think of any plugins that would be useful that aren't on this list?


  • FoxDev

    @ben_lubar said:

    nodebb-plugin-write-api (possibly useful for SockBot)

    /me makes a note to look into that API



    1. Disney or something?

  • FoxDev

    you don't keep tabs on the flame wars here do you?

    cause there's a recent one that would explain it


  • Trolleybus Mechanic

    @accalia said:

    you don't keep tabs on the flame wars here do you?

    She asked in a thread specifically dedicated to Ben getting real actual work done.

    Fucking hell.


  • FoxDev

    @Lorne_Kates said:

    She asked in a thread specifically dedicated to Ben getting real actual work done.

    in response to an extremely off topic question from Ben, and, i assume due to his use of my avatar, directed at me..... yes.

    be thankful i didn't wrote the full explanation here too.



  • @Lorne_Kates said:

    She asked in a thread specifically dedicated to Ben getting real actual work done.

    :rolleyes:

    @accalia said:

    be thankful i didn't wrote the full explanation here too.

    :rolleyes:


    Anyway, the postgres database setup instructions work and I was able to get NodeBB set up with all the plugins downloaded while that was going. Time to head to my desk and then set up the importer plugin.


  • Trolleybus Mechanic

    @accalia said:

    be thankful i didn't wrote the full explanation here too.

    Given that there's 257 🔥 threads, you could at least post a link to WHICH one.


  • FoxDev

    @Lorne_Kates said:

    @accalia said:
    be thankful i didn't wrote the full explanation here too.

    Given that there's 257 🔥 threads, you could at least post a link to WHICH one.

    i was the OP and there's currently six 🔥's in the title



  • So anyway, is there an SSO from Twitter plugin? I know a user who uses that.



  • What is it with people asking for things to be added to lists that contain those things in this thread?



  • @ben_lubar said:

    Here's what the NodeBB quote button produces:

    Then convert every [quote] to that format, I guess.

    If you can still find the correct post that's being quoted (i.e. hasn't been jeffed to someplace else), then making said into a link to it would be a nice added bonus feature.


  • :belt_onion:



  • It wasn't clear from context, sorry.


  • FoxDev

    @ben_lubar said:

    What is it with people asking for things to be added to lists that contain those things in this thread?

    welcome to requirements gathering 101



  • Could be me for all you know ;)



  • I guess duplicate requirements are better than missing or incorrect ones.


  • FoxDev

    @ben_lubar said:

    missing or incorrect ones.

    oh we'll find out we had those too once we go live with the new forum.

    no fear there.



  • @anotherusername said:

    [quote="ben_lubar, post:311, topic:54231"]
    Here's what the NodeBB quote button produces:

    Then convert every <blockquote> to that format, I guess.

    If you can still find the correct post that's being quoted (i.e. hasn't been jeffed to someplace else), then making said into a link to it would be a nice added bonus feature.

    Anyone feel like writing something that'll do this in JS or SQL? You'd have to have it work with Markdown backtick escapes, so it's non-trivial.

    The /t/from-quote/123/456 URLs will still work. No idea if I can do anything about Jeffed posts, but they're broken in Discourse already so whatever.



  • @accalia said:

    This insecurity can be mitigated but not elimiated if HTML is allowed.

    I would disagree. A proper whitelist-based subset of HTML which is aware of things such as hrefs, titles, classes, and styles should work fine. Any other attribute in the tag should be nuked; the parsing of classes and styles should also be whitelist-based, and all of them should be properly escaped.

    Handling stuff like unclosed and mismatched tags can be handled using a suitable library... parse the cleaned HTML into a DOM object, and then convert that back into valid HTML.

    @ben_lubar said:

    I remember the community server censor list having a bunch of variations of javascript followed by a colon in it.

    Oh hell no. If everything just gets escaped properly when it should be escaped, that's a non-issue.

    @ben_lubar said:

    Also I remember the ability to post an image that logs out the user that views it.

    The real issue there was that loading the URL logged the user out. If there's a logout URL that works via GET, then there should be some per-session nonce tied to it, without which nothing would happen.

    @dkf said:

    [color="red;other-css-shit:here"]

    Yep, exactly, and the resulting HTML was <span style="color:red;other-css-shit:here">. Nothing that couldn't have been easily prevented with proper sanitization/escaping. Although it was rather fun, when it wasn't abused too badly (and sometimes even when it was)...

    @PJH said:

    @ben_lubar said:
    https://what.thedailywtf.com/t/topic/52193 (invalid title)

    Because it's empty. Arguably a DC bug in that it shouldn't have been allowed.

    Right; I'd think that it'd be just fine to stick a placeholder in there and call it good.

    @ben_lubar said:

    Anyone feel like writing something that'll do this in JS or SQL? You'd have to have it work with Markdown backtick escapes, so it's non-trivial.

    It might be easier if you trash the raw and just start from the cooked HTML. Then you're dealing with (somewhat) sanitized HTML instead of the whole :disco:‌HTMLmarkdownup‌:arrows:BBcode 💩.


  • FoxDev

    @anotherusername said:

    If there's a logout URL that works via GET, then there should be some per-session nonce tied to it, without which nothing would happen.It should be disabled and replaced with one that works via POST

    FTFY



  • Or that.



  • @anotherusername said:

    Right; I'd think that it'd be just fine to stick a placeholder in there and call it good.

    I can't catch the error because it happens inside the importer written by @akhoury, not my exporter. In any case, there are only two topics skipped because of title and both of them are in one post.



  • If there's only two of them, you could just go edit the titles by hand. :P


  • FoxDev

    @anotherusername said:

    Or that.

    not or about it. you need to make a post to log in, you need to make a post to log out, because logging out is a user action, not a request for a resource. If you start conflating what a GET and what a POST is then.... well that's why i invented the BFC 9000...


  • FoxDev

    @anotherusername said:

    If there's only two of them, you could just go edit the titles by hand. 😛

    or add a special case in the exporter to fix the titles (UUID anyone?)



  • Why not DELETE /login HTTP/1.1



  • Because that's what Discourse does?


  • FoxDev

    @ben_lubar said:

    Why not DELETE /login HTTP/1.1

    that would work too, of course there are still browsers that don't understand DELETE, as well as paranoid network admins that block non GET/POST requests for rasins

    still if you want to have your web application spit in the face of someone who chooses to, or is forced to, browse under one of the aforesaid examples (or any other one that has a similar effect) then feel free, but expect me to complain about it.



  • Why do we want a "sound pack?" I don't know what a sound pack is, but I can't imagine it's a good idea to put anything called a "sound pack" on this forum.

    You know that less than 3 days in we'll be hearing looping howler monkeys at 300% volume, right?

    @ben_lubar said:

    nodebb-plugin-sso-{facebook,github,google,twitter} (onefour of Discourse's few good features)

    Do people signing in from Gith Ub have a unique icon so we can point and laugh at them?


  • Trolleybus Mechanic

    @blakeyrat said:

    Gith Ub

    A knock-off source repository from Africa written by disease-ridden tribal children suffering from malnutrition and malaria?

    Still better than Github.



  • Query:

    SELECT p.id * 2 + 1 AS _pid, COALESCE((SELECT t.value::int * 2 FROM topic_custom_fields AS t WHERE t.name = 'import_id' AND t.topic_id = p.topic_id), p.topic_id * 2 + 1) AS _tid, p.user_id AS _uid, p.raw AS _content, p.created_at AS _timestamp, p.updated_at AS _edited, CASE WHEN p.deleted_at IS NULL THEN 0 ELSE 1 END AS _deleted, COALESCE((SELECT c.value::int * 2 FROM post_custom_fields AS c WHERE c.name = 'import_id' AND c.post_id = r.id), r.id * 2 + 1) AS "_toPid" FROM posts AS p LEFT JOIN topics AS t ON p.topic_id = t.id LEFT OUTER JOIN posts AS r ON p.topic_id = r.topic_id AND p.reply_to_post_number = r.post_number LEFT OUTER JOIN post_custom_fields AS f ON f.post_id = p.id AND f.name = 'import_id' WHERE p.post_number <> 1 AND t.archetype = 'regular' AND f.value IS NULL AND p.id > $3::int AND p.created_at > $4::timestamp ORDER BY p.id ASC LIMIT $1::int OFFSET $2::int
    

    Example execution plan:

     Limit  (cost=240409.40..240423.94 rows=5818 width=308)
       ->  Sort  (cost=240409.40..240423.94 rows=5818 width=308)
             Sort Key: p.id
             ->  Nested Loop Left Join  (cost=119344.78..239209.09 rows=5818 width=308)
                   ->  Hash Right Join  (cost=119344.35..140469.99 rows=154 width=308)
                         Hash Cond: (f.post_id = p.id)
                         Filter: (f.value IS NULL)
                         ->  Seq Scan on post_custom_fields f  (cost=0.00..2011.78 rows=81086 width=18)
                               Filter: ((name)::text = 'import_id'::text)
                         ->  Hash  (cost=96832.04..96832.04 rows=420665 width=308)
                               ->  Hash Join  (cost=1714.91..96832.04 rows=420665 width=308)
                                     Hash Cond: (p.topic_id = t.id)
                                     ->  Seq Scan on posts p  (cost=0.00..83519.27 rows=656996 width=308)
                                           Filter: (post_number <> 1)
                                     ->  Hash  (cost=1545.92..1545.92 rows=13519 width=4)
                                           ->  Seq Scan on topics t  (cost=0.00..1545.92 rows=13519 width=4)
                                                 Filter: ((archetype)::text = 'regular'::text)
                   ->  Index Scan using index_posts_on_topic_id_and_post_number on posts r  (cost=0.42..7.60 rows=1 width=12)
                         Index Cond: ((p.topic_id = topic_id) AND (p.reply_to_post_number = post_number))
                   SubPlan 1
                     ->  Index Scan using index_topic_custom_fields_on_topic_id_and_name on topic_custom_fields t_1  (cost=0.28..8.31 rows=1 width=5)
                           Index Cond: ((topic_id = p.topic_id) AND ((name)::text = 'import_id'::text))
                   SubPlan 2
                     ->  Index Scan using index_post_custom_fields_on_post_id_and_name on post_custom_fields c  (cost=0.42..8.45 rows=1 width=14)
                           Index Cond: ((post_id = r.id) AND ((name)::text = 'import_id'::text))
    (25 rows)
    

    Any PostgreSQL experts have any ideas about how to optimize this?



  • Ok, new query plan:

     Limit  (cost=147914.33..147928.87 rows=5817 width=327)
       ->  Sort  (cost=147914.33..147928.87 rows=5817 width=327)
             Sort Key: p.id
             ->  Hash Left Join  (cost=122936.25..146675.59 rows=5817 width=327)
                   Hash Cond: (p.topic_id = tf.topic_id)
                   ->  Nested Loop Left Join  (cost=122737.02..146202.01 rows=5817 width=322)
                         ->  Hash Right Join  (cost=122736.18..143860.76 rows=154 width=308)
                               Hash Cond: (f.post_id = p.id)
                               Filter: (f.value IS NULL)
                               ->  Seq Scan on post_custom_fields f  (cost=0.00..2011.78 rows=81086 width=18)
                                     Filter: ((name)::text = 'import_id'::text)
                               ->  Hash  (cost=100225.39..100225.39 rows=420623 width=308)
                                     ->  Hash Join  (cost=1714.91..100225.39 rows=420623 width=308)
                                           Hash Cond: (p.topic_id = t.id)
                                           ->  Seq Scan on posts p  (cost=0.00..86913.79 rows=656930 width=308)
                                                 Filter: ((post_number <> 1) AND (id > (-1)) AND (created_at > '1970-01-01 00:00:00'::timestamp without time zone))
                                           ->  Hash  (cost=1545.92..1545.92 rows=13519 width=4)
                                                 ->  Seq Scan on topics t  (cost=0.00..1545.92 rows=13519 width=4)
                                                       Filter: ((archetype)::text = 'regular'::text)
                         ->  Nested Loop Left Join  (cost=0.84..15.19 rows=1 width=26)
                               ->  Index Scan using index_posts_on_topic_id_and_post_number on posts r  (cost=0.42..7.60 rows=1 width=12)
                                     Index Cond: ((p.topic_id = topic_id) AND (p.reply_to_post_number = post_number))
                               ->  Index Scan using index_post_custom_fields_on_post_id_and_name on post_custom_fields rf  (cost=0.42..7.58 rows=1 width=18)
                                     Index Cond: ((post_id = r.id) AND ((name)::text = 'import_id'::text))
                   ->  Hash  (cost=125.91..125.91 rows=5865 width=9)
                         ->  Seq Scan on topic_custom_fields tf  (cost=0.00..125.91 rows=5865 width=9)
                               Filter: ((name)::text = 'import_id'::text)
    


  • That's a lot of sequential scans. If this were a MySQL or MSSQL DB, I'd say add moar indexes, but since this is Postgres...

    Hmm, I wonder what would happen if you did a WHERE post_id IN (SELECT post_id FROM post_custom_fields WHERE name = 'import_id'). Subqueries are usually terrible, but if we can reduce the cost of those sequential scans...

    I wish I could ask Thalagyrt, but we're not paying him yet... :sadface:


Log in to reply