Written by

CEO at Ellipse
Question Pierre LaFay · Aug 11, 2023

Add processing during login in a class extending %CSP.REST

Hi,
For a REST application, when a user connects, I have to write a message in an application log.
The login is processed by the /login routine by default.

How can I add a process to the login process?
Is there a callback ?
Should I create a login method in my class that extends %CSP.REST ?
I'm not sure and can't find information in the documentation ?

I try this (not working) :

<Routes>

<Route Url="/lists" Method="GET" Call="GetLists" />

<Route Url="/me" Method="GET" Call="GetUserInformations" />

<Route Url="/changePassword" Method="PATCH" Call="ChangeUserPassword" />

<Route Url="/utilisateurs" Method="POST" Call="CreateUtilisateur" />

<Route Url="/utilisateurs" Method="PATCH" Call="ModifyUtilisateur" />

<Route Url="/login" Method="POST" Call="Login" />

</Routes>

}

ClassMethod Login(skipheader As %Boolean = 1) As %Status [ ProcedureBlock = 0 ]

{

Set sc = ##class(%CSP.REST).Login()

Set ^Pierre("test login")=sc

Return sc

}

Product version: IRIS 2023.1
$ZV: IRIS for UNIX (Ubuntu Server 22.04 LTS for x86-64) 2023.1 (Build 229U) Fri Apr 14 2023 17:29:40 EDT

Comments

Ashok Kumar T · Aug 11, 2023

Hello Pierre,

You can Override the method OnPreDispatch from the %CSP.REST in your dispatcher class and capture your user connect information in application log.

ClassMethod OnPreDispatch(pUrl As%String, pMethod As%String, ByRef pContinue As%Boolean) As%Status
{
    set^Pierre(pUrl)=""/// your implementationreturn$$$OK
}
0
Pierre LaFay  Aug 11, 2023 to Ashok Kumar T

Hi Ashok,

Thanks for your reply, overriding OnPreDispatch Method doesn't not work with login, refresh, logout (special routes) but with my own routes it's work. So It's not a solution for me

This the beginning of my class which extends %CSP.REST,  I missed something ?

Class Bna.Api.Bna2024 Extends%CSP.REST
{
Parameter HandleCorsRequest = 1;Parameter CHARSET = "UTF-8";Parameter CONTENTTYPE = "application/json";
XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
    <Route Url="/lists" Method="GET" Call="GetLists" />
    <Route Url="/me" Method="GET" Call="GetUserInformations" />
    <Route Url="/reset-password" Method="POST" Call="ResetUtilisateurPassword" />
    <Route Url="/utilisateurs" Method="GET" Call="GetUtilisateur" />
    <Route Url="/utilisateurs" Method="POST" Call="CreateUtilisateur" />
    <Route Url="/utilisateurs" Method="PATCH" Call="ModifyUtilisateur" />
    <Route Url="/utilisateurs" Method="DELETE" Call="DeleteUtilisateur" />
</Routes>
}
ClassMethod OnPreDispatch(pUrl As%String, pMethod As%String, ByRef pContinue As%Boolean) As%Status
{
    Set^Pierre("login")="on login (by overrided method pre dispatch)"return$$$OK
}
...
0
Ashok Kumar T  Aug 11, 2023 to Pierre LaFay

Hi Pierre 

Can you try with below. And try Create a subclass of %CSP.SessionEvents and try override OnStartRequestOnEndRequest .

ClassMethod Page(skipheader As%Boolean = 1) As%Status [ ProcedureBlock = 0 ]
{
	set^Pierre("login")="on login (by overrided method Page)"return##super(skipheader)
}
0
Pierre LaFay  Aug 13, 2023 to Ashok Kumar T

Hi ashok,

There is the same issue, Page method in my %CSP.REST subclass is not called...

0
Eduard Lebedyuk · Aug 11, 2023

You don't need to create a /login route since Login method is being called implicitly if auth is required.
To add logging, it's enough to redefine the Login method in your broker like this (##super docs):

ClassMethod Login(skipheader As%Boolean = 1) As%Status [ ProcedureBlock = 0 ]
{
    // do app-level loggingquit##super(skipheader)
}
0
Pierre LaFay  Aug 11, 2023 to Eduard Lebedyuk

Thanks Eduard,

That's my first try  (doesn't work, global ^Pierre not set with login)

It seems that method in my class doesn't override the methods on %CSP/REST.

This the beginning of my class which extends %CSP.REST, Do I miss something ?

Class Bna.Api.Bna2024 Extends%CSP.REST
{
Parameter HandleCorsRequest = 1;Parameter CHARSET = "UTF-8";Parameter CONTENTTYPE = "application/json";
XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]
{
<Routes>
    <Route Url="/lists" Method="GET" Call="GetLists" />
    <Route Url="/me" Method="GET" Call="GetUserInformations" />
    <Route Url="/reset-password" Method="POST" Call="ResetUtilisateurPassword" />
    <Route Url="/utilisateurs" Method="GET" Call="GetUtilisateur" />
    <Route Url="/utilisateurs" Method="POST" Call="CreateUtilisateur" />
    <Route Url="/utilisateurs" Method="PATCH" Call="ModifyUtilisateur" />
    <Route Url="/utilisateurs" Method="DELETE" Call="DeleteUtilisateur" />
</Routes>
}

ClassMethod Login(skipheader As%Boolean = 1) As%Status [ ProcedureBlock = 0 ]
{
    Set^Pierre("login")="on login (by overrided Login method)"Return##super(skipheader)
}
...
0
Eduard Lebedyuk  Aug 12, 2023 to Pierre LaFay

Leave only password auth for the rest web app?

0
Pierre LaFay  Aug 13, 2023 to Eduard Lebedyuk

Hi Eduard,

I'm sorry but I don't understand what you exactly mean

0
Eduard Lebedyuk  Aug 14, 2023 to Pierre LaFay

In your REST Web Application settings, leave only pass (and remove group by id, if any):

After that check that UnknownUser does not have %ALL.

Finally try to access your REST url using Postman (or similar tool) and you should be able to see Login methind being executed.

0
Pierre LaFay  Aug 20, 2023 to Eduard Lebedyuk

Hi Eduard,

Many thanks for yours answers

My app config is same of you, except I use JWT token authentification (UnKnownUser doesn't have %ALL) :

0
Eduard Lebedyuk  Aug 21, 2023 to Pierre LaFay

I guess you do need to use SessionEvent. OnLogin method specifically.

Or you can log every request using OnPreDispatch method in your REST broker.

0