Skip to content

Commit a55742c

Browse files
varundeepsainiVarun Deep Saini
andauthored
AMM-118: Add admin account lock controls (#332)
Co-authored-by: Varun Deep Saini <varun.23bcs10048@ms.sst.scaler.com>
1 parent bded02e commit a55742c

6 files changed

Lines changed: 396 additions & 128 deletions

File tree

src/main/java/com/iemr/common/controller/users/IEMRAdminController.java

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
@RequestMapping("/user")
7878
@RestController
7979
public class IEMRAdminController {
80+
private static final String USER_ID_FIELD = "userId";
8081
private final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
8182
private InputMapper inputMapper = new InputMapper();
8283

@@ -583,6 +584,13 @@ public String getLoginResponse(HttpServletRequest request) {
583584
throw new IEMRException("Authentication failed. Please log in again.");
584585
}
585586

587+
// Validate the token first
588+
Claims claims = jwtUtil.validateToken(jwtToken);
589+
if (claims == null) {
590+
logger.warn("Authentication failed: invalid or expired token.");
591+
throw new IEMRException("Authentication failed. Please log in again.");
592+
}
593+
586594
// Extract user ID from the JWT token
587595
String userId = jwtUtil.getUserIdFromToken(jwtToken);
588596

@@ -1248,4 +1256,104 @@ public ResponseEntity<?> checkUserDetails(@PathVariable("userName") String userN
12481256
}
12491257

12501258
}
1259+
1260+
@Operation(summary = "Lock user account")
1261+
@PostMapping(value = "/lockUserAccount", produces = MediaType.APPLICATION_JSON, headers = "Authorization")
1262+
public String lockUserAccount(@RequestBody String request, HttpServletRequest httpRequest) {
1263+
OutputResponse response = new OutputResponse();
1264+
try {
1265+
Long authenticatedUserId = getAuthenticatedUserId(httpRequest);
1266+
validateAdminPrivileges(authenticatedUserId);
1267+
Long userId = parseUserIdFromRequest(request);
1268+
boolean locked = iemrAdminUserServiceImpl.lockUserAccount(userId);
1269+
response.setResponse(locked ? "User account successfully locked" : "User account was already locked");
1270+
} catch (Exception e) {
1271+
logger.error("Error locking user account: " + e.getMessage(), e);
1272+
response.setError(e);
1273+
}
1274+
return response.toString();
1275+
}
1276+
1277+
@Operation(summary = "Unlock user account locked due to failed login attempts")
1278+
@PostMapping(value = "/unlockUserAccount", produces = MediaType.APPLICATION_JSON, headers = "Authorization")
1279+
public String unlockUserAccount(@RequestBody String request, HttpServletRequest httpRequest) {
1280+
OutputResponse response = new OutputResponse();
1281+
try {
1282+
Long authenticatedUserId = getAuthenticatedUserId(httpRequest);
1283+
validateAdminPrivileges(authenticatedUserId);
1284+
Long userId = parseUserIdFromRequest(request);
1285+
boolean unlocked = iemrAdminUserServiceImpl.unlockUserAccount(userId);
1286+
response.setResponse(unlocked ? "User account successfully unlocked" : "User account was not locked");
1287+
} catch (Exception e) {
1288+
logger.error("Error unlocking user account: " + e.getMessage(), e);
1289+
response.setError(e);
1290+
}
1291+
return response.toString();
1292+
}
1293+
1294+
@Operation(summary = "Get user account lock status")
1295+
@PostMapping(value = "/getUserLockStatus", produces = MediaType.APPLICATION_JSON, headers = "Authorization")
1296+
public String getUserLockStatus(@RequestBody String request, HttpServletRequest httpRequest) {
1297+
OutputResponse response = new OutputResponse();
1298+
try {
1299+
Long authenticatedUserId = getAuthenticatedUserId(httpRequest);
1300+
validateAdminPrivileges(authenticatedUserId);
1301+
Long userId = parseUserIdFromRequest(request);
1302+
String lockStatusJson = iemrAdminUserServiceImpl.getUserLockStatusJson(userId);
1303+
response.setResponse(lockStatusJson);
1304+
} catch (Exception e) {
1305+
logger.error("Error getting user lock status: " + e.getMessage(), e);
1306+
response.setError(e);
1307+
}
1308+
return response.toString();
1309+
}
1310+
1311+
private Long parseUserIdFromRequest(String request) throws IEMRException {
1312+
try {
1313+
JsonObject requestObj = JsonParser.parseString(request).getAsJsonObject();
1314+
if (!requestObj.has(USER_ID_FIELD) || requestObj.get(USER_ID_FIELD).isJsonNull()) {
1315+
throw new IEMRException(USER_ID_FIELD + " is required");
1316+
}
1317+
JsonElement userIdElement = requestObj.get(USER_ID_FIELD);
1318+
if (!userIdElement.isJsonPrimitive() || !userIdElement.getAsJsonPrimitive().isNumber()) {
1319+
throw new IEMRException(USER_ID_FIELD + " must be a number");
1320+
}
1321+
return userIdElement.getAsLong();
1322+
} catch (IEMRException e) {
1323+
throw e;
1324+
} catch (Exception e) {
1325+
logger.error("Failed to parse {} from request: {}", USER_ID_FIELD, e.getMessage());
1326+
throw new IEMRException("Invalid request body");
1327+
}
1328+
}
1329+
1330+
private Long getAuthenticatedUserId(HttpServletRequest httpRequest) throws IEMRException {
1331+
String authorization = httpRequest.getHeader("Authorization");
1332+
if (authorization != null && authorization.contains("Bearer ")) {
1333+
authorization = authorization.replace("Bearer ", "");
1334+
}
1335+
if (authorization == null || authorization.isEmpty()) {
1336+
throw new IEMRException("Authentication required");
1337+
}
1338+
try {
1339+
String sessionJson = sessionObject.getSessionObject(authorization);
1340+
if (sessionJson == null || sessionJson.isEmpty()) {
1341+
throw new IEMRException("Session expired. Please log in again.");
1342+
}
1343+
JSONObject session = new JSONObject(sessionJson);
1344+
return session.getLong("userID");
1345+
} catch (IEMRException e) {
1346+
throw e;
1347+
} catch (Exception e) {
1348+
logger.error("Authentication failed while extracting user ID: {}", e.getMessage());
1349+
throw new IEMRException("Authentication failed");
1350+
}
1351+
}
1352+
1353+
private void validateAdminPrivileges(Long userId) throws IEMRException {
1354+
if (!iemrAdminUserServiceImpl.hasAdminPrivileges(userId)) {
1355+
logger.warn("Unauthorized access attempt by userId: {}", userId);
1356+
throw new IEMRException("Access denied. Admin privileges required.");
1357+
}
1358+
}
12511359
}

src/main/java/com/iemr/common/data/users/User.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,10 @@ public class User implements Serializable {
213213
@Column(name = "dhistoken")
214214
private String dhistoken;
215215

216+
@Expose
217+
@Column(name = "lock_timestamp")
218+
private Timestamp lockTimestamp;
219+
216220
/*
217221
* protected User() { }
218222
*/

src/main/java/com/iemr/common/repository/users/IEMRUserRepositoryCustom.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ UserSecurityQMapping verifySecurityQuestionAnswers(@Param("UserID") Long UserID,
7575

7676
@Query("SELECT u FROM User u WHERE u.userID=5718")
7777
User getAllExistingUsers();
78-
78+
7979
User findByUserID(Long userID);
8080

8181
@Query("SELECT u FROM User u WHERE LOWER(u.userName) = LOWER(:userName)")

src/main/java/com/iemr/common/service/users/IEMRAdminUserService.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@ public List<ServiceRoleScreenMapping> getUserServiceRoleMappingForProvider(Integ
125125

126126
List<User> findUserIdByUserName(String userName) throws IEMRException;
127127

128+
boolean lockUserAccount(Long userId) throws IEMRException;
129+
130+
boolean unlockUserAccount(Long userId) throws IEMRException;
131+
132+
String getUserLockStatusJson(Long userId) throws IEMRException;
133+
134+
boolean hasAdminPrivileges(Long userId) throws IEMRException;
128135

129-
130136
}

0 commit comments

Comments
 (0)