Add ability to generate recovery links on admin user page for a user.

This commit is contained in:
Jennifer Taylor
2026-08-20 22:20:56 +00:00
parent 385ceb64bb
commit 9875294970
2 changed files with 53 additions and 0 deletions

View File

@@ -11,6 +11,7 @@ from bemani.common import (
ValidatedDict,
Profile,
ID,
format_recovery_link,
)
from bemani.data import Arcade, Machine, User, UserID, News, Event, Server, Client
from bemani.data.api.client import APIClient, NotAuthorizedAPIException, APIException
@@ -406,6 +407,7 @@ def viewuser(userid: int) -> Response:
},
{
"refresh": url_for("admin_pages.listuser", userid=userid),
"generaterecovery": url_for("admin_pages.generaterecovery", userid=userid),
"removeusercard": url_for("admin_pages.removeusercard", userid=userid),
"removeuserprofile": url_for("admin_pages.removeuserprofile", userid=userid),
"addusercard": url_for("admin_pages.addusercard", userid=userid),
@@ -1064,6 +1066,28 @@ def updatepassword(userid: int) -> Dict[str, Any]:
return {}
@admin_pages.route("/users/<int:userid>/password/recovery", methods=["POST"])
@jsonify
@adminrequired
def generaterecovery(userid: int) -> Dict[str, Any]:
# Cast the userID.
userid = UserID(userid)
user = g.data.local.user.get_user(userid)
# Make sure the user ID is valid
if user is None:
raise Exception("Cannot find user to generate recovery link for!")
# Generate a new recovery link.
token = g.data.local.user.create_recovery(userid)
url = format_recovery_link(g.config, token)
# Return new card list
return {
"url": url,
}
@admin_pages.route("/users/<int:userid>/cards/remove", methods=["POST"])
@jsonify
@adminrequired

View File

@@ -18,6 +18,7 @@ var user_management = createReactClass({
editing_password: false,
new_password1: '',
new_password2: '',
generating_recovery: false,
cards: window.cards,
profiles: window.profiles,
new_card: '',
@@ -192,6 +193,30 @@ var user_management = createReactClass({
event.preventDefault();
},
generateRecovery: function(event) {
this.setState({generating_recovery: true});
AJAX.post(
Link.get('generaterecovery'),
{},
function(response) {
this.setState({generating_recovery: false});
$.confirm({
escapeKey: 'Done',
animation: 'none',
closeAnimation: 'none',
title: 'Recovery Link',
content: response.url,
buttons: {
Done: function() {
},
}
});
}.bind(this)
);
event.preventDefault();
},
renderUsername: function() {
return (
<LabelledSection vertical={true} label="Username">{
@@ -250,6 +275,10 @@ var user_management = createReactClass({
this.setState({editing_password: true});
}.bind(this)}
/>
{ this.state.generating_recovery ?
<img className="loading" src={Link.get('static', window.assets + 'loading-16.gif')} /> :
<Edit title="generate recovery link" onClick={this.generateRecovery} />
}
</> :
<form className="inline" onSubmit={this.savePassword}>
<div>