Macro that produces a list of users' last login date?

Steve Goldberg
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 2, 2012

Would anybody be prepared to write a macro that I can use to produce a list of users showing when they last logged in? I'm aware that you can use com.atlassian.jira.bc.security.login.LoginInfo to do this, but I don't have the skills to write the macro myself. Any help would be appreciated.

Thanks

EDIT: If this you're just interested in the code, I have created a 'master' version that I frequently update following contributions from Remo Siegwart, Bruce Schlueter, and myself: https://github.com/stevegoldberg/ConfluenceMacros/tree/master/Last%20Login

22 answers

1 accepted

24 votes
Answer accepted
Remo Siegwart
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 3, 2012

The following user macro should display all users and their last successful login date:

## @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($loginManager = $containerContext.getComponent('loginManager'))
#set($users = $userAccessor.getUsers())

<table class="confluenceTable">
    <tr>
        <th class="confluenceTh">User</th>
        <th class="confluenceTh">Last Successful Login Date</th>
    </tr>
    #foreach($user in $users)
        <tr>
            <td class="confluenceTd">#usernameLink($user.name)</td>
            <td class="confluenceTd">$action.dateFormatter.formatDateTime($loginManager.getLoginInfo($user).lastSuccessfulLoginDate)</td>
        </tr>
    #end
</table>

Hope this helps

Steve Goldberg
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 6, 2012

That's incredibly useful, thanks. I may pester you again for some modifications if I can't figure them out myself.

Cheers

Remo Siegwart
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 6, 2012

Great, I'm glad that it's useful for you!

Here is some more information about the API of the objects in use:

This information should help you to customize the report to your needs.

Steve Goldberg
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 6, 2012

Well seeing as you're being so helpful, what I want to know is if it is possible to add a third column which would show whether the user has been disabled? We want to use the macro to quickly see who's inactive and can have their account disabled/deleted and a tick or cross next to each user to show if they are enabled or disabled would be helpful. Is this possible?

Remo Siegwart
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 6, 2012

You could use the UserAccessor for that. By calling $userAccessor.isDeactivated($user) you can find out if a user is deactivated. The end result could be something like this:

## @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($loginManager = $containerContext.getComponent('loginManager'))
#set($users = $userAccessor.getUsers())

<table class="confluenceTable">
    <tr>
        <th class="confluenceTh">User</th>
        <th class="confluenceTh">Last Successful Login Date</th>
        <th class="confluenceTh">Active</th>
    </tr>
    #foreach($user in $users)
        <tr>
            <td class="confluenceTd">#usernameLink($user.name)</td>
            <td class="confluenceTd">$action.dateFormatter.formatDateTime($loginManager.getLoginInfo($user).lastSuccessfulLoginDate)</td>
            <td class="confluenceTd" style="text-align:center;">
                #if($userAccessor.isDeactivated($user))
                    <img src="/s/en_GB/3047/11/_/images/icons/emoticons/error.png" width="18" height="18" border="0">
                #else
                    <img src="/s/en_GB/3047/11/_/images/icons/emoticons/check.png" width="18" height="18" border="0">
                #end
            </td>
        </tr>
    #end
</table>

Like JD Gebicki likes this
Steve Goldberg
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 7, 2012

Wow, that's amazing. How about a column that adds in when the account was created?

Remo Siegwart
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 7, 2012

How about this:

## @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($loginManager = $containerContext.getComponent('loginManager'))
#set($crowdService = $containerContext.getComponent('crowdService'))
#set($users = $userAccessor.getUsers())

<table class="confluenceTable">
    <tr>
        <th class="confluenceTh">User</th>
        <th class="confluenceTh">Last Successful Login Date</th>
        <th class="confluenceTh">Creation Date</th>
        <th class="confluenceTh">Active</th>
    </tr>
    #foreach($user in $users)
        #set($crowdUser = $crowdService.getUser($user.name))
        <tr>
            <td class="confluenceTd">#usernameLink($user.name)</td>
            <td class="confluenceTd">$action.dateFormatter.formatDateTime($loginManager.getLoginInfo($user).lastSuccessfulLoginDate)</td>
            <td class="confluenceTd">$action.dateFormatter.formatDateTime($crowdUser.createdDate)</td>
            <td class="confluenceTd" style="text-align:center;">
                #if($userAccessor.isDeactivated($user))
                    <img src="/s/en_GB/3047/11/_/images/icons/emoticons/error.png" width="18" height="18" border="0">
                #else
                    <img src="/s/en_GB/3047/11/_/images/icons/emoticons/check.png" width="18" height="18" border="0">
                #end
            </td>
        </tr>
    #end
</table>

Steve Goldberg
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 7, 2012

Fantastic. So, just taking a look at it. Using the {table-plus} macro I am able to sort columns by clicking on the header but I have noticed that it is sorting alphabetically - how do you change the format of the dates so that it goes yy/mm/dd hh:mm ? I know you can change ".formatDateTime" to, say, ".format" but how do I use .DateFormatter?

Thanks

Remo Siegwart
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 7, 2012

You should be able to use the formatGivenString(pattern, date) method of the DateFormatter. Something like this should work:

$action.dateFormatter.formatGivenString('yy/mm/dd hh:mm', $crowdUser.createdDate)

Steve Goldberg
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 8, 2012

Mucho gracias. Very helpful.

Rumceisz June 13, 2012

Hi Remo,

I inserted the macro but the 'Last Successful Login Date' is empty for all the users! The user list is correct: the table lists all the Confluence users, but the other column is empty. What can be wrong? Are there any settings needed?

Thanks in advance!

Best regards,

Rumi

Remo Siegwart
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 13, 2012

Do you use Crowd for user management?

See this answer by Thomas

Rumceisz June 17, 2012

Hi Remo,

tha macro is fantastic!

Can you please show an extension/modification for the macro which display the last login of a particular group? Hence, our $users and confluence-users group (which are the members who can really login to docspace) have 300 members difference! Who can be these 300 plus members??

Remo Siegwart
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 17, 2012

Not sure if I understand your question correctly, but if you want to display only users of a particular group, use something like this:

## @param group:title=Group|type=string|required=true|desc=The group you want to report on
#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($loginManager = $containerContext.getComponent('loginManager'))
#set($group = $userAccessor.getGroup($paramgroup))
#if($group)
    #set($usernames = $userAccessor.getMemberNames($group))

    &lt;table class="confluenceTable"&gt;
        &lt;tr&gt;
            &lt;th class="confluenceTh"&gt;User&lt;/th&gt;
            &lt;th class="confluenceTh"&gt;Last Successful Login Date&lt;/th&gt;
        &lt;/tr&gt;
        #foreach($username in $usernames)
            #set($user = $userAccessor.getUser($username))
            &lt;tr&gt;
                &lt;td class="confluenceTd"&gt;#usernameLink($user.name)&lt;/td&gt;
                &lt;td class="confluenceTd"&gt;$action.dateFormatter.formatDateTime($loginManager.getLoginInfo($user).lastSuccessfulLoginDate)&lt;/td&gt;
            &lt;/tr&gt;
        #end
    &lt;/table&gt;
#else
    &lt;p&gt;&lt;i&gt;No group with name "$paramgroup" found!&lt;/i&gt;&lt;/p&gt;
#end

Hope this helps

Rumceisz June 17, 2012

Hi Remo,

you're right understood! Your macro lists all the users of the Confluence instance. I only need a particular group members last login.

Thank you for the macro! I only ask where can I put the group-name in the code? I guess to $paramgroup))?

Thanks again,

Rumi

Thomas Berger June 17, 2012

Hi Rumi, you need to put Remo's code in a 'User Macro' and name it e.g. 'lastlogin', see https://confluence.atlassian.com/display/DOC/Writing+User+Macros for more details.

Then you would use it like {lastlogin:group=confluence-users} on the page you want the report.

Rumceisz June 18, 2012

Hi Remo and Thomas!

It works thank you very much!!

Rumi

Selcuk Savas
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 6, 2012

Remo you're a life saver!

prakash ganeshan March 11, 2013

Superb Macro .. :)

Royce Wong
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 20, 2015

I would like to know where $crowdUser.createdDate is from. https://developer.atlassian.com/static/javadoc/embedded-crowd-api/latest/reference/com/atlassian/crowd/embedded/api/User.html doesn't contain createdDate method. I am trying to find the API equivalent. Please let me know who you find out about $crowdUser.createdDate. Thanks.

Anudeep Gudipelli May 16, 2018

Hi Remo , 

Reading comments felt me that this macro is awesome. We use crowd for user directories, and i din't find solution for that, when click on the link you provided for thomas answer reg crowd user management, the link says its invaild parameters. 

I appreciate your help

Thank you,

Anudeep

Remo Siegwart
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 16, 2018

For crowd see this answer, just below your comment...

Anudeep Gudipelli May 17, 2018

Does this macro works on v5.9 and 5.10?

Currently we have two instances v5.9 and v 5.10 and in future we are going to migrate into one instance which would be v6.6.

Is there any chance to check, if there are some steps, I would like to exercise them.

Thank you

7 votes
Charles Pikscher November 12, 2019

Seems like this broke for Confluence 7, no more loginManager.  Anyone know the fix?

Charles Pikscher November 14, 2019

Bah.  They updated this to show no macro solution in pre-7 Confluence.  Guess who's staying at 6.15.9 for awhile...

https://confluence.atlassian.com/confkb/how-to-get-a-list-of-active-users-counting-towards-the-confluence-license-298978076.html

Sam May 6, 2020

Is there a version of this fix that includes the last login date?

Like Greg Bailey likes this
2 votes
Chris Kent
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 25, 2020

Has anyone been able to get this User Macro working for 7.x?

If so can you please share the code. I expect the ContainerManager has moved, or has a new class name perhaps, but I can't find it.

KC Integrations September 17, 2020

I managed to get my User Macro working in 7.x. For those interested here is my code:

 

## @Param group:title=Group|type=string|required=true|desc=Group to show

#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( $loginManager = $containerContext.getComponent('loginManager') )
#set( $crowdService = $containerContext.getComponent('crowdService') )

#set($timeNow=$content.currentDate.time)
#set($group = $userAccessor.getGroup($paramgroup))

#if($group)
#set($usernames = $userAccessor.getMemberNames($group))

<table class="confluenceTable" width="660px">
<tr>
<th class="confluenceTh " width="220px">Name</th>
<th class="confluenceTh" width="110px">Create date</th>
<th class="confluenceTh" width="110px">Last Successful Login</th>
<th class="confluenceTh" width="110px">Last Failed Login</th>
<th class="confluenceTh" width="110px" style="text-align:center;">Activated</th>
<th class="confluenceTh" width="110px" style="text-align:center;">Days</th>
</tr>
#foreach($username in $usernames)
#set($t3="9999")
#set($user = $userAccessor.getUserByName($username))
#set($crowdUser = $crowdService.getUser($user.name))
#set($lastLogin = $loginManager.getLoginInfo($user).lastSuccessfulLoginDate)

<tr>
<td class="confluenceTd">
<a target="_tab" href="/admin/users/viewuser.action?username=$username">$user.getFullName()</a>
</td>
<td class="confluenceTd" style="text-align:center;">
$action.dateFormatter.formatGivenString('yyyy.MM.dd', $crowdUser.createdDate)</td>
<td class="confluenceTd" style="text-align:center;">
<div>$action.dateFormatter.formatGivenString('yyyy.MM.dd',$lastLogin)</div>
</td>
<td class="confluenceTd" style="text-align:center;">
$action.dateFormatter.formatGivenString('yyyy.MM.dd',$loginManager.getLoginInfo($user).lastFailedLoginDate)</td>
<td class="confluenceTd" style="text-align:center;">
#if($userAccessor.isDeactivated($user))
<ac:macro ac:name="status">
<ac:parameter ac:name="colour">Red</ac:parameter>
<ac:parameter ac:name="title">No</ac:parameter>
</ac:macro>
#else
<ac:macro ac:name="status">
<ac:parameter ac:name="colour">Green</ac:parameter>
<ac:parameter ac:name="title">Yes</ac:parameter>
</ac:macro>
#set($totalactiveusers = $totalactiveusers + 1)
#end
</td>

