source upload
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
unit uCustomer;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SynCommons,
|
||||
mORMot;
|
||||
|
||||
type
|
||||
TSQLTasks = class;
|
||||
|
||||
TSQLPerson = class(TSQLRecord)
|
||||
private
|
||||
fFirstname, fSurname: RawUTF8;
|
||||
published
|
||||
property FirstName: RawUTF8 read fFirstname write fFirstname;
|
||||
property Surname: RawUTF8 read fSurname write fSurname;
|
||||
end;
|
||||
|
||||
TSQLCustomer = class(TSQLPerson)
|
||||
private
|
||||
fTasks: TSQLTasks;
|
||||
published
|
||||
property Tasks: TSQLTasks read fTasks;
|
||||
end;
|
||||
|
||||
TSQLTaskPriority = (tpLow, tpNormal, tpHigh);
|
||||
TSQLTask = class(TSQLRecord)
|
||||
private
|
||||
fPriority: TSQLTaskPriority;
|
||||
fText: RawUTF8;
|
||||
published
|
||||
property Priority: TSQLTaskPriority read fPriority write fPriority;
|
||||
property Text: RawUTF8 read fText write fText;
|
||||
end;
|
||||
|
||||
TSQLTasks = class(TSQLRecordMany)
|
||||
private
|
||||
fSource: TSQLCustomer;
|
||||
fDest: TSQLTask;
|
||||
published
|
||||
property Source: TSQLCustomer read fSource;
|
||||
property Dest: TSQLTask read fDest;
|
||||
end;
|
||||
|
||||
TSQLUser = class;
|
||||
TSQLUserRole = class(TSQLRecord)
|
||||
private
|
||||
fRoleName: RawUTF8;
|
||||
public
|
||||
// create standard roles: admin & user
|
||||
class procedure CreateStandardRoles(const ADatabase: TSQLRest);
|
||||
published
|
||||
property RoleName: RawUTF8 read fRoleName write fRoleName;
|
||||
end;
|
||||
|
||||
TSQLUserRoles = class(TSQLRecordMany)
|
||||
private
|
||||
fValidUntil: TTimeLog;
|
||||
fSource: TSQLUser;
|
||||
fDest: TSQLUserRole;
|
||||
published
|
||||
property ValidUntil: TTimeLog read fValidUntil write fValidUntil;
|
||||
property Dest: TSQLUserRole read fDest;
|
||||
property Source: TSQLUser read fSource;
|
||||
end;
|
||||
|
||||
// user of our system
|
||||
TSQLUser = class(TSQLPerson)
|
||||
private
|
||||
fRoles: TSQLUserRoles;
|
||||
fLogin, fPassword: RawUTF8;
|
||||
procedure SetPassword(const APwd: RawUTF8);
|
||||
public
|
||||
function HasRole(const ARoleName: RawUTF8; const ARoleID: integer = -1): boolean; overload;
|
||||
// returned aRowID is an ID of row in PIVOT TABLE !!!
|
||||
// so that we can access additional data stored in pivot connection
|
||||
function HasRole(const ARoleName: RawUTF8; const ARoleID: integer; var ARowID: integer): boolean; overload;
|
||||
// returns 0 on fail, UserID on success
|
||||
class function SignIn(const ALogin, APassword: RawUTF8): Integer;
|
||||
published
|
||||
property Roles: TSQLUserRoles read fRoles write fRoles;
|
||||
property Login: RawUTF8 read fLogin write fLogin;
|
||||
property Password: RawUTF8 read fPassword write SetPassword;
|
||||
end;
|
||||
|
||||
function CreateSampleModel: TSQLModel;
|
||||
procedure InitClient();
|
||||
|
||||
var
|
||||
globalClient: TSQLRestClientURI;
|
||||
currentUser: TSQLUser;
|
||||
model: TSQLModel;
|
||||
|
||||
implementation
|
||||
|
||||
uses SysUtils, uQueryHistory, SynCrypto, mORMotSQLite3, Forms;
|
||||
|
||||
|
||||
procedure InitClient();
|
||||
begin
|
||||
Model:= CreateSampleModel;
|
||||
globalClient:= TSQLRestClientDB.Create(Model, CreateSampleModel, ChangeFileExt(Application.ExeName,'.db3'), TSQLRestServerDB);
|
||||
TSQLRestClientDB(globalClient).Server.CreateMissingTables;
|
||||
end;
|
||||
|
||||
function CreateSampleModel: TSQLModel;
|
||||
begin
|
||||
result := TSQLModel.Create([TSQLCustomer, TSQLTask, TSQLTasks, TSQLQueryHistory, TSQLUser, TSQLUserRole, TSQLUserRoles]);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
class procedure TSQLUserRole.CreateStandardRoles(const ADatabase: TSQLRest);
|
||||
const
|
||||
names: array [0..1] of RawUTF8 = ( 'user', 'admin' );
|
||||
var
|
||||
i: integer;
|
||||
role: TSQLUserRole;
|
||||
begin
|
||||
for i:= low(names) to high(names) do
|
||||
begin
|
||||
role:= TSQLUserRole.Create(ADatabase, 'RoleName = ?', [names[i]]);
|
||||
try
|
||||
// if the role isn't present yet
|
||||
if role.ID = 0 then
|
||||
begin
|
||||
role.RoleName:= names[i];
|
||||
ADatabase.Add(role, true);
|
||||
end
|
||||
finally
|
||||
FreeAndNil(role);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TSQLUser.SetPassword(const APwd: RawUTF8);
|
||||
begin
|
||||
fPassword:= SynCrypto.MD5(APwd);
|
||||
end;
|
||||
|
||||
|
||||
class function TSQLUser.SignIn(const ALogin, APassword: RawUTF8): Integer;
|
||||
var
|
||||
usr: TSQLUser;
|
||||
begin
|
||||
result:= 0;
|
||||
usr:= TSQLUser.Create(globalClient, '(User.Login = ? AND User.Password = ?)', [ALogin, SynCrypto.MD5(APassword)]);
|
||||
try
|
||||
result:= usr.ID;
|
||||
// check if is not expired
|
||||
if not usr.HasRole('user') then
|
||||
result:= 0
|
||||
else
|
||||
currentUser:= usr;
|
||||
finally
|
||||
if result = 0 then // if no valid user found, free it. otherwise we'll keep it until application end.
|
||||
FreeAndNil(usr);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSQLUser.HasRole(const ARoleName: RawUTF8; const ARoleID: integer = -1): boolean;
|
||||
var
|
||||
dummy: integer;
|
||||
begin
|
||||
result:= HasRole(ARoleName, ARoleID, dummy);
|
||||
end;
|
||||
|
||||
|
||||
|
||||
function TSQLUser.HasRole(const ARoleName: RawUTF8; const ARoleID: integer; var ARowID: integer): boolean;
|
||||
var
|
||||
role: TSQLUserRole;
|
||||
begin
|
||||
result:= false;
|
||||
ARowID:= -1;
|
||||
// we want the RowID anyway, so skip that part: 'UserRoles.ValidUntil <= date(''now'')'
|
||||
fRoles.FillMany(globalClient, fID);
|
||||
|
||||
// loop through the roles
|
||||
while fRoles.FillOne do
|
||||
begin
|
||||
if fRoles.Dest <> nil then
|
||||
try
|
||||
role:= TSQLUserRole.Create(globalClient, fRoles.Dest.ID);
|
||||
if ((ARoleID = -1) and (role.RoleName = ARoleName)) or ((ARoleID > -1) and (role.ID = ARoleID) ) then
|
||||
begin
|
||||
// if using "admin" account, role validity doesn't expire.
|
||||
if fLogin <> 'admin' then
|
||||
result:= fRoles.ValidUntil >= TimeLogNow()
|
||||
else
|
||||
result:= true;
|
||||
ARowID:= fRoles.ID;
|
||||
break;
|
||||
end;
|
||||
finally
|
||||
FreeAndNil(role);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
initialization
|
||||
currentUser:= nil;
|
||||
finalization
|
||||
FreeAndNil(globalClient);
|
||||
FreeAndNil(model);
|
||||
FreeAndNil(currentUser);
|
||||
|
||||
end.
|
Reference in New Issue
Block a user