From f30dffc6b7ef4130803507ae4ae533fc26ab7edd Mon Sep 17 00:00:00 2001 From: mochi Date: Sat, 19 Sep 2020 16:48:48 +0200 Subject: [PATCH] Creates login plugin for TGUI to streamline and unify login frontend and backend --- code/game/machinery/computer/medical.dm | 69 ++---- code/modules/tgui/plugins/login.dm | 202 ++++++++++++++++++ code/modules/tgui/{ => plugins}/modal.dm | 0 paradise.dme | 3 +- .../tgui/interfaces/MedicalRecords.js | 4 +- .../tgui/interfaces/common/LoginInfo.js | 22 +- .../tgui/interfaces/common/LoginScreen.js | 22 +- tgui/packages/tgui/public/tgui.bundle.js | 2 +- 8 files changed, 245 insertions(+), 79 deletions(-) create mode 100644 code/modules/tgui/plugins/login.dm rename code/modules/tgui/{ => plugins}/modal.dm (100%) diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index c733a7c92c1..e0e6c501e86 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -14,9 +14,6 @@ icon_screen = "medcomp" req_one_access = list(ACCESS_MEDICAL, ACCESS_FORENSICS_LOCKERS) circuit = /obj/item/circuitboard/med_data - var/obj/item/card/id/scan = null - var/authenticated = null - var/rank = null var/screen = null var/datum/data/record/active1 = null var/datum/data/record/active2 = null @@ -65,11 +62,7 @@ return ..() /obj/machinery/computer/med_data/attackby(obj/item/O, mob/user, params) - if(istype(O, /obj/item/card/id) && !scan) - usr.drop_item() - O.forceMove(src) - scan = O - tgui_interact(user) + if(tgui_login_attackby(O, user)) return return ..() @@ -92,14 +85,10 @@ /obj/machinery/computer/med_data/tgui_data(mob/user) var/data[0] data["temp"] = temp - data["scan"] = scan ? scan.name : null - data["authenticated"] = authenticated - data["rank"] = rank data["screen"] = screen data["printing"] = printing - data["isAI"] = isAI(user) - data["isRobot"] = isrobot(user) - if(authenticated) + tgui_login_data(data, user) + if(data["loginState"]["logged_in"]) switch(screen) if(MED_DATA_R_LIST) if(!isnull(GLOB.data_core.general)) @@ -199,58 +188,21 @@ . = TRUE if(tgui_act_modal(action, params)) return + if(tgui_login_act(action, params)) + return switch(action) if("cleartemp") temp = null - if("scan") - if(scan) - scan.forceMove(loc) - if(ishuman(usr) && !usr.get_active_hand()) - usr.put_in_hands(scan) - scan = null - else - var/obj/item/I = usr.get_active_hand() - if(istype(I, /obj/item/card/id)) - usr.drop_item() - I.forceMove(src) - scan = I - if("login") - var/login_type = text2num(params["login_type"]) - if(login_type == LOGIN_TYPE_NORMAL && istype(scan)) - if(check_access(scan)) - authenticated = scan.registered_name - rank = scan.assignment - else if(login_type == LOGIN_TYPE_AI && isAI(usr)) - authenticated = usr.name - rank = "AI" - else if(login_type == LOGIN_TYPE_ROBOT && isrobot(usr)) - authenticated = usr.name - var/mob/living/silicon/robot/R = usr - rank = "[R.modtype] [R.braintype]" - if(authenticated) - active1 = null - active2 = null - screen = MED_DATA_R_LIST else . = FALSE if(.) return - if(authenticated) + if(tgui_login_get().logged_in) . = TRUE switch(action) - if("logout") - if(scan) - scan.forceMove(loc) - if(ishuman(usr) && !usr.get_active_hand()) - usr.put_in_hands(scan) - scan = null - authenticated = null - screen = null - active1 = null - active2 = null if("screen") screen = clamp(text2num(params["screen"]) || 0, MED_DATA_R_LIST, MED_DATA_MEDBOT) active1 = null @@ -403,10 +355,11 @@ else if(istype(active1) && (field in active1.fields)) active1.fields[field] = answer if("add_c") - if(!length(answer) || !istype(active2) || !length(authenticated)) + var/datum/tgui_login/state = tgui_login_get() + if(!length(answer) || !istype(active2) || !length(state.name)) return active2.fields["comments"] += list(list( - header = "Made by [authenticated] ([rank]) on [GLOB.current_date_string] [station_time_timestamp()]", + header = "Made by [state.name] ([state.name]) on [GLOB.current_date_string] [station_time_timestamp()]", text = answer )) else @@ -493,6 +446,10 @@ ..(severity) +/obj/machinery/computer/med_data/tgui_login_on_login(datum/tgui_login/state) + active1 = null + active2 = null + screen = MED_DATA_R_LIST /obj/machinery/computer/med_data/laptop name = "medical laptop" diff --git a/code/modules/tgui/plugins/login.dm b/code/modules/tgui/plugins/login.dm new file mode 100644 index 00000000000..286d06dce51 --- /dev/null +++ b/code/modules/tgui/plugins/login.dm @@ -0,0 +1,202 @@ +/** + * tgui login + * + * Allows the handling of logins using IDs within tgui. + * + * Two key procs: + * * [/obj/proc/tgui_login_act] - Call in your tgui_act() proc to catch any login actions and handle them. + * * [/obj/proc/tgui_login_data] - Call in your tgui_data() proc to pass login info. + * + * How to use (DM side): + * 1. Call [/obj/proc/tgui_login_act] at the start of your tgui_act() proc + * 2. Call [/obj/proc/tgui_login_data] in your tgui_data() proc while passing the data list + * 3. In your object, call [/obj/proc/tgui_login_get] to get the current login state. + * 4. Optional: call [/obj/proc/tgui_login_attackby] in your attackby() to make the login process easier. + * + * How to use (JS side): Use the and interfaces. + */ + +GLOBAL_LIST(tgui_logins) + +/** + * Call this from a proc that is called in tgui_act() to process login actions + * + * Arguments: + * * action - The called action + * * params - The params to the action + */ +/obj/proc/tgui_login_act(action = "", params) + . = null + switch(action) + if("login_insert") + var/datum/tgui_login/state = tgui_login_get() + if(state.id) // An ID is already inserted, eject it + return tgui_login_eject(state = state) + else // No ID, attempt to insert one in + return tgui_login_insert(usr.get_active_hand(), state = state) + if("login_eject") + return tgui_login_eject() + if("login_login") + return tgui_login_login(text2num(params["login_type"])) + if("login_logout") + return tgui_login_logout() + +/** + * Adds login state data. + * + * Arguments: + * * data - The data list to be returned + * * user - The user calling tgui_data() + * * state - The current login state + */ +/obj/proc/tgui_login_data(list/data, mob/user, datum/tgui_login/state = tgui_login_get()) + data["loginState"] = list( + "id" = state.id ? state.id.name : null, + "name" = state.name, + "rank" = state.rank, + "logged_in" = state.logged_in, + ) + data["isAI"] = isAI(user) + data["isRobot"] = isrobot(user) + +/** + * Convenience function to perform login actions when + * the source object is hit by specific items. + * + * Arguments: + * * O - The object + * * user - The user + */ +/obj/proc/tgui_login_attackby(obj/item/O, mob/user) + if(istype(O, /obj/item/card/id) && tgui_login_insert(O)) + tgui_interact(user) + return TRUE + +/** + * Attempts to insert an object as an ID. + * + * Arguments: + * * O - The object to try inserting + * * state - The current login state + */ +/obj/proc/tgui_login_insert(obj/item/O, datum/tgui_login/state = tgui_login_get()) + if(state.id) + return + + if(istype(O, /obj/item/card/id)) + // Move the ID inside + usr.drop_item() + O.forceMove(src) + + // Update the state + state.id = O + + return TRUE + +/** + * Attempts to eject the inserted ID. + * + * Arguments: + * * state - The current login state + */ +/obj/proc/tgui_login_eject(datum/tgui_login/state = tgui_login_get()) + if(!state.id) + return + + // Drop the ID + state.id.forceMove(loc) + if(ishuman(usr) && !usr.get_active_hand()) + usr.put_in_hands(state.id) + + // Update the state + state.id = null + + return TRUE + +/** + * Attempts to log in with the given login type. + * + * Arguments: + * * login_type - The login type: LOGIN_TYPE_NORMAL (checks for inserted ID), LOGIN_TYPE_AI and LOGIN_TYPE_ROBOT + * * state - The current login state + */ +/obj/proc/tgui_login_login(login_type = LOGIN_TYPE_NORMAL, datum/tgui_login/state = tgui_login_get()) + if(!state.id || state.logged_in) + return + + if(login_type == LOGIN_TYPE_NORMAL) + if(check_access(state.id)) + state.name = state.id.registered_name + state.rank = state.id.assignment + else if(login_type == LOGIN_TYPE_AI && isAI(usr)) + state.name = usr.name + state.rank = "AI" + else if(login_type == LOGIN_TYPE_ROBOT && isrobot(usr)) + var/mob/living/silicon/robot/R = usr + state.name = usr.name + state.rank = "[R.modtype] [R.braintype]" + + state.logged_in = TRUE + tgui_login_on_login(state = state) + + return TRUE + +/** + * Attempts to log out. + * + * Arguments: + * * state - The current login state + */ +/obj/proc/tgui_login_logout(datum/tgui_login/state = tgui_login_get()) + if(!state.logged_in) + return + + state.name = state.rank = "" + state.logged_in = FALSE + tgui_login_on_logout(state = state) + + return TRUE + +/** + * Returns (or creates) the login state for the source object. + * + * Arguments: + * * state - The current login state + */ +/obj/proc/tgui_login_get() + . = LAZYACCESS(GLOB.tgui_logins, UID()) + if(!.) + LAZYINITLIST(GLOB.tgui_logins) + . = GLOB.tgui_logins[UID()] = new /datum/tgui_login + +/** + * Called on successful login. + * + * Arguments: + * * state - The current login state + */ +/obj/proc/tgui_login_on_login(datum/tgui_login/state = tgui_login_get()) + return + +/** + * Called on successful logout. + * + * Arguments: + * * state - The current login state + */ +/obj/proc/tgui_login_on_logout(datum/tgui_login/state = tgui_login_get()) + return + +/** + * Login state (there should be only one for one datum) + */ +/datum/tgui_login + var/obj/item/card/id/id = null + var/name = "" + var/rank = "" + var/logged_in = FALSE + +/datum/tgui_login/New(id, name, rank) + src.id = id + src.name = name + src.rank = rank diff --git a/code/modules/tgui/modal.dm b/code/modules/tgui/plugins/modal.dm similarity index 100% rename from code/modules/tgui/modal.dm rename to code/modules/tgui/plugins/modal.dm diff --git a/paradise.dme b/paradise.dme index 7fe2674b7d8..2388afbd722 100644 --- a/paradise.dme +++ b/paradise.dme @@ -2472,12 +2472,13 @@ #include "code\modules\telesci\telepad.dm" #include "code\modules\telesci\telesci_computer.dm" #include "code\modules\tgui\external.dm" -#include "code\modules\tgui\modal.dm" #include "code\modules\tgui\states.dm" #include "code\modules\tgui\tgui.dm" #include "code\modules\tgui\modules\_base.dm" #include "code\modules\tgui\modules\crew_monitor.dm" #include "code\modules\tgui\modules\ert_manager.dm" +#include "code\modules\tgui\plugins\login.dm" +#include "code\modules\tgui\plugins\modal.dm" #include "code\modules\tgui\states\admin.dm" #include "code\modules\tgui\states\always.dm" #include "code\modules\tgui\states\conscious.dm" diff --git a/tgui/packages/tgui/interfaces/MedicalRecords.js b/tgui/packages/tgui/interfaces/MedicalRecords.js index 926ac9fbefb..a8b53da52a9 100644 --- a/tgui/packages/tgui/interfaces/MedicalRecords.js +++ b/tgui/packages/tgui/interfaces/MedicalRecords.js @@ -57,10 +57,10 @@ const virusModalBodyOverride = (modal, context) => { export const MedicalRecords = (_properties, context) => { const { data } = useBackend(context); const { - authenticated, + loginState, screen, } = data; - if (!authenticated) { + if (!loginState.logged_in) { return ( diff --git a/tgui/packages/tgui/interfaces/common/LoginInfo.js b/tgui/packages/tgui/interfaces/common/LoginInfo.js index 7a8bb1dc427..66380bd4a6d 100644 --- a/tgui/packages/tgui/interfaces/common/LoginInfo.js +++ b/tgui/packages/tgui/interfaces/common/LoginInfo.js @@ -2,18 +2,16 @@ import { useBackend } from '../../backend'; import { Box, Button, NoticeBox } from '../../components'; /** - * Displays a notice box showing the - * `authenticated` and `rank` data fields if they exist. + * Displays a notice box displaying the current login state. * - * Also gives an option to log off (calls `logout` TGUI action) + * Also gives an option to log off (calls `login_logout` TGUI action) * @param {object} _properties * @param {object} context */ export const LoginInfo = (_properties, context) => { const { act, data } = useBackend(context); const { - authenticated, - rank, + loginState, } = data; if (!data) { return; @@ -21,14 +19,22 @@ export const LoginInfo = (_properties, context) => { return ( - Logged in as: {authenticated} ({rank}) + Logged in as: {loginState.name} ({loginState.rank})