Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion app/Console/Commands/LdapSyncRoles.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@

use App\Ldap\Committee;
use App\Ldap\Community;
use App\Ldap\Group;
use App\Ldap\Role;
use App\Models\GroupMembership;
use App\Models\RoleMembership;
use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\Isolatable;
use Illuminate\Support\Facades\DB;

class LdapSyncRoles extends Command
{
Expand Down Expand Up @@ -45,6 +48,9 @@ public function handle()
->setDn(Community::$rootDn)
->search('ou', $this->argument('community'))
->get();

$this->comment("Committees:");

foreach ($realms as $realm){
$committees = Committee::fromCommunity($realm->getFirstAttribute('ou'))
->search('ou', $this->argument('committee'))
Expand All @@ -60,7 +66,7 @@ public function handle()
->where('committee_dn', $committee->getDn())
->where('role_cn', $role->getFirstAttribute('cn'))
->get();
$this->comment(" |-> " .$role->getDn());
$this->comment(" |-> " . $role->getDn());
// delete all members so far
$role->setAttribute('uniqueMember', ['']);
$ldapMembers = $role->members();
Expand All @@ -73,5 +79,38 @@ public function handle()
}
}
}

$this->comment("\nGroups:");

foreach ($realms as $realm) {
$groups = Group::fromCommunity($realm->getFirstAttribute('ou'))
->search('ou', $this->argument('group'))
->get();

foreach ($groups as $group) {
$this->comment("> " . $group->getDn());

// delete all members so far
$group->setAttribute('uniqueMember', ['']);

$roles = GroupMembership::where('group_dn', $group->getDn())->get();

foreach ($roles as $role) {
$roleCn = str_replace('cn=', '', substr($role->role_dn, 0, strpos($role->role_dn, ',')));
$committeeDn = strstr($role->role_dn, "ou=");
$activeMemberships = RoleMembership::active($date)
->where('committee_dn', $committeeDn)
->where('role_cn', $roleCn)
->get();

$ldapMembers = $group->users();
foreach ($activeMemberships as $membership) {
// add only active members back
$this->comment(" |-> $membership->username");
$ldapMembers->attach($membership->user->ldap());
}
}
}
}
}
}
60 changes: 60 additions & 0 deletions app/Console/Commands/MoveGroupRolesFromLdapToDatabase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace App\Console\Commands;

use App\Ldap\Community;
use App\Ldap\Group;
use App\Models\GroupMembership;
use Illuminate\Console\Command;

class MoveGroupRolesFromLdapToDatabase extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'app:move-group-roles-from-ldap-to-database
{community? : The short name to search for of the community}
{group? : The short name to search for of the group}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Command description';

/**
* Execute the console command.
*/
public function handle()
{
$realms = Community::query()
->list() // only first level
->setDn(Community::$rootDn)
->search('ou', $this->argument('community'))
->get();

foreach ($realms as $realm) {
$groups = Group::fromCommunity($realm->getFirstAttribute('ou'))
->search('ou', $this->argument('group'))
->get();

foreach ($groups as $group) {
$this->comment("> " . $group->getDn());

// get roles
$roles = $group->members()->get();

foreach ($roles as $role) {
$this->comment($role);
GroupMembership::create([
'group_dn' => $group->getDn(),
'role_dn' => $role,
]);
}
}
}
}
}
11 changes: 8 additions & 3 deletions app/Livewire/Group/AddRoleToGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use Livewire\Attributes\Locked;
use Livewire\Component;

use App\Models\GroupMembership;

class AddRoleToGroup extends Component
{
#[Locked]
Expand Down Expand Up @@ -42,9 +44,12 @@ public function render()

public function save()
{
/** @var Group $group */
$group = Group::findOrFail(Group::dnFrom($this->uid, $this->group_cn));
$group->members()->attach($this->selected_role_dn);
$group_dn = Group::findOrFail(Group::dnFrom($this->uid, $this->group_cn));
GroupMembership::create([
'group_dn' => $group_dn,
'role_dn' => $this->selected_role_dn,
]);

return redirect()->route('realms.groups.roles', ['uid' => $this->uid, 'cn' => $this->group_cn])
->with('message', __('groups.success_role_add'))
;
Expand Down
28 changes: 9 additions & 19 deletions app/Livewire/Group/ListRolesInGroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Ldap\Community;
use App\Ldap\Group;
use App\Ldap\Role;
use App\Models\GroupMembership;
use Livewire\Attributes\Url;
use Livewire\Component;
use Livewire\WithPagination;
Expand Down Expand Up @@ -51,16 +52,15 @@ public function updatedSearch(): void
}

public function render() {
/** @var Group $group */
$group = Group::findOrFail($this->group_dn);
$roles = $group->members()->get();
$users = $group->users()->get();
// slice breaks it, whyever - get to go.
$rolesDB = GroupMembership::select('role_dn')->where('group_dn', $this->group_dn)->get();
$roles = [];
foreach ($rolesDB as $row) {
$role = Role::findOrFail($row->role_dn);
array_push($roles, $role);
}
return view(
'livewire.group.roles', [
'roles' => $roles,
'users' => $users,
'group' => $group,
]
)->title(__('groups.roles_list_title', ['name' => $this->group_cn]));
}
Expand All @@ -75,14 +75,7 @@ public function deletePrepare(string $role_dn): void
$committee = $role->committee();

$this->deleteRoleDN = $role_dn;
$this->deleteRoleName = [
'role_short' => $role->getFirstAttribute('description'),
'role_name' => $role->getFirstAttribute('cn'),
'committee_name' => $committee?->getFirstAttribute('description'),
'committee_short' => $committee?->getFirstAttribute('ou'),
'group_short' => $group->getFirstAttribute('cn'),
'group_name' => $group->getFirstAttribute('description')
];
$this->deleteRoleName = [ $role->getFirstAttribute('cn') ];

$this->showDeleteModal = true;
}
Expand All @@ -92,10 +85,7 @@ public function deleteCommit(): void
$community = Community::findByUid($this->realm_uid);
$this->authorize('delete', [Group::class, $community]);

$group = Group::findOrFail($this->group_dn);
$role = Role::findOrFail($this->deleteRoleDN);

$group->roles()->detach($role);
GroupMembership::where('group_dn', $this->group_dn)->where('role_dn', $this->deleteRoleDN)->delete();

$this->close();
}
Expand Down
37 changes: 37 additions & 0 deletions app/Models/GroupMembership.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace App\Models;

use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;

/**
* @property integer $group_id
* @property Group $group
* @property Role $role
*/

class GroupMembership extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'role_group_relation';

/**
* @var array
*/
protected $fillable = [
'group_dn',
'role_dn',
];

public function roles(): HasMany
{
return $this->hasMany(Role::class);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('role_group_relation', function (Blueprint $table) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wie soll hier der migrationspfad von bestehenden Daten sein? aka ließt die bisherigen Gruppen aus speichert die zusammensetzung in der DB und stups mal das neue sync script.

2 Möglichkeiten: entweder die migration macht das mit, oder es gibt ein cmd Command Befehl den man dann ausführen muss - dass müsste dann auch ins Changelog beim Release.

imho ist variante 2 etwas robuster, generiert aber auch code den man "nie wieder" braucht (also außer halt genau bei dem Versionssprung).

Weiterer kleiner Vorteil von V2 ist, dass das frische migrieren long term etwas schneller ist, wenn mans in ein seperates command auslagert

Meinungen?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Das hier wäre noch zu klären @schlagma

$table->id();
$table->string('group_dn');
$table->string('role_dn');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('role_group_relation');
}
};