mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-14 01:02:57 -07:00
parent
b04344dd17
commit
51fbd56c44
26 changed files with 631 additions and 204 deletions
|
@ -22,7 +22,7 @@ namespace Ombi.Core.Tests.Rule.Request
|
|||
[Fact]
|
||||
public async Task Should_ReturnSuccess_WhenAdminAndRequestMovie()
|
||||
{
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true);
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiRoles.Admin)).Returns(true);
|
||||
var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie };
|
||||
var result = await Rule.Execute(request);
|
||||
|
||||
|
@ -33,7 +33,7 @@ namespace Ombi.Core.Tests.Rule.Request
|
|||
[Fact]
|
||||
public async Task Should_ReturnSuccess_WhenAdminAndRequestTV()
|
||||
{
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true);
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiRoles.Admin)).Returns(true);
|
||||
var request = new BaseRequest() { RequestType = Store.Entities.RequestType.TvShow };
|
||||
var result = await Rule.Execute(request);
|
||||
|
||||
|
@ -44,7 +44,7 @@ namespace Ombi.Core.Tests.Rule.Request
|
|||
[Fact]
|
||||
public async Task Should_ReturnSuccess_WhenAutoApproveMovieAndRequestMovie()
|
||||
{
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.AutoApproveMovie)).Returns(true);
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiRoles.AutoApproveMovie)).Returns(true);
|
||||
var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie };
|
||||
var result = await Rule.Execute(request);
|
||||
|
||||
|
@ -55,7 +55,7 @@ namespace Ombi.Core.Tests.Rule.Request
|
|||
[Fact]
|
||||
public async Task Should_ReturnSuccess_WhenAutoApproveTVAndRequestTV()
|
||||
{
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.AutoApproveTv)).Returns(true);
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiRoles.AutoApproveTv)).Returns(true);
|
||||
var request = new BaseRequest() { RequestType = Store.Entities.RequestType.TvShow };
|
||||
var result = await Rule.Execute(request);
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace Ombi.Core.Tests.Rule
|
|||
[Fact]
|
||||
public async Task Should_ReturnSuccess_WhenRequestingMovieWithMovieRole()
|
||||
{
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestMovie)).Returns(true);
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiRoles.RequestMovie)).Returns(true);
|
||||
var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie };
|
||||
var result = await Rule.Execute(request);
|
||||
|
||||
|
@ -33,7 +33,7 @@ namespace Ombi.Core.Tests.Rule
|
|||
[Fact]
|
||||
public async Task Should_ReturnFail_WhenRequestingMovieWithoutMovieRole()
|
||||
{
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestMovie)).Returns(false);
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiRoles.RequestMovie)).Returns(false);
|
||||
var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie };
|
||||
var result = await Rule.Execute(request);
|
||||
|
||||
|
@ -44,7 +44,7 @@ namespace Ombi.Core.Tests.Rule
|
|||
[Fact]
|
||||
public async Task Should_ReturnSuccess_WhenRequestingMovieWithAdminRole()
|
||||
{
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true);
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiRoles.Admin)).Returns(true);
|
||||
var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie };
|
||||
var result = await Rule.Execute(request);
|
||||
|
||||
|
@ -54,7 +54,7 @@ namespace Ombi.Core.Tests.Rule
|
|||
[Fact]
|
||||
public async Task Should_ReturnSuccess_WhenRequestingTVWithAdminRole()
|
||||
{
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true);
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiRoles.Admin)).Returns(true);
|
||||
var request = new BaseRequest() { RequestType = Store.Entities.RequestType.TvShow };
|
||||
var result = await Rule.Execute(request);
|
||||
|
||||
|
@ -64,7 +64,7 @@ namespace Ombi.Core.Tests.Rule
|
|||
[Fact]
|
||||
public async Task Should_ReturnSuccess_WhenRequestingTVWithTVRole()
|
||||
{
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestTv)).Returns(true);
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiRoles.RequestTv)).Returns(true);
|
||||
var request = new BaseRequest() { RequestType = Store.Entities.RequestType.TvShow };
|
||||
var result = await Rule.Execute(request);
|
||||
|
||||
|
@ -74,7 +74,7 @@ namespace Ombi.Core.Tests.Rule
|
|||
[Fact]
|
||||
public async Task Should_ReturnFail_WhenRequestingTVWithoutTVRole()
|
||||
{
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestTv)).Returns(false);
|
||||
PrincipalMock.Setup(x => x.IsInRole(OmbiRoles.RequestTv)).Returns(false);
|
||||
var request = new BaseRequest() { RequestType = Store.Entities.RequestType.TvShow };
|
||||
var result = await Rule.Execute(request);
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace Ombi.Core.Claims
|
||||
{
|
||||
public static class OmbiClaims
|
||||
public static class OmbiRoles
|
||||
{
|
||||
public const string Admin = nameof(Admin);
|
||||
public const string AutoApproveMovie = nameof(AutoApproveMovie);
|
62
src/Ombi.Core/Helpers/EmailValidator.cs
Normal file
62
src/Ombi.Core/Helpers/EmailValidator.cs
Normal file
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Ombi.Core.Helpers
|
||||
{
|
||||
public static class EmailValidator
|
||||
{
|
||||
static bool _invalid;
|
||||
|
||||
public static bool IsValidEmail(string strIn)
|
||||
{
|
||||
_invalid = false;
|
||||
if (string.IsNullOrEmpty(strIn))
|
||||
return false;
|
||||
|
||||
// Use IdnMapping class to convert Unicode domain names.
|
||||
try
|
||||
{
|
||||
strIn = Regex.Replace(strIn, "(@)(.+)$", DomainMapper,
|
||||
RegexOptions.None, TimeSpan.FromMilliseconds(200));
|
||||
}
|
||||
catch (RegexMatchTimeoutException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_invalid)
|
||||
return false;
|
||||
|
||||
// Return true if strIn is in valid e-mail format.
|
||||
try
|
||||
{
|
||||
return Regex.IsMatch(strIn,
|
||||
@"^(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))" +
|
||||
@"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$",
|
||||
RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));
|
||||
}
|
||||
catch (RegexMatchTimeoutException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static string DomainMapper(Match match)
|
||||
{
|
||||
// IdnMapping class with default property values.
|
||||
IdnMapping idn = new IdnMapping();
|
||||
|
||||
string domainName = match.Groups[2].Value;
|
||||
try
|
||||
{
|
||||
domainName = idn.GetAscii(domainName);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
_invalid = true;
|
||||
}
|
||||
return match.Groups[1].Value + domainName;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,15 +19,15 @@ namespace Ombi.Core.Rule.Rules.Request
|
|||
|
||||
public Task<RuleResult> Execute(BaseRequest obj)
|
||||
{
|
||||
if (User.IsInRole(OmbiClaims.Admin))
|
||||
if (User.IsInRole(OmbiRoles.Admin))
|
||||
{
|
||||
obj.Approved = true;
|
||||
return Task.FromResult(Success());
|
||||
}
|
||||
|
||||
if (obj.RequestType == RequestType.Movie && User.IsInRole(OmbiClaims.AutoApproveMovie))
|
||||
if (obj.RequestType == RequestType.Movie && User.IsInRole(OmbiRoles.AutoApproveMovie))
|
||||
obj.Approved = true;
|
||||
if (obj.RequestType == RequestType.TvShow && User.IsInRole(OmbiClaims.AutoApproveTv))
|
||||
if (obj.RequestType == RequestType.TvShow && User.IsInRole(OmbiRoles.AutoApproveTv))
|
||||
obj.Approved = true;
|
||||
return Task.FromResult(Success()); // We don't really care, we just don't set the obj to approve
|
||||
}
|
||||
|
|
|
@ -18,17 +18,17 @@ namespace Ombi.Core.Rule.Rules
|
|||
|
||||
public Task<RuleResult> Execute(BaseRequest obj)
|
||||
{
|
||||
if (User.IsInRole(OmbiClaims.Admin))
|
||||
if (User.IsInRole(OmbiRoles.Admin))
|
||||
return Task.FromResult(Success());
|
||||
|
||||
if (obj.RequestType == RequestType.Movie)
|
||||
{
|
||||
if (User.IsInRole(OmbiClaims.RequestMovie))
|
||||
if (User.IsInRole(OmbiRoles.RequestMovie))
|
||||
return Task.FromResult(Success());
|
||||
return Task.FromResult(Fail("You do not have permissions to Request a Movie"));
|
||||
}
|
||||
|
||||
if (User.IsInRole(OmbiClaims.RequestTv))
|
||||
if (User.IsInRole(OmbiRoles.RequestTv))
|
||||
return Task.FromResult(Success());
|
||||
return Task.FromResult(Fail("You do not have permissions to Request a Movie"));
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace Ombi.Core.Rule.Rules.Specific
|
|||
var req = (BaseRequest)obj;
|
||||
var sendNotification = !req.Approved; /*|| !prSettings.IgnoreNotifyForAutoApprovedRequests;*/
|
||||
|
||||
if (User.IsInRole(OmbiClaims.Admin))
|
||||
if (User.IsInRole(OmbiRoles.Admin))
|
||||
sendNotification = false; // Don't bother sending a notification if the user is an admin
|
||||
return Task.FromResult(new RuleResult
|
||||
{
|
||||
|
|
|
@ -37,6 +37,10 @@ namespace Ombi.Store.Context
|
|||
public DbSet<TvIssues> TvIssues { get; set; }
|
||||
public DbSet<EmailTokens> EmailTokens { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
base.OnModelCreating(builder);
|
||||
}
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
|
|
|
@ -9,8 +9,8 @@ namespace Ombi.Attributes
|
|||
{
|
||||
var roles = new []
|
||||
{
|
||||
OmbiClaims.Admin,
|
||||
OmbiClaims.PowerUser
|
||||
OmbiRoles.Admin,
|
||||
OmbiRoles.PowerUser
|
||||
};
|
||||
Roles = string.Join(",",roles);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<li [routerLinkActive]="['active']" class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-user"></i> Welcome {{user.name}} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li [routerLinkActive]="['active']"><a [routerLink]="['/user/changepassword']"><i class="fa fa-key"></i> Change Password</a></li>
|
||||
<li [routerLinkActive]="['active']"><a [routerLink]="['/usermanagement/updatedetails']"><i class="fa fa-key"></i> Update Details</a></li>
|
||||
<li [routerLinkActive]="['active']"><a (click)="logOut()"><i class="fa fa-sign-out"></i> Logout</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
|
|
@ -44,8 +44,8 @@ export class AuthService extends ServiceHelpers {
|
|||
throw "Invalid token";
|
||||
}
|
||||
var json = this.jwtHelper.decodeToken(token);
|
||||
var roles = json["http://schemas.microsoft.com/ws/2008/06/identity/claims/role"]
|
||||
var name = json["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"];
|
||||
var roles = json["role"];
|
||||
var name = json["name"];
|
||||
|
||||
|
||||
var u = { name: name, roles: [] as string[] };
|
||||
|
@ -64,7 +64,6 @@ export class AuthService extends ServiceHelpers {
|
|||
|
||||
logout() {
|
||||
localStorage.removeItem('id_token');
|
||||
localStorage.removeItem('currentUser');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,3 +20,13 @@ export interface ICheckbox {
|
|||
enabled: boolean,
|
||||
}
|
||||
|
||||
export interface IIdentityResult {
|
||||
errors: string[],
|
||||
successful: boolean,
|
||||
}
|
||||
|
||||
export interface IUpdateLocalUser extends IUser {
|
||||
currentPassword: string,
|
||||
confirmNewPassword: string
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Http } from '@angular/http';
|
|||
import { Observable } from 'rxjs/Rx';
|
||||
|
||||
import { ServiceAuthHelpers } from './service.helpers';
|
||||
import { IUser, ICheckbox } from '../interfaces/IUser';
|
||||
import { IUser, IUpdateLocalUser, ICheckbox, IIdentityResult } from '../interfaces/IUser';
|
||||
|
||||
|
||||
@Injectable()
|
||||
|
@ -20,7 +20,7 @@ export class IdentityService extends ServiceAuthHelpers {
|
|||
return this.http.get(this.url).map(this.extractData);
|
||||
}
|
||||
|
||||
getUserById(id: number): Observable<IUser> {
|
||||
getUserById(id: string): Observable<IUser> {
|
||||
return this.http.get(`${this.url}User/${id}`).map(this.extractData);
|
||||
}
|
||||
|
||||
|
@ -32,13 +32,20 @@ export class IdentityService extends ServiceAuthHelpers {
|
|||
return this.http.get(`${this.url}Claims`).map(this.extractData);
|
||||
}
|
||||
|
||||
createUser(user: IUser): Observable<IUser> {
|
||||
createUser(user: IUser): Observable<IIdentityResult> {
|
||||
return this.http.post(this.url, JSON.stringify(user), { headers: this.headers }).map(this.extractData);
|
||||
}
|
||||
|
||||
updateUser(user: IUser): Observable<IUser> {
|
||||
updateUser(user: IUser): Observable<IIdentityResult> {
|
||||
return this.http.put(this.url, JSON.stringify(user), { headers: this.headers }).map(this.extractData);
|
||||
}
|
||||
updateLocalUser(user: IUpdateLocalUser): Observable<IIdentityResult> {
|
||||
return this.http.put(this.url + 'local', JSON.stringify(user), { headers: this.headers }).map(this.extractData);
|
||||
}
|
||||
|
||||
deleteUser(user: IUser): Observable<IIdentityResult> {
|
||||
return this.http.delete(`${this.url}/${user.id}`, { headers: this.headers }).map(this.extractData);
|
||||
}
|
||||
|
||||
hasRole(role: string): boolean {
|
||||
var roles = localStorage.getItem("roles") as string[] | null;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<div *ngIf="emailForm.get('host').hasError('required')">Host is required</div>
|
||||
<div *ngIf="emailForm.get('port').hasError('required')">The Port is required</div>
|
||||
<div *ngIf="emailForm.get('sender').hasError('required')">The Email Sender is required</div>
|
||||
<div *ngIf="emailForm.get('sender').hasError('email')">The Email Sender needs to be a valid email address</div>
|
||||
<div *ngIf="emailForm.get('sender').hasError('incorrectMailFormat')">The Email Sender needs to be a valid email address</div>
|
||||
<div *ngIf="emailForm.get('adminEmail').hasError('required')">The Email Sender is required</div>
|
||||
<div *ngIf="emailForm.get('adminEmail').hasError('email')">The Admin Email needs to be a valid email address</div>
|
||||
<div *ngIf="emailForm.get('username').hasError('required')">The Username is required</div>
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<div *ngIf="form">
|
||||
|
||||
<h3>Hello {{form.value.username}}!</h3>
|
||||
<div class="col-md-6">
|
||||
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
|
||||
<div class="modal-body" style="margin-top:45px;">
|
||||
<div class="form-group">
|
||||
<label for="emailAddress" class="control-label">Email Address</label>
|
||||
<div>
|
||||
<input type="text" formControlName="emailAddress" class="form-control form-control-custom " id="emailAddress" name="emailAddress">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="currentPassword" class="control-label">Current Password</label>
|
||||
<div>
|
||||
<input type="password" formControlName="currentPassword" class="form-control form-control-custom " id="currentPassword" name="currentPassword">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password" class="control-label">New Password</label>
|
||||
<div>
|
||||
<input type="password" formControlName="password" class="form-control form-control-custom " id="password" name="password">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="confirmPassword" class="control-label">Confirm New Password</label>
|
||||
<div>
|
||||
<input type="password" formControlName="confirmNewPassword" class="form-control form-control-custom " id="confirmPassword"
|
||||
name="confirmPassword">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button type="submit" class="btn btn-primary-outline" [disabled]="form.invalid">Save</button>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div *ngIf="form.invalid && form.dirty" class="alert alert-danger">
|
||||
<div *ngIf="form.get('emailAddress').hasError('email')">Email address format is incorrect</div>
|
||||
<div *ngIf="form.get('password').hasError('required')">The Password is required</div>
|
||||
<div *ngIf="form.get('confirmNewPassword').hasError('required')">The Confirm New Password is required</div>
|
||||
<div *ngIf="form.get('currentPassword').hasError('required')">Your current passowrd is required</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,61 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormGroup, Validators, FormBuilder } from '@angular/forms';
|
||||
|
||||
import { IUpdateLocalUser } from '../interfaces/IUser';
|
||||
import { IdentityService } from '../services/identity.service';
|
||||
import { NotificationService } from '../services/notification.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: './updatedetails.component.html'
|
||||
})
|
||||
export class UpdateDetailsComponent implements OnInit {
|
||||
constructor(private identityService: IdentityService,
|
||||
private notificationService: NotificationService,
|
||||
private fb: FormBuilder) { }
|
||||
|
||||
form: FormGroup;
|
||||
|
||||
ngOnInit(): void {
|
||||
this.identityService.getUser().subscribe(x => {
|
||||
var localUser = x as IUpdateLocalUser;
|
||||
this.form = this.fb.group({
|
||||
id:[localUser.id],
|
||||
username: [localUser.username],
|
||||
emailAddress: [localUser.emailAddress, [Validators.email]],
|
||||
confirmNewPassword: [localUser.confirmNewPassword],
|
||||
currentPassword: [localUser.currentPassword, [Validators.required]],
|
||||
password: [localUser.password],
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
onSubmit(form : FormGroup) {
|
||||
if (form.invalid) {
|
||||
this.notificationService.error("Validation", "Please check your entered values");
|
||||
return
|
||||
}
|
||||
|
||||
if (form.controls["password"].dirty) {
|
||||
if (form.value.password !== form.value.confirmNewPassword) {
|
||||
this.notificationService.error("Error", "Passwords do not match");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
this.identityService.updateLocalUser(this.form.value).subscribe(x => {
|
||||
if (x.successful) {
|
||||
this.notificationService.success("Updated", `All of your details have now been updated`)
|
||||
} else {
|
||||
x.errors.forEach((val) => {
|
||||
this.notificationService.error("Error", val);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -18,11 +18,25 @@
|
|||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="alias" class="control-label">Email Address</label>
|
||||
<label for="emailAddress" class="control-label">Email Address</label>
|
||||
<div>
|
||||
<input type="text" [(ngModel)]="user.emailAddress" class="form-control form-control-custom " id="emailAddress" name="emailAddress" value="{{user?.emailAddress}}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="password" class="control-label">Password</label>
|
||||
<div>
|
||||
<input type="password" [(ngModel)]="user.password" class="form-control form-control-custom " id="password" name="password">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="confirmPass" class="control-label">Confirm Password</label>
|
||||
<div>
|
||||
<input type="password" [(ngModel)]="confirmPass" class="form-control form-control-custom " id="confirmPass" name="confirmPass">
|
||||
</div>
|
||||
</div>
|
||||
<div *ngFor="let c of availableClaims">
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
|
@ -31,12 +45,9 @@
|
|||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" class="btn btn-danger-outline" (click)="update()">Create</button>
|
||||
<button type="button" class="btn btn-danger-outline" (click)="create()">Create</button>
|
||||
|
||||
</div>
|
|
@ -16,6 +16,7 @@ export class UserManagementAddComponent implements OnInit {
|
|||
|
||||
user: IUser;
|
||||
availableClaims: ICheckbox[];
|
||||
confirmPass: "";
|
||||
|
||||
ngOnInit(): void {
|
||||
this.identityService.getAllAvailableClaims().subscribe(x => this.availableClaims = x);
|
||||
|
@ -30,11 +31,35 @@ export class UserManagementAddComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
update(): void {
|
||||
create(): void {
|
||||
this.user.claims = this.availableClaims;
|
||||
|
||||
if (this.user.password) {
|
||||
if (this.user.password !== this.confirmPass) {
|
||||
this.notificationSerivce.error("Error", "Passwords do not match");
|
||||
return;
|
||||
}
|
||||
}
|
||||
var hasClaims = this.availableClaims.some((item) => {
|
||||
if (item.enabled) { return true; }
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!hasClaims) {
|
||||
this.notificationSerivce.error("Error", "Please assign a role");
|
||||
return;
|
||||
}
|
||||
|
||||
this.identityService.createUser(this.user).subscribe(x => {
|
||||
if (x.successful) {
|
||||
this.notificationSerivce.success("Updated", `The user ${this.user.username} has been created successfully`)
|
||||
this.router.navigate(['usermanagement']);
|
||||
} else {
|
||||
x.errors.forEach((val) => {
|
||||
this.notificationSerivce.error("Error", val);
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" class="btn btn-danger-outline" (click)="update()">Update</button>
|
||||
<button type="button" class="btn btn-primary-outline" (click)="update()">Update</button>
|
||||
<button type="button" class="btn btn-danger-outline" (click)="delete()">Delete</button>
|
||||
|
||||
</div>
|
||||
</div>
|
|
@ -1,4 +1,5 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { IUser } from '../interfaces/IUser';
|
||||
import { IdentityService } from '../services/identity.service';
|
||||
|
@ -11,10 +12,11 @@ import { ActivatedRoute } from '@angular/router';
|
|||
export class UserManagementEditComponent {
|
||||
constructor(private identityService: IdentityService,
|
||||
private route: ActivatedRoute,
|
||||
private notificationSerivce: NotificationService) {
|
||||
private notificationSerivce: NotificationService,
|
||||
private router: Router) {
|
||||
this.route.params
|
||||
.subscribe(params => {
|
||||
this.userId = +params['id']; // (+) converts string 'id' to a number
|
||||
this.userId = params['id'];
|
||||
|
||||
this.identityService.getUserById(this.userId).subscribe(x => {
|
||||
this.user = x;
|
||||
|
@ -23,12 +25,43 @@ export class UserManagementEditComponent {
|
|||
}
|
||||
|
||||
user: IUser;
|
||||
userId: number;
|
||||
userId: string;
|
||||
|
||||
delete(): void {
|
||||
this.identityService.deleteUser(this.user).subscribe(x => {
|
||||
if (x.successful) {
|
||||
this.notificationSerivce.success("Deleted", `The user ${this.user.username} was deleted`)
|
||||
this.router.navigate(['usermanagement']);
|
||||
} else {
|
||||
x.errors.forEach((val) => {
|
||||
this.notificationSerivce.error("Error", val);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
update(): void {
|
||||
this.identityService.updateUser(this.user).subscribe(x => {
|
||||
var hasClaims = this.user.claims.some((item) => {
|
||||
if (item.enabled) { return true; }
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
if (!hasClaims) {
|
||||
this.notificationSerivce.error("Error", "Please assign a role");
|
||||
return;
|
||||
}
|
||||
|
||||
this.identityService.updateUser(this.user).subscribe(x => {
|
||||
if (x.successful) {
|
||||
this.notificationSerivce.success("Updated", `The user ${this.user.username} has been updated successfully`)
|
||||
this.router.navigate(['usermanagement']);
|
||||
} else {
|
||||
x.errors.forEach((val) => {
|
||||
this.notificationSerivce.error("Error", val);
|
||||
});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { IUser, ICheckbox } from '../interfaces/IUser';
|
||||
import { IUser } from '../interfaces/IUser';
|
||||
import { IdentityService } from '../services/identity.service';
|
||||
|
||||
@Component({
|
||||
|
@ -15,65 +15,10 @@ export class UserManagementComponent implements OnInit {
|
|||
this.identityService.getUsers().subscribe(x => {
|
||||
this.users = x;
|
||||
});
|
||||
this.identityService.getAllAvailableClaims().subscribe(x => this.availableClaims = x);
|
||||
|
||||
this.resetCreatedUser();
|
||||
}
|
||||
|
||||
users: IUser[];
|
||||
selectedUser: IUser;
|
||||
createdUser: IUser;
|
||||
|
||||
availableClaims : ICheckbox[];
|
||||
|
||||
showEditDialog = false;
|
||||
showCreateDialogue = false;
|
||||
|
||||
edit(user: IUser) {
|
||||
this.selectedUser = user;
|
||||
this.showEditDialog = true;
|
||||
}
|
||||
|
||||
updateUser() {
|
||||
this.showEditDialog = false;
|
||||
this.identityService.updateUser(this.selectedUser).subscribe(x => this.selectedUser = x);
|
||||
}
|
||||
|
||||
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) {
|
||||
// var index = this.requests.indexOf(key, 0);
|
||||
// if (index > -1) {
|
||||
// this.requests.splice(index, 1);
|
||||
// }
|
||||
//}
|
||||
}
|
|
@ -1,13 +1,14 @@
|
|||
import { NgModule, } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
import { UserManagementComponent } from './usermanagement.component';
|
||||
import { UserManagementEditComponent } from './usermanagement-edit.component';
|
||||
import { UserManagementAddComponent } from './usermanagement-add.component';
|
||||
import { UpdateDetailsComponent } from './updatedetails.component';
|
||||
|
||||
import { IdentityService } from '../services/identity.service';
|
||||
|
||||
|
@ -17,19 +18,22 @@ const routes: Routes = [
|
|||
{ path: 'usermanagement', component: UserManagementComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'usermanagement/add', component: UserManagementAddComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'usermanagement/edit/:id', component: UserManagementEditComponent, canActivate: [AuthGuard] },
|
||||
{ path: 'usermanagement/updatedetails', component: UpdateDetailsComponent, canActivate: [AuthGuard] },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
RouterModule.forChild(routes),
|
||||
NgbModule.forRoot(),
|
||||
],
|
||||
declarations: [
|
||||
UserManagementComponent,
|
||||
UserManagementAddComponent,
|
||||
UserManagementEditComponent
|
||||
UserManagementEditComponent,
|
||||
UpdateDetailsComponent
|
||||
],
|
||||
exports: [
|
||||
RouterModule
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
using Ombi.Attributes;
|
||||
using Ombi.Core.Claims;
|
||||
using Ombi.Core.Helpers;
|
||||
using Ombi.Core.Models.UI;
|
||||
using Ombi.Models;
|
||||
using Ombi.Models.Identity;
|
||||
using Ombi.Store.Entities;
|
||||
using IdentityResult = Ombi.Models.Identity.IdentityResult;
|
||||
|
||||
namespace Ombi.Controllers
|
||||
{
|
||||
|
@ -34,16 +39,6 @@ namespace Ombi.Controllers
|
|||
private RoleManager<IdentityRole> RoleManager { get; }
|
||||
private IMapper Mapper { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current user.
|
||||
/// </summary>
|
||||
/// <returns>Information about the current user</returns>
|
||||
[HttpGet]
|
||||
public async Task<UserViewModel> GetUser()
|
||||
{
|
||||
return Mapper.Map<UserViewModel>(await UserManager.GetUserAsync(User));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is what the Wizard will call when creating the user for the very first time.
|
||||
/// This should never be called after this.
|
||||
|
@ -68,29 +63,18 @@ namespace Ombi.Controllers
|
|||
var userToCreate = new OmbiUser
|
||||
{
|
||||
UserName = user.Username,
|
||||
|
||||
UserType = UserType.LocalUser
|
||||
};
|
||||
|
||||
var result = await UserManager.CreateAsync(userToCreate, user.Password);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
if (!(await RoleManager.RoleExistsAsync("Admin")))
|
||||
if (!await RoleManager.RoleExistsAsync(OmbiRoles.Admin))
|
||||
{
|
||||
var r = await RoleManager.CreateAsync(new IdentityRole("Admin"));
|
||||
await RoleManager.CreateAsync(new IdentityRole(OmbiRoles.Admin));
|
||||
}
|
||||
var re = await UserManager.AddToRoleAsync(userToCreate, "Admin");
|
||||
|
||||
var v = User.IsInRole("Admin");
|
||||
|
||||
|
||||
await UserManager.AddToRoleAsync(userToCreate, OmbiRoles.Admin);
|
||||
}
|
||||
//await UserManager.CreateUser(new UserDto
|
||||
//{
|
||||
// Username = user.Username,
|
||||
// UserType = UserType.LocalUser,
|
||||
// Claims = new List<Claim>() { new Claim(ClaimTypes.Role, OmbiClaims.Admin) },
|
||||
// Password = user.Password,
|
||||
//});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -102,30 +86,30 @@ namespace Ombi.Controllers
|
|||
[HttpGet("Users")]
|
||||
public async Task<IEnumerable<UserViewModel>> GetAllUsers()
|
||||
{
|
||||
var type = typeof(OmbiClaims);
|
||||
FieldInfo[] fieldInfos = type.GetFields(BindingFlags.Public |
|
||||
BindingFlags.Static | BindingFlags.FlattenHierarchy);
|
||||
var users = await UserManager.Users
|
||||
.ToListAsync();
|
||||
|
||||
var fields = fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList();
|
||||
var allClaims = fields.Select(x => x.Name).ToList();
|
||||
var users = Mapper.Map<IEnumerable<UserViewModel>>(UserManager.Users).ToList();
|
||||
var model = new List<UserViewModel>();
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
model.Add(await GetUserWithRoles(user));
|
||||
}
|
||||
|
||||
return users;
|
||||
return model;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current logged in user.
|
||||
/// </summary>
|
||||
/// <returns>Information about all users</returns>
|
||||
[HttpGet]
|
||||
[Authorize]
|
||||
public async Task<UserViewModel> GetCurrentUser()
|
||||
{
|
||||
var user = await UserManager.GetUserAsync(User);
|
||||
|
||||
return await GetUserWithRoles(user);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -133,31 +117,48 @@ namespace Ombi.Controllers
|
|||
/// </summary>
|
||||
/// <returns>Information about the user</returns>
|
||||
[HttpGet("User/{id}")]
|
||||
public async Task<UserViewModel> GetUser(int id)
|
||||
public async Task<UserViewModel> GetUser(string id)
|
||||
{
|
||||
var type = typeof(OmbiClaims);
|
||||
FieldInfo[] fieldInfos = type.GetFields(BindingFlags.Public |
|
||||
BindingFlags.Static | BindingFlags.FlattenHierarchy);
|
||||
var user = await UserManager.Users.FirstOrDefaultAsync(x => x.Id == id);
|
||||
|
||||
var fields = fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList();
|
||||
var allClaims = fields.Select(x => x.Name).ToList();
|
||||
var user = Mapper.Map<UserViewModel>(await UserManager.Users.FirstOrDefaultAsync(x => x.Id == id.ToString()));
|
||||
return await GetUserWithRoles(user);
|
||||
}
|
||||
|
||||
|
||||
var userClaims = user.Claims.Select(x => x.Value);
|
||||
IEnumerable<string> left = allClaims.Except(userClaims);
|
||||
|
||||
foreach (var c in left)
|
||||
private async Task<UserViewModel> GetUserWithRoles(OmbiUser user)
|
||||
{
|
||||
user.Claims.Add(new ClaimCheckboxes
|
||||
var userRoles = await UserManager.GetRolesAsync(user);
|
||||
var vm = new UserViewModel
|
||||
{
|
||||
Enabled = false,
|
||||
Value = c
|
||||
Alias = user.Alias,
|
||||
Username = user.UserName,
|
||||
Id = user.Id,
|
||||
EmailAddress = user.Email,
|
||||
UserType = (Core.Models.UserType)(int)user.UserType,
|
||||
Claims = new List<ClaimCheckboxes>(),
|
||||
};
|
||||
|
||||
foreach (var role in userRoles)
|
||||
{
|
||||
vm.Claims.Add(new ClaimCheckboxes
|
||||
{
|
||||
Value = role,
|
||||
Enabled = true
|
||||
});
|
||||
}
|
||||
|
||||
// Add the missing claims
|
||||
var allRoles = await RoleManager.Roles.ToListAsync();
|
||||
var missing = allRoles.Select(x => x.Name).Except(userRoles);
|
||||
foreach (var role in missing)
|
||||
{
|
||||
vm.Claims.Add(new ClaimCheckboxes
|
||||
{
|
||||
Value = role,
|
||||
Enabled = false
|
||||
});
|
||||
}
|
||||
|
||||
return user;
|
||||
return vm;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -165,54 +166,250 @@ namespace Ombi.Controllers
|
|||
/// </summary>
|
||||
/// <param name = "user" > The user.</param>
|
||||
/// <returns></returns>
|
||||
//[HttpPost]
|
||||
//public async Task<UserViewModel> CreateUser([FromBody] UserViewModel user)
|
||||
//{
|
||||
// user.Id = null;
|
||||
// var userResult = await UserManager.CreateUser(Mapper.Map<UserDto>(user));
|
||||
// return Mapper.Map<UserViewModel>(userResult);
|
||||
//}
|
||||
[HttpPost]
|
||||
public async Task<IdentityResult> CreateUser([FromBody] UserViewModel user)
|
||||
{
|
||||
if (!EmailValidator.IsValidEmail(user.EmailAddress))
|
||||
{
|
||||
return Error($"The email address {user.EmailAddress} is not a valid format");
|
||||
}
|
||||
var ombiUser = new OmbiUser
|
||||
{
|
||||
Alias = user.Alias,
|
||||
Email = user.EmailAddress,
|
||||
UserName = user.Username,
|
||||
UserType = UserType.LocalUser,
|
||||
};
|
||||
var userResult = await UserManager.CreateAsync(ombiUser, user.Password);
|
||||
|
||||
if (!userResult.Succeeded)
|
||||
{
|
||||
// We did not create the user
|
||||
return new IdentityResult
|
||||
{
|
||||
Errors = userResult.Errors.Select(x => x.Description).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
var roleResult = await AddRoles(user.Claims, ombiUser);
|
||||
|
||||
if (roleResult.Any(x => !x.Succeeded))
|
||||
{
|
||||
var messages = new List<string>();
|
||||
foreach (var errors in roleResult.Where(x => !x.Succeeded))
|
||||
{
|
||||
messages.AddRange(errors.Errors.Select(x => x.Description).ToList());
|
||||
}
|
||||
|
||||
return new IdentityResult
|
||||
{
|
||||
Errors = messages
|
||||
};
|
||||
}
|
||||
|
||||
return new IdentityResult
|
||||
{
|
||||
Successful = true
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is for the local user to change their details.
|
||||
/// </summary>
|
||||
/// <param name="ui"></param>
|
||||
/// <returns></returns>
|
||||
[HttpPut("local")]
|
||||
[Authorize]
|
||||
public async Task<IdentityResult> UpdateLocalUser([FromBody] UpdateLocalUserModel ui)
|
||||
{
|
||||
if (string.IsNullOrEmpty(ui.CurrentPassword))
|
||||
{
|
||||
return Error("You need to provide your current password to make any changes");
|
||||
}
|
||||
|
||||
var changingPass = !string.IsNullOrEmpty(ui.Password) || !string.IsNullOrEmpty(ui.ConfirmNewPassword);
|
||||
|
||||
if (changingPass)
|
||||
{
|
||||
if (!ui.Password.Equals(ui?.ConfirmNewPassword, StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
return Error("Passwords do not match");
|
||||
}
|
||||
}
|
||||
|
||||
if (!EmailValidator.IsValidEmail(ui.EmailAddress))
|
||||
{
|
||||
return Error($"The email address {ui.EmailAddress} is not a valid format");
|
||||
}
|
||||
// Get the user
|
||||
var user = await UserManager.Users.FirstOrDefaultAsync(x => x.Id == ui.Id);
|
||||
if (user == null)
|
||||
{
|
||||
return Error("The user does not exist");
|
||||
}
|
||||
|
||||
// Make sure the pass is ok
|
||||
var passwordCheck = await UserManager.CheckPasswordAsync(user, ui.CurrentPassword);
|
||||
if (!passwordCheck)
|
||||
{
|
||||
return Error("Your password is incorrect");
|
||||
}
|
||||
|
||||
user.Email = ui.EmailAddress;
|
||||
|
||||
var updateResult = await UserManager.UpdateAsync(user);
|
||||
if (!updateResult.Succeeded)
|
||||
{
|
||||
return new IdentityResult
|
||||
{
|
||||
Errors = updateResult.Errors.Select(x => x.Description).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
if (changingPass)
|
||||
{
|
||||
var result = await UserManager.ChangePasswordAsync(user, ui.CurrentPassword, ui.Password);
|
||||
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
return new IdentityResult
|
||||
{
|
||||
Errors = result.Errors.Select(x => x.Description).ToList()
|
||||
};
|
||||
}
|
||||
}
|
||||
return new IdentityResult
|
||||
{
|
||||
Successful = true
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the user.
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <param name = "ui" > The user.</param>
|
||||
/// <returns></returns>
|
||||
//[HttpPut]
|
||||
//public async Task<UserViewModel> UpdateUser([FromBody] UserViewModel user)
|
||||
//{
|
||||
// var userResult = await UserManager.UpdateUser(Mapper.Map<UserDto>(user));
|
||||
// return Mapper.Map<UserViewModel>(userResult);
|
||||
//}
|
||||
[HttpPut]
|
||||
public async Task<IdentityResult> UpdateUser([FromBody] UserViewModel ui)
|
||||
{
|
||||
if (!EmailValidator.IsValidEmail(ui.EmailAddress))
|
||||
{
|
||||
return Error($"The email address {ui.EmailAddress} is not a valid format");
|
||||
}
|
||||
// Get the user
|
||||
var user = await UserManager.Users.FirstOrDefaultAsync(x => x.Id == ui.Id);
|
||||
user.Alias = ui.Alias;
|
||||
user.Email = ui.EmailAddress;
|
||||
var updateResult = await UserManager.UpdateAsync(user);
|
||||
if (!updateResult.Succeeded)
|
||||
{
|
||||
return new IdentityResult
|
||||
{
|
||||
Errors = updateResult.Errors.Select(x => x.Description).ToList()
|
||||
};
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// Deletes the user.
|
||||
///// </summary>
|
||||
///// <param name="user">The user.</param>
|
||||
///// <returns></returns>
|
||||
//[HttpDelete]
|
||||
//public async Task<StatusCodeResult> DeleteUser([FromBody] UserViewModel user)
|
||||
//{
|
||||
// await UserManager.DeleteUser(Mapper.Map<UserDto>(user));
|
||||
// return Ok();
|
||||
//}
|
||||
// Get the roles
|
||||
var userRoles = await UserManager.GetRolesAsync(user);
|
||||
|
||||
foreach (var role in userRoles)
|
||||
{
|
||||
await UserManager.RemoveFromRoleAsync(user, role);
|
||||
}
|
||||
|
||||
var result = await AddRoles(ui.Claims, user);
|
||||
if (result.Any(x => !x.Succeeded))
|
||||
{
|
||||
var messages = new List<string>();
|
||||
foreach (var errors in result.Where(x => !x.Succeeded))
|
||||
{
|
||||
messages.AddRange(errors.Errors.Select(x => x.Description).ToList());
|
||||
}
|
||||
|
||||
return new IdentityResult
|
||||
{
|
||||
Errors = messages
|
||||
};
|
||||
}
|
||||
|
||||
return new IdentityResult
|
||||
{
|
||||
Successful = true
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the user.
|
||||
/// </summary>
|
||||
/// <param name="userId">The user.</param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete("{userId}")]
|
||||
public async Task<IdentityResult> DeleteUser(string userId)
|
||||
{
|
||||
|
||||
var userToDelete = await UserManager.Users.FirstOrDefaultAsync(x => x.Id == userId);
|
||||
if (userToDelete != null)
|
||||
{
|
||||
var result = await UserManager.DeleteAsync(userToDelete);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
return new IdentityResult
|
||||
{
|
||||
Successful = true
|
||||
};
|
||||
}
|
||||
|
||||
return new IdentityResult
|
||||
{
|
||||
Errors = result.Errors.Select(x => x.Description).ToList()
|
||||
};
|
||||
}
|
||||
return Error("Could not find user to delete.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all available claims in the system.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[HttpGet("claims")]
|
||||
public IEnumerable<ClaimCheckboxes> GetAllClaims()
|
||||
public async Task<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 });
|
||||
var claims = new List<ClaimCheckboxes>();
|
||||
// Add the missing claims
|
||||
var allRoles = await RoleManager.Roles.ToListAsync();
|
||||
var missing = allRoles.Select(x => x.Name);
|
||||
foreach (var role in missing)
|
||||
{
|
||||
claims.Add(new ClaimCheckboxes
|
||||
{
|
||||
Value = role,
|
||||
Enabled = false
|
||||
});
|
||||
}
|
||||
return claims;
|
||||
}
|
||||
|
||||
private async Task<List<Microsoft.AspNetCore.Identity.IdentityResult>> AddRoles(IEnumerable<ClaimCheckboxes> roles, OmbiUser ombiUser)
|
||||
{
|
||||
var roleResult = new List<Microsoft.AspNetCore.Identity.IdentityResult>();
|
||||
foreach (var role in roles)
|
||||
{
|
||||
if (role.Enabled)
|
||||
{
|
||||
roleResult.Add(await UserManager.AddToRoleAsync(ombiUser, role.Value));
|
||||
}
|
||||
}
|
||||
return roleResult;
|
||||
}
|
||||
|
||||
private IdentityResult Error(string message)
|
||||
{
|
||||
return new IdentityResult
|
||||
{
|
||||
Errors = new List<string> { message }
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using IdentityModel;
|
||||
using IdentityServer4.Models;
|
||||
|
||||
namespace Ombi
|
||||
|
@ -25,7 +26,7 @@ namespace Ombi
|
|||
{
|
||||
new ApiResource("api", "API")
|
||||
{
|
||||
UserClaims = {"role", "name"},
|
||||
UserClaims = {JwtClaimTypes.Name, JwtClaimTypes.Role, JwtClaimTypes.Email, JwtClaimTypes.Id},
|
||||
|
||||
}
|
||||
};
|
||||
|
|
10
src/Ombi/Models/Identity/IdentityResult.cs
Normal file
10
src/Ombi/Models/Identity/IdentityResult.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace Ombi.Models.Identity
|
||||
{
|
||||
public class IdentityResult
|
||||
{
|
||||
public List<string> Errors { get; set; }
|
||||
public bool Successful { get; set; }
|
||||
}
|
||||
}
|
10
src/Ombi/Models/Identity/UpdateLocalUserModel.cs
Normal file
10
src/Ombi/Models/Identity/UpdateLocalUserModel.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using Ombi.Core.Models.UI;
|
||||
|
||||
namespace Ombi.Models.Identity
|
||||
{
|
||||
public class UpdateLocalUserModel : UserViewModel
|
||||
{
|
||||
public string CurrentPassword { get; set; }
|
||||
public string ConfirmNewPassword { get; set; }
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue