Browse Source

implemented removal of user

Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
sqlite
Stephan Richter 3 months ago
parent
commit
cc131d45e0
  1. 1
      de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Constants.java
  2. 30
      de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/UserController.java
  3. 4
      de.srsoftware.oidc.datastore.file/src/main/java/de/srsoftware/oidc/datastore/file/FileStore.java
  4. 13
      de.srsoftware.oidc.web/src/main/resources/en/scripts/common.js
  5. 31
      de.srsoftware.oidc.web/src/main/resources/en/scripts/users.js
  6. 1
      de.srsoftware.oidc.web/src/main/resources/en/todo.html
  7. 5
      de.srsoftware.oidc.web/src/main/resources/en/users.html

1
de.srsoftware.oidc.api/src/main/java/de/srsoftware/oidc/api/Constants.java

@ -48,4 +48,5 @@ public class Constants {
public static final String TOKEN_TYPE = "token_type"; public static final String TOKEN_TYPE = "token_type";
public static final String UNAUTHORIZED_CLIENT = "unauthorized_client"; public static final String UNAUTHORIZED_CLIENT = "unauthorized_client";
public static final String USER = "user"; public static final String USER = "user";
public static final String USER_ID = "user_id";
} }

30
de.srsoftware.oidc.backend/src/main/java/de/srsoftware/oidc/backend/UserController.java

