From 5cbd214b0702146866b35af5fe220cdf79fcfd3a Mon Sep 17 00:00:00 2001 From: MistakeNot4892 Date: Tue, 22 Dec 2020 11:26:25 +1100 Subject: [PATCH] Fixes network bugs and adjusts program access --- .../stock_parts/network_lock.dm | 6 +- code/game/objects/items/weapons/cards_ids.dm | 5 ++ code/modules/merchant/merchant_programs.dm | 2 +- .../modular_computers/file_system/program.dm | 42 ++++++----- .../file_system/programs/command/comm.dm | 4 +- .../programs/engineering/atmos_control.dm | 2 +- .../programs/engineering/power_monitor.dm | 2 +- .../programs/engineering/rcon_console.dm | 2 +- .../engineering/supermatter_monitor.dm | 2 +- .../programs/generic/deck_management.dm | 11 +-- .../file_system/programs/generic/docks.dm | 5 ++ .../programs/generic/file_browser.dm | 26 ++++--- .../programs/generic/ntdownloader.dm | 10 +-- .../programs/generic/ntnrc_client.dm | 2 +- .../programs/medical/suit_sensors.dm | 2 +- .../programs/research/ai_restorer.dm | 2 +- .../programs/research/email_administration.dm | 2 +- .../programs/security/digitalwarrant.dm | 2 +- .../programs/security/forceauthorization.dm | 2 +- .../file_system/reports/crew_record.dm | 4 +- .../networking/device_types/acl.dm | 22 +++++- .../networking/machinery/acl.dm | 75 +++++++++++++++++-- .../networking/machinery/mainframe.dm | 8 +- code/modules/modular_computers/ntos/files.dm | 72 ++++++++++-------- code/modules/modular_computers/ntos/ntos.dm | 5 +- maps/tradeship/tradeship_overrides.dm | 2 +- nano/templates/deck_management.tmpl | 9 --- nano/templates/file_manager.tmpl | 2 +- nano/templates/network_acl.tmpl | 36 +++++++++ 29 files changed, 245 insertions(+), 121 deletions(-) diff --git a/code/game/machinery/_machines_base/stock_parts/network_lock.dm b/code/game/machinery/_machines_base/stock_parts/network_lock.dm index ca9ceb6678d..d78bdfcc3a7 100644 --- a/code/game/machinery/_machines_base/stock_parts/network_lock.dm +++ b/code/game/machinery/_machines_base/stock_parts/network_lock.dm @@ -83,15 +83,15 @@ return data["connected"] = TRUE data["default_state"] = auto_deny_all - var/list/grants = list() + var/list/grants_data = list() if(!network.access_controller) return for(var/datum/computer_file/data/grant_record/GR in network.access_controller.get_all_grants()) - grants.Add(list(list( + grants_data.Add(list(list( "grant_name" = GR.stored_data, "assigned" = (GR.stored_data in grants) ))) - data["grants"] = grants + data["grants"] = grants_data /obj/item/stock_parts/network_lock/OnTopic(mob/user, href_list, datum/topic_state/state) . = ..() diff --git a/code/game/objects/items/weapons/cards_ids.dm b/code/game/objects/items/weapons/cards_ids.dm index 9b0d2ceb5ed..c4dfc7ad892 100644 --- a/code/game/objects/items/weapons/cards_ids.dm +++ b/code/game/objects/items/weapons/cards_ids.dm @@ -462,6 +462,11 @@ var/const/NO_EMAG_ACT = -50 to_chat(usr, SPAN_WARNING("Pressing the synchronization button on the card causes a red LED to flash three times.")) /obj/item/card/id/network/proc/refresh_access_record(var/datum/computer_network/network) + if(!network) + var/datum/extension/network_device/D = get_extension(src, /datum/extension/network_device) + network = D.get_network() + if(!network) + return for(var/datum/extension/network_device/mainframe/mainframe in network.get_mainframes_by_role(MF_ROLE_CREW_RECORDS)) for(var/datum/computer_file/report/crew_record/ar in mainframe.get_all_files()) if(ar.user_id != user_id) diff --git a/code/modules/merchant/merchant_programs.dm b/code/modules/merchant/merchant_programs.dm index c0e926db459..595396ee9e9 100644 --- a/code/modules/merchant/merchant_programs.dm +++ b/code/modules/merchant/merchant_programs.dm @@ -7,7 +7,7 @@ nanomodule_path = /datum/nano_module/program/merchant size = 12 usage_flags = PROGRAM_CONSOLE - required_access = access_merchant + required_access = list(access_merchant) var/obj/machinery/merchant_pad/pad = null var/current_merchant = 0 var/show_trades = 0 diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index 147155026bd..9937af84ae1 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -2,7 +2,7 @@ /datum/computer_file/program filetype = "PRG" filename = "UnknownProgram" // File name. FILE NAME MUST BE UNIQUE IF YOU WANT THE PROGRAM TO BE DOWNLOADABLE FROM NETWORK! - var/required_access = null // List of required accesses to run/download the program. + var/list/required_access = list() // List of required accesses to run/download the program. var/requires_access_to_run = 1 // Whether the program checks for required_access when run. var/requires_access_to_download = 1 // Whether the program checks for required_access when downloading. var/datum/nano_module/NM = null // If the program uses NanoModule, put it here and it will be automagically opened. Otherwise implement ui_interact. @@ -83,32 +83,40 @@ // Check if the user can run program. Only humans can operate computer. Automatically called in run_program() // User has to wear their ID or have it inhand for ID Scan to work. // Can also be called manually, with optional parameter being access_to_check to scan the user's ID -/datum/computer_file/program/proc/can_run(var/mob/living/user, var/loud = 0, var/access_to_check) +/datum/computer_file/program/proc/can_run(var/mob/living/user, var/loud = 0, var/list/accesses_to_check, var/datum/computer_network/network) if(!requires_access_to_run) - return 1 - // Defaults to required_access - if(!access_to_check) - access_to_check = required_access - if(!access_to_check) // No required_access, allow it. - return 1 + return TRUE + // Checks to see if network access is enabled, and then defaults to required_access if not. + if(!accesses_to_check) + if(network) + var/datum/extension/network_device/acl/access_controller = network.access_controller + if(access_controller && access_controller.program_control) + accesses_to_check = access_controller.get_program_access(filename) + + if(!length(accesses_to_check)) + accesses_to_check = required_access + + if(!length(accesses_to_check)) // No required_access, allow it. + return TRUE // Admin override - allows operation of any computer as aghosted admin, as if you had any required access. if(isghost(user) && check_rights(R_ADMIN, 0, user)) - return 1 + return TRUE if(!istype(user)) - return 0 + return FALSE var/obj/item/card/id/I = user.GetIdCard() if(!I) if(loud) - to_chat(user, "\The [computer] flashes an \"RFID Error - Unable to scan ID\" warning.") - return 0 - - if(access_to_check in I.access) - return 1 - else if(loud) - to_chat(user, "\The [computer] flashes an \"Access Denied\" warning.") + to_chat(user, SPAN_WARNING("The OS flashes an \"RFID Error - Unable to scan ID\" warning.")) + return FALSE + + if(has_access(accesses_to_check, I.access)) + return TRUE + if(loud) + to_chat(user, SPAN_WARNING("The OS flashes an \"Access Denied\" warning.")) + return FALSE // This attempts to retrieve header data for NanoUIs. If implementing completely new device of different type than existing ones // always include the device here in this proc. This proc basically relays the request to whatever is running the program. diff --git a/code/modules/modular_computers/file_system/programs/command/comm.dm b/code/modules/modular_computers/file_system/programs/command/comm.dm index 308e29a2909..5290a89f494 100644 --- a/code/modules/modular_computers/file_system/programs/command/comm.dm +++ b/code/modules/modular_computers/file_system/programs/command/comm.dm @@ -11,7 +11,7 @@ program_menu_icon = "flag" nanomodule_path = /datum/nano_module/program/comm extended_desc = "Used to command and control. Can relay long-range communications. This program can not be run on tablet computers." - required_access = access_bridge + required_access = list(access_bridge) requires_network = 1 size = 12 usage_flags = PROGRAM_CONSOLE | PROGRAM_LAPTOP @@ -109,7 +109,7 @@ /datum/nano_module/program/comm/proc/is_autenthicated(var/mob/user) if(program) - return program.can_run(user) + return program.can_run(user, program.computer.get_network()) return 1 /datum/nano_module/program/comm/proc/obtain_message_listener() diff --git a/code/modules/modular_computers/file_system/programs/engineering/atmos_control.dm b/code/modules/modular_computers/file_system/programs/engineering/atmos_control.dm index 4c64d3aad5d..7e5b5d2f454 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/atmos_control.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/atmos_control.dm @@ -6,7 +6,7 @@ program_key_state = "atmos_key" program_menu_icon = "shuffle" extended_desc = "This program allows remote control of air alarms. This program can not be run on tablet computers." - required_access = access_atmospherics + required_access = list(access_atmospherics) requires_network = 1 network_destination = "atmospheric control system" requires_network_feature = NETWORK_SYSTEMCONTROL diff --git a/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm b/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm index 487964e7030..4b42309390a 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/power_monitor.dm @@ -7,7 +7,7 @@ program_menu_icon = "battery-3" extended_desc = "This program connects to sensors to provide information about electrical systems" ui_header = "power_norm.gif" - required_access = access_engine + required_access = list(access_engine) requires_network = 1 network_destination = "power monitoring system" size = 9 diff --git a/code/modules/modular_computers/file_system/programs/engineering/rcon_console.dm b/code/modules/modular_computers/file_system/programs/engineering/rcon_console.dm index 94b67210775..dddd6659ee0 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/rcon_console.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/rcon_console.dm @@ -6,7 +6,7 @@ program_key_state = "rd_key" program_menu_icon = "power" extended_desc = "This program allows remote control of power distribution systems. This program can not be run on tablet computers." - required_access = access_engine + required_access = list(access_engine) network_destination = "RCON remote control system" requires_network_feature = NETWORK_SYSTEMCONTROL usage_flags = PROGRAM_LAPTOP | PROGRAM_CONSOLE diff --git a/code/modules/modular_computers/file_system/programs/engineering/supermatter_monitor.dm b/code/modules/modular_computers/file_system/programs/engineering/supermatter_monitor.dm index 4df162512fb..0612433117f 100644 --- a/code/modules/modular_computers/file_system/programs/engineering/supermatter_monitor.dm +++ b/code/modules/modular_computers/file_system/programs/engineering/supermatter_monitor.dm @@ -11,7 +11,7 @@ program_menu_icon = "notice" extended_desc = "This program connects to specially calibrated supermatter sensors to provide information on the status of supermatter-based engines." ui_header = "smmon_0.gif" - required_access = access_engine + required_access = list(access_engine) network_destination = "supermatter monitoring system" size = 5 category = PROG_ENG diff --git a/code/modules/modular_computers/file_system/programs/generic/deck_management.dm b/code/modules/modular_computers/file_system/programs/generic/deck_management.dm index 5a5413a0a22..3d900cfbd70 100644 --- a/code/modules/modular_computers/file_system/programs/generic/deck_management.dm +++ b/code/modules/modular_computers/file_system/programs/generic/deck_management.dm @@ -7,6 +7,7 @@ filename = "deckmngr" filedesc = "Deck Management" nanomodule_path = /datum/nano_module/deck_management + required_access = list(list(access_cargo, access_bridge)) program_icon_state = "request" program_key_state = "rd_key" program_menu_icon = "clock" @@ -25,8 +26,6 @@ var/datum/computer_file/report/selected_report //A report being viewed/edited. var/list/report_prototypes = list() //Stores report prototypes to use for UI purposes. var/datum/shuttle/prototype_shuttle //The shuttle for which the prototypes were built (to avoid excessive prototype rebuilding) - //The default access needed to properly use. Should be set in map files. - var/default_access = list(access_cargo, access_bridge) //The format is (needs one of list(these access constants or lists of access constants)) /datum/nano_module/deck_management/New() ..() @@ -45,7 +44,6 @@ var/logs = SSshuttle.shuttle_logs data["prog_state"] = prog_state - data["default_access"] = get_default_access(user) switch(prog_state) if(DECK_HOME) @@ -171,11 +169,6 @@ mission_data["queued"] = 1 return mission_data -/datum/nano_module/deck_management/proc/get_default_access(mob/user) - for(var/access_pattern in default_access) - if(check_access(user, access_pattern)) - return 1 - /datum/nano_module/deck_management/proc/get_shuttle_access(mob/user, datum/shuttle/shuttle) return shuttle.logging_access ? (check_access(user, shuttle.logging_access) || check_access(user, access_bridge)) : 0 @@ -211,8 +204,6 @@ if(..()) return 1 - if(!get_default_access(user)) - return 1 //No program access if you don't have the right access. if(text2num(href_list["warning"])) //Gives the user a chance to avoid losing unsaved reports. if(alert(user, "Are you sure you want to do this? Data may be lost.",, "Yes.", "No.") == "No.") return 1 //If yes, proceed to the actual action instead. diff --git a/code/modules/modular_computers/file_system/programs/generic/docks.dm b/code/modules/modular_computers/file_system/programs/generic/docks.dm index ad6fe91d40f..39ab97c28f5 100644 --- a/code/modules/modular_computers/file_system/programs/generic/docks.dm +++ b/code/modules/modular_computers/file_system/programs/generic/docks.dm @@ -1,8 +1,13 @@ /datum/computer_file/program/docking filename = "docking" filedesc = "Docking Control" +<<<<<<< HEAD required_access = access_bridge nanomodule_path = /datum/nano_module/docking +======= + required_access = list(access_bridge) + nanomodule_path = /datum/nano_module/program/docking +>>>>>>> af4c29a77e... Merge pull request #1053 from NataKilar/network-fixes program_icon_state = "supply" program_key_state = "rd_key" program_menu_icon = "triangle-2-e-w" diff --git a/code/modules/modular_computers/file_system/programs/generic/file_browser.dm b/code/modules/modular_computers/file_system/programs/generic/file_browser.dm index 2fd9d99e307..985d210d662 100644 --- a/code/modules/modular_computers/file_system/programs/generic/file_browser.dm +++ b/code/modules/modular_computers/file_system/programs/generic/file_browser.dm @@ -60,10 +60,11 @@ if(!network) return TOPIC_REFRESH // Helper for some user-friendliness. Try to select the first available mainframe. - var/list/file_servers = network.get_file_server_tags() + var/list/file_servers = network.get_file_server_tags(MF_ROLE_FILESERVER, user) + var/datum/file_storage/network/N = current_filesource if(!file_servers.len) + N.server = null // Don't allow players to see files on mainframes they cannot access. return TOPIC_REFRESH - var/datum/file_storage/network/N = current_filesource N.server = file_servers[1] return TOPIC_REFRESH @@ -163,11 +164,11 @@ ui_header = null return TOPIC_REFRESH - if(href_list["PRG_copyto"]) + if(href_list["PRG_transferto"]) . = TOPIC_REFRESH - var/datum/computer_file/F = current_filesource.get_file(href_list["PRG_copyto"]) - if(!F || !istype(F)) - error = "I/O ERROR: Unable to open file." + var/datum/computer_file/F = current_filesource.get_file(href_list["PRG_transferto"]) + if(!F || !istype(F) || F.unsendable) + error = "I/O ERROR: Unable to transfer file." return var/list/choices = list() for(var/T in file_sources) @@ -175,14 +176,14 @@ if(FS == current_filesource) continue choices[FS.name] = FS - var/file_source = input(usr, "Choose a destination storage medium:", "Copy To Another Medium") as null|anything in choices + var/file_source = input(usr, "Choose a destination storage medium:", "Transfer To Another Medium") as null|anything in choices if(file_source) var/datum/file_storage/dst = choices[file_source] var/nope = dst.check_errors() if(nope) - to_chat(user, SPAN_WARNING("Cannot copy file to [dst] for following reason: [nope]")) + to_chat(user, SPAN_WARNING("Cannot transfer file to [dst] for following reason: [nope]")) return - current_transfer = new(current_filesource, dst, F) + current_transfer = new(current_filesource, dst, F, FALSE) ui_header = "downloader_running.gif" /datum/computer_file/program/filemanager/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = GLOB.default_state) @@ -215,7 +216,8 @@ "name" = F.filename, "type" = F.filetype, "size" = F.size, - "undeletable" = F.undeletable + "undeletable" = F.undeletable, + "unsendable" = F.unsendable ))) data["files"] = files @@ -239,12 +241,12 @@ if(QDELETED(current_transfer)) //either completely error = "I/O ERROR: Unknown error during the file transfer." else //or during the saving at the destination - error = "I/O ERROR: Unable to store '[current_transfer.copying.filename]' at [current_transfer.copying_to]" + error = "I/O ERROR: Unable to store '[current_transfer.transferring.filename]' at [current_transfer.transfer_to]" qdel(current_transfer) current_transfer = null ui_header = null return - else if(!current_transfer.left_to_copy) //done + else if(!current_transfer.left_to_transfer) //done QDEL_NULL(current_transfer) ui_header = null diff --git a/code/modules/modular_computers/file_system/programs/generic/ntdownloader.dm b/code/modules/modular_computers/file_system/programs/generic/ntdownloader.dm index 19f07017774..e242b61d4a3 100644 --- a/code/modules/modular_computers/file_system/programs/generic/ntdownloader.dm +++ b/code/modules/modular_computers/file_system/programs/generic/ntdownloader.dm @@ -42,7 +42,7 @@ source.server = net.find_file_location(filename, MF_ROLE_SOFTWARE) if(source.check_errors() || destination.check_errors()) return 0 - current_transfer = new(source, destination, PRG) + current_transfer = new(source, destination, PRG, TRUE) ui_header = "downloader_running.gif" generate_network_log("Downloading file [filename] from [source.server].") @@ -77,11 +77,11 @@ if(QDELETED(current_transfer)) //either completely downloaderror = "I/O ERROR: Unknown error during the file transfer." else //or during the saving at the destination - downloaderror = "I/O ERROR: Unable to store '[current_transfer.copying.filename]' at [current_transfer.copying_to]" + downloaderror = "I/O ERROR: Unable to store '[current_transfer.transferring.filename]' at [current_transfer.transfer_to]" qdel(current_transfer) current_transfer = null ui_header = "downloader_finished.gif" - else if(!current_transfer.left_to_copy) //done + else if(!current_transfer.left_to_transfer) //done QDEL_NULL(current_transfer) ui_header = "downloader_finished.gif" if(!current_transfer && downloads_queue.len > 0) @@ -94,7 +94,7 @@ if(href_list["PRG_downloadfile"]) if(!current_transfer) begin_file_download(href_list["PRG_downloadfile"]) - else if(check_file_download(href_list["PRG_downloadfile"]) && !downloads_queue.Find(href_list["PRG_downloadfile"]) && current_transfer.copying.filename != href_list["PRG_downloadfile"]) + else if(check_file_download(href_list["PRG_downloadfile"]) && !downloads_queue.Find(href_list["PRG_downloadfile"]) && current_transfer.transferring.filename != href_list["PRG_downloadfile"]) downloads_queue |= href_list["PRG_downloadfile"] return 1 if(href_list["PRG_removequeued"]) @@ -123,7 +123,7 @@ if(prog.current_transfer) // Download running. Wait please.. data |= prog.current_transfer.get_ui_data() data["downloadspeed"] = prog.current_transfer.get_transfer_speed() - var/datum/computer_file/program/P = prog.current_transfer.copying + var/datum/computer_file/program/P = prog.current_transfer.transferring if(istype(P)) data["transfer_desc"] = P.extended_desc diff --git a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm index 1d5b9ed4f6f..ff8a69ac0ba 100644 --- a/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm +++ b/code/modules/modular_computers/file_system/programs/generic/ntnrc_client.dm @@ -87,7 +87,7 @@ channel = null return 1 var/mob/living/user = usr - if(can_run(usr, 1, access_network)) + if(can_run(usr, 1, list(access_network))) if(channel) var/response = alert(user, "Really engage admin-mode? You will be disconnected from your current channel!", "NTNRC Admin mode", "Yes", "No") if(response == "Yes") diff --git a/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm b/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm index 2fb66027382..5616512c7ef 100644 --- a/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm +++ b/code/modules/modular_computers/file_system/programs/medical/suit_sensors.dm @@ -7,7 +7,7 @@ program_key_state = "med_key" program_menu_icon = "heart" extended_desc = "This program connects to life signs monitoring system to provide basic information on crew health." - required_access = access_medical + required_access = list(access_medical) network_destination = "crew lifesigns monitoring system" size = 11 category = PROG_MONITOR diff --git a/code/modules/modular_computers/file_system/programs/research/ai_restorer.dm b/code/modules/modular_computers/file_system/programs/research/ai_restorer.dm index f8477812c32..4f6ff3761e5 100644 --- a/code/modules/modular_computers/file_system/programs/research/ai_restorer.dm +++ b/code/modules/modular_computers/file_system/programs/research/ai_restorer.dm @@ -6,7 +6,7 @@ program_menu_icon = "person" extended_desc = "This program is capable of reconstructing damaged AI systems. It can also be used to upload basic laws to the AI. Requires direct AI connection via inteliCard slot." size = 12 - required_access = access_bridge + required_access = list(access_bridge) requires_access_to_run = 0 available_on_network = 1 nanomodule_path = /datum/nano_module/program/computer_aidiag/ diff --git a/code/modules/modular_computers/file_system/programs/research/email_administration.dm b/code/modules/modular_computers/file_system/programs/research/email_administration.dm index 9ddbc33c038..8e3d1d5f7db 100644 --- a/code/modules/modular_computers/file_system/programs/research/email_administration.dm +++ b/code/modules/modular_computers/file_system/programs/research/email_administration.dm @@ -9,7 +9,7 @@ requires_network = 1 available_on_network = 1 nanomodule_path = /datum/nano_module/program/email_administration - required_access = access_network + required_access = list(access_network) category = PROG_ADMIN /datum/nano_module/program/email_administration diff --git a/code/modules/modular_computers/file_system/programs/security/digitalwarrant.dm b/code/modules/modular_computers/file_system/programs/security/digitalwarrant.dm index 9508d7f2876..cd5e9e93efe 100644 --- a/code/modules/modular_computers/file_system/programs/security/digitalwarrant.dm +++ b/code/modules/modular_computers/file_system/programs/security/digitalwarrant.dm @@ -10,7 +10,7 @@ GLOBAL_LIST(all_warrants) program_menu_icon = "star" requires_network = 1 available_on_network = 1 - required_access = access_security + required_access = list(access_security) nanomodule_path = /datum/nano_module/program/digitalwarrant/ category = PROG_SEC diff --git a/code/modules/modular_computers/file_system/programs/security/forceauthorization.dm b/code/modules/modular_computers/file_system/programs/security/forceauthorization.dm index 994779e2476..01e5cc1c4d7 100644 --- a/code/modules/modular_computers/file_system/programs/security/forceauthorization.dm +++ b/code/modules/modular_computers/file_system/programs/security/forceauthorization.dm @@ -8,7 +8,7 @@ program_menu_icon = "locked" requires_network = 1 available_on_network = 1 - required_access = access_armory + required_access = list(access_armory) nanomodule_path = /datum/nano_module/program/forceauthorization/ category = PROG_SEC diff --git a/code/modules/modular_computers/file_system/reports/crew_record.dm b/code/modules/modular_computers/file_system/reports/crew_record.dm index 7126080ca79..5002c62eabd 100644 --- a/code/modules/modular_computers/file_system/reports/crew_record.dm +++ b/code/modules/modular_computers/file_system/reports/crew_record.dm @@ -32,10 +32,10 @@ GLOBAL_VAR_INIT(arrest_security_status, "Arrest") for(var/weakref/grant in grants) var/datum/computer_file/data/grant_record/GR = grant.resolve() if(!GR) - grants -= GR + grants -= grant continue if(GR.stored_data == grant_name) - grants -= GR + grants -= grant return /datum/computer_file/report/crew_record/proc/calculate_size() diff --git a/code/modules/modular_computers/networking/device_types/acl.dm b/code/modules/modular_computers/networking/device_types/acl.dm index f209d13669a..6f860939c0f 100644 --- a/code/modules/modular_computers/networking/device_types/acl.dm +++ b/code/modules/modular_computers/networking/device_types/acl.dm @@ -2,6 +2,17 @@ connection_type = NETWORK_CONNECTION_WIRED var/list/administrators = list() // A list of numerical user IDs of users that are administrators on a network. + var/program_control = FALSE // Whether the ACL controls program access or not. + var/list/program_access = list() // List of lists containing perimitted accesses for programs. + +/datum/extension/network_device/acl/New() + . = ..() + for(var/prog_type in subtypesof(/datum/computer_file/program)) + var/datum/computer_file/program/prog = prog_type + if(!initial(prog.available_on_network)) + continue + program_access[initial(prog.filename)] = list() + /datum/extension/network_device/acl/proc/add_admin(var/user_id) administrators |= user_id @@ -22,4 +33,13 @@ var/list/grant_files = network.get_all_files_of_type(/datum/computer_file/data/grant_record, MF_ROLE_CREW_RECORDS, TRUE) for(var/datum/computer_file/data/grant_record/GR in grant_files) grants |= GR - return grants \ No newline at end of file + return grants + +/datum/extension/network_device/acl/proc/get_program_access(var/program_name) + if(!length(program_access[program_name])) + return list() + . = list() + for(var/access in program_access[program_name]) + . += uppertext("[network_id].[access]") + + return list(.) \ No newline at end of file diff --git a/code/modules/modular_computers/networking/machinery/acl.dm b/code/modules/modular_computers/networking/machinery/acl.dm index bf013d700dc..9b5b9b2c617 100644 --- a/code/modules/modular_computers/networking/machinery/acl.dm +++ b/code/modules/modular_computers/networking/machinery/acl.dm @@ -13,6 +13,7 @@ // Datum file source for where grants/records are. var/datum/file_storage/network/file_source = /datum/file_storage/network/machine var/editing_user // Numerical user ID of the user being editing on this device. + var/editing_program // Name of current program being edited. var/list/initial_grants //defaults to all possible station accesses if left null /obj/machinery/network/acl/merchant @@ -67,6 +68,7 @@ if(href_list["back"]) editing_user = null + editing_program = null return TOPIC_REFRESH if(href_list["change_file_server"]) @@ -82,18 +84,43 @@ if(!grant) error = "ERROR: Grant record not found." return TOPIC_REFRESH - var/datum/computer_file/report/crew_record/AR = get_access_record() - if(!AR) - error = "ERROR: Access record not found." + if(editing_user) + var/datum/computer_file/report/crew_record/AR = get_access_record() + if(!AR) + error = "ERROR: Access record not found." + return TOPIC_REFRESH + AR.add_grant(grant) + else if(editing_program) + var/list/program_access = computer.program_access[editing_program] + program_access |= grant.stored_data return TOPIC_REFRESH - AR.add_grant(grant) if(href_list["remove_grant"]) - var/datum/computer_file/report/crew_record/AR = get_access_record() - if(!AR) - error = "ERROR: Access record not found." + if(editing_user) + var/datum/computer_file/report/crew_record/AR = get_access_record() + if(!AR) + error = "ERROR: Access record not found." + return TOPIC_REFRESH + AR.remove_grant(href_list["remove_grant"]) // Add the grant to the record. + if(editing_program) + var/datum/computer_file/data/grant_record/grant = computer.get_grant(href_list["remove_grant"]) + if(!grant) + error = "ERROR: Grant record not found." + return TOPIC_REFRESH + var/list/program_access = computer.program_access[editing_program] + program_access -= grant.stored_data return TOPIC_REFRESH - AR.remove_grant(href_list["remove_grant"]) // Add the grant to the record. + + if(href_list["clear_program_access"]) + if(editing_program) + computer.program_access[editing_program] = list() + else + error = "ERROR: Program not found." + return TOPIC_REFRESH + + if(href_list["toggle_program_control"]) + computer.program_control = !computer.program_control + return TOPIC_REFRESH if(href_list["create_grant"]) var/new_grant_name = uppertext(sanitize(input(usr, "Enter the name of the new grant:", "Create Grant"))) @@ -112,6 +139,18 @@ if(href_list["view_user"]) editing_user = href_list["view_user"] + editing_program = null + return TOPIC_REFRESH + + if(href_list["view_program"]) + var/prog = href_list["view_program"] + var/list/programs = computer.program_access + if(!(prog in programs)) + error = "ERROR: Program not found." + return TOPIC_REFRESH + editing_program = prog + editing_user = null + return TOPIC_REFRESH if(href_list["write_id"]) var/obj/item/stock_parts/computer/card_slot/card_slot = get_component_of_type(/obj/item/stock_parts/computer/card_slot) @@ -162,6 +201,7 @@ .["connected"] = TRUE .["file_server"] = file_source.server .["editing_user"] = editing_user + .["editing_program"] = editing_program // Let's build some data. if(editing_user) @@ -185,6 +225,17 @@ "assigned" = (GR in assigned_grants) ))) .["grants"] = grants + else if(editing_program) // Editing program access. + .["program_name"] = editing_program + var/list/program_access = computer.program_access[editing_program] + var/list/grants[0] + .["cleared_control"] = !length(program_access) + for(var/datum/computer_file/data/grant_record/GR in computer.get_all_grants()) + grants.Add(list(list( + "grant_name" = GR.stored_data, + "assigned" = (GR.stored_data in program_access) + ))) + .["grants"] = grants else // We're looking at all records. Or lack thereof. var/list/users[0] @@ -196,6 +247,14 @@ "size" = AR.size ))) .["users"] = users + var/list/programs[0] + .["program_control"] = computer.program_control + for(var/prog_name in computer.program_access) + programs.Add(list(list( + "name" = prog_name, + "grants" = length(computer.program_access[prog_name]) + ))) + .["programs"] = programs /obj/machinery/network/acl/proc/get_all_users() var/list/users = list() diff --git a/code/modules/modular_computers/networking/machinery/mainframe.dm b/code/modules/modular_computers/networking/machinery/mainframe.dm index cc284c48a0c..2d4660d7c6c 100644 --- a/code/modules/modular_computers/networking/machinery/mainframe.dm +++ b/code/modules/modular_computers/networking/machinery/mainframe.dm @@ -46,10 +46,4 @@ if(href_list["toggle_role"]) var/datum/extension/network_device/mainframe/M = get_extension(src, /datum/extension/network_device) M.toggle_role(href_list["toggle_role"]) - return TOPIC_REFRESH - -/obj/machinery/network/mainframe/on_update_icon() - if(operable()) - icon_state = "blackbox" - else - icon_state = "blackbox_off" \ No newline at end of file + return TOPIC_REFRESH \ No newline at end of file diff --git a/code/modules/modular_computers/ntos/files.dm b/code/modules/modular_computers/ntos/files.dm index 042ece4a948..6aec57a2f95 100644 --- a/code/modules/modular_computers/ntos/files.dm +++ b/code/modules/modular_computers/ntos/files.dm @@ -112,7 +112,7 @@ /datum/file_storage/proc/get_file(filename) -/datum/file_storage/proc/store_file(datum/computer_file/F) +/datum/file_storage/proc/store_file(datum/computer_file/F, copied) /datum/file_storage/proc/save_file(filename, new_data) @@ -167,9 +167,10 @@ var/datum/extension/network_device/mainframe/M = get_mainframe() return M && M.get_file(filename) -/datum/file_storage/network/store_file(datum/computer_file/F) +/datum/file_storage/network/store_file(datum/computer_file/F, copied) + var/datum/computer_file/stored = copied ? F.clone() : F var/datum/extension/network_device/mainframe/M = get_mainframe() - return M && M.store_file(F) + return M && M.store_file(stored) /datum/file_storage/network/delete_file(filename) var/datum/extension/network_device/mainframe/M = get_mainframe() @@ -246,10 +247,11 @@ return FALSE return os.get_file(filename, get_disk()) -/datum/file_storage/disk/store_file(datum/computer_file/F) +/datum/file_storage/disk/store_file(datum/computer_file/F, copied) + var/datum/computer_file/stored = copied ? F.clone() : F if(check_errors()) return FALSE - return os.store_file(F, get_disk()) + return os.store_file(stored, get_disk()) /datum/file_storage/disk/save_file(filename, new_data) if(check_errors()) @@ -272,7 +274,7 @@ /datum/file_storage/disk/removable/get_disk() var/obj/item/stock_parts/computer/drive_slot/drive_slot = os.get_component(PART_D_SLOT) - return drive_slot.stored_drive + return drive_slot?.stored_drive /datum/file_storage/disk/removable/check_errors() . = ..() @@ -287,25 +289,27 @@ // Datum tracking progress between of file transfer between two file streams /datum/file_transfer - var/datum/file_storage/copying_from - var/datum/file_storage/copying_to - var/datum/computer_file/copying - var/left_to_copy - -/datum/file_transfer/New(datum/file_storage/source, datum/file_storage/destination, datum/computer_file/file) - copying_from = source - copying_to = destination - copying = file - left_to_copy = file.size + var/datum/file_storage/transfer_from + var/datum/file_storage/transfer_to + var/datum/computer_file/transferring + var/left_to_transfer + var/copying = FALSE // Whether or not this file transfer is copying, rather than transferring. + +/datum/file_transfer/New(datum/file_storage/source, datum/file_storage/destination, datum/computer_file/file, copy) + transfer_from = source + transfer_to = destination + transferring = file + left_to_transfer = file.size + copying = copy /datum/file_transfer/Destroy() - copying_from = null - copying_to = null - copying = null + transfer_from = null + transfer_to = null + transferring = null . = ..() /datum/file_transfer/proc/check_self() - if(QDELETED(copying_from) || QDELETED(copying_from) || QDELETED(copying)) + if(QDELETED(transfer_from) || QDELETED(transfer_from) || QDELETED(transferring)) qdel(src) return FALSE return TRUE @@ -315,27 +319,35 @@ . = check_self() if(!.) return - left_to_copy = max(0, left_to_copy - get_transfer_speed()) - if(!left_to_copy) - return copying_to.store_file(copying) + left_to_transfer = max(0, left_to_transfer - get_transfer_speed()) + if(!left_to_transfer) + if(copying) + return transfer_to.store_file(transferring, TRUE) + else + . = transfer_from.delete_file(transferring.filename) // Check if we can delete the file. + if(.) + . = transfer_to.store_file(transferring, FALSE) + // If we failed to store the file, restore it to its former location. + if(!.) + transfer_from.store_file(transferring, FALSE) /datum/file_transfer/proc/get_transfer_speed() if(!check_self()) return 0 - return min(copying_from.get_transfer_speed(), copying_to.get_transfer_speed()) + return min(transfer_from.get_transfer_speed(), transfer_to.get_transfer_speed()) /datum/file_transfer/proc/get_eta() if(!check_self() || !get_transfer_speed()) return INFINITY - return round(left_to_copy / get_transfer_speed()) + return round(left_to_transfer / get_transfer_speed()) /datum/file_transfer/proc/get_ui_data() if(!check_self()) return var/list/data = list() - data["transfer_from"] = copying_from.name - data["transfer_to"] = copying_to.name - data["transfer_file"] = copying.filename - data["transfer_progress"] = copying.size - left_to_copy - data["transfer_total"] = copying.size + data["transfer_from"] = transfer_from.name + data["transfer_to"] = transfer_to.name + data["transfer_file"] = transferring.filename + data["transfer_progress"] = transferring.size - left_to_transfer + data["transfer_total"] = transferring.size return data \ No newline at end of file diff --git a/code/modules/modular_computers/ntos/ntos.dm b/code/modules/modular_computers/ntos/ntos.dm index f6fc66dcd9c..8cce083ddf3 100644 --- a/code/modules/modular_computers/ntos/ntos.dm +++ b/code/modules/modular_computers/ntos/ntos.dm @@ -113,10 +113,11 @@ if(P in running_programs) P.program_state = PROGRAM_STATE_ACTIVE active_program = P - else if(P.can_run(user, 1)) + else if(P.can_run(user, 1, null, get_network())) P.on_startup(user, src) active_program = P - + else + return running_programs |= P update_host_icon() return 1 diff --git a/maps/tradeship/tradeship_overrides.dm b/maps/tradeship/tradeship_overrides.dm index 692ee998e31..683df6085b0 100644 --- a/maps/tradeship/tradeship_overrides.dm +++ b/maps/tradeship/tradeship_overrides.dm @@ -1,5 +1,5 @@ /datum/computer_file/program/merchant/tradeship - required_access = null + required_access = list() /obj/machinery/computer/modular/preset/merchant/tradeship default_software = list( diff --git a/nano/templates/deck_management.tmpl b/nano/templates/deck_management.tmpl index 85450862550..8246ce9ad74 100644 --- a/nano/templates/deck_management.tmpl +++ b/nano/templates/deck_management.tmpl @@ -1,11 +1,3 @@ -
- You - {{if !data.default_access}} - do not - {{/if}} - have program access. -
-{{if data.default_access}} {{if data.prog_state == 1}}

Shuttles:

{{for data.shuttles}} @@ -279,4 +271,3 @@ {{/if}} {{/if}} -{{/if}} diff --git a/nano/templates/file_manager.tmpl b/nano/templates/file_manager.tmpl index d0558f468f9..4c9608d0f3d 100644 --- a/nano/templates/file_manager.tmpl +++ b/nano/templates/file_manager.tmpl @@ -51,7 +51,7 @@ {{:helper.link('DELETE', null, { "PRG_deletefile" : value.name }, value.undeletable ? 'disabled' : null)}} {{:helper.link('RENAME', null, { "PRG_rename" : value.name }, value.undeletable ? 'disabled' : null)}} {{:helper.link('CLONE', null, { "PRG_clone" : value.name }, value.undeletable ? 'disabled' : null)}} - {{:helper.link('COPY TO', null, { "PRG_copyto" : value.name }, value.undeletable ? 'disabled' : null)}} + {{:helper.link('TRANSFER TO', null, { "PRG_transferto" : value.name }, value.unsendable ? 'disabled' : null)}} {{/for}} {{if data.usbconnected}} diff --git a/nano/templates/network_acl.tmpl b/nano/templates/network_acl.tmpl index aa985571d60..ff3db28d5c2 100644 --- a/nano/templates/network_acl.tmpl +++ b/nano/templates/network_acl.tmpl @@ -62,6 +62,24 @@ {{/for}} {{:helper.link('Back to menu', null, { "back" : 1 })}} + {{else data.editing_program}} +

Editing Program: {{:data.program_name}}

+
+ + {{:helper.link('REMOVE ACCESS REQUIREMENT', null, { "clear_program_access" : 1}, data.cleared_control ? 'selected' : null)}} +
Grant + Operations + {{for data.grants}} +
{{:value.grant_name}} + + {{if value.assigned}} + {{:helper.link('REMOVE', null, { "remove_grant" : value.grant_name })}} + {{else}} + {{:helper.link('ASSIGN', null, { "assign_grant" : value.grant_name })}} + {{/if}} + {{/for}} +
+ {{:helper.link('Back to menu', null, { "back" : 1 })}} {{else}}

Available Users ({{:data.file_server}}):

@@ -77,6 +95,24 @@ {{:helper.link('VIEW', null, { "view_user" : value.user_id })}} {{/for}}
+
+

Available Programs:

+ {{if data.program_control}} + {{:helper.link('DISABLE PROGRAM ACCESS CONTROL', null, { "toggle_program_control" : 1})}} + +
Program + Grants + Access + {{for data.programs}} +
{{:value.name}} + {{:value.grants}} + + {{:helper.link('EDIT', null, { "view_program" : value.name})}} + {{/for}} +
+ {{else}} + {{:helper.link('ENABLE PROGRAM ACCESS CONTROL', null, { "toggle_program_control" : 1})}} + {{/if}} {{/if}} {{/if}} {{/if}} \ No newline at end of file