mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-19 21:03:17 -07:00
work around the user management
This commit is contained in:
parent
5b49d03f85
commit
5ec9123851
19 changed files with 328 additions and 68 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -237,3 +237,4 @@ _Pvt_Extensions
|
||||||
*.ncrunchproject
|
*.ncrunchproject
|
||||||
*.ncrunchsolution
|
*.ncrunchsolution
|
||||||
|
|
||||||
|
*.txt
|
||||||
|
|
|
@ -11,5 +11,6 @@ namespace Ombi.Core.IdentityResolver
|
||||||
Task<UserDto> GetUser(string username);
|
Task<UserDto> GetUser(string username);
|
||||||
Task<IEnumerable<UserDto>> GetUsers();
|
Task<IEnumerable<UserDto>> GetUsers();
|
||||||
Task DeleteUser(UserDto user);
|
Task DeleteUser(UserDto user);
|
||||||
|
Task<UserDto> UpdateUser(UserDto userDto);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -84,6 +84,12 @@ namespace Ombi.Core.IdentityResolver
|
||||||
await UserRepository.DeleteUser(Mapper.Map<User>(user));
|
await UserRepository.DeleteUser(Mapper.Map<User>(user));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<UserDto> UpdateUser(UserDto userDto)
|
||||||
|
{
|
||||||
|
var user = Mapper.Map<User>(userDto);
|
||||||
|
return Mapper.Map<UserDto>(await UserRepository.UpdateUser(user));
|
||||||
|
}
|
||||||
|
|
||||||
private UserHash HashPassword(string password)
|
private UserHash HashPassword(string password)
|
||||||
{
|
{
|
||||||
// generate a 128-bit salt using a secure PRNG
|
// generate a 128-bit salt using a secure PRNG
|
||||||
|
|
|
@ -7,9 +7,15 @@ namespace Ombi.Core.Models.UI
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
public string Alias { get; set; }
|
public string Alias { get; set; }
|
||||||
public List<string> Claims { get; set; }
|
public List<ClaimCheckboxes> Claims { get; set; }
|
||||||
public string EmailAddress { get; set; }
|
public string EmailAddress { get; set; }
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
public UserType UserType { get; set; }
|
public UserType UserType { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ClaimCheckboxes
|
||||||
|
{
|
||||||
|
public string Value { get; set; }
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using Ombi.Core.Models.UI;
|
||||||
|
|
||||||
namespace Ombi.Mapping
|
namespace Ombi.Mapping
|
||||||
{
|
{
|
||||||
|
@ -23,4 +25,17 @@ namespace Ombi.Mapping
|
||||||
return default(DateTime);
|
return default(DateTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ClaimsConverter : ITypeConverter<Claim, ClaimCheckboxes>
|
||||||
|
{
|
||||||
|
|
||||||
|
public ClaimCheckboxes Convert(Claim source, ClaimCheckboxes destination, ResolutionContext context)
|
||||||
|
{
|
||||||
|
return new ClaimCheckboxes
|
||||||
|
{
|
||||||
|
Enabled = true,
|
||||||
|
Value = source.Value
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -16,11 +16,13 @@ namespace Ombi.Mapping.Profiles
|
||||||
CreateMap<User, UserDto>().ReverseMap();
|
CreateMap<User, UserDto>().ReverseMap();
|
||||||
|
|
||||||
|
|
||||||
CreateMap<UserDto, UserViewModel>()
|
CreateMap<Claim, ClaimCheckboxes>().ConvertUsing<ClaimsConverter>();
|
||||||
.ForMember(dest => dest.Claims, opts => opts.MapFrom(src => src.Claims.Select(x => x.Value).ToList())); // Map the claims to a List<string>
|
|
||||||
|
|
||||||
CreateMap<string, Claim>()
|
CreateMap<UserDto, UserViewModel>().ForMember(x => x.Password, opt => opt.Ignore());
|
||||||
.ConstructUsing(str => new Claim(ClaimTypes.Role, str)); // This is used for the UserViewModel List<string> claims => UserDto List<claim>
|
|
||||||
|
CreateMap<ClaimCheckboxes, Claim>()
|
||||||
|
.ConstructUsing(checkbox => checkbox.Enabled ? new Claim(ClaimTypes.Role, checkbox.Value) : null);
|
||||||
|
// This is used for the UserViewModel List<string> claims => UserDto List<claim>
|
||||||
CreateMap<UserViewModel, UserDto>();
|
CreateMap<UserViewModel, UserDto>();
|
||||||
|
|
||||||
CreateMap<string, DateTime>().ConvertUsing<StringToDateTimeConverter>();
|
CreateMap<string, DateTime>().ConvertUsing<StringToDateTimeConverter>();
|
||||||
|
|
|
@ -10,5 +10,6 @@ namespace Ombi.Store.Repository
|
||||||
Task<User> GetUser(string username);
|
Task<User> GetUser(string username);
|
||||||
Task<IEnumerable<User>> GetUsers();
|
Task<IEnumerable<User>> GetUsers();
|
||||||
Task DeleteUser(User user);
|
Task DeleteUser(User user);
|
||||||
|
Task<User> UpdateUser(User user);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -64,5 +64,12 @@ namespace Ombi.Store.Repository
|
||||||
Db.Users.Remove(user);
|
Db.Users.Remove(user);
|
||||||
await Db.SaveChangesAsync();
|
await Db.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<User> UpdateUser(User user)
|
||||||
|
{
|
||||||
|
Db.Users.Update(user);
|
||||||
|
await Db.SaveChangesAsync();
|
||||||
|
return user;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -60,7 +60,7 @@ namespace Ombi.Auth
|
||||||
private async Task GenerateToken(HttpContext context)
|
private async Task GenerateToken(HttpContext context)
|
||||||
{
|
{
|
||||||
var request = context.Request;
|
var request = context.Request;
|
||||||
UserAuthModel userInfo; // TODO use a stong type
|
UserAuthModel userInfo;
|
||||||
|
|
||||||
using (var bodyReader = new StreamReader(request.Body))
|
using (var bodyReader = new StreamReader(request.Body))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
|
@ -38,6 +40,7 @@ namespace Ombi.Controllers
|
||||||
/// This should never be called after this.
|
/// This should never be called after this.
|
||||||
/// The reason why we return false if users exists is that this method doesn't have any
|
/// The reason why we return false if users exists is that this method doesn't have any
|
||||||
/// authorization and could be called from anywhere.
|
/// authorization and could be called from anywhere.
|
||||||
|
/// <remarks>We have [AllowAnonymous] since when going through the wizard we do not have a JWT Token yet</remarks>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="user"></param>
|
/// <param name="user"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
@ -66,15 +69,46 @@ namespace Ombi.Controllers
|
||||||
[HttpGet("Users")]
|
[HttpGet("Users")]
|
||||||
public async Task<IEnumerable<UserViewModel>> GetAllUsers()
|
public async Task<IEnumerable<UserViewModel>> GetAllUsers()
|
||||||
{
|
{
|
||||||
return Mapper.Map<IEnumerable<UserViewModel>>(await IdentityManager.GetUsers());
|
var type = typeof(OmbiClaims);
|
||||||
|
FieldInfo[] fieldInfos = type.GetFields(BindingFlags.Public |
|
||||||
|
BindingFlags.Static | BindingFlags.FlattenHierarchy);
|
||||||
|
|
||||||
|
var fields = fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList();
|
||||||
|
var allClaims = fields.Select(x => x.Name).ToList();
|
||||||
|
var users = Mapper.Map<IEnumerable<UserViewModel>>(await IdentityManager.GetUsers()).ToList();
|
||||||
|
|
||||||
|
foreach (var user in users)
|
||||||
|
{
|
||||||
|
var userClaims = user.Claims.Select(x => x.Value);
|
||||||
|
var left = allClaims.Except(userClaims);
|
||||||
|
|
||||||
|
foreach (var c in left)
|
||||||
|
{
|
||||||
|
user.Claims.Add(new ClaimCheckboxes
|
||||||
|
{
|
||||||
|
Enabled = false,
|
||||||
|
Value = c
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<UserViewModel> CreateUser([FromBody] UserViewModel user)
|
public async Task<UserViewModel> CreateUser([FromBody] UserViewModel user)
|
||||||
{
|
{
|
||||||
|
user.Id = null;
|
||||||
var userResult = await IdentityManager.CreateUser(Mapper.Map<UserDto>(user));
|
var userResult = await IdentityManager.CreateUser(Mapper.Map<UserDto>(user));
|
||||||
return Mapper.Map<UserViewModel>(userResult);
|
return Mapper.Map<UserViewModel>(userResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPut]
|
||||||
|
public async Task<UserViewModel> UpdateUser([FromBody] UserViewModel user)
|
||||||
|
{
|
||||||
|
var userResult = await IdentityManager.UpdateUser(Mapper.Map<UserDto>(user));
|
||||||
|
return Mapper.Map<UserViewModel>(userResult);
|
||||||
|
}
|
||||||
|
|
||||||
[HttpDelete]
|
[HttpDelete]
|
||||||
public async Task<StatusCodeResult> DeleteUser([FromBody] UserViewModel user)
|
public async Task<StatusCodeResult> DeleteUser([FromBody] UserViewModel user)
|
||||||
|
@ -82,6 +116,19 @@ namespace Ombi.Controllers
|
||||||
await IdentityManager.DeleteUser(Mapper.Map<UserDto>(user));
|
await IdentityManager.DeleteUser(Mapper.Map<UserDto>(user));
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("claims")]
|
||||||
|
public IEnumerable<ClaimCheckboxes> GetAllClaims()
|
||||||
|
{
|
||||||
|
var type = typeof(OmbiClaims);
|
||||||
|
FieldInfo[] fieldInfos = type.GetFields(BindingFlags.Public |
|
||||||
|
BindingFlags.Static | BindingFlags.FlattenHierarchy);
|
||||||
|
|
||||||
|
var fields = fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList();
|
||||||
|
var allClaims = fields.Select(x => x.Name).ToList();
|
||||||
|
|
||||||
|
return allClaims.Select(x => new ClaimCheckboxes() {Value = x});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace Ombi
|
||||||
.UseStartup<Startup>()
|
.UseStartup<Startup>()
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
|
||||||
host.Run();
|
host.Run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -719,4 +719,5 @@ body {
|
||||||
|
|
||||||
.ui-growl-item{
|
.ui-growl-item{
|
||||||
margin-top:35px $i;
|
margin-top:35px $i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,10 @@
|
||||||
<li [routerLinkActive]="['active']"><a [routerLink]="['/search']"><i class="fa fa-search"></i> Search</a></li>
|
<li [routerLinkActive]="['active']"><a [routerLink]="['/search']"><i class="fa fa-search"></i> Search</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li [routerLinkActive]="['active']"><a [routerLink]="['/requests']"><i class="fa fa-plus"></i> Requests</a></li>
|
<li [routerLinkActive]="['active']"><a [routerLink]="['/requests']"><i class="fa fa-plus"></i> Requests</a></li>
|
||||||
|
</ul>
|
||||||
|
<ul *ngIf="isAdmin || isPowerUser" class="nav navbar-nav">
|
||||||
|
<li [routerLinkActive]="['active']"><a [routerLink]="['/usermanagement']"><i class="fa fa-user"></i> User Management</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ import { StatusService } from './services/status.service';
|
||||||
import { SettingsModule } from './settings/settings.module';
|
import { SettingsModule } from './settings/settings.module';
|
||||||
import { WizardModule } from './wizard/wizard.module';
|
import { WizardModule } from './wizard/wizard.module';
|
||||||
|
|
||||||
import { ButtonModule } from 'primeng/primeng';
|
import { ButtonModule, DialogModule } from 'primeng/primeng';
|
||||||
import { GrowlModule } from 'primeng/components/growl/growl';
|
import { GrowlModule } from 'primeng/components/growl/growl';
|
||||||
import { DataTableModule, SharedModule } from 'primeng/primeng';
|
import { DataTableModule, SharedModule } from 'primeng/primeng';
|
||||||
|
|
||||||
|
@ -64,7 +64,8 @@ const routes: Routes = [
|
||||||
SharedModule,
|
SharedModule,
|
||||||
InfiniteScrollModule,
|
InfiniteScrollModule,
|
||||||
AuthModule,
|
AuthModule,
|
||||||
WizardModule
|
WizardModule,
|
||||||
|
DialogModule
|
||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
|
|
|
@ -6,7 +6,7 @@ enum envs {
|
||||||
live = 2
|
live = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
var envVar = "#{Environment}";
|
var envVar = '0';
|
||||||
var env = envs.local;
|
var env = envs.local;
|
||||||
if (envs[envVar]) {
|
if (envs[envVar]) {
|
||||||
env = envs[envVar];
|
env = envs[envVar];
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
id: string,
|
id: string,
|
||||||
username: string,
|
username: string,
|
||||||
alias: string,
|
alias: string,
|
||||||
claims: string[],
|
claims: ICheckbox[],
|
||||||
emailAddress: string,
|
emailAddress: string,
|
||||||
password: string,
|
password: string,
|
||||||
userType : UserType,
|
userType : UserType,
|
||||||
|
@ -14,3 +14,9 @@ export enum UserType {
|
||||||
PlexUser = 2,
|
PlexUser = 2,
|
||||||
EmbyUser = 3
|
EmbyUser = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface ICheckbox {
|
||||||
|
value: string,
|
||||||
|
enabled:boolean,
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ import { Http } from '@angular/http';
|
||||||
import { Observable } from 'rxjs/Rx';
|
import { Observable } from 'rxjs/Rx';
|
||||||
|
|
||||||
import { ServiceAuthHelpers } from './service.helpers';
|
import { ServiceAuthHelpers } from './service.helpers';
|
||||||
import { IUser } from '../interfaces/IUser';
|
import { IUser, ICheckbox } from '../interfaces/IUser';
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -24,6 +24,18 @@ export class IdentityService extends ServiceAuthHelpers {
|
||||||
return this.http.get(`${this.url}/Users`).map(this.extractData);
|
return this.http.get(`${this.url}/Users`).map(this.extractData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getAllAvailableClaims(): Observable<ICheckbox[]> {
|
||||||
|
return this.http.get(`${this.url}/Claims`).map(this.extractData);
|
||||||
|
}
|
||||||
|
|
||||||
|
createUser(user: IUser): Observable<IUser> {
|
||||||
|
return this.http.post(this.url, JSON.stringify(user), { headers: this.headers }).map(this.extractData);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateUser(user: IUser): Observable<IUser> {
|
||||||
|
return this.http.put(this.url, JSON.stringify(user), { headers: this.headers }).map(this.extractData);
|
||||||
|
}
|
||||||
|
|
||||||
hasRole(role: string): boolean {
|
hasRole(role: string): boolean {
|
||||||
var roles = localStorage.getItem("roles") as string[];
|
var roles = localStorage.getItem("roles") as string[];
|
||||||
if (roles) {
|
if (roles) {
|
||||||
|
|
|
@ -15,60 +15,170 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-success-outline" (click)="showCreateDialogue=true">Add User</button>
|
||||||
<!-- Table -->
|
<!-- Table -->
|
||||||
<table class="table table-striped table-hover table-responsive table-condensed">
|
<table class="table table-striped table-hover table-responsive table-condensed">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
<a (click)="changeSort('username')">
|
<a>
|
||||||
Username
|
Username
|
||||||
<!--<span ng-show="sortType == 'username' && !sortReverse" class="fa fa-caret-down"></span>
|
<!--<span ng-show="sortType == 'username' && !sortReverse" class="fa fa-caret-down"></span>
|
||||||
<span ng-show="sortType == 'username' && sortReverse" class="fa fa-caret-up"></span>-->
|
<span ng-show="sortType == 'username' && sortReverse" class="fa fa-caret-up"></span>-->
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a>
|
<a>
|
||||||
Alias
|
Alias
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a>
|
<a>
|
||||||
Email
|
Email
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
Roles
|
Roles
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a>
|
<a>
|
||||||
User Type
|
User Type
|
||||||
</a>
|
</a>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr *ngFor="let u of users">
|
<tr *ngFor="let u of users">
|
||||||
<td>
|
<td>
|
||||||
{{u.username}}
|
{{u.username}}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{u.alias}}
|
{{u.alias}}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{u.emailAddress}}
|
{{u.emailAddress}}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span *ngFor="let claim of u.claims">{{claim}}</span>
|
<div *ngFor="let claim of u.claims"><span *ngIf="claim.enabled">{{claim.value}}</span></div>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td ng-hide="hideColumns">
|
<td ng-hide="hideColumns">
|
||||||
<span ng-if="u.userType === 1">Local User</span>
|
<span *ngIf="u.userType === 1">Local User</span>
|
||||||
<span ng-if="u.userType === 2">Plex User</span>
|
<span *ngIf="u.userType === 2">Plex User</span>
|
||||||
<span ng-if="u.userType === 3">Emby User</span>
|
<span *ngIf="u.userType === 3">Emby User</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a (click)="edit(u)" class="btn btn-sm btn-info-outline">Details/Edit</a>
|
<a (click)="edit(u)" class="btn btn-sm btn-info-outline">Details/Edit</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="modal fade in" *ngIf="showEditDialog" style="display: block;">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" (click)="showEditDialog=false">×</button>
|
||||||
|
<h4 class="modal-title">Editing User {{selectedUser?.username}}</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="username" class="control-label">Username</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" [(ngModel)]="selectedUser.username" [readonly]="true" class="form-control form-control-custom " id="username" name="username" value="{{selectedUser?.username}}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="alias" class="control-label">Alias</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" [(ngModel)]="selectedUser.alias" class="form-control form-control-custom " id="alias" name="alias" value="{{selectedUser?.alias}}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="alias" class="control-label">Email Address</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" [(ngModel)]="selectedUser.emailAddress" class="form-control form-control-custom " id="emailAddress" name="emailAddress" value="{{selectedUser?.emailAddress}}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngFor="let c of selectedUser.claims">
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label for="claim{{c.value}}">{{c.value}}</label>
|
||||||
|
<input type="checkbox" [(ngModel)]="c.enabled" [value]="c.value" [checked]="c.value" id="claim{{c.value}}" name="claim{{c.value}}" ng-checked="c.enabled">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-danger-outline" (click)="showEditDialog=false">Close</button>
|
||||||
|
<button type="button" class="btn btn-primary-outline" (click)="updateUser()">Save changes</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="lightbox">
|
||||||
|
<div class="modal fade in " *ngIf="showCreateDialogue" style="display: block;">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" (click)="showCreateDialogue=false">×</button>
|
||||||
|
<h4 class="modal-title">Create User</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="username" class="control-label">Username</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" [(ngModel)]="createdUser.username" class="form-control form-control-custom " id="username" name="username" value="{{createdUser?.username}}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="alias" class="control-label">Alias</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" [(ngModel)]="createdUser.alias" class="form-control form-control-custom " id="alias" name="alias" value="{{createdUser?.alias}}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="emailAddress" class="control-label">Email Address</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" [(ngModel)]="createdUser.emailAddress" class="form-control form-control-custom " id="emailAddress" name="emailAddress" value="{{createdUser?.emailAddress}}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="password" class="control-label">Password</label>
|
||||||
|
<div>
|
||||||
|
<input type="password" [(ngModel)]="createdUser.password" class="form-control form-control-custom " id="password" name="password" value="{{createdUser?.password}}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div *ngFor="let c of availableClaims">
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
<label for="create{{c.value}}">{{c.value}}</label>
|
||||||
|
<input type="checkbox" [(ngModel)]="c.enabled" [value]="c.value" [checked]="c.value" id="create{{c.value}}" name="create{{c.value}}" ng-checked="c.enabled">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-danger-outline" (click)="showCreateDialogue=false">Close</button>
|
||||||
|
<button type="button" class="btn btn-primary-outline" (click)="create()">Add User</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,6 +1,6 @@
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
import { IUser } from '../interfaces/IUser';
|
import { IUser, ICheckbox } from '../interfaces/IUser';
|
||||||
import { IdentityService } from '../services/identity.service';
|
import { IdentityService } from '../services/identity.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -16,17 +16,57 @@ export class UserManagementComponent implements OnInit {
|
||||||
this.identityService.getUsers().subscribe(x => {
|
this.identityService.getUsers().subscribe(x => {
|
||||||
this.users = x;
|
this.users = x;
|
||||||
});
|
});
|
||||||
|
this.identityService.getAllAvailableClaims().subscribe(x => this.availableClaims = x);
|
||||||
|
|
||||||
|
this.resetCreatedUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
users: IUser[];
|
users: IUser[];
|
||||||
selectedUser: IUser;
|
selectedUser: IUser;
|
||||||
|
createdUser: IUser;
|
||||||
|
|
||||||
|
availableClaims : ICheckbox[];
|
||||||
|
|
||||||
|
showEditDialog = false;
|
||||||
|
showCreateDialogue = false;
|
||||||
|
|
||||||
edit(user: IUser) {
|
edit(user: IUser) {
|
||||||
this.selectedUser = user;
|
this.selectedUser = user;
|
||||||
|
this.showEditDialog = true;
|
||||||
}
|
}
|
||||||
changeSort(username: string) {
|
|
||||||
//??????
|
updateUser() {
|
||||||
|
this.showEditDialog = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
create() {
|
||||||
|
this.createdUser.claims = this.availableClaims;
|
||||||
|
this.identityService.createUser(this.createdUser).subscribe(x => {
|
||||||
|
this.users.push(x); // Add the new user
|
||||||
|
|
||||||
|
this.showCreateDialogue = false;
|
||||||
|
this.resetCreatedUser();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private resetClaims() {
|
||||||
|
//this.availableClaims.forEach(x => {
|
||||||
|
// x.enabled = false;
|
||||||
|
//});
|
||||||
|
}
|
||||||
|
|
||||||
|
private resetCreatedUser() {
|
||||||
|
this.createdUser = {
|
||||||
|
id: "-1",
|
||||||
|
alias: "",
|
||||||
|
claims: [],
|
||||||
|
emailAddress: "",
|
||||||
|
password: "",
|
||||||
|
userType: 1,
|
||||||
|
username: ""
|
||||||
|
}
|
||||||
|
this.resetClaims();
|
||||||
}
|
}
|
||||||
|
|
||||||
//private removeRequestFromUi(key : IRequestModel) {
|
//private removeRequestFromUi(key : IRequestModel) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue