#1 Re: mORMot 2 » Questions from a noob trying to do a RESTful API » 2025-10-18 12:39:10

I might have read your post in diagonal and misunderstood some parts of it - will read it again big_smile

#2 Re: mORMot 2 » Questions from a noob trying to do a RESTful API » 2025-10-18 11:41:21

you dont have to, you can consume interface based services with any client. For example, apply this patch to the sample and just call /find like

curl 'http://127.0.0.1:11111/find?name=test

and /add

curl http://127.0.0.1:11111/add \
  --request POST \
  --header 'Content-Type: application/json' \
  --data '{
  "name": "test",
  "question": "This is a test?"
}'

#3 Re: mORMot 2 » Questions from a noob trying to do a RESTful API » 2025-10-16 08:43:34

hi gcarreno,

gcarreno wrote:

Alas, the MVC example produces HTML pages. My WEB API will only produce JSON...

Append `/json` at the end of the url to see what happen smile  (it was primarly made for debugging purpose, but it can be consumed as is too).

What about the question about database migration?

I wrote some parts of rock migration, a module used by ProcessWire community (I am pretty sure you know it) so I can clearly see what you have in mind. As you already mentioned, things turn a bit different with a compiled approach but not that much I think.

I've just published a very minimal example here showing how to compare current model table with external table fields to remove orphaned columns. Then, imagine you set up a proper ci/cd pipelnie for example with jenkins and fpc, you could write migration files to be consumed by your flow, compile, deploy. And as mormot is able to serialize any class/record into a json object, writing a migration module similar to what you’d have on cakephp to keep or rollback your db/api definition should be ok. Anyway, nothing native yet big_smile 

Hope this points you in more or less the right direction lol

#4 Re: mORMot 2 » ESChannel exception » 2025-10-14 15:30:09

Small update. I migrated the certificate and fixed the server config, previous error not gone, but a new one:

14/10/2025 17:06:49.512	Enter	70	 mormot.rest.http.client.TRestHttpClientSocket(01b84970) CallBackGet api/timestamp
14/10/2025 17:06:49.512	Enter	70	    mormot.rest.http.client.TRestHttpClientSocket(01b84970) InternalUri GET
14/10/2025 17:06:49.512	Exception	70	 ENetSock {LastError:"nrClosed",Message:"THttpClientSocket.SockInReadLn [#5 Closed]"} [TTicketPull sagas] at 016a2f45 mormot.net.sock.pas TCrtSocket.Bind (5841)  mormot.core.os.windows.inc XorOSEntropy (2311) mormot.core.os.windows.inc XorOSEntropy (2316)  {4 0.27 0.76 8 645.8MB/1.7GB 1db10a01}
14/10/2025 17:06:50.160	Client	70	       mormot.rest.http.client.TRestHttpClientSocket(01b84970) GET api/timestamp status=200 len=12 state=0
14/10/2025 17:06:50.160	Leave	70	    00.654.548

Then I patched two machines TLS with KB3140245, and imported missing intermediate certs into Windows 7/10 clients and then no more SEC_E_MESSAGE_ALTERED.

#5 Re: mORMot 2 » ESChannel exception » 2025-10-13 13:39:58

Idk if the following is related and could give some hints. I have the same issue on Windows 7; Recently, we switched new deployed computers on Windows 10 and the same issue is happening.

The current http server is apache reverse proxy for a specific reason using a Sectigo RSA certificate. Actually, I havn't tried to fix it, but I observed the following:
- on my own computer, the error isn't triggered.
- some months ago, I could fix it on Windows 7 by registering missing certs on the local certificate store.

So on my side, I suspect a problem on the certificate chain. I will have more info in the next day as we have renewed the certificate and I will update the server conf.

