Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
emiMobile
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Mac Stephens
emiMobile
Commits
09ad9902
Commit
09ad9902
authored
Sep 08, 2026
by
Mac Stephens
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add client version to mismatch errors, server logs, and connected clients
parent
ca97cf69
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
60 additions
and
8 deletions
+60
-8
Api.Server.Module.dfm
emiMobileServer/Source/Api.Server.Module.dfm
+3
-0
Api.Server.Module.pas
emiMobileServer/Source/Api.Server.Module.pas
+10
-1
Auth.ServiceImpl.pas
emiMobileServer/Source/Auth.ServiceImpl.pas
+11
-4
Main.dfm
emiMobileServer/Source/Main.dfm
+12
-0
Main.pas
emiMobileServer/Source/Main.pas
+1
-0
WebSocket.Manager.pas
emiMobileServer/Source/WebSocket.Manager.pas
+16
-2
ConnectionModule.pas
webEMIMobile/ConnectionModule.pas
+3
-1
Module.Websocket.pas
webEMIMobile/Module.Websocket.pas
+4
-0
No files found.
emiMobileServer/Source/Api.Server.Module.dfm
View file @
09ad9902
...
@@ -26,5 +26,8 @@ object ApiServerModule: TApiServerModule
...
@@ -26,5 +26,8 @@ object ApiServerModule: TApiServerModule
object XDataServer1JWT: TSparkleJwtMiddleware
object XDataServer1JWT: TSparkleJwtMiddleware
OnGetSecret = XDataServer1JWTGetSecret
OnGetSecret = XDataServer1JWTGetSecret
end
end
object XDataServer1Forward: TSparkleForwardMiddleware
OnAcceptProxy = XDataServer1ForwardAcceptProxy
end
end
end
end
end
emiMobileServer/Source/Api.Server.Module.pas
View file @
09ad9902
...
@@ -13,7 +13,7 @@ uses
...
@@ -13,7 +13,7 @@ uses
Sparkle
.
HttpServer
.
Module
,
Sparkle
.
HttpServer
.
Context
,
Sparkle
.
HttpServer
.
Module
,
Sparkle
.
HttpServer
.
Context
,
Sparkle
.
Comp
.
CompressMiddleware
,
Sparkle
.
Comp
.
CorsMiddleware
,
Sparkle
.
Comp
.
CompressMiddleware
,
Sparkle
.
Comp
.
CorsMiddleware
,
Sparkle
.
Comp
.
GenericMiddleware
,
Aurelius
.
Drivers
.
UniDac
,
UniProvider
,
Sparkle
.
Comp
.
GenericMiddleware
,
Aurelius
.
Drivers
.
UniDac
,
UniProvider
,
Data
.
DB
,
DBAccess
,
Uni
;
Data
.
DB
,
DBAccess
,
Uni
,
Sparkle
.
Comp
.
ForwardMiddleware
;
type
type
TApiServerModule
=
class
(
TDataModule
)
TApiServerModule
=
class
(
TDataModule
)
...
@@ -23,9 +23,12 @@ type
...
@@ -23,9 +23,12 @@ type
XDataServer1CORS
:
TSparkleCorsMiddleware
;
XDataServer1CORS
:
TSparkleCorsMiddleware
;
XDataServer1Compress
:
TSparkleCompressMiddleware
;
XDataServer1Compress
:
TSparkleCompressMiddleware
;
XDataServer1JWT
:
TSparkleJwtMiddleware
;
XDataServer1JWT
:
TSparkleJwtMiddleware
;
XDataServer1Forward
:
TSparkleForwardMiddleware
;
procedure
XDataServer1LoggingMiddlewareCreate
(
Sender
:
TObject
;
procedure
XDataServer1LoggingMiddlewareCreate
(
Sender
:
TObject
;
var
Middleware
:
IHttpServerMiddleware
);
var
Middleware
:
IHttpServerMiddleware
);
procedure
XDataServer1JWTGetSecret
(
Sender
:
TObject
;
var
Secret
:
string
);
procedure
XDataServer1JWTGetSecret
(
Sender
:
TObject
;
var
Secret
:
string
);
procedure
XDataServer1ForwardAcceptProxy
(
Sender
:
TObject
;
const
Value
:
string
;
var
Accept
:
Boolean
);
private
private
{ Private declarations }
{ Private declarations }
public
public
...
@@ -89,6 +92,12 @@ begin
...
@@ -89,6 +92,12 @@ begin
Middleware
:=
TLoggingMiddleware
.
Create
(
Logger
);
Middleware
:=
TLoggingMiddleware
.
Create
(
Logger
);
end
;
end
;
procedure
TApiServerModule
.
XDataServer1ForwardAcceptProxy
(
Sender
:
TObject
;
const
Value
:
string
;
var
Accept
:
Boolean
);
begin
Accept
:=
True
;
end
;
procedure
TApiServerModule
.
XDataServer1JWTGetSecret
(
Sender
:
TObject
;
procedure
TApiServerModule
.
XDataServer1JWTGetSecret
(
Sender
:
TObject
;
var
Secret
:
string
);
var
Secret
:
string
);
begin
begin
...
...
emiMobileServer/Source/Auth.ServiceImpl.pas
View file @
09ad9902
...
@@ -168,7 +168,8 @@ var
...
@@ -168,7 +168,8 @@ var
iniFile
:
TIniFile
;
iniFile
:
TIniFile
;
webClientVersion
:
string
;
webClientVersion
:
string
;
begin
begin
Logger
.
Log
(
3
,
'AuthService.VerifyVersion called'
);
Logger
.
Log
(
1
,
Format
(
'Client version check started: client="%s"'
,
[
ClientVersion
]));
Result
:=
TJSONObject
.
Create
;
Result
:=
TJSONObject
.
Create
;
TXDataOperationContext
.
Current
.
Handler
.
ManagedObjects
.
Add
(
Result
);
TXDataOperationContext
.
Current
.
Handler
.
ManagedObjects
.
Add
(
Result
);
...
@@ -180,20 +181,26 @@ begin
...
@@ -180,20 +181,26 @@ begin
if
webClientVersion
=
''
then
if
webClientVersion
=
''
then
begin
begin
Logger
.
Log
(
2
,
'AuthService.VerifyVersion: webClientVersion not configured'
);
Logger
.
Log
(
2
,
Format
(
'Client version check failed: client="%s", required version is not configured'
,
[
ClientVersion
]));
Result
.
AddPair
(
'error'
,
'webClientVersion is not configured.'
);
Result
.
AddPair
(
'error'
,
'webClientVersion is not configured.'
);
Exit
;
Exit
;
end
;
end
;
if
clientVersion
<>
webClientVersion
then
if
clientVersion
<>
webClientVersion
then
begin
begin
Logger
.
Log
(
2
,
'AuthService.VerifyVersion: client version mismatch'
);
Logger
.
Log
(
2
,
Format
(
'Client version check failed: client="%s", required="%s"'
,
[
ClientVersion
,
webClientVersion
]));
Result
.
AddPair
(
'error'
,
Result
.
AddPair
(
'error'
,
'Your browser is running an old version of the app.'
+
sLineBreak
+
'Your browser is running an old version of the app.'
+
sLineBreak
+
'Please click below to reload.'
);
'Please click below to reload.'
);
end
end
else
else
Logger
.
Log
(
3
,
'AuthService.VerifyVersion: version check passed'
);
Logger
.
Log
(
1
,
Format
(
'Client version check succeeded: client="%s", required="%s"'
,
[
ClientVersion
,
webClientVersion
]));
finally
finally
iniFile
.
Free
;
iniFile
.
Free
;
end
;
end
;
...
...
emiMobileServer/Source/Main.dfm
View file @
09ad9902
...
@@ -68,6 +68,13 @@ object FMain: TFMain
...
@@ -68,6 +68,13 @@ object FMain: TFMain
end
end
item
item
Expanded = False
Expanded = False
FieldName = 'ClientVersion'
Title.Caption = 'Version'
Width = 80
Visible = True
end
item
Expanded = False
FieldName = 'ConnectedAt'
FieldName = 'ConnectedAt'
Width = 150
Width = 150
Visible = True
Visible = True
...
@@ -162,6 +169,11 @@ object FMain: TFMain
...
@@ -162,6 +169,11 @@ object FMain: TFMain
Size = 30
Size = 30
end
end
item
item
Name = 'ClientVersion'
DataType = ftString
Size = 20
end
item
Name = 'ConnectedAt'
Name = 'ConnectedAt'
DataType = ftDateTime
DataType = ftDateTime
end>
end>
...
...
emiMobileServer/Source/Main.pas
View file @
09ad9902
...
@@ -241,6 +241,7 @@ begin
...
@@ -241,6 +241,7 @@ begin
tblConnectedClients
.
Append
;
tblConnectedClients
.
Append
;
tblConnectedClients
.
FieldByName
(
'ConnectionId'
).
AsString
:=
client
.
ConnectionId
;
tblConnectedClients
.
FieldByName
(
'ConnectionId'
).
AsString
:=
client
.
ConnectionId
;
tblConnectedClients
.
FieldByName
(
'UserId'
).
AsString
:=
client
.
UserId
;
tblConnectedClients
.
FieldByName
(
'UserId'
).
AsString
:=
client
.
UserId
;
tblConnectedClients
.
FieldByName
(
'ClientVersion'
).
AsString
:=
client
.
ClientVersion
;
tblConnectedClients
.
FieldByName
(
'ConnectedAt'
).
AsDateTime
:=
client
.
ConnectedAt
;
tblConnectedClients
.
FieldByName
(
'ConnectedAt'
).
AsDateTime
:=
client
.
ConnectedAt
;
tblConnectedClients
.
Post
;
tblConnectedClients
.
Post
;
end
;
end
;
...
...
emiMobileServer/Source/WebSocket.Manager.pas
View file @
09ad9902
...
@@ -20,6 +20,7 @@ type
...
@@ -20,6 +20,7 @@ type
TConnectedClientSnapshot
=
record
TConnectedClientSnapshot
=
record
ConnectionId
:
string
;
ConnectionId
:
string
;
UserId
:
string
;
UserId
:
string
;
ClientVersion
:
string
;
ConnectedAt
:
TDateTime
;
ConnectedAt
:
TDateTime
;
end
;
end
;
...
@@ -27,6 +28,7 @@ type
...
@@ -27,6 +28,7 @@ type
private
private
FConnectionId
:
string
;
FConnectionId
:
string
;
FUserId
:
string
;
FUserId
:
string
;
FClientVersion
:
string
;
FConnectedAt
:
TDateTime
;
FConnectedAt
:
TDateTime
;
FLastSeenAt
:
TDateTime
;
FLastSeenAt
:
TDateTime
;
FHeartbeatSeen
:
Boolean
;
FHeartbeatSeen
:
Boolean
;
...
@@ -35,6 +37,7 @@ type
...
@@ -35,6 +37,7 @@ type
public
public
property
ConnectionId
:
string
read
FConnectionId
write
FConnectionId
;
property
ConnectionId
:
string
read
FConnectionId
write
FConnectionId
;
property
UserId
:
string
read
FUserId
write
FUserId
;
property
UserId
:
string
read
FUserId
write
FUserId
;
property
ClientVersion
:
string
read
FClientVersion
write
FClientVersion
;
property
ConnectedAt
:
TDateTime
read
FConnectedAt
write
FConnectedAt
;
property
ConnectedAt
:
TDateTime
read
FConnectedAt
write
FConnectedAt
;
property
LastSeenAt
:
TDateTime
read
FLastSeenAt
write
FLastSeenAt
;
property
LastSeenAt
:
TDateTime
read
FLastSeenAt
write
FLastSeenAt
;
property
HeartbeatSeen
:
Boolean
read
FHeartbeatSeen
write
FHeartbeatSeen
;
property
HeartbeatSeen
:
Boolean
read
FHeartbeatSeen
write
FHeartbeatSeen
;
...
@@ -330,6 +333,7 @@ var
...
@@ -330,6 +333,7 @@ var
json
:
TJSONValue
;
json
:
TJSONValue
;
messageType
:
string
;
messageType
:
string
;
userId
:
string
;
userId
:
string
;
clientVersion
:
string
;
connectionId
:
string
;
connectionId
:
string
;
client
:
TConnectedClient
;
client
:
TConnectedClient
;
response
:
TJSONObject
;
response
:
TJSONObject
;
...
@@ -350,6 +354,10 @@ begin
...
@@ -350,6 +354,10 @@ begin
(
not
json
.
TryGetValue
<
string
>(
'userId'
,
userId
))
then
(
not
json
.
TryGetValue
<
string
>(
'userId'
,
userId
))
then
Exit
;
Exit
;
clientVersion
:=
''
;
if
SameText
(
messageType
,
'identify'
)
then
json
.
TryGetValue
<
string
>(
'clientVersion'
,
clientVersion
);
client
:=
TConnectedClient
(
TTMSFNCWebSocketServerConnection
(
AConnection
).
UserData
);
client
:=
TConnectedClient
(
TTMSFNCWebSocketServerConnection
(
AConnection
).
UserData
);
if
not
Assigned
(
client
)
then
if
not
Assigned
(
client
)
then
...
@@ -364,7 +372,10 @@ begin
...
@@ -364,7 +372,10 @@ begin
connectionId
:=
client
.
ConnectionId
;
connectionId
:=
client
.
ConnectionId
;
if
SameText
(
messageType
,
'identify'
)
then
if
SameText
(
messageType
,
'identify'
)
then
client
.
UserId
:=
userId
begin
client
.
UserId
:=
userId
;
client
.
ClientVersion
:=
clientVersion
;
end
else
else
client
.
HeartbeatSeen
:=
True
;
client
.
HeartbeatSeen
:=
True
;
finally
finally
...
@@ -373,7 +384,9 @@ begin
...
@@ -373,7 +384,9 @@ begin
if
SameText
(
messageType
,
'identify'
)
then
if
SameText
(
messageType
,
'identify'
)
then
begin
begin
Logger
.
Log
(
1
,
'WebSocket client identified: '
+
connectionId
+
' - '
+
userId
);
Logger
.
Log
(
1
,
Format
(
'WebSocket client identified: %s - %s - version %s'
,
[
connectionId
,
userId
,
clientVersion
]));
NotifyClientsChanged
;
NotifyClientsChanged
;
end
end
else
else
...
@@ -443,6 +456,7 @@ begin
...
@@ -443,6 +456,7 @@ begin
begin
begin
Result
[
i
].
ConnectionId
:=
FClients
[
i
].
ConnectionId
;
Result
[
i
].
ConnectionId
:=
FClients
[
i
].
ConnectionId
;
Result
[
i
].
UserId
:=
FClients
[
i
].
UserId
;
Result
[
i
].
UserId
:=
FClients
[
i
].
UserId
;
Result
[
i
].
ClientVersion
:=
FClients
[
i
].
ClientVersion
;
Result
[
i
].
ConnectedAt
:=
FClients
[
i
].
ConnectedAt
;
Result
[
i
].
ConnectedAt
:=
FClients
[
i
].
ConnectedAt
;
end
;
end
;
finally
finally
...
...
webEMIMobile/ConnectionModule.pas
View file @
09ad9902
...
@@ -110,7 +110,9 @@ begin
...
@@ -110,7 +110,9 @@ begin
error
:=
''
;
error
:=
''
;
if
error
<>
''
then
if
error
<>
''
then
TFViewErrorPage
.
Display
(
error
)
TFViewErrorPage
.
Display
(
error
+
sLineBreak
+
sLineBreak
+
'Current client version: v'
+
clientVersion
)
else
else
SuccessProc
;
SuccessProc
;
end
,
end
,
...
...
webEMIMobile/Module.Websocket.pas
View file @
09ad9902
...
@@ -120,6 +120,9 @@ var
...
@@ -120,6 +120,9 @@ var
implementation
implementation
uses
ConnectionModule
;
{%CLASSGROUP 'Vcl.Controls.TControl'}
{%CLASSGROUP 'Vcl.Controls.TControl'}
{$R *.dfm}
{$R *.dfm}
...
@@ -619,6 +622,7 @@ begin
...
@@ -619,6 +622,7 @@ begin
msg
:=
TJSObject
.
new
;
msg
:=
TJSObject
.
new
;
msg
[
'message'
]
:=
'identify'
;
msg
[
'message'
]
:=
'identify'
;
msg
[
'userId'
]
:=
userId
;
msg
[
'userId'
]
:=
userId
;
msg
[
'clientVersion'
]
:=
TDMConnection
.
clientVersion
;
EMiMobileWebSocketClient
.
Send
(
TJSJSON
.
stringify
(
msg
));
EMiMobileWebSocketClient
.
Send
(
TJSJSON
.
stringify
(
msg
));
except
except
on
E
:
Exception
do
on
E
:
Exception
do
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment