Security in domain?

283 views
Skip to first unread message

oguzh4n

unread,
Apr 1, 2014, 8:17:33 PM4/1/14
to ddd...@googlegroups.com
Hello,

I'm working on a collaboration project. I have an aggregate root called "Project". 
Users can create,edit,delete,view on Project if has access to "Project" Aggregate.

Our security context is complicated. We are a permission lookup depend of created "Project" properties and user level/locality (ProjectType, Project Depended Project, Project Blocked Users, Project Users, Restricted Project, Everyting Accessible)
There are 20+ rules like this:
Example:
 - If ProjectType == "Hierarchical",when a user added to "Project" followers list, this user and its managers (managers of managers) can access to this project with own permissions 
(permissions dynamically set to user according to properties of "Project" and user access level (manager or itself, follower type))
 - If ProjectType == "TeamBased", all "Project" users can access to this project with own permissions
(permissions dynamically set to user according to properties of "Project" and user access level (manager or itself))
 ...
I'm using AuthorizationCommandHandlerDecorator check permissions for command now. 
public void Handle(CreateProjectEntityCommand command){
var project = _projectRepository.Get(command.ProjectId);
if(_securityService.HasAccess(project, "CreateProjectEntity", CurrentUser))
throw new Exception("no access");
project.CreateProjectEntity(command.EntityName);
}

In permission creation, raised event from "Project" AR and create new resource for user
// Project AR
public void CreateProjectEntity(string entityName) {
DomainEvents.Raise(new ProjectEntityCreated(this));
}
public void Handle(ProjectEntityCreated ev) {
var project = _projectRepository.Get(ev.ProjectId);
var owners = _userRepository.GetAll(ev.Owners);
var followers = _userRepository.GetAll(ev.Followers);
var authors = _userRepository.GetAll(ev.Authors);
var user = _securityService.GetCurrentUser;
if(project.Type=="Hierarchical") {
var ownerPermissions = _securityRuleLookup.GetRolePermissions("Entity Of Project","Owner");
var ownerManagersPermissions = _securityRuleLookup.GetRolePermissions("Entity Of Project","Owner Managers Level 1");
var ownerTLevelManagersPermissions = _securityRuleLookup.GetRolePermissions("Entity Of Project","Owner Managers Level > 1");
_securityService.AddPermissions(owners,ownerPermissions,ev.ProjectId);
_securityService.AddPermissions(GetManagersOfUsers(owners),ownerManagersPermissions,ev.ProjectId);
_securityService.AddPermissions(GetTLevelManagersOfUsers(owners),ownerTLevelManagersPermissions,ev.ProjectId);
// ... same process for followers, authors, complex rules for user and managers
}
}
Authorization/Security shouldn't part of domain in my read and research. But our security has business rules and I should implement security context in domain. Am I wrong?

Regards,

oguzh4n

unread,
Apr 8, 2014, 11:29:56 AM4/8/14
to ddd...@googlegroups.com
any idea? :)

2 Nisan 2014 Çarşamba 03:17:33 UTC+3 tarihinde oguzh4n yazdı:

@yreynhout

unread,
Apr 9, 2014, 9:06:26 AM4/9/14
to ddd...@googlegroups.com
React to the ProjectEntityCreated event in a different BC (authorization has nothing to do with this model). Then expose a lib from the authorization BC that you can use in this BC that deals with allowing/denying a user to execute the behavior (applies to viewing as well).

oguzh4n

unread,
Apr 9, 2014, 10:44:11 AM4/9/14
to ddd...@googlegroups.com
ProjectEntityCreated event handles in Application Service now.  Exposed lib (from Authroization BC) should be Domain Service or Application Service? Authroization creation/check behaviour of Application Service?

9 Nisan 2014 Çarşamba 16:06:26 UTC+3 tarihinde @yreynhout yazdı:

@yreynhout

unread,
Apr 10, 2014, 10:33:14 AM4/10/14
to ddd...@googlegroups.com
I'd put in my application service pipeline, e.g. something you can easily do with claims based security:

void Authorize(ClaimsIdentity identity, CreateProjectEntityCommand command) {
  var project = _projectRepository.Get(command.ProjectId);
  if(!identity.HasPermissionTo(PermissionSet.CreateProjectEntity)) {
    throw new CommandAuthorizationException("....");
  }

  // where HasPermissionTo is an extension method on ClaimsIdentity that verifies a claim under the hood
}

further down the pipeline you have your regular handler

void Handle(CreateProjectEntityCommand command) {
  var project = _projectRepository.Get(command.ProjectId);
  project.CreateProjectEntity(command.EntityName);
}

now I can test & evolve authorization and handling concerns separately (but that might be overshooting in your case - you can melt the Authorize and Handle)). 

The claims enrichment of the identity that initiates the command is a separate thing and is done based on projected authorization permissions (or a fully fledged model if you're like me). These authorization permissions are what I alluded to earlier, basically the reaction to your ProjectEntityCreated causes this.

oguzh4n

unread,
Apr 11, 2014, 7:35:35 AM4/11/14
to ddd...@googlegroups.com
ProjectEntityCreated should handle in different bc right?  I understand it like this

Project BC Domain
 - Project -> Raise ProjectEntityCreated 

Authorization BC Domain
 - AuthroizationBuilder <- ProjectEntityCreated, build permissions using events (business rule)

Authorization BC Application, exposed api for checking permission from other bcs

Project BC Application, check permissions from Authroization BC Application


10 Nisan 2014 Perşembe 17:33:14 UTC+3 tarihinde @yreynhout yazdı:
Reply all
Reply to author
Forward
0 new messages