Laravel, Groups und Berechtigungen

Werner S

Mitglied
Grüße,

nach dem man mir hier gut geholfen hat, ein großes Danke an @JR Cologne , habe ich noch eine weitere Frage.

Aus einem bestehenden System ohne Framework oder der gleichen möchte ich das Berechtigungssystem das in meinen Augen recht Simple System übernehmen.
In der Usertabelle wird eine neue Spalte angelegt mit der Gruppen ID "user_perm_grp". Die Gruppentabelle wird angelegt mit Spalten alla "project_add", "show_event" etc.

Tabellen
PHP:
Schema::table('users', function (Blueprint $table) {
            $table->integer('user_perm_grp')->nullable()->unsigned()->after('password');
            $table->foreign('user_perm_grp')->references('id')->on('groups')->onDelete('cascade');
        });

Schema::create('groups', function (Blueprint $table) {
            $table->increments('id');
            $table->string('auth_name');
            $table->tinyInteger('user_add')->default(0);
            $table->tinyInteger('show_event')->default(0);
            $table->tinyInteger('project_add')->default(0);
            $table->timestamps();
        });


PHP:
//model/Group.php
public function user()
    {
        return $this->belongsToMany(User::class, 'user_perm_grp', 'id');
    }

//model/User.php
public function group() {
        return $this->hasOne(Group::class, 'user_perm_grp', 'id');

    }

Jeder User kann nur einer Gruppe zugehören.
Nehmen wir den ProjectController.php. Hier soll überprüft werden ob der User zu der Gruppe gehört die die entsprechenden Berechtigungen besitzt.
Dazu befinden sich die Abfrage im ProjectController.php index()

PHP:
/**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        // GruppenID aus der Usertabelle laden
        $user_auth = Auth::user()->user_perm_grp;

        // Gruppe anhand der ID Lesen
        $acl = Group::find($user_auth); // Gruppen Infos
        
        /*
         * Gibt der Wert project_add aus der group Tabelle
         * kein true (1) zurück, gibt es ein 403er
         * Wurde anhand der GruppenID nix gefunden,
         * gibt es auch ein 403er
         */
        if(is_null($acl) or !$acl->project_add) {
            return view('access');
            exit;
        }

        return view('project.index');
    }

Das ganze funktioniert 1A. Da ich aber nicht in jedem Controller in jeder public function die ganzen 6 Zeilen (reiner Code) einfügen will, möchte ich die abfrage gerne in die GroupController.php auslagern.

Dazu habe ich mir in der GroupController.php eine neue public function angelegt

PHP:
/**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function access_check()
    {


    }

und würde gerne im ProjectController.php mit sowas Arbeiten Group::access_check(Auth::user()->user_perm_grp, 'project_add'); Erster Wert ist die GruppenID aus der Usertabelle, 2 Wert ist die Spalte aus der Group Tabelle. Hat die Spalte die 1, passiert gar nichts, hat die Spalte den Wert 0 soll die view('access') aufgerufen werden.

Ich weiss das es nicht die beste Lösung ist, möchte aber erst mal darauf bauen da mein Wissen bezüglich Laravel noch recht klein ist und ich so besser in die Materie einsteigen kann. Was ich dazu finden konnte ist leider alles in Englisch in dieser Sprache bin ich nicht leider so mächtig.
 

JR Cologne

Administrator
Teammitglied
Sorry, ich hoffe, ich bin nicht zu spät dran...

Das ganze funktioniert 1A. Da ich aber nicht in jedem Controller in jeder public function die ganzen 6 Zeilen (reiner Code) einfügen will, möchte ich die abfrage gerne in die GroupController.php auslagern.

Dazu habe ich mir in der GroupController.php eine neue public function angelegt

Eine Auslagerung in einen Controller ergibt eigentlich nie Sinn.
Ein Controller ist dafür da, für bestimmte Routen gewünschte Funktionen auszuführen bzw. Views zu rendern.
Der Controller wird dabei niemals aus anderen Controllern aufgerufen, sondern immer nur durch das Routing.

Wenn du eine Methode á la Group::access_check(Auth::user()->user_perm_grp, 'project_add'); konstruieren möchtest, sollte schon anhand des Aufrufs ersichtlich sein, dass du eigentlich das Group-Model meinst bzw. dort deine Methode zu implementieren ist.

Mein Vorschlag wäre entsprechend, im Modal eine Methode zu implementieren, die die Gruppe heraussucht und anschließend überprüft, ob der übergebene String (z.B. "project_add") als Permission-Property für die Gruppe existiert und bei der jeweiligen Gruppe truthy/aktiviert ist oder nicht.
Die Entscheidung, welche View gerendert wird, sollte dann aber dem Controller überlassen sein.

PHP:
// model/Group.php
public static function access_check(int $groupId, string $permission): bool
{
    $acl = self::find($groupId);

    if (is_null($acl)) {
        return false;
    }
 
    if (!isset($acl->{$permission}) || !$acl->{$permission}) {
       return false;
    }

    return true;
}

// ProjectController.php
public function index()
{
   /*
    * Gibt der Wert project_add aus der group Tabelle
    * kein true (1) zurück, gibt es ein 403er
    * Wurde anhand der GruppenID nix gefunden,
    * gibt es auch ein 403er
    */
    if(!Group::access_check(Auth::user()->user_perm_grp, 'project_add')) {
        return view('access');
        exit;
    }

    return view('project.index');
}
 
Zuletzt bearbeitet:

Werner S

Mitglied
Sorry, ich hoffe, ich bin nicht zu spät dran...
Nein, beruflich hatte ich so einiges zu tun so das ich erst mal wieder Pause machen musste.
Ich hab es jetzt erst mal nur grob überflogen und eingebaut, es führt zu einem
ErrorException
Non-static method App\Models\Group::access_check() should not be called statically
Ich schaue mir das die Tage noch mal an wo genau der Fehler liegen könnte.
 

JR Cologne

Administrator
Teammitglied
Ich habe einfach vergessen, die Methode als statisch zu definieren. Sonst kann sie nicht mit Group::access_check() aufgerufen werden.

Ist oben im Code korrigiert.
 

Werner S

Mitglied
Ich habe einfach vergessen, die Methode als statisch zu definieren. Sonst kann sie nicht mit Group::access_check() aufgerufen werden.

Ist oben im Code korrigiert.
Hi.

Ich hatte kurz nach meinem Beitrag den noch Editiert das ich bereits die Methode als statisch definiert habe.
Habe aber wohl den Tab geschlossen anstatt abzusenden :ROFLMAO:

Ich dank dir für deine Hilfe.
Jetzt muss ich noch schauen das ich das irgendwie auch im Blade anwenden kann. Hat der User nicht die Berechtigung, soll auch der Button zum hinzufügen eines neuen Projektes verschwinden.

Nachtrag: Auch das wäre geschafft.
HTML:
@if( \App\Models\Group::access_check(Auth::user()->user_perm_grp, 'project_add')) .... @endif
 
Zuletzt bearbeitet:

JR Cologne

Administrator
Teammitglied
Sehr gut! :)

Das kannst du vielleicht im Template noch etwas verschönern, indem du im Controller die entsprechende Methode aufrufst und das Ergebnis dann als Variable ins Blade-Template weiterreichst.

Kann man aber auch so machen.
 

Werner S

Mitglied
Sehr gut! :)

Das kannst du vielleicht im Template noch etwas verschönern, indem du im Controller die entsprechende Methode aufrufst und das Ergebnis dann als Variable ins Blade-Template weiterreichst.

Kann man aber auch so machen.
So etwa oder noch schöner?

PHP:
$permission = Group::access_check(Auth::user()->user_perm_grp, 'project_add');

return view('projects.index', compact('projects', 'projectuser', 'permission'));

HTML:
<span class="navbar-text">
    @if( $permission)
    <a href="{{route('projects.create')}}" class="btn btn-secondary">{{ __('default.add') }}</a>
    @endif
</span>
 
Oben Unten