diff --git a/backend/src/controllers/admin.cpp b/backend/src/controllers/admin.cpp index 9db135e..010ddf6 100644 --- a/backend/src/controllers/admin.cpp +++ b/backend/src/controllers/admin.cpp @@ -92,5 +92,19 @@ namespace api { void admin::is_admin(req_type, cbk_type cbk) { cbk(dto::Responses::get_success_res()); } + + void admin::get_token(req_type, cbk_type cbk, uint64_t user) { + db::MapperUser user_mapper(drogon::app().getDbClient()); + + try { + const auto &db_user = user_mapper.findByPrimaryKey(user); + + const std::string &token = auth::get_token(db_user); + + cbk(dto::Responses::get_login_res(token)); + } catch (const std::exception&) { + cbk(dto::Responses::get_badreq_res("Bad user")); + } + } } #pragma clang diagnostic pop \ No newline at end of file diff --git a/backend/src/controllers/controllers.h b/backend/src/controllers/controllers.h index fe43de7..efb788b 100644 --- a/backend/src/controllers/controllers.h +++ b/backend/src/controllers/controllers.h @@ -25,6 +25,7 @@ public: METHOD_ADD(admin::delete_user, "/delete", drogon::Post, "Login", "Admin"); METHOD_ADD(admin::disable_2fa, "/disable_2fa", drogon::Post, "Login", "Admin"); METHOD_ADD(admin::is_admin, "/is_admin", drogon::Get, "Login", "Admin"); + METHOD_ADD(admin::get_token, "/get_token/{}", drogon::Get, "Login", "Admin"); METHOD_LIST_END void users(req_type, cbk_type); @@ -33,6 +34,7 @@ public: void delete_user(req_type, cbk_type); void disable_2fa(req_type, cbk_type); void is_admin(req_type, cbk_type); + void get_token(req_type, cbk_type, uint64_t user); }; class auth : public drogon::HttpController { diff --git a/frontend/src/api/admin.ts b/frontend/src/api/admin.ts index 467f4f3..6ed4c7d 100644 --- a/frontend/src/api/admin.ts +++ b/frontend/src/api/admin.ts @@ -54,5 +54,11 @@ export const disable_tfa = ( token ); +export const impersonate = ( + user: number, + token: string +): Promise => + get_token(`/api/admin/get_token/${user}`, token); + export const is_admin = async (token: string): Promise => !isErrorResponse(await get_token('/api/admin/is_admin', token)); diff --git a/frontend/src/views/AdminView.vue b/frontend/src/views/AdminView.vue index ae2670d..75f612a 100644 --- a/frontend/src/views/AdminView.vue +++ b/frontend/src/views/AdminView.vue @@ -48,6 +48,16 @@ const setRole = loadingMsgWrapper( } ); +const impersonate = loadingMsgWrapper(message, async (user: number) => { + const token = await check_token(jwt); + if (!token) return; + + const res = await Admin.impersonate(user, token); + if (isErrorResponse(res)) return console.error(res.message); + jwt.setToken(res.jwt); + await router.push({ path: '/' }); +}); + const action = ( func: ( user: number, @@ -122,6 +132,9 @@ const columns: DataTableColumn[] = [ render(user) { return ( + impersonate(user.id)}> + Impersonate + logoutUser(user.id)}> Logout all