working on edit client
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
@@ -1,7 +1,13 @@
|
||||
/* © SRSoftware 2024 */
|
||||
package de.srsoftware.oidc.api;
|
||||
|
||||
import static de.srsoftware.oidc.api.Constants.*;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public record Client(String id, String name, String secret, Set<String> redirectUris) {
|
||||
public Map<String, Object> map() {
|
||||
return Map.of(CLIENT_ID, id, NAME, name, SECRET, secret, REDIRECT_URIS, redirectUris);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
package de.srsoftware.oidc.api;
|
||||
|
||||
public class Constants {
|
||||
public static final String CLIENT_ID = "client_id";
|
||||
public static final String NAME = "name";
|
||||
public static final String REDIRECT_URI = "redirect_uri";
|
||||
public static final String SECRET = "secret";
|
||||
public static final String CLIENT_ID = "client_id";
|
||||
public static final String NAME = "name";
|
||||
public static final String REDIRECT_URI = "redirect_uri";
|
||||
public static final String REDIRECT_URIS = "redirect_uris";
|
||||
public static final String SECRET = "secret";
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public class Backend extends PathHandler {
|
||||
if (!session.user().hasPermission(MANAGE_CLIENTS)) return sendError(ex, "NOT ALLOWED");
|
||||
var json = json(ex);
|
||||
var redirects = new HashSet<String>();
|
||||
for (Object o : json.getJSONArray(REDIRECT_URI)) {
|
||||
for (Object o : json.getJSONArray(REDIRECT_URIS)) {
|
||||
if (o instanceof String s) redirects.add(s);
|
||||
}
|
||||
var client = new Client(json.getString(CLIENT_ID), json.getString(NAME), json.getString(SECRET), redirects);
|
||||
@@ -128,6 +128,8 @@ public class Backend extends PathHandler {
|
||||
return addClient(ex, session);
|
||||
case "/authorize":
|
||||
return authorize(ex, session);
|
||||
case "/client":
|
||||
return loadClient(ex, session);
|
||||
case "/clients":
|
||||
return clients(ex, session);
|
||||
case "/update/password":
|
||||
@@ -145,6 +147,17 @@ public class Backend extends PathHandler {
|
||||
return SessionToken.from(ex).map(SessionToken::sessionId).flatMap(sessions::retrieve);
|
||||
}
|
||||
|
||||
private boolean loadClient(HttpExchange ex, Session session) throws IOException {
|
||||
if (!session.user().hasPermission(MANAGE_CLIENTS)) return sendEmptyResponse(HTTP_FORBIDDEN, ex);
|
||||
var json = json(ex);
|
||||
if (json.has(CLIENT_ID)) {
|
||||
var clientID = json.getString(CLIENT_ID);
|
||||
var client = clients.getClient(clientID).map(Client::map).map(JSONObject::new);
|
||||
if (client.isPresent()) return sendContent(ex, client.get());
|
||||
}
|
||||
return sendEmptyResponse(HTTP_NOT_FOUND, ex);
|
||||
}
|
||||
|
||||
private boolean logout(HttpExchange ex, Session session) throws IOException {
|
||||
sessions.dropSession(session.id());
|
||||
new SessionToken("").addTo(ex);
|
||||
|
||||
@@ -12,24 +12,25 @@
|
||||
<a id="clients" href="clients.html">Clients</a>
|
||||
</nav>
|
||||
<h1>Clients</h1>
|
||||
|
||||
These are clients that are registered with LightOIDC:
|
||||
<table>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th>ID</th>
|
||||
<th>Redirect URLs</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
<tr id="bottom">
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
<button onclick="window.location.href='newclient.html';">Add new client…</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<span class="hidden" id="message">Really remove client "{}"?</span>
|
||||
<fieldset>
|
||||
<legend>These are clients that are registered with LightOIDC:</legend>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th>ID</th>
|
||||
<th>Redirect URLs</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
<tr id="bottom">
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
<button onclick="window.location.href='newclient.html';">Add new client…</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<span class="hidden" id="message">Really remove client "{}"?</span>
|
||||
</fieldset>
|
||||
</body>
|
||||
</html>
|
||||
@@ -8,7 +8,7 @@ async function handleClients(response){
|
||||
for (let id in clients){
|
||||
var row = document.createElement("tr");
|
||||
var client = clients[id];
|
||||
row.innerHTML = "<td>"+client.name+"</td>\n<td>"+id+"</td>\n<td>"+client.redirect_uris.join("<br/>")+'</td>\n<td><button onclick="remove(\''+id+'\')" type="button">remove '+client.name+'</button></td>';
|
||||
row.innerHTML = "<td>"+client.name+"</td>\n<td>"+id+"</td>\n<td>"+client.redirect_uris.join("<br/>")+'</td>\n<td><button onclick="remove(\''+id+'\')" type="button">remove '+client.name+'</button><button type="button" onclick="edit(\''+id+'\')">Edit</button></td>';
|
||||
bottom.parentNode.insertBefore(row,bottom);
|
||||
}
|
||||
}
|
||||
@@ -27,4 +27,8 @@ function remove(clientId){
|
||||
}
|
||||
}
|
||||
|
||||
function edit(clientId){
|
||||
redirect("edit_client.html?id="+clientId);
|
||||
}
|
||||
|
||||
fetch(api+"/clients",{method:'POST'}).then(handleClients);
|
||||
@@ -19,6 +19,11 @@ function getValue(id){
|
||||
return get(id).value;
|
||||
}
|
||||
|
||||
function hide(id){
|
||||
console.log('hide('+id+')');
|
||||
get(id).style.display = 'none';
|
||||
}
|
||||
|
||||
function redirect(page){
|
||||
window.location.href = page;
|
||||
}
|
||||
@@ -29,6 +34,10 @@ function setText(id, text){
|
||||
|
||||
|
||||
function setValue(id,newVal){
|
||||
document.getElementById(id).value = newVal;
|
||||
get(id).value = newVal;
|
||||
}
|
||||
|
||||
function show(id){
|
||||
console.log('show('+id+')');
|
||||
get(id).style.display = '';
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Light OIDC</title>
|
||||
<script src="common.js"></script>
|
||||
<script src="user.js"></script>
|
||||
<script src="edit_client.js"></script>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<nav></nav>
|
||||
<h1>Edit client</h1>
|
||||
<fieldset>
|
||||
<legend>Data</legend>
|
||||
<table>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<td><input type="text" disabled="true" id="client_id" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<td><input type="text" id="name" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Secret</th>
|
||||
<td><input type="text" id="secret" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Redirect URIs</th>
|
||||
<td>
|
||||
<textarea id="redirects"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><button type="button" id="button">Update</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
</body>
|
||||
</html>
|
||||
20
de.srsoftware.oidc.web/src/main/resources/en/edit_client.js
Normal file
20
de.srsoftware.oidc.web/src/main/resources/en/edit_client.js
Normal file
@@ -0,0 +1,20 @@
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var id = params.get('id');
|
||||
|
||||
fetch(api+'/client',
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
client_id : id
|
||||
})
|
||||
}).then(handleResponse);
|
||||
|
||||
async function handleResponse(response){
|
||||
if (response.ok){
|
||||
var json = await response.json();
|
||||
get('client_id').value = json.client_id;
|
||||
get('name').value = json.name;
|
||||
get('secret').value = json.secret;
|
||||
get('redirects').value = json.redirect_uris.join("\n");
|
||||
}
|
||||
}
|
||||
@@ -10,16 +10,24 @@
|
||||
<h1>Login</h1>
|
||||
<fieldset id="login">
|
||||
<legend>User credentials</legend>
|
||||
<label>
|
||||
Username
|
||||
<input type="text" id="username" />
|
||||
</label>
|
||||
<label>
|
||||
Password
|
||||
<input type="password" id="password" onkeydown="keyDown()"/>
|
||||
</label>
|
||||
<button type="button" onClick="tryLogin()">Login</button>
|
||||
<table>
|
||||
<tr>
|
||||
<th>User name</th>
|
||||
<td><input type="text" id="username" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Password</th>
|
||||
<td><input type="password" id="password" onkeydown="keyDown()"/></td>
|
||||
</tr>
|
||||
<tr id="error" style="display: none">
|
||||
<th>Error</th>
|
||||
<td class="warning">Failed to log in!</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><button type="button" onClick="tryLogin()">Login</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
<div id="error"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,10 +1,11 @@
|
||||
async function handleLogin(response){
|
||||
if (response.ok){
|
||||
var body = await response.json();
|
||||
|
||||
hide('error');
|
||||
setTimeout(doRedirect,100);
|
||||
} else {
|
||||
show('error');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function doRedirect(){
|
||||
@@ -14,7 +15,6 @@ function doRedirect(){
|
||||
}
|
||||
|
||||
function tryLogin(){
|
||||
document.getElementById("error").innerHTML = "";
|
||||
var username = getValue('username');
|
||||
var password = getValue('password');
|
||||
fetch(api+"/login",{
|
||||
|
||||
@@ -29,8 +29,11 @@
|
||||
<th>redirect urls</th>
|
||||
<td><textarea cols="50" rows="5" id="redirect-urls"></textarea></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><button id="button" type="button" onclick="addClient()">Add client</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
<button id="button" type="button" onclick="addClient()">Add client</button>
|
||||
</fieldset>
|
||||
</body>
|
||||
</html>
|
||||
@@ -4,7 +4,7 @@ function addClient(){
|
||||
client_id : getValue('client-id'),
|
||||
name : getValue('client-name'),
|
||||
secret : getValue('client-secret'),
|
||||
redirect_uri : getValue('redirect-urls').split("\n")
|
||||
redirect_uris : getValue('redirect-urls').split("\n")
|
||||
};
|
||||
fetch(api+'/add/client',{
|
||||
method : 'POST',
|
||||
|
||||
@@ -28,8 +28,15 @@
|
||||
<th>ID</th>
|
||||
<td><input id="uuid" type="text" disabled="true"></td>
|
||||
</tr>
|
||||
<tr id="update_error" style="display: none">
|
||||
<th>Error</th>
|
||||
<td class="warning">Failed to update settings!</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><button id="updateBtn" type="button" onClick="update()">Update</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
<button id="updateBtn" type="button" onClick="update()">Update</button>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>
|
||||
@@ -48,8 +55,19 @@
|
||||
<th>Repeat Password</th>
|
||||
<td><input id="newpass2" type="password" onkeydown="passKeyDown()"></td>
|
||||
</tr>
|
||||
<tr id="wrong_password" style="display: none">
|
||||
<th>Error</th>
|
||||
<td class="warning">Wrong password!</td>
|
||||
</tr>
|
||||
<tr id="password_mismatch" style="display: none">
|
||||
<th>Error</th>
|
||||
<td class="warning">Mismatch between new password and repetition!</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><button id="passBtn" type="button" onClick="updatePass()">Update</button></td>
|
||||
</tr>
|
||||
</table>
|
||||
<button id="passBtn" type="button" onClick="updatePass()">Update</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
</body>
|
||||
|
||||
@@ -11,18 +11,16 @@ function fillForm(){
|
||||
|
||||
|
||||
function handleResponse(response){
|
||||
setText('updateBtn',response.ok ? 'saved.' : 'failed!');
|
||||
if (response.ok){
|
||||
hide('update_error')
|
||||
setText('updateBtn', 'saved.');
|
||||
} else {
|
||||
show('update_error');
|
||||
setText('updateBtn', 'Update failed!');
|
||||
}
|
||||
enable('updateBtn');
|
||||
setTimeout(function(){
|
||||
setText('updateBtn','Update');
|
||||
enable('updateBtn');
|
||||
},10000);
|
||||
}
|
||||
|
||||
function handlePasswordResponse(response){
|
||||
setText('passBtn',response.ok ? 'saved.' : 'failed!');
|
||||
setTimeout(function(){
|
||||
setText('passBtn','Update');
|
||||
enable('passBtn');
|
||||
},10000);
|
||||
}
|
||||
|
||||
@@ -43,6 +41,26 @@ function update(){
|
||||
setText('updateBtn','sent…');
|
||||
}
|
||||
|
||||
|
||||
async function handlePasswordResponse(response){
|
||||
if (response.ok){
|
||||
hide('wrong_password');
|
||||
hide('password_mismatch');
|
||||
setText('passBtn', 'saved.');
|
||||
} else {
|
||||
setText('passBtn', 'Update failed!');
|
||||
var text = await response.text();
|
||||
if (text == 'wrong password') show('wrong_password');
|
||||
if (text == 'password mismatch') show('password_mismatch');
|
||||
|
||||
}
|
||||
enable('passBtn');
|
||||
setTimeout(function(){
|
||||
setText('passBtn','Update');
|
||||
},10000);
|
||||
}
|
||||
|
||||
|
||||
function updatePass(){
|
||||
disable('passBtn');
|
||||
var newData = {
|
||||
@@ -58,10 +76,6 @@ function updatePass(){
|
||||
body : JSON.stringify(newData)
|
||||
}).then(handlePasswordResponse);
|
||||
setText('passBtn','sent…');
|
||||
setTimeout(function(){
|
||||
setText('passBtn','Update');
|
||||
enable('passBtn');
|
||||
},10000);
|
||||
}
|
||||
|
||||
function passKeyDown(ev){
|
||||
|
||||
@@ -5,12 +5,22 @@ body {
|
||||
|
||||
body fieldset {
|
||||
border-radius: 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
a {
|
||||
color: yellow;
|
||||
}
|
||||
|
||||
input, textarea{
|
||||
width: 600px;
|
||||
}
|
||||
|
||||
input:disabled{
|
||||
color: white;
|
||||
background-color: gray;
|
||||
}
|
||||
|
||||
fieldset th,
|
||||
form th{
|
||||
text-align: right;
|
||||
@@ -18,4 +28,8 @@ form th{
|
||||
|
||||
.hidden{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.warning{
|
||||
color: yellow;
|
||||
}
|
||||
Reference in New Issue
Block a user