Extend Existing Controller?

Hey all, I hope I’m posting this in the right place. I’m trying to develop a plugin for my new Discourse website.

I forked the example repo here, got a Plugin Outlet working, then hit a wall and started to feel pretty lost and confused. I’m recently starting to get the hang of MVC PHP frameworks like Laravel, but I am VERY new to JS frameworks. I’ve never touched Ruby, Rails, or Ember before.

The Problem

My website is for an HOA community. What I’m trying to do is collect and save a few extra fields of data per user:

  • legal_name (string)
  • is_owner (bool)
  • is_resident (bool)
  • building (string) - representing their building number
  • unit (string) - representing their unit number
  • … and a few other internal variables, like whether a moderator has confirmed them.

I want to make these fields required for user signup. That means modifying the user signup form. I hooked into the create-account-after-password outlet and got some extra fields to display, but obviously this doesn’t make it functional.

I think I need to extend the controller in app/assets/javascripts/discourse/app/controllers/create-account.js, not only to catch the new form values when submitted but even for something as (seemingly) basic as using the site name this.siteSettings.title in a client.en.yml translation field! (Right now the extra fields in my signup form are headed, “What’s your connection to [missing %{title} value]?” Which is obviously not good.)

The more I tried to look for answers, the more questions I had and the bigger they became. Different guides I tried to follow were apparently written for different versions of Discourse. The example plugin repo has things I don’t understand. What’s the difference between a clientside route and a serverside route? What’s the difference between a plugin and a module? I’m so lost.

If anybody could offer some help, I will be very grateful. Thank you in advance.

2 Likes

I think you could do that with Create and configure custom user fields

3 Likes

Thank you! That doesn’t provide all of the functionality that I think I want, but it definitely makes me pause to consider whether that feature can help me toward my goals.

Either way I think I still need to answer the original question of how to extend existing controllers using a plugin. Is such a thing possible?

save it just to display somewhere? what is it you want to do with this data? i’m under the impression you want store it for some other functionality rather than just display it somewhere on the forum.

This can be accomplished without any programming with Create and configure custom user fields

3 Likes

what is it you want to do with this data? i’m under the impression you want store it for some other functionality rather than just display it somewhere on the forum.

Well, my ultimate hope/vision was:

1. Tiered moderation

Grant owners of each unit in the community moderator powers over ONLY the residents of their unit.

Bearing in mind that there are close to 200 units in our community, it didn’t seem feasible to use the groups feature to accomplish this. See also #3 below, which groups would also conflict with.

2. Signup UX

The perfect UX in my mind would also make the drop menu for “unit” on the signup form dynamically react to the user’s choice in the “building” field, so as to offer only units that are in that building. (I was going to figure out some way to parse a JSON config file for this when Discourse initialized.)

3. Field privacy settings

I wanted to offer each user the choice whether to hide their building and/or unit number from other users not in their unit.

My impression is that the core custom fields feature offers this option only per field (not per user) and also only to admins, not to the users themselves.

4. Fancy styling

This would be more of an icing-on-the-cake thing, but instead of displaying it as something like “Owner: yes,” I wanted to give the system special knowledge of these fields to style them differently on user summaries. Like put an SVG deed icon, and a check mark if a moderator has confirmed their status (or a house icon for residents). That sort of thing.

So, yeah …

Maybe I’m being too picky here, but I feel like once I’m past the learning curve to accomplish the core functionality then the smaller wish list items will become almost trivial.

Many of the residents in my community are older people with little to no computer knowledge. I have serious concerns about some of the residents not wanting to adopt and use my Discourse website just because it’s new and not Facebook, let alone because of genuine usage issues like address privacy or unvalidated input of building/unit numbers.

2 Likes

Groups will work fine for that purpose, and you can easily have 200 groups.
All you would need to do is to manually or programmatically map the field onto a group. But you might also want to have people send in some kind of "proof’ after registration.
You could do it manually, code that yourself, use Pavilion’s custom wizard plugin for that.

That’s true, but you could have users who want to make it public display that field somewhere else, i.e. have a “private” building field and a “public” building field.

2 Likes

If you do need to add features, you want to create a plugin or theme component, not fork discourse.

You can do that in a theme component, so you don’t need a plugin for that, but if you are making a plugin, you can include the front end changes in the plugin too. Developing Discourse Plugins - Part 1 - Create a basic plugin. Looking for plugins that add similar functionality is also a good way to go. There is a Discourse repo called all-the-plugins that you can use to be able to search for examples.

