Skip to content

Commit d6ce668

Browse files
RANGER-5271 : Last login date and time on Ranger Home page (#655)
1 parent bc66e45 commit d6ce668

File tree

8 files changed

+65
-2
lines changed

8 files changed

+65
-2
lines changed

security-admin/src/main/java/org/apache/ranger/biz/SessionMgr.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import java.util.ArrayList;
2323
import java.util.Calendar;
24+
import java.util.Date;
2425
import java.util.HashSet;
2526
import java.util.List;
2627
import java.util.Set;
@@ -326,6 +327,18 @@ public XXAuthSession processFailureLogin(int authStatus, int authType,
326327
return gjAuthSession;
327328
}
328329

330+
public Date getLastSuccessLoginAuthTimeByUserId(String loginId) {
331+
XXAuthSession xXAuthSession = daoManager.getXXAuthSession().getLastSuccessLoginAuthSessionByUserId(loginId);
332+
333+
if (xXAuthSession != null) {
334+
return authSessionService.populateViewBean(xXAuthSession).getAuthTime();
335+
} else {
336+
logger.info("Session cleaned up or User logged in for first time");
337+
}
338+
339+
return null;
340+
}
341+
329342
protected boolean validateUserSession(UserSessionBase userSession,
330343
String currentLoginId) {
331344
if (currentLoginId

security-admin/src/main/java/org/apache/ranger/biz/UserMgr.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,9 @@ public VXPortalUser mapXXPortalUserToVXPortalUser(XXPortalUser user,
585585

586586
userProfile.setUserRoleList(userRoleList);
587587
}
588+
userProfile.setLastLoginTime(sessionMgr.getLastSuccessLoginAuthTimeByUserId(sess.getLoginId()));
588589
userProfile.setUserSource(user.getUserSource());
590+
589591
return userProfile;
590592
}
591593

security-admin/src/main/java/org/apache/ranger/db/XXAuthSessionDao.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,23 @@ public List<XXAuthSession> getAuthSessionByUserId(Long userId){
7171
}
7272
}
7373

74+
public XXAuthSession getLastSuccessLoginAuthSessionByUserId(String loginId) {
75+
if (loginId == null) {
76+
return null;
77+
}
78+
try {
79+
List<XXAuthSession> sessions = getEntityManager()
80+
.createNamedQuery("XXAuthSession.getSuccessAuthSessionsByUserId", tClass)
81+
.setParameter("loginId", loginId)
82+
.setParameter("authStatus", XXAuthSession.AUTH_STATUS_SUCCESS)
83+
.setMaxResults(2)
84+
.getResultList();
85+
return sessions.size() >= 2 ? sessions.get(1) : null;
86+
} catch (NoResultException ignoreNoResultFound) {
87+
return null;
88+
}
89+
}
90+
7491
public long getRecentAuthFailureCountByLoginId(String loginId, int timeRangezSecond){
7592
Date authWindowStartTime = new Date(DateUtil.getUTCDate().getTime() - timeRangezSecond * 1000);
7693

security-admin/src/main/java/org/apache/ranger/view/VXPortalUser.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,17 @@
2020
package org.apache.ranger.view;
2121

2222
import java.util.Collection;
23+
import java.util.Date;
2324
import java.util.List;
2425
import java.util.Map;
2526

2627
import org.apache.ranger.common.AppConstants;
28+
import org.apache.ranger.json.JsonDateSerializer;
2729
import com.fasterxml.jackson.annotation.JsonAutoDetect;
2830
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
2931
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
3032
import com.fasterxml.jackson.annotation.JsonInclude;
33+
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
3134

3235
@JsonAutoDetect(getterVisibility=Visibility.NONE, setterVisibility=Visibility.NONE, fieldVisibility=Visibility.ANY)
3336
@JsonInclude(JsonInclude.Include.NON_NULL)
@@ -95,6 +98,9 @@ public class VXPortalUser extends VXDataObject implements java.io.Serializable {
9598
*/
9699
protected String syncSource;
97100

101+
@JsonSerialize(using = JsonDateSerializer.class)
102+
protected Date lastLoginTime;
103+
98104
/**
99105
* Configuration properties.
100106
*
@@ -348,6 +354,14 @@ public void setSyncSource(final String syncSource) {
348354
this.syncSource = syncSource;
349355
}
350356

357+
public Date getLastLoginTime() {
358+
return lastLoginTime;
359+
}
360+
361+
public void setLastLoginTime(Date lastLoginTime) {
362+
this.lastLoginTime = lastLoginTime;
363+
}
364+
351365
/**
352366
* This return the bean content in string format
353367
* @return formatedStr
@@ -366,6 +380,7 @@ public String toString( ) {
366380
str += "userRoleList={" + userRoleList + "} ";
367381
str += "otherAttributes={" + otherAttributes + "} ";
368382
str += "syncSource={" + syncSource + "} ";
383+
str += "lastLoginTime={" + lastLoginTime + "} ";
369384
str += "}";
370385
return str;
371386
}

security-admin/src/main/resources/META-INF/jpa_named_queries.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@
4848
<query>DELETE FROM XXAuthSession obj WHERE obj.id in :ids
4949
</query>
5050
</named-query>
51+
<named-query name="XXAuthSession.getSuccessAuthSessionsByUserId">
52+
<query>SELECT obj FROM XXAuthSession obj WHERE obj.loginId = :loginId and obj.authStatus = :authStatus order by obj.id DESC
53+
</query>
54+
</named-query>
55+
5156

5257
<!-- XXPortalUser -->
5358
<named-query name="XXPortalUser.findByEmailAddress">

security-admin/src/main/webapp/react-webapp/src/styles/style.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1309,7 +1309,7 @@ header {
13091309
}
13101310

13111311
.top-scroll {
1312-
bottom: 3px;
1312+
bottom: 10px;
13131313
right: 5px;
13141314
}
13151315

security-admin/src/main/webapp/react-webapp/src/views/Layout.jsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import { Loader } from "../components/CommonComponents";
4040
import { Suspense } from "react";
4141
import { PathAssociateWithModule } from "../utils/XAEnums";
4242
import { flatMap, values } from "lodash";
43+
import dateFormat from "dateformat";
4344

4445
const Layout = () => {
4546
let location = useLocation();
@@ -94,6 +95,13 @@ const Layout = () => {
9495
activate();
9596
};
9697

98+
const lastLoginInformation = userProfile?.lastLoginTime
99+
? `You last logged in on, ${dateFormat(
100+
new Date(userProfile.lastLoginTime),
101+
"dddd, mmm dd, yyyy, hh:MM:ss TT"
102+
)}`
103+
: "";
104+
97105
useEffect(() => {
98106
const interval = setInterval(() => {
99107
if (isPrompted()) {
@@ -170,6 +178,9 @@ const Layout = () => {
170178
>
171179
Licensed under the Apache License, Version 2.0
172180
</a>
181+
<span className="float-end mb-2 me-4" style={{ color: "#999" }}>
182+
{lastLoginInformation}
183+
</span>
173184
</p>
174185
</div>
175186
</footer>

security-admin/src/main/webapp/react-webapp/src/views/SideBar/SideBar.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ export const SideBar = () => {
125125

126126
const userProps = getUserProfile();
127127
const loginId = (
128-
<span className="login-id user-name">{userProps?.loginId}</span>
128+
<span className="login-id user-name p-0">{userProps?.loginId}</span>
129129
);
130130

131131
let location = useLocation();

0 commit comments

Comments
 (0)