mirror of https://github.com/gophish/gophish
Added ability to allow admin to 'su' to other accounts (#1812)
* Added ability to allow admin to 'su' to other accounts * Naming convention and user message modifications * Removed debug statementpull/1557/merge
parent
26e82cb2e3
commit
38a6a77c9c
|
@ -130,6 +130,7 @@ func (as *AdminServer) registerRoutes() {
|
|||
router.HandleFunc("/settings", mid.Use(as.Settings, mid.RequireLogin))
|
||||
router.HandleFunc("/users", mid.Use(as.UserManagement, mid.RequirePermission(models.PermissionModifySystem), mid.RequireLogin))
|
||||
router.HandleFunc("/webhooks", mid.Use(as.Webhooks, mid.RequirePermission(models.PermissionModifySystem), mid.RequireLogin))
|
||||
router.HandleFunc("/impersonate", mid.Use(as.Impersonate, mid.RequirePermission(models.PermissionModifySystem), mid.RequireLogin))
|
||||
// Create the API routes
|
||||
api := api.NewServer(api.WithWorker(as.worker))
|
||||
router.PathPrefix("/api/").Handler(api)
|
||||
|
@ -269,6 +270,24 @@ func (as *AdminServer) Webhooks(w http.ResponseWriter, r *http.Request) {
|
|||
getTemplate(w, "webhooks").ExecuteTemplate(w, "base", params)
|
||||
}
|
||||
|
||||
// Impersonate allows an admin to login to a user account without needing the password
|
||||
func (as *AdminServer) Impersonate(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if r.Method == "POST" {
|
||||
username := r.FormValue("username")
|
||||
u, err := models.GetUserByUsername(username)
|
||||
if err != nil {
|
||||
log.Error(err)
|
||||
http.Error(w, err.Error(), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
session := ctx.Get(r, "session").(*sessions.Session)
|
||||
session.Values["id"] = u.Id
|
||||
session.Save(r, w)
|
||||
}
|
||||
http.Redirect(w, r, "/", 302)
|
||||
}
|
||||
|
||||
// Login handles the authentication flow for a user. If credentials are valid,
|
||||
// a session is created
|
||||
func (as *AdminServer) Login(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -115,6 +115,55 @@ const deleteUser = (id) => {
|
|||
})
|
||||
}
|
||||
|
||||
const impersonate = (id) => {
|
||||
var user = users.find(x => x.id == id)
|
||||
if (!user) {
|
||||
return
|
||||
}
|
||||
Swal.fire({
|
||||
title: "Are you sure?",
|
||||
html: "You will be logged out of your account and logged in as <strong>" + escapeHtml(user.username) + "</strong>",
|
||||
type: "warning",
|
||||
animation: false,
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "Swap User",
|
||||
confirmButtonColor: "#428bca",
|
||||
reverseButtons: true,
|
||||
allowOutsideClick: false,
|
||||
}).then((result) => {
|
||||
if (result.value) {
|
||||
|
||||
fetch('/impersonate', {
|
||||
method: 'post',
|
||||
body: "username=" + user.username + "&csrf_token=" + encodeURIComponent(csrf_token),
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
}).then((response) => {
|
||||
if (response.status == 200) {
|
||||
Swal.fire({
|
||||
title: "Success!",
|
||||
html: "Successfully changed to user <strong>" + escapeHtml(user.username) + "</strong>.",
|
||||
type: "success",
|
||||
showCancelButton: false,
|
||||
confirmButtonText: "Home",
|
||||
allowOutsideClick: false,
|
||||
}).then((result) => {
|
||||
if (result.value) {
|
||||
window.location.href = "/"
|
||||
}});
|
||||
} else {
|
||||
Swal.fire({
|
||||
title: "Error!",
|
||||
type: "error",
|
||||
html: "Failed to change to user <strong>" + escapeHtml(user.username) + "</strong>.",
|
||||
showCancelButton: false,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const load = () => {
|
||||
$("#userTable").hide()
|
||||
|
@ -136,7 +185,11 @@ const load = () => {
|
|||
userTable.row.add([
|
||||
escapeHtml(user.username),
|
||||
escapeHtml(user.role.name),
|
||||
"<div class='pull-right'><button class='btn btn-primary edit_button' data-toggle='modal' data-backdrop='static' data-target='#modal' data-user-id='" + user.id + "'>\
|
||||
"<div class='pull-right'>\
|
||||
<button class='btn btn-warning impersonate_button' data-user-id='" + user.id + "'>\
|
||||
<i class='fa fa-retweet'></i>\
|
||||
</button>\
|
||||
<button class='btn btn-primary edit_button' data-toggle='modal' data-backdrop='static' data-target='#modal' data-user-id='" + user.id + "'>\
|
||||
<i class='fa fa-pencil'></i>\
|
||||
</button>\
|
||||
<button class='btn btn-danger delete_button' data-user-id='" + user.id + "'>\
|
||||
|
@ -180,4 +233,7 @@ $(document).ready(function () {
|
|||
$("#userTable").on('click', '.delete_button', function (e) {
|
||||
deleteUser($(this).attr('data-user-id'))
|
||||
})
|
||||
$("#userTable").on('click', '.impersonate_button', function (e) {
|
||||
impersonate($(this).attr('data-user-id'))
|
||||
})
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue