mirror of
https://github.com/DragonMinded/bemaniutils.git
synced 2026-09-07 09:55:17 -05:00
Implement delete user button on admin user profile page.
This commit is contained in:
@@ -435,3 +435,14 @@ class GameData(BaseData):
|
||||
)
|
||||
for result in cursor.mappings()
|
||||
]
|
||||
|
||||
def delete_user(self, userid: UserID) -> None:
|
||||
"""
|
||||
Given a user ID, make sure all game-related things are unlinked from
|
||||
the user or deleted from the DB, whichever relevant.
|
||||
"""
|
||||
sql = "DELETE FROM series_achievement WHERE userid = :userid"
|
||||
self.execute(sql, {"userid": userid})
|
||||
|
||||
sql = "DELETE FROM game_settings WHERE userid = :userid"
|
||||
self.execute(sql, {"userid": userid})
|
||||
|
||||
@@ -302,3 +302,14 @@ class LobbyData(BaseData):
|
||||
# Prune any orphaned lobbies too
|
||||
sql = "DELETE FROM lobby WHERE time <= :time"
|
||||
self.execute(sql, {"time": Time.now() - Time.SECONDS_IN_HOUR})
|
||||
|
||||
def delete_user(self, userid: UserID) -> None:
|
||||
"""
|
||||
Given a user ID, make sure all lobby-related things are unlinked from
|
||||
the user or deleted from the DB, whichever relevant.
|
||||
"""
|
||||
sql = "DELETE FROM playsession WHERE userid = :userid"
|
||||
self.execute(sql, {"userid": userid})
|
||||
|
||||
sql = "DELETE FROM lobby WHERE userid = :userid"
|
||||
self.execute(sql, {"userid": userid})
|
||||
|
||||
@@ -572,6 +572,14 @@ class MachineData(BaseData):
|
||||
for entry in cursor.mappings()
|
||||
]
|
||||
|
||||
def delete_user(self, userid: UserID) -> None:
|
||||
"""
|
||||
Given a user ID, make sure all machine-related things are unlinked from
|
||||
the user or deleted from the DB, whichever relevant.
|
||||
"""
|
||||
sql = "DELETE FROM arcade_owner WHERE userid = :userid"
|
||||
self.execute(sql, {"userid": userid})
|
||||
|
||||
def create_session(self, arcadeid: ArcadeID, expiration: int = (30 * 86400)) -> str:
|
||||
"""
|
||||
Given an arcade ID, create a session string.
|
||||
|
||||
@@ -1021,3 +1021,14 @@ class MusicData(BaseData):
|
||||
)
|
||||
for result in cursor.mappings()
|
||||
]
|
||||
|
||||
def delete_user(self, userid: UserID) -> None:
|
||||
"""
|
||||
Given a user ID, make sure all music-related things are unlinked from
|
||||
the user or deleted from the DB, whichever relevant.
|
||||
"""
|
||||
sql = "DELETE FROM score_history WHERE userid = :userid"
|
||||
self.execute(sql, {"userid": userid})
|
||||
|
||||
sql = "DELETE FROM score WHERE userid = :userid"
|
||||
self.execute(sql, {"userid": userid})
|
||||
|
||||
@@ -320,6 +320,14 @@ class NetworkData(BaseData):
|
||||
for result in cursor.mappings()
|
||||
]
|
||||
|
||||
def delete_user(self, userid: UserID) -> None:
|
||||
"""
|
||||
Given a user ID, make sure all network-related things are unlinked from
|
||||
the user or deleted from the DB, whichever relevant.
|
||||
"""
|
||||
sql = "UPDATE audit SET userid = NULL WHERE userid = :userid"
|
||||
self.execute(sql, {"userid": userid})
|
||||
|
||||
def delete_events(self, oldest_event_ts: int) -> None:
|
||||
"""
|
||||
Given a timestamp of the oldset event we should keep around, delete
|
||||
|
||||
@@ -1503,3 +1503,39 @@ class UserData(BaseData):
|
||||
|
||||
# Finally, return the user ID
|
||||
return UserID(userid)
|
||||
|
||||
def delete_user(self, userid: UserID) -> None:
|
||||
"""
|
||||
Given a user ID, make sure all user-related things are unlinked from
|
||||
the user or deleted from the DB, whichever relevant.
|
||||
"""
|
||||
sql = "SELECT COUNT(refid) AS refcount FROM refid WHERE userid = :userid"
|
||||
cursor = self.execute(sql, {"userid": userid})
|
||||
|
||||
# First nuke all profiles, and things related to a player's refid (profile ID basically).
|
||||
if cursor.rowcount == 1 and cursor.mappings().fetchone()["refcount"] > 0:
|
||||
sql = "DELETE FROM time_based_achievement WHERE refid IN (SELECT refid FROM refid WHERE userid = :userid)"
|
||||
self.execute(sql, {"userid": userid})
|
||||
sql = "DELETE FROM achievement WHERE refid IN (SELECT refid FROM refid WHERE userid = :userid)"
|
||||
self.execute(sql, {"userid": userid})
|
||||
sql = "DELETE FROM profile WHERE refid IN (SELECT refid FROM refid WHERE userid = :userid)"
|
||||
self.execute(sql, {"userid": userid})
|
||||
|
||||
# Now nuke any active sessions for the user.
|
||||
self._destroy_sessions(userid, "userid")
|
||||
|
||||
# Finally, nuke anything we own that points at the user.
|
||||
sql = "DELETE FROM link WHERE userid = :userid OR other_userid = :userid"
|
||||
self.execute(sql, {"userid": userid})
|
||||
sql = "DELETE FROM balance WHERE userid = :userid"
|
||||
self.execute(sql, {"userid": userid})
|
||||
sql = "DELETE FROM extid WHERE userid = :userid"
|
||||
self.execute(sql, {"userid": userid})
|
||||
sql = "DELETE FROM refid WHERE userid = :userid"
|
||||
self.execute(sql, {"userid": userid})
|
||||
sql = "DELETE FROM card WHERE userid = :userid"
|
||||
self.execute(sql, {"userid": userid})
|
||||
|
||||
# And finally, nuke the user themselves.
|
||||
sql = "DELETE FROM user WHERE id = :userid"
|
||||
self.execute(sql, {"userid": userid})
|
||||
|
||||
@@ -427,6 +427,8 @@ def viewuser(userid: int) -> Response:
|
||||
"updateemail": url_for("admin_pages.updateemail", userid=userid),
|
||||
"updatepin": url_for("admin_pages.updatepin", userid=userid),
|
||||
"updatepassword": url_for("admin_pages.updatepassword", userid=userid),
|
||||
"removeuser": url_for("admin_pages.removeuser", userid=userid),
|
||||
"viewusers": url_for("admin_pages.viewusers"),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -467,6 +469,31 @@ def listuser(userid: int) -> Dict[str, Any]:
|
||||
}
|
||||
|
||||
|
||||
@admin_pages.route("/users/<int:userid>/remove", methods=["POST"])
|
||||
@jsonify
|
||||
@adminrequired
|
||||
def removeuser(userid: int) -> Dict[str, Any]:
|
||||
# Cast the userID.
|
||||
userid = UserID(userid)
|
||||
user = g.data.local.user.get_user(userid)
|
||||
|
||||
# We only try to run through deleting if the user exists, to avoid
|
||||
# somebody accidentally putting a bad user ID in here.
|
||||
if not user:
|
||||
return {"success": False}
|
||||
|
||||
# Now, go through and delete them from everything that matters.
|
||||
g.data.local.network.delete_user(userid)
|
||||
g.data.local.machine.delete_user(userid)
|
||||
g.data.local.lobby.delete_user(userid)
|
||||
g.data.local.music.delete_user(userid)
|
||||
g.data.local.game.delete_user(userid)
|
||||
g.data.local.user.delete_user(userid)
|
||||
|
||||
# And return nothing, since this can be called multiple places.
|
||||
return {"success": True}
|
||||
|
||||
|
||||
@admin_pages.route("/arcades/list")
|
||||
@jsonify
|
||||
@adminrequired
|
||||
|
||||
@@ -471,6 +471,39 @@ var user_management = createReactClass({
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
deleteUser: function(event) {
|
||||
$.confirm({
|
||||
escapeKey: 'Cancel',
|
||||
animation: 'none',
|
||||
closeAnimation: 'none',
|
||||
title: 'Delete User',
|
||||
content: (
|
||||
'Are you sure you want to delete this user? All of their game profiles, scores, ' +
|
||||
'PASELI balances and settings will be deleted along with the account itself.'
|
||||
),
|
||||
buttons: {
|
||||
Delete: {
|
||||
btnClass: 'delete',
|
||||
action: function() {
|
||||
AJAX.post(
|
||||
Link.get('removeuser'),
|
||||
{},
|
||||
function(response) {
|
||||
// If it succeeded, redirect back to users.
|
||||
if (response.success) {
|
||||
window.location = Link.get('viewusers');
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
}.bind(this),
|
||||
},
|
||||
Cancel: function() {
|
||||
},
|
||||
}
|
||||
});
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
renderDeleteProfileButton: function(profile) {
|
||||
return (
|
||||
<>
|
||||
@@ -494,6 +527,9 @@ var user_management = createReactClass({
|
||||
{this.renderPIN()}
|
||||
{this.renderLastPlayed()}
|
||||
</div>
|
||||
<div className="section">
|
||||
<Delete title="delete user" onClick={this.deleteUser.bind(this)} />
|
||||
</div>
|
||||
<div className="section">
|
||||
<h3>Cards</h3>
|
||||
{this.state.cards.map(function(card) {
|
||||
|
||||
Reference in New Issue
Block a user