Description:
With v16.1, application administrators can allow accessing all data within the application for a specific role and simultaneously prevent the access to a few data types or members. Alternatively, an end-user can deny access to all data for a role and only allow access to a strict list of objects or members.
See more information about the implemented functionality here: Permission Policies.
Prior to version 16.1, the SecuritySystemUser/SecuritySystemRole (XPO) and User/Role (EF) classes were used to create and process permissions. By default, the DenyAll policy was used, and it was necessary to add the Allow permission for objects and types. These classes are not compatible with the Allow/Deny permissions model.
This topic describes how to migrate to Allow/Deny security model in the existing application.
Answer:
IMPORTANT NOTES
1. The code, table names and other examples in this article are given for the DevExpress.ExpressApp.Security.Strategy.SecuritySystemUser, DevExpress.ExpressApp.Security.Strategy.SecuritySystemRole and related persistent classes when eXpress Persistent Objects (XPO) is used for data access. If you are using Entity Framework (EF), modify the code below to use the DevExpress.Persistent.BaseImpl.EF.User, DevExpress.Persistent.BaseImpl.EF.Role and related classes by analogy. If your EF application already uses the Allow/Deny policy, you may need to additionally perform a migration, as described in the How to: Add Navigation Permissions to an Entity Framework Application Created with XAF 16.1 article.
2. Backup your XAF project and database before going further, because database modifications are to be done.
3. The main purpose of the following instructions is to simplify the migration as we cannot guarantee that all existing permissions will be converted correctly, because the old classes use different permission mechanisms. Only common scenarios are covered, others may not work, and you would need to manually check if all permissions are converted correctly and update them further yourself in case of any problems.
4. Additional limitations include the following:
- Existing references to SecuritySystemUser and SecuritySystemRole in your business objects, Controllers and other project code will not be redirected to corresponding PermissionPolicyUser and PermissionPolicyRole objects, and you will need to update this code manually.
- Database tables corresponding to the old security classes (SecuritySystemUser, SecuritySystemRole, SecuritySystemMemberPermissionsObject, SecuritySystemObjectPermissionsObject, SecuritySystemRoleParentRoles_SecuritySystemRoleChildRoles, SecuritySystemTypePermissionsObject, SecuritySystemUserUsers_SecuritySystemRoleRoles) will not be removed automatically as they may be needed by other applications relying on them.
- An existing key value of converted permission records will not be copied to new permission objects.
- In some cases, it is better to rework permissions so that they will match the new Security System. For example, a permission where all objects are allowed except those that use a complex criterion may be replaced with a permission where some objects are denied using a simple criterion.
If you do not need to transfer existing permissions to the new permissions policy, invoke the Application Designer for the YourSolutionName.Wxx/WxxApplication.xx file and set the UserType and RoleType properties of the SecurityStrategyComplex component to the PermissionPolicyUser and PermissionPolicyRole values respectively. After that, update your code that creates predefined users, roles and the required permissions as per the Using the Security System help article.
If your database already contains permissions configured by end-users, you can use the example below in the YourSolutionName.Module/DatabaseUpdate/Updater.cs file to copy them to new security classes. Before pasting this code to the Updater.cs file, ensure that both (PermissionPolicyUser/PermissionPolicyRole and SecuritySystemUser/SecuritySystemRole) security types are added as exported types.
C#using System;
using System.Linq;
using DevExpress.ExpressApp;
using DevExpress.Data.Filtering;
using DevExpress.Persistent.Base;
using DevExpress.ExpressApp.Updating;
using DevExpress.Xpo;
using DevExpress.ExpressApp.Xpo;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.BaseImpl.PermissionPolicy;
using System.Collections.Generic;
using DevExpress.ExpressApp.Security.Strategy;
namespace YourSolutionName.Module.DatabaseUpdate {
public class Updater : ModuleUpdater {
public Updater(IObjectSpace objectSpace, Version currentDBVersion) : base(objectSpace, currentDBVersion) { }
public override void UpdateDatabaseAfterUpdateSchema() {
base.UpdateDatabaseAfterUpdateSchema();
foreach(SecuritySystemUser securitySystemUser in ObjectSpace.GetObjects<SecuritySystemUser>()) {
CopyUser(securitySystemUser);
}
foreach(SecuritySystemRole securitySystemRole in ObjectSpace.GetObjects<SecuritySystemRole>()) {
CopyRole(securitySystemRole, null);
}
ObjectSpace.CommitChanges();
}
private void CopyUser(SecuritySystemUser securitySystemUser) {
PermissionPolicyUser permissionPolicyUser = ObjectSpace.FindObject<PermissionPolicyUser>(new BinaryOperator("UserName", securitySystemUser.UserName));
if(permissionPolicyUser == null) {
permissionPolicyUser = ObjectSpace.CreateObject<PermissionPolicyUser>();
permissionPolicyUser.UserName = securitySystemUser.UserName;
permissionPolicyUser.IsActive = securitySystemUser.IsActive;
permissionPolicyUser.ChangePasswordOnFirstLogon = securitySystemUser.ChangePasswordOnFirstLogon;
foreach(SecuritySystemRole securitySystemRole in securitySystemUser.Roles) {
CopyRole(securitySystemRole, permissionPolicyUser);
}
}
}
private void CopyRole(SecuritySystemRole securitySystemRole, PermissionPolicyUser permissionPolicyUser) {
PermissionPolicyRole permissionPolicyRole = ObjectSpace.FindObject<PermissionPolicyRole>(new BinaryOperator("Name", securitySystemRole.Name));
if(permissionPolicyRole == null) {
permissionPolicyRole = ObjectSpace.CreateObject<PermissionPolicyRole>();
permissionPolicyRole.Name = securitySystemRole.Name;
permissionPolicyRole.PermissionPolicy = SecurityPermissionPolicy.DenyAllByDefault;
permissionPolicyRole.IsAdministrative = securitySystemRole.IsAdministrative;
permissionPolicyRole.CanEditModel = securitySystemRole.CanEditModel;
foreach(SecuritySystemTypePermissionObject securitySystemTypePermissionObject in securitySystemRole.TypePermissions) {
CopyTypePermissions(securitySystemTypePermissionObject, securitySystemRole, permissionPolicyRole);
}
foreach(SecuritySystemRole parentRole in securitySystemRole.ParentRoles) {
CopyParentRole(parentRole, permissionPolicyRole);
}
}
if(permissionPolicyUser != null) {
permissionPolicyUser.Roles.Add(permissionPolicyRole);
}
}
private void CopyParentRole(SecuritySystemRole parentRole, PermissionPolicyRole permissionPolicyRole) {
if(parentRole.IsAdministrative) {
permissionPolicyRole.IsAdministrative = true;
}
if(parentRole.CanEditModel) {
permissionPolicyRole.IsAdministrative = true;
}
foreach(SecuritySystemTypePermissionObject securitySystemTypePermissionObject in parentRole.TypePermissions) {
CopyTypePermissions(securitySystemTypePermissionObject, parentRole, permissionPolicyRole);
}
foreach(SecuritySystemRole subParentRole in parentRole.ParentRoles) {
CopyParentRole(subParentRole, permissionPolicyRole);
}
}
private void CopyTypePermissions(SecuritySystemTypePermissionObject securitySystemTypePermissionObject, SecuritySystemRole securitySystemRole, PermissionPolicyRole permissionPolicyRole) {
PermissionPolicyTypePermissionObject permissionPolicyTypePermissionObject = ObjectSpace.FindObject<PermissionPolicyTypePermissionObject>(new BinaryOperator("TargetType", securitySystemTypePermissionObject.TargetType));
permissionPolicyTypePermissionObject = ObjectSpace.CreateObject<PermissionPolicyTypePermissionObject>();
permissionPolicyTypePermissionObject.TargetType = GetTargetType(securitySystemTypePermissionObject.TargetType);
permissionPolicyTypePermissionObject.Role = permissionPolicyRole;
if(securitySystemTypePermissionObject.AllowRead) {
permissionPolicyTypePermissionObject.ReadState = SecurityPermissionState.Allow;
}
if(securitySystemTypePermissionObject.AllowWrite) {
permissionPolicyTypePermissionObject.WriteState = SecurityPermissionState.Allow;
}
if(securitySystemTypePermissionObject.AllowCreate) {
permissionPolicyTypePermissionObject.CreateState = SecurityPermissionState.Allow;
}
if(securitySystemTypePermissionObject.AllowDelete) {
permissionPolicyTypePermissionObject.DeleteState = SecurityPermissionState.Allow;
}
if(securitySystemTypePermissionObject.AllowNavigate) {
permissionPolicyTypePermissionObject.NavigateState = SecurityPermissionState.Allow;
}
foreach(SecuritySystemObjectPermissionsObject securitySystemObjectPermissionsObject in securitySystemTypePermissionObject.ObjectPermissions) {
CopyObjectPermissions(securitySystemObjectPermissionsObject, permissionPolicyTypePermissionObject);
}
foreach(SecuritySystemMemberPermissionsObject securitySystemMemberPermissionsObject in securitySystemTypePermissionObject.MemberPermissions) {
CopyMemberPermission(securitySystemMemberPermissionsObject, permissionPolicyTypePermissionObject);
}
permissionPolicyRole.TypePermissions.Add(permissionPolicyTypePermissionObject);
}
private void CopyMemberPermission(SecuritySystemMemberPermissionsObject securitySystemMemberPermissionsObject, PermissionPolicyTypePermissionObject permissionPolicyTypePermissionObject) {
PermissionPolicyMemberPermissionsObject permissionPolicyMemberPermissionsObject = ObjectSpace.CreateObject<PermissionPolicyMemberPermissionsObject>();
permissionPolicyMemberPermissionsObject.TypePermissionObject = permissionPolicyTypePermissionObject;
if(securitySystemMemberPermissionsObject.AllowRead) {
permissionPolicyMemberPermissionsObject.ReadState = SecurityPermissionState.Allow;
}
if(securitySystemMemberPermissionsObject.AllowWrite) {
permissionPolicyMemberPermissionsObject.WriteState = SecurityPermissionState.Allow;
}
permissionPolicyMemberPermissionsObject.Members = securitySystemMemberPermissionsObject.Members;
permissionPolicyMemberPermissionsObject.Criteria = securitySystemMemberPermissionsObject.Criteria;
permissionPolicyTypePermissionObject.MemberPermissions.Add(permissionPolicyMemberPermissionsObject);
}
private void CopyObjectPermissions(SecuritySystemObjectPermissionsObject securitySystemObjectPermissionsObject, PermissionPolicyTypePermissionObject permissionPolicyTypePermissionObject) {
PermissionPolicyObjectPermissionsObject permissionPolicyObjectPermissionsObject = ObjectSpace.CreateObject<PermissionPolicyObjectPermissionsObject>();
permissionPolicyObjectPermissionsObject.TypePermissionObject = permissionPolicyTypePermissionObject;
if(securitySystemObjectPermissionsObject.AllowRead) {
permissionPolicyObjectPermissionsObject.ReadState = SecurityPermissionState.Allow;
}
if(securitySystemObjectPermissionsObject.AllowWrite) {
permissionPolicyObjectPermissionsObject.WriteState = SecurityPermissionState.Allow;
}
if(securitySystemObjectPermissionsObject.AllowDelete) {
permissionPolicyObjectPermissionsObject.DeleteState = SecurityPermissionState.Allow;
}
if(securitySystemObjectPermissionsObject.AllowNavigate) {
permissionPolicyObjectPermissionsObject.NavigateState = SecurityPermissionState.Allow;
}
permissionPolicyObjectPermissionsObject.Criteria = securitySystemObjectPermissionsObject.Criteria;
permissionPolicyTypePermissionObject.ObjectPermissions.Add(permissionPolicyObjectPermissionsObject);
}
private Type GetTargetType(Type currentType) {
Type outType;
if(!SecurityAssociationClassDictionary.TryGetValue(currentType, out outType)) {
outType = currentType;
}
return outType;
}
private static Dictionary<Type, Type> SecurityAssociationClassDictionary = new Dictionary<Type, Type>(){
{ typeof(SecuritySystemUser),typeof(PermissionPolicyUser) },
{ typeof(SecuritySystemRole),typeof(PermissionPolicyRole) },
{ typeof(SecuritySystemTypePermissionObject ),typeof(PermissionPolicyTypePermissionObject ) },
{ typeof(SecuritySystemObjectPermissionsObject ),typeof(PermissionPolicyObjectPermissionsObject ) },
{ typeof(SecuritySystemMemberPermissionsObject ),typeof(PermissionPolicyMemberPermissionsObject ) }
};
}
}
Visual BasicImports System
Imports System.Linq
Imports DevExpress.ExpressApp
Imports DevExpress.Data.Filtering
Imports DevExpress.Persistent.Base
Imports DevExpress.ExpressApp.Updating
Imports DevExpress.Xpo
Imports DevExpress.ExpressApp.Xpo
Imports DevExpress.Persistent.BaseImpl
Imports DevExpress.Persistent.BaseImpl.PermissionPolicy
Imports System.Collections.Generic
Imports DevExpress.ExpressApp.Security.Strategy
Namespace YourSolutionName.Module.DatabaseUpdate
Public Class Updater
Inherits ModuleUpdater
Public Sub New(ByVal objectSpace As IObjectSpace, ByVal currentDBVersion As Version)
MyBase.New(objectSpace, currentDBVersion)
End Sub
Public Overrides Sub UpdateDatabaseAfterUpdateSchema()
MyBase.UpdateDatabaseAfterUpdateSchema()
For Each securitySystemUser As SecuritySystemUser In ObjectSpace.GetObjects(Of SecuritySystemUser)()
CopyUser(securitySystemUser)
Next securitySystemUser
For Each securitySystemRole As SecuritySystemRole In ObjectSpace.GetObjects(Of SecuritySystemRole)()
CopyRole(securitySystemRole, Nothing)
Next securitySystemRole
ObjectSpace.CommitChanges()
End Sub
Private Sub CopyUser(ByVal securitySystemUser As SecuritySystemUser)
Dim permissionPolicyUser As PermissionPolicyUser = ObjectSpace.FindObject(Of PermissionPolicyUser)(New BinaryOperator("UserName", securitySystemUser.UserName))
If permissionPolicyUser Is Nothing Then
permissionPolicyUser = ObjectSpace.CreateObject(Of PermissionPolicyUser)()
permissionPolicyUser.UserName = securitySystemUser.UserName
permissionPolicyUser.IsActive = securitySystemUser.IsActive
permissionPolicyUser.ChangePasswordOnFirstLogon = securitySystemUser.ChangePasswordOnFirstLogon
For Each securitySystemRole As SecuritySystemRole In securitySystemUser.Roles
CopyRole(securitySystemRole, permissionPolicyUser)
Next securitySystemRole
End If
End Sub
Private Sub CopyRole(ByVal securitySystemRole As SecuritySystemRole, ByVal permissionPolicyUser As PermissionPolicyUser)
Dim permissionPolicyRole As PermissionPolicyRole = ObjectSpace.FindObject(Of PermissionPolicyRole)(New BinaryOperator("Name", securitySystemRole.Name))
If permissionPolicyRole Is Nothing Then
permissionPolicyRole = ObjectSpace.CreateObject(Of PermissionPolicyRole)()
permissionPolicyRole.Name = securitySystemRole.Name
permissionPolicyRole.PermissionPolicy = SecurityPermissionPolicy.DenyAllByDefault
permissionPolicyRole.IsAdministrative = securitySystemRole.IsAdministrative
permissionPolicyRole.CanEditModel = securitySystemRole.CanEditModel
For Each securitySystemTypePermissionObject As SecuritySystemTypePermissionObject In securitySystemRole.TypePermissions
CopyTypePermissions(securitySystemTypePermissionObject, securitySystemRole, permissionPolicyRole)
Next securitySystemTypePermissionObject
For Each parentRole As SecuritySystemRole In securitySystemRole.ParentRoles
CopyParentRole(parentRole, permissionPolicyRole)
Next parentRole
End If
If permissionPolicyUser IsNot Nothing Then
permissionPolicyUser.Roles.Add(permissionPolicyRole)
End If
End Sub
Private Sub CopyParentRole(ByVal parentRole As SecuritySystemRole, ByVal permissionPolicyRole As PermissionPolicyRole)
If parentRole.IsAdministrative Then
permissionPolicyRole.IsAdministrative = True
End If
If parentRole.CanEditModel Then
permissionPolicyRole.IsAdministrative = True
End If
For Each securitySystemTypePermissionObject As SecuritySystemTypePermissionObject In parentRole.TypePermissions
CopyTypePermissions(securitySystemTypePermissionObject, parentRole, permissionPolicyRole)
Next securitySystemTypePermissionObject
For Each subParentRole As SecuritySystemRole In parentRole.ParentRoles
CopyParentRole(subParentRole, permissionPolicyRole)
Next subParentRole
End Sub
Private Sub CopyTypePermissions(ByVal securitySystemTypePermissionObject As SecuritySystemTypePermissionObject, ByVal securitySystemRole As SecuritySystemRole, ByVal permissionPolicyRole As PermissionPolicyRole)
Dim permissionPolicyTypePermissionObject As PermissionPolicyTypePermissionObject = ObjectSpace.FindObject(Of PermissionPolicyTypePermissionObject)(New BinaryOperator("TargetType", securitySystemTypePermissionObject.TargetType))
permissionPolicyTypePermissionObject = ObjectSpace.CreateObject(Of PermissionPolicyTypePermissionObject)()
permissionPolicyTypePermissionObject.TargetType = GetTargetType(securitySystemTypePermissionObject.TargetType)
permissionPolicyTypePermissionObject.Role = permissionPolicyRole
If securitySystemTypePermissionObject.AllowRead Then
permissionPolicyTypePermissionObject.ReadState = SecurityPermissionState.Allow
End If
If securitySystemTypePermissionObject.AllowWrite Then
permissionPolicyTypePermissionObject.WriteState = SecurityPermissionState.Allow
End If
If securitySystemTypePermissionObject.AllowCreate Then
permissionPolicyTypePermissionObject.CreateState = SecurityPermissionState.Allow
End If
If securitySystemTypePermissionObject.AllowDelete Then
permissionPolicyTypePermissionObject.DeleteState = SecurityPermissionState.Allow
End If
If securitySystemTypePermissionObject.AllowNavigate Then
permissionPolicyTypePermissionObject.NavigateState = SecurityPermissionState.Allow
End If
For Each securitySystemObjectPermissionsObject As SecuritySystemObjectPermissionsObject In securitySystemTypePermissionObject.ObjectPermissions
CopyObjectPermissions(securitySystemObjectPermissionsObject, permissionPolicyTypePermissionObject)
Next securitySystemObjectPermissionsObject
For Each securitySystemMemberPermissionsObject As SecuritySystemMemberPermissionsObject In securitySystemTypePermissionObject.MemberPermissions
CopyMemberPermission(securitySystemMemberPermissionsObject, permissionPolicyTypePermissionObject)
Next securitySystemMemberPermissionsObject
permissionPolicyRole.TypePermissions.Add(permissionPolicyTypePermissionObject)
End Sub
Private Sub CopyMemberPermission(ByVal securitySystemMemberPermissionsObject As SecuritySystemMemberPermissionsObject, ByVal permissionPolicyTypePermissionObject As PermissionPolicyTypePermissionObject)
Dim permissionPolicyMemberPermissionsObject As PermissionPolicyMemberPermissionsObject = ObjectSpace.CreateObject(Of PermissionPolicyMemberPermissionsObject)()
permissionPolicyMemberPermissionsObject.TypePermissionObject = permissionPolicyTypePermissionObject
If securitySystemMemberPermissionsObject.AllowRead Then
permissionPolicyMemberPermissionsObject.ReadState = SecurityPermissionState.Allow
End If
If securitySystemMemberPermissionsObject.AllowWrite Then
permissionPolicyMemberPermissionsObject.WriteState = SecurityPermissionState.Allow
End If
permissionPolicyMemberPermissionsObject.Members = securitySystemMemberPermissionsObject.Members
permissionPolicyMemberPermissionsObject.Criteria = securitySystemMemberPermissionsObject.Criteria
permissionPolicyTypePermissionObject.MemberPermissions.Add(permissionPolicyMemberPermissionsObject)
End Sub
Private Sub CopyObjectPermissions(ByVal securitySystemObjectPermissionsObject As SecuritySystemObjectPermissionsObject, ByVal permissionPolicyTypePermissionObject As PermissionPolicyTypePermissionObject)
Dim permissionPolicyObjectPermissionsObject As PermissionPolicyObjectPermissionsObject = ObjectSpace.CreateObject(Of PermissionPolicyObjectPermissionsObject)()
permissionPolicyObjectPermissionsObject.TypePermissionObject = permissionPolicyTypePermissionObject
If securitySystemObjectPermissionsObject.AllowRead Then
permissionPolicyObjectPermissionsObject.ReadState = SecurityPermissionState.Allow
End If
If securitySystemObjectPermissionsObject.AllowWrite Then
permissionPolicyObjectPermissionsObject.WriteState = SecurityPermissionState.Allow
End If
If securitySystemObjectPermissionsObject.AllowDelete Then
permissionPolicyObjectPermissionsObject.DeleteState = SecurityPermissionState.Allow
End If
If securitySystemObjectPermissionsObject.AllowNavigate Then
permissionPolicyObjectPermissionsObject.NavigateState = SecurityPermissionState.Allow
End If
permissionPolicyObjectPermissionsObject.Criteria = securitySystemObjectPermissionsObject.Criteria
permissionPolicyTypePermissionObject.ObjectPermissions.Add(permissionPolicyObjectPermissionsObject)
End Sub
Private Function GetTargetType(ByVal currentType As Type) As Type
Dim outType As Type = Nothing
If Not SecurityAssociationClassDictionary.TryGetValue(currentType, outType) Then
outType = currentType
End If
Return outType
End Function
Private Shared SecurityAssociationClassDictionary As New Dictionary(Of Type, Type)() From {
{GetType(SecuritySystemUser), GetType(PermissionPolicyUser)},
{GetType(SecuritySystemRole), GetType(PermissionPolicyRole)},
{GetType(SecuritySystemTypePermissionObject), GetType(PermissionPolicyTypePermissionObject)},
{GetType(SecuritySystemObjectPermissionsObject), GetType(PermissionPolicyObjectPermissionsObject)},
{GetType(SecuritySystemMemberPermissionsObject), GetType(PermissionPolicyMemberPermissionsObject)}
}
End Class
End Namespace
As a result, new permissions will be created in the database. After the database is updated, manually check if all permissions are converted correctly. Please do not hesitate to contact us if you encounter any issue.
See Also:
How to convert a database when migrating from the 'User' and 'Role' classes to the 'SecuritySystemUser' and 'SecuritySystemRole' classes
How to migrate DevExpress XAF SecuritySystemUser to PermissionPolicyUser (posted by our customer on CodeProject)
Hi,
I am trying to convert my users to new systems. I reworked my code, but following code returns no objects:
foreach (SecuritySystemUser securitySystemUser in ObjectSpace.GetObjects<SecuritySystemUser>()) { CopyUser(securitySystemUser); } foreach (SecuritySystemRole securitySystemRole in ObjectSpace.GetObjects<SecuritySystemRole>()) { CopyRole(securitySystemRole, null); }
I checked the database, old tables are still populated. Any ideas why this might be happening?
Should this code be run before or after the change to UserType and RoleType?
Regards,
Mario
Hello,
I've created a separate ticket on your behalf (T446269: Using the T418166 in the existing application.). It has been placed in our processing queue and will be answered shortly.
Hi,
I successfully finished migration to new system (still need to validate all permissions manually), so I would like to share my experience with security system conversion.
Since I have many roles (several dozens) and some of the customers have several dozen users (and each user connected with several dozen roles), it was important that transition was smooth as possible.
So, I had to modify above script.
First, above script does not preserve passwords which is a major hassle for users. In order to do that, I ran following script in Updater.cs:
ExecuteNonQueryCommand(@" insert into PermissionPolicyUser (Oid, UserName, StoredPassword, ChangePasswordOnFirstLogon, IsActive) select NEWID(), UserName, StoredPassword, ChangePasswordOnFirstLogon, IsActive from SecuritySystemUser where GCRecord is null", false);
After that, above scripts needed slight changes to properly handle cases when user is found (currently all actions are ignored if user exists).
Besides that, I needed to revamp entire database and remove/move all references which I managed to do with scripts.
If anyone needs scripts to handle existing references/indexes/fields, I can share them, just let me know.
There was also an issue with empty collections with SecuritySystemUser / Role which I found a way to work in T446269: Using the T418166 in the existing application.
Anyway, not pretty, but doable in two days worth of work.
Above script helped quite a lot, so thank you very much for it.
Regards,
Mario
Thank you for sharing your experience with us.
Hi Mario and Alexey,
I tried to run the new code into my application with the old database with Security.Strategy but I got the following error.
I guess that is because I should handle or delete existing references/indexes. Am I right?? Can you help me with that?
Thanks, br
No se pudo crear 'ForeignKey' 'FK_RoleDashboardDefinitionDashboardDefinitions_Roles'. Pariente: 'RoleDashboardDefinitionDashboardDefinitions'. Error: Ejecutando Sql 'alter table "dbo"."RoleDashboardDefinitionDashboardDefinitions" add constraint "FK_RoleDashboardDefinitionDashboardDefinitions_Roles" foreign key ("Roles") references "dbo"."PermissionPolicyRole"("Oid") NOT FOR REPLICATION' con parámetros '' excepción 'System.Data.SqlClient.SqlException (0x80131904): There is already an object named 'FK_RoleDashboardDefinitionDashboardDefinitions_Roles' in the database.
Could not create constraint or index. See previous errors.
Hello JUAN,
I've created a separate ticket on your behalf (T446533: Exception using the T418166). It has been placed in our processing queue and will be answered shortly.
I spotted an issue with the CopyRole function when multiple users are part of the same role. Once the first user is added to the role, the subsequent users are not. I modified the CopyRole method to the following:
private void CopyRole(SecuritySystemRole securitySystemRole, PermissionPolicyUser permissionPolicyUser) { PermissionPolicyRole permissionPolicyRole = ObjectSpace.FindObject<PermissionPolicyRole>(new BinaryOperator("Name", securitySystemRole.Name)); if (permissionPolicyRole == null) { permissionPolicyRole = ObjectSpace.CreateObject<PermissionPolicyRole>(); permissionPolicyRole.Name = securitySystemRole.Name; permissionPolicyRole.PermissionPolicy = SecurityPermissionPolicy.DenyAllByDefault; permissionPolicyRole.IsAdministrative = securitySystemRole.IsAdministrative; permissionPolicyRole.CanEditModel = securitySystemRole.CanEditModel; foreach (SecuritySystemTypePermissionObject securitySystemTypePermissionObject in securitySystemRole.TypePermissions) { CopyTypePermissions(securitySystemTypePermissionObject, securitySystemRole, permissionPolicyRole); } foreach (SecuritySystemRole parentRole in securitySystemRole.ParentRoles) { CopyParentRole(parentRole, permissionPolicyRole); } } //Note: This has been moved outside of the creation condition if (permissionPolicyUser != null) { permissionPolicyUser.Roles.Add(permissionPolicyRole); } }
Hello Dave,
We strive to improve the quality of our documentation and greatly appreciate your comments. We have updated this article. Thanks!
I'm not sure if it makes a difference however my project is all vb, can the code to upgrade be converted to vb for me to try and upgrade my project, thanks
@Kevin: I've added VB.NET code obtained from one of the automatic conversion tools. I hope this helps.
Thanks Dennis, its much appreciated, I seem to have an issue still, below is the output when I try and run it.
1>------ Build started: Project: eSynergy.Module, Configuration: Debug Any CPU ------
1>C:\Users\Kevin\Source\Workspaces\eSynergy\eSynergy\eSynergy.Module\Controllers\DatabaseUpdate\Updater.vb(80,53): error BC30451: 'SecurityPermissionPolicy' is not declared. It may be inaccessible due to its protection level.
1>C:\Users\Kevin\Source\Workspaces\eSynergy\eSynergy\eSynergy.Module\Controllers\DatabaseUpdate\Updater.vb(115,62): error BC30451: 'SecurityPermissionState' is not declared. It may be inaccessible due to its protection level.
1>C:\Users\Kevin\Source\Workspaces\eSynergy\eSynergy\eSynergy.Module\Controllers\DatabaseUpdate\Updater.vb(118,63): error BC30451: 'SecurityPermissionState' is not declared. It may be inaccessible due to its protection level.
1>C:\Users\Kevin\Source\Workspaces\eSynergy\eSynergy\eSynergy.Module\Controllers\DatabaseUpdate\Updater.vb(121,64): error BC30451: 'SecurityPermissionState' is not declared. It may be inaccessible due to its protection level.
1>C:\Users\Kevin\Source\Workspaces\eSynergy\eSynergy\eSynergy.Module\Controllers\DatabaseUpdate\Updater.vb(124,64): error BC30451: 'SecurityPermissionState' is not declared. It may be inaccessible due to its protection level.
1>C:\Users\Kevin\Source\Workspaces\eSynergy\eSynergy\eSynergy.Module\Controllers\DatabaseUpdate\Updater.vb(127,66): error BC30451: 'SecurityPermissionState' is not declared. It may be inaccessible due to its protection level.
1>C:\Users\Kevin\Source\Workspaces\eSynergy\eSynergy\eSynergy.Module\Controllers\DatabaseUpdate\Updater.vb(141,65): error BC30451: 'SecurityPermissionState' is not declared. It may be inaccessible due to its protection level.
1>C:\Users\Kevin\Source\Workspaces\eSynergy\eSynergy\eSynergy.Module\Controllers\DatabaseUpdate\Updater.vb(144,66): error BC30451: 'SecurityPermissionState' is not declared. It may be inaccessible due to its protection level.
1>C:\Users\Kevin\Source\Workspaces\eSynergy\eSynergy\eSynergy.Module\Controllers\DatabaseUpdate\Updater.vb(154,65): error BC30451: 'SecurityPermissionState' is not declared. It may be inaccessible due to its protection level.
1>C:\Users\Kevin\Source\Workspaces\eSynergy\eSynergy\eSynergy.Module\Controllers\DatabaseUpdate\Updater.vb(157,66): error BC30451: 'SecurityPermissionState' is not declared. It may be inaccessible due to its protection level.
1>C:\Users\Kevin\Source\Workspaces\eSynergy\eSynergy\eSynergy.Module\Controllers\DatabaseUpdate\Updater.vb(160,67): error BC30451: 'SecurityPermissionState' is not declared. It may be inaccessible due to its protection level.
1>C:\Users\Kevin\Source\Workspaces\eSynergy\eSynergy\eSynergy.Module\Controllers\DatabaseUpdate\Updater.vb(163,69): error BC30451: 'SecurityPermissionState' is not declared. It may be inaccessible due to its protection level.
1>C:\Users\Kevin\Source\Workspaces\eSynergy\eSynergy\eSynergy.Module\Controllers\DatabaseUpdate\Updater.vb(170,76): warning BC42030: Variable 'outType' is passed by reference before it has been assigned a value. A null reference exception could result at runtime.
CodeRush for Roslyn canceled the build because project eSynergy.Module.Web\eSynergy.Module.Web.vbproj failed to build. You can disable this behavior on the IDE\Build options page.
2>------ Build started: Project: eSynergy.Module.Web, Configuration: Debug Any CPU ------
Build has been canceled.
@Kevin: These compilation errors occur because for some reason your Updater.vb file is missing the Imports statements it should normally have by default. I have explicitly added them into the code examples above. Please submit a separate ticket using the https://www.devexpress.com/ask service if this update does not help you move forward. Thanks.
What are the required Interfaces to implement for a Custom User and/or Role implementation?
Thanks
@Gustavo: I've created a separate ticket on your behalf (T563902: Fully custom implementation of the PermissionPolicyXXX classes). It has been placed in our processing queue and will be answered shortly.
Is this the latest iteration of docs for this upgrade? I'm just starting to dive into this on a production web app which was originally developed in XAF 14.2.
Mario, I would be interested in your script to update all references. Also, I'm using a custom user class (derived from SecuritySystemUser) so running into FK_User_Oid issues when it tries to create new PermissionPolicyUser object.
Also trying to make this go in one pass via Updater class and having all references in app already set to use PermissionPolicy objects without having to make multiple passes or do the upgrade offline in dev.
I'm starting to think might be easier to let updater create the new objects but then handle all the conversion via SQL only so I can preserve the Oid values. Maybe I'll check out the CodeProject solution.
@Randy: Yes. You may also want to check out the How to migrate DevExpress XAF SecuritySystemUser to PermissionPolicyUser article posted by our customer on CodeProject.
Here is my scenario:
Other than some SQL contained in RDL (SSRS) reports I do not have any direct references to SecuritySystemUser, so that's not a big deal to take care of.
I have a custom class (User) derived from SecuritySystemUser
I do not wish to change Oid to string values on any references or associations to User so seems the CodeProject solution mostly deals with this.
Questions:
How do I handle in a single pass changing my User class to be derived from PermissionPolicyUser wihtout requiring a 2nd build version to be deployed after conversion?
What are other considerations of having a custom User class and trying to migrate in ModuleUpdater?
I would also like to copy the password, so it does look like part of the CodeProject example would be of benefit for copying just the user objects, especially since I want to preserve the existing Oid values for user objects (not necessarily for roles/permissions) as there are many objects that reference this.
Making some progress. I was able to get User and SystemSecurityUser to convert to PermissionPolicyUser and handle all the references…
However, when it gets to the CopyUser loop, no objects are returned in ObjectSpace.GetObjects<SecuritySystemUser>() even though there is still data there. I don't get any errors and looking at SQL profiler, nothing is hitting the database.
// UpdateDatabaseBeforeUpdateSchema public override void UpdateDatabaseBeforeUpdateSchema() { base.UpdateDatabaseBeforeUpdateSchema(); if (CurrentDBVersion < new Version("1.0.6450.23803") && CurrentDBVersion > new Version("0.0.0.0")) { ExecuteNonQueryCommand("ALTER TABLE AuditDataItemPersistent ALTER COLUMN OldValue Nvarchar(MAX)", true); ExecuteNonQueryCommand("ALTER TABLE AuditDataItemPersistent ALTER COLUMN NewValue Nvarchar(MAX)", true); } if (CurrentDBVersion < new Version("1.0.6612.31390") && CurrentDBVersion > new Version("0.0.0.0")) { // drop constraint so new PermissionPolicyUser table can be created ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[User] DROP CONSTRAINT [FK_User_Oid]", false); // SELECT * INTO temp_User FROM [User] ExecuteNonQueryCommand(@"SELECT * INTO temp_User FROM [User]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[Class] NOCHECK CONSTRAINT [FK_Class_User]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[Client] NOCHECK CONSTRAINT [FK_Client_Staff]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[ClientCase] NOCHECK CONSTRAINT [FK_ClientCase_Counselor]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[ClientViewAudit] NOCHECK CONSTRAINT [FK_ClientViewAudit_User]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[FollowUp] NOCHECK CONSTRAINT [FK_FollowUp_User]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[FollowUp] NOCHECK CONSTRAINT [FK_FollowUp_CompletedBy]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[LoginAudit] NOCHECK CONSTRAINT [FK_LoginAudit_User]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[UsersXLocations] NOCHECK CONSTRAINT [FK_UsersXLocations_Users]", false); // DELETE from [User] ExecuteNonQueryCommand(@"DELETE FROM [User]", false); } }
public override void UpdateDatabaseAfterUpdateSchema() { base.UpdateDatabaseAfterUpdateSchema(); if (CurrentDBVersion < new Version("1.0.6612.31390") && CurrentDBVersion > new Version("0.0.0.0")) { // convert SecuritySystem to PermissionPolicy ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[User] NOCHECK CONSTRAINT [FK_User_Oid]", false); ExecuteNonQueryCommand(@"INSERT INTO PermissionPolicyUser (Oid, UserName, StoredPassword, ChangePasswordOnFirstLogon, IsActive, ObjectType, OptimisticLockField) SELECT Oid, UserName, StoredPassword, ChangePasswordOnFirstLogon, IsActive, ObjectType, OptimisticLockField FROM SecuritySystemUser", false); ExecuteNonQueryCommand(@"INSERT INTO [User] SELECT * from temp_User", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[User] CHECK CONSTRAINT [FK_User_Oid]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[Class] CHECK CONSTRAINT [FK_Class_User]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[Client] CHECK CONSTRAINT [FK_Client_Staff]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[ClientCase] CHECK CONSTRAINT [FK_ClientCase_Counselor]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[ClientViewAudit] CHECK CONSTRAINT [FK_ClientViewAudit_User]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[FollowUp] CHECK CONSTRAINT [FK_FollowUp_User]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[FollowUp] CHECK CONSTRAINT [FK_FollowUp_CompletedBy]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[LoginAudit] CHECK CONSTRAINT [FK_LoginAudit_User]", false); ExecuteNonQueryCommand(@"ALTER TABLE [dbo].[UsersXLocations] CHECK CONSTRAINT [FK_UsersXLocations_Users]", false); ExecuteNonQueryCommand(@"DROP TABLE temp_User", false); // HERE IS THE PROBLEM: NOTHING FOUND IN .GetObjects() for the old types foreach (SecuritySystemUser securitySystemUser in ObjectSpace.GetObjects<SecuritySystemUser>()) { CopyUser(securitySystemUser); } foreach (SecuritySystemRole securitySystemRole in ObjectSpace.GetObjects<SecuritySystemRole>()) { CopyRole(securitySystemRole, null); } ObjectSpace.CommitChanges(); } }
I even added this to my module constructor (although I don't believe it's needed)
AdditionalExportedTypes.AddRange(new Type[] { typeof(SecuritySystemUser), typeof(SecuritySystemRole) });
So I can log in and I see that it's using the new PermissionPolicyUser object, but I have no roles or permissions
@Randy Jean: I've created a separate ticket on your behalf (T604600: Questions on migrating to the PermissionPolicyXXX classes from SecuritySystemXXX ones). It has been placed in our processing queue and we will answer it as soon as we can.