#if($loginManager.getLoginInfo($user).lastSuccessfulLoginDate)
#set($t3= $timeNow - $loginManager.getLoginInfo($user).lastSuccessfulLoginDate.time)
#set($t3=$t3/1000/24/60/60)
#end

<td class="confluenceTd" style="text-align:center;">
#if($t3 < 31)
<ac:macro ac:name="status">
<ac:parameter ac:name="colour">Green</ac:parameter>
<ac:parameter ac:name="title">$t3</ac:parameter>
</ac:macro>
#elseif($t3 < 365)
<ac:macro ac:name="status">
<ac:parameter ac:name="colour">Yellow</ac:parameter>
<ac:parameter ac:name="title">$t3</ac:parameter>
</ac:macro>
#else
<ac:macro ac:name="status">
<ac:parameter ac:name="colour">Red</ac:parameter>
<ac:parameter ac:name="title">$t3</ac:parameter>
</ac:macro>
#end
</td>
</tr>
#end
</table>
#end

Like Riist Vara likes this
Diego October 8, 2020

hey @KC Integrations 

 

Thanks for updating it and sharing but for some reason mine is not showing the Create, Last Login and Last Failed login columns. Days is always showing red and 9999. Do you happen to know what could I be doing wrong? I just copied and pasted your code. Is your still working?

 

Thanks!

Chris Kent
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 11, 2020

Hi @Diego ,

I think you need to enable some classes from the velocity context. Edit the file: 

 

and at the bottom, comment out some classes, here is a copy of the last section of the file: WEB-INF/classes/velocity.properties

# ----------------------------------------------------------------------------
# SECURE INTROSPECTOR
# ----------------------------------------------------------------------------
# If selected, prohibits methods in certain classes and packages from being
# accessed. If you are adding new package or class restriction, please also
# add it to /confluence-core/confluence/src/etc/java/org/apache/velocity/runtime/defaults/velocity.properties
# The list is maintained at:
# https://extranet.atlassian.com/display/CSPF/Restrict+packages+and+classes+usage+from+velocity+files
# ----------------------------------------------------------------------------

#introspector.restrict.packages = java.lang.reflect,\
introspector.restrict.packages = \
com.atlassian.cache,\
com.atlassian.confluence.util.http,\
com.atlassian.failurecache,\
com.atlassian.vcache,\
com.atlassian.sal.api.net,\
com.google.common.cache,\
com.google.common.net,\
com.hazelcast,java.jms,\
java.rmi,\
javax.management,\
javax.naming,\
org.apache.commons.httpclient,\
org.apache.httpcomponents.httpclient,\
org.apache.http.client,\
org.ehcache,\
com.google.common.reflect,\
com.sun.jmx,com.sun.jna,\
javax.xml,jdk.nashorn,\
net.bytebuddy,\
net.sf.cglib,org.apache.bcel,\
org.javassist,org.ow2.asm,\
sun,\
com.atlassian.activeobjects,\
com.atlassian.hibernate,\
#java.sql,\
javax.persistence,\
#javax.sql,\
liquibase,\
net.java.ao,\
net.sf.hibernate,\
org.hibernate,\
com.atlassian.confluence.setup.bandana,\
com.atlassian.filestore,\
com.atlassian.media,\
com.google.common.io,java.io,\
java.nio,java.util.jar,\
java.util.zip,\
org.apache.commons.io,\
com.atlassian.confluence.impl.util.sandbox,\
com.atlassian.confluence.util.io,\
com.atlassian.confluence.util.sandbox,\
com.atlassian.quartz,\
com.atlassian.scheduler,\
com.atlassian.utils.process,\
com.atlassian.util.concurrent,\
io.atlassian.util.concurrent,\
java.util.concurrent,\
org.apache.commons.exec,\
org.springframework.util.concurrent,\
org.quartz,\
oshi

#introspector.restrict.classes = java.lang.Class,\
introspector.restrict.classes = \
java.lang.ClassLoader,\
java.lang.Compiler,\
java.lang.InheritableThreadLocal,\
java.lang.Package,\
java.lang.Process,\
java.lang.Runtime,\
java.lang.RuntimePermission,\
java.lang.SecurityManager,\
java.lang.System,\
java.lang.Thread,\
java.lang.ThreadGroup,\
java.lang.ThreadLocal, \
com.atlassian.applinks.api.ApplicationLinkRequestFactory,\
com.atlassian.confluence.util.ConfluenceUberClassLoader,\
com.atlassian.core.util.ClassLoaderUtils,\
com.atlassian.core.util.ClassHelper

Like Riist Vara likes this
Frederick Roeser October 30, 2020

@Chris Kent 

Thanks for posting your code. The original "last login" macro is my favourite admin plugin. Unfortunately it does not work anymore .

I'm on 7.4.5 (server version) and I tried your solution. Sadly it does not work for me. It just produces a blank page.

Does anyone has an idea why?

KC Integrations November 1, 2020

Hi,

Did you remove all the security restrictions for velocity templates. These security settings are new and prevent a lot of complicated user macros from working ;(

Charles Pikscher January 13, 2021

Finally got around to trying this (editing velocity.properties).  I can confirm it works on 7.9.3.  Nice find!

Charles Pikscher August 16, 2023

FYI. there was a change (just updated to 7.19.12) per:

https://developer.atlassian.com/server/confluence/confluence-objects-accessible-from-velocity/

Had to add this to setenv.sh:

CATALINA_OPTS="-Dmacro.required.velocity.context.keys=action,req,spaceManager,permissionHelper,userAccessor,htmlUtil ${CATALINA_OPTS}"
2 votes
Romain LORY March 17, 2020

Hello,

I try to do this on Confluence 7.2.1 and the column Last successful login date is still black.

Have you an idea on how to solved it?

 

Regards

Gerald MURIEL September 9, 2022

Hello same here, we are on 7.18.3.

1 vote
Bruce Schlueter November 28, 2012

Hi Remo,

a really nice job you did with your macro. What I noticed is that the sort order seems to brake if we add the time to the line, so we just keep the date like this :

&lt;td class="confluenceTd"&gt;$action.dateFormatter.formatGivenString('dd.MM.yyyy', $crowdUser.createdDate)&lt;/td&gt;

That is enough for us as we do not really need the exact time and the day suffices.

Another point concerning the last column "Active". Is there a possibility to sort this? I cant get it working...

Any idea would be great, like adding "True" or "False" and hide this and just show the image.

Thanks

Steve Goldberg
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 28, 2012

Instead of using tick and cross icons, I just use the status macro:

#if($userAccessor.isDeactivated($user))
	&lt;ac:macro ac:name="status"&gt;
		&lt;ac:parameter ac:name="colour"&gt;Red&lt;/ac:parameter&gt;
		&lt;ac:parameter ac:name="title"&gt;NO&lt;/ac:parameter&gt;
	&lt;/ac:macro&gt;
#else
	&lt;ac:macro ac:name="status"&gt;
		&lt;ac:parameter ac:name="colour"&gt;Green&lt;/ac:parameter&gt;
		&lt;ac:parameter ac:name="title"&gt;YES&lt;/ac:parameter&gt;
	&lt;/ac:macro&gt;
#set($totalactiveusers = $totalactiveusers + 1)
#end

Bruce Schlueter November 28, 2012

Thanks, that works like a charme.

We are just setting up our wiki and we would like to know who never logged in. I tried something like

#if($loginManager.getLoginInfo($user).lastSuccessfulLoginDate ==' ')

or this

 #if($loginManager.getLoginInfo($user).lastSuccessfulLoginDate ==null)

But I just get an empty table. How can I check for null values?

Remo Siegwart
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 28, 2012

Try the following:

#if(!$loginManager.getLoginInfo($user).lastSuccessfulLoginDate)

Bruce Schlueter November 28, 2012

Thanks a lot, that is what I was missing.

1 vote
Thomas Berger June 2, 2012

Little bug for Crowd users: '$user' should be '$user.name' for the last successful login date:

<td class="confluenceTd">$action.dateFormatter.formatDateTime($loginManager.getLoginInfo($user.name).lastSuccessfulLoginDate)</td>
Steve Goldberg
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 4, 2012

If I modify the code to include that change, will it still work for non-Crowd users?

Thomas Berger June 4, 2012

Not sure, don't think so. We are using Crowd and I was referring to the code you've posted at (Feb 08 at 11:15 AM).

But I've noticed that the version above that was not for Crowd.

0 votes
Application Services November 13, 2019

I found out that the updated_date in the Confluence [dbo].[cwd_user] table actually shows last log in date/time.

Very useful.

0 votes
Ankit Jhingan August 10, 2019

 

I am getting the error using the macro shared by @remo

page isnt working because it took too long to respond.
HTTP ERROR 504

0 votes
JD Gebicki March 22, 2019

Thank you so much, Remo! We are always close to our user limit, and this will be immensely helpful in identifying inactive users to be disabled. Really, thank you!!

0 votes
Dana Jansen December 12, 2018

is it possible to prevent specific groups from being listed. i.e. the confluence-users group will have too many users to list

0 votes
Alex Fox November 30, 2018

Is it possible to use this on a confluence page but to view the user's last login date to Jira? Our confluence uses Jira for user management. Great macro though!

0 votes
SimratPal Singh October 24, 2018

How do I consume this code withing my Confluence?

George Lewe (LSY)
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
October 25, 2018

Hi SimratPal,

you have to write a User Macro

https://confluence.atlassian.com/doc/writing-user-macros-4485.html

Only works with Confluence Server though.

0 votes
Charles Pikscher June 3, 2018

Sorted by date.  Sorry, can't get the spaces right.

## @param group:title=Group|type=string|required=true|desc=Group Name|default=confluence-users
#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($loginManager = $containerContext.getComponent('loginManager'))
#set($group = $userAccessor.getGroup($paramgroup))
#set($usernames = $userAccessor.getMemberNames($group))

#set($rows= [])
#foreach($username in $usernames)
#set($user = $userAccessor.getUser($username))
#set($foo = $rows.add( {"name" : $user.name, "date" : $loginManager.getLoginInfo($user).lastSuccessfulLoginDate} ))
#end

#set($ii = $rows.size() - 2)
#foreach($i in [0..$ii])
#set($jj = $rows.size() - $i - 2)
#foreach($j in [0..$jj])
#set($inc = $j + 1)
#if ($rows.get($j).get("date"))
#if ($rows.get($inc).get("date"))
#if ($rows.get($j).get("date").before($rows.get($inc).get("date")))
#set($tmp = $rows.get($j))
#set($foo = $rows.set($j, $rows.get($inc)))
#set($foo = $rows.set($inc, $tmp))
#end
#end
#else
#set($tmp = $rows.get($j))
#set($foo = $rows.set($j, $rows.get($inc)))
#set($foo = $rows.set($inc, $tmp))
#end
#end
#end

<h2>$group</h2>

<table class="confluenceTable">
<tr>
<th class="confluenceTh">Count</th>
<th class="confluenceTh">User</th>
<th class="confluenceTh">Last Successful Login Date</th>
</tr>
#foreach($row in $rows)
<tr>
<td class="confluenceTd">$velocityCount</td>
<td class="confluenceTd">#usernameLink($row.get("name"))</td>
<td class="confluenceTd">$action.dateFormatter.formatDateTime($row.get("date"))</td>
</tr>
#end
</table>
Nidhi Telang August 7, 2018

Hi Folks,

Could you please advise for Bitbucket. I need to find last login date of users in bitbucket.

 com.atlassian.jira.bc.security.login.LoginInfo -  this one is for jira, can't find one for bitbucket. Please advice.

Thanks

Charles Pikscher August 7, 2018

For Bitbucket, I use the REST API (rest/api/1.0/admin/users) to get lastAuthenticationTimestamp (ms from 1/1/1970).

Dana Grahf September 6, 2018

Do I just need to paste the above code snipped into Create UserMacro from the Admin console?  If so what Macro Processing Body should I select: No Macro Body, Escaped, Unrendered, Rendered

Charles Pikscher September 6, 2018

I used No macro body.  And then add the macro to a page with Add->Other Macros

Dana Grahf September 6, 2018

Thank you.  Also on the login details topic - trying to solve this item too... https://community.atlassian.com/t5/Confluence-questions/postgres-statement-for-null-successdate/qaq-p/884856

Charles Pikscher September 6, 2018

This macro will show a blank for users in the group that have never logged in.

0 votes
Stefan Baader January 23, 2014

Remo, very useful User Macro. Do you know how to filter only users of some given space?

Cheers, Stefan

Steve Goldberg
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 23, 2014

What do you mean by 'space'? Do you mean 'group' or do you mean something more complicated like the users who can access a particular space?

Stefan Baader February 4, 2015

Steve, I mean all users with permissions to a specific space (kind of community). Groups, single users.

George Lewe (LSY)
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
August 13, 2015

Try this. It displays last login of user permitted to current space: {code}## Macro title: Last Login By Current Space ## Macro has a body: N ## Body processing: No macro body ## ## Macro to display the last login date of users who have access to the current space ## @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($loginManager = $containerContext.getComponent('loginManager')) #set($users = $userAccessor.getUsers()) <table class="confluenceTable"> <tr> <th class="confluenceTh">User</th> <th class="confluenceTh">Last Successful Login</th> </tr> #foreach($user in $users) ## list the last login date of users who can view the current space #if ($permissionHelper.canView($user, $space)) <tr> <td class="confluenceTd">#usernameLink($user.name)</td> #if (!$loginManager.getLoginInfo($user).lastSuccessfulLoginDate) <td class="confluenceTd" style="background-color:#ff0000"> <strong>NEVER</strong> </td> #else <td class="confluenceTd">$action.dateFormatter.formatDateTime($loginManager.getLoginInfo($user.name).lastSuccessfulLoginDate)</td> #end </tr> #end #end </table>{code}

George Lewe (LSY)
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
August 13, 2015

Jesus, I am commenting this for the third time now. What is the markup for a code block in a comment here? :-)

