├── .github
└── ISSUE_TEMPLATE
│ └── bug_report.md
├── .gitignore
├── .vs
├── opencomputer-security-system
│ ├── FileContentIndex
│ │ └── read.lock
│ └── v17
│ │ └── .wsuo
└── slnx.sqlite
├── .vscode
└── settings.json
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── doorsetup
├── door.lua
└── finish.lua
├── modules.txt
├── permissions.txt
├── remotecontrol
└── main.lua
├── sectors
├── Database Module
│ └── Main.lua
├── Server Module
│ └── sectors.lua
├── sectorcontrol.lua
└── sectorcontrolgui.lua
├── security
├── Database Module
│ ├── Main.lua
│ ├── Pass.lua
│ └── User.lua
├── Server Module
│ └── security.lua
├── autoinstaller.lua
├── diagnostic.lua
├── doorControl.lua
├── quikidlink.lua
└── securityAPI.lua
└── whattodo.txt
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | What should it be doing?
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Mod versions:**
27 | -Open Computers version: #
28 | -Open Security version: #
29 |
30 | **Other Mods (optional in case it's being used as part of a system**
31 |
32 | **Additional context**
33 | Add any other context about the problem here.
34 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 |
3 | .vs/VSWorkspaceState.json
4 | .vs/slnx.sqlite
5 | .vs/opencomputer-security-system/v17/.wsuo
6 | *.sqlite
7 | *.vsidx
8 | *.sqlite
9 | .vs/slnx.sqlite
10 | .vs/opencomputer-security-system/v17/.wsuo
11 | .vs/opencomputer-security-system/FileContentIndex/9d9cebae-4c71-423c-bb87-e5d813dec504.vsidx
12 |
--------------------------------------------------------------------------------
/.vs/opencomputer-security-system/FileContentIndex/read.lock:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/731bf46fc76339673a55b87a03d83d6ccc009c3a/.vs/opencomputer-security-system/FileContentIndex/read.lock
--------------------------------------------------------------------------------
/.vs/opencomputer-security-system/v17/.wsuo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/731bf46fc76339673a55b87a03d83d6ccc009c3a/.vs/opencomputer-security-system/v17/.wsuo
--------------------------------------------------------------------------------
/.vs/slnx.sqlite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/731bf46fc76339673a55b87a03d83d6ccc009c3a/.vs/slnx.sqlite
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "githubPullRequests.ignoredPullRequestBranches": [
3 | "main"
4 | ]
5 | }
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | If you wish to contribute, there are a few things to remember
2 | 1. Minor changes that don't really affect every single program change the third number (2.2.1 goes to 2.2.2) This means that all numbers are compatable with eachother (a 2.2.0 server works with a 2.2.2 door)
3 | 2. Major changes that cause every device to need an update or be on the same version need the second number changed (2.2.1 goes to 2.3.0)
4 | 3. Version changes to the door control likely need a version checking update in the diagnostic tablet. I'll be happy enough to do this part for you however, so it isn't that important.
5 | 4. The autoinstaller and anything that downloads code from the web download from the main branch, so if you are testing a doorcontrol and autoinstaller update, you will have to wget the new code yourself afterward
6 |
7 | In order to contribute, you just have to fork the repository, make the necessary changes, and when you think it's good enough, pull request in.
8 | I will fix or perform changes in the following conditions:
9 | 1. Diagnostic tablet versioning (if you don't make any changes to the diagnostic tablet, I'll add the version number myself)
10 | 2. The bug is minor enough that I can easilly spot it
11 |
12 | I will not fix or do changes myself on the following:
13 | 1. You need help coding a certain part of the program
14 | 2. The bug is very well hidden (eg: I cannot see the problem easily)
15 |
16 | I might add more to this later when I figure out what else I need.
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # opensecurity-security-system
2 |
3 | A Fully fleshed out Security System solution for OpenComputers and OpenSecurity using the servertine system.
4 |
5 | Featuring...
6 |
7 | - Multiple door controlling with a single door computer
8 | - Powerful passes system you set up yourself
9 | - Security card blocking and disabling from the database
10 | - Easy door creation using the Autoinstaller or door creation module
11 | - Easy door editing, installing, and diagnostics with the diagnostic program
12 | - Long-range data transfer with built-in support for servertine's range extender program
13 | - Modularity with a modified servertine API with support for changing user card data
14 | - Optional modules you can play with that interface with your system (like Sectors module)
15 | - And much more!
16 |
17 |
18 | If you have used this before, you may be wondering, "what's servertine?" I split up the server and database from the security system and am making them into a new project called "Servertine", which is a powerful system you can create powerful modules for and easilly connect to them using the servertine API. They also support other features like the range extender. The reason being for this is an API I can easilly build more programs off of and ease of updating the existing passes system. The move to a modular system brings no drawbacks to the system as well.
19 |
20 | Download servertine here
21 | Join the Servertine discord
22 |
23 | I will be making a full video tutorial series soon. Channel is here
24 |
25 | ----Server: The brain of the system. Install the security module onto the servertine server and keep it running and everything is handled for you! it stores user data as well as pass data and handles the logic for doorcontrol systems.
26 |
27 | ----Database: Where you modify the system parameters. Install the Servertine Database on MineOS and install the security module and manage users, passes, and such with ease and speed.
28 |
29 | ----Door Control: Control security door and redstone from these convenient door systems! Easy to set up and easy to change settings with, these really have it all.
30 |
31 | Autoinstaller setup: Run the command "pastebin run cP70MhB0" and follow the prompts. Syncs nicely with the accelerated door setup program on the diagnostic tablet to allow for scanning of the doors and readers instead of copying the uuid with an analyzer.
32 |
33 | Door Setup module setup: Setup the passes and simple settings on the database, install the stuff onto a drive, and finish on the computer.
34 |
35 | ----Autoinstaller: Install the doors with ths simple autoinstaller! Just follow the prompts
36 |
37 | pastebin run cP70MhB0
38 |
39 | ----Diagnostic tablet: A program with a whole bunch of programs to make door setup, management, and more easier
40 |
41 | Diagnostics: a special program that works with the new admin card to get info about a door and it's settings and if it works. It is best used with a tablet that has a tier 2 gpu, a wireless modem, and an internet card. When the admin card is scanned, it sends all the info of the computer to the tablet. It's most noteable use is with the multidoor computer, as it tells you if that magnetic card reader is connected to a door, what the key of the door is (if you want to edit door settings after first set up) and more.
42 |
43 | Accelerated door setup program to put on a tablet. This helps accelerate multi-door setup time, as it is portable compared to moving back and forth between the pc and the door. Also, if your tablet has an analyzer with it, you can scan the blocks with the tablet instead of just entering the uuid manually
44 |
45 | Door editing: Lets you edit doors with amazing ease. Just swipe the door with an admin card and change settings, add/delete doors, and more. Is a major game changer compared to autoinstaller door editing.
46 |
47 | Remote Control: Open and close doors from any distance without having to swipe cards. You get access to every single door linked to the server. This also lets you open doors contrary to what the settings are set to for the door, like toggling doors that would normally be delayed.
48 |
49 | ----Security API is a modified version of the Servertine API, with locked data that is sent to the server, ability to check passes from a card that is swiped, and get and set variables in user accounts (if string)
50 |
51 | ----Optional modules for more functionality
52 |
53 | Sector system- Give doors groups which you can manage with the sector control computer. Lock doors open or lock them shut and let certain passes either bypass these or turn them off.
54 |
55 | If you have any questions, don't hesitate to ask!
56 |
57 | Tutorial playlist here (older videos may be outdated)
58 |
59 | 
60 | 
61 | 
62 |
63 | Changelog: Before splitting off
64 |
65 | - 2.1.0: Completely from scratch work for door now out with full modular support! 3/15
66 | - 2.1.1: Bug fixes I believe... 3/23
67 | - 2.1.2: Door control bug fix: deleting a pass no longer breaks all doors. After update, doors should fix it themselves. 3/28
68 | - 2.2.0: Multiple Pass update: You can now use multiple passes on the same door control, with advanced checks and such! 4/6
69 | - 2.2.0 Side update 1: Created the securityAPI. Information in wiki 4/11
70 |
- 2.2.0 Side update 2: Improved diagnostic tablet with a simple user interface; Moved accelerated door setup code to the diagnostic tablet
71 |
- 2.2.1 Diagnostics update: Accelerated door setup and diagnostics are combined to one tablet with easy to use controls. Works with both 2.2.0 and 2.2.1 and future doors (2.2.1 and up allow you to see every door configuration on multi-doors) 4/30
72 | - 2.2.2 Runtime Editing update: Added the editor to the diagnostic tablet program, so you can now swipe the admin card in the door control and edit all the doors without having to use the autoinstaller! (Does not include pass editing which still requires the autoinstaller atm) Works with 2.2.2 and up Only. Also changed uuid resetting button to show a yes/no page. 5/18
73 | - 2.3.0 Functional string update: String and HiddenStrings can now be grabbed and set via the securityAPI. This allows you to make custom programs using it (such as a door you can only use 3 times, etc.) This gives a use for the hidden string, as it is now a string value unable to be edited in the database. Get and set with securityapi only works with strings, not int, group, or bool. Check SecurityAPI wiki page for more info. MineOS database now downloads userTable from server on reboot instead of using the one already saved on the database in order to avoid resetting string values set on the server. mineos also has option to turn on and off autoupdate (in dbsettings.txt in app folder) 5/30
74 | - 2.3.1 QOL update: MineOS database now has lang file support as well as a dark style you can enable in dbsettings. Diagnostic tablet's editing mode can now add and delete doors and change the pass settings 6/26
75 | - 2.3.2 Remote Control update: Diagnostic tablet can now remote control doors! Either toggle a door open/closed or open with a delay. Server must be updated to version 2.3.2, but doors may not have to be updated (still recommended) 7/12
76 | - 2.4.0 Sector Update: Replaced the useless forceOpen and bypassLock settings with the new sectors system. You can create however many sectors you like in the mineOS database and set doors to that sector. Then, with the new sectorcontrol program, you can control sectors with redstone, locking them down or locking them open. Certain passes can also be set to open locked down doors or just bypass the lockdown! This also comes with the range extender program for doorcontrols and modules system to build in your own programs to be part of the server. Server also got a GUI upgrade and autoinstaller can install servers and modules. 7/26
77 | - 3.0.0 Servertine split: Split up the security system with the server and database. They are now modules. 9/16
78 | - 3.0.1 Door Editor: Edit door settings with this handy module and save it to an external drive! Now easilly set up doors to an extent BEFORE putting it in the computer! 10/27
79 | - 4.0.0 Servertine movement & QOL: Lots of bug fixes and stuff. Added crypting support to lots of stuff which didn't have it for extra security. Changed groups to use dropdown and ints (level) to have a text box input as well. DoorSetup now saves progress if you leave that module and go back. Major sectorcontrol changes. Added support for Biometric Reader. MOOORE
80 | - 4.0.2 (yes I skipped one) Major refinement update: Security module now has 2 tabs in it, which split up setting up the users and pass management. Keypad and RFID Reader support. TONS MORE
81 |
82 |
83 | Seperate Changelogs (Using format on website of incrementing it by a digit)
84 |
85 | Security:
86 |
87 | - Setup module on website (right before version 4.0.0 on above changelog)
88 | - Biometrics, unblocked some extra features, pretty much update 4.0.0
89 | - Minor bug fix for callback int on certain buttons
90 | - Split module into multiple files and such (exact same as version 4.0.2)
91 | - Accidental duplication of previous update (whoops)
92 | - Fixed rcdoors command sending every device even if not a doorsystem. Added sector control program to the diagnostic tablet. Readded the ability to change readers using runtime door editing
93 |
94 | Sector:
95 |
96 | - Setup module on website (right before version 4.0.0 on above changelog)
97 | - Sector control overhaul (Exact same as update version 4.0.0)
98 | - Updated to support latest Security module version (exact same as update version 4.0.2)
99 | - Accidental duplication of previous update (what is wrong with meeee)
100 |
101 | Door Editing:
102 |
103 | - Setup module on website (right before version 4.0.0 on above changelog)
104 | - Fixed a bug with path towards the finish.lua (finishing program) file
105 | - Progress is saved when switching modules from this one, updating finish.lua to work with biometrics, etc. (Exact same as version 4.0.0)
106 | - Updated to support latest Security module version (exact same as update version 4.0.2)
107 | - Hotfixed loadTable function to use compat file rather than built in one (which didn't support OpenOS)
108 | - Added the ability to reset the progress in case you need it. Databackup also resets if you export the door.
109 |
110 | Remote Control:
111 |
112 | - Released Remote Control!
113 |
114 |
115 | Queued updates:
116 |
117 | - none queued yet
118 |
119 |
120 | Future updates:
121 |
122 | - none queued yet
123 |
124 |
125 | Important information:
126 | If you have anything you would like to try adding yourself, feel free to add whatever you want to the code and pull request it into the main branch. I can then check if it's a worthwhile update and merge.
127 |
--------------------------------------------------------------------------------
/doorsetup/finish.lua:
--------------------------------------------------------------------------------
1 | --The program installed on a drive by the doorsetup module to finish up setup on the pc
2 | local component = require("component")
3 | local term = require("term")
4 | local io = require("io")
5 | local ser = require("serialization")
6 | local fs = require("filesystem")
7 | local shell = require("shell")
8 | local event = require("event")
9 | local uuid = require("uuid")
10 | local thread = require("thread")
11 | local modem = component.modem
12 | local link
13 | local modemPort = 1000
14 | local syncPort = 199
15 | local diagPort = 180
16 |
17 | local program = "ctrl.lua"
18 | local settingFileName = "doorSettings.txt"
19 | local configFileName = "extraConfig.txt"
20 | local doorCode = "https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/main/security/doorControl.lua"
21 |
22 | local settingData = {}
23 | local randomNameArray = {"q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "a", "s", "d", "f", "g", "h", "j", "k", "l", "z", "x", "c", "v", "b", "n", "m"}
24 | local commandArray = {"getInput","analyzer","clearTerm","terminate","advanalyzer"}
25 |
26 | local query = {["num"]=0}
27 | local editorSettings = {}
28 |
29 | local function saveTable(table, location)
30 | --saves a table to a file
31 | local tableFile = assert(io.open(location, "w"))
32 | tableFile:write(ser.serialize(table))
33 | tableFile:close()
34 | end
35 | local function loadTable(location)
36 | --returns a table stored in a file.
37 | local tableFile = assert(io.open(location))
38 | return ser.unserialize(tableFile:read("*all"))
39 | end
40 |
41 | local function send(label,port,linker,...)
42 | if linker and link ~= nil then
43 | link.send(modem.address,...)
44 | return
45 | end
46 | if label then
47 | modem.send(label,port,...)
48 | else
49 | modem.broadcast(port,...)
50 | end
51 | end
52 |
53 | local function sendMsg(...)
54 | local arg = table.pack(...)
55 | for i=1,#arg,1 do
56 | local argType = type(arg[i])
57 | if editorSettings.accelerate == true then
58 | if argType == "string" then
59 | send(editorSettings.from,editorSettings.port,false,"print",arg[i])
60 | elseif argType == "number" then
61 | send(editorSettings.from,editorSettings.port,false,commandArray[arg[i]])
62 | if arg[i] < 3 then
63 | local e, _, _, _, _, text = event.pull("modem_message")
64 | return text
65 | end
66 | if arg[i] == 4 then
67 | print("terminated connection")
68 | end
69 | if arg[i] == 5 then
70 | local wait = true
71 | local distable = {}
72 | while wait do
73 | local e, _, _, _, _, text = event.pull("modem_message")
74 | if text == "finished" then
75 | return distable
76 | else
77 | table.insert(distable,text)
78 | end
79 | end
80 | end
81 | else
82 | send(editorSettings.from,editorSettings.port,false,"print","potential error in code for sendMsg")
83 | end
84 | else
85 | if argType == "string" then
86 | print(arg[i])
87 | elseif argType == "number" then
88 | if arg[i] == 1 then
89 | local text = term.read()
90 | return text:sub(1,-2)
91 | elseif arg[i] == 2 then
92 | return "nil"
93 | elseif arg[i] == 3 then
94 | term.clear()
95 | elseif arg[i] == 4 then
96 | print("Finished editing.")
97 | elseif arg[i] == 5 then
98 | local wait = true
99 | local distable = {}
100 | while wait do
101 | local text = term.read()
102 | text = text:sub(1,-2)
103 | if text == "" then
104 | return distable
105 | else
106 | table.insert(distable,text)
107 | end
108 | end
109 | else
110 | print("potential error in code for sendMsg")
111 | end
112 | end
113 | end
114 | end
115 | return true
116 | end
117 |
118 | term.clear()
119 | print("Checking for finishing file...")
120 | local finishTable = loadTable("finishSettings.txt")
121 | if finishTable == nil then
122 | print("Error getting table")
123 | os.exit()
124 | end
125 | print("Success...")
126 | modemPort = finishTable.config.port
127 | modem.close()
128 | if component.isAvailable("tunnel") then
129 | link = component.tunnel
130 | end
131 |
132 | print("Sending query to server...")
133 | if link == nil then
134 | modem.open(modemPort)
135 | end
136 | send(nil,modemPort,true,"getquery",ser.serialize({"passSettings","sectors","&&&crypt"}))
137 | local e,_,from,port,_,msg = event.pull(3,"modem_message")
138 | if e == nil then
139 | print("No query received. Assuming old server system is in place and will not work.")
140 | os.exit()
141 | end
142 | print("Query received")
143 | query = ser.unserialize(msg)
144 | if query.num ~= 3 then
145 | print("Security server is not valid. Must be 3.0.0 and up")
146 | os.exit()
147 | end
148 | editorSettings.x = 2
149 | editorSettings.num = query.num
150 | editorSettings.version = query.version
151 | editorSettings.hassector = query.data.sectors ~= nil
152 | editorSettings.settings = query.data.passSettings
153 | editorSettings.settings.sectors = query.data.sectors
154 | editorSettings.scanner = false
155 | editorSettings.accelerate = false
156 | editorSettings.single = false
157 | term.clear()
158 | local text = sendMsg("Would you like to use an external device for accelerated setup?","This makes it easier to set up doors without having to move from the door to the pc constantly.","It requires a diagnostic tablet (found on github)","1 for yes, 2 for no",1)
159 | if tonumber(text) == 1 then
160 | modem.open(diagPort)
161 | modem.close(modemPort)
162 | sendMsg("Start up accelerated door setup on your diagnostic tablet","in 60 seconds with no changes the program will close")
163 |
164 | local time = 0
165 | local timer = function(seconds)
166 | time = seconds
167 | for i=1,seconds, 1 do
168 | os.sleep(1)
169 | time = time - 1
170 | end
171 | end
172 | local waiter = true
173 | local e, _, from, port, _, msg, barcode, t
174 | t = thread.create(timer) --setup incorrect
175 | while waiter do
176 | e, _, from, port, _, msg, barcode = event.pull(time, "modem_message")
177 | if e then
178 | if msg == "accsetup" then
179 | waiter = false
180 | end
181 | else
182 | waiter = false
183 | end
184 | end
185 |
186 | if e then
187 | if link == nil then
188 | modem.open(modemPort)
189 | end
190 | t:kill()
191 | send(from,port,false,"connected")
192 | term.clear()
193 | sendMsg("Connection successful! All prompts will be on the tablet now on.")
194 | os.sleep(1)
195 | editorSettings.scanner = barcode
196 | editorSettings.accelerate = true
197 | editorSettings.from = from
198 | editorSettings.port = port
199 | else
200 | modem.close(diagPort)
201 | print("Setup cancelled")
202 | os.exit()
203 | end
204 | else
205 | print("normal setup initiating")
206 | end
207 | editorSettings.type = "doorsystem"
208 | os.execute("wget -f " .. doorCode .. " " .. program)
209 | editorSettings.x = tonumber(sendMsg("Would you like to use the simple pass setup or new advanced one?","1 for simple, 2 for advanced",1))
210 |
211 | local config = {}
212 | config.type = editorSettings.type
213 | config.num = editorSettings.num
214 | config.version = editorSettings.version
215 | config.cryptKey = finishTable.config.cryptKey
216 | config.port = modemPort
217 | saveTable(config,configFileName)
218 |
219 | editorSettings.single = #finishTable == 1 and true or false
220 |
221 | settingData = {}
222 | for i=1,#finishTable,1 do
223 | local loopArray = {}
224 | sendMsg(3)
225 | local j
226 | if editorSettings.single == false then
227 | sendMsg("Door # " .. i .. " out of " .. #finishTable .. " is being edited: " .. finishTable[i].name.data)
228 | local keepLoop = true
229 | while keepLoop do
230 | j = randomNameArray[math.floor(math.random(1,26))]..randomNameArray[math.floor(math.random(1,26))]..randomNameArray[math.floor(math.random(1,26))]..randomNameArray[math.floor(math.random(1,26))]
231 | keepLoop = false
232 | for key,value in pairs(settingData) do
233 | if key == j then
234 | keepLoop = true
235 | end
236 | end
237 | end
238 | text = sendMsg("Magnetic card reader?",editorSettings.scanner and "Scan the magnetic card reader with your tablet." or "Enter the uuid of the device in TEXT. When finished, don't type anything and just press enter",5)
239 | loopArray["reader"] = {}
240 | local hasPad = false
241 | for _, value in pairs(text) do
242 | local thisType = component.type(value)
243 | if thisType == "os_magreader" then
244 | table.insert(loopArray["reader"],{["uuid"]=value,["type"]="swipe"})
245 | elseif thisType == "os_biometric" then
246 | table.insert(loopArray["reader"],{["uuid"]=value,["type"]="biometric"})
247 | elseif thisType == "os_rfidreader" then
248 | table.insert(loopArray["reader"],{["uuid"]=value,["type"]="rfid"})
249 | elseif thisType == "os_keypad" then
250 | hasPad = true
251 | component.proxy(value).setDisplay("inactive", 6)
252 | table.insert(loopArray["reader"],{["uuid"]=value,["type"]="keypad",["global"]=false,["pass"]="1111"})
253 | end
254 | end
255 | if hasPad then
256 | text = sendMsg("Keypads detected: Would you like to use a global or local password?","global passwords are set by the database. local are set and saved on this door computer","1 for global, 2 for local",1)
257 | if text == "1" then
258 | text = sendMsg("What is the key for that keypad variable?",1)
259 | else
260 | hasPad = false
261 | text = sendMsg("What is the pin for the keypad to need to allow you in?","4 or less numbers (4 recommended)",1)
262 | end
263 | for key, value in pairs(loopArray["reader"]) do
264 | if value.type == "keypad" then
265 | loopArray["reader"][key].global = hasPad
266 | loopArray["reader"][key].pass = text
267 | end
268 | end
269 | end
270 | else
271 | local hasPad = false
272 | j = randomNameArray[math.floor(math.random(1,26))]..randomNameArray[math.floor(math.random(1,26))]..randomNameArray[math.floor(math.random(1,26))]..randomNameArray[math.floor(math.random(1,26))]
273 | local distable = {}
274 | for key,_ in pairs(component.list("os_magreader")) do
275 | table.insert(distable,{["uuid"]=key,["type"]="swipe"})
276 | end
277 | for key,_ in pairs(component.list("os_biometric")) do
278 | table.insert(distable,{["uuid"]=key,["type"]="biometric"})
279 | end
280 | for key,_ in pairs(component.list("os_rfidreader")) do
281 | table.insert(distable,{["uuid"]=key,["type"]="rfid"})
282 | end
283 | for key,_ in pairs(component.list("os_keypad")) do
284 | hasPad = true
285 | component.proxy(key).setDisplay("inactive", 6)
286 | table.insert(distable,{["uuid"]=key,["type"]="keypad",["global"]=false,["pass"]="1111"})
287 | end
288 | if hasPad then
289 | text = sendMsg("Keypads detected: Would you like to use a global or local password?","global passwords are set by the database. local are set and saved on this door computer","1 for global, 2 for local",1)
290 | if text == "1" then
291 | text = sendMsg("What is the key for that keypad variable?",1)
292 | else
293 | hasPad = false
294 | text = sendMsg("What is the pin for the keypad to need to allow you in?","4 or less numbers (4 recommended)",1)
295 | end
296 | for key, value in pairs(distable) do
297 | if value.type == "keypad" then
298 | distable[key].global = hasPad
299 | distable[key].pass = text
300 | end
301 | end
302 | end
303 | loopArray["reader"] = distable
304 | end
305 | loopArray["name"] = finishTable[i].name.data
306 | --Door Type/RedColor/Address/RedSide Area
307 | if finishTable[i].doorType.finished == true then
308 | loopArray["doorType"] = finishTable[i].doorType.data
309 | else
310 | text = sendMsg("Door Type? 1=redstone. 2=bundled. 3=door/rolldoor. NUMBER ONLY",1)
311 | loopArray["doorType"] = tonumber(text)
312 | end
313 | if loopArray.doorType == 2 then
314 | text = sendMsg("What color. Use the Color API wiki on the opencomputers wiki, and enter the NUMBER",1)
315 | loopArray["redColor"] = tonumber(text)
316 | loopArray["doorAddress"] = {}
317 | text = sendMsg("What side? 0=bottom, 1=top, 2=back, 3=front, 4=right, 5=left. NUMBER ONLY",1)
318 | loopArray["redSide"] = tonumber(text)
319 | if editorSettings.single == false then
320 | sendMsg("No need to input anything for door address. The setting doesn't require it :)")
321 | end
322 | elseif loopArray.doorType == 1 then
323 | loopArray["redColor"] = 0
324 | loopArray["doorAddress"] = {}
325 | text = sendMsg("No need for redColor! The settings you inputted before don't require it :)","What side? 0=bottom, 1=top, 2=back, 3=front, 4=right, 5=left. NUMBER ONLY",1)
326 | loopArray["redSide"] = tonumber(text)
327 | if editorSettings.single == false then
328 | sendMsg("No need to input anything for door address. The setting doesn't require it :)")
329 | end
330 | else
331 | loopArray["redColor"] = 0
332 | loopArray["redSide"] = 0
333 | sendMsg("no need to input anything for redColor. The setting doesn't require it :)","no need to input anything for redSide. The setting doesn't require it :)")
334 | loopArray["doorAddress"] = {}
335 | if editorSettings.single == false then
336 | text = sendMsg("What is the address for the doorcontrol/rolldoor block?", editorSettings.scanner and "Scan the blocks with tablet" or "Enter uuids as text",5)
337 | loopArray["doorAddress"] = text
338 | else
339 | loopArray["doorAddress"] = {}
340 | for key,_ in pairs(component.list("os_rolldoorcontroller")) do
341 | table.insert(loopArray["doorAddress"],key)
342 | end
343 | for key,_ in pairs(component.list("os_doorcontroller")) do
344 | table.insert(loopArray["doorAddress"],key)
345 | end
346 | end
347 | end
348 | --Toggle/Delay Area
349 | if finishTable[i].toggle.finished == true then
350 | sendMsg("Toggle has already been preset")
351 | loopArray["toggle"] = finishTable[i].toggle.data
352 | else
353 | text = sendMsg("Should the door be toggleable, or not? 0 for autoclose and 1 for toggleable",1)
354 | loopArray["toggle"] = tonumber(text)
355 | end
356 | if loopArray.toggle == 0 then
357 | if finishTable[i].delay.finished == true then
358 | sendMsg("Delay has already been preset")
359 | loopArray["delay"] = finishTable[i].delay.data
360 | else
361 | text = sendMsg("How long should the door stay open in seconds? NUMBER ONLY",1)
362 | loopArray["delay"] = tonumber(text)
363 | end
364 | else
365 | sendMsg("No need to change delay! Previous setting doesn't require it :)")
366 | loopArray["delay"] = 0
367 | end
368 | --Card Read Area (Beeg area)
369 | if finishTable[i].cardRead.finished == true then
370 | sendMsg("Door Passes have already been preset")
371 | loopArray["cardRead"] = finishTable[i].cardRead.data
372 | else
373 | if editorSettings.x == 2 then
374 | local readLoad = {}
375 | sendMsg("Remember how many of each pass you want before you start.","type something and enter to continue",1)
376 | readLoad.add = tonumber(sendMsg("How many add passes do you want to add?","remember multiple base passes can use the same add pass",1))
377 | readLoad.base = tonumber(sendMsg("How many base passes do you want to add?",1))
378 | readLoad.reject = tonumber(sendMsg("How many reject passes do you want to add?","These don't affect supreme passes",1))
379 | readLoad.supreme = tonumber(sendMsg("How many supreme passes do you want to add?",1))
380 | loopArray.cardRead = {}
381 | local nextmsg = {}
382 | nextmsg.beg, nextmsg.mid, nextmsg.back = "What should be read for "," pass number ","? 0 = staff"
383 | for i=1,#editorSettings.settings.var,1 do
384 | nextmsg.back = nextmsg.back .. ", " .. i .. " = " .. editorSettings.settings.label[i]
385 | end
386 | local passFunc = function(type,num)
387 | local newRules = {["uuid"]=uuid.next(),["request"]=type,["data"]=type == "base" and {} or false}
388 | local text = sendMsg(nextmsg.beg..type..nextmsg.mid..num..nextmsg.back,1)
389 | if tonumber(text) == 0 then
390 | newRules.call = "checkstaff"
391 | newRules.param = 0
392 | sendMsg("No need for extra parameter. This mode doesn't require it :)")
393 | else
394 | newRules["tempint"] = tonumber(text)
395 | newRules["call"] = editorSettings.settings.calls[tonumber(text)]
396 | if editorSettings.settings.type[tonumber(text)] == "string" or editorSettings.settings.type == "-string" then
397 | text = sendMsg("What is the string you would like to read? Enter text.",1)
398 | newRules["param"] = text
399 | elseif editorSettings.settings.type[tonumber(text)] == "bool" then
400 | newRules["param"] = 0
401 | sendMsg("No need for extra parameter. This mode doesn't require it :)")
402 | elseif editorSettings.settings.type[tonumber(text)] == "int" then
403 | if editorSettings.settings.above[tonumber(text)] == true then
404 | text = sendMsg("What level and above should be required?",1)
405 | else
406 | text = sendMsg("what level exactly should be required?",1)
407 | end
408 | newRules["param"] = tonumber(text)
409 | elseif editorSettings.settings.type[tonumber(text)] == "-int" then
410 | local nextmsg = "What group are you wanting to set?"
411 | for i=1,#editorSettings.settings.data[tonumber(text)],1 do
412 | nextmsg = nextmsg .. ", " .. i .. " = " .. editorSettings.settings.data[tonumber(text)][i]
413 | end
414 | text = sendMsg(nextmsg,1)
415 | newRules["param"] = tonumber(text)
416 | else
417 | sendMsg("error in cardRead area for num 2")
418 | newRules["param"] = 0
419 | end
420 | end
421 | return newRules
422 | end
423 | for i=1,readLoad.add,1 do
424 | local rule = passFunc("add",i)
425 | table.insert(loopArray.cardRead,rule)
426 | end
427 | local addNum = #loopArray.cardRead
428 | for i=1,readLoad.base,1 do
429 | local rule = passFunc("base",i)
430 | text = tonumber(sendMsg("How many add passes do you want to link?",1))
431 | if text ~= 0 then
432 | local nextAdd = "Which pass do you want to add? "
433 | for j=1,addNum,1 do
434 | nextAdd = nextAdd .. ", " .. j .. " = " .. editorSettings.settings.label[loopArray.cardRead[j].tempint]
435 | end
436 | for j=1,text,1 do
437 | text = tonumber(sendMsg(nextAdd,1))
438 | table.insert(rule.data,loopArray.cardRead[text].uuid)
439 | end
440 | end
441 | table.insert(loopArray.cardRead,rule)
442 | end
443 | for i=1,readLoad.reject,1 do
444 | local rule = passFunc("reject",i)
445 | table.insert(loopArray.cardRead,rule)
446 | end
447 | for i=1,readLoad.supreme,1 do
448 | local rule = passFunc("supreme",i)
449 | table.insert(loopArray.cardRead,rule)
450 | end
451 | else --{["uuid"]=uuid.next()["call"]=t1,["param"]=t2,["request"]="supreme",["data"]=false}
452 | local nextmsg = "What should be read? 0 = staff,"
453 | for i=1,#editorSettings.settings.var,1 do
454 | nextmsg = nextmsg .. ", " .. i .. " = " .. editorSettings.settings.label[i]
455 | end
456 | text = sendMsg(nextmsg,1)
457 | loopArray["cardRead"] = {{["uuid"]=uuid.next(),["call"]="",["param"]=0,["request"]="supreme",["data"]=false}}
458 | if tonumber(text) == 0 then
459 | loopArray["cardRead"][1].call = "checkstaff"
460 | loopArray["cardRead"][1].param = 0
461 | sendMsg("No need to set access level. This mode doesn't require it :)")
462 | else
463 | loopArray["cardRead"][1].call = editorSettings.settings.calls[tonumber(text)]
464 | if editorSettings.settings.type[tonumber(text)] == "string" or editorSettings.settings.type[tonumber(text)] == "-string" then
465 | text = sendMsg("What is the string you would like to read? Enter text.",1)
466 | loopArray["cardRead"][1].param = text
467 | elseif editorSettings.settings.type[tonumber(text)] == "bool" then
468 | loopArray["cardRead"][1].param = 0
469 | sendMsg("No need to set access level. This mode doesn't require it :)")
470 | elseif editorSettings.settings.type[tonumber(text)] == "int" then
471 | if editorSettings.settings.above[tonumber(text)] == true then
472 | text = sendMsg("What level and above should be required?",1)
473 | else
474 | text = sendMsg("what level exactly should be required?",1)
475 | end
476 | loopArray["cardRead"][1].param = tonumber(text)
477 | elseif editorSettings.settings.type[tonumber(text)] == "-int" then
478 | local nextmsg = "What group are you wanting to set?"
479 | for i=1,#editorSettings.settings.data[tonumber(text)],1 do
480 | nextmsg = nextmsg .. ", " .. i .. " = " .. editorSettings.settings.data[tonumber(text)][i]
481 | end
482 | text = sendMsg(nextmsg,1)
483 | loopArray["cardRead"][1].param = tonumber(text)
484 | else
485 | sendMsg("error in cardRead area for num 2")
486 | loopArray["cardRead"][1].param = 0
487 | end
488 | end
489 | end
490 | end
491 | --Sectors Area
492 | if editorSettings.hassector then
493 | if finishTable[i].sector.finished == true then
494 | sendMsg("Sector has already been preset")
495 | loopArray["sector"] = finishTable[i].sector.data
496 | else
497 | local nextmsg = "What sector would you like this door to be part of? 0 = no sector"
498 | for i=1,#editorSettings.settings.sectors,1 do --Issue
499 | nextmsg = nextmsg .. ", " .. i .. " = " .. editorSettings.settings.sectors[i].name
500 | end
501 | text = tonumber(sendMsg(nextmsg,1))
502 | if text == 0 then
503 | loopArray["sector"]=false
504 | else
505 | loopArray["sector"]=editorSettings.settings.sectors[text].uuid
506 | end
507 | end
508 | else
509 | loopArray["sector"] = false
510 | end
511 | --End of Loop
512 | settingData[j] = loopArray
513 | end
514 |
515 | text = sendMsg("All done with installer!","Would you like to start the computer now?","1 for yes, 2 for no",1)
516 | editorSettings.start = false
517 | if tonumber(text) == 1 then
518 | sendMsg("Ok, will start computer.",4)
519 | editorSettings.start = true
520 | else
521 | sendMsg("Ok, closing out.",4)
522 | end
523 | saveTable(settingData,settingFileName)
524 | if editorSettings.start == true then
525 | print("Starting...")
526 | os.execute(program)
527 | else
528 | print("Run " .. program .. " now to start door.")
529 | end
530 | os.execute("del finishSettings.txt")
531 | os.execute("del finish.lua")
--------------------------------------------------------------------------------
/modules.txt:
--------------------------------------------------------------------------------
1 | {{name="Security",id=1111,version="3.0.0",database={folder="Security",main="https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/main/security/Database%20Module/Main.lua",debug="https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/2.5.0/security/Database%20Module/Main.lua",extras={}},server={folder="Security",main="https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/main/security/Server%20Module/security.lua",debug="https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/2.5.0/security/Server%20Module/security.lua",extras={}},requirements={}},{name="Sectors",id=1112,version="3.0.0",database={folder="Sectors",main="https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/main/sectors/Database%20Module/Main.lua",debug="https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/2.5.0/sectors/Database%20Module/Main.lua",extras={}},server={folder="Sectors",main="https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/main/sectors/Server%20Module/sectors.lua",debug="https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/2.5.0/sectors/Server%20Module/sectors.lua",extras={}},requirements={1111}},{name="Door Setup",id=1113,version="1.0.0",database={folder="DoorSetup",main="https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/main/doorsetup/door.lua",extras={{name="finish.lua",url="https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/main/doorsetup/finish.lua"}}},requirements={1111}}}
--------------------------------------------------------------------------------
/permissions.txt:
--------------------------------------------------------------------------------
1 | security.* (All things in Security module & Sectors)
2 | security.varmanagement (add/del users and add/del vars and write cards/admincard)
3 | security.sectors (All things in Sectors module)
4 | security.name (Name)
5 | security.writecard (write card)
6 | security.admincard (write admin card)
7 | security.resetuuid (reset user uuid for card)
8 | security.passediting (all passes)
9 | security.link (link button)
10 | security.block (block user)
11 | security.staff (staff pass)
12 | security.doorsetup (create a door with doorsetup module)
13 | security.mcid (link and clear a user's minecraft id)
14 | security.keypad (Manage global keypad passwords)
15 | security.(any var added by user)
16 |
17 | dev.* (all developer module features)
18 | dev.usermanagement (manage users and permissions and such.)
19 | dev.systemmanagement (manage modules and settings)
20 |
21 | Any permission written with a ~ before it will be disabled for that user
22 | (in case you want someone to, say, do all security functions except write a card, do ~security.writecard and security.*)
--------------------------------------------------------------------------------
/remotecontrol/main.lua:
--------------------------------------------------------------------------------
1 | local module = {}
2 | local component = require("component")
3 | local GUI = require("GUI")
4 | local ser = require("serialization")
5 | local modem = component.modem
6 |
7 | local userTable -- Holds userTable stuff.
8 |
9 | local workspace, window, loc, database, style, compat = table.unpack({...}) --Sets up necessary variables: workspace is workspace, window is area to work in, loc is localization file, database are database commands, and style is the selected style file.
10 |
11 | module.name = "R.C." --The name that shows up on the module's button.
12 | module.table = {} --Set to the keys you want pulled from the userlist on the server,
13 | module.debug = false --The database will set to true if debug mode on database is enabled. If you want to enable certain functions in debug mode.
14 | module.config = {} --optional. Lets you add config settings which can be pulled by database.checkConfig("name").
15 | --[[ INFO ABOUT module.config
16 | Each value of table must be this: ["name"] = {["label"] = "a label",["type"]="bool",["default"]=false}
17 | name = name that the variable is stored in. What you'll call with database.checkConfig("name") replacing "name" with the name
18 | label = What the label will be in the settings database
19 | type = The type of input it takes. bool is a button, string is a string input, int is a number (int) input
20 | default = Default value if created for first time. bool is true or false, string is string input, and int is a number.
21 | server = Whether the settings are pushed to the server as well (server-side settings) Settings are always saved database side
22 | ]]
23 | local diagPort = 180
24 |
25 |
26 | module.init = function(usTable) --Set userTable to what's received. Runs only once at the beginning
27 | userTable = usTable
28 | end
29 |
30 | module.onTouch = function() --Runs when the module's button is clicked. Set up the workspace here.
31 | --Verify their permissions
32 | if database.checkPerms("security",{"rc"},true) then
33 | window:addChild(GUI.label(2,16,3,3,style.passNameLabel,"You do not have permissions to do this"))
34 | return
35 | end
36 | --Door Setup
37 | local worked,_,_,_,_,doors = database.send(true,"rcdoors") --get doors
38 | if(worked) then --got doors
39 | local tempPasses = ser.unserialize(database.crypt(doors,true)) --decrypt and make table
40 | doors = {}
41 | for key,value in pairs(tempPasses) do --Perform loop to sort in a way which will be sent to the doors to activate them
42 | for keym,valuem in pairs(value.data) do
43 | table.insert(doors,{["call"]=value.id,["type"]=value.type,["data"]=valuem,["key"]=keym})
44 | end
45 | end
46 | --Define Variables
47 | local doorList, listPageLabel, listUpButton, listDownButton, openFive, openTen, openThirty, toggleOpen, openNum, openNumInput
48 | local pageMult = 10
49 | local listPageNumber = 0
50 | local previousPage = 0
51 |
52 | --Functions
53 |
54 | local function doorListCallback()
55 | openFive.disabled = false
56 | openTen.disabled = false
57 | openThirty.disabled = false
58 | toggleOpen.disabled = false
59 | openNum.disabled = false
60 | openNumInput.disabled = false
61 | end
62 |
63 | local function updateList()
64 | doorList:removeChildren()
65 | if (pageMult * listPageNumber) + 1 > #doors and listPageNumber ~= 0 then
66 | listPageNumber = listPageNumber - 1
67 | end
68 | local temp = pageMult * listPageNumber
69 | for i = temp + 1, temp + pageMult, 1 do
70 | if doors[i] == nil then
71 |
72 | else
73 | doorList:addItem(doors[i].data.name).onTouch = doorListCallback
74 | end
75 | end
76 | doorList.selectedItem = 1
77 | previousPage = listPageNumber
78 | if pageMult * listPageNumber + pageMult < #doors then
79 | listUpButton.disabled = false
80 | else
81 | listUpButton.disabled = true
82 | end
83 | if listPageNumber == 0 then
84 | listDownButton.disabled = true
85 | end
86 | listDownButton.disabled = listPageNumber == 0
87 | listUpButton.disabled = #doors <= temp + pageMult
88 | openFive.disabled = false
89 | openTen.disabled = false
90 | openThirty.disabled = false
91 | toggleOpen.disabled = false
92 | openNum.disabled = false
93 | openNumInput.disabled = false
94 | end
95 |
96 | local function pageCallback(_,button)
97 | local function canFresh()
98 | updateList()
99 | doorListCallback()
100 | end
101 | if #doors ~= 0 then
102 | if button.isPos then
103 | if listPageNumber < #doors/pageMult - 1 then
104 | listPageNumber = listPageNumber + 1
105 | canFresh()
106 | end
107 | else
108 | if listPageNumber > 0 then
109 | listPageNumber = listPageNumber - 1
110 | canFresh()
111 | end
112 | end
113 | end
114 | end
115 |
116 | local function performCommand(_,button)
117 | local selected = pageMult * listPageNumber + doorList.selectedItem
118 | local send = {["id"]=doors[selected].call,["key"]=doors[selected].key,["type"]="base"}
119 | if(button.sendIt == 1) then
120 | send.type = "toggle"
121 | elseif(button.sendIt == 2) then
122 | send.type, send.delay = "delay", 5
123 | elseif (button.sendIt == 3) then
124 | send.type,send.delay = "delay", 10
125 | elseif(button.sendIt == 4) then
126 | send.type,send.delay = "delay", 30
127 | elseif(button.sendIt == 5) then
128 | if(openNumInput.text ~= "") then
129 | send.type,send.delay = "delay", tonumber(openNumInput.text)
130 | else
131 | GUI.alert("No seconds specified")
132 | return
133 | end
134 | end
135 | modem.send(send.id,diagPort,"remoteControl",ser.serialize(send))
136 | end
137 |
138 | --Setup GUI
139 |
140 | window:addChild(GUI.panel(1,1,37,33,style.listPanel))
141 | doorList = window:addChild(GUI.list(2, 2, 35, 31, 3, 0, style.listBackground, style.listText, style.listAltBack, style.listAltText, style.listSelectedBack, style.listSelectedText, false))
142 | listPageLabel = window:addChild(GUI.label(2,33,3,3,style.listPageLabel,tostring(listPageNumber + 1)))
143 | listUpButton = window:addChild(GUI.button(8,33,3,1, style.listPageButton, style.listPageText, style.listPageSelectButton, style.listPageSelectText, "+"))
144 | listUpButton.onTouch, listUpButton.isPos = pageCallback,true
145 | listDownButton = window:addChild(GUI.button(12,33,3,1, style.listPageButton, style.listPageText, style.listPageSelectButton, style.listPageSelectText, "-"))
146 | listDownButton.onTouch, listDownButton.isPos = pageCallback,false
147 | openFive = window:addChild(GUI.button(64,14,16,1, style.sectorButton,style.sectorText,style.sectorSelectButton,style.sectorSelectText, "5 Seconds"))
148 | openFive.sendIt = 2
149 | openFive.onTouch = performCommand
150 | openFive.disabled = true
151 | openTen = window:addChild(GUI.button(64,16,16,1, style.sectorButton,style.sectorText,style.sectorSelectButton,style.sectorSelectText, "10 Seconds"))
152 | openTen.sendIt = 3
153 | openTen.onTouch = performCommand
154 | openTen.disabled = true
155 | openThirty = window:addChild(GUI.button(64,18,16,1, style.sectorButton,style.sectorText,style.sectorSelectButton,style.sectorSelectText, "30 Seconds"))
156 | openThirty.sendIt = 4
157 | openThirty.onTouch = performCommand
158 | openThirty.disabled = true
159 | toggleOpen = window:addChild(GUI.button(64,12,16,1, style.sectorButton,style.sectorText,style.sectorSelectButton,style.sectorSelectText, "Toggle Open"))
160 | toggleOpen.sendIt = 1
161 | toggleOpen.onTouch = performCommand
162 | toggleOpen.disabled = true
163 | openNumInput = window:addChild(GUI.input(64,21,16,1, style.passInputBack,style.passInputText,style.passInputPlaceholder,style.passInputFocusBack,style.passInputFocusText, "", loc.inputname))
164 | openNumInput.onInputFinished = function()
165 | if openNumInput.text ~= nil and openNumInput ~= "" then
166 | local num = tonumber(openNumInput.text)
167 | if(num == nil and num > 0) then
168 | openNumInput.text = ""
169 | end
170 | end
171 | end
172 | openNumInput.disabled = true
173 | openNum = window:addChild(GUI.button(64,20,16,1, style.sectorButton,style.sectorText,style.sectorSelectButton,style.sectorSelectText, "# Seconds"))
174 | openNum.sendIt = 5
175 | openNum.onTouch = performCommand
176 | openNum.disabled = true
177 | updateList()
178 | else
179 | GUI.alert("No connection received")
180 | end
181 | end
182 |
183 | module.close = function()
184 | return {} --Return table of what you want the database to auto save (if enabled) of the keys used by this module
185 | end
186 |
187 | return module
188 |
--------------------------------------------------------------------------------
/sectors/Database Module/Main.lua:
--------------------------------------------------------------------------------
1 | local module = {}
2 | local GUI = require("GUI")
3 | local uuid = require("uuid")
4 |
5 | local userTable
6 |
7 | local workspace, window, loc, database, style, compat = table.unpack({...})
8 |
9 | module.name = "Sectors"
10 | module.table = {"sectors"}
11 | module.debug = false
12 | module.config = {}
13 |
14 | module.init = function(usTable)
15 | userTable = usTable
16 | end
17 |
18 | module.onTouch = function()
19 | local sectorList, sectorNameInput, newSectorButton, delSectorButton, sectorPassNew, sectorPassRemove, sectorPassEdit, sectorPassList, userPassSelfSelector, userPassDataSelector, userPassTypeSelector, userPassPrioritySelector
20 | local sectorListNum, sectorListUp, sectorListDown, sectorPassListNum, sectorPassListUp, sectorPassListDown
21 |
22 | local canPerm
23 |
24 | local pageMult = 10
25 | local listPageNumber = 0
26 | local previousPage = 0
27 |
28 | local pageMultPass = 5
29 | local listPageNumberPass = 0
30 | local previousPagePass = 0
31 | local prevPass = "string"
32 |
33 | --Sector functions
34 |
35 | local function uuidtopass(uuid)
36 | if uuid == "checkstaff" then
37 | return true, 0
38 | end
39 | for i=1,#userTable.passSettings.calls,1 do
40 | if userTable.passSettings.calls[i] == uuid then
41 | return true, i
42 | end
43 | end
44 | return false
45 | end
46 |
47 | local function refreshInput()
48 | local uuid = userPassSelfSelector.selectedItem - 1
49 | if uuid ~= 0 then
50 | if userTable.passSettings.type[uuid] == "string" or userTable.passSettings.type[uuid] == "-string" or userTable.passSettings.type[uuid] == "int" then
51 | if prevPass == "-int" then
52 | userPassDataSelector:remove()
53 | userPassDataSelector = window:addChild(GUI.input(100,22,16,1, style.containerInputBack,style.containerInputText,style.containerInputPlaceholder,style.containerInputFocusBack,style.containerInputFocusText, "", loc.inputtext))
54 | end
55 | userPassDataSelector.text = ""
56 | userPassDataSelector.disabled = canPerm
57 | elseif userTable.passSettings.type[uuid] == "-int" then
58 | if prevPass ~= "-int" then
59 | userPassDataSelector:remove()
60 | userPassDataSelector = window:addChild(GUI.comboBox(100,21,30,3, style.sectorComboBack,style.sectorComboText,style.sectorComboArrowBack,style.sectorComboArrowText))
61 | else
62 | userPassDataSelector:clear()
63 | end
64 | for _,value in pairs(userTable.passSettings.data[uuid]) do
65 | userPassDataSelector:addItem(value)
66 | end
67 | userPassDataSelector.selectedItem = 1
68 | else
69 | if prevPass == "-int" then
70 | userPassDataSelector:remove()
71 | userPassDataSelector = window:addChild(GUI.input(100,22,16,1, style.containerInputBack,style.containerInputText,style.containerInputPlaceholder,style.containerInputFocusBack,style.containerInputFocusText, "", loc.inputtext))
72 | end
73 | userPassDataSelector.text = ""
74 | userPassDataSelector.disabled = true
75 | end
76 | else
77 | if prevPass == "-int" then
78 | userPassDataSelector:remove()
79 | userPassDataSelector = window:addChild(GUI.input(100,22,16,1, style.containerInputBack,style.containerInputText,style.containerInputPlaceholder,style.containerInputFocusBack,style.containerInputFocusText, "", loc.inputtext))
80 | end
81 | userPassDataSelector.text = ""
82 | userPassDataSelector.disabled = true
83 | end
84 | prevPass = uuid ~= 0 and userTable.passSettings.type[uuid] or "bool"
85 | end
86 |
87 | --[[local function sectorPassCallback() Commented out because not planning on making it possible to add sectors for simplicity for meeeee
88 | local selectedId = pageMultPass * listPageNumberPass + sectorPassList.selectedItem
89 | local secSelect = pageMult * listPageNumber + sectorList.selectedItem
90 | local sectorpass = userTable.sectors[secSelect].pass[selectedId]
91 | local uuid = uuidtopass(sectorpass.uuid)
92 | userPassSelfSelector.selectedItem = uuid + 1
93 | userPassTypeSelector.selectedItem = sectorpass.lock
94 | refreshInput(uuid)
95 | end]]
96 |
97 | local function sectorListCallback()
98 | local selectedId = pageMult * listPageNumber + sectorList.selectedItem
99 | sectorNameInput.text = userTable.sectors[selectedId].name
100 | sectorPassList:removeChildren()
101 | if (pageMultPass * listPageNumberPass) + 1 > #userTable.sectors[selectedId].pass and listPageNumberPass ~= 0 then
102 | listPageNumberPass = listPageNumberPass - 1
103 | end
104 | local temp = pageMultPass * listPageNumberPass
105 | if previousPagePass ~= listPageNumberPass then
106 | sectorPassList.selectedItem = 1
107 | previousPagePass = listPageNumberPass
108 | end
109 | sectorPassListDown.disabled = listPageNumberPass == 0
110 | sectorPassListUp.disabled = #userTable.sectors[selectedId].pass <= temp + pageMultPass
111 | sectorPassListNum.text = tostring(listPageNumberPass + 1)
112 | sectorPassNew.disabled = canPerm
113 | sectorPassRemove.disabled = canPerm
114 | sectorPassEdit.disabled = canPerm
115 | for i = temp + 1, temp + pageMultPass, 1 do
116 | if (userTable.sectors[selectedId].pass[i] == nil) then
117 | if i == temp + 1 then
118 | sectorPassRemove.disabled = true
119 | sectorPassEdit.disabled = true
120 | end
121 | else
122 | local work, pass = uuidtopass(userTable.sectors[selectedId].pass[i].uuid)
123 | local lockType = {loc.sectoropen,loc.sectordislock}
124 | if pass ~= 0 then
125 | local disdata = userTable.sectors[selectedId].pass[i].data ~= nil and userTable.sectors[selectedId].pass[i].data or "0"
126 | if userTable.passSettings.type[pass] == "-int" then
127 | disdata = userTable.passSettings.data[pass][disdata]
128 | end
129 | sectorPassList:addItem(userTable.passSettings.label[pass] .. " : " .. tostring(disdata) .. " : p" .. tostring(userTable.sectors[selectedId].pass[i].priority) .. " : " .. lockType[userTable.sectors[selectedId].pass[i].lock])
130 | else
131 | sectorPassList:addItem("Staff : 0 : p" .. tostring(userTable.sectors[selectedId].pass[i].priority) .. " : " .. lockType[userTable.sectors[selectedId].pass[i].lock])
132 | end
133 | end
134 | end
135 | workspace:draw()
136 | end
137 |
138 | local function updateSecList()
139 | local selectedId = sectorList.selectedItem
140 | sectorList:removeChildren()
141 | if (pageMult * listPageNumber) + 1 > #userTable.sectors and listPageNumber ~= 0 then
142 | listPageNumber = listPageNumber - 1
143 | end
144 | local temp = pageMult * listPageNumber
145 | sectorListNum.text = tostring(listPageNumber + 1)
146 | for i = temp + 1, temp + pageMult, 1 do
147 | if (userTable.sectors[i] == nil) then
148 |
149 | else
150 | sectorList:addItem(userTable.sectors[i].name).onTouch = sectorListCallback
151 | end
152 | end
153 | database.save()
154 | if (previousPage == listPageNumber) then
155 | sectorList.selectedItem = selectedId
156 | else
157 | sectorList.selectedItem = 1
158 | listPageNumberPass = 0
159 | sectorListCallback()
160 | previousPage = listPageNumber
161 | end
162 | sectorListDown.disabled = listPageNumber == 0
163 | sectorListUp.disabled = #userTable.sectors <= temp + pageMult
164 | database.update()
165 | workspace:draw()
166 | end
167 |
168 | local function pageCallback(workspace,button)
169 | local function canFresh()
170 | updateSecList()
171 | sectorListCallback()
172 | end
173 | if button.isPos then
174 | if button.isListNum == 1 then
175 | if listPageNumber < #userTable.sectors/pageMult - 1 then
176 | listPageNumber = listPageNumber + 1
177 | canFresh()
178 | end
179 | else
180 | if listPageNumberPass < #userTable.sectors[pageMult * listPageNumber + sectorList.selectedItem].pass/pageMultPass - 1 then
181 | listPageNumberPass = listPageNumberPass + 1
182 | canFresh()
183 | end
184 | end
185 | else
186 | if button.isListNum == 1 then
187 | if listPageNumber > 0 then
188 | listPageNumber = listPageNumber - 1
189 | canFresh()
190 | end
191 | else
192 | if listPageNumberPass > 0 then
193 | listPageNumberPass = listPageNumberPass - 1
194 | canFresh()
195 | end
196 | end
197 | end
198 | end
199 |
200 | local function createSector()
201 | local addVarArray = {["name"]="new sector",["uuid"]=uuid.next(),["pass"]={}}
202 | table.insert(userTable.sectors,addVarArray)
203 | addVarArray = nil
204 | database.save()
205 | database.update()
206 | updateSecList()
207 | end
208 | local function deleteSector()
209 | local selected = pageMult * listPageNumber + sectorList.selectedItem
210 | table.remove(userTable.sectors,selected)
211 | if #userTable.sectors < pageMult * listPageNumber + 1 and listPageNumber ~= 0 then
212 | listPageNumber = listPageNumber - 1
213 | end
214 | database.save()
215 | database.update()
216 | updateSecList()
217 | end
218 |
219 | local function createSectorPass()
220 | local selected = userPassSelfSelector.selectedItem - 1
221 | local data = selected == 0 and nil or userTable.passSettings.type[selected] == "-int" and userPassDataSelector.selectedItem or userTable.passSettings.type[selected] == "bool" and nil or userTable.passSettings.type[selected] == "int" and tonumber(userPassDataSelector.text) or userPassDataSelector.text
222 | local uuid = selected == 0 and "checkstaff" or userTable.passSettings.calls[selected]
223 | table.insert(userTable.sectors[pageMult * listPageNumber + sectorList.selectedItem].pass,{["uuid"]=uuid,["data"]=data,["lock"]=userPassTypeSelector.selectedItem,["priority"]=userPassPrioritySelector.selectedItem})
224 | database.save()
225 | database.update()
226 | sectorListCallback()
227 | end
228 | local function deleteSectorPass()
229 | local selected = pageMultPass * listPageNumberPass + sectorPassList.selectedItem
230 | table.remove(userTable.sectors[pageMult * listPageNumber + sectorList.selectedItem].pass,selected)
231 | if #userTable.sectors[pageMult * listPageNumber + sectorList.selectedItem].pass < pageMultPass * listPageNumberPass + 1 and listPageNumberPass ~= 0 then
232 | listPageNumberPass = listPageNumberPass - 1
233 | end
234 | database.save()
235 | database.update()
236 | sectorListCallback()
237 | end
238 | local function editSectorPass()
239 | local selected = pageMultPass * listPageNumberPass + sectorPassList.selectedItem
240 | local apples = userTable.sectors[pageMult * listPageNumber + sectorList.selectedItem].pass[selected]
241 | table.remove(userTable.sectors[pageMult * listPageNumber + sectorList.selectedItem].pass,selected)
242 | sectorListCallback()
243 | userPassPrioritySelector.selectedItem = apples.priority
244 | userPassTypeSelector.selectedItem = apples.lock
245 | _, apples.uuid = uuidtopass(apples.uuid)
246 | userPassSelfSelector.selectedItem = apples.uuid + 1 --issue
247 | refreshInput()
248 | if apples.uuid == 0 or userTable.passSettings.type[apples.uuid] == "bool" then
249 |
250 | elseif userTable.passSettings.type[apples.uuid] == "-int" then
251 | userPassDataSelector.selectedItem = apples.data
252 | else
253 | userPassDataSelector.text = userTable.passSettings.type[apples.uuid] == "int" and tostring(apples.data) or apples.data
254 | end
255 | end
256 |
257 | canPerm = database.checkPerms("security",{"sector"},true)
258 |
259 | --GUI Setup
260 | window:addChild(GUI.panel(1,1,37,33,style.listPanel))
261 | sectorList = window:addChild(GUI.list(2, 2, 35, 31, 3, 0, style.listBackground, style.listText, style.listAltBack, style.listAltText, style.listSelectedBack, style.listSelectedText, false))
262 | sectorList:addItem("HELLO")
263 | listPageNumber = 0
264 |
265 |
266 | --Sector infos newSectorButton, delSectorButton
267 | window:addChild(GUI.label(40,12,1,1,style.passNameLabel,"Sector name: "))
268 | sectorNameInput = window:addChild(GUI.input(64,12,16,1, style.passInputBack,style.passInputText,style.passInputPlaceholder,style.passInputFocusBack,style.passInputFocusText, "", loc.inputname))
269 | sectorNameInput.onInputFinished = function()
270 | local selected = pageMult * listPageNumber + sectorList.selectedItem
271 | userTable.sectors[selected].name = sectorNameInput.text
272 | updateSecList()
273 | sectorListCallback()
274 | end
275 | sectorNameInput.disabled = canPerm
276 |
277 | newSectorButton = window:addChild(GUI.button(85,12,16,1, style.sectorButton,style.sectorText,style.sectorSelectButton,style.sectorSelectText, loc.addvar))
278 | newSectorButton.onTouch = createSector
279 | newSectorButton.disabled = canPerm
280 | delSectorButton = window:addChild(GUI.button(100,12,16,1, style.sectorButton,style.sectorText,style.sectorSelectButton,style.sectorSelectText, loc.delvar))
281 | delSectorButton.onTouch = deleteSector
282 | delSectorButton.disabled = canPerm
283 |
284 | window:addChild(GUI.panel(40,14,96,1,style.bottomDivider))
285 | window:addChild(GUI.panel(40,15,1,18,style.bottomDivider))
286 |
287 | window:addChild(GUI.panel(42,17,37,17,style.listPanel))
288 | sectorPassList = window:addChild(GUI.list(43, 18, 35, 15, 3, 0, style.listBackground, style.listText, style.listAltBack, style.listAltText, style.listSelectedBack, style.listSelectedText, false))
289 |
290 | window:addChild(GUI.label(85,18,1,1,style.passNameLabel,"Select Pass : "))
291 | userPassSelfSelector = window:addChild(GUI.comboBox(100,17,30,3, style.sectorComboBack,style.sectorComboText,style.sectorComboArrowBack,style.sectorComboArrowText))
292 | userPassSelfSelector:addItem("staff").onTouch = refreshInput
293 | for i=1,#userTable.passSettings.var,1 do
294 | userPassSelfSelector:addItem(userTable.passSettings.label[i]).onTouch = refreshInput
295 | end
296 | userPassSelfSelector.disabled = canPerm
297 | window:addChild(GUI.label(85,22,1,1,style.passNameLabel,"Change Input: "))
298 | userPassDataSelector = window:addChild(GUI.input(100,22,30,1, style.passInputBack,style.passInputText,style.passInputPlaceholder,style.passInputFocusBack,style.passInputFocusText, "", loc.inputtext))
299 | userPassDataSelector.disabled = true
300 | refreshInput()
301 | window:addChild(GUI.label(85,26,1,1,style.passNameLabel,"Bypass Type : "))
302 | userPassTypeSelector = window:addChild(GUI.comboBox(100,25,30,3, style.sectorComboBack,style.sectorComboText,style.sectorComboArrowBack,style.sectorComboArrowText))
303 | userPassTypeSelector.disabled = canPerm
304 | userPassTypeSelector:addItem(loc.sectoropen)
305 | userPassTypeSelector:addItem(loc.sectordislock)
306 | window:addChild(GUI.label(85,30,1,1,style.passNameLabel,"Priority : "))
307 | userPassPrioritySelector = window:addChild(GUI.comboBox(100,29,30,3, style.sectorComboBack,style.sectorComboText,style.sectorComboArrowBack,style.sectorComboArrowText))
308 | userPassPrioritySelector.disabled = canPerm
309 | for i=1,5,1 do
310 | userPassPrioritySelector:addItem(tostring(i))
311 | end
312 | sectorPassNew = window:addChild(GUI.button(85,33,14,1, style.sectorButton,style.sectorText,style.sectorSelectButton,style.sectorSelectText, loc.addvar))
313 | sectorPassNew.onTouch = createSectorPass
314 | sectorPassNew.disabled = true
315 | sectorPassRemove = window:addChild(GUI.button(100,33,14,1, style.sectorButton,style.sectorText,style.sectorSelectButton,style.sectorSelectText, loc.delvar))
316 | sectorPassRemove.onTouch = deleteSectorPass
317 | sectorPassRemove.disabled = true
318 | sectorPassEdit = window:addChild(GUI.button(115,33,14,1, style.sectorButton,style.sectorText,style.sectorSelectButton,style.sectorSelectText, loc.editvar))
319 | sectorPassEdit.onTouch = editSectorPass
320 | sectorPassEdit.disabled = true
321 | --List Buttons Setup
322 | sectorListNum = window:addChild(GUI.label(2,33,3,3,style.listPageLabel,tostring(listPageNumber + 1)))
323 | sectorListUp = window:addChild(GUI.button(8,33,3,1, style.listPageButton, style.listPageText, style.listPageSelectButton, style.listPageSelectText, "+"))
324 | sectorListUp.onTouch, sectorListUp.isPos, sectorListUp.isListNum = pageCallback,true,1
325 | sectorListDown = window:addChild(GUI.button(12,33,3,1, style.listPageButton, style.listPageText, style.listPageSelectButton, style.listPageSelectText, "-"))
326 | sectorListDown.onTouch, sectorListDown.isPos, sectorListDown.isListNum = pageCallback,false,1
327 |
328 | sectorPassListNum = window:addChild(GUI.label(43,33,3,3,style.listPageLabel,tostring(listPageNumberPass + 1)))
329 | sectorPassListUp = window:addChild(GUI.button(51,33,3,1, style.listPageButton, style.listPageText, style.listPageSelectButton, style.listPageSelectText, "+"))
330 | sectorPassListUp.onTouch, sectorPassListUp.isPos, sectorPassListUp.isListNum = pageCallback,true,2
331 | sectorPassListDown = window:addChild(GUI.button(55,33,3,1, style.listPageButton, style.listPageText, style.listPageSelectButton, style.listPageSelectText, "-"))
332 | sectorPassListDown.onTouch, sectorPassListDown.isPos, sectorPassListDown.isListNum = pageCallback,false,2
333 |
334 | updateSecList()
335 | end
336 |
337 | module.close = function()
338 | return {["sectors"]={}}
339 | end
340 |
341 | return module
--------------------------------------------------------------------------------
/sectors/Server Module/sectors.lua:
--------------------------------------------------------------------------------
1 | local userTable = {}
2 | local doorTable = {}
3 | local server = {}
4 | local modemPort = 199
5 |
6 | local component = require("component")
7 | local modem = component.modem
8 | local ser = require("serialization")
9 | local uuid = require("uuid")
10 |
11 | local module = {}
12 | module.name = "sectors"
13 | module.commands = {"sectorupdate","doorsecupdate"} --removed doorSector so it isn't received from outside of the server via modems
14 | module.skipcrypt = {}
15 | module.table = {["sectors"] = {{["name"]="Placeholder Sector",["uuid"]=uuid.next(),["type"]=1,["pass"]={}}}}
16 | module.table.sectorStatus = {[module.table.sectors[1].uuid]=1}
17 | module.debug = false
18 | module.version = "4.0.3"
19 | module.id = 1112
20 |
21 | local function checkMCID(id) --Pulled from Security module
22 | for _, value in pairs(userTable.passes) do
23 | if value.mcid == id then
24 | return true, value.uuid, value.name
25 | end
26 | end
27 | return false
28 | end
29 |
30 | function module.init(setit ,doors, serverCommands) --Called when server is first started. Passes userTable and doorTable.
31 | userTable = setit
32 | doorTable = doors
33 | server = serverCommands
34 | if module.debug then server.print("Received " .. #userTable.sectors .. " Sectors\n") end
35 | end
36 |
37 | function module.setup() --Called when userlist is updated or server is first started
38 | if module.debug then server.print("Received " .. #userTable.sectors .. " Sectors\n") end
39 | for key,_ in pairs(userTable.sectorStatus) do
40 | local good = false
41 | for i=1,#userTable.sectors,1 do
42 | if userTable.sectors[i].uuid == key then
43 | good = true
44 | break
45 | end
46 | end
47 | if good == false then
48 | userTable.sectorStatus[key] = nil
49 | end
50 | end
51 | for i=1,#userTable.sectors,1 do
52 | if userTable.sectorStatus[userTable.sectors[i].uuid] == nil then
53 | userTable.sectorStatus[userTable.sectors[i].uuid] = 1
54 | end
55 | end
56 | server.send(false,"getSectorList",ser.serialize({["sectors"]=userTable.sectors,["sectorStatus"]=userTable.sectorStatus}))
57 | end
58 |
59 | function module.message(command,datar) --Called when a command goes past all default commands and into modules.
60 | local data
61 | if datar ~= nil then
62 | data = ser.unserialize(datar)
63 | end
64 | if command == "sectorupdate" then
65 | local st, name = false, "ERROR"
66 | if data[2] > 0 and data[2] <= 3 then
67 | for _,value in pairs(userTable.sectors) do
68 | if value.uuid == data[1] then
69 | st = true
70 | name = value.name
71 | end
72 | end
73 | end
74 | if st then
75 | userTable.sectorStatus[data[1]] = data[2]
76 | local me = {"disabled","lockdown","open"}
77 | return true,{{["text"]="Sectors: ",["color"]=0x9924C0},{["text"]="Sector ",["color"]=nil,["line"]=false},{["text"]=name,["color"]=0x00FF00,["line"]=false},{["text"]="Status set to ",["color"]=nil,["line"]=true},{["text"]=me[data[2]],["color"]=nil,["line"]=false}},true,false,"checkSector",ser.serialize(userTable.sectorStatus)
78 | else
79 |
80 | end
81 | elseif command == "doorsector" then
82 | if data.isBio then
83 | local e,good,nome = checkMCID(data.uuid)
84 | if e then
85 | data.uuid = good
86 | data.name = nome
87 | else
88 | return true,{{["text"]="Sectors: ",["color"]=0x9924C0},{["text"]="User" .. data.uuid .. " not linked to biometrics",["color"]=0x994049}},false,true,server.crypt("false")
89 | end
90 | end
91 | for i=1,#userTable.sectors,1 do
92 | if userTable.sectors[i].uuid == data.sector then
93 | if userTable.sectorStatus[userTable.sectors[i].uuid] == 1 then
94 | return true,nil,false,true,"true"
95 | else
96 | local passed = false
97 | local user = false
98 | for j=1,#userTable.passes,1 do
99 | if string.sub(userTable.passes[j].uuid,1,-14) == data.uuid or userTable.passes[j].uuid == data.uuid then
100 | user = j
101 | break
102 | end
103 | end
104 | if user == false then
105 | return true, {{["text"]="Sectors: ",["color"]=0x9924C0},{["text"]="Sector check failed: User Not Found",["color"]=nil,["line"]=false}}, false, true, "false"
106 | end
107 | local printText = "User " .. data.name .. " failed sector check of " .. userTable.sectors[i].name
108 | for p=1,5,1 do
109 | for _,value in pairs(userTable.sectors[i].pass) do
110 | if value.priority == p then
111 | if value.uuid ~= "checkstaff" then
112 | for j=1,#userTable.passSettings.calls,1 do
113 | if userTable.passSettings.calls[j] == value.uuid then
114 | local check = function(rule)
115 | if userTable.passSettings.type[j] == "string" then
116 | return userTable.passes[user][userTable.passSettings.var[j]] == rule
117 | elseif userTable.passSettings.type[j] == "-string" then
118 | for z=1,#userTable.passes[user][userTable.passSettings.var[j]],1 do
119 | if userTable.passes[user][userTable.passSettings.var[j]][z] == rule then
120 | return true
121 | end
122 | end
123 | return false
124 | elseif userTable.passSettings.type[j] == "int" or userTable.passSettings.type[j] == "-int" then
125 | if userTable.passSettings.above[j] == false or userTable.passSettings.type[j] == "-int" then
126 | return userTable.passes[user][userTable.passSettings.var[j]] == tonumber(rule)
127 | else
128 | return userTable.passes[user][userTable.passSettings.var[j]] >= tonumber(rule)
129 | end
130 | elseif userTable.passSettings.type[j] == "bool" then
131 | return userTable.passes[user][userTable.passSettings.var[j]]
132 | end
133 | end
134 | passed = check(value.data)
135 | break
136 | end
137 | end
138 | else
139 | if userTable.passes[user].staff then
140 | passed = true
141 | end
142 | end
143 | if passed then
144 | if userTable.sectorStatus[userTable.sectors[i].uuid] == 3 and value.lock == 1 then
145 | printText = "Cannot bypass open sector " .. userTable.sectors[i].name
146 | end
147 | if value.lock == 1 then
148 | return true,nil,nil,true,"openbypass"
149 | else
150 | if data.isRFID then
151 | return true, nil, nil, true, "false"
152 | else
153 | return true, {{["text"]="Sectors: ",["color"]=0x9924C0},{["text"]="User " .. data.name .. " requested a bypass of " .. userTable.sectors[i].name,["color"]=0xFF0000,["line"]=false}},false,true,"lockbypass"
154 | end
155 | end
156 | end
157 | end
158 | end
159 | end
160 | return true, {{["text"]="Sectors: ",["color"]=0x9924C0},{["text"]=printText,["color"]=nil,["line"]=false}},false,true,"false"
161 | end
162 | end
163 | end
164 | elseif command == "doorsecupdate" then
165 | for i=1,#userTable.sectors,1 do
166 | if userTable.sectors[i].uuid == datar then
167 | userTable.sectorStatus[userTable.sectors[i].uuid] = 1
168 | return true,{{["text"]="Sectors: ",["color"]=0x9924C0},{["text"]="Sector Lockdown lifted of " .. userTable.sectors[i].name,["color"]=nil,["line"]=false}},true,false,"checkSector",ser.serialize(userTable.sectorStatus)
169 | end
170 | end
171 | else
172 |
173 | end
174 | return false
175 | end
176 |
177 | function module.piggyback(command,data) --Called after a command is passed. Passed to all modules which return nothing.
178 |
179 | end
180 |
181 | return module
--------------------------------------------------------------------------------
/sectors/sectorcontrol.lua:
--------------------------------------------------------------------------------
1 | local version = "4.0.3"
2 |
3 | local sector = {}
4 | local sectorStatus = {}
5 | local sectorSettings = {}
6 |
7 | local modemPort = 1000
8 | local syncPort = 199
9 |
10 | local component = require("component")
11 | local gpu = component.gpu
12 | local event = require("event")
13 | local ser = require("serialization")
14 | local term = require("term")
15 | local thread = require("thread")
16 | local process = require("process")
17 | local uuid = require("uuid")
18 | local computer = component.computer
19 | local keyboard = require("keyboard")
20 |
21 | local redstone = component.redstone
22 | local modem = component.modem
23 |
24 | local query
25 |
26 | local testR = true
27 | local lengthNum = 0
28 | local pageNum = 1
29 | local listNum = 1
30 |
31 | local redColorTypes = {"white","orange","magenta","light blue","yellow","lime","pink","gray","silver","cyan","purple","blue","brown","green","red","black"}
32 | local redSideTypes = {"bottom","top","back","front","right","left"}
33 |
34 | local updatePulse = false
35 |
36 | --------Table To File
37 |
38 | local function saveTable( tbl,filename )
39 | local tableFile = assert(io.open(filename, "w"))
40 | tableFile:write(ser.serialize(tbl))
41 | tableFile:close()
42 | end
43 |
44 | local function loadTable( sfile )
45 | local tableFile = io.open(sfile)
46 | if tableFile ~= nil then
47 | return ser.unserialize(tableFile:read("*all"))
48 | else
49 | return nil
50 | end
51 | end
52 |
53 | --------Base Functions
54 |
55 | local function convert( chars, dist, inv )
56 | return string.char( ( string.byte( chars ) - 32 + ( inv and -dist or dist ) ) % 95 + 32 )
57 | end
58 |
59 | local function crypt(str,k,inv)
60 | local enc= "";
61 | for i=1,#str do
62 | if(#str-k[5] >= i or not inv)then
63 | for inc=0,3 do
64 | if(i%4 == inc)then
65 | enc = enc .. convert(string.sub(str,i,i),k[inc+1],inv);
66 | break;
67 | end
68 | end
69 | end
70 | end
71 | if(not inv)then
72 | for i=1,k[5] do
73 | enc = enc .. string.char(math.random(32,126));
74 | end
75 | end
76 | return enc;
77 | end
78 |
79 | local function splitString(str, sep)
80 | local sep, fields = sep or ":", {}
81 | local pattern = string.format("([^%s]+)", sep)
82 | str:gsub(pattern, function(c) fields[#fields+1] = c end)
83 | return fields
84 | end
85 |
86 | local function deepcopy(orig)
87 | local orig_type = type(orig)
88 | local copy
89 | if orig_type == 'table' then
90 | copy = {}
91 | for orig_key, orig_value in next, orig, nil do
92 | copy[deepcopy(orig_key)] = deepcopy(orig_value)
93 | end
94 | setmetatable(copy, deepcopy(getmetatable(orig)))
95 | else -- number, string, boolean, etc
96 | copy = orig
97 | end
98 | return copy
99 | end
100 |
101 | local function setGui(pos, text, wrap, color)
102 | term.setCursor(1,pos)
103 | term.clearLine()
104 | if color then gpu.setForeground(color) else gpu.setForeground(0xFFFFFF) end
105 | if wrap then print(text) else term.write(text) end
106 | end
107 |
108 | local function pageChange(dir,pos,length,call,...)
109 | if dir == "hor" then
110 | if type(pos) == "boolean" then
111 | if pos then
112 | if pageNum < length then
113 | pageNum = pageNum + 1
114 | end
115 | else
116 | if pageNum > 1 then
117 | pageNum = pageNum - 1
118 | end
119 | end
120 | else
121 | pageNum = pos
122 | end
123 | elseif dir == "ver" then
124 | if type(pos) == "boolean" then
125 | if pos then
126 | if listNum < length + 1 then
127 | listNum = listNum + 1
128 | end
129 | else
130 | if listNum > 1 then
131 | listNum = listNum - 1
132 | end
133 | end
134 | else
135 | listNum = pos
136 | end
137 | elseif dir == "setup" then
138 | pageNum = pos
139 | listNum = 1
140 | end
141 | call(...)
142 | end
143 |
144 | -- removed AutoUpdate function due to being unnecessary to the checking of if a change was detected
145 |
146 | --------Called Functions
147 |
148 | local function colorSearch(color,side)
149 | local c,s = -1,-1
150 | if type(color) == "number" then
151 | c = color
152 | else
153 | for i=1,#redColorTypes,1 do
154 | if redColorTypes[i] == color then
155 | c = i - 1
156 | end
157 | end
158 | end
159 | for i=1,#redSideTypes,1 do
160 | if type(side) == "number" then
161 | s = side
162 | else
163 | if redSideTypes[i] == side then
164 | s = i - 1
165 | end
166 | end
167 | end
168 | return c,s
169 | end
170 |
171 | local function redlinkcheck(color,side)
172 | for key,value in pairs(sectorSettings) do
173 | if key ~= "cryptKey" and key ~= "port" then --We don't want cryptKey or port being used
174 | if value.open.color == color and value.open.side == side then
175 | sectorSettings[key].open.color = -1
176 | sectorSettings[key].open.side = -1
177 | end
178 | if value.lock.color == color and value.lock.side == side then
179 | sectorSettings[key].lock.side = -1
180 | sectorSettings[key].lock.color = -1
181 | end
182 | if value.disable.color == color and value.disable.side == side then
183 | sectorSettings[key].disable.side = -1
184 | sectorSettings[key].disable.color = -1
185 | end
186 | end
187 | end
188 | end
189 |
190 | local function arrangeSectors(query)
191 | sector = {}
192 | local amt = (#query) * 3
193 | local count = 1
194 | local save = false
195 | for i=1,math.ceil(amt/9),1 do
196 | sector[i] = {}
197 | for j=1,3,1 do
198 | if query[count] ~= nil then
199 | sector[i][j] = deepcopy(query[count])
200 | if sectorSettings[query[count].uuid] == nil then
201 | sectorSettings[query[count].uuid] = {["open"]={["side"]=-1,["color"]=-1},["lock"]={["side"]=-1,["color"]=-1},["disable"]={["side"]=-1,["color"]=-1}}
202 | save = true
203 | end
204 | count = count + 1
205 | end
206 | end
207 | end
208 | for key,value in pairs(sectorSettings) do
209 | local here = false
210 | if key == "cryptKey" or key == "port" then
211 | here = true
212 | else
213 | for i=1,#query,1 do
214 | if query[i].uuid == key then
215 | here = true
216 | break
217 | end
218 | end
219 | end
220 | if here == false then
221 | sectorSettings[key] = nil
222 | save = true
223 | end
224 | end
225 | if save then
226 | saveTable(sectorSettings,"sectorsetup.txt")
227 | end
228 | end
229 |
230 | local function sectorGui(editmode)
231 | setGui(1,"Sector Control Program")
232 | if #sector == 0 then
233 | setGui(2,"Create a sector to begin")
234 | else
235 | setGui(2,"Page " .. pageNum .. "/" .. #sector)
236 | setGui(3,"")
237 | setGui(4,"------------------------------")
238 | local pre, count = "> ",1
239 | if (#sector[pageNum] * 3) < listNum then
240 | listNum = (#sector[pageNum] * 3)
241 | end
242 | if listNum == count then
243 | pre = "> "
244 | else
245 | pre = " "
246 | end
247 | for i=1,#sector[pageNum],1 do
248 | local secKeys = {["disable"] = "Clear sector ",["lock"] = "Lockdown sector ",["open"] = "Open sector "}
249 | for j=1,3,1 do
250 | local key = ""
251 | if j == 1 then
252 | key = "open"
253 | elseif j == 2 then
254 | key = "lock"
255 | else
256 | key = "disable"
257 | end
258 | if listNum == count then
259 | pre = "> "
260 | else
261 | pre = " "
262 | end
263 | setGui(count + 4,sectorSettings[sector[pageNum][i].uuid][key].side ~= -1 and pre .. value .. sector[pageNum][i].name .. ": " .. redSideTypes[sectorSettings[sector[pageNum][i].uuid][key].side + 1] .. " : " .. redColorTypes[sectorSettings[sector[pageNum][i].uuid][key].color + 1] or pre .. value .. sector[pageNum][i].name .. ": " .. "unlinked : unlinked")
264 | count = count + 1
265 | end
266 | end
267 | count = count + 4
268 | setGui(count,"------------------------------")
269 | end
270 | end
271 |
272 | --------Main Program
273 |
274 | term.clear()
275 | local fill = io.open("redstonelinks.txt", "r")
276 | if fill~=nil then
277 | io.close(fill)
278 | else
279 | modem.open(syncPort)
280 | modem.broadcast(syncPort,"syncport")
281 | local e,_,_,_,_,msg = event.pull(1,"modem_message")
282 | modem.close(syncPort)
283 | if e then
284 | modemPort = tonumber(msg)
285 | else
286 | print("What port is the server running off of?")
287 | local text = term.read()
288 | modemPort = tonumber(text:sub(1,-2))
289 | term.clear()
290 | end
291 |
292 | saveTable({["cryptKey"]={1,2,3,4,5},["port"]=modemPort},"redstonelinks.txt")
293 | print("Crypt key is set to default (1,2,3,4,5)")
294 | end
295 |
296 | sectorSettings = loadTable("redstonelinks.txt")
297 |
298 | if sectorSettings.cryptKey == nil then
299 | sectorSettings.cryptKey = {1,2,3,4,5}
300 | print("Crypt key is set to default (1,2,3,4,5)")
301 | modem.open(syncPort)
302 | modem.broadcast(syncPort,"syncport")
303 | local e,_,_,_,_,msg = event.pull(1,"modem_message")
304 | modem.close(syncPort)
305 | if e then
306 | modemPort = tonumber(msg)
307 | else
308 | print("What port is the server running off of?")
309 | local text = term.read()
310 | modemPort = tonumber(text:sub(1,-2))
311 | term.clear()
312 | end
313 | sectorSettings.port = modemPort
314 | saveTable(sectorSettings,"redstonelinks.txt")
315 | end
316 | if sectorSettings.default ~= nil then
317 | sectorSettings.default = nil
318 | for key, value in pairs(sectorSettings) do
319 | if key ~= "cryptKey" and key ~= "port" then
320 | value.disable = {["side"]=-1,["color"]=-1}
321 | end
322 | end
323 | end
324 |
325 | modemPort = sectorSettings.port
326 |
327 | print("Sending query to server...")
328 | modem.open(modemPort)
329 | modem.broadcast(modemPort,"getquery",ser.serialize({"sectors"})) --TODO: Remove all sectorStatus calls
330 | local e,_,_,_,_,msg = event.pull(3,"modem_message")
331 | modem.close(modemPort)
332 | if e == nil then
333 | print("No query received. Assuming old server system is in place and will not work")
334 | os.exit()
335 | else
336 | print("Query received")
337 | msg = crypt(msg,sectorSettings.cryptKey,true)
338 | query = ser.unserialize(msg).data.sectors
339 | end
340 | modem.open(modemPort)
341 |
342 | arrangeSectors(query)
343 |
344 | --[[thread.create(function() --Unneeded function.
345 | while true do
346 | local ev, p1, p2, p3, p4, p5 = event.pull("key_down")
347 | local char = tonumber(keyboard.keys[p3])
348 | if char ~= nil then
349 | if char > 0 then
350 | if char <= lengthNum then
351 | event.push("numInput",char)
352 | lengthNum = 0
353 | end
354 | end
355 | end
356 | end
357 | end)]]
358 |
359 | local editmode = false
360 |
361 | pageChange("setup",1,#sector, sectorGui, editmode)
362 |
363 | while true do
364 | local ev,num,side,key,value,command,msg = event.pullMultiple("modem_message","redstone_changed","key_down")
365 | if #sector ~= 0 then
366 | if ev == "modem_message" then
367 | if command == "getSectorList" then
368 | query = ser.unserialize(msg).sectors
369 | arrangeSectors(query)
370 | pageChange("setup",1,#sector, sectorGui, editmode)
371 | end
372 | elseif ev == "key_down" then
373 | if editmode == false then
374 | local char = keyboard.keys[key]
375 | if char == "left" then
376 | term.clear()
377 | pageChange("hor",false,#sector, sectorGui, editmode)
378 | os.sleep(0.5)
379 | elseif char == "right" then
380 | term.clear()
381 | pageChange("hor",true,#sector, sectorGui, editmode)
382 | os.sleep(0.5)
383 | elseif char == "up" then
384 | term.clear()
385 | pageChange("ver",false,(#sector[pageNum]*2) + 1, sectorGui, editmode)
386 | os.sleep(0.5)
387 | elseif char == "down" then
388 | term.clear()
389 | pageChange("ver",true,(#sector[pageNum]*2) + 1, sectorGui, editmode)
390 | os.sleep(0.5)
391 | elseif char == "enter" then
392 | setGui(20,"Which side should redstone input from?")
393 | term.setCursor(1,21)
394 | term.clearLine()
395 | local side = term.read():sub(1,-2)
396 | if tonumber(side) ~= nil then
397 | side = tonumber(side)
398 | end
399 | setGui(20,"Which color should be checked?")
400 | term.setCursor(1,21)
401 | term.clearLine()
402 | local color = term.read():sub(1,-2)
403 | if tonumber(color) ~= nil then
404 | color = tonumber(color)
405 | end
406 | color, side = colorSearch(color,side)
407 | if color ~= -1 and side ~= -1 then
408 | redlinkcheck(color,side)
409 | if (listNum)%3 == 0 then
410 | sectorSettings[sector[pageNum][math.ceil((listNum)/3)].uuid].disable.color = color
411 | sectorSettings[sector[pageNum][math.ceil((listNum)/3)].uuid].disable.side = side
412 | elseif (listNum)%3 == 2 then
413 | sectorSettings[sector[pageNum][math.ceil((listNum)/3)].uuid].lock.color = color
414 | sectorSettings[sector[pageNum][math.ceil((listNum)/3)].uuid].lock.side = side
415 | else
416 | sectorSettings[sector[pageNum][math.ceil((listNum)/3)].uuid].open.color = color
417 | sectorSettings[sector[pageNum][math.ceil((listNum)/3)].uuid].open.side = side
418 | end
419 | end
420 | saveTable(sectorSettings,"redstonelinks.txt")
421 | pageChange("hor",pageNum,#sector, sectorGui, editmode)
422 | os.sleep(0.5)
423 | elseif char == "back" then
424 | if (listNum)%3 == 0 then
425 | sectorSettings[sector[pageNum][math.ceil((listNum)/3)].uuid].disable.color = -1
426 | sectorSettings[sector[pageNum][math.ceil((listNum)/3)].uuid].disable.side = -1
427 | elseif (listNum)%3 == 2 then
428 | sectorSettings[sector[pageNum][math.ceil((listNum)/3)].uuid].lock.color = -1
429 | sectorSettings[sector[pageNum][math.ceil((listNum)/3)].uuid].lock.side = -1
430 | else
431 | sectorSettings[sector[pageNum][math.ceil((listNum)/3)].uuid].open.color = -1
432 | sectorSettings[sector[pageNum][math.ceil((listNum)/3)].uuid].open.side = -1
433 | end
434 | pageChange("hor",pageNum,#sector, sectorGui, editmode)
435 | os.sleep(0.5)
436 | end
437 | end
438 | elseif ev == "redstone_changed" then
439 | local officialChange = {false} --If the change in redstone is something saved to redstonelinks.txtr
440 | if key == 0 and value > 0 then
441 | for i=1,#query,1 do
442 | if sectorSettings[query[i].uuid].open.side == side and sectorSettings[query[i].uuid].open.color == command then
443 | officialChange[1] = true
444 | officialChange[2] = query[i].uuid
445 | officialChange[3] = side
446 | officialChange[4] = command
447 | officialChange[5] = 3
448 | break
449 | end
450 | if sectorSettings[query[i].uuid].lock.side == side and sectorSettings[query[i].uuid].lock.color == command then
451 | officialChange[1] = true
452 | officialChange[2] = query[i].uuid
453 | officialChange[3] = side
454 | officialChange[4] = command
455 | officialChange[5] = 2
456 | break
457 | end
458 | if sectorSettings[query[i].uuid].disable.side == side and sectorSettings[query[i].uuid].disable.color == command then
459 | officialChange[1] = true
460 | officialChange[2] = query[i].uuid
461 | officialChange[3] = side
462 | officialChange[4] = command
463 | officialChange[5] = 1
464 | break
465 | end
466 | --[[if sectorStatus[query[i].uuid] ~= current then --a change was detected
467 | officialChange = true
468 | end]]
469 | end
470 | end
471 | if officialChange[1] then
472 | modem.broadcast(modemPort,"sectorupdate",crypt(ser.serialize({officialChange[2],officialChange[5]}),sectorSettings.cryptKey))
473 | end
474 | end
475 | else
476 | os.sleep(1)
477 | end
478 | end
479 |
--------------------------------------------------------------------------------
/sectors/sectorcontrolgui.lua:
--------------------------------------------------------------------------------
1 | local version = "4.0.2"
2 |
3 | local sector = {}
4 | local sectorStatus = {}
5 | local sectorSettings = {}
6 |
7 | local modemPort = 1000
8 | local syncPort = 199
9 |
10 | local component = require("component")
11 | local gpu = component.gpu
12 | local event = require("event")
13 | local ser = require("serialization")
14 | local term = require("term")
15 | local thread = require("thread")
16 | local process = require("process")
17 | local uuid = require("uuid")
18 | local computer = component.computer
19 | local keyboard = require("keyboard")
20 |
21 | --local redstone = component.redstone
22 | local modem = component.modem
23 |
24 | local query
25 |
26 | local testR = true
27 | local lengthNum = 0
28 | local pageNum = 1
29 | local listNum = 1
30 | local secid
31 |
32 | local redColorTypes = {"white","orange","magenta","light blue","yellow","lime","pink","gray","silver","cyan","purple","blue","brown","green","red","black"}
33 | local redSideTypes = {"bottom","top","back","front","right","left"}
34 |
35 | local updatePulse = false
36 |
37 | --------Table To File
38 |
39 | local function saveTable( tbl,filename )
40 | local tableFile = assert(io.open(filename, "w"))
41 | tableFile:write(ser.serialize(tbl))
42 | tableFile:close()
43 | end
44 |
45 | local function loadTable( sfile )
46 | local tableFile = io.open(sfile)
47 | if tableFile ~= nil then
48 | return ser.unserialize(tableFile:read("*all"))
49 | else
50 | return nil
51 | end
52 | end
53 |
54 | --------Base Functions
55 |
56 | local function convert( chars, dist, inv )
57 | return string.char( ( string.byte( chars ) - 32 + ( inv and -dist or dist ) ) % 95 + 32 )
58 | end
59 |
60 | local function crypt(str,k,inv)
61 | local enc= "";
62 | for i=1,#str do
63 | if(#str-k[5] >= i or not inv)then
64 | for inc=0,3 do
65 | if(i%4 == inc)then
66 | enc = enc .. convert(string.sub(str,i,i),k[inc+1],inv);
67 | break;
68 | end
69 | end
70 | end
71 | end
72 | if(not inv)then
73 | for i=1,k[5] do
74 | enc = enc .. string.char(math.random(32,126));
75 | end
76 | end
77 | return enc;
78 | end
79 |
80 | local function deepcopy(orig)
81 | local orig_type = type(orig)
82 | local copy
83 | if orig_type == 'table' then
84 | copy = {}
85 | for orig_key, orig_value in next, orig, nil do
86 | copy[deepcopy(orig_key)] = deepcopy(orig_value)
87 | end
88 | setmetatable(copy, deepcopy(getmetatable(orig)))
89 | else -- number, string, boolean, etc
90 | copy = orig
91 | end
92 | return copy
93 | end
94 |
95 | local function setGui(pos, text, wrap, color)
96 | term.setCursor(1,pos)
97 | term.clearLine()
98 | if color then gpu.setForeground(color) else gpu.setForeground(0xFFFFFF) end
99 | if wrap then print(text) else term.write(text) end
100 | end
101 |
102 | local function pageChange(dir,pos,length,call,...)
103 | if dir == "hor" then
104 | if pos then
105 | if pageNum < length then
106 | pageNum = pageNum + 1
107 | end
108 | else
109 | if pageNum > 1 then
110 | pageNum = pageNum - 1
111 | end
112 | end
113 | elseif dir == "ver" then
114 | if pos then
115 | if listNum < length + 1 then
116 | listNum = listNum + 1
117 | end
118 | else
119 | if listNum > 1 then
120 | listNum = listNum - 1
121 | end
122 | end
123 | elseif dir == "setup" then
124 | pageNum = pos
125 | listNum = 1
126 | end
127 | call(...)
128 | end
129 |
130 | -- removed AutoUpdate function due to being unnecessary to the checking of if a change was detected
131 |
132 | --------Called Functions
133 |
134 | local function arrangeSectors(query)
135 | sector = {}
136 | local amt = (#query) * 3
137 | local count = 1
138 | local save = false
139 | for i=1,math.ceil(amt/9),1 do
140 | sector[i] = {}
141 | for j=1,3,1 do
142 | if query[count] ~= nil then
143 | sector[i][j] = deepcopy(query[count])
144 | if sectorSettings[query[count].uuid] == nil then
145 | sectorSettings[query[count].uuid] = {status=1}
146 | save = true
147 | end
148 | count = count + 1
149 | end
150 | end
151 | end
152 | for key,value in pairs(sectorSettings) do
153 | local here = false
154 | if key == "cryptKey" or key == "port" then
155 | here = true
156 | else
157 | for i=1,#query,1 do
158 | if query[i].uuid == key then
159 | here = true
160 | break
161 | end
162 | end
163 | end
164 | if here == false then
165 | sectorSettings[key] = nil
166 | save = true
167 | end
168 | end
169 | if save then
170 | saveTable(sectorSettings,"redstonelinks.txt")
171 | end
172 | end
173 |
174 | local function sectorGui(editmode)
175 | setGui(1,"Sector Control Program")
176 | local aft = " "
177 | if #sector == 0 then
178 | setGui(2,"Create a sector to begin")
179 | else
180 | setGui(2,"Page " .. pageNum .. "/" .. #sector)
181 | setGui(3,"")
182 | setGui(4,"------------------------------")
183 | local pre, count = "> ",1
184 | if (#sector[pageNum] * 3) < listNum then
185 | listNum = (#sector[pageNum] * 3)
186 | end
187 | if listNum == count then
188 | pre = "> "
189 | else
190 | pre = " "
191 | end
192 | for i=1,#sector[pageNum],1 do
193 | local secKeys = {[2] = "Clear",[1] = "Lockdown",[3] = "Open"}
194 | for key,value in ipairs(secKeys) do
195 | if listNum == count then
196 | pre = "> "
197 | else
198 | pre = " "
199 | end
200 | setGui(count + 4, pre .. sector[pageNum][i].name .. " : " .. value)
201 | count = count + 1
202 | end
203 | end
204 | count = count + 4
205 | setGui(count,"------------------------------")
206 | end
207 | end
208 |
209 | --------Main Program
210 |
211 | term.clear()
212 | local fill = io.open("redstonelinks.txt", "r")
213 | if fill~=nil then
214 | io.close(fill)
215 | else
216 | modem.open(syncPort)
217 | modem.broadcast(syncPort,"syncport")
218 | local e,_,_,_,_,msg = event.pull(1,"modem_message")
219 | modem.close(syncPort)
220 | if e then
221 | modemPort = tonumber(msg)
222 | else
223 | print("What port is the server running off of?")
224 | local text = term.read()
225 | modemPort = tonumber(text:sub(1,-2))
226 | term.clear()
227 | end
228 |
229 | saveTable({["cryptKey"]={1,2,3,4,5},["port"]=modemPort},"redstonelinks.txt")
230 | print("Crypt key is set to default (1,2,3,4,5)")
231 | end
232 |
233 | sectorSettings = loadTable("redstonelinks.txt")
234 |
235 | if sectorSettings.cryptKey == nil then
236 | sectorSettings.cryptKey = {1,2,3,4,5}
237 | print("Crypt key is set to default (1,2,3,4,5)")
238 | modem.open(syncPort)
239 | modem.broadcast(syncPort,"syncport")
240 | local e,_,_,_,_,msg = event.pull(1,"modem_message")
241 | modem.close(syncPort)
242 | if e then
243 | modemPort = tonumber(msg)
244 | else
245 | print("What port is the server running off of?")
246 | local text = term.read()
247 | modemPort = tonumber(text:sub(1,-2))
248 | term.clear()
249 | end
250 | sectorSettings.port = modemPort
251 | saveTable(sectorSettings,"redstonelinks.txt")
252 | end
253 | if sectorSettings.default ~= nil then
254 | sectorSettings.default = nil
255 | for key, value in pairs(sectorSettings) do
256 | if key ~= "cryptKey" and key ~= "port" then
257 | value.disable = {["side"]=-1,["color"]=-1}
258 | end
259 | end
260 | end
261 |
262 | modemPort = sectorSettings.port
263 |
264 | print("Sending query to server...")
265 | modem.open(modemPort)
266 | modem.broadcast(modemPort,"getquery",ser.serialize({"sectors"})) --TODO: Remove all sectorStatus calls
267 | local e,_,_,_,_,msg = event.pull(3,"modem_message")
268 | modem.close(modemPort)
269 | if e == nil then
270 | print("No query received. Assuming old server system is in place and will not work")
271 | os.exit()
272 | else
273 | print("Query received")
274 | msg = crypt(msg,sectorSettings.cryptKey,true)
275 | query = ser.unserialize(msg).data.sectors
276 | end
277 | modem.open(modemPort)
278 |
279 | arrangeSectors(query)
280 |
281 | --[[thread.create(function() --Unneeded function.
282 | while true do
283 | local ev, p1, p2, p3, p4, p5 = event.pull("key_down")
284 | local char = tonumber(keyboard.keys[p3])
285 | if char ~= nil then
286 | if char > 0 then
287 | if char <= lengthNum then
288 | event.push("numInput",char)
289 | lengthNum = 0
290 | end
291 | end
292 | end
293 | end
294 | end)]]
295 |
296 | local editmode = false
297 |
298 | pageChange("setup",1,#sector, sectorGui, editmode)
299 |
300 | while true do
301 | local ev,num,side,key,value,command,msg = event.pullMultiple("modem_message","redstone_changed","key_down")
302 | local state = 1
303 | editmode = false
304 | if #sector ~= 0 then
305 | if ev == "modem_message" then
306 | if command == "getSectorList" then
307 | query = ser.unserialize(msg).sectors
308 | arrangeSectors(query)
309 | end
310 | elseif ev == "key_down" then
311 | if editmode == false then
312 | local char = keyboard.keys[key]
313 | if char == "left" then
314 | term.clear()
315 | pageChange("hor",false,#sector, sectorGui, editmode)
316 | os.sleep(0.1)
317 | elseif char == "right" then
318 | term.clear()
319 | pageChange("hor",true,#sector, sectorGui, editmode)
320 | os.sleep(0.1)
321 | elseif char == "up" then
322 | term.clear()
323 | pageChange("ver",false,(#sector[pageNum]*3), sectorGui, editmode)
324 | os.sleep(0.1)
325 | elseif char == "down" then
326 | term.clear()
327 | pageChange("ver",true,(#sector[pageNum]*3), sectorGui, editmode)
328 | os.sleep(0.1)
329 | elseif char == "enter" then
330 | if listNum == 3 or listNum == 6 or listNum == 9 then state = 3 elseif listNum == 1 or listNum == 4 or listNum == 7 then state = 2 else state = 1 end
331 | if listNum <= 3 then
332 | if pageNum == 1 then
333 | secid = query[1]
334 | else
335 | secid = query[1+((pageNum-1)*3)]
336 | end
337 | elseif listNum <= 6 then
338 | if pageNum == 1 then
339 | secid = query[2]
340 | else
341 | secid = query[2+((pageNum-1)*3)]
342 | end
343 | else
344 | if pageNum == 1 then
345 | secid = query[3]
346 | else
347 | secid = query[3+((pageNum-1)*3)]
348 | end
349 | end
350 | modem.broadcast(modemPort,"sectorupdate",crypt(ser.serialize({secid.uuid,state}),sectorSettings.cryptKey))
351 | os.sleep(0.1)
352 | end
353 | end
354 | end
355 |
356 | else
357 | os.sleep(1)
358 | end
359 | end
360 |
--------------------------------------------------------------------------------
/security/Database Module/Main.lua:
--------------------------------------------------------------------------------
1 | local module = {}
2 | local component = require("component")
3 | local ser = require("serialization")
4 | local GUI = require("GUI")
5 | local scanner --if biometric reader is connected this isn't nil
6 | local writer --Card reader
7 |
8 | local handler --Holds the handler for cardinsert and cardremoval events in cardwriter
9 |
10 | local permissions = {} --Holds current user's permissions whos signed in
11 |
12 | local userTable
13 |
14 | local workspace, window, loc, database, style, compat = table.unpack({...})
15 | local system, fs, event
16 | if compat == nil then
17 | system = require("System") --Set it to the MineOS
18 | fs = require("Filesystem")
19 | event = require("event")
20 | else
21 | system = compat.system
22 | fs = compat.fs
23 | event = compat.event
24 | end
25 |
26 | module.name = "Security"
27 | module.table = {"passes","passSettings","securityKeypads"} --passes is all card accounts; passSettings are the modular passes people can create
28 | module.debug = false
29 | module.config = {["secAPI"] = {["label"] = "Security API",["type"]="bool",["default"]=true,["server"]=true},["quickMCLink"] = {["label"] = "Allow quikidlink?",["type"]="bool",["default"]=false,["server"]=true}} --secAPI allows getVar and setVar commands by securityAPI; quikIDLink allows use of quikidlink program to link user with seperate bio reader
30 |
31 | module.init = function(usTable)
32 | userTable = usTable
33 | end
34 |
35 | if component.isAvailable("os_cardwriter") then --see if it exists, otherwise close/crash program.
36 | writer = component.os_cardwriter
37 | else
38 | GUI.alert(loc.cardwriteralert)
39 | return
40 | end
41 | if component.isAvailable("os_biometric") then --see if it exists, otherwise you can't link user biometrics
42 | scanner = component.os_biometric
43 | end
44 |
45 | module.onTouch = function()
46 | local tabWindow, tabs, cardStatusLabel, selected
47 | local userEdit, passEdit
48 | do --keep it contained to remove memory after done
49 | local result, reason = loadfile(fs.path(system.getCurrentScript()) .. "Modules/modid" .. tostring(module.id) .. "/pass.lua")
50 | if result then
51 | passEdit = result
52 | else
53 | GUI.alert("Failed to load file pass.lua: " .. tostring(reason))
54 | end
55 | result, reason = loadfile(fs.path(system.getCurrentScript()) .. "Modules/modid" .. tostring(module.id) .. "/user.lua")
56 | if result then
57 | userEdit = result
58 | else
59 | GUI.alert("Failed to load file user.lua: " .. tostring(reason))
60 | end
61 | end
62 |
63 | local function migrateTab(_, button)
64 | if not button.doTheMove then
65 | tabWindow:removeChildren()
66 | end
67 | if selected ~= button.myId then
68 | local success, result = pcall(button.toRun, workspace, tabWindow, loc, database, style, permissions, userTable)
69 | if not success then
70 | GUI.alert("Failed to run file: " .. tostring(result))
71 | end
72 | workspace:draw()
73 | selected = button.myId
74 | end
75 | end
76 |
77 | --Database name and stuff and CardWriter
78 |
79 | local function eventCallback(ev, id) --changing text of label if user inserts or removes all cards from cardwriter
80 | if ev == "cardInsert" then
81 | cardStatusLabel.text = loc.cardpresent
82 | elseif ev == "cardRemove" then
83 | cardStatusLabel.text = loc.cardabsent
84 | end
85 | end
86 |
87 | window:addChild(GUI.panel(123,1,12,3,style.cardStatusPanel))
88 | cardStatusLabel = window:addChild(GUI.label(124, 2, 10,1,style.cardStatusLabel,loc.cardabsent))
89 | handler = event.addhandler(eventCallback) --create callback to the handler to check for cardinsert and cardremoval
90 |
91 | tabWindow = window:addChild(GUI.container(1,4,window.width,window.height - 3))
92 | tabs = window:addChild(GUI.list(1, 1, 75, 3, 2, 0, style.listBackground, style.listText, style.listAltBack, style.listAltText, style.listSelectedBack, style.listSelectedText, true))
93 | tabs:setDirection(GUI.DIRECTION_HORIZONTAL)
94 | tabs:setAlignment(GUI.ALIGNMENT_HORIZONTAL_CENTER, GUI.ALIGNMENT_VERTICAL_TOP)
95 | local meh = tabs:addItem("Cards")
96 | meh.onTouch = migrateTab
97 | meh.myId = 1
98 | meh.toRun = userEdit
99 | meh = tabs:addItem("Passes / Keypad")
100 | meh.onTouch = migrateTab
101 | meh.myId = 2
102 | meh.toRun = passEdit
103 | meh.disabled = database.checkPerms("security",{"varmanagement","keypad"},true)
104 |
105 | tabs.selected = 1
106 | migrateTab(nil, {["doTheMove"]=true,["myId"]=1,["toRun"]=userEdit})
107 | end
108 |
109 | module.close = function() --when user switches modules
110 | event.removehandler(handler) --don't keep looking for event
111 | return {"passes","passSettings"} --returns what I want updated (if autoupdate enabled)
112 | end
113 |
114 | return module
115 |
--------------------------------------------------------------------------------
/security/Database Module/Pass.lua:
--------------------------------------------------------------------------------
1 | --A second file I created to be able to store all the pass editing in a seperate file
2 | local workspace, window, loc, database, style, permissions, userTable = table.unpack({...})
3 |
4 | local component = require("component")
5 | local ser = require("serialization")
6 | local GUI = require("GUI")
7 | local uuid = require("uuid")
8 | local modem = component.modem
9 |
10 | local modemPort = 199
11 |
12 | --Variable declarations for keypad stuff
13 | local padBox, padLabel, padPass, padNew, padNewKey, padDel
14 | local canPad = database.checkPerms("security",{"varmanagement","keypad"},true) --whether they have keypad perms
15 | local canPass = database.checkPerms("security",{"varmanagement"},true)
16 |
17 | local function split(s, delimiter) --splits string to table. "e,f,g" to {"e","f","g"}
18 | local result = {};
19 | for match in (s..delimiter):gmatch("(.-)"..delimiter) do
20 | table.insert(result, match);
21 | end
22 | return result;
23 | end
24 |
25 | local function keypadCallback(_,button)
26 | if padBox:count() > 0 then
27 | local selected = padBox.selectedItem
28 | if button == nil then
29 | button = padBox:getItem(selected)
30 | end
31 | padLabel.text = userTable.securityKeypads[button.key].label
32 | padPass.text = canPad and "****" or userTable.securityKeypads[button.key].pass
33 | padLabel.disabled = canPad
34 | padPass.disabled = canPad
35 | end
36 | end
37 |
38 | local function updateKeyList()
39 | database.save()
40 | local selected = padBox.selectedItem
41 | if padBox:count() > 0 then
42 | padBox:clear()
43 | end
44 | for key,value in pairs(userTable.securityKeypads) do
45 | local meh = padBox:addItem(key)
46 | meh.key = key
47 | meh.onTouch = keypadCallback
48 | end
49 | if padBox:count() < selected then
50 | selected = selected - 1
51 | end
52 | padDel.disabled = true
53 | if padBox:count() ~= 0 then
54 | padDel.disabled = false
55 | padBox.selectedItem = selected
56 | end
57 | database.update({"securityKeypads"})
58 | end
59 |
60 | local function padNewF()
61 | if padNewKey.text ~= "" then
62 | userTable.securityKeypads[padNewKey.text] = {["pass"]="1234",["label"]=padNewKey.text}
63 | padNewKey.text = ""
64 | updateKeyList()
65 | end
66 | end
67 |
68 | local function padDelF()
69 | local selected = padBox.selectedItem
70 | local sel = padBox:getItem(selected)
71 | userTable.securityKeypads[sel.key] = nil
72 | padLabel.disabled = true
73 | padPass.disabled = true
74 | updateKeyList()
75 | end
76 |
77 | local function passLabelCallback()
78 | local selected = padBox:getItem(padBox.selectedItem)
79 | userTable.securityKeypads[selected.key].label = padLabel.text
80 | end
81 |
82 | local function passInputCallback()
83 | local selected = padBox:getItem(padBox.selectedItem)
84 | if tonumber(padPass.text) ~= nil and tonumber(padPass.text) >= 1000 and tonumber(padPass.text) <= 9999 then
85 | userTable.securityKeypads[selected.key].pass = padPass.text
86 | else
87 | padPass.text = userTable.securityKeypads[selected.key].pass
88 | end
89 | end
90 |
91 | --Variable declarations for Variable pass stuff
92 | local addVarButton, delVarButton, editVarButton, updateVarButton, clearVarButton, varList, varLabel, varDesc
93 | local varKeyInput, varLabelInput, varTypeSelect, addVarArray, extraVar, extraVar2 --NOTE: Updatevarbutton works in both add and edit mode
94 | local varMode = "none" --Indicates the mode, so pressing add button knows what to do when pressed. add means that a new one is added to the list. edit means var will be edited. none means nothing will happen (just in case)
95 |
96 | local function passComboPress()
97 | local describe = {["string"]="Regular String",["-string"]="Multi String",["int"]="Level",["-int"]="Group",["bool"]="Bool"}
98 | local selected = varList.selectedItem
99 | varLabel.text = "Label: " .. userTable.passSettings.label[selected]
100 | varDesc.text = "Desc: " .. describe[userTable.passSettings.type[selected]]
101 | if userTable.passSettings.type[selected] == "string" or userTable.passSettings.type[selected] == "-string" then
102 | varDesc.text = varDesc.text .. " | " .. (userTable.passSettings.data[selected] == 1 and "Editable" or userTable.passSettings.data[selected] == 2 and "Uneditable" or "Hidden")
103 | elseif userTable.passSettings.type[selected] == "int" then
104 | varDesc.text = varDesc.text .. " | " .. (userTable.passSettings.above[selected] and "Checks above" or "Checks exact")
105 | elseif userTable.passSettings.type[selected] == "-int" then
106 | varDesc.text = varDesc.text .. " | " .. tostring(#userTable.passSettings.data[selected]) .. " groups"
107 | end
108 | editVarButton.disabled = userTable.passSettings.type[selected] == "bool" and true or false
109 | delVarButton.disabled = false
110 | end
111 |
112 | local function updatePassCombo()
113 | if varList:count() > 0 then
114 | varList:clear()
115 | end
116 | for i=1,#userTable.passSettings.var,1 do
117 | local k = varList:addItem(userTable.passSettings.var[i])
118 | k.onTouch = passComboPress
119 | end
120 | varLabel.text = "Label: NAN"
121 | varDesc.text = "Desc: NAN"
122 | editVarButton.disabled = true
123 | delVarButton.disabled = true
124 | end
125 |
126 | local function checkTypeCallback() --Used when creating a var and choosing the type of var, or if editing
127 | local typeArray = {"string","-string","int","-int","bool"}
128 | local selected = varTypeSelect.selectedItem
129 | if varMode == "add" then --if add, it sets it all to default
130 | addVarArray.above = false
131 | addVarArray.data = false
132 | addVarArray.type = typeArray[selected]
133 | end
134 | if extraVar ~= nil then --if already populated, remove first so it can be readded
135 | extraVar:remove()
136 | extraVar = nil
137 | end
138 | --Merged edit and add mode checks
139 | if selected == 3 then --int (number)
140 | extraVar = window:addChild(GUI.button(36,19,32,1, style.containerButton,style.containerText,style.containerSelectButton,style.containerSelectText, loc.newvarcheckabove))
141 | extraVar.onTouch = function() --a button to determine whether to check above or not. Checkabove means if needed 1 and they have 3, it lets them in. If false, 3 doesn't work
142 | addVarArray.above = extraVar.pressed
143 | end
144 | extraVar.switchMode = true
145 | if varMode == "edit" then
146 | extraVar.pressed = addVarArray.above
147 | else
148 | addVarArray.data = false
149 | end
150 | elseif selected == 4 then -- -int (groups)
151 | extraVar = window:addChild(GUI.input(36,19,32,1, style.containerInputBack,style.containerInputText,style.containerInputPlaceholder,style.containerInputFocusBack,style.containerInputFocusText, "", loc.newvargroup))
152 | extraVar.onInputFinished = function() --Input the groups into a textbox splitting with a comma
153 | addVarArray.data = split(extraVar.text,",")
154 | end
155 | if varMode == "edit" then
156 | local isme = addVarArray.data[1]
157 | for i=2,#addVarArray.data,1 do --combine back into a string to be rejoined after saving
158 | isme = isme .. "," .. addVarArray.data[i]
159 | end
160 | extraVar.text = isme
161 | else
162 | addVarArray.data = ""
163 | end
164 | elseif selected == 1 or selected == 2 then --string or -string
165 | extraVar = window:addChild(GUI.comboBox(36,19,32,1,style.containerComboBack,style.containerComboText,style.containerComboArrowBack,style.containerComboArrowText))
166 | local sub = function()
167 | addVarArray.data = extraVar.selectedItem
168 | end --you choose whether they can edit it, only view it, or can't see it (only changed by setVar and getVar)
169 | extraVar:addItem("Editable").onTouch = sub
170 | extraVar:addItem("Uneditable").onTouch = sub
171 | extraVar:addItem("Hidden").onTouch = sub
172 | if varMode == "edit" then
173 | extraVar.selectedItem = addVarArray.data
174 | else
175 | addVarArray.data = 1
176 | end
177 | else --bool (no config and shouldn't be able to edit at all)
178 | extraVar = window:addChild(GUI.label(36,19,3,3,style.passNameLabel,"NAN"))
179 | if varMode == "add" then
180 | addVarArray.data = false
181 | end
182 | end
183 | end
184 |
185 | local function clearVarF() --Clear current stuff on creation area
186 | varKeyInput.text = ""
187 | varKeyInput.disabled = true
188 | varLabelInput.text = ""
189 | varLabelInput.disabled = true
190 | varTypeSelect.selectedItem = 5
191 | varTypeSelect.disabled = true
192 | addVarArray = nil
193 | if extraVar ~= nil then
194 | extraVar:remove()
195 | extraVar = window:addChild(GUI.label(36,19,3,3,style.passNameLabel,"NAN"))
196 | end
197 | updateVarButton.disabled = true
198 | clearVarButton.disabled = true
199 | varMode = "none"
200 | end
201 |
202 | local function addVarF() --Prep creation area for adding a var
203 | if varMode == "none" then
204 | varKeyInput.disabled = false
205 | varLabelInput.disabled = false
206 | varTypeSelect.disabled = false
207 | varTypeSelect.selectedItem = 5
208 | addVarArray = {["var"]="",["label"]="",["calls"]=uuid.next(),["type"]="bool",["above"]=false,["data"]=false}
209 | extraVar2 = nil
210 | updateVarButton.disabled = false
211 | clearVarButton.disabled = false
212 | varMode = "add"
213 | else
214 | GUI.alert("Please clear current changes in var edit mode before adding a var")
215 | end
216 | end
217 |
218 | local function editVarF() --Prep creation area for editing a var
219 | if varMode == "none" then
220 | local selected = varList.selectedItem
221 | addVarArray = {["var"]=userTable.passSettings.var[selected],["label"]=userTable.passSettings.label[selected],["type"]=userTable.passSettings.type[selected],["above"]=userTable.passSettings.above[selected],["data"]=userTable.passSettings.data[selected]}
222 | varKeyInput.disabled = true
223 | varKeyInput.text = addVarArray.var
224 | varLabelInput.disabled = false
225 | varLabelInput.text = addVarArray.label
226 | varTypeSelect.disabled = true
227 | varTypeSelect.selectedItem = addVarArray.type == "string" and 1 or addVarArray.type == "-string" and 2 or addVarArray.type == "int" and 3 or addVarArray.type == "-int" and 4 or 5
228 | extraVar2 = nil
229 | updateVarButton.disabled = false
230 | clearVarButton.disabled = false
231 | varMode = "edit"
232 | checkTypeCallback()
233 | else
234 | GUI.alert("Please clear current changes in var edit mode before editing a var")
235 | end
236 | end
237 |
238 | local function delVarF() --delete a created var
239 | local selected = varList.selectedItem
240 | table.remove(userTable.passSettings.data,selected)
241 | table.remove(userTable.passSettings.label,selected)
242 | table.remove(userTable.passSettings.calls,selected)
243 | table.remove(userTable.passSettings.type,selected)
244 | table.remove(userTable.passSettings.above,selected)
245 | for i=1,#userTable.passes,1 do
246 | userTable.passes[i][userTable.passSettings.var[selected]] = nil
247 | end
248 | table.remove(userTable.passSettings.var,selected)
249 | database.save()
250 | database.update({"passes","passSettings"})
251 | updatePassCombo()
252 | end
253 |
254 | local searchBase = {"name","blocked","staff","uuid","link","mcid"}
255 |
256 | local function updateVarF() --Either add or change (depending on add or edit mode) a var
257 | if varMode == "add" then
258 | if addVarArray.var ~= "" and addVarArray.label ~= "" then
259 | local skipAll = false
260 | for _, value in pairs(searchBase) do
261 | if value == addVarArray.var then
262 | skipAll = true
263 | break
264 | end
265 | end
266 | if not skipAll then
267 | for _, value in pairs(userTable.passSettings.var) do
268 | if value == addVarArray.var then
269 | skipAll = true
270 | break
271 | end
272 | end
273 | end
274 | if not skipAll then
275 | for i=1,#userTable.passes,1 do
276 | if addVarArray.type == "string" then
277 | userTable.passes[i][addVarArray.var] = "none"
278 | elseif addVarArray.type == "-string" then
279 | userTable.passes[i][addVarArray.var] = {}
280 | elseif addVarArray.type == "int" or addVarArray.type == "-int" then
281 | userTable.passes[i][addVarArray.var] = 0
282 | elseif addVarArray.type == "bool" then
283 | userTable.passes[i][addVarArray.var] = false
284 | else
285 | GUI.alert(loc.addvaralert)
286 | return
287 | end
288 | end
289 | table.insert(userTable.passSettings.var,addVarArray.var)
290 | table.insert(userTable.passSettings.label,addVarArray.label)
291 | table.insert(userTable.passSettings.calls,addVarArray.calls)
292 | table.insert(userTable.passSettings.type,addVarArray.type)
293 | table.insert(userTable.passSettings.above,addVarArray.above)
294 | table.insert(userTable.passSettings.data,addVarArray.data)
295 | database.save()
296 | database.update({"passes","passSettings"})
297 | clearVarF()
298 | updatePassCombo()
299 | else
300 | GUI.alert("Var key conflicts with another one already created. Please change it.")
301 | end
302 | else
303 | GUI.alert("Please add a var key or label before updating")
304 | end
305 | elseif varMode == "edit" then
306 | local selected = 1
307 | for _,value in pairs(userTable.passSettings.var) do
308 | if value == addVarArray.var then
309 | break
310 | else
311 | selected = selected + 1
312 | end
313 | end
314 | if selected <= #userTable.passSettings.var then
315 | if userTable.passSettings.type[selected] == "int" then
316 | userTable.passSettings.above[selected] = addVarArray.above
317 | elseif userTable.passSettings.type[selected] == "-int" or userTable.passSettings.type[selected] == "string" or userTable.passSettings.type[selected] == "-string" then
318 | userTable.passSettings.data[selected] = addVarArray.data
319 | end
320 | userTable.passSettings.label[selected] = addVarArray.label
321 | database.save()
322 | database.update({"passes","passSettings"})
323 | clearVarF()
324 | updatePassCombo()
325 | else
326 | GUI.alert("Var not found in the list. Was it deleted?")
327 | end
328 | end
329 | end
330 |
331 | local function onVarKeyInput()
332 | addVarArray.var = varKeyInput.text
333 | end
334 |
335 | local function onVarLabelInput()
336 | addVarArray.label = varLabelInput.text
337 | end
338 |
339 | --Create keypad stuff
340 | window:addChild(GUI.label(1,1,3,3,style.passNameLabel,"Global Keypads"))
341 | padBox = window:addChild(GUI.comboBox(1,3,20,1,style.containerComboBack,style.containerComboText,style.containerComboArrowBack,style.containerComboArrowText))
342 | padDel = window:addChild(GUI.button(22,3,10,1, style.passButton, style.passText, style.passSelectButton, style.passSelectText, loc.delete))
343 | padDel.onTouch = padDelF
344 | padDel.disabled = true
345 | window:addChild(GUI.label(1,5,3,3,style.passNameLabel,"Label"))
346 | padLabel = window:addChild(GUI.input(1,6,15,1, style.passInputBack,style.passInputText,style.passInputPlaceholder,style.passInputFocusBack,style.passInputFocusText, "", loc.inputname))
347 | padLabel.onInputFinished = passLabelCallback
348 | padLabel.disabled = true
349 | window:addChild(GUI.label(17,5,3,3,style.passNameLabel,"Pin / Password"))
350 | padPass = window:addChild(GUI.input(17,6,15,1, style.passInputBack,style.passInputText,style.passInputPlaceholder,style.passInputFocusBack,style.passInputFocusText, "", loc.inputpass))
351 | padPass.onInputFinished = passInputCallback
352 | padPass.disabled = true
353 | padNew = window:addChild(GUI.button(22,8,7,1, style.passButton, style.passText, style.passSelectButton, style.passSelectText, loc.new))
354 | padNew.onTouch = padNewF
355 | padNew.disabled = canPad
356 | padNewKey = window:addChild(GUI.input(1,8,20,1, style.passInputBack,style.passInputText,style.passInputPlaceholder,style.passInputFocusBack,style.passInputFocusText, "", "input key"))
357 | padNewKey.disabled = canPad
358 | window:addChild(GUI.panel(34,2,1,28,style.bottomDivider)) --Create pass creation stuff
359 | window:addChild(GUI.label(36,1,3,3,style.passNameLabel,"Pass Management"))
360 | varList = window:addChild(GUI.comboBox(36,3,32,1,style.containerComboBack,style.containerComboText,style.containerComboArrowBack,style.containerComboArrowText))
361 | varList.disabled = canPass
362 | varLabel = window:addChild(GUI.label(36,5,3,3,style.passNameLabel,"Label: NAN"))
363 | varDesc = window:addChild(GUI.label(36,7,3,3,style.passNameLabel,"Desc: NAN"))
364 | addVarButton = window:addChild(GUI.button(36,9,10,1, style.passButton, style.passText, style.passSelectButton, style.passSelectText, loc.addvar))
365 | addVarButton.onTouch = addVarF
366 | addVarButton.disabled = canPass
367 | editVarButton = window:addChild(GUI.button(47,9,10,1, style.passButton, style.passText, style.passSelectButton, style.passSelectText, loc.editvar))
368 | editVarButton.onTouch = editVarF
369 | editVarButton.disabled = true
370 | delVarButton = window:addChild(GUI.button(58,9,10,1, style.passButton, style.passText, style.passSelectButton, style.passSelectText, loc.delvar))
371 | delVarButton.onTouch = delVarF
372 | delVarButton.disabled = true
373 | window:addChild(GUI.panel(36,11,32,1,style.bottomDivider))
374 | varKeyInput = window:addChild(GUI.input(36,13,32,1, style.containerInputBack,style.containerInputText,style.containerInputPlaceholder,style.containerInputFocusBack,style.containerInputFocusText, "", loc.newvarkey))
375 | varKeyInput.onInputFinished = onVarKeyInput
376 | varKeyInput.disabled = true
377 | varLabelInput = window:addChild(GUI.input(36,15,32,1, style.containerInputBack,style.containerInputText,style.containerInputPlaceholder,style.containerInputFocusBack,style.containerInputFocusText, "", loc.newvarlabel))
378 | varLabelInput.onInputFinished = onVarLabelInput
379 | varLabelInput.disabled = true
380 | varTypeSelect = window:addChild(GUI.comboBox(36,17,32,1, style.containerComboBack,style.containerComboText,style.containerComboArrowBack,style.containerComboArrowText))
381 | local lik = varTypeSelect:addItem("String")
382 | lik.onTouch = checkTypeCallback --every time one is selected it refreshes the extra setting needed for certain choices
383 | lik = varTypeSelect:addItem("Multi-String")
384 | lik.onTouch = checkTypeCallback
385 | lik = varTypeSelect:addItem("Level (Int)")
386 | lik.onTouch = checkTypeCallback
387 | lik = varTypeSelect:addItem("Group")
388 | lik.onTouch = checkTypeCallback
389 | lik = varTypeSelect:addItem("Pass (true/false)")
390 | lik.onTouch = checkTypeCallback
391 | varTypeSelect.selectedItem = 5
392 | varTypeSelect.disabled = true
393 | extraVar = window:addChild(GUI.label(36,19,3,3,style.passNameLabel,"NAN"))
394 | updateVarButton = window:addChild(GUI.button(36,21,20,1, style.passButton, style.passText, style.passSelectButton, style.passSelectText, loc.update))
395 | updateVarButton.onTouch = updateVarF
396 | updateVarButton.disabled = true
397 | clearVarButton = window:addChild(GUI.button(36,23,20,1, style.passButton, style.passText, style.passSelectButton, style.passSelectText, "clear"))
398 | clearVarButton.onTouch = clearVarF
399 | clearVarButton.disabled = true
400 |
401 | updateKeyList()
402 | updatePassCombo()
--------------------------------------------------------------------------------
/security/Server Module/security.lua:
--------------------------------------------------------------------------------
1 | local userTable = {}
2 | local doorTable = {}
3 | local server = {}
4 | local modemPort = 199
5 |
6 | local component = require("component")
7 | local modem = component.modem
8 | local ser = require("serialization")
9 |
10 | local module = {}
11 | module.name = "passes"
12 | module.commands = {"rcdoors","checkLinked","getvar","setvar","checkRules","linkMCID","checkKeypad"}
13 | module.skipcrypt = {}
14 | module.table = {["passes"]={},["passSettings"]={["var"]={"level"},["label"]={"Level"},["calls"]={"checkLevel"},["type"]={"int"},["above"]={true},["data"]={false}},["securityKeypads"] = {["testone"]={["pass"]="1234",["label"]="Test One"}}}
15 | module.debug = false
16 | module.version = "4.0.3"
17 | module.id = 1111
18 |
19 | local function getPassID(command,rules)
20 | local bill
21 | if rules ~= nil then
22 | for i=1,#rules,1 do
23 | if rules[i].uuid == command then
24 | command = rules[i].call
25 | bill = i
26 | break
27 | end
28 | end
29 | end
30 | for i=1,#userTable.passSettings.calls,1 do
31 | if command == userTable.passSettings.calls[i] then
32 | return true, i, bill
33 | end
34 | end
35 | return command == "checkstaff" and true or false, command == "checkstaff" and 0 or false
36 | end
37 |
38 | local function getVar(var,user)
39 | for key, value in pairs(userTable.passes) do
40 | if string.sub(value.uuid,1,-14) == user or value.uuid == user then
41 | return value[var]
42 | end
43 | end
44 | return "Nil "..var
45 | end
46 |
47 | local function checkVar(rule,user,index)
48 | if index ~= 0 then
49 | if userTable.passSettings.type[index] == "string" then
50 | return user[userTable.passSettings.var[index]] == rule.param
51 | elseif userTable.passSettings.type[index] == "-string" then
52 | for i=1,#user[userTable.passSettings.var[index]],1 do
53 | if user[userTable.passSettings.var[index]][i] == rule.param then
54 | return true
55 | end
56 | end
57 | return false
58 | elseif userTable.passSettings.type[index] == "int" or userTable.passSettings.type[index] == "-int" then
59 | if userTable.passSettings.above[index] == false or userTable.passSettings.type[index] == "-int" then
60 | return user[userTable.passSettings.var[index]] == rule.param
61 | else
62 | return user[userTable.passSettings.var[index]] >= rule.param
63 | end
64 | elseif userTable.passSettings.type[index] == "bool" then
65 | return user[userTable.passSettings.var[index]]
66 | end
67 | else
68 | return user.staff
69 | end
70 | return false
71 | end
72 | --return true, not value.blocked, value[var], value.staff
73 | local function checkAdvVar(user,rules) --{["uuid"]=uuid.next()["call"]=t1,["param"]=t2,["request"]="supreme",["data"]=false}
74 | local label,color = "will be set",0x000000
75 | local foundOne = false
76 | for key, value in pairs(userTable.passes) do
77 | if string.sub(value.uuid,1,-14) == user or value.uuid == user then
78 | foundOne = true
79 | local skipBase = false
80 | for i=1,#rules,1 do
81 | if rules[i].request == "reject" then
82 | local e, call = getPassID(rules[i].call)
83 | if e then
84 | local good = checkVar(rules[i],value,call)
85 | if good then
86 | label,color = call ~= 0 and "Denied: var " .. userTable.passSettings.label[call] .. " is rejected" or "Denied: var staff" .. " is rejected", 0xFF0000
87 | skipBase = true
88 | break
89 | end
90 | end
91 | end
92 | end
93 | if skipBase == false then
94 | for i=1,#rules,1 do
95 | if rules[i].request == "base" then
96 | local e, call = getPassID(rules[i].call)
97 | if e then
98 | local good = checkVar(rules[i],value,call)
99 | if good then
100 | label,color = call ~= 0 and "Accepted by base var " .. userTable.passSettings.label[call] or "Accepted by base var" .. "staff", 0x00B600
101 | local isGood = true
102 | for j=1,#rules[i].data,1 do
103 | local bill
104 | e, call, bill = getPassID(rules[i].data[j],rules)
105 | if e then
106 | good = checkVar(rules[bill],value,call)
107 | if good == false then
108 | isGood = false
109 | label,color = "Denied: did not meet base requirements", 0xFF0000
110 | break
111 | end
112 | end
113 | end
114 | if isGood then
115 | return true, not value.blocked, true, value.staff,label,color
116 | end
117 | end
118 | end
119 | end
120 | end
121 | end
122 | for i=1,#rules,1 do
123 | if rules[i].request == "supreme" then
124 | local e,call = getPassID(rules[i].call)
125 | if e then
126 | local good = checkVar(rules[i],value,call)
127 | if good then
128 | label,color = call ~= 0 and "Accepted by supreme var " .. userTable.passSettings.label[call] or "Accepted by supreme var " .. "staff", 0x00FF00
129 | return true, not value.blocked, true, value.staff,label,color
130 | end
131 | end
132 | end
133 | end
134 | if foundOne then
135 | if label == "will be set" then
136 | label,color = "Denied: does not have any required passes",0xFF0000
137 | end
138 | return true, not value.blocked, false, value.staff,label,color
139 | end
140 | end
141 | end
142 | return false
143 | end
144 |
145 | local function getDoorInfo(type,id,key)
146 | local arrange
147 | if type == "doorsystem" or type == "customdoor" then
148 | for i=1,#doorTable,1 do --doorTable[i] = {type="single or multi",id="computer's modem uuid",data={door's setting table}}
149 | if doorTable[i].id == id then
150 | if type == "customdoor" then
151 | return{["read"]=doorTable[i].data.cardRead,["name"]=doorTable[i].data.name}
152 | else
153 | if doorTable[i].data[key]~=nil then
154 | return {["read"]=doorTable[i].data[key].cardRead,["name"]=doorTable[i].data[key].name}
155 | end
156 | end
157 | end
158 | end
159 | end
160 | return nil, arrange
161 | end
162 |
163 | local function checkLink(user)
164 | for _, value in pairs(userTable.passes) do
165 | if value.link == user then
166 | return true, not value.blocked, value.name
167 | end
168 | end
169 | return false
170 | end
171 |
172 | local function checkMCID(id)
173 | for _, value in pairs(userTable.passes) do
174 | if value.mcid == id then
175 | return true, value.uuid, value.name
176 | end
177 | end
178 | return false
179 | end
180 |
181 | function module.init(setit ,doors, serverCommands) --Called when server is first started
182 | userTable = setit
183 | doorTable = doors
184 | server = serverCommands
185 | if module.debug then server.print("Received Stuff for passes!") end
186 | if userTable.passes ~= nil and userTable.passes[1] ~= nil and userTable.passes[1].mcid == nil then --make sure old systems migrate successfully
187 | for _,value in pairs(userTable.passes) do
188 | value.mcid = "nil"
189 | end
190 | end
191 | end
192 |
193 | function module.setup() --Called when userlist is updated or server is first started
194 | if module.debug then server.print("Received Stuff for passes!") end
195 | end
196 |
197 | function module.message(command,datar,from) --Called when a command goes past all default commands and into modules.
198 | local data
199 | if datar ~= nil then
200 | data = ser.unserialize(datar)
201 | end
202 | local thisUserName = false
203 | if command == "setvar" or command == "getvar" or command == "checkRules" then
204 | thisUserName = getVar("name",data.uuid)
205 | end
206 | if command == "rcdoors" then
207 | local sendTable = {}
208 | for _,value in pairs(doorTable) do
209 | local datar
210 | if value.type == "doorsystem" then
211 | datar = {}
212 | for key,pal in pairs(value.data) do
213 | datar[key] = {["name"]=pal.name}
214 | end
215 | table.insert(sendTable,{["id"]=value.id,["type"]=value.type,["data"]=datar})
216 | end
217 | end
218 | return true,{{["text"]="Passes: ",["color"]=0x9924C0},{["text"]="Sending remote control table",["color"]=0xFFFFFF}},false,true,server.crypt(ser.serialize(sendTable))
219 | elseif command == "checkLinked" then
220 | local cu, isBlocked, thisName = checkLink(data)
221 | local dis = {}
222 | if cu == true then
223 | if isBlocked == false then
224 | dis["status"] = false
225 | dis["reason"] = 2
226 | data = server.crypt(ser.serialize(dis))
227 | return true,{{["text"]="Passes: ",["color"]=0x9924C0},{["text"]="Checking if device is linked to a user: ",["color"]=0xFFFF80},{["text"]=" user " .. thisName .. "is blocked",["color"]=0xFF0000,["line"]=true}},false,true,data
228 | else
229 | dis["status"] = true
230 | dis["name"] = thisName
231 | data = server.crypt(ser.serialize(dis))
232 | return true,{{["text"]="Passes: ",["color"]=0x9924C0},{["text"]="Checking if device is linked to a user: ",["color"]=0xFFFF80},{["text"]=" tablet is connected to " .. thisName,["color"]=0x00FF00,["line"]=true}},false,true,data
233 | end
234 | else
235 | dis["status"] = false
236 | dis["reason"] = 1
237 | data = server.crypt(ser.serialize(dis))
238 | return true,{{["text"]="Passes: ",["color"]=0x9924C0},{["text"]="Checking if device is linked to a user: ",["color"]=0xFFFF80},{["text"]=" tablet not linked",["color"]=0x990000,["line"]=true}},false,true,data
239 | end--IMPORTANT: Hello
240 | elseif command == "getvar" then
241 | if (server.configCheck("secAPI")) then
242 | local worked = false
243 | for _, value in pairs(userTable.passes) do
244 | if string.sub(value.uuid,1,-14) == data.uuid or value.uuid == data.uuid then
245 | worked = true
246 | local mee = type(value[data.var]) == "table" and ser.serialize(value[data.var]) or value[data.var]
247 | return true,nil,false,true,server.crypt(mee)
248 | end
249 | end
250 | else
251 | return true, {{["text"]="Passes: ",["color"]=0x9924C0},{["text"]="SecAPI getvar requested when disabled by database",["color"]=0xFF0000}}, false, true, server.crypt({})
252 | end
253 | elseif command == "setvar" then
254 | if (server.configCheck("secAPI")) then
255 | local worked = false
256 | local counter = 1
257 | for _, value in pairs(userTable.passes) do
258 | if string.sub(value.uuid,1,-14) == data.uuid or value.uuid == data.uuid then
259 | worked = true
260 | if type(userTable.passes[counter][data.var]) == type(data.data) then
261 | userTable.passes[counter][data.var] = data.data
262 | end
263 | return true,nil,true,true,server.crypt("true")
264 | else
265 | counter = counter + 1
266 | end
267 | end
268 | else
269 | return true, {{["text"]="Passes: ",["color"]=0x9924C0},{["text"]="SecAPI getvar requested when disabled by database",["color"]=0xFF0000}}, false, true, server.crypt({})
270 | end
271 | elseif command == "linkMCID" then
272 | if (server.configCheck("quickMCLink")) then
273 | local worked = false
274 | local counter = 1
275 | for _, value in pairs(userTable.passes) do
276 | if string.sub(value.uuid,1,-14) == data.uuid or value.uuid == data.uuid then
277 | worked = true
278 | if value.mcid == "nil" and not value.blocked then --make sure an account isn't linked AND they are not blocked.
279 | value.mcid = data.mcid
280 | return true, nil, true, true, server.crypt("true")
281 | else
282 | return true, nil, false, true, server.crypt("false")
283 | end
284 | else
285 | counter = counter + 1
286 | end
287 | end
288 | else
289 | return true, {{["text"]="Passes: ",["color"]=0x9924C0},{["text"]="Quick Linking MCID's has been disabled by database",["color"]=0xFF0000}}, false, true, server.crypt("false")
290 | end
291 | elseif command == "checkKeypad" then --theoretically should be goody goody two shoes :D (maybe)
292 | for key, value in pairs(doorTable) do
293 | if value.id == from then
294 | for _, value2 in pairs(value.data[data.key].reader) do
295 | if value2.uuid == data.uuid then
296 | if value2.global == false then --Local pass
297 | if value2.pass == data.pass then
298 | return true, {{["text"]="Passes: ",["color"]=0x9924C0},{["text"]="Correct password for " .. value.data[data.key].name,["color"]=0x00FF00}}, false, true, server.crypt("true")
299 | else
300 | return true, {{["text"]="Passes: ",["color"]=0x9924C0},{["text"]="Incorrect password for " .. value.data[data.key].name,["color"]=0xFF0000}}, false, true, server.crypt("false")
301 | end
302 | else --Check the global one
303 | if userTable.securityKeypads[value2.pass].pass == data.pass then
304 | return true, {{["text"]="Passes: ",["color"]=0x9924C0},{["text"]="Correct password for " .. value.data[data.key].name,["color"]=0x00FF00}}, false, true, server.crypt("true")
305 | else
306 | return true, {{["text"]="Passes: ",["color"]=0x9924C0},{["text"]="Incorrect password for " .. value.data[data.key].name,["color"]=0xFF0000}}, false, true, server.crypt("false")
307 | end
308 | end
309 | end
310 | end
311 | end
312 | end
313 | return true, {{["text"]="Passes: ",["color"]=0xFF0000},{["text"]="Door was not found",["color"]=0xFF0000}}, false, true, server.crypt("false")
314 | elseif command == "checkRules" then
315 | local currentDoor = getDoorInfo(data.type,from,data.key)
316 | local enter = true
317 | if data.isBio then
318 | local e,good,nome = checkMCID(data.uuid)
319 | if e then
320 | data.uuid = good
321 | thisUserName = nome
322 | else
323 | return true,{{["text"]="Passes: ",["color"]=0x9924C0},{["text"]="User" .. data.uuid .. " not linked to biometrics",["color"]=0x994049}},false,true,server.crypt("false")
324 | end
325 | end
326 | if data.sector ~= false then
327 | local a,c,_,_,b = server.modulemsg("doorsector",ser.serialize(data))
328 | if a then
329 | if b ~= "true" and b ~= "openbypass" then
330 | enter = false
331 | if b == "false" then
332 | return true,c,false,true,server.crypt("false")
333 | elseif b == "lockbypass" then
334 | return true,c,false,true,server.crypt("bypass")
335 | end
336 | end
337 | end
338 | end
339 | if enter then
340 | local chatTable = {{["text"]="Passes: ",["color"]=0x9924C0}}
341 | table.insert(chatTable,{["text"]="Checking user " .. thisUserName .. "'s credentials on " .. currentDoor.name .. ":",["color"]=0xFFFF80,["line"]=false})
342 | local cu, isBlocked, varCheck, isStaff,label,color = checkAdvVar(data.uuid,currentDoor.read)
343 | if cu then
344 | if isBlocked then
345 | if varCheck then
346 | data = server.crypt("true")
347 | table.insert(chatTable,{["text"]=label,["color"]=color,["line"]=true})
348 | else
349 | if isStaff then
350 | data = server.crypt("true")
351 | table.insert(chatTable,{["text"]="access granted due to staff",["color"]=0xFF00FF,["line"]=true})
352 | else
353 | data = server.crypt("false")
354 | table.insert(chatTable,{["text"]=label,["color"]=color,["line"]=true})
355 | end
356 | end
357 | else
358 | data = server.crypt("false")
359 | table.insert(chatTable,{["text"]="user is blocked",["color"]=0xFF0000,["line"]=true})
360 | end
361 | else
362 | data = server.crypt("false")
363 | table.insert(chatTable,{["text"]="user not found",["color"]=0x990000,["line"]=true})
364 | end
365 | return true,chatTable,false,true,data
366 | end
367 | end
368 | return false
369 | end
370 | function module.piggyback(command,data) --Called after a command is passed. Passed to all modules which return nothing.
371 | if command == "setdevice" then
372 | data = ser.unserialize(data)
373 | if data.type == "doorsystem" or data.type == "customdoor" then
374 | server.send(true,server.crypt(ser.serialize({["settings"]=userTable.passSettings,["sectors"]=userTable.sectors})))
375 | end
376 | end
377 | return
378 | end
379 |
380 | return module
--------------------------------------------------------------------------------
/security/autoinstaller.lua:
--------------------------------------------------------------------------------
1 | local component = require("component")
2 | local term = require("term")
3 | local io = require("io")
4 | local ser = require("serialization")
5 | local fs = require("filesystem")
6 | local shell = require("shell")
7 | local event = require("event")
8 | local uuid = require("uuid")
9 | local thread = require("thread")
10 | local modem = component.modem
11 | local link
12 | local modemPort = 1000
13 | local syncPort = 199
14 | local diagPort = 180
15 |
16 | local midPoint = "main"
17 |
18 | local program = "ctrl.lua"
19 | local settingFileName = "doorSettings.txt"
20 | local configFileName = "extraConfig.txt"
21 | local doorCode = "https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/" .. midPoint .. "/security/doorControl.lua"
22 | --local versionHolderCode = "https://raw.githubusercontent.com/cadergator10/opencomputer-security-system/main/src/versionHolder.txt"
23 |
24 | local settingData = {}
25 | local randomNameArray = {"q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "a", "s", "d", "f", "g", "h", "j", "k", "l", "z", "x", "c", "v", "b", "n", "m"}
26 | local commandArray = {"getInput","analyzer","clearTerm","terminate","advanalyzer"}
27 |
28 | local query = {["num"]=0}
29 | local editorSettings = {} --Types of variables used in runInstall: type = door type (single or multi) required, num = old or new type (1 or 2) required, times = times to loop through (only edited before entering runInstall if adding more doors to multi) conditional, version = server version "not used yet", accelerate = if using seperate door setup tablet required, scanner = only used if accelerate true and if tablet has analyzer required, key = key of multidoor if editing door depends, edit = if editing. false if new door. required
30 |
31 | local function saveTable(table, location)
32 | --saves a table to a file
33 | local tableFile = assert(io.open(location, "w"))
34 | tableFile:write(ser.serialize(table))
35 | tableFile:close()
36 | end
37 | local function loadTable(location)
38 | --returns a table stored in a file.
39 | local tableFile = assert(io.open(location))
40 | return ser.unserialize(tableFile:read("*all"))
41 | end
42 |
43 | local function send(label,port,linker,...)
44 | if linker and link ~= nil then
45 | link.send(modem.address,...)
46 | return
47 | end
48 | if label then
49 | modem.send(label,port,...)
50 | else
51 | modem.broadcast(port,...)
52 | end
53 | end
54 |
55 | local function sendMsg(...)
56 | local arg = table.pack(...)
57 | for i=1,#arg,1 do
58 | local argType = type(arg[i])
59 | if editorSettings.accelerate == true then
60 | if argType == "string" then
61 | send(editorSettings.from,editorSettings.port,false,"print",arg[i])
62 | elseif argType == "number" then
63 | send(editorSettings.from,editorSettings.port,false,commandArray[arg[i]])
64 | if arg[i] < 3 then
65 | local e, _, _, _, _, text = event.pull("modem_message")
66 | return text
67 | end
68 | if arg[i] == 4 then
69 | print("terminated connection")
70 | end
71 | if arg[i] == 5 then
72 | local wait = true
73 | local distable = {}
74 | while wait do
75 | local e, _, _, _, _, text = event.pull("modem_message")
76 | if text == "finished" then
77 | return distable
78 | else
79 | table.insert(distable,text)
80 | end
81 | end
82 | end
83 | else
84 | send(editorSettings.from,editorSettings.port,false,"print","potential error in code for sendMsg")
85 | end
86 | else
87 | if argType == "string" then
88 | print(arg[i])
89 | elseif argType == "number" then
90 | if arg[i] == 1 then
91 | local text = term.read()
92 | return text:sub(1,-2)
93 | elseif arg[i] == 2 then
94 | return "nil"
95 | elseif arg[i] == 3 then
96 | term.clear()
97 | elseif arg[i] == 4 then
98 | print("Finished editing.")
99 | elseif arg[i] == 5 then
100 | local wait = true
101 | local distable = {}
102 | while wait do
103 | local text = term.read()
104 | text = text:sub(1,-2)
105 | if text == "" then
106 | return distable
107 | else
108 | table.insert(distable,text)
109 | end
110 | end
111 | else
112 | print("potential error in code for sendMsg")
113 | end
114 | end
115 | end
116 | end
117 | return true
118 | end
119 |
120 | local function runInstall()
121 | local tmpTable = {}
122 | local times = 1
123 | local text = ""
124 | editorSettings.x = tonumber(sendMsg("Would you like to use the simple pass setup or new advanced one?","1 for simple, 2 for advanced",1))
125 | sendMsg(3)
126 | if editorSettings.single == false then
127 | if editorSettings.times ~= nil then
128 | tmpTable = editorSettings.data
129 | times = editorSettings.times
130 | elseif editorSettings.key ~= nil then
131 | times = 1
132 | tmpTable = editorSettings.data
133 | else
134 | text = sendMsg("Read the text carefully. Some of the inputs REQUIRE NUMBERS ONLY! Some require text.","The redSide is always 2, or back of the computer.","How many different doors are there?",1)
135 | times = tonumber(text)
136 | end
137 | else
138 | times = 1
139 | end
140 |
141 | local config = {}
142 | if editorSettings.edit then
143 | config = loadTable(configFileName)
144 | end
145 | config.type = editorSettings.type
146 | config.num = editorSettings.num
147 | config.version = editorSettings.version
148 | if editorSettings.edit == false or editorSettings.edit == nil then
149 | text = sendMsg("Do you want to use the default cryptKey of {1,2,3,4,5}?","1 for yes, 2 for no",1)
150 | if tonumber(text) == 2 then
151 | config.cryptKey = {}
152 | sendMsg("there are 5 parameters, each requiring a number. Recommend doing 1 digit numbers cause I got no idea how this works lol")
153 | for i=1,5,1 do
154 | text = sendMsg("enter param " .. i,1)
155 | config.cryptKey[i] = tonumber(text)
156 | end
157 | else
158 | config.cryptKey = {1,2,3,4,5}
159 | end
160 | config.port = modemPort
161 | end
162 | saveTable(config,configFileName)
163 |
164 | for i=1,times,1 do
165 | local loopArray = {}
166 | sendMsg(3)
167 | local j
168 | if editorSettings.single == false then
169 | sendMsg("Door # " .. i .. " is being edited:")
170 | if editorSettings.key == nil then
171 | local keepLoop = true
172 | while keepLoop do
173 | j = randomNameArray[math.floor(math.random(1,26))]..randomNameArray[math.floor(math.random(1,26))]..randomNameArray[math.floor(math.random(1,26))]..randomNameArray[math.floor(math.random(1,26))]
174 | keepLoop = false
175 | for key,value in pairs(tmpTable) do
176 | if key == j then
177 | keepLoop = true
178 | end
179 | end
180 | end
181 | else
182 | j = editorSettings.key
183 | end
184 | text = sendMsg("Magnetic card reader?",editorSettings.scanner and "Scan the magnetic card reader with your tablet." or "Enter the uuid of the device in TEXT. When finished, don't type anything and just press enter",5)
185 | loopArray["reader"] = {}
186 | local hasPad = false
187 | for _, value in pairs(text) do
188 | local thisType = component.type(value)
189 | if thisType == "os_magreader" then
190 | table.insert(loopArray["reader"],{["uuid"]=value,["type"]="swipe"})
191 | elseif thisType == "os_biometric" then
192 | table.insert(loopArray["reader"],{["uuid"]=value,["type"]="biometric"})
193 | elseif thisType == "os_rfidreader" then
194 | table.insert(loopArray["reader"],{["uuid"]=value,["type"]="rfid"})
195 | elseif thisType == "os_keypad" then
196 | hasPad = true
197 | component.proxy(value).setDisplay("inactive", 6)
198 | table.insert(loopArray["reader"],{["uuid"]=value,["type"]="keypad",["global"]=false,["pass"]="1111"})
199 | end
200 | end
201 | if hasPad then
202 | text = sendMsg("Keypads detected: Would you like to use a global or local password?","global passwords are set by the database. local are set and saved on this door computer","1 for global, 2 for local",1)
203 | if text == "1" then
204 | text = sendMsg("What is the key for that keypad variable?",1)
205 | else
206 | hasPad = false
207 | text = sendMsg("What is the pin for the keypad to need to allow you in?","4 or less numbers (4 recommended)",1)
208 | end
209 | for key, value in pairs(loopArray["reader"]) do
210 | if value.type == "keypad" then
211 | loopArray["reader"][key].global = hasPad
212 | loopArray["reader"][key].pass = text
213 | end
214 | end
215 | end
216 | else
217 | j = randomNameArray[math.floor(math.random(1,26))]..randomNameArray[math.floor(math.random(1,26))]..randomNameArray[math.floor(math.random(1,26))]..randomNameArray[math.floor(math.random(1,26))]
218 | local distable = {}
219 | local hasPad = false
220 | for key,_ in pairs(component.list("os_magreader")) do
221 | table.insert(distable,{["uuid"]=key,["type"]="swipe"})
222 | end
223 | for key,_ in pairs(component.list("os_biometric")) do
224 | table.insert(distable,{["uuid"]=key,["type"]="biometric"})
225 | end
226 | for key,_ in pairs(component.list("os_rfidreader")) do
227 | table.insert(distable,{["uuid"]=key,["type"]="rfid"})
228 | end
229 | for key,_ in pairs(component.list("os_keypad")) do
230 | hasPad = true
231 | component.proxy(key).setDisplay("inactive", 6)
232 | table.insert(distable,{["uuid"]=key,["type"]="keypad",["global"]=false,["pass"]="1111"})
233 | end
234 | if hasPad then
235 | text = sendMsg("Keypads detected: Would you like to use a global or local password?","global passwords are set by the database. local are set and saved on this door computer","1 for global, 2 for local",1)
236 | if text == "1" then
237 | text = sendMsg("What is the key for that keypad variable?",1)
238 | else
239 | hasPad = false
240 | text = sendMsg("What is the pin for the keypad to need to allow you in?","4 or less numbers (4 recommended)",1)
241 | end
242 | for key, value in pairs(distable) do
243 | if value.type == "keypad" then
244 | distable[key].global = hasPad
245 | distable[key].pass = text
246 | end
247 | end
248 | end
249 | loopArray["reader"] = distable
250 | end
251 | text = sendMsg("What do you want to nickname this door?",1)
252 | loopArray["name"] = text
253 | text = sendMsg("Door Type? 1=redstone 2=bundled. 3=door/rolldoor controller. NUMBER ONLY",1)
254 | loopArray["doorType"] = tonumber(text)
255 | if loopArray.doorType == 2 then
256 | text = sendMsg("What color. Use the Color API wiki on the opencomputers wiki, and enter the NUMBER",1)
257 | loopArray["redColor"] = tonumber(text)
258 | loopArray["doorAddress"] = {""}
259 | text = sendMsg("What side? 0=bottom, 1=top, 2=back, 3=front, 4=right, 5=left. NUMBER ONLY",1)
260 | loopArray["redSide"] = tonumber(text)
261 | if editorSettings.single == false then
262 | sendMsg("No need to input anything for door address. The setting doesn't require it :)")
263 | end
264 | elseif loopArray.doorType == 1 then
265 | loopArray["redColor"] = 0
266 | loopArray["doorAddress"] = {""}
267 | text = sendMsg("No need for redColor! The settings you inputted before don't require it :)","What side? 0=bottom, 1=top, 2=back, 3=front, 4=right, 5=left. NUMBER ONLY",1)
268 | loopArray["redSide"] = tonumber(text)
269 | if editorSettings.single == false then
270 | sendMsg("No need to input anything for door address. The setting doesn't require it :)")
271 | end
272 | else
273 | loopArray["redColor"] = 0
274 | loopArray["redSide"] = 0
275 | sendMsg("no need to input anything for redColor. The setting doesn't require it :)","no need to input anything for redSide. The setting doesn't require it :)")
276 | if editorSettings.single == false then
277 | text = sendMsg("What is the address for the door/rolldoor controller blocks?", editorSettings.scanner and "Scan the blocks with tablet then click screen when done" or "Enter uuids as text then enter with no text and enter",5)
278 | loopArray["doorAddress"] = text
279 | else
280 | loopArray["doorAddress"] = {}
281 | for key,_ in pairs(component.list("os_doorcontroller")) do
282 | table.insert(loopArray["doorAddress"],key)
283 | end
284 | for key,_ in pairs(component.list("os_rolldoorcontroller")) do
285 | table.insert(loopArray["doorAddress"],key)
286 | end
287 | end
288 | end
289 | text = sendMsg("Should the door be toggleable, or not? 0 for autoclose and 1 for toggleable",1)
290 | loopArray["toggle"] = tonumber(text)
291 | if loopArray.toggle == 0 then
292 | text = sendMsg("How long should the door stay open in seconds? NUMBER ONLY",1)
293 | loopArray["delay"] = tonumber(text)
294 | else
295 | sendMsg("No need to change delay! Previous setting doesn't require it :)")
296 | loopArray["delay"] = 0
297 | end
298 | if editorSettings.x == 2 then
299 | local readLoad = {}
300 | sendMsg("Remember how many of each pass you want before you start.","type something and enter to continue",1)
301 | readLoad.add = tonumber(sendMsg("How many add passes do you want to add?","remember multiple base passes can use the same add pass",1))
302 | readLoad.base = tonumber(sendMsg("How many base passes do you want to add?",1))
303 | readLoad.reject = tonumber(sendMsg("How many reject passes do you want to add?","These don't affect supreme passes",1))
304 | readLoad.supreme = tonumber(sendMsg("How many supreme passes do you want to add?",1))
305 | loopArray.cardRead = {}
306 | local nextmsg = {}
307 | nextmsg.beg, nextmsg.mid, nextmsg.back = "What should be read for "," pass number ","? 0 = staff"
308 | for i=1,#editorSettings.settings.var,1 do
309 | nextmsg.back = nextmsg.back .. ", " .. i .. " = " .. editorSettings.settings.label[i]
310 | end
311 | local passFunc = function(type,num)
312 | local newRules = {["uuid"]=uuid.next(),["request"]=type,["data"]=type == "base" and {} or false}
313 | local text = sendMsg(nextmsg.beg..type..nextmsg.mid..num..nextmsg.back,1)
314 | if tonumber(text) == 0 then
315 | newRules.call = "checkstaff"
316 | newRules.param = 0
317 | sendMsg("No need for extra parameter. This mode doesn't require it :)")
318 | else
319 | newRules["tempint"] = tonumber(text)
320 | newRules["call"] = editorSettings.settings.calls[tonumber(text)]
321 | if editorSettings.settings.type[tonumber(text)] == "string" or editorSettings.settings.type == "-string" then
322 | text = sendMsg("What is the string you would like to read? Enter text.",1)
323 | newRules["param"] = text
324 | elseif editorSettings.settings.type[tonumber(text)] == "bool" then
325 | newRules["param"] = 0
326 | sendMsg("No need for extra parameter. This mode doesn't require it :)")
327 | elseif editorSettings.settings.type[tonumber(text)] == "int" then
328 | if editorSettings.settings.above[tonumber(text)] == true then
329 | text = sendMsg("What level and above should be required?",1)
330 | else
331 | text = sendMsg("what level exactly should be required?",1)
332 | end
333 | newRules["param"] = tonumber(text)
334 | elseif editorSettings.settings.type[tonumber(text)] == "-int" then
335 | local nextmsg = "What group are you wanting to set?"
336 | for i=1,#editorSettings.settings.data[tonumber(text)],1 do
337 | nextmsg = nextmsg .. ", " .. i .. " = " .. editorSettings.settings.data[tonumber(text)][i]
338 | end
339 | text = sendMsg(nextmsg,1)
340 | newRules["param"] = tonumber(text)
341 | else
342 | sendMsg("error in cardRead area for num 2")
343 | newRules["param"] = 0
344 | end
345 | end
346 | return newRules
347 | end
348 | for i=1,readLoad.add,1 do
349 | local rule = passFunc("add",i)
350 | table.insert(loopArray.cardRead,rule)
351 | end
352 | local addNum = #loopArray.cardRead
353 | for i=1,readLoad.base,1 do
354 | local rule = passFunc("base",i)
355 | text = tonumber(sendMsg("How many add passes do you want to link?",1))
356 | if text ~= 0 then
357 | local nextAdd = "Which pass do you want to add? "
358 | for j=1,addNum,1 do
359 | nextAdd = nextAdd .. ", " .. j .. " = " .. editorSettings.settings.label[loopArray.cardRead[j].tempint]
360 | end
361 | for j=1,text,1 do
362 | text = tonumber(sendMsg(nextAdd,1))
363 | table.insert(rule.data,loopArray.cardRead[text].uuid)
364 | end
365 | end
366 | table.insert(loopArray.cardRead,rule)
367 | end
368 | for i=1,readLoad.reject,1 do
369 | local rule = passFunc("reject",i)
370 | table.insert(loopArray.cardRead,rule)
371 | end
372 | for i=1,readLoad.supreme,1 do
373 | local rule = passFunc("supreme",i)
374 | table.insert(loopArray.cardRead,rule)
375 | end
376 | else --{["uuid"]=uuid.next()["call"]=t1,["param"]=t2,["request"]="supreme",["data"]=false}
377 | local nextmsg = "What should be read? 0 = staff,"
378 | for i=1,#editorSettings.settings.var,1 do
379 | nextmsg = nextmsg .. ", " .. i .. " = " .. editorSettings.settings.label[i]
380 | end
381 | text = sendMsg(nextmsg,1)
382 | loopArray["cardRead"] = {{["uuid"]=uuid.next(),["call"]="",["param"]=0,["request"]="supreme",["data"]=false}}
383 | if tonumber(text) == 0 then
384 | loopArray["cardRead"][1].call = "checkstaff"
385 | loopArray["cardRead"][1].param = 0
386 | sendMsg("No need to set access level. This mode doesn't require it :)")
387 | else
388 | loopArray["cardRead"][1].call = editorSettings.settings.calls[tonumber(text)]
389 | if editorSettings.settings.type[tonumber(text)] == "string" or editorSettings.settings.type[tonumber(text)] == "-string" then
390 | text = sendMsg("What is the string you would like to read? Enter text.",1)
391 | loopArray["cardRead"][1].param = text
392 | elseif editorSettings.settings.type[tonumber(text)] == "bool" then
393 | loopArray["cardRead"][1].param = 0
394 | sendMsg("No need to set access level. This mode doesn't require it :)")
395 | elseif editorSettings.settings.type[tonumber(text)] == "int" then
396 | if editorSettings.settings.above[tonumber(text)] == true then
397 | text = sendMsg("What level and above should be required?",1)
398 | else
399 | text = sendMsg("what level exactly should be required?",1)
400 | end
401 | loopArray["cardRead"][1].param = tonumber(text)
402 | elseif editorSettings.settings.type[tonumber(text)] == "-int" then
403 | local nextmsg = "What group are you wanting to set?"
404 | for i=1,#editorSettings.settings.data[tonumber(text)],1 do
405 | nextmsg = nextmsg .. ", " .. i .. " = " .. editorSettings.settings.data[tonumber(text)][i]
406 | end
407 | text = sendMsg(nextmsg,1)
408 | loopArray["cardRead"][1].param = tonumber(text)
409 | else
410 | sendMsg("error in cardRead area for num 2")
411 | loopArray["cardRead"][1].param = 0
412 | end
413 | end
414 | end --Sectors beginning
415 | if editorSettings.hassector then
416 | local nextmsg = "What sector would you like this door to be part of? 0 = no sector"
417 | for i=1,#editorSettings.settings.sectors,1 do --Issue
418 | nextmsg = nextmsg .. ", " .. i .. " = " .. editorSettings.settings.sectors[i].name
419 | end
420 | text = tonumber(sendMsg(nextmsg,1))
421 | if text == 0 then
422 | loopArray["sector"]=false
423 | else
424 | loopArray["sector"]=editorSettings.settings.sectors[text].uuid
425 | end
426 | else
427 | loopArray["sector"] = false
428 | end
429 | tmpTable[j] = loopArray
430 | end
431 | text = sendMsg("All done with installer!","Would you like to start the computer now?","1 for yes, 2 for no",1)
432 | editorSettings.start = false
433 | if tonumber(text) == 1 then
434 | sendMsg("Ok, will start computer.",4)
435 | editorSettings.start = true
436 | else
437 | sendMsg("Ok, closing out.",4)
438 | end
439 | return tmpTable
440 | end
441 |
442 | local function oldFiles()
443 | term.clear()
444 | local config = loadTable(configFileName)
445 | if config == nil then
446 | sendMsg("Error reading config file. Is this an up to date version?","It is recommended to wipe and reinstall at this point",4)
447 | end
448 | editorSettings.type = config.type
449 | editorSettings.single = false
450 | local text = sendMsg("Old files detected. Please select an option:","1 = wipe all files","2 = update door","3 = change cryptKey","4 = change port",1)
451 | if tonumber(text) == 1 then
452 | term.clear()
453 | sendMsg("Deleting all files...")
454 | local path = shell.getWorkingDirectory()
455 | fs.remove(path .. "/" .. program)
456 | fs.remove(path .. "/" .. settingFileName)
457 | if config ~= nil then fs.remove(path .. "/" .. configFileName) end
458 | local fill = io.open(settingFileName)
459 | if fill~=nil then
460 | sendMsg("an error occured and some files may not have deleted.",4)
461 | fill:close()
462 | else
463 | sendMsg("all done!",4)
464 | end
465 | elseif tonumber(text) == 2 then
466 | text = sendMsg("Are you sure you want to do this? New updates sometimes require manual changing of config.","1 for continue, 2 for cancel",1)
467 | if tonumber(text) == 1 then
468 | os.execute("wget -f " .. doorCode .. " " .. program)
469 | end
470 | text = sendMsg("all done! is set to " .. ser.serialize(config.cryptKey),"Would you like to start the computer now?","1 for yes, 2 for no",1)
471 | if tonumber(text) == 1 then
472 | sendMsg("Starting...",4)
473 | os.execute(program)
474 | else
475 | sendMsg("Ok, closing out.",4)
476 | end
477 | elseif tonumber(text) == 3 then
478 | sendMsg("there are 5 parameters, each requiring a number. Recommend doing 1 digit numbers cause I got no idea how this works lol")
479 | for i=1,5,1 do
480 | text = sendMsg("enter param " .. i,1)
481 | config.cryptKey[i] = tonumber(text)
482 | end
483 | saveTable(config,configFileName)
484 | text = sendMsg("all done! is set to " .. ser.serialize(config.cryptKey),"Would you like to start the computer now?","1 for yes, 2 for no",1)
485 | if tonumber(text) == 1 then
486 | sendMsg("Starting...",4)
487 | os.execute(program)
488 | else
489 | sendMsg("Ok, closing out.",4)
490 | end
491 | elseif tonumber(text) == 4 then
492 | config.port = modemPort
493 | sendMsg("Port changed to " .. modemPort)
494 | saveTable(config,configFileName)
495 | end
496 | config = nil
497 | end
498 |
499 | modem.close()
500 | term.clear()
501 |
502 | if component.isAvailable("tunnel") then
503 | link = component.tunnel
504 | end
505 |
506 | modem.open(syncPort)
507 | modem.broadcast(syncPort,"syncport")
508 | local e,_,_,_,_,msg = event.pull(1,"modem_message")
509 | modem.close(syncPort)
510 | if e then
511 | modemPort = tonumber(msg)
512 | else
513 | print("What port is the server running off of?")
514 | local text = term.read()
515 | modemPort = tonumber(text:sub(1,-2))
516 | term.clear()
517 | end
518 |
519 | print("Sending query to server...")
520 | if link == nil then
521 | modem.open(modemPort)
522 | end
523 | send(nil,modemPort,true,"getquery",ser.serialize({"passSettings","sectors","&&&crypt"}))
524 | local e,_,from,port,_,msg = event.pull(3,"modem_message")
525 | if e == nil then
526 | print("No query received. Assuming old server system is in place and will not work.")
527 | os.exit()
528 | end
529 | print("Query received")
530 | query = ser.unserialize(msg)
531 | if query.num ~= 3 then
532 | print("Security server is not valid. Must be 3.0.0 and up")
533 | os.exit()
534 | end
535 | editorSettings.x = 2
536 | editorSettings.num = query.num
537 | editorSettings.version = query.version
538 | editorSettings.hassector = query.data.sectors ~= nil
539 | editorSettings.settings = query.data.passSettings
540 | editorSettings.settings.sectors = query.data.sectors
541 | editorSettings.scanner = false
542 | editorSettings.accelerate = false
543 | editorSettings.single = false
544 | term.clear()
545 | local text = sendMsg("Would you like to use an external device for accelerated setup?","This makes it easier to set up doors without having to move from the door to the pc constantly.","It requires a diagnostic tablet (found on github)","1 for yes, 2 for no",1)
546 | if tonumber(text) == 1 then
547 | modem.open(diagPort)
548 | modem.close(modemPort)
549 | sendMsg("Start up accelerated door setup on your diagnostic tablet","in 60 seconds with no changes the program will close")
550 |
551 | local time = 0
552 | local timer = function(seconds)
553 | time = seconds
554 | for i=1,seconds, 1 do
555 | os.sleep(1)
556 | time = time - 1
557 | end
558 | end
559 | local waiter = true
560 | local e, _, from, port, _, msg, barcode, t
561 | t = thread.create(timer) --setup incorrect
562 | while waiter do
563 | e, _, from, port, _, msg, barcode = event.pull(time, "modem_message")
564 | if e then
565 | if msg == "accsetup" then
566 | waiter = false
567 | end
568 | else
569 | waiter = false
570 | end
571 | end
572 |
573 | if e then
574 | modem.open(modemPort)
575 | t:kill()
576 | send(from,port,false,"connected")
577 | term.clear()
578 | sendMsg("Connection successful! All prompts will be on the tablet now on.")
579 | os.sleep(1)
580 | editorSettings.scanner = barcode
581 | editorSettings.accelerate = true
582 | editorSettings.from = from
583 | editorSettings.port = port
584 | else
585 | modem.close(diagPort)
586 | print("Setup cancelled")
587 | os.exit()
588 | end
589 | else
590 | sendMsg("Normal setup initiating.")
591 | end
592 | term.clear()
593 | sendMsg("Checking files...")
594 | local text
595 | local fill = io.open(program,"r")
596 | if fill~=nil then
597 | fill:close()
598 | oldFiles()
599 | else
600 | term.clear()
601 | editorSettings.type = "doorsystem"
602 | os.execute("wget -f " .. doorCode .. " " .. program)
603 | text = sendMsg("Would you like to use the simplified single door or multi-door?","true for single door of false for regular, multidoor setup",1)
604 | editorSettings.single = text == "true" and true or false
605 | settingData = runInstall()
606 | saveTable(settingData,settingFileName)
607 | if editorSettings.start == true then
608 | print("Starting...")
609 | os.execute(program)
610 | else
611 | print("Run " .. program .. " now to start door.")
612 | end
613 | end
614 |
--------------------------------------------------------------------------------
/security/quikidlink.lua:
--------------------------------------------------------------------------------
1 | --A program that allows users to link their card to their MC User (if there is not one linked already)
2 | local apiCode = "https://raw.githubusercontent.com/cadergator10/Opencomputers-servertine/main/serpAPI.lua" --Shouldn't need the modified SecurityAPI version due to it implementing custom features.
3 | local component = require("component")
4 | local term = require("term")
5 | local io = require("io")
6 | local ser = require("serialization")
7 | local fs = require("filesystem")
8 | local event = require("event")
9 | local api = require("serpAPI.lua")
10 |
11 | term.clear()
12 | if api == nil then --Checkong for SerpAPI program. If it doesn't exist, download it.
13 | print("No API installed. Downloading")
14 | os.execute("wget -f " .. apiCode .. " " .. "serpAPI")
15 | api = require("serpAPI.lua") --Attempt to get again. Experimental (dont know if it will work)
16 | end
17 |
18 | api.setup({["type"]="quikidlink"},{}) --Prepare table to submit to server. Setting the type in case I want to do something on the server and such
19 |
20 | for key,_ in pairs(component.list("os_magreader")) do --Prepare light on magreader to signal stuff
21 | component.proxy(key).swipeIndicator(false)
22 | component.proxy(key).setLightState(3) --3 is red and yellow, meaning swipe card
23 | end
24 |
25 | while true do
26 | term.clear()
27 | print("Quick Minecraft UUID Link")
28 | print("---------------------------------------------------------------------------")
29 | print("Please swipe the card you want to link your ID to")
30 | local ev, address, _, str = event.pull("magData") --wait for a card swipe
31 | component.proxy(address).setLightState(2) --2 is yellow, meaning waiting. Doing stuff
32 | local _, data = api.crypt(str, true) --decrypt card's data
33 | data = ser.unserialize(data) --unserialize card data
34 | if ev and data ~= nil then --Read the data successfully and decrypted
35 | print("Welcome " .. data.name)
36 | print("Please click the biometric reader to link player")
37 | component.proxy(address).setLightState(6) --6 is green and yellow, meaning click bioreader
38 | local e, ad, msg = event.pull(7,"bioReader") --wait for bioreader click or timeout
39 | component.proxy(address).setLightState(2) --2 is yellow. Waiting for message back
40 | if e then --clicked bioreader
41 | print("Waiting for response from server...")
42 | data = api.crypt(ser.serialize({["uuid"]=data.uuid,["mcid"]=msg})) --encrypting data and sending to server to check if user exists and they don't have a mcid linked yet
43 | e, msg = api.send(true,"linkMCID",data)
44 | if e then --Received message back
45 | _, msg = api.crypt(msg,true)
46 | if msg == "true" then --Linked user successfully
47 | print("Link success! All biometric reader doors should work for you now")
48 | component.proxy(address).setLightState(4) --4 is green, meaning success
49 | else --Failed for some reason
50 | print("Link failed: Either card already is linked, account no longer exists, or card is blocked")
51 | component.proxy(address).setLightState(1) --1 is red, meaning failed in this case.
52 | end
53 | else --No message received
54 | print("Server failed to respond. Has it crashed or is it off?")
55 | component.proxy(address).setLightState(7) --7 is all lights, indicating error (server down or crash?)
56 | end
57 | else --Didn't click bio reader in time
58 | print("Biometric timeout")
59 | component.proxy(address).setLightState(1) --1 is red, indicating a timeout for the bioreader and no link
60 | end
61 | else --Card wasn't able to be read
62 | print("Failed to read card")
63 | component.proxy(address).setLightState(1) --1 is red, indicating in this case that either nothing was received (ev) or card was nil (no data on card or incorrect crypted data)
64 | end
65 | os.sleep(3)
66 | component.proxy(address).setLightState(3) --reset it to swipe card mode
67 | end
--------------------------------------------------------------------------------
/security/securityAPI.lua:
--------------------------------------------------------------------------------
1 | local version = "4.0.3"
2 | --testR = true
3 |
4 | local security = {}
5 |
6 | local cardRead = {};
7 |
8 | local adminCard = "admincard"
9 |
10 | local modemPort = 1000
11 | local syncPort = 199
12 | local diagPort = 180
13 | local dbPort = 144
14 |
15 | local component = require("component")
16 | local gpu = component.gpu
17 | local event = require("event")
18 | local ser = require("serialization")
19 | local term = require("term")
20 | local thread = require("thread")
21 | local process = require("process")
22 | local uuid = require("uuid")
23 | local computer = component.computer
24 |
25 | local magReader = component.os_magreader
26 | local modem = component.modem
27 | local link
28 |
29 | local baseVariables = {"name","uuid","date","link","blocked","staff"}
30 | local varSettings = {}
31 |
32 | local query
33 |
34 | local settingData = {}
35 | local extraConfig = {}
36 |
37 | --------TableToFile
38 |
39 | local function saveTable( tbl,filename )
40 | local tableFile = assert(io.open(filename, "w"))
41 | tableFile:write(ser.serialize(tbl))
42 | tableFile:close()
43 | end
44 |
45 | local function loadTable( sfile )
46 | local tableFile = io.open(sfile)
47 | if tableFile ~= nil then
48 | return ser.unserialize(tableFile:read("*all"))
49 | else
50 | return nil
51 | end
52 | end
53 |
54 | --------Base Functions
55 |
56 | local function convert( chars, dist, inv )
57 | return string.char( ( string.byte( chars ) - 32 + ( inv and -dist or dist ) ) % 95 + 32 )
58 | end
59 |
60 | local function crypt(str,k,inv)
61 | local enc= "";
62 | for i=1,#str do
63 | if(#str-k[5] >= i or not inv)then
64 | for inc=0,3 do
65 | if(i%4 == inc)then
66 | enc = enc .. convert(string.sub(str,i,i),k[inc+1],inv);
67 | break;
68 | end
69 | end
70 | end
71 | end
72 | if(not inv)then
73 | for i=1,k[5] do
74 | enc = enc .. string.char(math.random(32,126));
75 | end
76 | end
77 | return enc;
78 | end
79 |
80 | local function splitString(str, sep)
81 | local sep, fields = sep or ":", {}
82 | local pattern = string.format("([^%s]+)", sep)
83 | str:gsub(pattern, function(c) fields[#fields+1] = c end)
84 | return fields
85 | end
86 |
87 | local function send(label,port,linker,...) --Pingme
88 | if linker and link ~= nil then
89 | link.send(modem.address,...)
90 | return
91 | end
92 | if label then
93 | modem.send(label,port,...)
94 | else
95 | modem.broadcast(port,...)
96 | end
97 | end
98 |
99 | --------Called Functions
100 |
101 | local function update(_, localAddress, remoteAddress, port, distance, msg, data)
102 | if msg == "deviceCheck" then
103 | send(nil, modemPort,true,"true")
104 | end
105 | end
106 |
107 | function security.setup()
108 | local e
109 | local fill = io.open("extraConfig.txt", "r")
110 | if fill ~= nil then
111 | io.close(fill)
112 | else
113 | local config = {}
114 | config.cryptKey = {}
115 | term.clear()
116 | print("First Time Config Setup: Would you like to use default cryptKey? 1 for yes, 2 for no")
117 | local text = term.read()
118 | if tonumber(text) == 2 then
119 | print("there are 5 parameters, each requiring a number. Recommend doing 1 digit numbers")
120 | for i=1,5,1 do
121 | print("enter param " .. i)
122 | text = term.read()
123 | config.cryptKey[i] = tonumber(text)
124 | end
125 | else
126 | config.cryptKey = {1,2,3,4,5}
127 | end
128 | config.type = "single"
129 | config.num = 3
130 | config.version = version
131 | modem.open(syncPort)
132 | modem.broadcast(syncPort,"syncport")
133 | local e,_,_,_,_,msg = event.pull(1,"modem_message")
134 | modem.close(syncPort)
135 | if e then
136 | config.port = tonumber(msg)
137 | else
138 | print("What port is the server running off of?")
139 | local text = term.read()
140 | config.port = tonumber(text:sub(1,-2))
141 | term.clear()
142 | end
143 | saveTable(config,"extraConfig.txt")
144 | end
145 | extraConfig = loadTable("extraConfig.txt")
146 | modemPort = extraConfig.port
147 | if component.isAvailable("tunnel") then
148 | link = component.tunnel
149 | modem.close(modemPort)
150 | else
151 | modem.open(modemPort)
152 | end
153 | send(nil,modemPort,true,"getquery",ser.serialize({"passSettings"}))
154 | e,_,_,_,_,query = event.pull(3,"modem_message")
155 | if e == nil then
156 | print("Failed query. Is the server on?")
157 | os.exit()
158 | end
159 | query = ser.unserialize(crypt(query,extraConfig.cryptKey,true))
160 | if query.num ~= 3 then
161 | print("Server is not 3.0.0 and up")
162 | os.exit()
163 | end
164 | fill = io.open("securitySettings.txt")
165 | if fill ~= nil then
166 | io.close(fill)
167 | else
168 | term.clear()
169 | settingData = {}
170 | print("First time pass setup")
171 | print("Would you like to use the simple pass setup or new advanced one? 1 for simple, 2 for advanced")
172 | local text = term.read()
173 | settingData.name = "Test Security API"
174 | if tonumber(text) == 1 then
175 | local nextmsg = "What should be read? 0 = staff,"
176 | for i=1,#query.data.passSettings.var,1 do
177 | nextmsg = nextmsg .. ", " .. i .. " = " .. query.data.passSettings.label[i]
178 | end
179 | print(nextmsg)
180 | text = term.read()
181 | settingData.cardRead = {{["uuid"]=uuid.next(),["call"]="",["param"]=0,["request"]="supreme",["data"]=false}}
182 | if tonumber(text) == 0 then
183 | settingData.cardRead[1].call = "checkstaff"
184 | settingData.cardRead[1].param = 0
185 | print("No need to set access level. This mode doesn't require it :)")
186 | else
187 | settingData.cardRead[1].call = query.data.passSettings.calls[tonumber(text)]
188 | if query.data.passSettings.type[tonumber(text)] == "string" or query.data.passSettings.type[tonumber(text)] == "-string" then
189 | print("What is the string you would like to read? Enter text.")
190 | text = term.read()
191 | settingData.cardRead[1].param = text:sub(1,-2)
192 | elseif query.data.passSettings.type[tonumber(text)] == "bool" then
193 | settingData.cardRead[1].param = 0
194 | print("No need to set access level. This mode doesn't require it :)")
195 | elseif query.data.passSettings.type[tonumber(text)] == "int" then
196 | if query.data.passSettings.above[tonumber(text)] == true then
197 | print("What level and above should be required?")
198 | else
199 | print("what level exactly should be required?")
200 | end
201 | text = term.read()
202 | settingData.cardRead[1].param = tonumber(text)
203 | elseif query.data.passSettings.type[tonumber(text)] == "-int" then
204 | local nextmsg = "What group are you wanting to set?"
205 | for i=1,#query.data.passSettings.data[tonumber(text)],1 do
206 | nextmsg = nextmsg .. ", " .. i .. " = " .. query.data.passSettings.data[tonumber(text)][i]
207 | end
208 | print(nextmsg)
209 | text = term.read()
210 | settingData.cardRead[1].param = tonumber(text)
211 | else
212 | print("error in cardRead area for num 2")
213 | settingData.cardRead[1].param = 0
214 | end
215 | end
216 | else
217 | local readLoad = {}
218 | print("Remember how many of each pass you want before you start.","Press enter to continue")
219 | term.read()
220 | print("How many add passes do you want to add?","remember multiple base passes can use the same add pass")
221 | readLoad.add = tonumber(term.read())
222 | print("How many base passes do you want to add?")
223 | readLoad.base = tonumber(term.read())
224 | print("How many reject passes do you want to add?","These don't affect supreme passes")
225 | readLoad.reject = tonumber(term.read())
226 | print("How many supreme passes do you want to add?")
227 | readLoad.supreme = tonumber(term.read())
228 | settingData.cardRead = {}
229 | local nextmsg = {}
230 | nextmsg.beg, nextmsg.mid, nextmsg.back = "What should be read for "," pass number ","? 0 = staff"
231 | for i=1,#query.data.passSettings.var,1 do
232 | nextmsg.back = nextmsg.back .. ", " .. i .. " = " .. query.data.passSettings.label[i]
233 | end
234 | local passFunc = function(type,num)
235 | local newRules = {["uuid"]=uuid.next(),["request"]=type,["data"]=type == "base" and {} or false}
236 | print(nextmsg.beg..type..nextmsg.mid..num..nextmsg.back)
237 | text = term.read()
238 | if tonumber(text) == 0 then
239 | newRules.call = "checkstaff"
240 | newRules.param = 0
241 | print("No need for extra parameter. This mode doesn't require it :)")
242 | else
243 | newRules["tempint"] = tonumber(text)
244 | newRules["call"] = query.data.passSettings.calls[tonumber(text)]
245 | if query.data.passSettings.type[tonumber(text)] == "string" or query.data.passSettings.type[tonumber(text)] == "-string" then
246 | print("What is the string you would like to read? Enter text.")
247 | text = term.read()
248 | newRules["param"] = text:sub(1,-2)
249 | elseif query.data.passSettings.type[tonumber(text)] == "bool" then
250 | newRules["param"] = 0
251 | print("No need for extra parameter. This mode doesn't require it :)")
252 | elseif query.data.passSettings.type[tonumber(text)] == "int" then
253 | if query.data.passSettings.above[tonumber(text)] == true then
254 | print("What level and above should be required?")
255 | else
256 | print("what level exactly should be required?")
257 | end
258 | text = term.read()
259 | newRules["param"] = tonumber(text)
260 | elseif query.data.passSettings.type[tonumber(text)] == "-int" then
261 | local nextmsg = "What group are you wanting to set?"
262 | for i=1,#query.data.passSettings.data[tonumber(text)],1 do
263 | nextmsg = nextmsg .. ", " .. i .. " = " .. query.data.passSettings.data[tonumber(text)][i]
264 | end
265 | print(nextmsg)
266 | text = term.read()
267 | newRules["param"] = tonumber(text)
268 | else
269 | print("error in cardRead area for num 2")
270 | newRules["param"] = 0
271 | end
272 | end
273 | return newRules
274 | end
275 | for i=1,readLoad.add,1 do
276 | local rule = passFunc("add",i)
277 | table.insert(settingData.cardRead,rule)
278 | end
279 | local addNum = #settingData.cardRead
280 | for i=1,readLoad.base,1 do
281 | local rule = passFunc("base",i)
282 | print("How many add passes do you want to link?")
283 | text = tonumber(term.read())
284 | if text ~= 0 then
285 | local nextAdd = "Which pass do you want to add? "
286 | for j=1,addNum,1 do
287 | nextAdd = nextAdd .. ", " .. j .. " = " .. query.data.passSettings.label[settingData.cardRead[j].tempint]
288 | end
289 | for j=1,text,1 do
290 | print(nextAdd)
291 | text = tonumber(term.read())
292 | table.insert(rule.data,settingData.cardRead[text].uuid)
293 | end
294 | end
295 | table.insert(settingData.cardRead,rule)
296 | end
297 | for i=1,readLoad.reject,1 do
298 | local rule = passFunc("reject",i)
299 | table.insert(settingData.cardRead,rule)
300 | end
301 | for i=1,readLoad.supreme,1 do
302 | local rule = passFunc("supreme",i)
303 | table.insert(settingData.cardRead,rule)
304 | end
305 | end
306 | saveTable(settingData,"securitySettings.txt")
307 | end
308 | term.clear()
309 | settingData = loadTable("securitySettings.txt")
310 | fill = {}
311 | fill["type"] = "customdoor"
312 | fill["data"] = settingData
313 | send(nil,modemPort,true,"setdevice",crypt(ser.serialize(fill),extraConfig.cryptKey))
314 | local got, _, _, _, _, fill = event.pull(2, "modem_message")
315 | if got then
316 | varSettings = ser.unserialize(crypt(fill,extraConfig.cryptKey,true))
317 | else
318 | print("Failed to receive confirmation from server")
319 | os.exit()
320 | end
321 | got = nil
322 | event.listen("modem_message", update)
323 | process.info().data.signal = function(...)
324 | print("caught hard interrupt")
325 | event.ignore("modem_message", update)
326 | os.exit()
327 | end
328 | end
329 |
330 | function security.checkPass(str,loc)
331 | local data = crypt(str,extraConfig.cryptKey,true)
332 | local tmpTable = ser.unserialize(data)
333 | tmpTable["type"] = "customdoor"
334 | data = crypt(ser.serialize(tmpTable), extraConfig.cryptKey)
335 | if loc ~= nil then
336 | send(loc,modemPort,true,"checkRules",data,true)
337 | else
338 | send(nil,modemPort,true,"checkRules",data,true)
339 | end
340 | local e, _, from, port, _, msg = event.pull(3, "modem_message")
341 | if e then
342 | data = crypt(msg, extraConfig.cryptKey, true)
343 | if data == "true" then
344 | return true, true
345 | else
346 | return true, false
347 | end
348 | else
349 | return false, "timed out"
350 | end
351 | end
352 |
353 | function security.getVar(str,var,loc)
354 | local data = crypt(str,extraConfig.cryptKey,true)
355 | data = ser.unserialize(data)
356 | if type(var) == "boolean" or var == nil then
357 | var = settingData.cardRead[1].call
358 | for i=1,#query.data.passSettings.calls, 1 do
359 | if var == query.data.passSettings.calls[i] then
360 | var = query.data.passSettings.var[i]
361 | break
362 | end
363 | end
364 | end
365 | data.var = var
366 | data = crypt(ser.serialize(data),extraConfig.cryptKey)
367 | if loc ~= nil then
368 | send(loc,modemPort,true,"getvar",data)
369 | else
370 | send(nil,modemPort,true,"getvar",data)
371 | end
372 | local e, _, from, port, _, msg = event.pull(3, "modem_message")
373 | if e then
374 | data = crypt(msg, extraConfig.cryptKey, true)
375 |
376 | return true, ser.unserialize(data) or data
377 | else
378 | return false, "timed out or user not found"
379 | end
380 | end
381 | function security.setVar(str,var,it,loc)
382 | local data = crypt(str,extraConfig.cryptKey,true)
383 | data = ser.unserialize(data)
384 | if type(var) == "boolean" or var == nil then
385 | var = settingData.cardRead[1].call
386 | for i=1,#query.data.passSettings.calls, 1 do
387 | if var == query.data.passSettings.calls[i] then
388 | var = query.data.passSettings.var[i]
389 | break
390 | end
391 | end
392 | end
393 | data.var = var
394 | data.data = it
395 | data = crypt(ser.serialize(data),extraConfig.cryptKey)
396 | if loc ~= nil then
397 | send(loc,modemPort,true,"setvar",data)
398 | else
399 | send(nil,modemPort,true,"setvar",data)
400 | end
401 | local e, _, from, port, _, msg = event.pull(3, "modem_message")
402 | if e then
403 | return true, "no error"
404 | else
405 | return false, "timed out"
406 | end
407 | end
408 |
409 | local function checkLink() --ported directly from my single program using this. Should work as I haven't modified it since
410 | print("retrieving config")
411 | local fill = io.open("linkConfig.txt", "r")
412 | if fill~=nil then
413 | print("previous config detected")
414 | io.close(fill)
415 | else
416 | print("no config detected. Making new one")
417 | settingData = {}
418 | settingData["code"] = uuid.next()
419 | saveTable(settingData,"linkConfig.txt")
420 | end
421 | settingData = loadTable("linkConfig.txt")
422 | print("loaded config. Connecting to account...")
423 | modem.open(modemPort)
424 | local str = crypt(settingData["code"],extraConfig.cryptKey)
425 | send(nil,modemPort,true,"checkLinked",str)
426 | local e, _, from, port, _, msg = event.pull(1, "modem_message")
427 | modem.close(modemPort)
428 | if e then
429 | str = crypt(msg, extraConfig.cryptKey, true)
430 | local da = ser.unserialize(str)
431 | if da["status"] == true then
432 | print("successfully connected")
433 | return "true",da["name"],settingData.code
434 | else
435 | if da["reason"] == 1 then
436 | print("No account linked. When you are ready, click the screen")
437 | event.pull("touch")
438 | term.write("wait...")
439 | modem.open(dbPort)
440 | local newUUID = uuid.next()
441 | send(nil,dbPort,false,crypt(newUUID,extraConfig.cryptKey))
442 | e, _, from, port, _, msg = event.pull(3, "modem_message")
443 | modem.close(dbPort)
444 | if e then
445 | local nm = crypt(msg,extraConfig.cryptKey,true)
446 | term.write(" linked to " .. nm .. "\n")
447 | settingData["code"] = newUUID
448 | saveTable(settingData,"linkConfig.txt")
449 | return true,nm, settingData.code
450 | else
451 | term.write(" linking failed\n")
452 | return "false","nil", settingData.code
453 | end
454 | elseif da["reason"] == 2 then
455 | print("Your account is blocked")
456 | return "false","nil", settingData.code
457 | else
458 | print("unknown error")
459 | return "false","nil", settingData.code
460 | end
461 | end
462 | else
463 | print("server timeout")
464 | return "false"
465 | end
466 | end
467 |
468 | function security.link() --If using linking, do this rather than security.setup()
469 | local e
470 | local fill = io.open("extraConfig.txt", "r")
471 | if fill ~= nil then
472 | io.close(fill)
473 | else
474 | local config = {}
475 | config.cryptKey = {}
476 | term.clear()
477 | print("First Time Config Setup: Would you like to use default cryptKey? 1 for yes, 2 for no")
478 | local text = term.read()
479 | if tonumber(text) == 2 then
480 | print("there are 5 parameters, each requiring a number. Recommend doing 1 digit numbers")
481 | for i=1,5,1 do
482 | print("enter param " .. i)
483 | text = term.read()
484 | config.cryptKey[i] = tonumber(text)
485 | end
486 | else
487 | config.cryptKey = {1,2,3,4,5}
488 | end
489 | config.type = "link"
490 | config.num = 3
491 | config.version = version
492 | modem.open(syncPort)
493 | modem.broadcast(syncPort,"syncport")
494 | local e,_,_,_,_,msg = event.pull(1,"modem_message")
495 | modem.close(syncPort)
496 | if e then
497 | config.port = tonumber(msg)
498 | else
499 | print("What port is the server running off of?")
500 | local text = term.read()
501 | config.port = tonumber(text:sub(1,-2))
502 | term.clear()
503 | end
504 | saveTable(config,"extraConfig.txt")
505 | end
506 | extraConfig = loadTable("extraConfig.txt")
507 | modemPort = extraConfig.port
508 | if component.isAvailable("tunnel") then
509 | link = component.tunnel
510 | modem.close(modemPort)
511 | else
512 | modem.open(modemPort)
513 | end
514 | send(nil,modemPort,true,"getquery",ser.serialize({"passSettings"}))
515 | e,_,_,_,_,query = event.pull(3,"modem_message")
516 | if e == nil then
517 | print("Failed query. Is the server on?")
518 | os.exit()
519 | end
520 | query = ser.unserialize(crypt(query,extraConfig.cryptKey,true))
521 | if query.num ~= 3 then
522 | print("Server is not 3.0.0 and up")
523 | os.exit()
524 | end
525 | local worked, user = checkLink()
526 |
527 | end
528 |
529 | function security.crypt(str,reverse)
530 | return true,crypt(str,extraConfig.cryptKey,reverse)
531 | end
532 |
533 | function security.save(table,location)
534 | saveTable(table,location)
535 | end
536 | function security.load(location)
537 | return loadTable(location)
538 | end
539 |
540 | function security.send(wait,...)
541 | send(nil,modemPort,true,...)
542 | if wait then
543 | local e, _, _, _, _, msg,msg2 = event.pull(3, "modem_message")
544 | if e then
545 | return true,msg,msg2
546 | else
547 | return false,"timed out"
548 | end
549 | else
550 | return true,"no return requested"
551 | end
552 | return false, "unknown error"
553 | end
554 |
555 | return security
556 |
557 |
--------------------------------------------------------------------------------
/whattodo.txt:
--------------------------------------------------------------------------------
1 | Instructions on what I gotta check out and maybe add
2 |
3 | Definitely Servertine (this):
4 | 2. DoorSetup allow runtime door editing on currently running doors. (maybe an added perk of choosing door systems through naming multidoors)
5 | 5. SectorControl module for Servertine (an optional manual changing utility)
6 | 8. Database remote control module
7 |
8 | Debug and Test
9 | RFID Reader
10 | Linking and User ID
11 | KeyPad, RFID Reader, and Biometric Reader.
12 |
13 | done
14 | groups (-int) get dropdown rather than int changer with +- (DONE)
15 | Text Box for level in security module (no +- buttons alone, quick change) (DONE)
16 | CryptKey ALL THE FEATURES I CAN to prevent security holes (DONE)
17 | Save changes done on DoorSetup to prevent data loss upon leaving the module (DONE)
18 | Make SectorControl utilize runtime changes (3 wires per sector: 1 to turn off lockdown, another to enable, and another to lock open) (DONE)
19 |
20 |
21 | DO:
22 | 4. Update workspace when pressing the two buttons (update gui)
--------------------------------------------------------------------------------