Help with confluence macro to request crowd - crowdService
Asked by GvD:

Hi all,

One of our services is running JIRA + confluence with crowd as authentication backend.

As part of the user management tools, we wrote a confluence macro to help us keeping track of users last login, account activity etc...

The problem is that the code we use seems not to get the Last Login Date called "lastAuthenticated" from crowd (apparently not a standard attribute). But we can get the standard attributes such as the username.

Following works and returns the name:

```
$crowdService.getUserWithAttributes($user.name).getDisplayName()
```

Following doesn't work, nothing is returned (even asking a list of available keys returns nothing)

```
$crowdService.getUserWithAttributes($user.name).getValue("lastAuthenticated")
```

Our macro is following:

```
## @noparams#set($containerManagerClass = $content.class.forName('com.atlassian.spring.container.ContainerManager'))#set($getInstanceMethod = $containerManagerClass.getDeclaredMethod('getInstance',null))#set($containerManager = $getInstanceMethod.invoke(null,null))#set($containerContext = $containerManager.containerContext)#set($crowdService = $containerContext.getComponent('crowdService'))  #set($groups = $userAccessor.getGroupsAsList())<table class="confluenceTable" width="660px">    <tr>        <th class="confluenceTh">Group</th>        <th class="confluenceTh">Name</th>        <th class="confluenceTh">Email</th>        <th class="confluenceTh">Last Login</th>    </tr>    #foreach ($group in $groups)        #set($usernames = $userAccessor.getMemberNames($group))        #foreach($username in $usernames)            #set($user = $userAccessor.getUser($username))            #set($lastLogin = $crowdService.getUserWithAttributes($username).getValue("lastAuthenticated"))            <tr>               <td class="confluenceTd">$group.Name</td>               <td class="confluenceTd">#usernameLink($user.name)</td>               <td class="confluenceTd">$user.email</td>               <td class="confluenceTd">$lastLogin</td>            </tr>         #end    #end</table>
```

We did ask Atlassian support but were told that development/API queries is beyond their technical expertise... And that we should ask the developers community.

Is there someone here that has any idea about this issue?

Any suggestion is welcome, thank you :smile:


Answers:
author: Stephen Deutsch
body: The user macro on this page might be able to help you out:

<https://answers.atlassian.com/questions/89027>


author: GvD
body: Hi,

We found where the problem comes from but are not able to explain it...

Our production code is following:

```
## @noparams#set($containerManagerClass = $content.class.forName('com.atlassian.spring.container.ContainerManager'))#set($getInstanceMethod = $containerManagerClass.getDeclaredMethod('getInstance',null))#set($containerManager = $getInstanceMethod.invoke(null,null))#set($containerContext = $containerManager.containerContext)#set($crowdService = $containerContext.getComponent('crowdService')) #set($groups = $userAccessor.getGroupsAsList()) <table class="confluenceTable" width="660px">    <tr>        <th class="confluenceTh">Group</th>        <th class="confluenceTh">Name</th>        <th class="confluenceTh">Email</th>        <th class="confluenceTh">Last Login</th>    </tr>    #foreach ($group in $groups)    #if ($group.Name.startsWith("BLABLA"))        #set($usernames = $userAccessor.getMemberNames($group))        #foreach($username in $usernames)            #set($user = $userAccessor.getUser($username))            #set($lastLogin = $crowdService.getUserWithAttributes($username).getValue("lastAuthenticated"))            <tr>               <td class="confluenceTd">$group.Name</td>               <td class="confluenceTd">#usernameLink($user.name)</td>               <td class="confluenceTd">$user.email</td>               <td class="confluenceTd">$lastLogin</td>            </tr>         #end    #end    #end</table>
```

This code does partially work, the result is a table listing the user-groups startingwith "BLABLA", the specific users and in the last login column we litteraly have "$lastLogin" in all lines.

If we remove the #if ($group.Name.startsWith("BLABLA")) and its #end, then it works...better.

It then lists all the user-groups, the specific users and in the last login column we litteraly have "$lastLogin" in the 165 first lines, the other lines contain the correct last login date!

It looks like there is a timeout related problem...?

Any idea is welcome


author: GvD
body: Stephen,

Indeed there was a line missing as I needed to remove a few lines before posting the macro here. Corrected our macro. The code we have is available in the initial question...

I used the code your provided with a statically declared user (that exists), but it doesn't work:

```
## @noparams#set($containerManagerClass = $content.class.forName('com.atlassian.spring.container.ContainerManager'))#set($getInstanceMethod = $containerManagerClass.getDeclaredMethod('getInstance',null))#set($containerManager = $getInstanceMethod.invoke(null,null))#set($containerContext = $containerManager.containerContext)#set($crowdService = $containerContext.getComponent('crowdService'))  #set($Long = $generalUtil.getSystemStartupTime() )#set($lastAuthenticatedDate = $generalUtil.buildDate )$lastAuthenticatedDate.setTime($Long.parseLong($crowdService.getUserWithAttributes("existinguser").getValue("lastAuthenticated")))<p>$action.dateFormatter.formatDateTime($lastAuthenticatedDate)</p>
```

This is the error we get:

```
Error rendering macro 'userlogintest' : Error occurred rendering template content
```

I think that we write the macro correctly as using our macro, following code works and returns an email address:

```
#set($lastLogin = $crowdService.getUserWithAttributes($username).getEmailAddress())
```

But following code returns "`$lastLogin`"

```
#set($lastLogin = $crowdService.getUserWithAttributes($username).getValue("lastAuthenticated"))
```

comments: author: Stephen Deutsch
body: What does your confluence log file say as to why the error occurred?


author: GvD
body: Hi Stephen,

Sorry for the delay, it really takes time to get the logs...

I hope to be able to provide them soon as we really would like to fix this issue.


author: Stephen Deutsch
body: It seems like from your posted macro that you are not calling the function to get the crowdService, only loginManager. However, this may be the Confluence embedded crowdService and not the larger Crowd instance. Anyways, this worked on our instance of Confluence:

```
## @noparams#set($containerManagerClass = $content.class.forName('com.atlassian.spring.container.ContainerManager'))#set($getInstanceMethod = $containerManagerClass.getDeclaredMethod('getInstance',null))#set($containerManager = $getInstanceMethod.invoke(null,null))#set($containerContext = $containerManager.containerContext)#set($crowdService = $containerContext.getComponent('crowdService'))  #set ( $Long = $generalUtil.getSystemStartupTime() )#set ( $lastAuthenticatedDate = $generalUtil.buildDate )$lastAuthenticatedDate.setTime($Long.parseLong($crowdService.getUserWithAttributes($req.remoteUser).getValue("lastAuthenticated")))<p>$action.dateFormatter.formatDateTime($lastAuthenticatedDate)</p>
```


author: GvD
body: Hi Stephen,

Thank you for your answer.

Unfortunately, this doesn't help as by using that macro, they call the loginManager (from Confluence) which will return only the last time the user has accessed the Confluence. In our case we use JIRA 85% of the time and Confluence 15% of the time... Both (confluence and Jira) are important and so we really need to get the information form crowd (to make sure that we really have the correct information).

```
$loginManager.getLoginInfo($user).lastSuccessfulLoginDate
```


Tags: confluence

last-login

macro

user-macro