HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

Anyone know of an addon to ban users from a discussion?

24567

Comments

  • Ok so when I click on the menu item now the op up shows that it is "thinking" and then it eventually resolves to a blank page but not at the path that we sent it. It stays on the same url where I was when I clicked the menu item. So wondering if the url path is wrong somehow or if being an embedded forum is causing the issue. How to make it work for embedded or not?

  • R_JR_J Ex-Fanboy Munich Admin

    Please do two things:
    1. right click on the link in the drop down and open it in a new tab. Check if that is working.
    2. look at the JavaScript console of your browser. What you describe sounds as if there is a js error.

  • This is the behavior.

  • R_JR_J Ex-Fanboy Munich Admin

    /vanilla/discussionban/106 cannot be found. That is quite strange

    Please try what is happening, when you create the method in the discussion controller. Search for
    'Url' => '/vanilla/discussionBan/'.$args['Discussion']->DiscussionID, and make it
    'Url' => '/discussion/discussionBan/'.$args['Discussion']->DiscussionID,

    and public function vanillaController_discussionBan_create($sender) { should become public function discussionController_discussionBan_create($sender) {

  • Hmmm same behavior.

  • R_JR_J Ex-Fanboy Munich Admin

    What is the link when you open it in a new tab?

  • Well I can't get it from right clicking on the menu item and I can't right click it to tell it to open in a new tab....
    However, my forum root is at: https://vikefans.com/discussion/#/discussions

    So given the path that we put in for discussion id 106 I would think it would be:

    https://vikefans.com/discussion/discussionBan/106/ But that gives me a page not found error.

    Trying https://vikefans.com/discussion/#/discussionBan/106/
    Brings me to a blank page.

  • MikeOlsonMikeOlson
    edited July 2017

    so if I change

            if (isset($args['DiscussionOptions'])) {
                $args['DiscussionOptions']['discussionBan'] = array(
                    'Label' => t('Ban Users From This Discussion'),
                    'Url' => '/discussion/discussionBan/'.$args['Discussion']->DiscussionID,
                    'Class' => 'Popup'
                );
    

    to

            if (isset($args['DiscussionOptions'])) {
                $args['DiscussionOptions']['discussionBan'] = array(
                    'Label' => t('Ban Users From This Discussion'),
                    'Url' => 'discussion/discussionBan/'.$args['Discussion']->DiscussionID,
                    'Class' => 'Popup'
                );
    

    I get a popup but it is just a listing of the comments in the thread.

  • Ok I got it working.

    First I needed to switch back to the array method you were using.... But I needed to drop the first slas from the url. Now the popup comes up.

                $args['DiscussionOptions']['discussionBan'] = [
                    'Label' => t('Ban User from Discussion'),
                    'Url' => 'discussion/discussionBan/'.$args['Discussion']->DiscussionID,
                    'Class' => 'Popup'
                ];
    
  • ok so it only works from the discussion list view. If I go into a discussion and click the menu item a popup comes up but it shows a list of all comments in the discussion.

  • ok so I get that I should see some output when hitting submit from what is in the first part of the if/else statement but nothing shows up. If I put an echo in the else statement I do see that returned so I understand how it is supposed to work but that decho isn't returning anything for me. After clicking the button it grays out and there is nothing displayed.

            if ($sender->Form->authenticatedPostBack()) {
                // This will only be run when the user pressed the button.
                decho($sender->Form->formValues(), 'debug', true);
                die;
            } else {
                // This will be run when the view is opened
    
            }
    
  • R_JR_J Ex-Fanboy Munich Admin

    Great that you solve the issue, which isn't an embed issue but a mistake I make quite often: I have the bad habit to use absolute paths :(


    In fact you plan to not really see anything when hitting the submit button, though getting some kind of response would be nice.

    Here is what should work in any case (but it wouldn't be too helpful for debugging):

            if ($sender->Form->authenticatedPostBack() == false) {
                // This will be run when the view is opened
                $sender->Form->setValue('UserNames', 'HelloWorld');
            } else {
                // This will only be run when the user pressed the button.
                $sender->informMessage(t("Your changes have been saved."));
            }
    

    You will notice that I switched the order: the upper code block is for the first time the form is shown and the second code block handles what should happen after submit has been pressed. It doesn't matter at all how you do it, but I just thought it would feel more natural that order...

    In your view there is a control called UserNames. We simply give it some value so that you see how to fill it.

    After a form is saved, users should get some feedback. The informMessage() will do that.

    Now here is what you should do next: find out about the Discussion tables Attributes column. Try to save to it and read from it. After all, there is not much more to do in this method then:
    1. before the form is render
    1.1. read a list of user ids from the discussion attributes (and it will already be accessible as an array)
    1.2. loop through that array and get the names to that ids (search the source code for "getByUsername" to find examples on how to do that)
    1.3. feed that list of names to the text box
    1.4. find out how to feed the names so that they are displayed correctly ;-)
    2. after the submit button has been pressed
    2.1. get the value of the text box
    2.2. make that string in array
    2.3. loop through that array and get the userid for all that names
    2.4. save that array to the discussion (remember the saveToSerializedColumn method)

    That should be everything which is needed to keep track of the list of banned users.

    Why converting the names, you might ask? First of all "denormalization". It simply is the correct way to store information. But that is no satisfying answer. There are mainly two reasons. One is that an ID is much, much shorter than a name and you certainly do not want to blow up your database. But the second reason weighs much more. You can users allow to change their names. If you do that in your forum, they would simply rename themselves from asshole to asshole² and the ban would be useless. Or imagine you delete a very annoying user with the name John (although deleting users is a bad idea) and when the next user happily takes the user name "John" he would take over all those bans from the evil John. Therefore you have to save the IDs and not the names.


    After we are finished with the above, three things are missing:
    1. Banned users must be stopped from saving comments (most important thing)
    2. User should get a visual hint when they open a discussion they are banned from
    3. There should be a module in the panel showing banned users. That is a comfort feature and should come last

  • R_JR_J Ex-Fanboy Munich Admin

    Oh wait, with that code change I get some strange results sometimes. Please use this line: 'Url' => url('vanilla/discussionban/'.$args['Discussion']->DiscussionID),

    (You might have seen that I switched back to "vanilla/discussionban" instead of "discussion/discussionban"

    I made all those changes on the github repo so that you can download a version from there so that we talk about the same code base

  • R_JR_J Ex-Fanboy Munich Admin

    Oh and what is certainly missing too, are some permission checks. Although we show this link only to users with correct permissions, the method itself is accessible even for guests by now.

    And also it should be checked if the one saving the banned users is allowed to access that discussion. Maybe during your research for other problems you stumble upon how to secure the access to this method. "checkPermission" is the key word...

  • Hmmm the infomessage is still not displaying and the form just closes itself. Although I had been wondering how to do a message, which is something that I use a lot in working through code.

    Is that because of this in the view?
    <?php echo $this->Form->close('Ban Users'); ?>

    is there there a submit rather than a close?

  • R_JR_J Ex-Fanboy Munich Admin

    If you inspect the html of the popup, you will see that there is a submit button.

    By the way: you can find out such things also by looking at Vanillas source code. And you will learn a lot about Vanilla if you do!

    If you do not see any message (which is a pitty), don't focus on that. The main task is not to display anything. Get the most important things done: saving user information to the database and retrieve that information.
    You could always inspect the db directly to see if a saving action has been successful.

    And as I said before: you can always open the link in a separate tab. If you hover over the link, you will see the address.

  • Well the thing isn't so much that I don't see the message, but the form actually closes. So I won't see anything. Which is a shame.

  • R_JR_J Ex-Fanboy Munich Admin

    Okay, plan is:

    • you have an additional option in the discussion options menu [checked]
    • that option opens a popup with an input field and a button [checked]
    • when the form opens and there are already banned users, the form should be pre-populated with that names [open]
    • when the submit button is clicked, the currently displayed users shall be saved [open]

    If the "informMessage" would work, it would display a satisfying "Your changes have been saved". But only because that isn't shown doesn't mean you cannot run code.

    And again: if you open that link in a separate tab in parallel, you would be able to see much more than if you use it in a popup. If I look at /discussion/#/discussion/discussionban/106 at your forum, I can see the form

    You might want to put a $sender->permission('Garden.Moderation.Manage'); right below the public function discussionController_create($sender) { so that not everybody is able to look at you testing things ;-)

  • Moving on to trying to save to the database table.

    ok so is there a better way to do this than doing a query from as described here> http://docs.vanillaforums.com/developer/framework/datasets/

  • @R_J said:
    Okay, plan is:

    • you have an additional option in the discussion options menu [checked]
    • that option opens a popup with an input field and a button [checked]
    • when the form opens and there are already banned users, the form should be pre-populated with that names [open]
    • when the submit button is clicked, the currently displayed users shall be saved [open]

    If the "informMessage" would work, it would display a satisfying "Your changes have been saved". But only because that isn't shown doesn't mean you cannot run code.

    And again: if you open that link in a separate tab in parallel, you would be able to see much more than if you use it in a popup. If I look at /discussion/#/discussion/discussionban/106 at your forum, I can see the form

    You might want to put a $sender->permission('Garden.Moderation.Manage'); right below the public function discussionController_create($sender) { so that not everybody is able to look at you testing things ;-)

    Thanks R_J
    I have the form open in a separate tab now and the info message is working correctly!

Sign In or Register to comment.