What is the correct way to create a "common" theme AND Login for all apps

We require a common Theme and Login for all our apps. We created a theme but when we use it to create a new app, everything in the theme is essentially copied to the app being created.

When the Login is changed we have to now change it in every app, this is not useful. We want a common Login so that when it changes all the apps are changed automatically. So I deleted the Login from the apps derived from the Theme and referenced the Login in the theme. Problem now is we have issues with exceptions and re-directing back to the correct app.

What is the correct and best practice way of using a theme plus a Login that is common over all apps such that if the Login changes it is changed only in one place?

Hi Elize,

I'm not sure there's a "correct" way to do it, it all depends on what you want. The way you've described is also the way we do it, have all the exception handling etc. in the Theme eSpace. I'm not sure what "issues" you have redirecting to the correct app? What we do is using the built-in Function GetExceptionUrl() to get the URL of the page that threw the exception, then use some Regex to extract the eSpace name, then query some system tables to get the Application Id, then query some other tables to get the Application Home Screen, and put that in a Session variable, which we use for the "Click here to continue" link on the Exception Screen. It may be a bit convoluted, but it works for us.

Hi Kilian,

Thank you for the response, apologies for the delayed reply, but what you suggest is what we I have already done, but all not working. For the Exception I already used the GetExceptionUrl() as you mention, so that works fine without having to select anything from tables, it is redirected to the app where the entry was. The problem is when a user clicks on "logout" and tries to login again it tries to login to the Template espace and states it has no entry, it no longer knows what the entry espace is, I have tried several options, but cannot find a solution. This then also results into when the user tries to access a page that the have no permission the "NO Permission" screen is displayed and if the user then logs out to login as another user that has permissions, then it tries to login to the Template where the shared login etc. is. 

Hi Elize,

In short, what we do is use the GetExceptionUrl() to get the URL, then use the meta model to query which Application it belongs to, and what the Entry Point of the Application is. Next we redirect to that Entry Point. It's not that trivial, but it works fine. I can't share that eSpace publicly, but if you like to have it please PM me.

Hi Killian,

As I stated, when we encounter exception we use the following (below code snippet) which works fine, when we click on the "continue" on exception page it goes back to the entry espace as expected, the problem is on the "Logout", there was no exception, so will this work? When user clicks "logout" on top right logout button, then the Login screen comes up with the URL of the template in the browser address bar and when the user then logs in it states "there is not entry".

Substr(GetExceptionURL(), 0, Index(GetExceptionURL(), "/", startIndex: Length(GetExceptionURL()), searchFromEnd: True, ignoreCase: True)+1)

Hi Elize,

Out Logout button redirects to the Login page, passing along the application URL (as Input Parameter to the Login Screen) of the current application (which is a Session Variable). In the Login Screen, we then determine the Entry Point to the application. If there's no Input Parameter specified, we redirect to a default application.

I saved the OriginalUrl in a session variable when the user logged in, but when the user logs out this session variable is cleared, which makes sense, the user's session no longer exists (I confirmed this with log message to Service Center backend before and after logout), so I cannot see how you saved this in a session variable and after logout that value is still available? 

That is why my original question was to OutSystems, what is the correct way of setting up entry points and management of login, logout and exceptions so that these can be shared between all your applications, no response? It is not viable for me to go trial and error, our timelines do not allow for this. Can OutSystems please provide more documentation about the architecture of the login, logout, exceptions and sharing between applications?

Well, I can't speak for OutSystems, but yes, of course the Session Variable is cleared after logout, but it's pretty simple to fix that:

Just set it to a local var in the Logout Action, and pass it to the Login Screen.

Yes, I did think of that and did try it, did not work, but I will give it another shot because I tried so many things, may have done something wrong....

As you can see by the comment, it's been working for us since 2015 :)

OK, I tried this before and it did not work, it seems to work now, the log messages previously had no value for Session.OriginalURL, but perhaps I set it in the wrong place. I still however got a case where it did not work where after "No Permission" I clicked on "Logout" it gave me 'Wrong URL address - this module does not contain a default entry' and it had the template address in the URL. I am trying to reproduce to see if I can get it again, but no luck, it was a specific set of events that caused it. But so far so good, seems to work 99% of the time. I wish OutSystems would be more clear on what the correct way is to do this kind of shared Login which is an obvious requirement that often will occur, this feels like a "hack".

Yes, I agree it would be nicer to have an out-of-the-box solution for this, but perhaps it's not a too common scenario to be considered by OutSystems. Anyway, I'm glad you have something that works for 99%, and as for the "Wrong URL address", maybe you can catch that case as well and present a nicer message to the user.

If you think any of my answers above helped you solve your problem, I'd be happy if you could mark it as Solution :).

OK, just got a case where I have problems, after an error on a "Save" button for the heck of it clicked on the User Name at top right hand corner to get the "MyInfo" edit and got this, this is not an acceptable situation for me, think I am logging a support call with OutSystems, cannot deliver this to a client.

Thanks for the efforts Kilian. I cannot say this is the solution though.

I confirmed, this is random, just had a case again where "No Permission" page, then clicked on Logout and get "The page cannot be found...."

When I check Log messages in ServiceCenter then on Logout the Session,OriginalURL is now empty, where before (when it did work) there was the correct URL in. So it does not always work and I do not know why, I was coding away and making changes and then when I ran again it failed - I am logged in as admin on for example the Users module then when I open my app that user does not have permission to the pages and I forget because it is automatically logged int, then I log out and get this error, and I should not. All I can hope for now is that my clients will not need to login with 2 different users on the same browser - which is unlikely, they mostly will have only one login, but still this behavior is not acceptable.

OK, added some more "hacking" and I think one step closer. I think what happens to the scenario where I am logged in on the Users module as "admin" and then run my app in the same browser, and the app automatically is then logged in as "admin", then "Login" page is never run again and "Login" is not done where the Session.OriginalURL is set, so it is never set.

To solve this I added in the application when the home page is opened in the preparation to call an action on the Template SetOriginalURL that sets the Session.OriginalURL which is located in the Template espace.

On the HomePage in preparation I get the OriginalURL with: 

SyntaxEditor Code Snippet

Substr(GetBookmarkableURL(),0, Index(GetBookmarkableURL(), GetEntryEspaceName(),startIndex:,searchFromEnd:,ignoreCase:)) + GetEntryEspaceName()

This then works for this scenario where you are automatically logged in as another user which was logged into OutSystems on another application, then logout to login as another user.

All this should not be necessary.....