Skip to content

Commit af715c5

Browse files
committed
Add change user lock status
1 parent 2851d0d commit af715c5

File tree

6 files changed

+121
-0
lines changed

6 files changed

+121
-0
lines changed

src/main/java/ru/loolzaaa/authserver/controllers/UserController.java

+9
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,15 @@ ResponseEntity<RequestStatusDTO> deleteUser(@PathVariable("username") String use
5959
return ResponseEntity.status(requestStatusDTO.getStatusCode()).body(requestStatusDTO);
6060
}
6161

62+
@PreAuthorize("hasRole('ADMIN')")
63+
@PatchMapping(value = "/user/{username}/lock", produces = "application/json")
64+
ResponseEntity<RequestStatusDTO> changeUserLockStatus(@PathVariable("username") String username,
65+
@RequestParam(value = "enabled", required = false) Boolean enabled,
66+
@RequestParam(value = "lock", required = false) Boolean lock) {
67+
RequestStatusDTO requestStatusDTO = userControlService.changeUserLockStatus(username, enabled, lock);
68+
return ResponseEntity.status(requestStatusDTO.getStatusCode()).body(requestStatusDTO);
69+
}
70+
6271
@PostMapping(value = "/user/{username}/password/change", produces = "application/json")
6372
ResponseEntity<RequestStatusDTO> changeUserPassword(@PathVariable("username") String username,
6473
@RequestParam("oldPassword") String oldPassword,

src/main/java/ru/loolzaaa/authserver/model/UserAttributes.java

+1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ private UserAttributes() {}
88
public static final String PRIVILEGES = "privileges";
99
public static final String CREDENTIALS_EXP = "credentials_exp";
1010
public static final String TEMPORARY = "temporary";
11+
public static final String LOCK = "lock";
1112
}

src/main/java/ru/loolzaaa/authserver/model/UserPrincipal.java

