RecroSec |
Ez a fejezet a RecroGrid Framework jogosultsági modulját, a RecroSec használatát mutatja be.
This topic contains the following sections:
Az alapszintű jogosultsági rendszert, ahol miden egyes RecroGrid hozzáférését globálisan lehet paraméterezni, a RecroSec nagyon jól kiegészíti, mivel többfelhasználós környezetben felhasználónként lehet szabályozni a jogosultságokat.
A RecroSec jogosultsági rendszer három darab adatbázis View-en keresztül képes kapcsolódni bármely típusú felhasználói nyilvántartáshoz. A rendszer a felhasználói nyilvántartást kizárólag olvasásra használja, és egy külön jogosultsági réteg bevezetésével kapcsolja a felhasználókhoz és csoportokhoz a jogosultságokat. A jogosultságokat futásidőben egy online felületen lehet paraméterezni. Az egyes felhasználók a különböző fizikai és logikai objektumokhoz tartozó jogosultsága, az erre kialakított függvénnyel az alkalmazás bármely pontján lekérdezhető, a RecroGrid használata esetén pedig automatikus a kiértékelés.
Definiálni kell az adatbázisban három darab View-t, ami alapján a RecroSec képes felismerni a rendszerben használt felhasználókat és felhasználói csoportokat.
vRecroSec_User -> két karakteres mező: UserId és UserName
vRecroSec_Role -> két karakteres mező: RoleId és RoleName
vRecroSec_UsersInRole -> két karakteres mező: UserId és RoleId
Caution |
---|
Amennyiben a rendszerben használt felhasználói, illetve csoport azonosítók nem karakteresek, akkor azokat a View-ban konvertálni kell. |
Note |
---|
ASP.NET Identity használata esetén ezek a View-k automatikusan létrejönnek. |
Az alkalmazás web.config beállításában az alkalmazásbeállítások alatt a RecroSec szekcióban engedélyezni kell a RecroSec használatát, ami minimálisan három beállítást igényel:
SingleUserMode beállítás legyen false.
AdministratorGroupName beállításban definiálni kell az Adminisztrátori csoportnak a névét.
Definiálni kell egy statikus függvényt, ami visszaadja a aktuális felhasználó azonosítóját, és ennek a függvénynek a elérést meg kell adni a CurrentUserIdProperty beállításban.
<Recrovit.RecroSec> <setting name="Enabled" serializeAs="String"> <!--true eseten minden objektumot paraméterezni kell, egyébként az entitásban lehet jelezni, hogy RecroSec kell--> <value>true</value> </setting> <setting name="SingleUserMode" serializeAs="String"> <value>true</value> </setting> <setting name="AdministratorGroupName" serializeAs="String"> <value>Administrators</value> </setting> <setting name="CacheMode" serializeAs="String"> <!--Process, RGCache, Disable--> <value>Process</value> </setting> <setting name="AnonymousId" serializeAs="String"> <value>Anonymous</value> </setting> <setting name="CurrentUserId" serializeAs="String"> <!--e.g. ApplicationUserManager -> public static string GetCurrentUserId(HttpContext context) { return context.User.Identity.GetUserId(); }--> <value>GetCurrentUserId,RGFDemo.ApplicationUserManager,RGFDemo</value> </setting> <!--<setting name="VirtualUserId" serializeAs="String"> <value>GetVirtualUserId,RGFDemo.ApplicationUserManager,RGFDemo</value> </setting>--> </Recrovit.RecroSec>
Tip |
---|
A beállításokat az alkalmazásban is lehet definiálni (lásd RecroSec properties), így biztosítva, hogy ne lehessen jogosultsági rendszert kikapcsolni. |
Ha a RecroSec a web.config beállításában engedélyezett, akkor alapértelmezés szerint minden RecroGrid az entitás nevéhez tartozó logikai objektum jogosultsági beállításait használja. Ha az nem definiált, vagy az entitás RGO_RecroSec opciós beállítás false, akkor az adminisztrátor kivételével senkinek nem lesz hozzá jogosultsága. Ha az RGO_RecroSec opciós beállítás értéke true, akkor a entitás neve, vagy egyéb esetben a meghatározott logikai objektum alapján keresi a jogosultságot, függetlenül a globális RecroSec engedélyezéstől.
Ha a fentiek alapján a jogosultság ellenőrzése engedélyezett, akkor a RecroGrid alapértelmezés szerint a List nézetben entitás (tábla), Form nézetben pedig rekord szinten figyeli a jogosultságot. Az RGO_RecroSecLevel opciós beállítás segítségével ez megváltoztatható:
Ha a beállítás tartalmazza a Row kulcsszót, akkor List nézetben is rekordonként figyeli a jogosultságot.
Ha a beállítás tartalmazza a Column kulcsszót, akkor List, és Form nézetben is oszloponként figyeli a jogosultságot.
További lehetőség, ha csak néhány oszlopra kell (vagy nem kell) figyelni a jogosultságot, akkor azt a mezőhöz definiált RGO_RecroSec opciós beállítással lehet megadni:
Ha értéke true, akkor entitáshoz kapcsolt RGO_RecroSec/Alias alapján figyeli a jogosultságot.
Note |
---|
RGO_RecroSec a fent leírtak szerint, Alias pedig a mező Alias azonosítója. |
Ha értéke false, akkor nem figyeli a jogosultságot.
Egyéb esetben a meghatározott logikai objektumhoz kapcsolt jogosultságot figyeli.
Tip |
---|
Ha ugyanazon feltétel alapján több mezőt is lehet figyelni, akkor ugyanahhoz a logikai objektumhoz több mezőt is hozzá lehet kapcsolni. |
Ha az RGO_RecroSecLevel opciós beállításban a rekord szintű jogosultság engedélyezve van, akkor List nézetben a rendszer már az SQL adatlekérdezésben hozzákapcsolja az aktuális entitáshoz a RecroSec-ben definiált logikai objektumokat a rekordok kulcsa alapján, hogy ne keljen ezt rekordonként egyesével megtenni. A lekérdezést optimalizálni lehet, ha az entitás mezői között (vagy akár már adatbázis szinten) szerepel az a mező, ahol az Alias ObjectPermissionId.
//ColName ESQL:(case when {0}.discontinued=true then 2 else 1 end) //Alias ObjectPermissionId
Bonyolultabb esetben szükség lehet szerveroldalon befolyásolni a jogosultság kiértékelését, amit a GetPermissions(String, String, Object, NullableInt32) virtuális metódus megvalósításával lehet elvégezni.
protected override UserPermissions GetPermissions(string objectName, string objectKey = null, object dataRec = null, int? objectPermissionId = null) { if (objectName.IndexOf("/") == -1) { if (dataRec is Products && ((Products)dataRec).Discontinued) { //Jogosultság lekérése a paraméterezésből a objectPermissionId=2 szerint return RecroSec.GetPermissionsForUser(this.RecroGridContext.GetCurrentUserId(), objectName, objectKey, dataRec, 2); //Közvetlen jogosultság megadása aktuális felhasználó szerint //if (RecroSec.CurrentUserId == ...) { //return new UserPermissions("R"); } } else if (dataRec is RGClientColumn[]) { RGClientColumn[] clientRec = (RGClientColumn[])dataRec; var discontinued = clientRec.SingleOrDefault(r => r.Property.Alias.Equals("discontinued", StringComparison.InvariantCultureIgnoreCase)); if (discontinued != null && ((bool)discontinued.DbValue)) { //Jogosultság lekérése a paraméterezésből a objectPermissionId=2 szerint return RecroSec.GetPermissionsForUser(this.RecroGridContext.GetCurrentUserId(), objectName, objectKey, dataRec, 2); //Közvetlen jogosultság megadása aktuális felhasználó szerint //if (RecroSec.CurrentUserId == ...) { //return new UserPermissions(""); } } } } return base.GetPermissions(objectName, objectKey, dataRec, objectPermissionId); }
Tip |
---|
Szükség esetén az RG_Self Entity típusú mező definiálásával, List nézetben is (a megjelenítendő mezőktől függetlenül) beolvasásra kerül a teljes rekord. |
A jogosultságok végső eredményét befolyásolni lehet egy elő- és egy utófeldolgozási lépésben.
Előfeldolgozás esetén módosítani lehet, hogy melyik logikai objektumhoz kapcsolt jogosultságot kell használni. A lehetőségek a következők:
Az aktuális típusos rekord IRecroSecPreprocessing interface alapján.
Logikai objektumhoz kapcsolódó Preprocessing metódus a paraméterezés alapján.
Logikai objektumhoz kapcsolódó PreprocessingTSQL SQL procedure a paraméterezés alapján.
Utófeldolgozás esetén az aktuális felhasználó végső jogosultságait lehet módosítani az aktuális objektumhoz. A lehetőségek a következők:
Az aktuális típusos rekord IRecroSecPostprocessing interface alapján.
Logikai objektumhoz kapcsolódó Postprocessing metódus a paraméterezés alapján
Logikai objektumhoz kapcsolódó PostprocessingTSQL SQL procedure a paraméterezés alapján.
Tip |
---|
Ha kód szinten kell módosítani a jogosultságot, akkor javasolt inkább az előfeldolgozások választása (és esetleges új logikai objektumok létrehozása), mert akkor megmarad a felhasználónkénti online paraméterezhető lehetőség. |
public partial class Products : IRecroSecPreprocessing, IRecroSecPostprocessing { //IRecroSecPreprocessing public int? RecroSecPreprocessing(RecroSecProcessingParam param) { if (param.ObjectName.IndexOf("/") == -1 && this.Discontinued) { return 2; } return param.ObjectPermissionId; } //IRecroSecPostprocessing public void RecroSecPostprocessing(RecroSecProcessingParam param, UserPermissions permissions) { if (param.ObjectName.IndexOf("/") == -1 && this.Discontinued /*&& param.UserId == ...*/) { //permissions.CRUD = "R"; } } }
if (objectName.IndexOf("/") == -1) { if (dataRec is RGClientColumn[]) { RGClientColumn[] clientRec = (RGClientColumn[])dataRec; var self = clientRec.SingleOrDefault(r => r.Property.Alias.Equals("RG_Self", StringComparison.InvariantCultureIgnoreCase)); if (self != null && self.DbValue is Products) { var product = self.DbValue as Products; RecroSecProcessingParam param = new RecroSecProcessingParam(objectName, objectKey, product, objectPermissionId); //Jogosultság maghatározása IRecroSecPreprocessing interface alapján objectPermissionId = product.RecroSecPreprocessing(param); return RecroSec.GetPermissions(objectName, objectKey, dataRec, objectPermissionId); //Közvetlen jogosultság megadása IRecroSecPostprocessing interface alapján //UserPermissions permissions = base.GetPermissions(objectName, objectKey, dataRec, objectPermissionId); //product.RecroSecPostprocessing(param, permissions); //return permissions; } } }
public partial class Products { public static int Preprocessing(RecroSecProcessingParam param) { object dataRec = param.Target; if (param.ObjectName.IndexOf("/") == -1) { if (dataRec is Products && ((Products)dataRec).Discontinued) { return 2; } if (dataRec is RecroGrid.RGClientColumn[]) { var clientRec = (RecroGrid.RGClientColumn[])dataRec; var discontinued = clientRec.SingleOrDefault(r => r.Property.Alias.Equals("discontinued", StringComparison.InvariantCultureIgnoreCase)); if (discontinued != null && ((bool)discontinued.DbValue)/*&& param.UserId == ...*/) { return 2; } } } return param.ObjectPermissionId; } public static void Postprocessing(RecroSecProcessingParam param, UserPermissions permissions) { object dataRec = param.Target; if (param.ObjectName.IndexOf("/") == -1) { if (dataRec is Products && ((Products)dataRec).Discontinued/*&& param.UserId == ...*/) { //permissions.CRUD = "R"; } if (dataRec is RecroGrid.RGClientColumn[]) { var clientRec = (RecroGrid.RGClientColumn[])dataRec; var discontinued = clientRec.SingleOrDefault(r => r.Property.Alias.Equals("discontinued", StringComparison.InvariantCultureIgnoreCase)); if (discontinued != null && ((bool)discontinued.DbValue)/*&& param.UserId == ...*/) { //permissions.CRUD = ""; } } } } }
A beállított jogosultságok az alkalmazás bármely pontján a RecroSec GetPermissions(String, String, Object, NullableInt32) metódus segítségével egyszerűen lekérdezhetők.
public partial class RG_Product : RecroGridDBC<Products, AdventureWorksDBContext> { public RG_Product(IRecroGridContext rgContext) : base(rgContext, new AdventureWorksDBContext()) { RGCustomMenu menu = new RGCustomMenu(); menu.AddItem("Permission", "perm"); menu.AddItemGlobal("Egyedi", "egyedi"); this.RGOptions["RGO_CustomMenu"] = menu; } protected override Task<bool> OnCustomFunction(RecroTrack tracking, ref Products dataRec, CustomFunctionEventArgs args, RGUIMessages messages) { if (dataRec != null) { switch (args.FunctionName) { case "perm": var permission = RecroSec.GetPermissionsForUser(tracking.UserId, "RG_Product", null, dataRec); messages.AddInfo(permission.CRUD); break; } } switch (args.FunctionName) { case "egyedi": var permission1 = RecroSec.GetPermissionsForUser(tracking.UserId, "RG_Product", null, dataRec); messages.AddInfo(permission1.GetPermission("egyedi1") ? "van joga" : "nincs joga"); break; } return base.OnCustomFunction(tracking, ref dataRec, args, messages); } }