25/06/2025 07:49:02.464	Enter	73	 mormot.rest.http.client.TRestHttpClientSocket(77b1a0).CallBackGet api/timestamp
25/06/2025 07:49:02.464	Enter	73	    mormot.rest.http.client.TRestHttpClientSocket(77b1a0).InternalUri GET
25/06/2025 07:49:03.560	Exception	73	       ESChannel {Message:"<the.domain.fr>: HandshakeStep returned 8009030F [SEC_E_MESSAGE_ALTERED], System Error 5 [ERROR_ACCESS_DENIED]"} [] at 01285bdf mormot.net.sock.windows.inc TSChannelNetTls.ESChannelRaiseLastError (1927)   {65529.79 4.99 12 0.8GB/2GB 1db10a01}
25/06/2025 07:49:03.560	Exception	73	       ESChannel {Message:"recv: Handshake aborted"} [] at 01285d26 mormot.net.sock.windows.inc TSChannelNetTls.FreeAndCheckSocket (1948)   {65529.79 4.99 12 0.8GB/2GB 1db10a01}
25/06/2025 07:49:03.560	Exception	73	       ESChannel {Message:"recv: Handshake aborted"} [] at 01285d26 mormot.net.sock.windows.inc TSChannelNetTls.FreeAndCheckSocket (1948)   {65529.79 4.99 12 0.8GB/2GB 1db10a01}
25/06/2025 07:49:03.560	Client	73	       mormot.rest.http.client.TRestHttpClientSocket(77b1a0) GET api/timestamp status=666 len=0 state=0
25/06/2025 07:49:03.560	Leave	73	    01.102.694
25/06/2025 07:49:03.560	Enter	73	    mormot.rest.http.client.TRestHttpClientSocket(77b1a0).InternalUri GET
25/06/2025 07:49:04.720	Client	73	       mormot.rest.http.client.TRestHttpClientSocket(77b1a0) GET api/timestamp status=200 len=12 state=0
25/06/2025 07:49:04.720	Leave	73	    01.173.370
25/06/2025 07:49:04.720	Service return	73	    mormot.rest.http.client.TRestHttpClientSocket(77b1a0) 135919590467
25/06/2025 07:49:04.720	Leave	73	 02.276.213

The issues I'm aware of (using ssl tools):
- The chain doesn't contain any intermediate certificates

#6 Re: mORMot 2 » mORMot2 (2.3 stable) fail to create x64 package » 2025-10-08 14:18:23

@FlaviusFX, I think it's related to the following, I remember it was fixed a few days later after the release, read issues #306 on github.

#7 Re: mORMot 2 » How can I get secret from TJwtHS256? » 2025-10-08 08:56:27

This is beyond the scope of jwt thing, you didn't described how you are adding user and I then assume you are adding manually an user into the external auth user table: if ORM cache is enabled, then this behavior is expected. You could read that you are hitting orm cache on the console by enabling server logs (and by reading the manual).

Thats said, set db.usecache to false or write a small rest client tool for adding your users..

#8 Re: mORMot 2 » How can I get secret from TJwtHS256? » 2025-10-07 09:13:30

I can help your but put some efforts smile
just share the file

#9 Re: mORMot 2 » How can I get secret from TJwtHS256? » 2025-10-07 06:37:21

I see, your file is probably missing something or contain a bad formatting. Swagger doesn't care about the server itself, it's about the file definition.

#10 Re: mORMot 2 » How can I get secret from TJwtHS256? » 2025-10-06 16:28:33

I dont understand this one sorry - if you mean swagger editor, you will get a button if you define some security schemes.  Which api definition are  you talking about ?

#11 Re: mORMot 2 » How can I get secret from TJwtHS256? » 2025-10-06 12:42:05

Yes I've read your comment (I edited it on the PR smile )  It was not really a bug but a change on the framework implementation. I didn't had the time to push my changes and merging @koraycayiroglu code.

Is it possible to create interface based service for authentication and use it in client side?

Yes you can, just register your service with bypassauthentication true. On the initial sample they were implemented as service methods as I think it fit better to access service context. You can mix both interface/service methods without problem.

#12 Re: mORMot 2 » How can I get secret from TJwtHS256? » 2025-10-05 16:12:17

The secret is the same as the param you set on TJwtHS256.Create if SecretPbkdf2Round is 0. If you didn't modified the public example then a new secret is generated on each server start and it's the sha256 hash of a random guid, see there.

Just set a breakpoint and copy the value, or echo the key on the console (or generate a new hash from a dummy secret) and then copy paste the key on jwt.io, you should get a valid signature.

#13 Re: mORMot 2 » lists in objects to Json » 2025-10-01 08:08:04

Personal taste, I feel more comfortable using IDocDict/List. Maybe take a look at this blog post if it helps (check the advanced features: filtering, searching):

https://blog.synopse.info/?post/2024/02 … hi-and-FPC

#14 Re: mORMot 2 » Issue with SetUser after introducing Modular Crypt » 2025-09-30 10:42:03

Indeed, I forgot this one big_smile

It's working as expected smile

#15 Re: mORMot 2 » Issue with SetUser after introducing Modular Crypt » 2025-09-30 10:06:08

