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) :

}

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 Thangavel · 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 implementation
    return $$$OK
}
0
Pierre LaFay  Aug 11, 2023 to Ashok Kumar Thangavel

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 Thangavel  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 Thangavel

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 logging
    quit ##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