This commit is contained in:
2020-12-07 17:51:52 +00:00
parent f25706b02e
commit e6e77f121d
3 changed files with 87 additions and 12 deletions

View File

@@ -77,13 +77,11 @@ namespace AyaNova.Api.Controllers
var o = await biz.GetAsync(id);
if (o == null)
return NotFound(new ApiErrorResponse(ApiErrorCode.NOT_FOUND));
bool IsOutsideUser = (o.UserType == UserType.Customer || o.UserType == UserType.HeadOffice);
if (IsOutsideUser && !AllowedOutsideUser)
if (o.IsOutsideUser && !AllowedOutsideUser)
return StatusCode(403, new ApiNotAuthorizedResponse());
if (!IsOutsideUser && !AllowedInsideUser)
if (!o.IsOutsideUser && !AllowedInsideUser)
return StatusCode(403, new ApiNotAuthorizedResponse());
return Ok(ApiOkResponse.Response(o));

View File

@@ -115,18 +115,28 @@ namespace AyaNova.Biz
//CREATE
internal async Task<dtUser> CreateAsync(User newObject)
{
//Also used for Contacts (customer type user or ho type user)
//by users with no User right but with Customer rights so need to double check here
if (
(newObject.IsOutsideUser && !Authorized.HasCreateRole(CurrentUserRoles, AyaType.Customer)) ||
(!newObject.IsOutsideUser && !Authorized.HasCreateRole(CurrentUserRoles, AyaType.User))
)
{
AddError(ApiErrorCode.NOT_AUTHORIZED);
return null;
}
//password and login are optional but in the sense that they can be left out in a PUT
// but if left out here we need to generate a random value instead so they can't login but the code is happy
//because a login name and password are required always
if (string.IsNullOrWhiteSpace(newObject.Password))
{
newObject.Password = Hasher.GenerateSalt();//set it to some big random value
}
if (string.IsNullOrWhiteSpace(newObject.Login))
{
newObject.Login = Hasher.GenerateSalt();//set it to some big random value
}
//This is a new user so it will have been posted with a password in plaintext which needs to be salted and hashed
newObject.Salt = Hasher.GenerateSalt();
@@ -173,6 +183,18 @@ namespace AyaNova.Biz
AddError(ApiErrorCode.NOT_FOUND, "id");
return null;
}
//Also used for Contacts (customer type user or ho type user)
//by users with no User right but with Customer rights so need to double check here
if (
(dbObject.IsOutsideUser && !Authorized.HasCreateRole(CurrentUserRoles, AyaType.Customer)) ||
(!dbObject.IsOutsideUser && !Authorized.HasCreateRole(CurrentUserRoles, AyaType.User))
)
{
AddError(ApiErrorCode.NOT_AUTHORIZED);
return null;
}
User newObject = new User();
CopyObject.Copy(dbObject, newObject, "Id, Salt, Login, Password, CurrentAuthToken, DlKey, DlKeyExpire, Wiki, Serial");
string newUniqueName = string.Empty;
@@ -236,6 +258,18 @@ namespace AyaNova.Biz
AddError(ApiErrorCode.NOT_FOUND, "id");
return null;
}
//Also used for Contacts (customer type user or ho type user)
//by users with no User right but with Customer rights so need to double check here
if (
(dbObject.IsOutsideUser && !Authorized.HasModifyRole(CurrentUserRoles, AyaType.Customer)) ||
(!dbObject.IsOutsideUser && !Authorized.HasModifyRole(CurrentUserRoles, AyaType.User))
)
{
AddError(ApiErrorCode.NOT_AUTHORIZED);
return null;
}
User SnapshotOfOriginalDBObj = new User();
CopyObject.Copy(dbObject, SnapshotOfOriginalDBObj);
CopyObject.Copy(putObject, dbObject, "Id, Salt, CurrentAuthToken, LoginKey, DlKey, DlKeyExpire");
@@ -398,12 +432,25 @@ namespace AyaNova.Biz
internal async Task<bool> DeleteAsync(long id)
{
using (var transaction = await ct.Database.BeginTransactionAsync())
{
try
{
User dbObject = await ct.User.SingleOrDefaultAsync(z => z.Id == id);
if (dbObject == null)
return false;
//Also used for Contacts (customer type user or ho type user)
//by users with no User right but with Customer rights so need to double check here
if (
(dbObject.IsOutsideUser && !Authorized.HasDeleteRole(CurrentUserRoles, AyaType.Customer)) ||
(!dbObject.IsOutsideUser && !Authorized.HasDeleteRole(CurrentUserRoles, AyaType.User))
)
{
AddError(ApiErrorCode.NOT_AUTHORIZED);
return false;
}
await ValidateCanDelete(dbObject);
if (HasErrors)
return false;
@@ -448,12 +495,25 @@ namespace AyaNova.Biz
private async Task ValidateAsync(User proposedObj, User currentObj)
{
//skip validation if seeding
if(ServerBootConfig.SEEDING) return;
if (ServerBootConfig.SEEDING) return;
//run validation and biz rules
bool isNew = currentObj == null;
//UserType change has Inside / Outside role implications
//a user attempting to change a UserType between inside or outside status must have the correct rights
//to *BOTH* Customer and User since it's affecting both types
if (currentObj.IsOutsideUser != proposedObj.IsOutsideUser)
{
//only can change if have both rights
if (
!Authorized.HasModifyRole(CurrentUserRoles, AyaType.User) ||
!Authorized.HasModifyRole(CurrentUserRoles, AyaType.Customer)
)
{
AddError(ApiErrorCode.NOT_AUTHORIZED, "UserType");
}
}
//do we need to check the license situation?
if (proposedObj.IsTech && proposedObj.Active)

View File

@@ -35,6 +35,14 @@ namespace AyaNova.Models
[NotMapped, JsonIgnore]
public AyaType AyaType { get => AyaType.User; }
public bool IsOutsideUser
{
get
{
return this.UserType == UserType.Customer || this.UserType == UserType.HeadOffice;
}
}
// [JsonIgnore]//hide from being returned (as null anyway) with User object in routes
// public UserOptions UserOptions { get; set; }
}//eoc
@@ -114,6 +122,15 @@ namespace AyaNova.Models
}
}
public bool IsOutsideUser
{
get
{
return this.UserType == UserType.Customer || this.UserType == UserType.HeadOffice;
}
}
[NotMapped, JsonIgnore]
public AyaType AyaType { get => AyaType.User; }