Plugin zur Anzeige des vollständigen Namens nur für Benutzer derselben Gruppe

Hallo zusammen,

ich suche seit einigen Wochen mit Google nach einer Lösung für mein Problem und stehe kurz davor, aufzugeben.

Der Hintergrund:
Ich entwickle und betreibe ein Admin-Panel für Sportvereine, das mehrere Mandanten unterstützt. Mein selbst gehostetes Discourse-Forum ist derzeit nur für Mitglieder dieser Vereine zugänglich. Ich möchte es jedoch für die Öffentlichkeit öffnen. Meine eigene SSO-Integration weist den Discourse-Benutzern nach dem Einloggen automatisch den vollständigen Namen aus meiner Datenbank zu.

Das Problem:
Derzeit kann ich mein Forum nicht öffentlich machen, da der vollständige Name eines Benutzers nur für andere Benutzer desselben Vereins sichtbar sein soll.

Meine Erfahrung als Ruby-Entwickler ist null (ich bin JS-Entwickler), aber bisher habe ich diesen Code-Teil herausgefunden:

# plugin.rb

after_initialize {
  require_dependency 'basic_user_serializer'
  require_dependency 'current_user'

  class ::BasicUserSerializer
    attributes :name

    def name
      # Feste Liste von Gruppennamen, die die Zugehörigkeit zu einem Verein anzeigen
      clubGroups = Array['foo', 'bar', 'baz']
      
      # TEIL, DEN ICH NICHT VERSTEHEN KANN:
      # Zeige den Namen des Benutzers NUR, wenn sie eine der gleichen Gruppen aus den aktuellen `clubGroups` des angemeldeten Benutzers teilen,
      # z. B. bin ich als Benutzer angemeldet, der zur Gruppe 'bar' gehört, was bedeutet, dass ich zum Bar-Verein gehöre. Ich sollte nur die Namen der Benutzer sehen können, die ebenfalls zur Gruppe 'bar' gehören.
      ???

    end
  end
}

Ich kann folgende Punkte nicht herausfinden:

  1. Wie rufe ich die Gruppen des aktuellen Benutzers ab?
  2. Wie rufe ich die Gruppen des jeweiligen Benutzers ab?

Sobald ich das habe, könnte ich die beiden Arrays mit clubGroups vergleichen und entscheiden, ob der Name des Benutzers angezeigt werden soll oder nicht.

Eine weitere Herausforderung für mich wird sein, die Möglichkeit zu deaktivieren, den eigenen Namen zu bearbeiten, aber das ist eine andere Geschichte.

Das GroupUser-Modell enthält die Gruppenmitgliedschaften der Benutzer.

Sie möchten etwas wie GroupUser.where(user_id: current_user.id), um die Gruppen-IDs für den aktuellen Benutzer zurückzugeben.

Dadurch erhalten Sie eine Active Record-Relation.

Anschließend können Sie diese mit map in ein Array umwandeln:

GroupUser.where(user_id: myuser.id).map {|gu| gu.group_id}

Gehen Sie für Ihren hervorgehobenen Benutzer nach demselben Prinzip vor.

Perfekt! Danke :slight_smile:

Ich weiß noch nicht, wie man daraus eine funktionierende Lösung macht, aber das ist bereits ein großer Hinweis.

Gib niemals auf. Bleib einfach dran. :rocket:

Ein weiteres Hindernis:

Beim Versuch, die ID des aktuellen Benutzers abzurufen, um sie an die Abfrage zu übergeben, weiß ich nicht wirklich, wie ich sie abrufen kann. Wenn ich im Code zum Modell CurrentUser navigiere, ist die einzige Methode, die für meine Anforderungen relevant aussieht, current_user. Wenn ich jedoch Folgendes ausführe:

pp CurrentUser.current_user

erhalte ich folgende Fehlermeldung:

undefined method `current_user' for CurrentUser:Module

Ich glaube, mir fehlt hier definitiv ein grundlegendes Wissen über Ruby, aber vielleicht könnt ihr das leicht für mich lösen?

Du solltest dir den Code dieses Plugins ansehen. Er fügt Avatar-Flairs für Personen in denselben Gruppen hinzu, sodass sie sich als Gruppenmitglieder erkennen können. Das ist zwar eine andere Funktion, aber er enthält den Code, der prüft, ob der betrachtende Benutzer derselben Gruppe angehört wie derjenige, der den Beitrag verfasst hat.

Der Hinweis hier ist diese Methode:

  def user_is_current_user
    object.id == scope.user&.id
  end

Der serialisierte Benutzer ist object.

Der aktuelle Benutzer befindet sich tatsächlich in scope.user, also funktioniert folgendes wahrscheinlich für den aktuellen Benutzer:

GroupUser.where(user_id: scope.user&.id).map {|gu| gu.group_id}

usw. usw.

Gute Tipps:

  1. Lies den Discourse-Quellcode.
  2. Wie von @RGJ erwähnt, schau dir einige Open-Source-Plugins an, um zu sehen, wie sie Dinge umsetzen.
  3. Prototypen von Funktionen in der Rails-Konsole: rails c --sandbox.

Toll! Viele großartige Erkenntnisse. Danke euch :heart_eyes:

Ich tauche jetzt ein :dealwithit:

Für den Fall, dass zukünftige Besucher dieses Themas danach suchen, hier die finale Lösung, die ich entwickelt habe.

Sie ist nicht perfekt und auch nicht optimiert, aber sie funktioniert! Und das ist der erste und wichtigste Schritt :wink:

after_initialize {
  require_dependency 'basic_user_serializer'

  class ::BasicUserSerializer
    attributes :name

    def name
      if user_is_current_user
        return _old_name_method
      else
        # TODO: diese Liste bearbeitbar machen
        clubGroups = Array['...']

        if scope.user
          ownGroups = GroupUser.where(user_id: scope.user.id)
                               .map { |gu| gu.group_id }
                               .map { |group_id| Group.find_by(id: group_id) }
                               .filter { |group| clubGroups.include? group.name }

          if ownGroups.length > 0
            ownGroupsIds = ownGroups.map { |g| g.id }

            if GroupUser.exists?(user_id: user.id, group_id: ownGroupsIds)
              return _old_name_method
            end
          end
        end
      end

      return ''
    end

    private def _old_name_method
      return Hash === user ? user[:name] : user.try(:name)
    end
  end
}