Having public vs private versions of those fields as suggested seems like a good solution, but you can also add user fields in a plugin and control how and whether those fields are added to the serializer to display them.

This is what theme components do. Theme Developer Quick Reference Guide could be a start.

2 Likes

I don’t think TS intended to fork discourse??

3 Likes

It looks like the repo he linked to is a fork and not a plugin.

2 Likes

image

Forking discourse-plugin-skeleton seems a good start for writing a plugin to me…

5 Likes

Agreed! I don’t know what I think I saw! Don’t know how I missed that it was a fork. :person_shrugging:

I thought I looked for plugin.rb

2 Likes

it’s ok i learned things from this conversation as a result :grin:

2 Likes

Thanks @RGJ for clarifying that for me! :sweat_smile: Yes, I definitely would never have forked Discourse itself just for this.

you can also add user fields in a plugin and control how and whether those fields are added to the serializer to display them.

Does this include adding them to the “create account” modal form, and making them required? Can you point me toward any examples or guides for how to do this?

I’ve already read the entire guide that you linked to “Developing Discourse Plugins.” That’s where I started. In the end the only real functionality it shows how to extend is creating a new admin page with a purple tentacle. I already have an admin page working for my plugin, but I’m not even sure I will need one. It’s unrelated to the current problems in front of me, so their example isn’t very helpful for my case.

2 Likes

Groups will work fine for that purpose, and you can easily have 200 groups

It would actually be between 400 and 600 to cover all the permutations (owner, resident, or affiliate of each unit). But how would that work? Can 200 groups all display identically to users, so it just says “Owner” instead of “Owner 187” or something?

This is more of a nitty-gritty question, but does an internal group ID get exposed to end users anywhere, e.g. in a URL? If a user has their unit number set to private, could someone figure it out by checking the group ID against other users?

It seems to me that I would possibly have better results creating just 3 groups (owner, resident, and affiliate – or just 2: owner and resident). Maybe I could assign those groups as appropriate like you said, then block certain actions if the user is trying to moderate a resident of the wrong unit?

I guess if blocking an action like that is totally impossible, then yeah I’m stuck with making 600 groups … and just hoping that we don’t have any users getting clever ideas to “hack” the system and dox anyone.

Wait. What? So if I’m a renter and I say something in the forum my landlord can change my words? Topics are owned only by a single category, so you would then have conversations that are only between the owner and tenant.

That doesn’t make sense. And there really isn’t an easy way to have topic-level permissions.

I would think that you’d want some per-building groups and categories, but per unit control just doesn’t make sense.

I didn’t say anything about topic-level permissions.

Maybe “moderator” is the wrong word? I don’t know. (I’ve never used Discourse before now.)

I’m talking about approving or removing access to the forum per user. So no, your landlord can’t change your words, but they’re the ones with authority to confirm your signup as a resident, and if you become a troll they can mute or ban you. Posts and topics are moderated equally against a content policy, by website staff, not by the owners.

My goal is to tie access to the forum as much as possible to legal chain of authority over each property itself. No confirmed owner who legally owns a property here should ever be banned, but if they make a post that violates policy that post can be removed by staff. However if they sell the property, their “owner” status is immediately revoked, possibly resulting in removal from the website (unless they opt for “affiliate” status and are approved by the new owner of the property).

In our community there is no relation that one unit has to another in the same building, except that it’s physically attached. That’s it. Grouping people by building is pretty much a cosmetic UX decision; appointing authorities over whole buildings would make no sense here.

I found this: Add a custom per-user setting in a plugin

In the comments, one user said he “patched a controller.” He has a .js.es6 file in assets/javascripts/discourse/initializers/ that references a method called api.modifyClass()

Hmmmmmmm :thinking: Maybe I am onto something here.

2 Likes

Yeah! That’s the ticket!

I do advise that you get more familiarity with discourse before you decide just what you want to do.

I think that it’ll be easier if a small set of people approve people joining the site rather than every owner of a unit also controls access to the site. If the owners are who decides, what happens when someone sells the unit? Who would decide then? What about an owner who doesn’t care of their tenant can be a member of the forum? If think leaving it to the manager of the complex would make much more sense and likely not require a plugin.

1 Like