Plugin per mostrare il nome completo solo agli utenti dello stesso gruppo

Ciao a tutti,

sto cercando di risolvere il mio problema su Google da alcune settimane e sono molto vicino a rinunciare.

Il contesto:
Sto sviluppando e mantenendo un pannello di amministrazione multi-tenant per club sportivi.
Il mio forum Discourse self-hosted è attualmente accessibile solo ai membri di quei club. Vorrei renderlo pubblico. La mia integrazione SSO personalizzata assegna automaticamente il nome completo degli utenti dal mio database all’utente di Discourse dopo il login.

Il problema:
Attualmente non posso rendere pubblico il mio forum perché il nome completo di un utente dovrebbe essere visibile solo agli utenti dello stesso club.

La mia esperienza come sviluppatore Ruby è pari a zero (sono uno sviluppatore JS), ma finora sono riuscito a capire questa parte di codice:

# plugin.rb

after_initialize {
  require_dependency 'basic_user_serializer'
  require_dependency 'current_user'

  class ::BasicUserSerializer
    attributes :name

    def name
      # insieme fisso di nomi di gruppi che indicano l'appartenenza a un club
      clubGroups = Array['foo', 'bar', 'baz']
      
      # PARTE CHE NON RIESCO A RISOLVERE:
      # Mostra il nome dell'utente SOLO se condivide uno dei `clubGroups` dell'utente attualmente loggato,
      # ad esempio, sono loggato come un utente che appartiene al gruppo 'bar', il che significa che appartengo al club Bar. Dovrei essere in grado di vedere i nomi solo degli utenti che appartengono anch'essi al gruppo 'bar'
      ???

    end
  end
}

Non riesco a capire le seguenti cose:

  1. come recuperare i gruppi dell’utente corrente
  2. come recuperare i gruppi dell’utente in evidenza

Una volta ottenuti questi dati, potrei confrontare i due array con clubGroups e decidere se mostrare o meno il nome dell’utente.

Un’altra sfida per me sarà disabilitare la possibilità di modificare il proprio nome, ma questa è un’altra storia.

Il modello GroupUser contiene l’appartenenza al gruppo da parte dell’utente.

Dovresti usare qualcosa come: GroupUser.where(user_id: current_user.id) per restituire gli ID dei gruppi per l’utente corrente.

Questo ti restituirà una relazione Active Record.

Poi potresti voler mappare la relazione in un array:

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

Segui lo stesso approccio per il tuo utente in evidenza.

Perfetto! Grazie :slight_smile:

Non so ancora come trasformarlo in una soluzione funzionante, ma è già un ottimo indizio.

Non arrenderti mai. Continua così. :rocket:

Un altro ostacolo:

Quando provo a recuperare l’ID dell’utente corrente da passare alla query, non sono sicuro di come fare.
Quando navigo nel modello CurrentUser nel codice, l’unico metodo che sembra rilevante per le mie esigenze è current_user, ma quando provo a fare questo:

pp CurrentUser.current_user

ricevo l’errore:

undefined method `current_user' for CurrentUser:Module

Penso che mi stia sicuramente sfuggendo qualche conoscenza di base su Ruby, ma forse puoi risolverlo facilmente per me?

Potresti dare un’occhiata al codice di questo plugin. Aggiunge un flair per gli avatar degli utenti appartenenti agli stessi gruppi, in modo che possano riconoscersi come membri del gruppo. È una cosa diversa, ma contiene il codice che verifica se l’utente che visualizza fa parte dello stesso gruppo dell’utente che ha pubblicato.

Il indizio qui è questo metodo:

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

L’utente che viene serializzato è object.

L’utente corrente si trova invece in scope.user, quindi:

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

probabilmente funziona per l’utente corrente.

eccetera, eccetera.

Consigli utili:

  1. Leggi il codice sorgente di Discourse
  2. Come suggerito da @RGJ, consulta alcuni plugin open source per vedere come vengono gestite le cose
  3. Fai delle prove nella console di Rails con rails c --sandbox

Incredibile! Un sacco di ottime conoscenze. Grazie ragazzi :heart_eyes:

Mi immergo subito :dealwithit:

Per il bene dei futuri visitatori di questo argomento, ecco la soluzione finale a cui sono arrivato.

Non è perfetta, né ottimizzata, ma funziona! Ed è il primo e più importante passo :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: rendere modificabile questa lista
        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
}