mirror of
https://github.com/dirkjanm/ROADtools
synced 2026-06-08 13:48:32 +00:00
roadrecon: add group members in roles overview and add links to entra portal on users and groups
This commit is contained in:
@@ -5,5 +5,9 @@
|
||||
<mat-slide-toggle [(ngModel)]="mfa" [checked]="mfa">
|
||||
Show MFA columns (only accurate if you collected this data)
|
||||
</mat-slide-toggle>
|
||||
<br />
|
||||
<mat-slide-toggle [(ngModel)]="portallinks" [checked]="portallinks">
|
||||
Show management links to Entra portal on objects
|
||||
</mat-slide-toggle>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
@@ -9,6 +9,8 @@ import { LocalStorage } from 'ngx-webstorage';
|
||||
export class ConfigComponent implements OnInit {
|
||||
@LocalStorage()
|
||||
public mfa;
|
||||
@LocalStorage()
|
||||
public portallinks;
|
||||
|
||||
constructor() { }
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<tr *ngIf="group.isAssignableToRole != null"><th>Can be assigned to roles</th><td>{{ group.isAssignableToRole? 'Yes':'No' }}</td></tr>
|
||||
<tr *ngIf="group.createdDateTime != null"><th>Created</th><td>{{ group.createdDateTime }}</td></tr>
|
||||
<tr><th>Group source</th><td>{{ group.dirSyncEnabled? 'Synced with AD':'Cloud-only' }}</td></tr>
|
||||
<tr *ngIf="showPortalLink"><th>Manage in Entra portal</th><td><a target="_blank" href="https://entra.microsoft.com/#view/Microsoft_AAD_IAM/GroupDetailsMenuBlade/~/Overview/groupId/{{ group.objectId }}"><mat-icon>open_in_new</mat-icon></a></td></tr>
|
||||
</table>
|
||||
</mat-card>
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
@@ -1,41 +1,46 @@
|
||||
import { Component, OnInit, Inject, ViewChild } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { GroupsItem } from '../../aadobjects.service'
|
||||
import { GroupsItem } from '../../aadobjects.service';
|
||||
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { MatSort } from '@angular/material/sort';
|
||||
import { Location } from '@angular/common';
|
||||
import { LocalStorageService } from 'ngx-webstorage';
|
||||
|
||||
@Component({
|
||||
template: ''
|
||||
})
|
||||
export class GroupsdialogInitComponent implements OnInit {
|
||||
user: GroupsItem;
|
||||
myurl: string;
|
||||
showPortalLink: boolean;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
public dialog: MatDialog,
|
||||
private location: Location
|
||||
private location: Location,
|
||||
private localSt: LocalStorageService
|
||||
) {
|
||||
this.myurl = this.router.url;
|
||||
this.showPortalLink = this.localSt.retrieve('portallinks');
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.data
|
||||
.subscribe((data: { user: GroupsItem }) => {
|
||||
const dialogRef = this.dialog.open(GroupsdialogComponent, {
|
||||
data: data.user
|
||||
data: {
|
||||
group: data.user,
|
||||
showPortalLink: this.showPortalLink
|
||||
}
|
||||
});
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
console.log(this.router.url);
|
||||
console.log(this.myurl);
|
||||
if(this.router.url == this.myurl){
|
||||
this.location.back();
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Component({
|
||||
@@ -49,11 +54,16 @@ export class GroupsdialogComponent {
|
||||
public displayedColumnsServicePrincipal: string[] = ['displayName', 'servicePrincipalType']
|
||||
public displayedColumnsOwners: string[] = ['displayName', 'userPrincipalName']
|
||||
public displayedColumnsDevices: string[] = ['displayName', 'deviceModel', 'deviceOSType', 'deviceTrustType'];
|
||||
public showPortalLink: boolean;
|
||||
public group: GroupsItem;
|
||||
|
||||
@ViewChild(MatSort, { static: true }) sort: MatSort;
|
||||
|
||||
@ViewChild(MatSort, {static: true}) sort: MatSort;
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<GroupsdialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public group: GroupsItem
|
||||
) { }
|
||||
|
||||
@Inject(MAT_DIALOG_DATA) public data: { group: GroupsItem, showPortalLink: boolean }
|
||||
) {
|
||||
this.group = data.group;
|
||||
this.showPortalLink = data.showPortalLink;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<tr><th>Account source</th><td>{{ user.dirSyncEnabled? 'Synced with AD':'Cloud-only' }}</td></tr>
|
||||
<tr><th>Account type</th><td>{{ user.userType }}</td></tr>
|
||||
<tr><th>Status</th><td>{{ user.accountEnabled? 'Enabled':'Disabled' }}</td></tr>
|
||||
<tr *ngIf="showPortalLink"><th>Manage in Entra portal</th><td><a target="_blank" href="https://entra.microsoft.com/#blade/Microsoft_AAD_UsersAndTenants/UserProfileMenuBlade/userId/{{ user.objectId }}"><mat-icon>open_in_new</mat-icon></a></td></tr>
|
||||
</table>
|
||||
</mat-card>
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
@@ -4,26 +4,34 @@ import { UsersItem } from '../../aadobjects.service'
|
||||
import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
||||
import { MatSort } from '@angular/material/sort';
|
||||
import { Location } from '@angular/common';
|
||||
import { LocalStorageService } from 'ngx-webstorage';
|
||||
|
||||
@Component({
|
||||
template: ''
|
||||
})
|
||||
export class UsersdialogInitComponent implements OnInit {
|
||||
user: UsersItem;
|
||||
myurl: string;
|
||||
showPortalLink: boolean;
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
public dialog: MatDialog,
|
||||
private location: Location
|
||||
private location: Location,
|
||||
private localSt:LocalStorageService
|
||||
) {
|
||||
this.myurl = this.router.url;
|
||||
this.showPortalLink = this.localSt.retrieve('portallinks');
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.data
|
||||
.subscribe((data: { user: UsersItem }) => {
|
||||
const dialogRef = this.dialog.open(UsersdialogComponent, {
|
||||
data: data.user
|
||||
const dialogRef = this.dialog.open(UsersdialogComponent,{
|
||||
data: {
|
||||
user: data.user,
|
||||
showPortalLink: this.showPortalLink
|
||||
}
|
||||
});
|
||||
dialogRef.afterClosed().subscribe(result => {
|
||||
if(this.router.url == this.myurl){
|
||||
@@ -46,11 +54,15 @@ export class UsersdialogComponent {
|
||||
public displayedColumnsServicePrincipals: string[] = ['displayName', 'publisherName', 'microsoftFirstParty', 'passwordCredentials', 'keyCredentials', 'appRoles', 'oauth2Permissions'];
|
||||
public displayedColumnsDevices: string[] = ['displayName', 'deviceManufacturer', 'accountEnabled', 'deviceModel', 'deviceOSType', 'deviceOSVersion', 'deviceTrustType', 'isCompliant', 'isManaged', 'isRooted'];
|
||||
public displayedColumnsApplications: string[] = ['displayName', 'passwordCredentials', 'keyCredentials', 'appRoles', 'oauth2Permissions'];
|
||||
|
||||
public showPortalLink: boolean;
|
||||
public user: UsersItem;
|
||||
@ViewChild(MatSort, {static: true}) sort: MatSort;
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<UsersdialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public user: UsersItem
|
||||
) { }
|
||||
@Inject(MAT_DIALOG_DATA) public data: {user: UsersItem, showPortalLink: boolean}
|
||||
) {
|
||||
this.user = data.user;
|
||||
this.showPortalLink = data.showPortalLink;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -507,9 +507,24 @@ def get_allroles():
|
||||
'scopeNames': snames,
|
||||
'scopeIds': sids
|
||||
}
|
||||
_, principal = resolve_objectid(assignment.principalId)
|
||||
principalType, principal = resolve_objectid(assignment.principalId)
|
||||
aobj['principal'] = principal
|
||||
|
||||
roleobj['assignments'].append(aobj)
|
||||
if principalType == 'Group':
|
||||
group = db.session.get(Group, assignment.principalId)
|
||||
for member in group.memberUsers:
|
||||
mp = users_schema.dump([member])[0]
|
||||
mp['displayName'] = f"{principal['displayName']} member: {mp['displayName']}"
|
||||
roleobj['assignments'].append({
|
||||
'type': 'assignment',
|
||||
'scope': assignment.resourceScopes,
|
||||
'scopeTypes': stypes,
|
||||
'scopeNames': snames,
|
||||
'scopeIds': sids,
|
||||
'principal': mp
|
||||
})
|
||||
|
||||
for assignment in role.eligibleAssignments:
|
||||
stypes, snames, sids = translate_rolescopes(assignment.resourceScopes)
|
||||
aobj = {
|
||||
@@ -519,9 +534,22 @@ def get_allroles():
|
||||
'scopeNames': snames,
|
||||
'scopeIds': sids
|
||||
}
|
||||
_, principal = resolve_objectid(assignment.principalId)
|
||||
principalType, principal = resolve_objectid(assignment.principalId)
|
||||
aobj['principal'] = principal
|
||||
roleobj['assignments'].append(aobj)
|
||||
if principalType == 'Group':
|
||||
group = db.session.get(Group, assignment.principalId)
|
||||
for member in group.memberUsers:
|
||||
mp = users_schema.dump([member])[0]
|
||||
mp['displayName'] = f"{principal['displayName']} member: {mp['displayName']}"
|
||||
roleobj['assignments'].append({
|
||||
'type': 'eligible',
|
||||
'scope': assignment.resourceScopes,
|
||||
'scopeTypes': stypes,
|
||||
'scopeNames': snames,
|
||||
'scopeIds': sids,
|
||||
'principal': mp
|
||||
})
|
||||
allroles.append(roleobj)
|
||||
return jsonify(allroles)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user