+3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ public UserPrincipal(User user) {
4545
log.info("User [{}] credentials is expired", user.getLogin());
4646
this.credentialsNonExpired = false;
4747
}
48+
if (authNode.has(UserAttributes.LOCK)) {
49+
this.accountNonLocked = !authNode.get(UserAttributes.LOCK).asBoolean();
50+
}
4851
} else {
4952
log.info("User [{}] is locked", user.getLogin());
5053
this.accountNonLocked = false;

src/main/java/ru/loolzaaa/authserver/repositories/UserRepository.java

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414
public interface UserRepository extends CrudRepository<User, Long> {
1515
Optional<User> findByLogin(String username);
1616

17+
@Modifying
18+
@Query("UPDATE users SET enabled = :enabled WHERE login = :login")
19+
void updateEnabledByLogin(@Param("enabled") boolean enabled, @Param("login") String login);
20+
1721
@Modifying
1822
@Query("UPDATE users SET config = :config::jsonb WHERE login = :login")
1923
void updateConfigByLogin(@Param("config") JsonNode config, @Param("login") String login);

src/main/java/ru/loolzaaa/authserver/services/UserControlService.java

+34
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,40 @@ public RequestStatusDTO deleteUser(String login, String password) {
163163
return RequestStatusDTO.ok("User [%s] deleted. Hash %s database", login, isHashDeleted ? "deleted from" : "stayed in");
164164
}
165165

166+
@Transactional
167+
public RequestStatusDTO changeUserLockStatus(String login, Boolean enabled, Boolean lock) {
168+
if (enabled == null && lock == null) {
169+
log.warn("Try to change NONE of enabled/lock flags for user: {}", login);
170+
throw new RequestErrorException("Try to change NONE of enabled/lock flags for user: [%s]", login);
171+
}
172+
if (enabled != null && lock != null) {
173+
log.warn("Try to change BOTH of enabled/lock flags for user: {}", login);
174+
throw new RequestErrorException("Try to change BOTH of enabled/lock flags for user: [%s]", login);
175+
}
176+
177+
User user = userRepository.findByLogin(login).orElse(null);
178+
179+
if (user == null) {
180+
log.warn("Try to lock non existing user: {}", login);
181+
throw new RequestErrorException("There is no user with login [%s]", login);
182+
}
183+
184+
StringBuilder answer = new StringBuilder("User [%s] ");
185+
if (enabled != null) {
186+
userRepository.updateEnabledByLogin(enabled, login);
187+
log.info("User [{}] {}", login, enabled ? "enabled" : "disabled");
188+
answer.append(enabled ? "enabled" : "disabled");
189+
}
190+
if (lock != null) {
191+
JsonNode userConfig = user.getConfig();
192+
((ObjectNode) userConfig.get(ssoServerProperties.getApplication().getName())).put(UserAttributes.LOCK, lock);
193+
userRepository.updateConfigByLogin(userConfig, login);
194+
log.info("User [{}] {}", login, lock ? "locked" : "unlocked");
195+
answer.append(lock ? "locked" : "unlocked");
196+
}
197+
return RequestStatusDTO.ok(answer.toString(), login);
198+
}
199+
166200
@Transactional
167201
public RequestStatusDTO changeUserPassword(String login, String oldPassword, String newPassword) {
168202
User user = userRepository.findByLogin(login).orElse(null);

src/main/resources/templates/admin.html

+70
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,43 @@ <h5>Reset user password</h5>
107107
</div>
108108
</div>
109109
</div>
110+
<div class="container border rounded my-3 p-3">
111+
<h5>Update user enabled/lock flags</h5>
112+
<div class="row">
113+
<div class="col">
114+
<div class="mb-3">
115+
<label for="usernameInput4" class="form-label">Username</label>
116+
<input type="text" class="form-control" id="usernameInput4">
117+
</div>
118+
</div>
119+
<div class="col">
120+
<div class="mb-3">
121+
<label for="userEnabledSelect" class="form-label">Enabled</label>
122+
<select class="form-select" aria-label="Default select example" id="userEnabledSelect">
123+
<option selected>Open this select menu</option>
124+
<option value="1">True</option>
125+
<option value="0">False</option>
126+
</select>
127+
</div>
128+
</div>
129+
<div class="col">
130+
<div class="mb-3">
131+
<label for="userLockSelect" class="form-label">Lock</label>
132+
<select class="form-select" aria-label="Default select example" id="userLockSelect">
133+
<option selected>Open this select menu</option>
134+
<option value="1">True</option>
135+
<option value="0">False</option>
136+
</select>
137+
</div>
138+
</div>
139+
<div class="col-2">
140+
<div class="d-grid mb-3">
141+
<label class="form-label">&nbsp;</label>
142+
<button class="btn btn-warning" type="button" onclick="changeUserLockStatus()">Change</button>
143+
</div>
144+
</div>
145+
</div>
146+
</div>
110147
<div class="d-grid">
111148
<a href="/" class="btn btn-secondary" type="button">Back to main page</a>
112149
</div>
@@ -191,6 +228,39 @@ <h5>Reset user password</h5>
191228
}
192229
});
193230
}
231+
function changeUserLockStatus() {
232+
let username = document.getElementById('usernameInput4').value;
233+
let enabled = document.getElementById('userEnabledSelect').value;
234+
let lock = document.getElementById('userLockSelect').value;
235+
let valid1 = username != '';
236+
let valid2 = ((enabled == '0' || enabled == '1') && lock != '0' && lock != '1') ||
237+
((lock == '0' || lock == '1') && enabled != '0' && enabled != '1');
238+
if (!valid1) {
239+
alert('Username must not be empty');
240+
return;
241+
}
242+
if (!valid2) {
243+
alert('Only one flag can update');
244+
return;
245+
}
246+
let params = new URLSearchParams();
247+
if (enabled == '0' || enabled == '1') {
248+
params.append('enabled', enabled == '1');
249+
}
250+
if (lock == '0' || lock == '1') {
251+
params.append('lock', lock == '1');
252+
}
253+
instance.patch(`/api/user/${username}/lock`, params)
254+
.then(resp => alert(resp.data.text))
255+
.catch(err => {
256+
console.log(err);
257+
if (err?.response?.data?.text) {
258+
alert(err.response.data.text);
259+
} else {
260+
alert('ERROR! See console');
261+
}
262+
});
263+
}
194264
instance.interceptors.response.use(function (response) {
195265
const _csrf = document.cookie.match(new RegExp(`XSRF-TOKEN=([^;]+)`));
196266
if (_csrf !== undefined && _csrf !== null) document.getElementsByName('_csrf').forEach(el => el.value = _csrf[1]);

0 commit comments

Comments
 (0)