unit UserProfile;

interface
uses
  Controls,
  SysUtils,
  Dialogs;

type
  PAccessRuleRec =^ TAccessRuleRec;
  TAccessRuleRec = record
    places: string;
    expr: string;
    access: boolean;
//    lastres: Integer;  // 0 - no h
  end;

  TAccessRules = array of PAccessRuleRec;

  TUserProfile = class
    private
      rules: array of TAccessRules;

      procedure addRule(group: Integer; places, expr: string; access: boolean);
      function getCardConfirmation(action: string): boolean;
    public
      id: Integer;
      name: string;
      descr: string;
      place: string;
      password: string;
      cardcode: string;

      cardConfirmList: array of string;
      noCardConfirm: Boolean;

      procedure addGroup;
      procedure addRuleIntoLastGroup(places: string; expr: string; access: boolean);
      procedure addRuleIntoAllGroups(places: string; expr: string; access: boolean);
      procedure clearRules;

      function isPermitted(action: string; showmsg: Boolean = true; dontUseCard: Boolean = false): boolean;
      function isPermittedNoMessage(action: string; showmsg: Boolean = true): boolean;      

      constructor create;
      destructor destroy; override;

      function getProfileStr: string;

  end;


implementation
uses
  infodlg,
  UserConfirmation,
  UserControlEx,
  logger,
  Numbers,
  HyperStr;

{ TUserProfile }

constructor TUserProfile.create;
begin
  id := -1; // unknown user
end;

destructor TUserProfile.destroy;
begin
  clearRules;
end;

procedure TUserProfile.addGroup;
var
  i: Integer;
begin
  i := Length(rules);
  SetLength( rules, i+1 );
end;

procedure TUserProfile.addRuleIntoAllGroups(places, expr: string;
  access: boolean);
var
  i: Integer;
begin
  if Length(rules) = 0 then
    addGroup;
    
  for i:=0 to Length(rules)-1 do
    addRule(i, places, expr, access);
end;

procedure TUserProfile.addRuleIntoLastGroup(places, expr: string;
  access: boolean);
var
  i: Integer;
begin
  i := Length(rules)-1;
  if i>=0 then
    addRule(i, places, expr, access);
end;

procedure TUserProfile.addRule(group: Integer; places, expr: string;
  access: boolean);
var
  j: Integer;
begin
  j := Length(rules[group]);
  SetLength(rules[group], j+1);
  New( rules[group][j] );
  rules[group][j].places := places;
  rules[group][j].expr := expr;
  rules[group][j].access := access;
end;



procedure TUserProfile.clearRules;
var
  i,j,n: Integer;
begin
  n := Length(rules)-1;
  for i:=0 to n do begin
    for j:=0 to Length(rules[i])-1 do
      Dispose( rules[i][j] );
    rules[i] := nil;
  end;
  rules := nil;
end;

function TUserProfile.isPermittedNoMessage(action: string; showmsg: Boolean = true): boolean;
var
  i,j: Integer;
  hitPlace, hitExpr: Boolean;
begin
  Result := false;
  if modeUserExLog then
    LoggerSaveMessage('Permission request: ' + action);

  if id < 0 then
  begin
    Result := false;
  end
  else
  if id = 0 then
  begin
    Result := true;
  end
  else
  begin
    for i:=0 to Length(rules)-1 do begin
      Result := False;

      for j:=0 to Length(rules[i])-1 do begin

        hitPlace := checkfilter(place, rules[i][j].places);
        hitExpr := checkfilter(action, rules[i][j].expr);
        if (hitPlace) and (hitExpr) then
          Result := rules[i][j].access;
      end;

      if Result then Break;
    end;
  end;

  if not Result then begin
    if showmsg then
      showInfoDlg('Действие запрещено', mtWarning, [mbOK], 0)
  end;

end;


function TUserProfile.isPermitted(action: string; showmsg: Boolean = true; dontUseCard: Boolean = false): boolean;
var
  i,j: Integer;
  hitPlace, hitExpr: Boolean;
begin
  Result := false;
  if modeUserExLog then
    LoggerSaveMessage('Permission request: ' + action);

  if id < 0 then
  begin
    Result := false;
  end
  else
  if id = 0 then
  begin
    Result := true;
  end
  else
  begin
    for i:=0 to Length(rules)-1 do begin
      Result := False;

      for j:=0 to Length(rules[i])-1 do begin

        hitPlace := checkfilter(place, rules[i][j].places);
        hitExpr := checkfilter(action, rules[i][j].expr);
        if (hitPlace) and (hitExpr) then
          Result := rules[i][j].access;
      end;

      if Result then Break;
    end;
  end;

  if not Result then begin
    if showmsg then
      MessageDlg('Действие запрещено', mtWarning, [mbOK], 0)
  end else begin
    if( not dontUseCard ) then
      Result := getCardConfirmation(action);
  end;

end;



function TUserProfile.getCardConfirmation(action: string): boolean;
var
  needToConfirm: Boolean;
  i: Integer;
begin
  Result := false;
  needToConfirm := false;

  if noCardConfirm then begin
    Result := True;
    Exit;
  end;

  for i:=0 to Length(cardConfirmList)-1 do
    if CheckFilter(action, cardConfirmList[i]) then begin
      needToConfirm := true;
      Break;
    end;

  if not needToConfirm then begin
    Result := True;
    Exit;
  end;

//  if cardcode='' then begin
//    MessageDlg('Действие доступно только при входе в систему ЭЛЕКТРОННОЙ КАРТОЙ!', mtWarning, [mbOK], 0);
//    Exit;
//  end;

  with TUserConfirmationForm.Create(nil) do begin
    if ShowModal = mrOk then
      Result := true;
    Free;
  end;

end;














function TUserProfile.getProfileStr: string;
var
  s: string;
  i,j: Integer;
begin
  s :=
      'id: ' + inttostr(id) +
      #13'name: ' + name +
      #13'descr: ' + descr +
      #13'place: ' + place;

  for i:=0 to Length(rules)-1 do begin
    s := s + #13#13;
    for j:=0 to length(rules[i])-1 do
      s := s + iif(rules[i][j].access, 'allow', 'deny') + ' ' + rules[i][j].expr + #13;
  end;

  result := s;
end;

end.


