Closed akkarawat2000 closed 1 year ago
Thanks for reaching out with your problem. I will investigate a bit further later today. After watching your video (very detailed and helpful!) I did have a couple of questions. Not likely to solve the problem, but just questions about the choices you made.
The convert error may be due to having a different date/time format but I will check in a little while what else might be causing the problem.
Hi , Andrew
Thank you for quick reply
and another problem I found during install first time have many issue like this
Loading Configuration ... ...Configuration File Not Found: C:\Data\Config.json ...Using Default Conf iguration Done.
I don't have Config.json
and have another issue , I will show to you again on video for easy explain and you will make it easy for complile first time for beginner like me .
please check my attach file .
Thank you
Akkarawat
Ok, I've never encountered a date so far in the future! I'll test with that and with your preferred date format. Note that when the API key record is created by default when the database is first created, it is valid sometime in the future, but as long as everything is in that date range, it shouldn't matter.
The Config.json file is something you can add yourself, but if you don't add one with your own customizations, it should create one on its own, so that shouldn't be a problem. I'll add something to the docs about what goes in it (if it isn't already there) as soon as I figure out what the ConvertError problem is.
It seems to be related to the API key valid date (converting between the UTC date from SQLite and local time) but I'm still working on figuring out why it is causing an error.
Thank you , I will wait you fix this problem but I hope you can fixed this problem soon because I see your source code I very like it , It's look easy understand and you made look professional . I will learn it from you sourcode in real situation
because example from TMS Software it's very basic and hard for figure out how to coding in real application.
Thank you for you share knowledge and experience .
Lastly I miss Canada , Vancouver too much I ever go to your country at age 23 your country very beautiful but very cold for me . haha
Yes, much colder than Thailand, at least in the winter months.
The date is causing problems - I can't even load swagger when my date is set to 2566 as the certificates it uses are no longer valid? Can you test if you have this problem using a 2023 date instead? Are there routinely problems with using dates so far in the future? That should break all kinds of certificates when browsing the web normally I would think.
The error is coming from SQLite when it tries to convert a date in to a Delphi TDateTime value. Still working on why that is, even with dates in the 2023-range.
Give this a try... In Unit2.pas, at the beginning of FormCreate, add the following lines.
// Let's use these internally for consistency
FormatSettings.DateSeparator := '-';
FormatSettings.ShortDateFormat := 'yyyy-mm-dd';
FormatSettings.TimeSeparator := ':';
FormatSettings.ShortTimeFormat := 'hh:nn:ss';
It seems that when using Query1.FieldByName('valid_until').AsDateTime, if the local system date format isn't in the above format, then it can't do the conversion. So let's set the local system date format to be what we are expecting it to be. This seems to work out ok.
I've updated the repository with this change as well.
Now, you should be able to generate a JWT from the Login endpoint in Swagger. Note that you should copy the whole thing, including the 'Bearer ' prefix, into the Swagger authorization edit field.
I've also added a bit of documentation regarding the Config.JSON file.
Hi , Andrew
I summary about problem for first time run your example please check from this video
https://www.youtube.com/watch?v=HwfESEnR7Hw
Thank you.
Akkarawat
Hi , Andrew
I made another video about Login Problem . please check this video
https://www.youtube.com/watch?v=4Fd5Zgpxbbg
Thank you
Akkarawat
Hi there...
There are a lot of different items in your videos. I will try and work through them all, but it will take me a little time to sort through them in this thread. In future, if you could post each issue or question in a separate issue here, it would make it easier to respond to them, and also help ensure I don't overlook any of them.
The first item I'd like to cover is about the login using Swagger.
When you use the Authorize button at the top of the Swagger page, the only thing that should be entered into the field is the JWT that is generated from the Login endpoint. And this is usually the first thing you should do when testing most of the other endpoints in Swagger (except for the Login and Info endpoints and one or two others, which do not need to be authorized). If you get an error 403 from an endpoint, it usually means that you have to get another JWT from the Login endpoint and use it to login with the Swagger button at the top of the page.
Here's an example of what this normally looks like.
Next, a comment about timestamps.
Nearly everything in the project refers to dates and times as UTC or GMT dates and times. Certainly anything stored in the database should be stored in that timezone (zero offset). Anytime we take dates or times and present them to the user, they are converted into the local timezone and optionally displayed in a regional format. Almost none of that happens in this project directly (the XData project) but rather in the other project (the TMS WEB Core project).
Even in Swagger, the dates and times normally presented will be in GMT, including the response data in the above examples.
Next, regional settings.
This appears to be the culprit behind the ConvertError you had encountered. If I set the regional settings to be something other than yyy-mm-dd then the error would come up. Change it back, and things work properly. The way I got around it was to add a block of code to the FormCreate method of Unit2.pas to set the date formats explicitly within the XData application so that any internal mechanisms would use the yyyy-mm-dd format instead of the regional settings.
// Let's use these internally for consistency
FormatSettings.DateSeparator := '-';
FormatSettings.ShortDateFormat := 'yyyy-mm-dd';
FormatSettings.TimeSeparator := ':';
FormatSettings.ShortTimeFormat := 'hh:nn:ss';
As XData doesn't really display much data on its own (that's for the TMS WEB Core project to look after) this shouldn't really make any difference. When I made this change, I forgot to rebuild the project, so I can't tell from your video whether you were using a version that included the above code or not? If this didn't fix the problem, I'd definitely like to know as that's kind of a fundamental problem. But it did fix it in my testing, so hopefully it will for you as well.
Next, XML generation settings.
The error you encountered about the XML files in the project file was due to my setting the path in the XML generation options as a complete path rather than just a relative path. I've adjusted this in the project so this shouldn't be an issue any longer. You should also be able to adjust these in the Delphi IDE without having to resort to editing the files. They can be found under:
Project Menu
Options Building Delphi Compiler Compiling
Other Options XML documentation output directory
This is needed in order to supply the XML data that Swagger uses to augment its interface. Note that this change needs to be made for each of the different build configurations you're using. I've set it in the Win64 Debug and Win64 Release configurations, but if you're using something else, then it would have to be set there as well.
Next, photos.
The photo file you were looking for was in the main project folder under the same location - ddl/photo/data. I must've made a copy of that in my release/debug folders and forgotten about it. My apologies! I've added a post-build script to the project that copies the contents of that folder from the main project folder in to the build folder. For some reason, it always comes back with a return code of 1, so I've also turned off the 'cancel on error' option. This build event was already being used to copy the RandomDLL.dll file into the build directory. Here's what it has now.
copy /Y RandomDLL.dll "$(OUTPUTDIR)"
mkdir "$(OUTPUTDIR)ddl"
mkdir "$(OUTPUTDIR)ddl\photo"
mkdir "$(OUTPUTDIR)ddl\photo\data"
copy /Y .\ddl\photo\data\*.* "$(OUTPUTDIR)ddl\photo\data"
I don't think the /Y options solved anything - I was hoping that was what was triggering the invalid return code but apparently not. Likewise, it might be that on some systems you can get by with a single mkdir command and it will create all the descendants. Maybe? Not sure. In any event, if I completely erase the contents of the build directory, this correctly copies over the necessary file.
At the moment, this has been changed so that 1.txt contains a Data URI with the image encoded directly in Base64. I think a previous iteration just had it as a regular image, can't quite recall. I commented out the part where two other images were being added. I will add a few more images so we have something more to look at in the demo. With this file in place, the initial run of the application should proceed without any problems when starting from an empty database.
Next, database initialization.
The idea behind using SQLite was that we shouldn't normally have to do anything at all to load any DLL files for this to work. In my Delphi installation, nothing is required. But it could be that I was mistaken about that, and DLL files are required for certain Delphi installations. Sorry about that, certainly wasn't my intention to have that be a roadblock for anyone. I will add a comment to the project about this once I figure out what versions are affected, and where the best place is to get the SQLite DLL if that is indeed what the problem is.
The project uses FireDAC so I had thought that if FireDAC was available, there would be no issues. But perhaps FireDAC isn't available with all the various Delphi installations that also support TMS XData.
If that problem is solved (by adding a DLL) then the database file (DemoData.sqlite by default, in the same build folder as the application) should automatically be created if it didn't exist already. If it did exist, it should be used after checking that all the necessary tables have been created, and any empty tables that have sample data have been loaded with sample data.
The idea here is that as the project evolves, new tables will likely be added, but hopefully it won't often be the case that existing tables need to be modified. We can do that as well by having extra logic in the DDL scripts to check for this, but it hasn't really been an issue as yet. It likely will be, and when it comes up it will likely need a little extra documentation to smooth things over. But right now, starting fresh, there should be no issues - the tables should be created and populated with sample data.
Next, accounts and passwords.
So far, just the SYSINSTALLER has been setup with an account to login. This has been sufficient to test that everything is working as designed. And as you've been seeing, it is obvious when things aren't working. There hasn't been much of a need for other accounts.
Naturally, when we get a bit further along, there will be more mechanisms added for adding accounts, changing passwords, and so on. We've got a couple of blog posts about notifications that I have to write before that is all incorporated here. For example, sending an email or a text message to someone so that they can confirm their identity when they want to change their password, or even sign up for a new account, is the standard way to do this kind of thing.
Once logged in, there are typically additional tools for changing passwords, potentially, so lots to do on this front.
In the interim, if you want to enable other accounts, you can change the "NO PASSWORD SET" values that you were looking at in the ddl\person\person_sqlite.inc file to a password hash. This is a SHA256 hash of the password that you want to use. You can generate a SHA256 hash online using a website like SHA256,
The catch is that a not-so-secret prefix is added to the password so that the hashes can't be guessed using a password hash library. The prefix is just 'XData-Password:'. So if we use our password for the SYSINSTALLER account with this prefix, plugging it into the above website gets us the f401... password hash that we see in the script.
To set a password for another account, just supply a password value with the same prefix, and add it to the script. If you've already run the script, then you'd have to update this value in the SQLite table directly.
By default,
This doesn't mean that the account has much access after logging in to the TMS WEB Core app, however, as they may not have been granted any access to anything else. In the above case, you'll see a login successful message, but no dashboard has been assigned, so it doesn't go anywhere.
One of the top priorities after notifications and multi-database support is a security module where such access can be administered.
I think that covers everything? I've added a 'hellothere' password_hash, and also changed around the initial sequence when the app is run for the first time so it is easier to see what is going on. In particular, adding Application.ProcessMessages to a bunch of places.
Hopefully that helps get things working a little more smoothly for you?
Oh, I forgot one - Icon Sets.
There was an error when starting fresh, as the icon-sets directory was not found. I had mistakenly thought it would just return no results, but it returned an error instead. So I added a line to create the directory if it doesn't exist, and now it works as expected.
This folder could also be populated automatically from the icon-sets folder in the main project folder using the post-build event mechanism we're using for the photos. But if you have a lot of icons, this might not be all that desirable. So instead, it will start with no icons. Just copy whatever icon sets are needed for testing into the icon-sets folder in the build folder and things should work properly.
Hi, Andrew
Thannk you very much for fixed many problem and explain to me . I will try and test your new source code again and report to you if have another problem . I want your example easy for anyone too for learning from you . That's my point .
for next time I'll post new topic for you easy .
Thank you. Akkarawat .
Yes, I want that as well. If it is a lot of trouble for people to use, it won't be of much value. So I appreciate the feedback and hopefully it works much better now. There is a lot more planned for this project, so it is a good idea to have it working as well as we can right from the start.
Hi Andrew
please see my problem from this video explain
https://www.youtube.com/watch?v=notgSbiu7Ao
please tell me how to fixed this problem from your source code
Thank you