Commit 30fc30ba by Mac Stephens

Time entries startup added, wip

parent 77fd1936
...@@ -24,7 +24,7 @@ type ...@@ -24,7 +24,7 @@ type
constructor Create; reintroduce; constructor Create; reintroduce;
destructor Destroy; override; destructor Destroy; override;
procedure Login(AUserId, ATaskId, AUrlCode: string; ASuccess: TOnLoginSuccess; AError: TOnLoginError); procedure Login(AUserId, ATaskId, AUrlCode: string; ASuccess: TOnLoginSuccess; AError: TOnLoginError);
[async] procedure WebLogin(AUserName, ATaskId, APassword: string; ASuccess: TOnLoginSuccess; AError: TOnLoginError); [async] procedure WebLogin(AUserName, ALoginType, ALoginValue, APassword: string; ASuccess: TOnLoginSuccess; AError: TOnLoginError);
procedure Logout; procedure Logout;
function GetToken: string; function GetToken: string;
function Authenticated: Boolean; function Authenticated: Boolean;
...@@ -122,8 +122,7 @@ begin ...@@ -122,8 +122,7 @@ begin
end; end;
[async] procedure TAuthService.WebLogin(AUserName, ATaskId, APassword: string; ASuccess: TOnLoginSuccess; [async] procedure TAuthService.WebLogin(AUserName, ALoginType, ALoginValue, APassword: string; ASuccess: TOnLoginSuccess; AError: TOnLoginError);
AError: TOnLoginError);
var var
sha: TWebSHAHash; sha: TWebSHAHash;
passwordHash: string; passwordHash: string;
...@@ -143,9 +142,9 @@ var ...@@ -143,9 +142,9 @@ var
end; end;
begin begin
if (AUserName = '') or (ATaskId = '') or (APassword = '') then if (AUserName = '') or (ALoginType = '') or (ALoginValue = '') or (APassword = '') then
begin begin
AError('Please enter user id, task id, and password.'); AError('Please enter all required login fields.');
Exit; Exit;
end; end;
...@@ -157,7 +156,7 @@ begin ...@@ -157,7 +156,7 @@ begin
end; end;
FClient.RawInvoke( FClient.RawInvoke(
'IAuthService.WebLogin', [AUserName, ATaskId, passwordHash], 'IAuthService.WebLogin', [AUserName, ALoginType, ALoginValue, passwordHash],
@OnLoad, @OnError @OnLoad, @OnError
); );
end; end;
......
...@@ -21,7 +21,7 @@ object FViewLogin: TFViewLogin ...@@ -21,7 +21,7 @@ object FViewLogin: TFViewLogin
end end
object edtUsername: TWebEdit object edtUsername: TWebEdit
Left = 240 Left = 240
Top = 160 Top = 180
Width = 121 Width = 121
Height = 21 Height = 21
ElementID = 'view.login.edtusername' ElementID = 'view.login.edtusername'
...@@ -31,7 +31,7 @@ object FViewLogin: TFViewLogin ...@@ -31,7 +31,7 @@ object FViewLogin: TFViewLogin
end end
object edtPassword: TWebEdit object edtPassword: TWebEdit
Left = 240 Left = 240
Top = 187 Top = 207
Width = 121 Width = 121
Height = 21 Height = 21
ElementID = 'view.login.edtpassword' ElementID = 'view.login.edtpassword'
...@@ -43,7 +43,7 @@ object FViewLogin: TFViewLogin ...@@ -43,7 +43,7 @@ object FViewLogin: TFViewLogin
end end
object btnLogin: TWebButton object btnLogin: TWebButton
Left = 240 Left = 240
Top = 214 Top = 234
Width = 121 Width = 121
Height = 25 Height = 25
Caption = 'Login' Caption = 'Login'
...@@ -92,6 +92,18 @@ object FViewLogin: TFViewLogin ...@@ -92,6 +92,18 @@ object FViewLogin: TFViewLogin
TextHint = 'TaskId' TextHint = 'TaskId'
WidthPercent = 100.000000000000000000 WidthPercent = 100.000000000000000000
end end
object edtDate: TWebEdit
Left = 240
Top = 156
Width = 121
Height = 22
ChildOrder = 6
ElementID = 'view.login.edtdate'
ElementFont = efCSS
HeightPercent = 100.000000000000000000
TextHint = 'Date'
WidthPercent = 100.000000000000000000
end
object XDataWebClient: TXDataWebClient object XDataWebClient: TXDataWebClient
Connection = DMConnection.AuthConnection Connection = DMConnection.AuthConnection
Left = 492 Left = 492
......
<nav class="navbar navbar-light bg-light login-navbar"> <nav class="navbar navbar-light bg-light login-navbar">
<div class="container-fluid"> <div class="container-fluid">
<a class="navbar-brand" href="#">Envoy Calls</a> <a class="navbar-brand" href="#">emT3web</a>
</div> </div>
</nav> </nav>
<div class="container mt-5"> <div class="container mt-5">
...@@ -17,8 +17,11 @@ ...@@ -17,8 +17,11 @@
<span id="view.login.message.label"></span> <span id="view.login.message.label"></span>
</div> </div>
<fieldset> <fieldset>
<div class="mb-3"> <div id="view.login.taskid.group" class="mb-3">
<input id="view.login.edttaskid" class="form-control" type="text" autofocus placeholder="Task Id"> <input id="view.login.edttaskid" class="form-control" type="text" placeholder="Task Id">
</div>
<div id="view.login.date.group" class="mb-3">
<input id="view.login.edtdate" class="form-control" type="date" placeholder="Date">
</div> </div>
<div class="mb-3"> <div class="mb-3">
<input id="view.login.edtusername" class="form-control" type="text" autofocus placeholder="Username"> <input id="view.login.edtusername" class="form-control" type="text" autofocus placeholder="Username">
......
...@@ -19,6 +19,7 @@ type ...@@ -19,6 +19,7 @@ type
btnCloseNotification: TWebButton; btnCloseNotification: TWebButton;
XDataWebClient: TXDataWebClient; XDataWebClient: TXDataWebClient;
edtTaskId: TWebEdit; edtTaskId: TWebEdit;
edtDate: TWebEdit;
procedure btnLoginClick(Sender: TObject); procedure btnLoginClick(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject); procedure btnCloseNotificationClick(Sender: TObject);
procedure WebFormCreate(Sender: TObject); procedure WebFormCreate(Sender: TObject);
...@@ -47,10 +48,16 @@ uses ...@@ -47,10 +48,16 @@ uses
{$R *.dfm} {$R *.dfm}
procedure TFViewLogin.btnLoginClick(Sender: TObject); procedure TFViewLogin.btnLoginClick(Sender: TObject);
var
timeEntriesParam: string;
procedure LoginSuccess; procedure LoginSuccess;
begin begin
DMConnection.currentTaskId := edtTaskId.Text; if SameText(timeEntriesParam, 'true') then
DMConnection.currentTaskId := ''
else
DMConnection.currentTaskId := edtTaskId.Text;
FLoginProc; FLoginProc;
end; end;
...@@ -60,11 +67,30 @@ procedure TFViewLogin.btnLoginClick(Sender: TObject); ...@@ -60,11 +67,30 @@ procedure TFViewLogin.btnLoginClick(Sender: TObject);
end; end;
begin begin
AuthService.WebLogin( timeEntriesParam := Application.Parameters.Values['time_entries'];
edtUsername.Text, edtTaskId.Text, edtPassword.Text,
@LoginSuccess, if SameText(timeEntriesParam, 'true') then
@LoginError begin
); AuthService.WebLogin(
edtUsername.Text,
'time_entries',
edtDate.Text,
edtPassword.Text,
@LoginSuccess,
@LoginError
);
end
else
begin
AuthService.WebLogin(
edtUsername.Text,
'task_items',
edtTaskId.Text,
edtPassword.Text,
@LoginSuccess,
@LoginError
);
end;
end; end;
class procedure TFViewLogin.Display(LoginProc: TSuccessProc); class procedure TFViewLogin.Display(LoginProc: TSuccessProc);
...@@ -110,14 +136,29 @@ begin ...@@ -110,14 +136,29 @@ begin
end; end;
procedure TFViewLogin.WebFormCreate(Sender: TObject); procedure TFViewLogin.WebFormCreate(Sender: TObject);
var
timeEntriesParam: string;
begin begin
console.log('TFViewLogin.WebFormCreate FUserId=' + FUserId + ' FTaskId=' + FTaskId + ' FMessage=' + FMessage); console.log('TFViewLogin.WebFormCreate FUserId=' + FUserId + ' FTaskId=' + FTaskId + ' FMessage=' + FMessage);
console.log('TFViewLogin.WebFormCreate URL task_id=' + Application.Parameters.Values['task_id']);
edtUsername.Text := ''; timeEntriesParam := Application.Parameters.Values['time_entries'];
edtTaskId.Text := Application.Parameters.Values['task_id'];
edtUsername.Text := FUserId;
edtTaskId.Text := FTaskId;
edtDate.Text := Application.Parameters.Values['date'];
console.log('TFViewLogin.WebFormCreate after assign edtUsername=' + edtUsername.Text + ' edtTaskId=' + edtTaskId.Text); if SameText(timeEntriesParam, 'true') then
begin
WebLabel1.Caption := 'Time Entries Sign In';
TJSHTMLElement(document.getElementById('view.login.taskid.group')).classList.add('d-none');
TJSHTMLElement(document.getElementById('view.login.date.group')).classList.remove('d-none');
end
else
begin
WebLabel1.Caption := 'Task Items Sign In';
TJSHTMLElement(document.getElementById('view.login.taskid.group')).classList.remove('d-none');
TJSHTMLElement(document.getElementById('view.login.date.group')).classList.add('d-none');
end;
if FMessage <> '' then if FMessage <> '' then
ShowNotification(FMessage) ShowNotification(FMessage)
......
...@@ -35,7 +35,8 @@ implementation ...@@ -35,7 +35,8 @@ implementation
uses uses
Auth.Service, Auth.Service,
View.TaskItems; View.TaskItems,
View.TimeEntries;
{$R *.dfm} {$R *.dfm}
...@@ -47,7 +48,16 @@ begin ...@@ -47,7 +48,16 @@ begin
lblUsername.Caption := userName; lblUsername.Caption := userName;
lblVersion.Caption := 'v' + DMConnection.clientVersion; lblVersion.Caption := 'v' + DMConnection.clientVersion;
ShowForm(TFTaskItems); if SameText(Application.Parameters.Values['time_entries'], 'true') then
begin
lblAppTitle.Caption := 'Time Entries';
ShowForm(TFTimeEntries);
end
else
begin
lblAppTitle.Caption := 'Task Items';
ShowForm(TFTaskItems);
end;
end; end;
procedure TFViewMain.lblLogoutClick(Sender: TObject); procedure TFViewMain.lblLogoutClick(Sender: TObject);
......
...@@ -1436,6 +1436,7 @@ begin ...@@ -1436,6 +1436,7 @@ begin
await(SaveField(ARowIndex, AFieldName)); await(SaveField(ARowIndex, AFieldName));
end; end;
[async] procedure TFTaskItems.HandleRenameManagedName(const AFieldName, AOldName, ANewName: string); [async] procedure TFTaskItems.HandleRenameManagedName(const AFieldName, AOldName, ANewName: string);
var var
newOptions: TJSArray; newOptions: TJSArray;
......
object FTimeEntries: TFTimeEntries
Width = 640
Height = 480
ElementFont = efCSS
end
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>TMS Web Project</title>
<style>
</style>
</head>
<body>
</body>
</html>
\ No newline at end of file
unit View.TimeEntries;
interface
uses
System.SysUtils, System.Classes, JS, Web, WEBLib.Graphics, WEBLib.Controls,
WEBLib.Forms, WEBLib.Dialogs;
type
TFTimeEntries = class(TWebForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
FTimeEntries: TFTimeEntries;
implementation
{$R *.dfm}
end.
\ No newline at end of file
...@@ -2,6 +2,7 @@ program emT3Web; ...@@ -2,6 +2,7 @@ program emT3Web;
uses uses
System.Classes, System.Classes,
System.SysUtils,
Vcl.Forms, Vcl.Forms,
XData.Web.Connection, XData.Web.Connection,
WEBLib.Dialogs, WEBLib.Dialogs,
...@@ -15,7 +16,8 @@ uses ...@@ -15,7 +16,8 @@ uses
uNameOffCanvas in 'uNameOffCanvas.pas', uNameOffCanvas in 'uNameOffCanvas.pas',
uDropdownHelpers in 'uDropdownHelpers.pas', uDropdownHelpers in 'uDropdownHelpers.pas',
View.Login in 'View.Login.pas' {FViewLogin: TWebForm} {*.html}, View.Login in 'View.Login.pas' {FViewLogin: TWebForm} {*.html},
View.ErrorPage in 'View.ErrorPage.pas' {FViewErrorPage: TWebForm} {*.html}; View.ErrorPage in 'View.ErrorPage.pas' {FViewErrorPage: TWebForm} {*.html},
View.TimeEntries in 'View.TimeEntries.pas' {FTimeEntries: TWebForm} {*.html};
{$R *.res} {$R *.res}
...@@ -76,7 +78,16 @@ var ...@@ -76,7 +78,16 @@ var
userIdParam: string; userIdParam: string;
taskIdParam: string; taskIdParam: string;
codeParam: string; codeParam: string;
timeEntriesParam: string;
begin begin
timeEntriesParam := Application.Parameters.Values['time_entries'];
if SameText(timeEntriesParam, 'true') then
begin
DisplayLoginView('', '', '');
Exit;
end;
userIdParam := Application.Parameters.Values['user_id']; userIdParam := Application.Parameters.Values['user_id'];
taskIdParam := Application.Parameters.Values['task_id']; taskIdParam := Application.Parameters.Values['task_id'];
codeParam := Application.Parameters.Values['url_code']; codeParam := Application.Parameters.Values['url_code'];
...@@ -101,22 +112,29 @@ procedure DoLogout(AMsg: string); ...@@ -101,22 +112,29 @@ procedure DoLogout(AMsg: string);
var var
userIdParam: string; userIdParam: string;
taskIdParam: string; taskIdParam: string;
timeEntriesParam: string;
begin begin
AuthService.Logout; AuthService.Logout;
timeEntriesParam := Application.Parameters.Values['time_entries'];
if SameText(timeEntriesParam, 'true') then
begin
DisplayLoginView('', '', AMsg);
Exit;
end;
userIdParam := Application.Parameters.Values['user_id']; userIdParam := Application.Parameters.Values['user_id'];
taskIdParam := Application.Parameters.Values['task_id']; taskIdParam := Application.Parameters.Values['task_id'];
DisplayLoginView(userIdParam, taskIdParam); DisplayLoginView(userIdParam, taskIdParam, AMsg);
end; end;
procedure UnauthorizedAccessProc(AMessage: string); procedure UnauthorizedAccessProc(AMessage: string);
begin begin
ShowAppDialog('UnauthorizedAccessProc: ' + AMessage); ShowAppDialog('UnauthorizedAccessProc: ' + AMessage);
end; end;
procedure StartApplication; procedure StartApplication;
var var
ClientVer: string; ClientVer: string;
......
...@@ -140,19 +140,20 @@ ...@@ -140,19 +140,20 @@
<DCCReference Include="Utils.pas"/> <DCCReference Include="Utils.pas"/>
<DCCReference Include="View.TaskItems.pas"> <DCCReference Include="View.TaskItems.pas">
<Form>FTaskItems</Form> <Form>FTaskItems</Form>
<FormType>dfm</FormType>
<DesignClass>TWebForm</DesignClass> <DesignClass>TWebForm</DesignClass>
</DCCReference> </DCCReference>
<DCCReference Include="uNameOffCanvas.pas"/> <DCCReference Include="uNameOffCanvas.pas"/>
<DCCReference Include="uDropdownHelpers.pas"/> <DCCReference Include="uDropdownHelpers.pas"/>
<DCCReference Include="View.Login.pas"> <DCCReference Include="View.Login.pas">
<Form>FViewLogin</Form> <Form>FViewLogin</Form>
<FormType>dfm</FormType>
<DesignClass>TWebForm</DesignClass> <DesignClass>TWebForm</DesignClass>
</DCCReference> </DCCReference>
<DCCReference Include="View.ErrorPage.pas"> <DCCReference Include="View.ErrorPage.pas">
<Form>FViewErrorPage</Form> <Form>FViewErrorPage</Form>
<FormType>dfm</FormType> <DesignClass>TWebForm</DesignClass>
</DCCReference>
<DCCReference Include="View.TimeEntries.pas">
<Form>FTimeEntries</Form>
<DesignClass>TWebForm</DesignClass> <DesignClass>TWebForm</DesignClass>
</DCCReference> </DCCReference>
<None Include="index.html"/> <None Include="index.html"/>
......
...@@ -20,7 +20,7 @@ type ...@@ -20,7 +20,7 @@ type
['{9CFD59B2-A832-4F82-82BB-9A25FC93F305}'] ['{9CFD59B2-A832-4F82-82BB-9A25FC93F305}']
function Login(userId, taskId, urlCode: string): string; function Login(userId, taskId, urlCode: string): string;
function VerifyVersion(ClientVersion: string): TJSONObject; function VerifyVersion(ClientVersion: string): TJSONObject;
function WebLogin(userName, taskId, password: string): string; function WebLogin(userName, loginType, loginValue, password: string): string;
end; end;
implementation implementation
......
...@@ -37,7 +37,8 @@ type ...@@ -37,7 +37,8 @@ type
public public
function Login(userId, taskId, urlCode: string): string; function Login(userId, taskId, urlCode: string): string;
function VerifyVersion(ClientVersion: string): TJSONObject; function VerifyVersion(ClientVersion: string): TJSONObject;
function WebLogin(userName, taskId, password: string): string; function WebLogin(userName, loginType, loginValue, password: string): string;
function CheckTimeEntriesLogin(userName, password: string): Integer;
end; end;
implementation implementation
...@@ -240,16 +241,27 @@ begin ...@@ -240,16 +241,27 @@ begin
end; end;
function TAuthService.WebLogin(userName, taskId, password: string): string; function TAuthService.WebLogin(userName, loginType, loginValue, password: string): string;
var var
userState: Integer; userState: Integer;
jwt: TJWT; jwt: TJWT;
begin begin
Logger.Log(3, Format('AuthService.WebLogin - UserName: %s, TaskID: %s', [userName, taskId])); Logger.Log(3, Format('AuthService.WebLogin - UserName: %s, LoginType: %s, LoginValue: %s',
[userName, loginType, loginValue]));
try try
userState := CheckUserLogin(userName, taskId, password); if SameText(loginType, 'task_items') then
userState := CheckUserLogin(userName, loginValue, password)
else if SameText(loginType, 'time_entries') then
userState := CheckTimeEntriesLogin(userName, password)
else
begin
Logger.Log(2, 'Web Login Error: Invalid login type: ' + loginType);
raise EXDataHttpUnauthorized.Create('Invalid login type');
end;
except except
on E: EXDataHttpUnauthorized do
raise;
on E: Exception do on E: Exception do
begin begin
Logger.Log(1, 'Web Login failed due to database error: ' + E.Message); Logger.Log(1, 'Web Login failed due to database error: ' + E.Message);
...@@ -259,8 +271,16 @@ begin ...@@ -259,8 +271,16 @@ begin
if userState = 0 then if userState = 0 then
begin begin
Logger.Log(2, 'Web Login Error: Invalid username, task id, or password'); if SameText(loginType, 'time_entries') then
raise EXDataHttpUnauthorized.Create('Invalid user name, task id, or password'); begin
Logger.Log(2, 'Web Login Error: Invalid username or password');
raise EXDataHttpUnauthorized.Create('Invalid user name or password');
end
else
begin
Logger.Log(2, 'Web Login Error: Invalid username, task id, or password');
raise EXDataHttpUnauthorized.Create('Invalid user name, task id, or password');
end;
end; end;
if userState = 1 then if userState = 1 then
...@@ -282,7 +302,7 @@ begin ...@@ -282,7 +302,7 @@ begin
jwt.Claims.Expiration := IncHour(Now, 12); jwt.Claims.Expiration := IncHour(Now, 12);
jwt.Claims.SetClaimOfType<string>('user_id', Self.userId); jwt.Claims.SetClaimOfType<string>('user_id', Self.userId);
jwt.Claims.SetClaimOfType<string>('user_name', userName); jwt.Claims.SetClaimOfType<string>('user_name', Self.userName);
jwt.Claims.SetClaimOfType<string>('user_fullname', userFullName); jwt.Claims.SetClaimOfType<string>('user_fullname', userFullName);
jwt.Claims.SetClaimOfType<string>('user_status', userStatus); jwt.Claims.SetClaimOfType<string>('user_status', userStatus);
jwt.Claims.SetClaimOfType<string>('user_email', userEmail); jwt.Claims.SetClaimOfType<string>('user_email', userEmail);
...@@ -353,6 +373,72 @@ begin ...@@ -353,6 +373,72 @@ begin
end; end;
function TAuthService.CheckTimeEntriesLogin(userName, password: string): Integer;
var
q: TUniQuery;
storedPasswordHash: string;
nameValue: string;
begin
Logger.Log(3, 'TAuthService.CheckTimeEntriesLogin(userName, password: string): Integer');
q := TUniQuery.Create(nil);
try
q.Connection := authDB.uqWebLogin.Connection;
q.SQL.Text :=
'select ' +
' USER_ID, USER_NAME, NAME, STATUS, EMAIL, ACCESS_LEVEL, ' +
' TASK_RIGHTS, PERSPECTIVE_ID, LAST_NAME, FIRST_NAME, PASSWORD ' +
'from users ' +
'where USER_NAME = :USER_NAME';
q.ParamByName('USER_NAME').AsString := userName;
q.Open;
if q.IsEmpty then
begin
Logger.Log(3, '--Time Entries Login failed 0: user not found');
Result := 0;
Exit;
end;
storedPasswordHash := HashPassword(q.FieldByName('PASSWORD').AsString);
if storedPasswordHash <> LowerCase(Trim(password)) then
begin
Logger.Log(3, '--Time Entries Login failed 0: password hash mismatch');
Result := 0;
Exit;
end;
if q.FieldByName('STATUS').AsString <> 'ACTIVE' then
begin
Logger.Log(3, '--Time Entries Login failed 1: user is not active');
Result := 1;
Exit;
end;
Self.userId := q.FieldByName('USER_ID').AsString;
Self.userName := q.FieldByName('USER_NAME').AsString;
userStatus := q.FieldByName('STATUS').AsString;
userEmail := q.FieldByName('EMAIL').AsString;
userAccessLevel := q.FieldByName('ACCESS_LEVEL').AsString;
userTaskRights := q.FieldByName('TASK_RIGHTS').AsString;
userPerspectiveId := q.FieldByName('PERSPECTIVE_ID').AsString;
userLastName := q.FieldByName('LAST_NAME').AsString;
userFirstName := q.FieldByName('FIRST_NAME').AsString;
nameValue := Trim(q.FieldByName('NAME').AsString);
if nameValue <> '' then
userFullName := nameValue
else
userFullName := Trim(userFirstName + ' ' + userLastName);
Result := 3;
finally
q.Free;
end;
end;
procedure TAuthService.LoadUserFromWebLoginQuery; procedure TAuthService.LoadUserFromWebLoginQuery;
var var
nameValue: string; nameValue: string;
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
MemoLogLevel=4 MemoLogLevel=4
FileLogLevel=4 FileLogLevel=4
webClientVersion=0.8.9 webClientVersion=0.8.9
LogFileNum=187 LogFileNum=190
[Database] [Database]
Server=192.168.102.131 Server=192.168.102.131
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment