Role groups within a single application


Author
Message
Larry Caylor
Larry Caylor
Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)
Group: Awaiting Activation
Posts: 592, Visits: 3.7K
I'm trying to find a way to use the RBS module for a new application and haven't been able to figure out a way to meet the applications requirements. The application will be used to track multiple projects. New projects may be added to the application at run time. All projects will share the same permissions. Users need the ability to have different roles and permissions within each project and I need to be able to determine their permissions for a specific project at run time, not just the over all application.  Attached is a diagram of what I'm trying to accomplish. Any suggestions?

-Larry

Attachments
SecurityReq.png (171 views, 24.00 KB)
Ivan George Borges
Ivan George Borges
Strategic Support Team Member (2.8K reputation)Strategic Support Team Member (2.8K reputation)Strategic Support Team Member (2.8K reputation)Strategic Support Team Member (2.8K reputation)Strategic Support Team Member (2.8K reputation)Strategic Support Team Member (2.8K reputation)Strategic Support Team Member (2.8K reputation)Strategic Support Team Member (2.8K reputation)Strategic Support Team Member (2.8K reputation)
Group: StrataFrame MVPs
Posts: 1.9K, Visits: 21K
Hi Larry!

Hope you are fine.

Here is a discussion that might give you some ideas:

http://forum.strataframe.net/FindPost3970.aspx

Larry Caylor
Larry Caylor
Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)
Group: Awaiting Activation
Posts: 592, Visits: 3.7K
Ivan,

Thanks for the link... looks similar to what I'm trying to accomplish. I wish the framework made it a little easier.

-Larry

Greg McGuffey
Greg McGuffey
Strategic Support Team Member (2.7K reputation)
Group: Forum Members
Posts: 2K, Visits: 6.6K
Larry,



Ivan referred you to a post of mine from about a million years ago, when I was first investigating SF and RBS. You definitely should check it out, but I can add some cliff notes (which normally mean a condensed version of the material, making it easier to understand...this might be more like a steep drop that causes pain if you fall off of it) that might also help.



First and fore most, it worked. BigGrin The app has been in production using SF and the RBS for 1+ years. This is definitely possible.



There are a couple of key concepts:

- The permissions for a user are set when they login. They don't change within the application after that.

- The RBS has no mechanism to handle storing separate roles/permissions based on project. It just isn't there.



