Skip to content

Commit

Permalink
Merge pull request #580 from AudiovisualMetadataPlatform/AMP-3083_amp…
Browse files Browse the repository at this point in the history
…User

AMP-2226
  • Loading branch information
yingfeng-iu authored Nov 12, 2023
2 parents c46b1fd + 511659d commit 20bda6b
Show file tree
Hide file tree
Showing 5 changed files with 432 additions and 392 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -30,6 +28,7 @@
import edu.indiana.dlib.amppd.web.AuthResponse;
import lombok.extern.slf4j.Slf4j;


/**
* Controller for REST operations on Login.
*
Expand All @@ -40,7 +39,7 @@
@RestController
@Slf4j
public class AmpUserController {

@Autowired
private AmpUserServiceImpl ampUserService;

Expand All @@ -49,16 +48,17 @@ public class AmpUserController {

@Autowired
private PermissionService permissionService;


// Note:
// Currently AMP user accounts are created via self registration, and the involved APIs which involves
// user initiated actions are available to every one, i.e. no authorization required.
// The APIs requiring authorization are those involving approving accounts and querying users.

@RequestMapping(value = "/account/authenticate", method = RequestMethod.POST)
@PostMapping(path = "/account/authenticate")
public ResponseEntity<?> authenticate(@RequestBody JwtRequest authenticationRequest) throws Exception {
String username = authenticationRequest.getUsername();
log.info("Authenticating login for user: " + username);
AuthResponse response = ampUserService.authenticate(username, authenticationRequest.getPassword());

// if authentication failed, respond with status 401
Expand All @@ -70,7 +70,7 @@ public ResponseEntity<?> authenticate(@RequestBody JwtRequest authenticationRequ
return ResponseEntity.ok(response);
}

@RequestMapping(value = "/account/validate", method = RequestMethod.POST)
@PostMapping(path = "/account/validate")
public ResponseEntity<?> validateToken() throws Exception {
// TODO
// this API simply returns 200 status if the token in the request is valid,
Expand All @@ -81,56 +81,52 @@ public ResponseEntity<?> validateToken() throws Exception {

@PostMapping(path = "/account/register", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody AuthResponse register(@RequestBody AmpUser user) {
log.info("Registrating user => Username: "+ user.getUsername() + ", Email:"+ user.getEmail());
log.info("Registering user account: " + user.getUsername());
AuthResponse res = ampUserService.registerAmpUser(user);
log.info(" user registration result: " + res);
return res;
}

@PostMapping(path = "/account/approve", produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody AuthResponse approveAccount(@RequestParam Long userId, @RequestParam Boolean approve) {
// check permission
boolean can = permissionService.hasPermission(ActionType.Update, TargetType.AmpUser, null);
if (!can) {
throw new AccessDeniedException("The current user cannot approve/reject user account registration.");
}

String action = approve ? "approve" : "reject";
log.info(action + "ing user account: " + userId);
AuthResponse res = ampUserService.approveAccount(userId, approve);
return res;
}

@PostMapping(path = "/account/activate", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody AuthResponse activateUser(@RequestBody AuthRequest request) {
log.info("Activate User");
log.info("Activating user account with token: " + request.getToken());
AuthResponse res = ampUserService.activateAccount(request.getToken());
log.info(" activate user result: " + res);
return res;
}

@PostMapping(path = "/account/forgot-password", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody AuthResponse forgotPassword(@RequestBody AuthRequest request) {
log.info("Forgot Password for User => Email:"+ request.getEmailid());
log.info("Sending reset-password email to user: " + request.getEmailid());
AuthResponse res = ampUserService.emailResetPasswordToken(request.getEmailid());
log.info("Forgot Password result: " + res);
return res;
}

@PostMapping(path = "/account/reset-password", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody AuthResponse resetPassword(@RequestBody AuthRequest request) {
log.info("Reset Password for User => Email:"+ request.getEmailid());
AuthResponse res = ampUserService.resetPassword(request.getEmailid(), request.getPassword(), request.getToken());
log.info(" reset Password result: " + res);
return res;
}

// TODO
// This should be GET, or it should be combined with resetPassword API
@PostMapping(path = "/account/reset-password-getEmail", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody AuthResponse resetPasswordGetEmail(@RequestBody AuthRequest request) {
log.info("Calling get email for a token using resetPasswordGetEmail()");
log.info("Retrieving email for reset-password token:" + request.getToken());
AuthResponse res = ampUserService.resetPasswordGetEmail(request.getToken());
log.info(" Fetched Email id for a token using resetPasswordGetEmail():"+res.getEmailid());
return res;
}

@PostMapping(path = "/account/approve", produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody AuthResponse approveAccount(@RequestParam Long userId, @RequestParam Boolean approve) {
// check permission
boolean can = permissionService.hasPermission(ActionType.Update, TargetType.AmpUser, null);
if (!can) {
throw new AccessDeniedException("The current user cannot approve/reject user account registration.");
}

String action = approve ? "approve" : "reject";
log.info(action + " User => id: " + userId);
AuthResponse res = ampUserService.approveAccount(userId, approve);
log.info(action + " User result: " + res);
@PostMapping(path = "/account/reset-password", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public @ResponseBody AuthResponse resetPassword(@RequestBody AuthRequest request) {
log.info("Resetting password for user:" + request.getEmailid());
AuthResponse res = ampUserService.resetPassword(request.getEmailid(), request.getPassword(), request.getToken());
return res;
}

Expand All @@ -141,10 +137,9 @@ public ResponseEntity<?> validateToken() throws Exception {
if (!can) {
throw new AccessDeniedException("The current user cannot view details of other users.");
}

log.info("User => id:"+ Id);
AmpUser ampuser= ampUserService.getUserById(Id);
log.info("Fetched User for given Id using getUserById()"+ampuser.getId());

AmpUser ampuser = ampUserService.getUserById(Id);
log.info("Successfully retrieved user with ID " + ampuser.getId());
return ampuser;
}

Expand All @@ -161,9 +156,9 @@ public List<AmpUserBrief> findActiveUsersByNameStartingIdsExcluding(@RequestPara
if (!can) {
throw new AccessDeniedException("The current user cannot view details of other users.");
}

List<AmpUserBrief> users = null;

// if users to exclude is not provided, skip the exclude-user criteria
if (idsExcluding == null || idsExcluding.isEmpty()) {
users = ampUserRepository.findByStatusAndNameStartsOrderByName(Status.ACTIVATED, nameStarting);
Expand All @@ -173,7 +168,7 @@ public List<AmpUserBrief> findActiveUsersByNameStartingIdsExcluding(@RequestPara
users = ampUserRepository.findByStatusAndNameStartsAndIdNotInOrderByName(Status.ACTIVATED, nameStarting, idsExcluding);
log.info("Successfully found " + users.size() + " active users with name starting with " + nameStarting + ", excluding the " + idsExcluding.size() + " users in the given list.");
}

return users;
}

Expand Down
6 changes: 4 additions & 2 deletions src/main/java/edu/indiana/dlib/amppd/model/TimedToken.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.validation.constraints.NotNull;

import lombok.Data;

Expand All @@ -25,15 +26,16 @@ public class TimedToken {
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

//@NotNull
@NotNull
@Index(unique="true")
@OneToOne(targetEntity = AmpUser.class, fetch = FetchType.EAGER)
@JoinColumn(nullable = false, name = "user_id")
private AmpUser user;

//@NotNull
@NotNull
@Index(unique="true")
private String token;

@NotNull
private Date expiryDate;
}
Loading

0 comments on commit 20bda6b

Please sign in to comment.