Hi @ab, I did some testing - Delphi 12.3 and FPC - and then:

- without rsoPerConnectionNone, client auth is fine (this was failing).
- enabling rsoPerConnectionNone, client fail at CheckPassoword()

fServer.fOptions:

[rsoNoInternalState,rsoNoTableURI,rsoMethodUnderscoreAsSlashUri,rsoPerConnectionNonce]
srvr       mormot.rest.server.TRestServerRoutingRest(0334c340)   Method GET root/auth?username=Admin=200 out=77 B in 3.09s
ret         ServerApiHost.TAppServer(033e9f40) Method len=77 {"result":"bd1a5ead8e255448fd09484e56e33a66ea8cefc3f6d3804735cb6cf7a46881c0"}
[debug] GET /root/auth?username=Admin&password=e23f6a5756da303c6b36de49077cb51d6828768a2763b0b82678122deba05ac8&clientnonce=58671B01_0fb7691644db0de2e1bd776ed8466eb2
[BeforeBody][aInHeaders]: 
  - X-Real-IP: 127.0.0.1
  - X-Forwarded-For: 127.0.0.1
  - X-Forwarded-Proto: https
  - X-Conn-ID: 17
  - Accept: */*

#16 Re: mORMot 2 » Issue with SetUser after introducing Modular Crypt » 2025-09-29 18:52:44

Ah! I checked the nginx configuration, the X-Conn-ID header is the only one missing - I didn't paid attention. Thanks you, I will test tomorrow.

#17 Re: mORMot 2 » Issue with SetUser after introducing Modular Crypt » 2025-09-29 14:17:26

I will look at it, the nginx config was kept minimal with a simple proxy_pass for testing. The demo program return both 200 OK (direct and nginx) if the server is compiled on last commit before 65e4597. Once I compile the server starting on commit 65e4597, then it fail on nginx only..

I will try again with a minimal server and report it here.

#18 Re: mORMot 2 » Issue with SetUser after introducing Modular Crypt » 2025-09-29 09:43:03

Is it just me, or am I the only one running into this issue? neutral

#19 Re: mORMot 2 » lists in objects to Json » 2025-09-29 09:39:23

I have provided you with examples there last day: D-H-R/mormot_json/issues/1


ab wrote:

And it is really funny how grok is even more hallucinating, the more you give him corrections.

I admit I feel like the more thinking they try to do, the more they tend to hallucinate...

#20 Re: mORMot 2 » Authentication » 2025-09-27 18:40:59

It was a sort of pseudo-code, MvcApp could have been a public property.  Glad you get it working, i suggest you to read mormot.core.mvc and mormot.rest.mvc to learn about what @ab said in previous post and to optimize your setup.

#21 mORMot 2 » Issue with SetUser after introducing Modular Crypt » 2025-09-26 19:49:35

flydev
Replies: 10

Hi @ab, I have an issue with TRestHttpClient.SetUser which is not working starting on this specific commit, and tested yet only on Delphi 12.3

65e4597 - rest: make server nonce unique per connection/client - our authentication scheme is now as secure as SCRAM could be, and even more since we feature strong "Modular Crypt" hashes like BCrypt or SCrypt smile - still compatible with old mORMot 1 clients

What happen: 

- It work using direct connection to server host (localhost, 192.168.*)
- it doesn't work behind NGINX on 80/http and 443/https

I havn't debugged yet as you might have an answer.

On the test program shown below, the client is a simple TRestHttpClient.SetUser and compiled on commit a919746 from july, 29. I get the same result compiling both server and client on commit 65e4597 or newer. I have saved logs just in case.

Client on left side get HTTP 200, on right side the client get a HTTP 403 return code.

3-D476-DE9-FEC1-4879-B632-9-EDACCCCC40-D.png

#22 Re: mORMot 2 » Authentication » 2025-09-26 10:58:28

To avoid writing same code over each method, you could set a service on a TRestServer to handle backend logic and attach your MVC instance to it. Then inherit your interfaces with something like that (TAppService will have access to CurrentSession):

  
  TAppService = class(TInjectableObjectRest)
  protected
    function TryGetSessionCookie(out S: TCookieData): boolean;
    function GetLoggedAuthorID(Right: TOrmAuthorRight): TID;
    function HasRight(Right: TOrmAuthorRight): boolean;
  end;
  
  TAppServer = class(TRestServerDB)
    FMvcApp: IMvcApplication;
    FAppService: TAppService;
  end;

then create a instance with a resolver and rest:

FMvcApp := ...
FAppService := TAppService.CreateWithResolverAndRest(Self.ServiceContainer, nil, Self);

TryGetSessionCookie implementation could look something like:

function TAppService.TryGetSessionCookie(out S: TCookieData): boolean;
begin
  result := false;
  S := Default(TCookieData);
  result := TAppServer(Server).MvcApp.CurrentSession.CheckAndRetrieve(@S, TypeInfo(TCookieData)) > 0;
end;

Write a service to handle backend logic:

TServiceResult = (seSuccess, seNotFound, seMissingField, sePersistenceError);

IBackendService = interface(IInvokable)
  ['{A513EF1E-62B1-44A3-A2A0-7F3A6E6F19E4}']
  function NewArticle: TServiceResult;
  function UpdateArticle(aPage: TPage): TServiceResult;
  function DeleteArticle(aID: TID): TServiceResult;
  // ...
end;

// inherit from TAppService
BackendService = class(TAppService, IBackendService)
  // ...
end; 

then register the backend service as usual on the rest server:

Self.ServiceDefine(TBackendService , [IBackendService]);

The JS client can then log in, get cookie and make backend calls... You could also hook on the *Uri rest events to set a custom "gate" logic.

Hope you get the idea...

#23 Re: mORMot 2 » ECDSA signature verification, how to do it correctly? » 2025-09-11 14:09:01

Why your function returns False
•  Assumes signature is always raw 64 bytes (R||S)
•  Your check Length(...) <> SizeOf(TEccSignature) exits early for any DER signature. OpenSSL (and many toolchains) output DER. So you never reach Verify for DER input.
•  Public key format mismatch
•  lCertificate.GetPublicKey returns the X.509 SubjectPublicKey (SPKI) in ASN.1. TCryptAsym.Verify expects EC public key in one of a few raw/PEM/DER encodings it can parse; SPKI isn’t always accepted directly by its low-level PemDerRawToEcc(). You either need to rewrap the SPKI to the EC compressed key DER, or use ICryptCert.Verify (which does that internally).
•  Data bytes/encoding

---

read code in gist

credit: gpt

ps: I tested the code


@ab: do you think the ai-model hallucinated?

#24 Re: mORMot 2 » Regression with RootRedirectToURI » 2025-09-02 11:11:54

ab wrote:

I did not remember changing anything about RootRedirectGet.

Just throwing this out there, it might have zero impact, but I noticed it while reading last month's commits: rsoAllowSingleServerNoRoot (this option was in fact not implemented at all in mORMot 2 !)


ITWT lol  désolé lol lol

#25 Re: mORMot 2 » Retrieve JSON value » 2025-08-21 21:19:37

You are missing the object creation that will trigger an AV and use ObjectToJson, not JsonEncode.

function TUtilisateursService.GetUtilisateur(aID: TID): RawJSON;
var
  obj: TOrmUtilisateurs;
begin
  obj := TOrmUtilisateurs; // <- missing create
  try
    if not fClientDB.Orm.Retrieve(aID, obj) then 
      raise ERestException.Create('404 - Utilisateur non trouvé');

    Result := ObjectToJson(obj); 
  finally
    obj.Free;
  end;
end;

ou

function TUtilisateursService.GetUtilisateur(aID: TID): RawJSON;
var
  obj: TOrmUtilisateurs;
begin
  obj := TOrmUtilisateurs.Create(fClientDB.Orm, aID);
  try
    if ID = 0 then
      raise ERestException.Create('404 - Utilisateur non trouvé'); 

    Result := ObjectToJson(obj); 
  finally
    obj.Free;
  end;
end;

read there: SAD1.18 5.2. Working with Objects

#26 Re: mORMot 2 » WSS Authentication » 2025-08-18 12:49:02

to check the command you show you could do it in InBeforeBody, you could validate specific upgrade in flags hsrConnectionUpgrade.

edit: what @ab just said

#27 Re: mORMot 2 » WSS Authentication » 2025-08-18 09:15:18

If it helps you find the way, on my side, I use TWebSocketProtocol.UpgradeBearerToken for that: read more there

#28 Re: mORMot 2 » Timestamp raises an EXCEPTION_ACCESS_VIOLATION when release build. » 2025-08-18 08:16:04

FYI you can make code simpler with

with ServiceDefine(TAdmin, [IAdmin], sicPerSession, SERVICE_CONTRACT_NONE_EXPECTED) do
begin
  ResultAsJSONObjectWithoutResult := True;
  SetOptions([], [optErrorOnMissingParam])
end;

#29 Re: mORMot 2 » Check Out This AI-Generated Podcast on mORMot 1.18 SAD » 2025-08-18 07:55:29

zen010101 wrote:

I’ve always felt that current large language models aren’t very friendly toward Object Pascal

don't be fooled ..

Microsoft wrote:

What data has GitHub Copilot been trained on?

GitHub Copilot is powered by generative AI models developed by GitHub, OpenAI, and Microsoft. It has been trained on natural language text and source code from publicly available sources, including code in public repositories on GitHub.

.. and it's not the only data source; You know.. personal privacy.. checkbox.. big-data, etc...

the mORMot framework is so BIG and complex that inputting a relatively small number of tokens rarely yields effective outputs.

The main issue, IMO, comes from when most datasets were built. The first public release of mormot v2 was around late 2020 (first commit in march 2020), but by then the models had already ingested mormot v1 source code. That’s why on gpt-3, gpt-4 (and even gpt-5!), you often get v1-based code in the answers - I'am quite sure you got the TSqlModel instead of TOrmModel things, etc.  which is why the “big prompt” is actually useful.

Also, if you let your tools adapt to your own habits, you’ll naturally get better results. On my side, no matter what I ask, I always end up with a marmot somewhere in the answer big_smile

#30 Re: mORMot 2 » Check Out This AI-Generated Podcast on mORMot 1.18 SAD » 2025-08-17 18:41:20

I mostly use cursor for frontend tasks, like building React dashboards or working with (syn)mustache templates (it actually works really well on Pascal codebases too). But I have to admit - warp terminal is a beast. I will try to make you a small demo if you’re interested.

To be honest, the real secret is to simply RTFM for each tool and configuring it properly, then taking the time to create a solid project structure (folder tree, rules, contextual prompts, etc) and calling the right model for a given task. The models to be used is now gpt-5 (truly impressive), claude-4-thinking and gemini-2.5-pro-thinking.

I'am not following ai trends closely but I'am quite sure claude-5 is in the pipe.

#31 Re: mORMot 2 » Check Out This AI-Generated Podcast on mORMot 1.18 SAD » 2025-08-17 17:40:37

zen010101 wrote:

Do you mean that through mcp-delphi, the tokens input to Gemini or ChatGPT can be significantly reduced? I'm sorry, but I'm a bit confused about how this is achieved. Could you give us some hints? smile

No. At this moment, the mcp-delphi server only allows AI agents to use your IDE to compile your project (Delphi, Lazarus, or FPC directly) and get the output, nothing more. That said, if your coding tool supports "auto-mode", you can let the agents create, compile, and fix the project for you - while you’re cooking, for example big_smile I tried it with gpt-5, project built successfully and potatoes where not burnt lol.

Then I thought it could be useful to have a dedicated MCP server for working with mormot. It would definitely reduce the number of tokens consumed, since the agents would be able to query a well structured knowledge base for the relevant part of the framework instead of injecting a huge prompt. I also believe the agents would "think" better as their memory context wouldn’t be overloaded.

#32 Re: mORMot 2 » Am I using JWT correctly? » 2025-08-15 14:30:56

Cool, thanks for the contribution  smile - I’ll ping you on the PR once I’ve compared it with the pushed changes

#33 Re: mORMot 2 » Am I using JWT correctly? » 2025-08-15 14:22:35

koraycayiroglu wrote:

made a pull request too

Thanks! I’ll review it this weekend. Is it based on the latest mORMot update?

#34 Re: mORMot 2 » Am I using JWT correctly? » 2025-08-15 14:17:19

Thanks for sharing, @koraycayiroglu.

I’ve since refactored parts of the setup and will clean and push the changes to the repo. For example:

We now use ServiceRunningContext via a locally assigned PServiceRunningContext variable.

I addressed an oddity in the token refresh flow — previously it retrieved logonname and password from query strings. Instead, I now generate a token_refresh_uuid embedded in the token payload, and retrieve the logonname from the built-in jcIssuer. This allows validating the user by combining it with the sessionkey.

The goal is to send credentials only once to obtain a valid JWT, and never send them again.

#35 Re: mORMot 2 » Check Out This AI-Generated Podcast on mORMot 1.18 SAD » 2025-08-14 07:17:54

I published a MCP server for delphi and lazarus/fpc; I am working on a special setup focused on mormot2. I must say from my tests with gemini - and now gpt-5 included - it's quite amazing. Token usage will be reduced a lot compared to "the-big-prompt".

You can find it there: https://github.com/flydev-fr/mcp-delphi

#36 Re: mORMot 2 » can we operate multi Postgres schemas? » 2025-08-10 08:46:33

keinn wrote:

The way I learned to use Mormot was by conducting a global search for potential keywords, which was quite challenging.

I thought SAD 8.3[.6] (External database ORM internals) and api/mORMotDB.html might help clarifying.

#37 Re: mORMot 2 » TGuid orm property (RTTI) » 2025-07-24 09:13:34

at least I get some more doc to ingest.

ab wrote:

Default "const" would pass it as two registers, not as a single register pointer.  sad

Aw nasty. Thanks you ab

#38 Re: mORMot 2 » TGuid orm property (RTTI) » 2025-07-23 22:23:00

I still didn't found where it happen exactly - in DecodeUriParametersIntoJson, InBody is built correctly with an uuid string in a json array. The issue seem happening elsewhere and deeper in ExecuteJson(). I will continue tomorrow.

I could observe that it happen only when the parameter is defined as const (required with TServiceCustomAnswer as return type) and then found that a method like:

function Example(const uuid: TGUID): RawUtf8;

.. produces the same problem. If using var/out TGUID, result is ok.

#39 Re: mORMot 2 » TGuid orm property (RTTI) » 2025-07-23 17:29:28

I just tested with `curl http://localhost:9088/api/main/UserService.ReadTest?user_uuid=3C28EA56-37FE-4ABC-A0B7-508D8C634E21` and I have the very same issue, result:

uuid is: 17868178-0000-0000-0000-000000000000

Then I have also compiled the server on ubuntu and same problem. FPC version on Ubuntu is 3.3.1. The lazarus project file is based on MVCServer.lpi with -Xm and compiled without optimization. I will test it with a simple and new project..


---

Edit: 

I have created a new simple project on ubuntu and compiled, result is the same, the guid is wrong.

#40 Re: mORMot 2 » TGuid orm property (RTTI) » 2025-07-23 17:03:53

1) Yes, but maybe I was unclear earlier, I cross-compile for both Windows and Linux on my Windows machine (FPC 3.2.2). I must say that I have compiled it directly on Ubuntu two months ago and got the very same issue.
2) no unit windows. I traced it to objpash.inc, line 134.

The server is behind nginx. The GUID param received on Linux is not null, but incorrect.

I compiled for linux and windows with "clean up and build" before posting here. Test results:

Linux: uuid is: 40918D38-0000-0000-0000-000000000000
Windows: uuid is: 3C28EA56-37FE-4ABC-A0B7-508D8C634E21 (as expected)   

- Logs Linux:

$  +         AuthServer.TRestServerAuth(408199d0) URI GET api/main/UserService.ReadTest?user_uuid=3C28EA56-37FE-4ABC-A0B7-508D8C634E21 in=0 B
$ call               AuthServer.TRestServerAuth(408199d0) UserService.ReadTest len=40 ["3C28EA56-37FE-4ABC-A0B7-508D8C634E21"]
$ srvr               RestJwtAuth.TRestRoutingREST_JWT(70f85803e000)   Interface GET api/main/UserService.ReadTest?user_uuid=3C28EA56-37FE-4ABC-A0B7-508D8C634E21=200 out=51 B in 555us
$ ret                AuthServer.TRestServerAuth(408199d0) Interface len=51 uuid is: 40918D38-0000-0000-0000-000000000000

- Logs  Windows:

+         AuthServer.TRestServerAuth(05ddad08) URI GET api/main/UserService.ReadTest?user_uuid=3C28EA56-37FE-4ABC-A0B7-508D8C634E21 in=0 B
call       AuthServer.TRestServerAuth(05ddad08) UserService.ReadTest len=40 ["3C28EA56-37FE-4ABC-A0B7-508D8C634E21"]
srvr      RestJwtAuth.TRestRoutingREST_JWT(06389a18)   Interface GET api/main/UserService.ReadTest?user_uuid=3C28EA56-37FE-4ABC-A0B7-508D8C634E21=200 out=51 B in 439us
ret       AuthServer.TRestServerAuth(05ddad08) Interface len=51 uuid is green: 3C28EA56-37FE-4ABC-A0B7-508D8C634E21

I will test with curl on the linux server without nginx in about 15 minutes.

#41 Re: mORMot 2 » TGuid orm property (RTTI) » 2025-07-22 14:23:52

Again, just a small question about TGUID as I’m hitting a cross-platform snag with FPC 3.2.2 but with TGUID defined as param on SOA:

IUserService = interface(IInvokable)
['...'] 
  function Read(const user_uuid: TGUID): TServiceCustomAnswer;
end;

- Win64 build (FPC 3.2.2): user_uuid arrives with the expected value.
- Linux x86-64 build (same sources & FPC version): user_uuid is always null.

Is this due to missing record RTTI for TGUID under FPC on Linux?
I can tackle the problem by passing it as RawUtf8, but I'am asking for my own knowledge.

thanks smile

#42 Re: mORMot 2 » How to get unescaped json string from IDocList » 2025-07-17 14:41:54

Hi, because it's a string, it's appending a string item to a json array.
Use IDocDict to add an object:

LDocList.AppendDoc(DocDict(['text', 'test']));

or you can serialize directly:

LDocList.Json := '[{"text": "test"},{"text": "test2"}]'; // don't make sense: `DocList('[{"text": "test"}]');`

when the array (Len) is not empty, you can assign an object directly to it using:

LDocList.O[1] := DocDict(['text', 'test2 is now test3']);

#43 Re: mORMot 2 » MVC rendering » 2025-07-14 11:04:03

@Alek, to force partial changes to be reloaded, apply theses modifications:

on mormot.rest.mvc.pas#L181 add:

FViewPath: RawUtf8;

and the public property:

property ViewPath: RawUtf8 read FViewPath write FViewPath;

on line mormot.rest.mvc.pas#L1245 add:

{$ifdef DEBUG}
fViewPartials.ViewPath := folder;
{$endif}

replace mormot.core.mustache.pas#L1317-L1332 with:

function TSynMustachePartials.GetPartial(
  const PartialName: RawUTF8): TSynMustache;
var
  i: PtrInt;
  Temp: TSynMustache;
begin
  if self=nil then begin
    result := nil;
    exit;
  end;
  i := fList.IndexOf(PartialName);
  if i<0 then
    result := nil
  else 
  begin
    // Partial files by default in mORMot are loaded just once and then cached which is very bad
    // during debugging when files are changed and it requires constant restart of the application.
    // With this change we're disabling cache in debugMode: -dDEBUG on fpc
    Result := TSynMustache(fList.Objects[i]);
    {$ifdef debug}
    begin
      Temp := TSynMustache.Parse(AnyTextFileToRawUTF8(UTF8ToString(MakePath([FViewPath, PartialName + '.partial'])), true));
      if Temp.Template <> '' then
        Result := Temp;
    end;
    {$endif debug}
  end;

@ab, any chance you consider adding it or similar - or did we missed something?

---
Edit: I missed last post of @ab - watching for files changes and triggering FlushAnyCache() should be the right way to do it while developping. Anyway, the method presented here still make getting partial markup changes easier.
---


Alek wrote:

UPDATED: and I also don't quite understand the meaning of the variables.

I made a gist trying to explain it (should be correct), read there: https://gist.github.com/flydev-fr/e0f0a … c2ac78f2bc


Call FlushAnyCache when you change data in your model. If I am correct, on the blog sample, the default data is cleared and filled with new data again if empty on GetViewInfo(). The method is virtual so you can implement your own flush logic there.

#44 Re: mORMot 2 » mORMot 2 support Delphi Mobile compiler ? » 2025-06-26 08:35:15

itSDS wrote:

... i think no one will make a server on mobile platform.

Sure — but on the other hand, I know a few friends in the IT sec field who would be stunned to carry a mobile phone running a dedicated app instead of walking around with an offline raspberry or any other pocket device.


ab wrote:

I started working on it.

When I was doing my daily commit reading, I couldn't help but smile wide… and the image of @ab that popped into my head was .. lol lol lol

782L.gif

#45 Re: mORMot 2 » Access violation writing to address » 2025-06-22 09:07:24

I can't reproduce it - it work as expected at least on fpc 3.2.2.

edit: ... and mormot 2.3.10775

#46 Re: mORMot 2 » Transaction with Multi-Table » 2025-06-20 13:39:23

@fatimaEzz, unit is "mormot.crypt.secure". 

protip: consider using a specialized tool to perform recursive content searches within a specified folder (/mormot/src), eg. Agent Ransack (free).

#47 mORMot 2 » [proposal] Add GetSetCsvValueTrimmed() for scoped set parsing » 2025-06-02 14:33:50

flydev
Replies: 0

hi @ab,

I'd like to propose the addition of a helper function in `mormot.core.rtti.pas` to enhance support for parsing scoped CSV values into enum sets.

About use case, in JWT-based APIs, I often use enum sets encoded as scoped strings such as: `users:create,users:read,system:logs`
These values are not directly mappable using `GetSetCsvValue()` due to their prefixed format (I might missed an existing gem!).

I wrote a helper named `GetSetCsvValueTrimmed()` which uses `TrimOneChar()` to remove the scoped prefix before matching against enumeration names (maybe another internal function would be more appropriate):

/// Parse a delimited list of scoped identifiers into a set, returned as a 64-bit bitmask
// - each entry in the CSV should follow a scoped naming pattern, e.g. 'users:create'
// - the prefix separator (scopeChar) is customizable and defaults to ':' if not specified
// - this function is similar to GetSetCsvValue(), but will remove the scope prefix
//   from each identifier before matching it against the enumeration names
// - returns 0 on parsing failure, or if none of the values map to known enum items
// - expects aTypeInfo to point to a set of enumerations with matching names
function GetSetCsvValueTrimmed(aTypeInfo: PRttiInfo; Csv: PUtf8Char; scopeChar: AnsiChar = ':'): QWord;  
function GetSetCsvValueTrimmed(aTypeInfo: PRttiInfo; Csv: PUtf8Char; scopeChar: AnsiChar): QWord;
var
  tmp: RawUtf8;
begin
  result := 0;
  if (Csv = nil) or (Csv^ = #0) or (aTypeInfo = nil) then
    exit;
  // remove scopes like 'users:' or 'system:' prefixes from each value
  tmp := TrimOneChar(Csv, scopeChar);
  result := GetSetCsvValue(aTypeInfo, pointer(tmp));
end;  

If it makes sense, I also wrote unit tests to validate typical JWT-like scope strings.

type 
  TEnumPetStorePerm = (
    epsPermNone, epsStoreRead, epsStoreWrite);
  TEnumPetStorePermSet = set of TEnumPetStorePerm;

  checkEqual(GetSetCsvValueTrimmed(TypeInfo(TEnumPetStorePermSet), 'store:read,store:write'), 6, 'TEnumPetStorePerm');
  // ...

Thanks!

#48 Re: mORMot 2 » ORM-Wrapper for mysql/maria/sqlite in one » 2025-05-29 13:11:09

I published a gist with a working example (mormot2), assuming a TAuthUser is on external db, feel free to change the table name with one of your..

/flydev-fr/84f808d5ff184df6036e54ac03dd43ab

#49 Re: mORMot 2 » ORM-Wrapper for mysql/maria/sqlite in one » 2025-05-29 12:51:47

TRestClientDB use an hidden TRestServerDB; you could map to an external db for example this should work:

Props := TSQLDBZEOSConnectionProperties.Create(...);
Props.ThreadSafeConnection.Connect;
OrmMapExternal(aORMSQLModel, [TYourOrmMapped], Props);
ORMDB:= TRestClientDB.Create(aORMSQLModel, nil, ':memory:', TRestServerDB, False, StringToUtf8(aPassword));
TRestServerDB(ORMDB.Server).Server.CreateMissingTables(0, [itoNoAutoCreateUsers]);

#50 Re: mORMot 2 » ORM-Wrapper for mysql/maria/sqlite in one » 2025-05-29 10:19:00

I dont really get what you are asking specifically, but did you took a look at /ex/extdb-bench or mongodb & techempower samples? also read test.orm.extdb.pas from test folder.


Basically to get a TRestServerDB virtually working with MariaDB, there is a generic connection definition:

  // 1. Define your external SQL connection
  Props := TSQLDBZEOSConnectionProperties.Create(
    FormatUtf8('zdbc:mysql://127.0.0.1:%/%?username=%;password=%',
      DB_PORT, DB_SOURCE, DB_USERNAME, DB_PASSWORD]),
      'aSqlite3.db', DB_USERNAME, DB_PASSWORD);
  Props.ThreadSafeConnection.Connect;
  // 2. Define your model and ORM mapping
  Model := TOrmModel.Create([TOrmSomething]);
  OrmMapExternal(Model, [TOrmSomething], Props);
  // 3. Create the REST server, mapped to the external DB
  Server := TRestServerDB.Create(Model);
  Server.Server.CreateMissingTables;

Board footer

Powered by FluxBB