This leads to some design decisions. First, you'll need to add some of your own tables (and associated BOs) to track at least the role(s) a user has for a project. You might also track what permissions a user has per project (to allow a user to be assigned permissions directly, like SF does...I skipped this, using only roles). If you're users can be assigned to projects (i.e. they aren't automatically assigned to them all), you'll likely need to track which projects a user is assigned as well. I also track the default project of a user, which is the one they get logged onto by default when they login. About every 6 months I come up with the idea to just put a drop down on the login form to let them choose which project, but then remember that since my users aren't automatically allowed access (or even know about) all projects, there is no way form me to know what to put into the project drop down until after they have logged in. If your project uses windows authentication or all users have access to all projects, this might be a good way to go though.



Next, you'll need to dynamically assign the roles a user has after they have been authenticated and you know what project they are going to be working on but before they've actually logged in (which is when the permissions get set within RBS). You uses the SFS BOs to clear any potentially conflicting roles, then use your lookup table to load the appropriate roles for the user/project. After you've done this, you log them in, which loads the app with the appropriate permissions. This means that you will need to authenticate them, get a project, clear and load roles/permissions, then log them in for real. Here is the OK button handler in my custom login form.



Private Sub btnOk_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOk.Click

  '-- Authenticate the user

  Dim userInfo As SFSUsersBO = Nothing

  Dim loginResult As Login.LoginResult



  Using userInfo

    loginResult = Login.AuthenticateUser(Me.Username, Me.Password, "", userInfo)



    '-- Based on result, we need to configure the app.

    '   The shared UserContext class handles the hard work of

    '   determining the default project, then setting permissions, etc.

    Select Case loginResult

      Case Login.LoginResult.Success

        UserContext.SetUserContext(LoggedInUser.CreateNew(userInfo))

      Case Login.LoginResult.AdminLoggedOn

        UserContext.SetUserContext(New AdminUser(Now))

      Case Login.LoginResult.SecMaintUserLoggedOn

        UserContext.SetUserContext(New SecurityMaintenanceUser(Now))

      Case Login.LoginResult.Failure

    End Select

  End Using



  '-- Raise the attempt login event

  '   This will handle any messages for user who's logon failed.

  Me.OnAttemptLogin()

End Sub





In UserContext.SetUserContext, I do the following (I've just included the comments to give you an idea of the things I'm doing and not make this too long of a post):



Public Shared Sub SetUserContext(ByVal secUser As ISecurityUser)

  '-- Determine if the user is an enterprise level or project level user



  '-- Save the User's ID, which is needed by other procedures in this class



  '-- Determine if the user is an admin



  '-- Load the project list for this user



  '-- Determine the user's default project. If none is set, and the user

  '   has access to at least one project, we set a default for them.



  '-- If there is still no default project, and the user is a project level

  '   user, then we can't continue. Notify them and exit.



  '-- If there is a default project, set it. SetCurrentProject handles

  '   setting roles based on project.

  If defaultProjectID <> 0 Then

    SetCurrentProject(defaultProjectID)

  End If

End Sub




In SetCurrentProject, I actually handle the setting of permissions. This is in a different method because it is also used when a user changes projects (selected from a list of available projects). Also note that I have a class of users who have "enterprise" level access. This means that they automatically have access to all projects and share permission/roles across all those projects. You may not have this type of user. Here is the code for SetCurrentProject:



Public Shared Sub SetCurrentProject(ByVal projectID As Integer, ByVal reloginUser As Boolean)

  '-- Does user have access to all projects?

  Dim userHasAllProjectAccess As Boolean = (_allProjectAccess = PermissionAction.Grant)



  '-- Check that the parameters are valid, i.e. is this project

  '   ID valid for the user. There are two possible causes

  '   for problems here. The first is that the default project

  '   table is corrupt and is pointing to a project that has

  '   been deleted or was imported from another server and

  '   doesn't exist. The other is that somebody is trying to

  '   break into the system Sad

  If Array.IndexOf(_userProjectList, projectID) < 0 Then

    Throw New ArgumentException("The project ID provided is invalid." _

        , "projectID" _

        , New Exception("The user does not have access to this project"))

  End If



  '-- Cache the project ID so it is easily accessible.

  _currentProjectID = projectID



  '-- Cache details about this project (client), so it is easily accessible

  '   to forms/methods that need the current project.

  Using boProject As New Project.ProjectBO

    boProject.FillByPrimaryKey(projectID)

    _currentProjectName = boProject.ProjectName

    '-- Other data about project you might need...



    '-- Notify subscribers that project state has changed. This

    '   notifies any open forms that the project has changed.

    boProject.NotifyProjectDataChanged()



    '-- Set the current BO (which allows above to occur)

    _currentProjectBO = boProject



    '-- Configure the bo to monitor for data changes

    AddHandler _currentProjectBO.ProjectDataChanged, AddressOf CurrentProject_DataChanged

  End Using



  '-- Handle setting roles

  If Not userHasAllProjectAccess Then

    '-- First clear any existing roles for the user.

    ClearUserProjectRoles()



    '-- Now set the roles defined

    '   Get the roles that can be defined by project

    Using userProjectRoles As New SecUserProjectRoleBO

      userProjectRoles.FillByUserProject(UserContext.CurrentUserID, _currentProjectID)



      '-- For each role, add it to the SF user roles linking data

      For Each projectRole As Data.DataRow In userProjectRoles.CurrentDataTable.Rows

        '-- Open a BO to the SF user roles data

        Using userSFRolesBO As New SFBO.SFSUsersXRolesBO

        userSFRolesBO.FillAllByUser(UserContext.CurrentUserID)

        userSFRolesBO.Add()

        userSFRolesBO.ur_rl_pk = DirectCast(projectRole.Item("RoleID"), Integer)

        userSFRolesBO.ur_us_pk = UserContext.CurrentUserID

        userSFRolesBO.Save()

        End Using

      Next

    End Using

  End If



  '-- If indicated, login user in (needed if user is changing projects)

  If reloginUser Then

    '-- Handle the case of admin users, who don't need refresh

    If SecurityBasics.CurrentUser.IsAdministrator Then Return



    '-- Login the user in again, which updates permissions

    Using userSFBO As New SFBO.SFSUsersBO

     userSFBO.FillByPrimaryKey(SecurityBasics.CurrentUser.UserPK)

     LoggedInUser.SetLoggedOnUser(userSFBO)

    End Using

  End If

End Sub




I included the code here as this is were the work is actually getting done. Once this is done, my user is logged in, they have been assigned the appropriate roles for the project and I have a shared class that defines the project context for them.



Most of the rest of the development is pretty normal, because my user is now correctly assigned permissions. Normal RBS security just does its thing.



However, there are now a large set of forms and associated BOs that need to also be project specific. I.e. RBS won't know within a form that it needs to track projects, and thus reload permissions (which would be very unwieldy also). So, most of my forms (there are some that aren't project specific, like the one that defines projects!) are based an a project base form that has a ProjectID property. These forms requires that the project ID be set. Any data loaded must be within this project. Then, the permissions will be valid. In my menu system, I simply construct the form using the UserContext.CurrentProjectID.



