Commit e137cc5a by Elias Sarraf

dev branch wip WebLogin

parent 93fe35a6
...@@ -4,11 +4,14 @@ emT3VCLDemo/Win64x/ ...@@ -4,11 +4,14 @@ emT3VCLDemo/Win64x/
emT3Web/__history/ emT3Web/__history/
emT3Web/__recovery/ emT3Web/__recovery/
emT3Web/config/ emT3Web/config/
emT3Web/css/__history/
emT3Web/Win32/ emT3Web/Win32/
emT3XDataServer/__history/ emT3XDataServer/__history/
emT3XDataServer/__recovery/
emT3XDataServer/bin/logs/ emT3XDataServer/bin/logs/
emT3XDataServer/bin/static/ emT3XDataServer/bin/static/
emT3XDataServer/Source/__history/ emT3XDataServer/Source/__history/
emT3XDataServer/Source/__recovery/
emT3XDataServer/Win32/ emT3XDataServer/Win32/
*.exe *.exe
...@@ -19,6 +22,3 @@ emT3XDataServer/Win32/ ...@@ -19,6 +22,3 @@ emT3XDataServer/Win32/
*.tvsconfig *.tvsconfig
*.txt *.txt
*.zip *.zip
emT3Web/css/__history/
...@@ -184,13 +184,13 @@ ...@@ -184,13 +184,13 @@
<BuildOrder>1</BuildOrder> <BuildOrder>1</BuildOrder>
<PCH>true</PCH> <PCH>true</PCH>
</PCHCompile> </PCHCompile>
<CppCompile Include="uMain.cpp"> <CppCompile Include="fMain.cpp">
<Form>fMain</Form> <Form>frmMain</Form>
<FormType>dfm</FormType> <FormType>dfm</FormType>
<DependentOn>uMain.h</DependentOn> <DependentOn>fMain.h</DependentOn>
<BuildOrder>2</BuildOrder> <BuildOrder>2</BuildOrder>
</CppCompile> </CppCompile>
<FormResources Include="uMain.dfm"/> <FormResources Include="fMain.dfm"/>
<BuildConfiguration Include="Base"> <BuildConfiguration Include="Base">
<Key>Base</Key> <Key>Base</Key>
</BuildConfiguration> </BuildConfiguration>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#pragma hdrstop #pragma hdrstop
#include <tchar.h> #include <tchar.h>
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
USEFORM("uMain.cpp", fMain); USEFORM("fMain.cpp", frmMain);
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int) int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{ {
...@@ -12,7 +12,7 @@ int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int) ...@@ -12,7 +12,7 @@ int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{ {
Application->Initialize(); Application->Initialize();
Application->MainFormOnTaskBar = true; Application->MainFormOnTaskBar = true;
Application->CreateForm(__classid(TfMain), &fMain); Application->CreateForm(__classid(TfrmMain), &frmMain);
Application->Run(); Application->Run();
} }
catch (Exception &exception) catch (Exception &exception)
......
...@@ -5,33 +5,35 @@ ...@@ -5,33 +5,35 @@
#include <System.NetEncoding.hpp> #include <System.NetEncoding.hpp>
#pragma hdrstop #pragma hdrstop
#include "uMain.h" #include "fMain.h"
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#pragma package(smart_init) #pragma package(smart_init)
#pragma link "MySQLUniProvider" #pragma link "MySQLUniProvider"
#pragma link "UniProvider" #pragma link "UniProvider"
#pragma resource "*.dfm" #pragma resource "*.dfm"
TfMain *fMain; TfrmMain *frmMain;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
__fastcall TfMain::TfMain(TComponent* Owner) __fastcall TfrmMain::TfrmMain(TComponent* Owner)
: TForm(Owner) : TForm(Owner)
{ {
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void __fastcall TfrmMain::FormCreate(TObject *Sender)
void __fastcall TfMain::FormCreate(TObject *Sender)
{ {
Randomize(); Randomize();
LogLine("App started"); LogLine( "ucETask->Server: " + ucETask->Server );
LogLine( "ucETask->Database: " + ucETask->Database );
LogLine( "ucETask->Username: " + ucETask->Username );
LogLine( "ucETask->Password: " + ucETask->Password );
LogLine( "App started" );
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void __fastcall TfrmMain::btnOpenTaskItemsClick(TObject *Sender)
void __fastcall TfMain::btnOpenTaskItemsClick(TObject *Sender)
{ {
const UnicodeString userId = edtUserId->Text.Trim(); String userId = edtUserId->Text.Trim();
const UnicodeString taskId = edtTaskId->Text.Trim(); String taskId = edtTaskId->Text.Trim();
const UnicodeString baseUrl = edtWebUrl->Text.Trim(); String baseUrl = edtWebUrl->Text.Trim();
const int expSeconds = StrToIntDef(edtExpSeconds->Text.Trim(), 60); int expSeconds = StrToIntDef(edtExpSeconds->Text.Trim(), 5);
if (userId.IsEmpty() || taskId.IsEmpty() || baseUrl.IsEmpty()) if (userId.IsEmpty() || taskId.IsEmpty() || baseUrl.IsEmpty())
{ {
...@@ -39,14 +41,14 @@ void __fastcall TfMain::btnOpenTaskItemsClick(TObject *Sender) ...@@ -39,14 +41,14 @@ void __fastcall TfMain::btnOpenTaskItemsClick(TObject *Sender)
return; return;
} }
const int codeInt = 100000 + Random(900000); int codeInt = 100000 + Random(900000);
const UnicodeString urlCode = IntToStr(codeInt); String urlCode = IntToStr(codeInt);
LogLine("Generated URL_CODE=" + urlCode); LogLine("Generated URL_CODE=" + urlCode);
try try
{ {
if (!ucETask->Connected) if( !ucETask->Connected )
{ {
LogLine("Connecting to MariaDB..."); LogLine("Connecting to MariaDB...");
ucETask->Connect(); ucETask->Connect();
...@@ -75,42 +77,97 @@ void __fastcall TfMain::btnOpenTaskItemsClick(TObject *Sender) ...@@ -75,42 +77,97 @@ void __fastcall TfMain::btnOpenTaskItemsClick(TObject *Sender)
return; return;
} }
const UnicodeString launchUrl = BuildLaunchUrl(baseUrl, userId, taskId, urlCode); String launchUrl = BuildLaunchUrl(baseUrl, userId, taskId, urlCode);
if (launchUrl.IsEmpty()) if( launchUrl.IsEmpty() ){
{
LogLine("Launch URL build failed"); LogLine("Launch URL build failed");
return; return;
} }
LogLine("Launching browser:"); LogLine( "Launching browser:" );
LogLine(launchUrl); LogLine( launchUrl );
ShellExecute(0, L"open", launchUrl.w_str(), 0, 0, SW_SHOWNORMAL); ShellExecute( 0, L"open", launchUrl.w_str(), 0, 0, SW_SHOWNORMAL );
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void TfrmMain::LogLine(String message)
void TfMain::LogLine(const String &message)
{ {
const String stamp = FormatDateTime("yyyy-mm-dd hh:nn:ss.zzz", Now()); String stamp = FormatDateTime("yyyy-mm-dd hh:nn:ss.zzz", Now());
memoLog->Lines->Add(stamp + " " + message); memoLog->Lines->Add(stamp + " " + message);
memoLog->SelStart = memoLog->Text.Length(); memoLog->SelStart = memoLog->Text.Length();
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
String TfrmMain::BuildLaunchUrl(String baseUrl, String userId, String taskId, String code)
String TfMain::BuildLaunchUrl(const String &baseUrl, const String &userId, const String &taskId, const String &code)
{ {
String cleanBaseUrl = baseUrl.Trim(); String cleanBaseUrl = baseUrl.Trim();
if (cleanBaseUrl.IsEmpty()) if( cleanBaseUrl.IsEmpty() )
return ""; return "";
String sep = cleanBaseUrl.Pos("?") > 0 ? "&" : "?"; return cleanBaseUrl + "?user_id=" + userId + "&task_id=" + taskId + "&url_code=" + code;
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnTaskItemsLoginClick(TObject *Sender)
{
String userId = edtUserId->Text.Trim();
String taskId = edtTaskId->Text.Trim();
String baseUrl = edtWebUrl->Text.Trim();
if( userId.IsEmpty() || taskId.IsEmpty() || baseUrl.IsEmpty() )
{
LogLine( "Missing required input (userId, taskId, or webUrl)" );
return;
}
String qUserId = TNetEncoding::URL->Encode(userId); String urlCode = 'WebLogin';
String qTaskId = TNetEncoding::URL->Encode(taskId);
String qCode = TNetEncoding::URL->Encode(code);
return cleanBaseUrl + sep + "user_id=" + qUserId + "&task_id=" + qTaskId + "&url_code=" + qCode; LogLine( "Generated URL_CODE=" + urlCode );
}
try
{
if( !ucETask->Connected )
{
LogLine("Connecting to MariaDB...");
ucETask->Connect();
LogLine("Connected");
}
LogLine( "Inserting row into web_tasks_url..." );
uqWebTasksUrl->Close();
uqWebTasksUrl->SQL->Text =
"insert into web_tasks_url (USER_ID, TASK_ID, URL_CODE, URL_TIME, URL_TIME_EXP) "
"values (:USER_ID, :TASK_ID, :URL_CODE, NOW(), :URL_TIME_EXP)";
uqWebTasksUrl->ParamByName("USER_ID")->AsString = userId;
uqWebTasksUrl->ParamByName("TASK_ID")->AsString = taskId;
uqWebTasksUrl->ParamByName("URL_CODE")->AsString = urlCode;
uqWebTasksUrl->ParamByName("URL_TIME_EXP")->AsInteger = 0;
uqWebTasksUrl->ExecSQL();
LogLine("Insert OK");
}
catch (const Exception &e)
{
LogLine("DB ERROR: " + e.Message);
return;
}
String launchUrl = baseUrl + "?user_id=" + userId + "&task_id=" + taskId;
if( launchUrl.IsEmpty() ){
LogLine("Launch URL build failed");
return;
}
LogLine( "Task Items Login url:" + launchUrl );
//ShellExecute( 0, L"open", launchUrl.w_str(), 0, 0, SW_SHOWNORMAL );
}
//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnConnectClick(TObject *Sender)
{
ucETask->Connect();
LogLine( "Connected to database" );
}
//---------------------------------------------------------------------------
object fMain: TfMain object frmMain: TfrmMain
Left = 0 Left = 0
Top = 0 Top = 0
Caption = 'fMain' Caption = 'frmMain'
ClientHeight = 441 ClientHeight = 524
ClientWidth = 624 ClientWidth = 810
Color = clBtnFace Color = clBtnFace
Font.Charset = DEFAULT_CHARSET Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText Font.Color = clWindowText
...@@ -52,12 +52,15 @@ object fMain: TfMain ...@@ -52,12 +52,15 @@ object fMain: TfMain
OnClick = btnOpenTaskItemsClick OnClick = btnOpenTaskItemsClick
end end
object memoLog: TMemo object memoLog: TMemo
Left = 20 Left = 0
Top = 102 Top = 108
Width = 581 Width = 810
Height = 311 Height = 416
Align = alBottom
Anchors = [akLeft, akTop, akRight, akBottom]
Lines.Strings = ( Lines.Strings = (
'') '')
ScrollBars = ssVertical
TabOrder = 1 TabOrder = 1
end end
object edtUserId: TEdit object edtUserId: TEdit
...@@ -89,6 +92,24 @@ object fMain: TfMain ...@@ -89,6 +92,24 @@ object fMain: TfMain
NumbersOnly = True NumbersOnly = True
TabOrder = 5 TabOrder = 5
end end
object btnTaskItemsLogin: TButton
Left = 140
Top = 64
Width = 109
Height = 25
Caption = 'Task Items Login'
TabOrder = 6
OnClick = btnTaskItemsLoginClick
end
object btnConnect: TButton
Left = 260
Top = 64
Width = 73
Height = 25
Caption = 'Connect'
TabOrder = 7
OnClick = btnConnectClick
end
object ucETask: TUniConnection object ucETask: TUniConnection
ProviderName = 'MySQL' ProviderName = 'MySQL'
Database = 'etask' Database = 'etask'
...@@ -105,7 +126,7 @@ object fMain: TfMain ...@@ -105,7 +126,7 @@ object fMain: TfMain
'MySQL.HttpTrustServerCertificate=False' 'MySQL.HttpTrustServerCertificate=False'
'MySQL.ProxyPort=0') 'MySQL.ProxyPort=0')
Username = 'root' Username = 'root'
Server = '192.168.102.131' Server = '192.168.116.131'
LoginPrompt = False LoginPrompt = False
Left = 390 Left = 390
Top = 342 Top = 342
......
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#ifndef uMainH #ifndef fMainH
#define uMainH #define fMainH
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#include <System.Classes.hpp> #include <System.Classes.hpp>
#include <Vcl.Controls.hpp> #include <Vcl.Controls.hpp>
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
#include "MySQLUniProvider.hpp" #include "MySQLUniProvider.hpp"
#include "UniProvider.hpp" #include "UniProvider.hpp"
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
class TfMain : public TForm class TfrmMain : public TForm
{ {
__published: // IDE-managed Components __published: // IDE-managed Components
TButton *btnOpenTaskItems; TButton *btnOpenTaskItems;
...@@ -30,16 +30,20 @@ __published: // IDE-managed Components ...@@ -30,16 +30,20 @@ __published: // IDE-managed Components
TUniConnection *ucETask; TUniConnection *ucETask;
TUniQuery *uqWebTasksUrl; TUniQuery *uqWebTasksUrl;
TMySQLUniProvider *MySQLUniProvider1; TMySQLUniProvider *MySQLUniProvider1;
TButton *btnTaskItemsLogin;
TButton *btnConnect;
void __fastcall FormCreate(TObject *Sender); void __fastcall FormCreate(TObject *Sender);
void __fastcall btnOpenTaskItemsClick(TObject *Sender); void __fastcall btnOpenTaskItemsClick(TObject *Sender);
void __fastcall btnTaskItemsLoginClick(TObject *Sender);
void __fastcall btnConnectClick(TObject *Sender);
private: private:
void LogLine(const String &message); void LogLine(String message);
String BuildLaunchUrl(const String &baseUrl, const String &userId, const String &taskId, const String &code); String BuildLaunchUrl(String baseUrl, String userId, String taskId, String code);
public: // User declarations public: // User declarations
__fastcall TfMain(TComponent* Owner); __fastcall TfrmMain(TComponent* Owner);
}; };
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
extern PACKAGE TfMain *fMain; extern PACKAGE TfrmMain *frmMain;
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
#endif #endif
...@@ -25,6 +25,8 @@ type ...@@ -25,6 +25,8 @@ type
destructor Destroy; override; destructor Destroy; override;
procedure Login(AUser, APassword, AClientVersion: string; ASuccess: TOnLoginSuccess; procedure Login(AUser, APassword, AClientVersion: string; ASuccess: TOnLoginSuccess;
AError: TOnLoginError); AError: TOnLoginError);
procedure WebLogin(AUser, APassword, ATaskId: string; ASuccess: TOnLoginSuccess;
AError: TOnLoginError);
procedure Logout; procedure Logout;
function GetToken: string; function GetToken: string;
function Authenticated: Boolean; function Authenticated: Boolean;
...@@ -121,6 +123,38 @@ begin ...@@ -121,6 +123,38 @@ begin
); );
end; end;
procedure TAuthService.WebLogin(AUser, APassword, ATaskId: string; ASuccess: TOnLoginSuccess;
AError: TOnLoginError);
procedure OnLoad(Response: TXDataClientResponse);
var
Token: JS.TJSObject;
begin
Token := JS.TJSObject(Response.Result);
SetToken(JS.toString(Token.Properties['value']));
ASuccess;
end;
procedure OnError(Error: TXDataClientError);
begin
AError(Format('%s: %s', [Error.ErrorCode, Error.ErrorMessage]));
end;
begin
if (AUser = '') or (APassword = '') then
begin
AError('Invalid or expired code, please try again.');
Exit;
end;
FClient.RawInvoke(
'IAuthService.WebLogin', [AUser, APassword, ATaskId],
@OnLoad, @OnError
);
end;
procedure TAuthService.Logout; procedure TAuthService.Logout;
begin begin
DeleteToken; DeleteToken;
......
object FViewErrorPage: TFViewErrorPage
Left = 0
Top = 0
Width = 534
Height = 426
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
TabOrder = 1
object lbTitle: TWebLabel
Left = 24
Top = 24
Width = 128
Height = 13
Caption = 'Oops... an error occurred!'
ElementID = 'view.errorpage.title'
Transparent = False
end
object lbMessage: TWebLabel
Left = 24
Top = 56
Width = 42
Height = 13
Caption = 'Message'
ElementID = 'view.errorpage.message'
Transparent = False
end
end
<div class="container">
<br />
<div class="panel panel-red">
<div id="view.errorpage.title" class="panel-heading">
Error Page
</div>
<div id="view.errorpage.message" class="panel-body">
Message
</div>
<div class="panel-footer">
<a href=".">Reload web application</a>
</div>
</div>
</div>
unit View.ErrorPage;
interface
uses
System.SysUtils, System.Classes, WEBLib.Graphics, WEBLib.Controls, WEBLib.Forms, WEBLib.Dialogs,
Vcl.Controls, Vcl.StdCtrls,
XData.Web.Connection, WEBLib.StdCtrls;
type
TFViewErrorPage = class(TWebForm)
lbTitle: TWebLabel;
lbMessage: TWebLabel;
public
class procedure Display(AErrorMessage: string);
class procedure DisplayConnectionError(AError: TXDataWebConnectionError);
end;
var
FViewErrorPage: TFViewErrorPage;
implementation
{$R *.dfm}
{ TFViewErrorPage }
class procedure TFViewErrorPage.Display(AErrorMessage: string);
procedure AfterCreateProc(AForm: TObject);
begin
TFViewErrorPage(AForm).lbMessage.Caption := AErrorMessage;
end;
begin
if Assigned(FViewErrorPage) then
FViewErrorPage.Free;
FViewErrorPage := TFViewErrorPage.CreateNew(@AfterCreateProc);
end;
class procedure TFViewErrorPage.DisplayConnectionError(
AError: TXDataWebConnectionError);
begin
Display(AError.ErrorMessage + ': ' + AError.RequestUrl);
end;
end.
object FViewLogin: TFViewLogin
Width = 640
Height = 480
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
ParentFont = False
OnCreate = WebFormCreate
object WebLabel1: TWebLabel
Left = 240
Top = 112
Width = 67
Height = 13
Caption = 'Please Sign In'
ElementID = 'view.login.title'
HeightPercent = 100.000000000000000000
Transparent = False
WidthPercent = 100.000000000000000000
end
object edtUsername: TWebEdit
Left = 240
Top = 160
Width = 121
Height = 21
ElementID = 'view.login.edtusername'
HeightPercent = 100.000000000000000000
TextHint = 'Username'
WidthPercent = 100.000000000000000000
end
object edtPassword: TWebEdit
Left = 240
Top = 187
Width = 121
Height = 21
ElementID = 'view.login.edtpassword'
HeightPercent = 100.000000000000000000
PasswordChar = '*'
TabOrder = 1
TextHint = 'Password'
WidthPercent = 100.000000000000000000
end
object btnLogin: TWebButton
Left = 240
Top = 214
Width = 121
Height = 25
Caption = 'Login'
ElementID = 'view.login.btnlogin'
HeightPercent = 100.000000000000000000
TabOrder = 2
WidthPercent = 100.000000000000000000
OnClick = btnLoginClick
end
object pnlMessage: TWebPanel
Left = 240
Top = 65
Width = 121
Height = 33
ElementID = 'view.login.message'
TabOrder = 3
object lblMessage: TWebLabel
Left = 16
Top = 11
Width = 42
Height = 13
Caption = 'Message'
ElementID = 'view.login.message.label'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
end
object btnCloseNotification: TWebButton
Left = 96
Top = 3
Width = 22
Height = 25
ElementID = 'view.login.message.button'
HeightPercent = 100.000000000000000000
WidthPercent = 100.000000000000000000
OnClick = btnCloseNotificationClick
end
end
object edtTaskId: TWebEdit
Left = 240
Top = 133
Width = 121
Height = 21
ChildOrder = 5
ElementID = 'view.login.edttaskid'
HeightPercent = 100.000000000000000000
TextHint = 'TaskId'
WidthPercent = 100.000000000000000000
end
object XDataWebClient: TXDataWebClient
Connection = DMConnection.AuthConnection
Left = 492
Top = 102
end
end
<nav class="navbar navbar-light bg-light login-navbar">
<div class="container-fluid">
<a class="navbar-brand" href="#">Envoy Calls</a>
</div>
</nav>
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-md-6 col-lg-4">
<div class="card login-card">
<div class="card-header">
<h3 id="view.login.title" class="fs-6 card-title">Please Sign In</h3>
</div>
<div class="card-body">
<div role="form">
<div id="view.login.message" class="alert alert-danger">
<button id="view.login.message.button" type="button" class="btn-close" aria-label="Close"></button>
<span id="view.login.message.label"></span>
</div>
<fieldset>
<div class="mb-3">
<input id="view.login.edttaskid" class="form-control" type="text" autofocus placeholder="Task Id">
</div>
<div class="mb-3">
<input id="view.login.edtusername" class="form-control" type="text" autofocus placeholder="Username">
</div>
<div class="mb-3">
<input id="view.login.edtpassword" class="form-control" type="password" placeholder="Password">
</div>
<div class="mb-3">
<button id="view.login.btnlogin" class="btn btn-primary w-100">Login</button>
</div>
</fieldset>
</div>
</div>
</div>
</div>
</div>
</div>
unit View.Login;
interface
uses
System.SysUtils, System.Classes, WEBLib.Graphics, WEBLib.Controls, WEBLib.Forms, WEBLib.Dialogs,
Vcl.Controls, Vcl.StdCtrls, WEBLib.StdCtrls, WEBLib.JSON,
JS, XData.Web.Connection, WEBLib.ExtCtrls,
App.Types, ConnectionModule, XData.Web.Client;
type
TFViewLogin = class(TWebForm)
WebLabel1: TWebLabel;
edtUsername: TWebEdit;
edtPassword: TWebEdit;
btnLogin: TWebButton;
pnlMessage: TWebPanel;
lblMessage: TWebLabel;
btnCloseNotification: TWebButton;
XDataWebClient: TXDataWebClient;
edtTaskId: TWebEdit;
procedure btnLoginClick(Sender: TObject);
procedure btnCloseNotificationClick(Sender: TObject);
procedure WebFormCreate(Sender: TObject);
private
FLoginProc: TSuccessProc;
FMessage: string;
procedure ShowNotification(Notification: string);
procedure HideNotification;
public
class procedure Display(LoginProc: TSuccessProc); overload;
class procedure Display(LoginProc: TSuccessProc; AMsg: string); overload;
end;
var
FViewLogin: TFViewLogin;
implementation
uses
Auth.Service,
View.ErrorPage;
{$R *.dfm}
procedure TFViewLogin.btnLoginClick(Sender: TObject);
procedure LoginSuccess;
begin
FLoginProc;
end;
procedure LoginError(AMsg: string);
begin
ShowNotification('Login Error: ' + AMsg);
end;
begin
AuthService.WebLogin(
edtUsername.Text, edtPassword.Text, edtTaskId.Text,
@LoginSuccess,
@LoginError
);
end;
class procedure TFViewLogin.Display(LoginProc: TSuccessProc);
begin
TFViewLogin.Display(LoginProc, '');
end;
class procedure TFViewLogin.Display(LoginProc: TSuccessProc; AMsg: string);
procedure FormCreate(AForm: TObject);
begin
TFViewLogin(AForm).FMessage := AMsg;
end;
begin
if Assigned(FViewLogin) then
FViewLogin.Free;
FViewLogin := TFViewLogin.CreateNew(@FormCreate);
FViewLogin.FLoginProc := LoginProc;
end;
procedure TFViewLogin.HideNotification;
begin
pnlMessage.ElementHandle.hidden := True;
end;
procedure TFViewLogin.ShowNotification(Notification: string);
begin
if Notification <> '' then
begin
lblMessage.Caption := Notification;
pnlMessage.ElementHandle.hidden := False;
end;
end;
procedure TFViewLogin.btnCloseNotificationClick(Sender: TObject);
begin
HideNotification;
end;
procedure TFViewLogin.WebFormCreate(Sender: TObject);
begin
// lblAppTitle.Caption := 'EM Systems - webCharms App ver 0.9.2.22';
if FMessage <> '' then
ShowNotification(FMessage)
else
HideNotification;
end;
end.
...@@ -13,10 +13,13 @@ uses ...@@ -13,10 +13,13 @@ uses
Utils in 'Utils.pas', Utils in 'Utils.pas',
View.TaskItems in 'View.TaskItems.pas' {FTaskItems: TWebForm} {*.html}, View.TaskItems in 'View.TaskItems.pas' {FTaskItems: TWebForm} {*.html},
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.ErrorPage in 'View.ErrorPage.pas' {FViewErrorPage: TWebForm} {*.html};
{$R *.res} {$R *.res}
procedure DisplayLoginView(AMessage: string = ''); forward;
procedure DoLogout(AMsg: string = ''); forward; procedure DoLogout(AMsg: string = ''); forward;
procedure DisplayMainView; procedure DisplayMainView;
...@@ -53,6 +56,16 @@ begin ...@@ -53,6 +56,16 @@ begin
end; end;
procedure DisplayLoginView(AMessage: string);
begin
AuthService.Logout;
DMConnection.ApiConnection.Connected := False;
if Assigned(FViewMain) then
FViewMain.Free;
TFViewLogin.Display(@DisplayMainView, AMessage);
end;
procedure DoLogin(); procedure DoLogin();
var var
userIdParam: string; userIdParam: string;
...@@ -63,11 +76,18 @@ begin ...@@ -63,11 +76,18 @@ begin
taskIdParam := Application.Parameters.Values['task_id']; taskIdParam := Application.Parameters.Values['task_id'];
codeParam := Application.Parameters.Values['url_code']; codeParam := Application.Parameters.Values['url_code'];
AuthService.Logout; if (userIdParam = '') or (taskIdParam = '') or (codeParam = '') then
DMConnection.ApiConnection.Connected := False; begin
if Assigned(FViewMain) then DisplayLoginView();
FViewMain.Free; end
Login( userIdParam, taskIdParam, codeParam ); else
begin
AuthService.Logout;
DMConnection.ApiConnection.Connected := False;
if Assigned(FViewMain) then
FViewMain.Free;
Login( userIdParam, taskIdParam, codeParam );
end;
end; end;
......
...@@ -144,6 +144,16 @@ ...@@ -144,6 +144,16 @@
</DCCReference> </DCCReference>
<DCCReference Include="uNameOffCanvas.pas"/> <DCCReference Include="uNameOffCanvas.pas"/>
<DCCReference Include="uDropdownHelpers.pas"/> <DCCReference Include="uDropdownHelpers.pas"/>
<DCCReference Include="View.Login.pas">
<Form>FViewLogin</Form>
<FormType>dfm</FormType>
<DesignClass>TWebForm</DesignClass>
</DCCReference>
<DCCReference Include="View.ErrorPage.pas">
<Form>FViewErrorPage</Form>
<FormType>dfm</FormType>
<DesignClass>TWebForm</DesignClass>
</DCCReference>
<None Include="index.html"/> <None Include="index.html"/>
<None Include="css\app.css"/> <None Include="css\app.css"/>
<None Include="config\config.json"/> <None Include="config\config.json"/>
......
...@@ -104,9 +104,8 @@ object AuthDatabase: TAuthDatabase ...@@ -104,9 +104,8 @@ object AuthDatabase: TAuthDatabase
Database = 'eTask' Database = 'eTask'
Username = 'root' Username = 'root'
Server = '192.168.102.131' Server = '192.168.102.131'
Connected = True
LoginPrompt = False LoginPrompt = False
Left = 69 Left = 71
Top = 133 Top = 133
EncryptedPassword = '9AFF92FF8CFF86FF8CFFCFFFCEFF' EncryptedPassword = '9AFF92FF8CFF86FF8CFFCFFFCEFF'
end end
......
...@@ -30,11 +30,13 @@ type ...@@ -30,11 +30,13 @@ type
procedure BeforeDestruction; override; procedure BeforeDestruction; override;
function CheckUrlLogin(const userId, taskId, urlCode: string): Integer; function CheckUrlLogin(const userId, taskId, urlCode: string): Integer;
function CheckUserLogin(const userId, taskId, password: string): Integer;
procedure LoadUserFromUrlLoginQuery; procedure LoadUserFromUrlLoginQuery;
procedure LoadUserFromWebLoginQuery;
public public
function Login(const userId, taskId, urlCode: string): string; function Login(const userId, taskId, urlCode: string): string;
function VerifyVersion(ClientVersion: string): TJSONObject; function VerifyVersion(ClientVersion: string): TJSONObject;
function WebLogin(const userId, taskId, password: string): string; function WebLogin(const userId, password, taskId: string): string;
end; end;
implementation implementation
...@@ -63,12 +65,14 @@ begin ...@@ -63,12 +65,14 @@ begin
end; end;
end; end;
procedure TAuthService.BeforeDestruction; procedure TAuthService.BeforeDestruction;
begin begin
authDB.Free; authDB.Free;
inherited; inherited;
end; end;
function TAuthService.VerifyVersion(ClientVersion: string): TJSONObject; function TAuthService.VerifyVersion(ClientVersion: string): TJSONObject;
var var
iniFile: TIniFile; iniFile: TIniFile;
...@@ -100,6 +104,7 @@ begin ...@@ -100,6 +104,7 @@ begin
end; end;
end; end;
function TAuthService.CheckUrlLogin(const userId, taskId, urlCode: string): Integer; function TAuthService.CheckUrlLogin(const userId, taskId, urlCode: string): Integer;
var var
sql: string; sql: string;
...@@ -109,7 +114,8 @@ begin ...@@ -109,7 +114,8 @@ begin
Logger.Log(3, 'TAuthService.CheckUrlLogin(const userId, taskId, urlCode: string): Integer' ); Logger.Log(3, 'TAuthService.CheckUrlLogin(const userId, taskId, urlCode: string): Integer' );
sql := 'select u.USER_ID, u.USER_NAME, u.NAME, u.STATUS, u.EMAIL, u.ACCESS_LEVEL, '; sql := 'select u.USER_ID, u.USER_NAME, u.NAME, u.STATUS, u.EMAIL, u.ACCESS_LEVEL, ';
sql := sql + 'u.TASK_RIGHTS, u.PERSPECTIVE_ID, u.LAST_NAME, u.FIRST_NAME, w.URL_TIME, w.URL_TIME_EXP '; sql := sql + 'u.TASK_RIGHTS, u.PERSPECTIVE_ID, u.LAST_NAME, u.FIRST_NAME, ';
sql := sql + 'w.URL_TIME, w.URL_TIME_EXP, w.WEB_LOGIN ';
sql := sql + 'from web_tasks_url w '; sql := sql + 'from web_tasks_url w ';
sql := sql + 'join users u on u.USER_ID = w.USER_ID '; sql := sql + 'join users u on u.USER_ID = w.USER_ID ';
sql := sql + 'where w.USER_ID = :USER_ID and w.TASK_ID = :TASK_ID and w.URL_CODE = :URL_CODE '; sql := sql + 'where w.USER_ID = :USER_ID and w.TASK_ID = :TASK_ID and w.URL_CODE = :URL_CODE ';
...@@ -151,27 +157,29 @@ begin ...@@ -151,27 +157,29 @@ begin
Result := 3; Result := 3;
end; end;
procedure TAuthService.LoadUserFromUrlLoginQuery; procedure TAuthService.LoadUserFromUrlLoginQuery;
var var
nameValue: string; nameValue: string;
begin begin
Self.userId := authDB.uqWebTasksUrl.FieldByName('USER_ID').AsString; Self.userId := authDB.uqWebTasksUrlUSER_ID.AsString;
userName := authDB.uqWebTasksUrl.FieldByName('USER_NAME').AsString; userName := authDB.uqWebTasksUrlUSER_NAME.AsString;
userStatus := authDB.uqWebTasksUrl.FieldByName('STATUS').AsString; userStatus := authDB.uqWebTasksUrlSTATUS.AsString;
userEmail := authDB.uqWebTasksUrl.FieldByName('EMAIL').AsString; userEmail := authDB.uqWebTasksUrlEMAIL.AsString;
userAccessLevel := authDB.uqWebTasksUrl.FieldByName('ACCESS_LEVEL').AsString; userAccessLevel := authDB.uqWebTasksUrlACCESS_LEVEL.AsString;
userTaskRights := authDB.uqWebTasksUrl.FieldByName('TASK_RIGHTS').AsString; userTaskRights := authDB.uqWebTasksUrlTASK_RIGHTS.AsString;
userPerspectiveId := authDB.uqWebTasksUrl.FieldByName('PERSPECTIVE_ID').AsString; userPerspectiveId := authDB.uqWebTasksUrlPERSPECTIVE_ID.AsString;
userLastName := authDB.uqWebTasksUrl.FieldByName('LAST_NAME').AsString; userLastName := authDB.uqWebTasksUrlLAST_NAME.AsString;
userFirstName := authDB.uqWebTasksUrl.FieldByName('FIRST_NAME').AsString; userFirstName := authDB.uqWebTasksUrlFIRST_NAME.AsString;
nameValue := Trim(authDB.uqWebTasksUrl.FieldByName('NAME').AsString); nameValue := Trim(authDB.uqWebTasksUrlNAME.AsString);
if nameValue <> '' then if nameValue <> '' then
userFullName := nameValue userFullName := nameValue
else else
userFullName := Trim(userFirstName + ' ' + userLastName); userFullName := Trim(userFirstName + ' ' + userLastName);
end; end;
function TAuthService.Login(const userId, taskId, urlCode: string): string; function TAuthService.Login(const userId, taskId, urlCode: string): string;
var var
userState: Integer; userState: Integer;
...@@ -230,6 +238,137 @@ begin ...@@ -230,6 +238,137 @@ begin
end; end;
end; end;
function TAuthService.WebLogin(const userId, password, taskID: string): string;
var
userState: Integer;
jwt: TJWT;
begin
Logger.Log(3, Format('AuthService.WebLogin - UserID: %s, TaskID: %s, password: %s', [userId, taskId, password]));
try
userState := CheckUserLogin(userId, taskId, password);
except
on E: Exception do
begin
Logger.Log(1, 'URL Login failed due to database error: ' + E.Message);
raise EXDataHttpException.Create(500, 'Login failed: Unable to connect to the database.');
end;
end;
if userState = 0 then
begin
Logger.Log(2, 'Login Error: Invalid url parameters');
raise EXDataHttpUnauthorized.Create('Invalid url parameters');
end;
if userState = 1 then
begin
Logger.Log(2, 'Login Error: User not active!');
raise EXDataHttpUnauthorized.Create('User not active!');
end;
if userState = 2 then
begin
Logger.Log(2, 'Login Error: Expired link');
raise EXDataHttpUnauthorized.Create('Expired link');
end;
jwt := TJWT.Create;
try
jwt.Claims.JWTId := LowerCase(Copy(TUtils.GuidToVariant(TUtils.NewGuid), 2, 36));
jwt.Claims.IssuedAt := Now;
jwt.Claims.Expiration := IncHour(Now, 12);
jwt.Claims.SetClaimOfType<string>('user_id', Self.userId);
jwt.Claims.SetClaimOfType<string>('user_name', userName);
jwt.Claims.SetClaimOfType<string>('user_fullname', userFullName);
jwt.Claims.SetClaimOfType<string>('user_status', userStatus);
jwt.Claims.SetClaimOfType<string>('user_email', userEmail);
jwt.Claims.SetClaimOfType<string>('user_access_level', userAccessLevel);
jwt.Claims.SetClaimOfType<string>('task_rights', userTaskRights);
jwt.Claims.SetClaimOfType<string>('user_perspective_id', userPerspectiveId);
jwt.Claims.SetClaimOfType<string>('first_name', userFirstName);
jwt.Claims.SetClaimOfType<string>('last_name', userLastName);
Result := TJOSE.SHA256CompactToken(serverConfig.jwtTokenSecret, jwt);
finally
jwt.Free;
end;
end;
function TAuthService.CheckUserLogin(const userId, taskId, password: string): Integer;
var
sql: string;
webLogin: string;
begin
Logger.Log(3, 'TAuthService.CheckUserLogin(const userId, taskId, password: string): Integer' );
sql := 'select u.USER_ID, u.USER_NAME, u.NAME, u.STATUS, u.EMAIL, u.ACCESS_LEVEL, ';
sql := sql + 'u.TASK_RIGHTS, u.PERSPECTIVE_ID, u.LAST_NAME, u.FIRST_NAME, ';
sql := sql + 'w.URL_TIME, w.URL_TIME_EXP, w.WEB_LOGIN ';
sql := sql + 'from web_tasks_url w ';
sql := sql + 'join users u on u.USER_ID = w.USER_ID ';
sql := sql + 'where w.USER_ID = :USER_ID and w.TASK_ID = :TASK_ID and u.PASSWORD = :PASSWORD and w.URL_CODE = :URL_CODE';
authDB.uqWebLogin.Close;
authDB.uqWebLogin.SQL.Text := sql;
authDB.uqWebLogin.ParamByName('USER_ID').AsString := userId;
authDB.uqWebLogin.ParamByName('TASK_ID').AsString := taskId;
authDB.uqWebLogin.ParamByName('PASSWORD').AsString := password;
authDB.uqWebLogin.ParamByName('URL_CODE').AsString := 'WebLogin';
authDB.uqWebLogin.Open;
if authDB.uqWebLogin.IsEmpty then
begin
Logger.Log(3, '--Web Login failed 0: authDB.uqWebLogin.IsEmpty');
Result := 0;
Exit;
end;
if authDB.uqWebLoginSTATUS.AsString <> 'ACTIVE' then
begin
Logger.Log(3, '--Web Login failed 1: authDB.uqWebLoginSTATUS.AsString <> ACTIVE');
Result := 1;
Exit;
end;
webLogin := authDB.uqWebLoginWEB_LOGIN.AsString;
if webLogin <> 'T' then
begin
Logger.Log( 3, '--Web Login failed 2: WEB_LOGIN <> "T"' );
Result := 2;
Exit;
end;
LoadUserFromWebLoginQuery;
Result := 3;
end;
procedure TAuthService.LoadUserFromWebLoginQuery;
var
nameValue: string;
begin
Self.userId := authDB.uqWebLOginUSER_ID.AsString;
userName := authDB.uqWebLoginUSER_NAME.AsString;
userStatus := authDB.uqWebLoginSTATUS.AsString;
userEmail := authDB.uqWebLoginEMAIL.AsString;
userAccessLevel := authDB.uqWebLoginACCESS_LEVEL.AsString;
userTaskRights := authDB.uqWebLoginTASK_RIGHTS.AsString;
userPerspectiveId := authDB.uqWebLoginPERSPECTIVE_ID.AsString;
userLastName := authDB.uqWebLoginLAST_NAME.AsString;
userFirstName := authDB.uqWebLoginFIRST_NAME.AsString;
nameValue := Trim(authDB.uqWebLoginNAME.AsString);
if nameValue <> '' then
userFullName := nameValue
else
userFullName := Trim(userFirstName + ' ' + userLastName);
end;
initialization initialization
RegisterServiceType(TAuthService); RegisterServiceType(TAuthService);
......
object AuthDatabase: TAuthDatabase
OnCreate = DataModuleCreate
OnDestroy = DataModuleDestroy
Height = 207
Width = 303
object uqWebTasksUrl: TUniQuery
Connection = ucETaskAuth
SQL.Strings = (
'select'
' u.USER_ID,'
' u.USER_NAME,'
' u.NAME,'
' u.STATUS,'
' u.EMAIL,'
' u.ACCESS_LEVEL,'
' u.TASK_RIGHTS,'
' u.PERSPECTIVE_ID,'
' u.LAST_NAME,'
' u.FIRST_NAME,'
' w.URL_TIME,'
' w.URL_TIME_EXP'
'from web_tasks_url w'
'join users u on u.USER_ID = w.USER_ID'
'where w.USER_ID = :USER_ID'
' and w.TASK_ID = :TASK_ID'
' and w.URL_CODE = :URL_CODE'
' and TIMESTAMPDIFF(SECOND, w.URL_TIME, NOW()) between 0 and w.U' +
'RL_TIME_EXP'
'order by w.URL_TIME desc'
'limit 1')
FetchRows = 100
Left = 78
Top = 43
ParamData = <
item
DataType = ftUnknown
Name = 'USER_ID'
Value = nil
end
item
DataType = ftUnknown
Name = 'TASK_ID'
Value = nil
end
item
DataType = ftUnknown
Name = 'URL_CODE'
Value = nil
end>
object uqWebTasksUrlUSER_ID: TStringField
FieldName = 'USER_ID'
Required = True
Size = 7
end
object uqWebTasksUrlUSER_NAME: TStringField
FieldName = 'USER_NAME'
Required = True
Size = 12
end
object uqWebTasksUrlNAME: TStringField
FieldName = 'NAME'
Size = 40
end
object uqWebTasksUrlSTATUS: TStringField
FieldName = 'STATUS'
Size = 7
end
object uqWebTasksUrlEMAIL: TStringField
FieldName = 'EMAIL'
Size = 50
end
object uqWebTasksUrlACCESS_LEVEL: TIntegerField
FieldName = 'ACCESS_LEVEL'
end
object uqWebTasksUrlTASK_RIGHTS: TIntegerField
FieldName = 'TASK_RIGHTS'
end
object uqWebTasksUrlPERSPECTIVE_ID: TStringField
FieldName = 'PERSPECTIVE_ID'
Size = 45
end
object uqWebTasksUrlLAST_NAME: TStringField
FieldName = 'LAST_NAME'
Size = 35
end
object uqWebTasksUrlFIRST_NAME: TStringField
FieldName = 'FIRST_NAME'
Size = 25
end
object uqWebTasksUrlURL_TIME: TDateTimeField
FieldName = 'URL_TIME'
ReadOnly = True
Required = True
end
object uqWebTasksUrlURL_TIME_EXP: TIntegerField
FieldName = 'URL_TIME_EXP'
ReadOnly = True
Required = True
end
end
object ucETaskAuth: TUniConnection
ProviderName = 'MySQL'
Database = 'eTask'
Username = 'root'
Server = '192.168.102.131'
Connected = True
LoginPrompt = False
Left = 69
Top = 133
EncryptedPassword = '9AFF92FF8CFF86FF8CFFCFFFCEFF'
end
object MySQLUniProvider1: TMySQLUniProvider
Left = 194
Top = 132
end
object uqWebLogin: TUniQuery
Connection = ucETaskAuth
SQL.Strings = (
'select'
' u.USER_ID,'
' u.USER_NAME,'
' u.NAME,'
' u.STATUS,'
' u.EMAIL,'
' u.ACCESS_LEVEL,'
' u.TASK_RIGHTS,'
' u.PERSPECTIVE_ID,'
' u.LAST_NAME,'
' u.FIRST_NAME,'
' w.WEB_LOGIN'
'from web_tasks_url w'
'join users u on u.USER_ID = w.USER_ID'
'where w.USER_ID = :USER_ID'
' and w.TASK_ID = :TASK_ID'
' and u.PASSWORD = :PASSWORD')
Left = 192
Top = 44
ParamData = <
item
DataType = ftUnknown
Name = 'USER_ID'
Value = nil
end
item
DataType = ftUnknown
Name = 'TASK_ID'
Value = nil
end
item
DataType = ftUnknown
Name = 'PASSWORD'
Value = nil
end>
object uqWebLoginUSER_ID: TStringField
FieldName = 'USER_ID'
Required = True
Size = 7
end
object uqWebLoginUSER_NAME: TStringField
FieldName = 'USER_NAME'
Required = True
Size = 12
end
object uqWebLoginNAME: TStringField
FieldName = 'NAME'
Size = 40
end
object uqWebLoginSTATUS: TStringField
FieldName = 'STATUS'
Size = 7
end
object uqWebLoginEMAIL: TStringField
FieldName = 'EMAIL'
Size = 50
end
object uqWebLoginACCESS_LEVEL: TIntegerField
FieldName = 'ACCESS_LEVEL'
end
object uqWebLoginTASK_RIGHTS: TIntegerField
FieldName = 'TASK_RIGHTS'
end
object uqWebLoginPERSPECTIVE_ID: TStringField
FieldName = 'PERSPECTIVE_ID'
Size = 45
end
object uqWebLoginLAST_NAME: TStringField
FieldName = 'LAST_NAME'
Size = 35
end
object uqWebLoginFIRST_NAME: TStringField
FieldName = 'FIRST_NAME'
Size = 25
end
object uqWebLoginWEB_LOGIN: TStringField
FieldName = 'WEB_LOGIN'
ReadOnly = True
Required = True
FixedChar = True
Size = 1
end
end
end
// Auth Database to verify logins
unit Auth.Database;
interface
uses
System.SysUtils, System.Classes, IniFiles, Vcl.Forms, MemDS,
Data.DB, DBAccess, Uni, UniProvider, PostgreSQLUniProvider, MySQLUniProvider;
type
TAuthDatabase = class(TDataModule)
uqWebTasksUrl: TUniQuery;
ucETaskAuth: TUniConnection;
MySQLUniProvider1: TMySQLUniProvider;
uqWebTasksUrlUSER_ID: TStringField;
uqWebTasksUrlUSER_NAME: TStringField;
uqWebTasksUrlNAME: TStringField;
uqWebTasksUrlSTATUS: TStringField;
uqWebTasksUrlEMAIL: TStringField;
uqWebTasksUrlACCESS_LEVEL: TIntegerField;
uqWebTasksUrlTASK_RIGHTS: TIntegerField;
uqWebTasksUrlPERSPECTIVE_ID: TStringField;
uqWebTasksUrlLAST_NAME: TStringField;
uqWebTasksUrlFIRST_NAME: TStringField;
uqWebTasksUrlURL_TIME: TDateTimeField;
uqWebTasksUrlURL_TIME_EXP: TIntegerField;
uqWebLogin: TUniQuery;
uqWebLoginUSER_ID: TStringField;
uqWebLoginUSER_NAME: TStringField;
uqWebLoginNAME: TStringField;
uqWebLoginSTATUS: TStringField;
uqWebLoginEMAIL: TStringField;
uqWebLoginACCESS_LEVEL: TIntegerField;
uqWebLoginTASK_RIGHTS: TIntegerField;
uqWebLoginPERSPECTIVE_ID: TStringField;
uqWebLoginLAST_NAME: TStringField;
uqWebLoginFIRST_NAME: TStringField;
uqWebLoginWEB_LOGIN: TStringField;
procedure DataModuleCreate(Sender: TObject);
procedure DataModuleDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
AuthDatabase: TAuthDatabase;
implementation
uses
System.JSON,
Common.Config,
Common.Logging,
uLibrary;
{%CLASSGROUP 'Vcl.Controls.TControl'}
{$R *.dfm}
procedure TAuthDatabase.DataModuleCreate(Sender: TObject);
begin
Logger.Log( 5, 'TAuthDatabase.DataModuleCreate' );
LoadDatabaseSettings( ucETaskAuth, 'emT3XDataServer.ini' );
try
ucETaskAuth.Connect;
except
on E: Exception do
begin
Logger.Log(2, '--TAuthDatabase.DataModuleCreate -Error connecting to database: ' + E.Message);
end;
end;
end;
procedure TAuthDatabase.DataModuleDestroy(Sender: TObject);
begin
ucETaskAuth.Connected := false;
end;
end.
[Auth.ServiceImpl.pas]
SaveTime=4/15/2026 6:21:59 PM
FileCount=1
File0=C:\Projects\emT3web\emT3XDataServer\Source\Auth.ServiceImpl.pas
[Auth.Database.pas]
SaveTime=4/15/2026 6:21:59 PM
FileCount=2
File0=C:\Projects\emT3web\emT3XDataServer\Source\Auth.Database.pas
File1=C:\Projects\emT3web\emT3XDataServer\Source\Auth.Database.dfm
...@@ -2,12 +2,11 @@ ...@@ -2,12 +2,11 @@
MemoLogLevel=4 MemoLogLevel=4
FileLogLevel=4 FileLogLevel=4
webClientVersion=0.8.8 webClientVersion=0.8.8
LogFileNum=161 LogFileNum=169
[Database] [Database]
Server=192.168.102.131
--Server=192.168.116.128
--Server=192.168.102.131 --Server=192.168.102.131
Server=192.168.116.131
--Server=192.168.159.10 --Server=192.168.159.10
Database=eTask Database=eTask
Username=root Username=root
......
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