0 votes
Selcuk Savas
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 23, 2013
Hi Remo, I have been using your macro and it works perfectly. Can I ask a favor? We recently created new groups and new users and it become complicated for me to report on them base on their last login details. Is it possible for you to add users login id and groups that they are in it to the macro? I tried myself but no success andf I am lost. I really appreciate your help. Cheers, Selcukl
0 votes
Selcuk Savas
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 23, 2013
Hi Remo, I have been using your macro and it works perfectly. Can I ask a favor? We recently created new groups and new users and it become complicated for me to report on them base on their last login details. Is it possible for you to add users login id and groups that they are in it to the macro? I tried myself but no success andf I am lost. I really appreciate your help. Cheers, Selcuk
Steve Goldberg
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 23, 2014

Hi Selcuk, you can use $userAccessor.getGroupNamesForUserName($username) to get the groups a user is part of and then use a loop to print them out as you want. E.g.:

#set ($groups = $userAccessor.getGroupNamesForUserName($username))
	&lt;ul&gt;
		#foreach ($group in $groups)
			&lt;li&gt;$group&lt;/li&gt;
		#end
	&lt;/ul&gt;
#end

0 votes
tg February 5, 2013

Hi and thanks all the above!

I'm doing this in Confluence 3.3 and $lastLoginDate.time doesn't work. (But $content.currentDate.time works fine.) Any suggestions on how else I might get $loginManager.getLoginInfo($user.name).lastSuccessfulLoginDate) in milliseconds?

Also, how do I format my compare date that is in milliseconds into a formatted date?

I'm using the code from here as the basis of my macro, so no JQuery or javascript is involved.

Any help would be greatly appreciated!

0 votes
Doods Perea November 28, 2012

Thanks Remo it works!

One little kink though, we are on Confluence 4.2.7 so the columns won't sort. Anyway you could extend help by providing extra code to the one you wrote above?

Kind regards,

Doods

0 votes
Doods Perea November 26, 2012

Hi Remo - excellent macro.

Is there a way to display only those that have not logged in to the system for the last 30 days? Also, can the column titles become clickable for sorting (desc/asc)?

Thanks in advance.

Remo Siegwart
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 27, 2012

Just add an if-clause and compare the last login date with the current date:

## @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($loginManager = $containerContext.getComponent('loginManager'))
#set($users = $userAccessor.getUsers())

#set($thirtyDaysInMilliseconds = 30 * 24 * 60 * 60 * 1000)
#set($thirtyDaysInThePastInMilliseconds = $content.currentDate.time - $thirtyDaysInMilliseconds)

&lt;table class="confluenceTable"&gt;
    &lt;tr&gt;
        &lt;th class="confluenceTh"&gt;User&lt;/th&gt;
        &lt;th class="confluenceTh"&gt;Last Successful Login Date&lt;/th&gt;
    &lt;/tr&gt;

    #foreach($user in $users)
        #set($lastLoginDate = $loginManager.getLoginInfo($user).lastSuccessfulLoginDate)
        #if($thirtyDaysInThePastInMilliseconds &gt; $lastLoginDate.time)
            &lt;tr&gt;
                &lt;td class="confluenceTd"&gt;#usernameLink($user.name)&lt;/td&gt;
                &lt;td class="confluenceTd"&gt;$action.dateFormatter.formatDateTime($lastLoginDate)&lt;/td&gt;
            &lt;/tr&gt;
        #end
    #end
&lt;/table&gt;

Table columns should be sortable by default since Confluence version 4.3.

Hope this helps

Like mpazz likes this
Doods Perea November 28, 2012

Thanks Remo it works!

One little kink though, we are on Confluence 4.2.7 so the columns won't sort. Anyway you could extend help by providing extra code to the one you wrote above?

Kind regards,

Doods

Remo Siegwart
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 28, 2012

Sadly, there is no easy way to do that in a user macro. You would need to write a custom plugin for that. So, I would suggest to wait for 4.3.

Thomas Berger November 28, 2012

You could use Bob Swift's Table-plus plugin to get a sortable table.

0 votes
Kjell Lauren September 19, 2012

I tried this on 3.5.17 and it shows empty fields for the last login, what might be the problem?

Thomas Berger October 4, 2012
 Try '$user.name' instead of '$user', seems to be a v3.5.x related issue...
&lt;td class="confluenceTd"&gt;$action.dateFormatter.formatDateTime($loginManager.getLoginInfo($user.name).lastSuccessfulLoginDate)&lt;/td&gt;
0 votes
Thomas Berger June 4, 2012

Not sure, don't think so. We are using Crowd and I was referring to the code you've posted at (Feb 08 at 11:15 AM).

But I've noticed that the version above that was not for Crowd.

0 votes
Jason Pepper March 15, 2012

Thats a great little script..

Please can you tell me how I would get a count of user logins e.g. user1 has logged in 123 times.. ?

Thx

Remo Siegwart
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 17, 2012

As far as I know it's not possible by default in Confluence. Confluence only stores a "total failed login count", but no total login count.

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events