This also means that most of my BOs have a FillByProjectID method.



You'll also have to make sure your browse dialogs would need a "static" filter on the project ID, that is you would need to set the project ID based on the current project and the user would not be able to change it. When I started, the browse dialog didn't support this, so I ended up rolling my own (great learning experience...but I'd use SFs now).



You'll also need UIs to create/manage projects, assign users to projects, assign roles/permissions to users for a project and to allow the user to change projects.



I also clean up there roles/permission in the SFS tables. This is redundant, as I'm also cleaning it up when they login, and I'd do a bit of investigation to see if I really need to be that anal.



I also have roles that are project specific and those that are not. The ones that are not project specific are things like access to the project definition data/forms, access to enterprise wide data (such as standards that might be used across all projects), etc. You could just use the admin role for that sort of stuff, but with the standards stuff, we needed to let content experts manage that. In some cases, they have NO access to any project related data. This means that I also track roles that are project specific. Thus a user could be a project specific user and have access to selected enterprise features. The ClearUserProjectRoles method thus actually only clears roles that are project specific, leaving any enterprise level roles alone.



Well, that turned into a book....Please let me know if you have any more questions or if you have any thoughts on how this might work better. This was the first thing I did in SF/.Net, during my trial, as I needed to know if this could be handled before committing to SF as the tool to use. As a result, there might be options I didn't consider/code that could be improved upon Hehe
Greg McGuffey
Greg McGuffey
Strategic Support Team Member (2.7K reputation)
Group: Forum Members
Posts: 2K, Visits: 6.6K
Ivan,



Thanks for the link... looks similar to what I'm trying to accomplish. I wish the framework made it a little easier.




What? My solution isn't easy? It's a simple 453 step process! Nothing to it! I'm greatly insulted! Tongue



Kidding aside, it would be nice if this was easier, but not sure how it could be generalized for inclusion in the framework. Maybe after you get yours going, we could compare notes and make an enhancement request! w00t
Edhy Rijo
E
StrataFrame VIP (3.7K reputation)StrataFrame VIP (3.7K reputation)StrataFrame VIP (3.7K reputation)StrataFrame VIP (3.7K reputation)StrataFrame VIP (3.7K reputation)StrataFrame VIP (3.7K reputation)StrataFrame VIP (3.7K reputation)StrataFrame VIP (3.7K reputation)StrataFrame VIP (3.7K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
Wow, I just read you 2 long post, good ideas there.  I don't have the need now to do something like this, but frankly, it would be very difficult to do in the VFP framework I was using Smile.

This just show how good is the RBS exposed to the framework so you can manipulate it based on data that does not even exist just yet.

Great post!Hehe

Edhy Rijo

Larry Caylor
Larry Caylor
Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)Advanced StrataFrame User (880 reputation)
Group: Awaiting Activation
Posts: 592, Visits: 3.7K
Greg,

Thank you for the detailed postBigGrin My need is slightly different in that I have a requirement for the user to be able to change projects (roles) as needed during the life of the application but I can see from your example how to get there wihout having to modify the RBS code.

-Larry

Greg McGuffey
Greg McGuffey
Strategic Support Team Member (2.7K reputation)
Group: Forum Members
Posts: 2K, Visits: 6.6K
Larry,



Actually, I have the same need (it seems like). My users can change projects any time they want. The SetCurrentProject does the heavy lifting both when they login and if they change their project while running the application. I have a UI that shows all projects they are assigned to. Here they can either set that project as their "working" project (the one that will be in context) or as their default (so they can manage which project they are logged into when they login).



Also, because the permissions are set when the user logs in, they can actually open multiple instances, logged into different projects (not sure that's a good idea...but they can do it).



In any case, I hope that gets you thinking!



Have a great weekend all! BigGrin
GO

Merge Selected

Merge into selected topic...



Merge into merge target...



Merge into a specific topic ID...




Similar Topics

Reading This Topic

Login

Explore
Messages
Mentions
Search