@ -1,8 +1,7 @@
/* © SRSoftware 2024 */ /* © SRSoftware 2024 */
package de.srsoftware.oidc.backend; package de.srsoftware.oidc.backend;
import static de.srsoftware.oidc.api.Constants.APP_NAME; import static de.srsoftware.oidc.api.Constants.*;
import static de.srsoftware.oidc.api.Constants.TOKEN;
import static de.srsoftware.oidc.api.data.Permission.MANAGE_USERS; import static de.srsoftware.oidc.api.data.Permission.MANAGE_USERS;
import static de.srsoftware.oidc.api.data.User.*; import static de.srsoftware.oidc.api.data.User.*;
import static de.srsoftware.utils.Strings.uuid; import static de.srsoftware.utils.Strings.uuid;
@ -44,6 +43,33 @@ public class UserController extends Controller {
return sendContent(ex, newID); return sendContent(ex, newID);
} }
@Override
public boolean doDelete(String path, HttpExchange ex) throws IOException {
var optSession = getSession(ex);
if (optSession.isEmpty()) return sendEmptyResponse(HTTP_UNAUTHORIZED, ex);
// post-login paths
var session = optSession.get();
switch (path) {
case "/delete":
return deleteUser(ex, session);
}
return badRequest(ex, "%s not found".formatted(path));
}
private boolean deleteUser(HttpExchange ex, Session session) throws IOException {
var json = json(ex);
if (!json.has(USER_ID)) return badRequest(ex, "missing_user_id");
var uuid = json.getString(USER_ID);
if (uuid == null || uuid.isBlank()) return badRequest(ex, "missing_user_id");
if (session.user().uuid().equals(uuid)) return badRequest(ex, "must_not_delete_self");
if (!json.has(CONFIRMED) || !json.getBoolean(CONFIRMED)) return badRequest(ex, "missing_confirmation");
Optional<User> targetUser = users.load(uuid);
if (targetUser.isEmpty()) return badRequest(ex, "unknown_user");
users.delete(targetUser.get());
return sendEmptyResponse(HTTP_OK, ex);
}
@Override @Override
public boolean doGet(String path, HttpExchange ex) throws IOException { public boolean doGet(String path, HttpExchange ex) throws IOException {
switch (path) { switch (path) {

4
de.srsoftware.oidc.datastore.file/src/main/java/de/srsoftware/oidc/datastore/file/FileStore.java

@ -76,7 +76,9 @@ public class FileStore implements AuthorizationService, ClientService, SessionSe
@Override @Override
public UserService delete(User user) { public UserService delete(User user) {
return null; var users = json.getJSONObject(USERS);
users.remove(user.uuid());
return save();
} }
@Override @Override

13
de.srsoftware.oidc.web/src/main/resources/en/scripts/common.js

@ -22,7 +22,15 @@ function getValue(id){
} }
function hide(id){ function hide(id){
get(id).style.display = 'none'; var elem = get(id);
if (elem) elem.style.display = 'none';
}
function hideAll(clazz){
var elems = document.getElementsByTagName('*'), i;
for (i in elems) {
if((' ' + elems[i].className + ' ').indexOf(' ' + clazz + ' ') > -1) elems[i].style.display = 'none';
}
} }
function isChecked(id){ function isChecked(id){
@ -48,5 +56,6 @@ function setValue(id,newVal){
} }
function show(id){ function show(id){
get(id).style.display = ''; var elem = get(id);
if (elem) elem.style.display = '';
} }

31
de.srsoftware.oidc.web/src/main/resources/en/scripts/users.js

@ -29,29 +29,42 @@ async function handleUsers(response){
var bottom = document.getElementById('bottom'); var bottom = document.getElementById('bottom');
for (let id in users){ for (let id in users){
var row = document.createElement("tr"); var row = document.createElement("tr");
var user = users[id]; var u = users[id];
row.innerHTML = `<td>${user.username}</td> row.innerHTML = `<td>${u.username}</td>
<td>${user.realname}</td> <td>${u.realname}</td>
<td>${user.email}</td> <td>${u.email}</td>
<td>${id}</td> <td>${id}</td>
<td> <td>
<button type="button" onclick="reset_password('${id}')" id="reset-${id}">Reset password</button> <button type="button" onclick="reset_password('${id}')" id="reset-${id}">Reset password</button>
<button class="danger" onclick="remove('${id}')" type="button">Remove</button> <button id="remove-${u.uuid}" class="danger" onclick="remove('${id}','${u.realname}')" type="button">Remove</button>
</td>`; </td>`;
bottom.parentNode.insertBefore(row,bottom); bottom.parentNode.insertBefore(row,bottom);
} }
} }
function handleRemove(response){ async function handleRemove(response){
if (response.ok){
redirect("users.html"); redirect("users.html");
} else {
var info = await response.text();
console.log(info);
show(info);
}
} }
function remove(userId){ function remove(userId,name){
disable(`remove-${userId}`);
if (userId == user.uuid) {
//return;
}
setText(`remove-${userId}`,"sent…");
hideAll('error');
var message = document.getElementById('message').innerHTML; var message = document.getElementById('message').innerHTML;
if (confirm(message.replace("{}",userId))) { if (confirm(message.replace("{}",name))) {
fetch(user_controller+"/delete",{ fetch(user_controller+"/delete",{
method: 'DELETE', method: 'DELETE',
body : JSON.stringify({ userId : userId }) body : JSON.stringify({ user_id : userId, confirmed : true })
}).then(handleRemove); }).then(handleRemove);
} }
} }

1
de.srsoftware.oidc.web/src/main/resources/en/todo.html

@ -12,7 +12,6 @@
<div id="content"> <div id="content">
<h1>to do…</h1> <h1>to do…</h1>
<ul> <ul>
<li><a href="users.html">Users: remove</a></li>
<li><a href="login.html">Login: "remember me" option</a></li> <li><a href="login.html">Login: "remember me" option</a></li>
<li>at_hash in ID Token</li> <li>at_hash in ID Token</li>
<li>drop outdated sessions</li> <li>drop outdated sessions</li>

5
de.srsoftware.oidc.web/src/main/resources/en/users.html

@ -41,7 +41,10 @@
</tr> </tr>
</table> </table>
<span class="error" style="display: none" id="pw-mismatch">Passwords do not match!</span> <span class="hidden" id="message">Really remove client "{}"?</span>
<span class="error" style="display: none" id="missing_user_id">Server did not receive a valid user_id for removal!</span>
<span class="error" style="display: none" id="missing_confirmation">Server did not receive confirmation for this request!</span>
<span class="error" style="display: none" id="unknown_user">The backend does not know this user!</span>
</fieldset> </fieldset>
</div> </div>
</body> </body>

Loading…
Cancel
Save