Jump to content

wprins

uniGUI Subscriber
  • Posts

    151
  • Joined

  • Last visited

Everything posted by wprins

  1. wprins

    Auto Login

    I'd like to point out for the benefit of the original poster that the demo does *not* protect the credentials. This is a major security concern for a production system, as anything else in the browser can read the credentials out of the cookies on the user's machine. For a production grade solution you must therefore not store the credentials themselves, but rather a login token. Or if you must store the credentials themselves, then they must be encrypted on the server using strong encryption (say AES256). If you use a token, then it should be validated upon use, to prevent eg. token theft and/or impersonation by a malicious third party. So for example a token should ideally include some way to validate the IP address making use of the token. (In our system I ended up employing AES256 encryption to protect the credentials in the browser, to allow seamless processing and auto-login from a specific URL straight to a specific screen/form/page without demanding the user to login - if the credentials are absent then of course you are asked to login as normal. Edit: To add, we used SynCrypto.pas, part of mORMot framework, for the AES encryption. )
  2. Thanks, that all seems reasonable. Have you tried other browsers, and does it occur there also? To clear the cache press Ctrl-Shift-Del. (Or click top-right three dots button->"More options"->"Clear browsing data", click on "Advanced tab" and delete everything.) It's perhaps easier to open an incognito window and this has the benefit of leaving all your cookies and things alone, press Ctrl-Shift-N: https://support.google.com/chrome/answer/95464?co=GENIE.Platform%3DAndroid&hl=en Is there anything else that is special about this form? And can you make it break in isolation? That is, if you put that form into a project by itself, does it still break? Do you have to do something else first before it breaks? Have you tried recreating this form in its current state from scratch and does that new form still break in the same way? Again, unless you can work out some way to replicate the issue it's going to be very hard to work out what's going on.
  3. When posting errors please always post: 1) Browser + version 2) Version of UniGUI 3) If possible, a MCVE. Admittedly not always easy or possible. But without some chance of replicating the problem it's virtually impossible to help or fix the issue at hand. Additionally, if you have seemingly spurious errors that persist despite removing seemingly everything that could possibly cause a problem, then repeat your test from a fresh browser context (e.g. "Incognito" window in Chrome, or deleting all cached data and then repeating the test.)
  4. In the simplest way then, the update form must be given as parameter a callback routine (say "UpdateCustomers()") from the main form containing the grid, that it will call when it's done. Maybe as constructor parameter. Inside the update form, just prior to closing or after saving it then calls the this routine (locally maybe something like "If Assigned(Callback) then Callback()") which in turn results in UpdateCustomers on the form containing the grid being run. (This is a simplified "direct" implementation of a subject and observer directly handing each other a means of notification without "formalising" it and the pattern supporting multiple observers etc. as is the case in the general way this pattern is usually implemented.)
  5. Have a look at the "mdemo" "megademo" application which should give you some ideas. Also ask yourself how you would do this in conventional Delphi VCL. If you can describe/implement what you want in conventional Delphi then you can use essentially the same approach in UniGUI. But to make a further parenthetical comment: Your comment re "need to redisplay the grid again with the modified customer" suggests you simply need to notify or otherwise refresh the grid when the modification has completed. How that happens depends somewhat on on how/when the update completes. In a very general sense, you need some form of the "observer pattern", you need to "notify" the grid (an "observer") that its "subject" (the customer list) has changed, which would then trigger a refresh/repopulate/reopening of the dataset or whatever is required.
  6. wprins

    Rename URL

    I've just left a comment on the other referenced post. HTH.
  7. You probably wouldn't save your unigui dll as "page1.php", but rather you would code your UniGUI app to recognize the old URLs and dynamically redirect/reinterpret them in a usable fashion to return a useful response to the client/browser. You would recognize and respond completely as you like in UniGUI, either at the generic server level inside UniGUIServerModule.HTTPCommand & HTTPDocument event handlers, or at a user (session) level inside TUniGUIMainModule.OnBeforeLogin (where you would deal with required authentication first by probably logging the user in first, and after that then record the fact [set a property or whatever on the main form] that the user has asked for some or other form that corresponds to the URL you're recognizing, which you'll then pick up and process when the application main form starts etc.) HTH.
  8. If it's for a course then there's no point (nor would it be allowed) to just supply you with the solution. The point with asking about Delphi is that if you're more used to Delphi you should perhaps explore the concepts in the comfort of Delphi first as that might be slightly easier to start with, before working out how the same concepts are realised in Java. Ultimately you're learning 2 things at once: The abstract concepts of socket based networking as well as how this is implemented/realised concretely in a programming language, in this case Java. You've not mentioned what you've tried so far and where you've gotten stuck? It might be worth (also) posting your question on a more general programming forum like StackOverflow. But you'll need to more specific and explain exactly where you're getting stuck ideally with an MCVE if possible. You should probably also read this. Hope that helps.
  9. Is this homework/done as part of some course? What have you tried so far and where have you become stuck exactly? Have you tried writing the same thing in Delphi and/or UniGui yet? If so how did you get on?
  10. You've forgotten to post links to the "other forum".
  11. Note, I've now created a github repo with the code and the fixes I made. It is available here.
  12. Of course you can use plain procedures or functions, but they key thing you must understand is that UniGUI is of necessity a multi-threaded environment. That means that you need to keep in the back of your mind the question whether there could be concurrency problems when you access any "shared thing" out there. Again, while one can mostly program with a single threaded "typical" mindset (ignoring threading issues) providing you're using things belonging to the "current" session, anything else that is shared must be carefully considered regarding possible concurrency problems. What would happen for example in your procedure above if 2 sessions execute it at exactly the same time? Since all the parameters would be distinct and there's no shared variables anywhere, there's no problem in this case. But if there was (for example) a shared global variable referenced in that procedure, then you'd have to think how multiple threads simultaneously trying to update such a shared resource would behave. You'd likely need a lock or monitor or mutex or something to ensure the threads interoperate correctly on the shared resource.
  13. Thanks for sharing. Am I right in assuming these are these Firemonkey applications? And what about the internals? Did you use datasnap or something else for the middle/back end? What about client architecture? Did you use FireDAC components or TClientDatasets or something else entirely? (Back in XE5 days I evaluated Delphi's Android support and suffice it to say it was IMHO dire at the time, basically broken and didn't work well enough for me to risk using in production. It looks though like things have come along very well and that I should revisit this.)
  14. We had a similar requirement. First of all, understand: URLFrame.URL is basically a way for you to get the browser to ask for a specified URL (file) in a totally standard "http/s" way. So you must think in terms of "URL" not "shared folder" in the first instance. Next, UniGUI's "FilesFolderURL" gives you a way to get a URL to refer to files in a known UniGUI FilesFolder location, via an HTTP/S URL therefore recognized by the UniGUI server. So, thats one way to get UniGUI to do the "translation" from server based path/file location to something that UniGUI will recognize an serve to a client browser. Of course it doesn't help you because you're interested in some other shared location accessible by your server. It follows that since UniGUI doesn't know about this location, you must implement something similar to what UniGUI does for its file/folder location. In short, to solve this we implemented a servermodule event handler/method (sorry I don't have the code in front of me otherwise I'd perhaps be a bit more specific) that basically recognizes special URL's requests (by prefix) and which further along the URL contains a file-id (AES256 encrypted filename/path in fact). The server module then of course decrypts the request and manually/directly serves up the requested file providing the requestor is allowed to do so of course. That's the essence of it anyway. Walter
  15. A big reason to prefer more decoupled approaches such as MVC, MVP, MVVM, MV* is testability. If all your logic is inside event handlers then typically it's quite hard to properly test and not possible to test entirely in isolation. This may not be a show stopping problem but it is a consideration at least. (Also see for example the "Humble Dialog" pattern and "Humble View".)
  16. wprins

    TUniScreenMask

    For what it's worth, the above example didn't work as-is in the latest UniGUI version(s). I've updated it, added a few logging calls and instructions to make it clearer what's happening, as well as changing the flow somewhat (avoiding using a custom event in favour of just triggering the actual button click instead.) The code is available here: https://github.com/ByteJuggler/uni_keycap/tree/master
  17. Hi, Just to note that the "layout.rar" example from the message in this post does not run on the latest UniGUI and displays the message: "'field' config has been deprecated. Please use the 'angleField' config instead." It might be useful to update it and/or include it in the official demo if it's not already there (? I've not exhaustively looked at all the included demos, my apologies if it's actually already included!) Edit: The simple way to "fix" this is to edit ClientEvents.UniEvents and open Ext.chart.CartesianChart, then open chart.beforeInit and comment out the "config.axes" assignment in the code. (There's obviously a better way of fixing it but I didn't have the time or patience to work out what exactly has changed and how it should be updated. Changing "fields" to "angleField" or "angleFields" did not work and resulted in another error message.) Walter
  18. Hi, Today upgraded our project to 1.5.0.1480 (from 1.0.xxx before). Mostly everything seems to be working ok except for 2 minor things: 1) Login form icon not displaying correctly. It displays correctly ad design time. The icon is supplied via the Form's Icon property, and seems fine in the object inspector. Edit: To add, it looks like the icon is there, but is not being resized to 16x16 anymore automatically for the login form thumbnail icon. (I'll see if manually resizing it fixes the issue...) Edit2: Resizing the icon doesn't fix it, it's somehow still too large it seems, and now being "upscaled" as well. I get the impression there's some code somewhere that's set to scale the supplied icon to size, except it's apparently using the wrong size. Edit3: I've removed the icon entirely from the login form. It now displays with the default Delphi icon at designtime but is somehow now displaying the correct icon correctly at runtime?! (It may be picking it up from the Application icon, I'm guessing.) 2) I usually (but not necessarily every time) during login get the following message: Event:click, Object: O50 not found in session list. It could be timed out, refresh page and try again. It's always O50, and only seems to happen on logging in. Any suggestions on what might be causing this would be appreciated. Obviously it's possible that it's something in our project but then neither of these problems existed prior to the upgrade. Thanks Walter
  19. Thanks, apologies, I should've found that myself.
  20. Sherzod, thank you. Out of interest, can one do the same via beforeInit()? (I assume so?)
  21. I assume you meant to write it as the above (note I inserted [in]). What do you mean by "another web application" and what do you mean by "call" exactly? You can call other web services in the normal way you would from non uniGUI applications by whatever means suits your purpose. You can also "call" and frame another website inside a uniGUI frame, with some work and some co-operation from the site being called/framed. You could call a uniGUI application in various ways as well, though you'd need to arrange things to suit your purpose, which is to say you'll have to arrange for the required credentials/login to be somehow handled seamlessly/in the background. (We do something like this from an iSeries green screen system which publishes a clickable URL on the green screen and it directly "calls" our UniGUI application, taking the user to a specific page/form in the UniGUI application. If the user isn't already logged in then they're prompted to log in, after which of course the browser knows the user and further logins is seamlessly handled as required.)
  22. Today I needed this feature. It would be better if TUniMemo exposed MaxLength as a property to control this. But thanks for this solution. Edit: Also setting the maximum length doesn't actually prevent the entry of more than the maximum length. It does colour the memo frame red and display a hover warning about the maximum length however. Is it possible to actually stop entry once the memo reaches capacity?
  23. For what it's worth, we generally employ the same policy -- avoid the use of closed source components whenever possible, UniGUI being essentially the only exception we've allowed in this policy for a very long time as it is such a good product. Still, I really continue to worry and dislike the level of risk we're carrying due to the size of FMSoft, e.g. if something happens to Farshad or FMSoft this will have quite serious consequences. It is entirely within the realm of possibilities to end up in a situation where FMSoft stops trading with no way to obtain the source code to UniGUI, and consequently that all the investment into a UniGUI based solution then ends up having to be abandoned and entirely rewritten due to lack of access to source and consequent inability to upgrade to newer versions of the Delphi and web ecosystems. (To add this is not just a purely hypothetical possibility either, I've actually worked with a company once where exactly this happened and a system had to be replaced at great cost and trauma to the business due to another business having gone under, so much so that they then negotiated special escrow agreements with a new provider to ensure they would have access to a product's source should that partner business cease trading etc... The whole issue is worrying enough that, as much as I like UniGUI, I do continue to consider the alternatives and will likely consider switching to eliminate this risk if something becomes available that is competitive with UniGUI.)
  24. Hi, I've today become aware of the new hyper-server functionality. Fantastic. It will solve some of the issues we've sort of just had to manage/deal with as mentioned in documentation. However, I have a question: It seems from the documentation however that Nodes (worker processes) that are managed by the hyper-server must reside on the same physical/virtual box? Is this corect? If so it's slightly unfortunate as it would seemingly be very useful if nodes could also be distributed over multiple servers rather than only being hosted on one single instance (for additional ability to scale and redundancy.) Or am I missing something or looking at this the wrong way? Thanks Walter
  25. For anyone finding this in future: The URL suggested by Gerhard (freegeoIP) is being retired as of July 2018. An alternative is www.ipify.org. Code as follows: procedure TLoginForm.UniLoginFormAjaxEvent(Sender: TComponent; EventName: string; Params: TUniStrings); begin if SameText(EventName, 'ClientIPAddr') then begin //Do what you want with the IP. As example we set the IP on a frame embedded in the login form (assumes there's a BrowserIP property.) LoginFrame.IPLabel.Caption := 'Your public IP is: '+Params.Values['ip']; LoginFrame.BrowserIP := Params.Values['ip']; end; end; procedure TLoginForm.UniLoginFormBeforeShow(Sender: TObject); begin //Reference: https://www.ipify.org/ UniSession.AddJS( '$(function() {'+ ' $.getJSON("https://api.ipify.org?format=jsonp&callback=?",'+ ' function(json) {'+ ' ajaxRequest(' + self.WebForm.JSName + ', "ClientIPAddr", ["ip="+json.ip]);'+ ' }'+ ' );'+ '});' ); end;
×
×
  • Create New...