mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2025-04-08 19:56:39 +00:00
fix users list page, add manage roles page
This commit is contained in:
parent
887025bfd7
commit
316aa018b1
@ -34,8 +34,6 @@ GET /admin/users
|
||||
last_login: user.last_login ? new Date(user.last_login).toISOString() : ''
|
||||
}));
|
||||
|
||||
console.log("Processed userList =>", userList);
|
||||
|
||||
response.writeHead(200, "OK", {
|
||||
"Content-Type": "text/html"
|
||||
});
|
||||
@ -45,10 +43,12 @@ GET /admin/users
|
||||
variables: {
|
||||
"page-content": "$:/plugins/tiddlywiki/multiwikiserver/templates/get-users",
|
||||
"user-list": JSON.stringify(userList),
|
||||
"username": state.authenticatedUser ? state.authenticatedUser.username : "Guest",
|
||||
"user-is-admin": state.authenticatedUser && state.authenticatedUser.isAdmin ? "yes" : "no"
|
||||
}
|
||||
});
|
||||
response.write(html);
|
||||
response.end();
|
||||
};
|
||||
|
||||
}());
|
||||
}());
|
@ -0,0 +1,36 @@
|
||||
/*\
|
||||
title: $:/plugins/tiddlywiki/multiwikiserver/routes/handlers/manage-roles.js
|
||||
type: application/javascript
|
||||
module-type: mws-route
|
||||
|
||||
GET /admin/roles
|
||||
|
||||
\*/
|
||||
(function() {
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.method = "GET";
|
||||
|
||||
exports.path = /^\/admin\/roles\/?$/;
|
||||
|
||||
exports.handler = function(request, response, state) {
|
||||
var roles = state.server.sqlTiddlerDatabase.listRoles();
|
||||
|
||||
response.writeHead(200, "OK", {"Content-Type": "text/html"});
|
||||
|
||||
var html = $tw.mws.store.adminWiki.renderTiddler("text/plain", "$:/plugins/tiddlywiki/multiwikiserver/templates/page", {
|
||||
variables: {
|
||||
"page-content": "$:/plugins/tiddlywiki/multiwikiserver/templates/manage-roles",
|
||||
"roles-list": JSON.stringify(roles),
|
||||
"username": state.authenticatedUser ? state.authenticatedUser.username : "Guest",
|
||||
"user-is-admin": state.authenticatedUser && state.authenticatedUser.isAdmin ? "yes" : "no"
|
||||
}
|
||||
});
|
||||
response.write(html);
|
||||
response.end();
|
||||
};
|
||||
|
||||
}());
|
@ -0,0 +1,70 @@
|
||||
/*\
|
||||
title: $:/plugins/tiddlywiki/multiwikiserver/routes/handlers/manage-user.js
|
||||
type: application/javascript
|
||||
module-type: mws-route
|
||||
|
||||
GET /admin/users/:user_id
|
||||
|
||||
\*/
|
||||
(function() {
|
||||
|
||||
/*jslint node: true, browser: true */
|
||||
/*global $tw: false */
|
||||
"use strict";
|
||||
|
||||
exports.method = "GET";
|
||||
|
||||
exports.path = /^\/admin\/users\/([^\/]+)\/?$/;
|
||||
|
||||
|
||||
exports.handler = function(request,response,state) {
|
||||
var user_id = $tw.utils.decodeURIComponentSafe(state.params[0]);
|
||||
console.log("user_id =>", user_id)
|
||||
|
||||
var userData = state.server.sqlTiddlerDatabase.getUser(user_id);
|
||||
|
||||
if(!userData) {
|
||||
response.writeHead(404, "Not Found", {"Content-Type": "text/html"});
|
||||
var errorHtml = $tw.mws.store.adminWiki.renderTiddler("text/plain", "$:/plugins/tiddlywiki/multiwikiserver/templates/error", {
|
||||
variables: {
|
||||
"error-message": "User not found"
|
||||
}
|
||||
});
|
||||
response.write(errorHtml);
|
||||
response.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert dates to strings and ensure all necessary fields are present
|
||||
const user = {
|
||||
user_id: userData.user_id || '',
|
||||
username: userData.username || '',
|
||||
email: userData.email || '',
|
||||
created_at: userData.created_at ? new Date(userData.created_at).toISOString() : '',
|
||||
last_login: userData.last_login ? new Date(userData.last_login).toISOString() : ''
|
||||
};
|
||||
|
||||
// Get all roles which the user has been assigned
|
||||
var userRoles = state.server.sqlTiddlerDatabase.getUserRoles(user_id);
|
||||
var allRoles = state.server.sqlTiddlerDatabase.listRoles();
|
||||
|
||||
response.writeHead(200, "OK", {
|
||||
"Content-Type": "text/html"
|
||||
});
|
||||
|
||||
// Render the html
|
||||
var html = $tw.mws.store.adminWiki.renderTiddler("text/plain", "$:/plugins/tiddlywiki/multiwikiserver/templates/page", {
|
||||
variables: {
|
||||
"page-content": "$:/plugins/tiddlywiki/multiwikiserver/templates/manage-user",
|
||||
"user": JSON.stringify(user),
|
||||
"user-roles": JSON.stringify(userRoles),
|
||||
"all-roles": JSON.stringify(allRoles),
|
||||
"username": state.authenticatedUser ? state.authenticatedUser.username : "Guest",
|
||||
"user-is-admin": state.authenticatedUser && state.authenticatedUser.isAdmin ? "yes" : "no"
|
||||
}
|
||||
});
|
||||
response.write(html);
|
||||
response.end();
|
||||
};
|
||||
|
||||
}());
|
@ -1156,6 +1156,17 @@ SqlTiddlerDatabase.prototype.removePermissionFromRole = function(roleId, permiss
|
||||
});
|
||||
};
|
||||
|
||||
SqlTiddlerDatabase.prototype.getUserRoles = function(userId) {
|
||||
const query = `
|
||||
SELECT r.role_id, r.role_name
|
||||
FROM user_roles ur
|
||||
JOIN roles r ON ur.role_id = r.role_id
|
||||
WHERE ur.user_id = $userId
|
||||
`;
|
||||
|
||||
return this.engine.runStatementGetAll(query, { $userId: userId });
|
||||
};
|
||||
|
||||
exports.SqlTiddlerDatabase = SqlTiddlerDatabase;
|
||||
|
||||
})();
|
@ -0,0 +1,40 @@
|
||||
title: $:/plugins/tiddlywiki/multiwikiserver/templates/add-user-modal
|
||||
|
||||
\define add-user-actions()
|
||||
<$action-sendmessage $message="tm-server-request"
|
||||
method="POST"
|
||||
url="/admin/users"
|
||||
headers="Content-Type: application/json"
|
||||
body={{{ [{"username": "$(newUsername)$", "email": "$(newEmail)$", "password": "$(newPassword)$"}jsonify[]] }}}
|
||||
redirectAfterSuccess="/admin/users"/>
|
||||
<$action-deletetiddler $tiddler="$:/temp/newUsername"/>
|
||||
<$action-deletetiddler $tiddler="$:/temp/newEmail"/>
|
||||
<$action-deletetiddler $tiddler="$:/temp/newPassword"/>
|
||||
\end
|
||||
|
||||
<h1>Add New User</h1>
|
||||
|
||||
<div>
|
||||
<label>Username:
|
||||
<$edit-text tiddler="$:/temp/newUsername" tag="input" default=""/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>Email:
|
||||
<$edit-text tiddler="$:/temp/newEmail" tag="input" default=""/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>Password:
|
||||
<$edit-text tiddler="$:/temp/newPassword" tag="input" type="password" default=""/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<$button class="tc-btn-big-green">
|
||||
Add User
|
||||
<<add-user-actions>>
|
||||
<$action-sendmessage $message="tm-close-tiddler"/>
|
||||
</$button>
|
||||
<$button class="tc-btn-invisible" message="tm-close-tiddler">
|
||||
Cancel
|
||||
</$button>
|
@ -0,0 +1,27 @@
|
||||
title: $:/plugins/tiddlywiki/multiwikiserver/templates/edit-role-modal
|
||||
|
||||
\define save-role-actions()
|
||||
<<edit-role-actions {{!!role-id}}>>
|
||||
\end
|
||||
|
||||
<h1>Edit Role</h1>
|
||||
|
||||
<div>
|
||||
<label>Role Name:
|
||||
<$edit-text tiddler="$:/temp/editRoleName" tag="input" default=""/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>Role Description:
|
||||
<$edit-text tiddler="$:/temp/editRoleDescription" tag="input" default=""/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<$button class="tc-btn-invisible">
|
||||
Save Changes
|
||||
<<save-role-actions>>
|
||||
<$action-sendmessage $message="tm-close-tiddler"/>
|
||||
</$button>
|
||||
<$button class="tc-btn-invisible" message="tm-close-tiddler">
|
||||
Cancel
|
||||
</$button>
|
@ -0,0 +1,32 @@
|
||||
title: $:/plugins/tiddlywiki/multiwikiserver/templates/edit-user-modal
|
||||
|
||||
\define edit-user-actions()
|
||||
<$action-sendmessage $message="tm-server-request"
|
||||
method="PUT"
|
||||
url={{{ [[$:/admin/users/]addsuffix{!!user-id}] }}}
|
||||
headers="Content-Type: application/json"
|
||||
body={{{ [{"username": "$(editUsername)$", "email": "$(editEmail)$"}jsonify[]] }}}
|
||||
redirectAfterSuccess="/admin/users"/>
|
||||
\end
|
||||
|
||||
<h1>Edit User</h1>
|
||||
|
||||
<div>
|
||||
<label>Username:
|
||||
<$edit-text tiddler="$:/temp/editUsername" tag="input" default=""/>
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>Email:
|
||||
<$edit-text tiddler="$:/temp/editEmail" tag="input" default=""/>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<$button class="tc-btn-big-green">
|
||||
Save Changes
|
||||
<<edit-user-actions>>
|
||||
<$action-sendmessage $message="tm-close-tiddler"/>
|
||||
</$button>
|
||||
<$button class="tc-btn-invisible" message="tm-close-tiddler">
|
||||
Cancel
|
||||
</$button>
|
@ -21,26 +21,11 @@ title: $:/plugins/tiddlywiki/multiwikiserver/templates/get-index
|
||||
</$genesis>
|
||||
\end
|
||||
|
||||
<div class="mws-header">
|
||||
<h1>Wikis Available Here</h1>
|
||||
<div class="mws-user-info">
|
||||
<span>Hello, <$text text=<<username>>/></span>
|
||||
<$list filter="[<user-is-admin>match[yes]]">
|
||||
<div class="mws-admin-dropdown">
|
||||
<button class="mws-admin-dropbtn">⚙️</button>
|
||||
<div class="mws-admin-dropdown-content">
|
||||
<a href="/admin/acl">Manage ACL</a>
|
||||
<a href="/admin/users">Manage Users</a>
|
||||
<a href="/admin/permissions">Manage Permissions</a>
|
||||
<a href="/admin/roles">Manage Roles</a>
|
||||
</div>
|
||||
</div>
|
||||
</$list>
|
||||
<form action="/logout" method="post" class="mws-logout-form">
|
||||
<input type="submit" value="Logout" class="mws-logout-button"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<$tiddler tiddler="$:/plugins/tiddlywiki/multiwikiserver/templates/mws-header">
|
||||
<$set name="page-title" value="Wikis Available Here">
|
||||
<$transclude/>
|
||||
</$set>
|
||||
</$tiddler>
|
||||
|
||||
<ul class="mws-vertical-list">
|
||||
<$list filter="[<recipe-list>jsonindexes[]] :sort[<currentTiddler>jsonget[recipe_name]]" variable="recipe-index">
|
||||
@ -88,7 +73,6 @@ title: $:/plugins/tiddlywiki/multiwikiserver/templates/get-index
|
||||
</li>
|
||||
</$list>
|
||||
</ul>
|
||||
|
||||
<form action="/recipes" method="post" class="mws-form">
|
||||
<div class="mws-form-heading">
|
||||
Create a new recipe or modify and existing one
|
||||
|
@ -1,89 +1,113 @@
|
||||
<!--
|
||||
title: $:/plugins/tiddlywiki/multiwikiserver/templates/get-users
|
||||
-->
|
||||
|
||||
\define lingo-base() $:/language/ControlPanel/Tools/
|
||||
\define edit-user-actions(user-id)
|
||||
<$action-sendmessage $message="tm-modal" $param="$:/plugins/tiddlywiki/multiwikiserver/templates/edit-user-modal" user-id=<<user-id>>/>
|
||||
\end
|
||||
|
||||
<h1>User Management</h1>
|
||||
\define delete-user-actions(user-id)
|
||||
<$action-sendmessage $message="tm-server-request"
|
||||
method="DELETE"
|
||||
url={{{ [[$:/admin/users/]addsuffix<user-id>] }}}
|
||||
redirectAfterSuccess="/admin/users"/>
|
||||
\end
|
||||
|
||||
<!-- Display raw user-list for debugging -->
|
||||
<h2>Debug Info</h2>
|
||||
<p><strong>Raw user list JSON:</strong> <$text text=<<user-list>>/></p>
|
||||
<$tiddler tiddler="$:/plugins/tiddlywiki/multiwikiserver/templates/mws-header">
|
||||
<$set name="page-title" value="User Management">
|
||||
<$transclude/>
|
||||
</$set>
|
||||
</$tiddler>
|
||||
|
||||
<!-- Attempt to parse the user-list JSON -->
|
||||
<$set name="userList" value=<<user-list>>>
|
||||
<!-- Display a message if the userList is empty -->
|
||||
<$list filter="[<userList>!is[blank]]" emptyMessage="The user list is empty or not provided.">
|
||||
<p><strong>User list found:</strong> <$text text=<<userList>>/></p>
|
||||
|
||||
<!-- Attempt to parse the user list -->
|
||||
<$set name="parsedUserList" value={{{ [<userList>jsonparse[]] }}}/>
|
||||
|
||||
<!-- Check if parsedUserList has any entries -->
|
||||
<$list filter="[<parsedUserList>count[]compare:number:gt[0]]" emptyMessage="No users found or failed to parse user data">
|
||||
<!-- Display parsed user list for debugging -->
|
||||
<p><strong>Parsed User List (as JSON):</strong> <$text text={{{ [<parsedUserList>jsonstringify[]] }}}/></p>
|
||||
|
||||
<!-- Display total user count -->
|
||||
<p><strong>Total users:</strong> <$text text={{{ [<parsedUserList>count[]] }}}/></p>
|
||||
|
||||
<!-- Render the user table if parsing was successful -->
|
||||
<table class="tc-view-field-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Username</th>
|
||||
<th>Email</th>
|
||||
<th>Created At</th>
|
||||
<th>Last Login</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<$list filter="[<userList>jsonindexes[]]" variable="userIndex">
|
||||
<$let currentUser={{{ [<userList>jsonget<userIndex>] }}}>
|
||||
<tr>
|
||||
<td><$text text={{{ [<currentUser>jsonget[username]] }}}/></td>
|
||||
<td><$text text={{{ [<currentUser>jsonget[email]] }}}/></td>
|
||||
<td><$text text={{{ [<currentUser>jsonget[created_at]] }}}/></td>
|
||||
<td><$text text={{{ [<currentUser>jsonget[last_login]] }}}/></td>
|
||||
<td>
|
||||
<$button message="tm-server-command" param="edit-user" user_id={{{ [<currentUser>jsonget[user_id]] }}} class="tc-btn-invisible">
|
||||
{{$:/core/images/edit-button}} Edit
|
||||
</$button>
|
||||
<$button message="tm-server-command" param="delete-user" user_id={{{ [<currentUser>jsonget[user_id]] }}} class="tc-btn-invisible">
|
||||
{{$:/core/images/delete-button}} Delete
|
||||
</$button>
|
||||
</td>
|
||||
</tr>
|
||||
</$let>
|
||||
</$list>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="users-container">
|
||||
<div class="users-list">
|
||||
<$list filter="[<user-list>jsonindexes[]]" variable="user-index">
|
||||
<$let currentUser={{{ [<user-list>jsonextract<user-index>] }}}>
|
||||
<$set name="user-id" value={{{ [<currentUser>jsonget[user_id]] }}}>
|
||||
<a href={{{ [[/admin/users/]addsuffix<user-id>] }}} class="user-item">
|
||||
<div class="user-info">
|
||||
<span class="user-name">
|
||||
<$text text={{{ [<currentUser>jsonget[username]] }}}/>
|
||||
</span>
|
||||
<span class="user-email">
|
||||
<$text text={{{ [<currentUser>jsonget[email]] }}}/>
|
||||
</span>
|
||||
</div>
|
||||
<div class="user-details">
|
||||
<span class="user-created">
|
||||
Created: <$text text={{{ [<currentUser>jsonget[created_at]] }}}/>
|
||||
</span>
|
||||
<span class="user-last-login">
|
||||
Last Login: <$text text={{{ [<currentUser>jsonget[last_login]] }}}/>
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
</$set>
|
||||
</$let>
|
||||
</$list>
|
||||
</$list>
|
||||
</$set>
|
||||
|
||||
<$button message="tm-modal" param="$:/plugins/tiddlywiki/multiwikiserver/templates/add-user-modal" class="tc-btn-big-green">
|
||||
Add New User
|
||||
</$button>
|
||||
</div>
|
||||
|
||||
<div class="add-user-form">
|
||||
<$button class="tc-btn-big-green">
|
||||
Add New User
|
||||
<$action-sendmessage $message="tm-modal" $param="$:/plugins/tiddlywiki/multiwikiserver/templates/add-user-modal"/>
|
||||
</$button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.tc-view-field-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.tc-view-field-table th, .tc-view-field-table td {
|
||||
border: 1px solid <<colour table-border>>;
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
.tc-view-field-table th {
|
||||
background-color: <<colour table-header-background>>;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.tc-view-field-table tr:nth-child(even) {
|
||||
background-color: <<colour table-header-background>>;
|
||||
}
|
||||
.users-container {
|
||||
max-width: 800px;
|
||||
margin: 2rem auto;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
padding: 2rem;
|
||||
}
|
||||
.user-item {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
background: none;
|
||||
border: none;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding: 1rem 0;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
text-decoration: none;
|
||||
}
|
||||
.user-item:hover {
|
||||
background-color: #f5f5f5;
|
||||
text-decoration: none;
|
||||
}
|
||||
.user-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.user-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
.user-email {
|
||||
color: #666;
|
||||
}
|
||||
.user-details {
|
||||
font-size: 0.9em;
|
||||
color: #888;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.add-user-form {
|
||||
margin-top: 2rem;
|
||||
text-align: right;
|
||||
}
|
||||
.tc-btn-big-green {
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 1em;
|
||||
}
|
||||
.tc-btn-big-green:hover {
|
||||
background-color: #45a049;
|
||||
}
|
||||
</style>
|
||||
|
123
plugins/tiddlywiki/multiwikiserver/templates/manage-roles.tid
Normal file
123
plugins/tiddlywiki/multiwikiserver/templates/manage-roles.tid
Normal file
@ -0,0 +1,123 @@
|
||||
title: $:/plugins/tiddlywiki/multiwikiserver/templates/manage-roles
|
||||
|
||||
\define add-role-actions()
|
||||
<$action-sendmessage $message="tm-server-request"
|
||||
method="POST"
|
||||
url="/admin/roles"
|
||||
headers="Content-Type: application/json"
|
||||
body={{{ [{"name": "$(newRoleName)$", "description": "$(newRoleDescription)$"}jsonify[]] }}}
|
||||
redirectAfterSuccess="/admin/roles"/>
|
||||
<$action-setfield $tiddler="$:/temp/newRoleName" text=""/>
|
||||
<$action-setfield $tiddler="$:/temp/newRoleDescription" text=""/>
|
||||
\end
|
||||
|
||||
\define edit-role-actions(role-id)
|
||||
<$action-sendmessage $message="tm-server-request"
|
||||
method="PUT"
|
||||
url={{{ [[$:/admin/roles/]addsuffix<role-id>] }}}
|
||||
headers="Content-Type: application/json"
|
||||
body={{{ [{"name": "$(newRoleName)$", "description": "$(newRoleDescription)$"}jsonify[]] }}}
|
||||
redirectAfterSuccess="/admin/roles"/>
|
||||
\end
|
||||
|
||||
\define delete-role-actions(role-id)
|
||||
<$action-sendmessage $message="tm-server-request"
|
||||
method="DELETE"
|
||||
url={{{ [[$:/admin/roles/]addsuffix<role-id>] }}}
|
||||
redirectAfterSuccess="/admin/roles"/>
|
||||
\end
|
||||
|
||||
<$tiddler tiddler="$:/plugins/tiddlywiki/multiwikiserver/templates/mws-header">
|
||||
<$set name="page-title" value="Manage Roles">
|
||||
<$transclude/>
|
||||
</$set>
|
||||
</$tiddler>
|
||||
|
||||
<div class="roles-container">
|
||||
<div class="roles-list">
|
||||
<$list filter="[<roles-list>jsonindexes[]]" variable="role-index">
|
||||
<$let role={{{ [<roles-list>jsonextract<role-index>] }}}>
|
||||
<div class="role-item">
|
||||
<span class="role-name">
|
||||
<$text text={{{ [<role>jsonget[role_name]] }}}/>
|
||||
</span>
|
||||
<span class="role-description">
|
||||
<$text text={{{ [<role>jsonget[description]] }}}/>
|
||||
</span>
|
||||
<div class="role-actions">
|
||||
<$button class="tc-btn-invisible">
|
||||
Edit
|
||||
<$action-setfield $tiddler="$:/temp/editRoleName" text={{{ [<role>jsonget[role_name]] }}}/>
|
||||
<$action-setfield $tiddler="$:/temp/editRoleDescription" text={{{ [<role>jsonget[description]] }}}/>
|
||||
<$action-sendmessage $message="tm-modal" $param="$:/plugins/tiddlywiki/multiwikiserver/templates/edit-role-modal" role-id={{{ [<role>jsonget[role_id]] }}}/>
|
||||
</$button>
|
||||
<$button class="tc-btn-invisible">
|
||||
Delete
|
||||
<$action-confirm $message="Are you sure you want to delete this role?">
|
||||
<<delete-role-actions {{{ [<role>jsonget[role_id]] }}}>>
|
||||
</$action-confirm>
|
||||
</$button>
|
||||
</div>
|
||||
</div>
|
||||
</$let>
|
||||
</$list>
|
||||
</div>
|
||||
|
||||
<div class="add-role-form">
|
||||
<$edit-text tiddler="$:/temp/newRoleName" tag="input" default="" placeholder="Role Name"/>
|
||||
<$edit-text tiddler="$:/temp/newRoleDescription" tag="input" default="" placeholder="Role Description"/>
|
||||
<$button class="tc-btn-invisible">
|
||||
Add Role
|
||||
<<add-role-actions>>
|
||||
</$button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.roles-container {
|
||||
max-width: 800px;
|
||||
margin: 2rem auto;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
padding: 2rem;
|
||||
}
|
||||
.role-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1rem 0;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.role-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
.role-description {
|
||||
color: #666;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
.role-actions button {
|
||||
margin-left: 0.5rem;
|
||||
padding: 0.5rem 1rem;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.add-role-form {
|
||||
margin-top: 2rem;
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
}
|
||||
.add-role-form input {
|
||||
flex-grow: 1;
|
||||
padding: 0.5rem;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
.add-role-form button {
|
||||
padding: 0.5rem 1rem;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
198
plugins/tiddlywiki/multiwikiserver/templates/manage-user.tid
Normal file
198
plugins/tiddlywiki/multiwikiserver/templates/manage-user.tid
Normal file
@ -0,0 +1,198 @@
|
||||
title: $:/plugins/tiddlywiki/multiwikiserver/templates/manage-user
|
||||
|
||||
<$tiddler tiddler="$:/plugins/tiddlywiki/multiwikiserver/templates/mws-header">
|
||||
<$set name="page-title" value="User Profile">
|
||||
<$transclude/>
|
||||
</$set>
|
||||
</$tiddler>
|
||||
|
||||
<div class="user-profile-container">
|
||||
<div class="user-profile-header">
|
||||
<div class="user-profile-avatar">
|
||||
<$text text={{{ [<user>jsonget[username]substr[0,1]uppercase[]] }}}/>
|
||||
</div>
|
||||
<h1 class="user-profile-name"><$text text={{{ [<user>jsonget[username]] }}}/></h1>
|
||||
<p class="user-profile-email"><$text text={{{ [<user>jsonget[email]] }}}/></p>
|
||||
</div>
|
||||
|
||||
<div class="user-profile-details">
|
||||
<div class="user-profile-item">
|
||||
<span class="user-profile-label">User ID:</span>
|
||||
<span class="user-profile-value"><$text text={{{ [<user>jsonget[user_id]] }}}/></span>
|
||||
</div>
|
||||
<div class="user-profile-item">
|
||||
<span class="user-profile-label">Created At:</span>
|
||||
<span class="user-profile-value"><$text text={{{ [<user>jsonget[created_at]split[T]first[]] }}}/></span>
|
||||
</div>
|
||||
<div class="user-profile-item">
|
||||
<span class="user-profile-label">Last Login:</span>
|
||||
<span class="user-profile-value"><$text text={{{ [<user>jsonget[last_login]split[T]first[]] }}}/></span>
|
||||
</div>
|
||||
|
||||
<div class="user-profile-roles">
|
||||
<h2>User Roles</h2>
|
||||
<ul>
|
||||
<$list filter="[<user-roles>jsonindexes[]]" variable="role-index">
|
||||
<li>
|
||||
<$text text={{{ [<user-roles>jsonextract<role-index>jsonget[role_name]] }}}/>
|
||||
</li>
|
||||
</$list>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="user-actions">
|
||||
<$button class="tc-btn-invisible">
|
||||
{{$:/core/images/edit-button}} Edit
|
||||
<<edit-user-actions {{{ [<currentUser>jsonget[user_id]] }}}>>
|
||||
</$button>
|
||||
<$button class="tc-btn-invisible">
|
||||
{{$:/core/images/delete-button}} Delete
|
||||
<$action-confirm $message="Are you sure you want to delete this user?">
|
||||
<<delete-user-actions {{{ [<currentUser>jsonget[user_id]] }}}>>
|
||||
</$action-confirm>
|
||||
</$button>
|
||||
</div>
|
||||
<hr />
|
||||
<div class="user-profile-roles-management">
|
||||
<h2>Manage User Roles</h2>
|
||||
<select id="roleSelect">
|
||||
<option value="">Select a role to add</option>
|
||||
<$list filter="[<all-roles>jsonindexes[]]" variable="role-index">
|
||||
<$let role={{{ [<all-roles>jsonextract<role-index>] }}}>
|
||||
<option value={{{ [<role>jsonget[role_id]] }}}>
|
||||
<$text text={{{ [<role>jsonget[role_name]] }}}/>
|
||||
</option>
|
||||
</$let>
|
||||
</$list>
|
||||
</select>
|
||||
<button onclick="addRoleToUser()">Add Role</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function addRoleToUser() {
|
||||
const roleId = document.getElementById('roleSelect').value;
|
||||
if (roleId) {
|
||||
fetch('/admin/users/{{{ [<user>jsonget[user_id]] }}}/roles', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ role_id: roleId })
|
||||
}).then(() => location.reload());
|
||||
}
|
||||
}
|
||||
|
||||
function removeRoleFromUser(roleId) {
|
||||
if (confirm("Are you sure you want to remove this role from the user?")) {
|
||||
fetch('/admin/users/{{{ [<user>jsonget[user_id]] }}}/roles/' + roleId, {
|
||||
method: 'DELETE'
|
||||
}).then(() => location.reload());
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.user-profile-container {
|
||||
max-width: 600px;
|
||||
margin: 2rem auto;
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.user-profile-header {
|
||||
background: #3498db;
|
||||
color: #fff;
|
||||
padding: 2rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.user-profile-avatar {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 50%;
|
||||
margin: 0 auto 1rem;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 3rem;
|
||||
* {
|
||||
color: #3498db;
|
||||
}
|
||||
}
|
||||
|
||||
.user-profile-name {
|
||||
font-size: 1.5rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.user-profile-email {
|
||||
font-size: 1rem;
|
||||
opacity: 0.8;
|
||||
margin: 0.5rem 0 0;
|
||||
}
|
||||
|
||||
.user-profile-details {
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.user-profile-item {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.user-profile-label {
|
||||
font-weight: bold;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.user-profile-value {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.user-profile-roles {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.user-profile-roles h2 {
|
||||
font-size: 1.2rem;
|
||||
color: #3498db;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.user-profile-roles ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.user-profile-roles li {
|
||||
background: #f1f1f1;
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 20px;
|
||||
display: inline-block;
|
||||
margin-right: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.user-profile-roles-management {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.user-profile-roles-management select {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.user-actions {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
.user-actions button {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 0.25rem 0.5rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
</style>
|
96
plugins/tiddlywiki/multiwikiserver/templates/mws-header.tid
Normal file
96
plugins/tiddlywiki/multiwikiserver/templates/mws-header.tid
Normal file
@ -0,0 +1,96 @@
|
||||
title: $:/plugins/tiddlywiki/multiwikiserver/templates/mws-header
|
||||
|
||||
<div class="mws-header">
|
||||
<h1><$text text=<<page-title>>/></h1>
|
||||
<div class="mws-user-info">
|
||||
<span>Hello, <$text text=<<username>>/></span>
|
||||
<$list filter="[<user-is-admin>match[yes]]">
|
||||
<div class="mws-admin-dropdown">
|
||||
<button class="mws-admin-dropbtn">⚙️</button>
|
||||
<div class="mws-admin-dropdown-content">
|
||||
<a href="/admin/acl">Manage ACL</a>
|
||||
<a href="/admin/users">Manage Users</a>
|
||||
<a href="/admin/permissions">Manage Permissions</a>
|
||||
<a href="/admin/roles">Manage Roles</a>
|
||||
</div>
|
||||
</div>
|
||||
</$list>
|
||||
<form action="/logout" method="post" class="mws-logout-form">
|
||||
<input type="submit" value="Logout" class="mws-logout-button"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.mws-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px;
|
||||
background-color: #f0f0f0;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.mws-user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mws-logout-form {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.mws-logout-button {
|
||||
padding: 5px 10px;
|
||||
background-color: #f44336;
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mws-logout-button:hover {
|
||||
background-color: #d32f2f;
|
||||
}
|
||||
|
||||
.mws-admin-dropdown {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.mws-admin-dropbtn {
|
||||
color: white;
|
||||
padding: 5px;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mws-admin-dropbtn:hover, .mws-admin-dropbtn:focus {
|
||||
cursor: pointer;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.mws-admin-dropdown-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #f1f1f1;
|
||||
min-width: 160px;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
z-index: 1;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.mws-admin-dropdown-content a {
|
||||
color: black;
|
||||
padding: 12px 16px;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mws-admin-dropdown-content a:hover {background-color: #ddd;}
|
||||
|
||||
.mws-admin-dropdown:hover .mws-admin-dropdown-content {display: block;}
|
||||
|
||||
.mws-admin-dropdown:hover {background-color: #2980B9;}
|
||||
</style>
|
Loading…
x
Reference in New Issue
Block a user