remoterf 0.0.7.27__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of remoterf might be problematic. Click here for more details.

remoteRF/core/app.py ADDED
@@ -0,0 +1,481 @@
1
+ from . import *
2
+ from ..common.utils import *
3
+
4
+ import getpass
5
+ import os
6
+ import datetime
7
+ import time
8
+ import ast
9
+
10
+ from prompt_toolkit import PromptSession
11
+
12
+ account = RemoteRFAccount()
13
+ session = PromptSession()
14
+
15
+ def welcome():
16
+ printf("Welcome to Remote RF Account System. (all times are in PST)", (Sty.BOLD, Sty.BLUE))
17
+ try:
18
+ inpu = session.prompt(stylize("Please ", Sty.DEFAULT, "login", Sty.GREEN, " or ", Sty.DEFAULT, "register", Sty.RED, " to continue. (", Sty.DEFAULT, 'l', Sty.GREEN, "/", Sty.DEFAULT, 'r', Sty.RED, "):", Sty.DEFAULT))
19
+ if inpu == 'r':
20
+ print("Registering new account ...")
21
+ account.username = input("Username: ")
22
+ double_check = True
23
+ while double_check:
24
+ password = getpass.getpass("Password (Hidden): ")
25
+ password2 = getpass.getpass("Confirm Password: ")
26
+ if password == password2:
27
+ double_check = False
28
+ else:
29
+ print("Passwords do not match. Try again")
30
+
31
+ account.password = password
32
+ account.email = input("Email: ") # TODO: Email verification.
33
+ # check if login was valid
34
+ os.system('cls' if os.name == 'nt' else 'clear')
35
+
36
+ if not account.create_user():
37
+ welcome()
38
+ else:
39
+ account.username = input("Username: ")
40
+ account.password = getpass.getpass("Password (Hidden): ")
41
+ # check if login was valid
42
+ if not account.login_user():
43
+ os.system('cls' if os.name == 'nt' else 'clear')
44
+ print("Invalid login. Try again. Contact admin(s) if you forgot your password.")
45
+ welcome()
46
+ except KeyboardInterrupt:
47
+ exit()
48
+ except EOFError:
49
+ exit()
50
+
51
+ def title():
52
+ printf(f"Remote RF Account System", Sty.BOLD)
53
+ # printf(f"Logged in as: ", Sty.DEFAULT, f'{account.username}', Sty.MAGENTA)
54
+ printf(f"Input ", Sty.DEFAULT, "'help' ", Sty.BRIGHT_GREEN, "for avaliable commands.", Sty.DEFAULT)
55
+
56
+ def commands():
57
+ printf("Commands:", Sty.BOLD)
58
+ printf("'clear' ", Sty.MAGENTA, "- Clear Terminal", Sty.DEFAULT)
59
+ printf("'getdev' ", Sty.MAGENTA, "- View Devices", Sty.DEFAULT)
60
+ printf("'help' or 'h'", Sty.MAGENTA, "- Show this help message", Sty.DEFAULT)
61
+ printf("'perms' ", Sty.MAGENTA, "- View Permissions", Sty.DEFAULT)
62
+ printf("'exit' or 'quit'", Sty.MAGENTA, "- Exit", Sty.DEFAULT)
63
+ printf("'getres' ", Sty.MAGENTA, "- View All Reservations", Sty.DEFAULT)
64
+ printf("'myres' ", Sty.MAGENTA, "- View My Reservations", Sty.DEFAULT)
65
+ printf("'cancelres' ", Sty.MAGENTA, "- Cancel a Reservation", Sty.DEFAULT)
66
+ printf("'resdev' ", Sty.MAGENTA, "- Reserve a Device", Sty.DEFAULT)
67
+ printf("'resdev -n' ", Sty.MAGENTA, "- Naive reserve device", Sty.DEFAULT)
68
+ # printf("'resdev s' ", Sty.MAGENTA, "- Reserve a Device (by single date)", Sty.DEFAULT)
69
+ # check if user is admin
70
+ # if account.get_perms().results['UC'] == 'Admin':
71
+
72
+ def clear():
73
+ os.system('cls' if os.name == 'nt' else 'clear')
74
+ title()
75
+
76
+ def reservations():
77
+ data = account.get_reservations()
78
+ if 'ace' in data.results:
79
+ print(f"Error: {unmap_arg(data.results['ace'])}")
80
+ return
81
+ entries = []
82
+
83
+ for key, value in data.results.items():
84
+ parts = unmap_arg(value).split(',')
85
+ # Create a dictionary for each entry with named fields
86
+ entry = {
87
+ 'username': parts[0],
88
+ 'device_id': int(parts[1]), # Convert device_id to integer for proper numerical sorting
89
+ 'start_time': datetime.datetime.strptime(parts[2], '%Y-%m-%d %H:%M:%S'), # Convert start_time to datetime
90
+ 'end_time': parts[3]
91
+ }
92
+ entries.append(entry)
93
+
94
+ if (entries == []):
95
+ printf("No reservations found.", Sty.BOLD)
96
+ return
97
+
98
+ printf("Reservations:", Sty.BOLD)
99
+
100
+ # Sort the entries by device_id and then by start_time
101
+ sorted_entries = sorted(entries, key=lambda x: (x['device_id'], x['start_time']))
102
+
103
+ # Format the sorted entries into strings
104
+ for entry in sorted_entries:
105
+ printf(f'Device ID: ', Sty.RED, f'{entry["device_id"]}', Sty.MAGENTA, f', Start Time: ', Sty.RED, f'{entry["start_time"].strftime("%Y-%m-%d %H:%M:%S")}', Sty.BLUE, f', End Time: ', Sty.RED, f'{entry["end_time"]}', Sty.BLUE)
106
+
107
+ def my_reservations():
108
+ data = account.get_reservations()
109
+ if 'ace' in data.results:
110
+ print(f"Error: {unmap_arg(data.results['ace'])}")
111
+ return
112
+ entries = []
113
+
114
+ for key, value in data.results.items():
115
+ parts = unmap_arg(value).split(',')
116
+ # Create a dictionary for each entry with named fields
117
+ entry = {
118
+ 'username': parts[0],
119
+ 'device_id': int(parts[1]), # Convert device_id to integer for proper numerical sorting
120
+ 'start_time': datetime.datetime.strptime(parts[2], '%Y-%m-%d %H:%M:%S'), # Convert start_time to datetime
121
+ 'end_time': parts[3]
122
+ }
123
+ entries.append(entry)
124
+
125
+ if (entries == []):
126
+ printf("No reservations found.", Sty.BOLD)
127
+ return
128
+
129
+ printf("Reservations under: ", Sty.BOLD, f'{account.username}', Sty.MAGENTA)
130
+
131
+ # Sort the entries by device_id and then by start_time
132
+ sorted_entries = sorted(entries, key=lambda x: (x['device_id'], x['start_time']))
133
+
134
+ for entry in sorted_entries:
135
+ if account.username == entry['username']:
136
+ printf(f'Device ID: ', Sty.RED, f'{entry["device_id"]}', Sty.MAGENTA, f', Start Time: ', Sty.RED, f'{entry["start_time"].strftime("%Y-%m-%d %H:%M:%S")}', Sty.BLUE, f', End Time: ', Sty.RED, f'{entry["end_time"]}', Sty.BLUE)
137
+
138
+ def cancel_my_reservation():
139
+ ## print all of ur reservations and their ids
140
+ ## ask for id to cancel
141
+ ## remove said reservation
142
+ data = account.get_reservations()
143
+ if 'ace' in data.results:
144
+ print(f"Error: {unmap_arg(data.results['ace'])}")
145
+ return
146
+
147
+ entries:list = []
148
+
149
+ for key, value in data.results.items():
150
+ parts = unmap_arg(value).split(',')
151
+ # Create a dictionary for each entry with named fields
152
+ entry = {
153
+ 'id': -1,
154
+ 'internal_id': key,
155
+ 'username': parts[0],
156
+ 'device_id': int(parts[1]), # Convert device_id to integer for proper numerical sorting
157
+ 'start_time': datetime.datetime.strptime(parts[2], '%Y-%m-%d %H:%M:%S'), # Convert start_time to datetime
158
+ 'end_time': parts[3]
159
+ }
160
+ if account.username == entry['username']:
161
+ entries.append(entry)
162
+
163
+ printf("Current Reservation(s) under ", Sty.BOLD, f'{account.username}:', Sty.MAGENTA)
164
+
165
+ sorted_entries = sorted(entries, key=lambda x: (x['device_id'], x['start_time'])) # sort by device_id and start_time
166
+ for i, entry in enumerate(sorted_entries): # label all reservations with unique id
167
+ entry['id'] = i
168
+ printf(f'Reservation ID: ', Sty.GRAY, f'{i}', Sty.MAGENTA, f' Device ID: ', Sty.GRAY, f'{entry["device_id"]}', Sty.BRIGHT_GREEN, f' Start Time: ', Sty.GRAY, f'{entry["start_time"].strftime("%Y-%m-%d %H:%M:%S")}', Sty.BLUE, f' End Time: ', Sty.GRAY, f'{entry["end_time"]}', Sty.BLUE)
169
+ # print(f"Reservation ID {i}, Device ID: {entry['device_id']}, Start Time: {entry['start_time'].strftime('%Y-%m-%d %H:%M:%S')}, End Time: {entry['end_time']}")
170
+
171
+ if sorted_entries == []:
172
+ printf("No reservations found.", Sty.BOLD)
173
+ return
174
+
175
+ inpu = session.prompt(stylize("Enter the ID of the reservation you would like to cancel ", Sty.BOLD, '(abort with any non number key input)', Sty.RED, ': ', Sty.BOLD))
176
+
177
+ if inpu.isdigit():
178
+ id = int(inpu)
179
+ if id >= len(sorted_entries):
180
+ print("Invalid ID.")
181
+ return
182
+
183
+ # grab the reservation
184
+ for entry in sorted_entries:
185
+ if entry['id'] == id:
186
+ db_id = entry['internal_id']
187
+ if session.prompt(stylize(f'Cancel reservation ID ', Sty.DEFAULT, f'{id}', Sty.MAGENTA, f' Device ID: ', Sty.DEFAULT, f'{entry["device_id"]}', Sty.BRIGHT_GREEN, f' Start Time: ', Sty.GRAY, f'{entry["start_time"].strftime("%Y-%m-%d %H:%M:%S")}', Sty.BLUE, f' End Time: ', Sty.DEFAULT, f'{entry["end_time"]}', Sty.BLUE, f' ? (y/n):', Sty.DEFAULT)) == 'y':
188
+ response = account.cancel_reservation(db_id)
189
+ if 'ace' in response.results:
190
+ print(f"Error: {unmap_arg(response.results['ace'])}")
191
+ elif 'UC' in response.results:
192
+ printf(f"Reservation ID ", Sty.DEFAULT, f'{id}', Sty.BRIGHT_BLUE, ' successfully canceled.', Sty.DEFAULT)
193
+ else:
194
+ print("Aborting. User canceled action.")
195
+ return
196
+
197
+ print(f"Error: No reservation found with ID {id}.")
198
+ else:
199
+ print("Aborting. A non integer key was given.")
200
+
201
+ def devices():
202
+ data = account.get_devices()
203
+ if 'ace' in data.results:
204
+ print(f"Error: {unmap_arg(data.results['ace'])}")
205
+ return
206
+ printf("Devices:", Sty.BOLD)
207
+
208
+ for key in sorted(data.results, key=int):
209
+ printf(f"Device ID:", Sty.DEFAULT, f' {key}', Sty.MAGENTA, f" Device Name: ", Sty.DEFAULT, f"{unmap_arg(data.results[key])}", Sty.GRAY)
210
+
211
+ def get_datetime(question:str):
212
+ timestamp = session.prompt(stylize(f'{question}', Sty.DEFAULT, ' (YYYY-MM-DD HH:MM): ', Sty.GRAY))
213
+ return datetime.datetime.strptime(timestamp + ':00', '%Y-%m-%d %H:%M:%S')
214
+
215
+ def reserve():
216
+ try:
217
+ id = session.prompt(stylize("Enter the device ID you would like to reserve: ", Sty.DEFAULT))
218
+ token = account.reserve_device(int(id), get_datetime("Reserve Start Time"), get_datetime("Reserve End Time"))
219
+ if token != '':
220
+ printf(f"Reservation successful. Thy Token -> ", Sty.BOLD, f"{token}", Sty.BG_GREEN)
221
+ printf(f"Please keep this token safe, as it is not saved on server side, and cannot be regenerated/reretrieved. ", Sty.DEFAULT)
222
+ except Exception as e:
223
+ printf(f"Error: {e}", Sty.BRIGHT_RED)
224
+
225
+ def perms():
226
+ data = account.get_perms()
227
+ if 'ace' in data.results:
228
+ print(f"Error: {unmap_arg(data.results['ace'])}")
229
+ return
230
+
231
+ results = ast.literal_eval(unmap_arg(data.results['UC']))[0]
232
+ printf(f'Permission Level: ', Sty.BOLD, f'{results[0]}', Sty.BLUE)
233
+ if results[0] == 'Normal User':
234
+ print(unmap_arg(data.results['details']))
235
+ elif results[0] == 'Power User':
236
+ printf(f'Max Reservations: ', Sty.DEFAULT, f'{results[3]}', Sty.MAGENTA)
237
+ printf(f'Max Reservation Duration (min): ', Sty.DEFAULT, f'{int(results[4]/60)}', Sty.MAGENTA)
238
+ printf(f'Device IDs allowed Access to: ', Sty.DEFAULT, f'{results[5]}', Sty.MAGENTA)
239
+ elif results[0] == 'Admin':
240
+ printf(f'No restrictions on reservation count or duration.', Sty.DEFAULT)
241
+ else:
242
+ printf(f"Error: Unknown permission level {results[0]}", Sty.BRIGHT_RED)
243
+
244
+ # New block scheduling
245
+
246
+ def fetch_all_reservations():
247
+ data = account.get_reservations()
248
+ if 'ace' in data.results:
249
+ print(f"Error: {unmap_arg(data.results['ace'])}")
250
+ return []
251
+ entries = []
252
+
253
+ for key, value in data.results.items():
254
+ parts = unmap_arg(value).split(',')
255
+ # Convert both start and end times to datetime objects.
256
+ entry = {
257
+ 'username': parts[0],
258
+ 'device_id': int(parts[1]), # Stored as an int
259
+ 'start_time': datetime.datetime.strptime(parts[2], '%Y-%m-%d %H:%M:%S'),
260
+ 'end_time': datetime.datetime.strptime(parts[3], '%Y-%m-%d %H:%M:%S')
261
+ }
262
+ entries.append(entry)
263
+ return entries
264
+
265
+ def fetch_reservations_for_range(start_day: datetime.date, end_day: datetime.date):
266
+ """
267
+ Fetch all reservations (via fetch_all_reservations) and filter those whose start_time date falls between start_day and end_day (inclusive).
268
+ Returns a dictionary keyed by (device_id, day) (device_id as string, day as datetime.date) with a list of reservation tuples.
269
+ """
270
+ all_res = fetch_all_reservations() # This calls the network only once.
271
+ res_dict = {}
272
+ for res in all_res:
273
+ res_day = res['start_time'].date()
274
+ if start_day <= res_day <= end_day:
275
+ key = (str(res['device_id']), res_day)
276
+ res_dict.setdefault(key, []).append((res['start_time'], res['end_time']))
277
+ return res_dict
278
+
279
+ def is_slot_conflicting(slot: tuple, reservations: list):
280
+ """Return True if the slot overlaps with any reservation in the provided list."""
281
+ slot_start, slot_end = slot
282
+ for res_start, res_end in reservations:
283
+ if slot_start < res_end and slot_end > res_start:
284
+ return True
285
+ return False
286
+
287
+ def interactive_reserve_next_days(block_minutes=60):
288
+ """
289
+ Interactive function that:
290
+ 1) Displays a menu of all devices (0-based indexing).
291
+ 2) Prompts the user for which device they want.
292
+ 3) Prompts how many days (starting today) to check for available reservations.
293
+ 4) Prompts for an optional block duration in minutes (default = 60).
294
+ 5) Displays the free time slots (in 'block_minutes' increments) for that device,
295
+ over the indicated number of days, also 0-based indexed.
296
+ 6) Reserves the chosen slot on that device, after confirmation.
297
+ """
298
+ try:
299
+ # --- 1) Fetch and display all devices ---
300
+ data = account.get_devices()
301
+ if 'ace' in data.results:
302
+ print(f"Error: {unmap_arg(data.results['ace'])}")
303
+ return
304
+
305
+ print("Devices:")
306
+ # Sort devices by integer key
307
+ sorted_device_ids = sorted(data.results.keys(), key=int)
308
+
309
+ for idx, dev_id in enumerate(sorted_device_ids):
310
+ dev_name = unmap_arg(data.results[dev_id])
311
+ print(f"{idx}. Device ID: {dev_id} Name: {dev_name}")
312
+
313
+ # --- 2) Prompt user to pick a device by 0-based index ---
314
+ device_selection = input("Which device do you want? (enter the 0-based index) ")
315
+ try:
316
+ device_selection = int(device_selection)
317
+ if device_selection < 0 or device_selection >= len(sorted_device_ids):
318
+ print("Invalid selection.")
319
+ return
320
+ except ValueError:
321
+ print("Invalid input. Please enter a number.")
322
+ return
323
+
324
+ chosen_device_id = sorted_device_ids[device_selection]
325
+
326
+ # --- 3) Prompt user for the number of days ---
327
+ num_days = int(input("Enter the number of days to check for available reservations (starting today): "))
328
+
329
+ # --- 4) Optionally override block_minutes ---
330
+ # user_block_input = input(f"Enter block duration in minutes (e.g. 15, 30, 60, 120). Press Enter to default ({block_minutes}): ").strip()
331
+ # if user_block_input:
332
+ # try:
333
+ # block_minutes = int(user_block_input)
334
+ # except ValueError:
335
+ # print("Invalid block duration. Using default of 60 minutes.")
336
+ # block_minutes = 60
337
+
338
+ # --- 5) Find all free time slots for the chosen device over the next `num_days` days ---
339
+
340
+ today = datetime.date.today()
341
+ end_day = today + datetime.timedelta(days=num_days - 1)
342
+
343
+ # We only need one call to fetch reservations for the range:
344
+ reservations_range = fetch_reservations_for_range(today, end_day)
345
+
346
+ # We'll keep a list of (day, (slot_start, slot_end)) for which the device is free
347
+ available_slots = []
348
+
349
+ now = datetime.datetime.now()
350
+
351
+ # Helper to build time slots of length 'block_minutes' starting at 00:00 up to 24:00
352
+ def build_time_slots(date: datetime.date, block_size: int):
353
+ slots = []
354
+ start_of_day = datetime.datetime.combine(date, datetime.time(0, 0))
355
+ minutes_in_day = 24 * 60 # 1440
356
+ current_offset = 0
357
+ while current_offset < minutes_in_day:
358
+ slot_start = start_of_day + datetime.timedelta(minutes=current_offset)
359
+ slot_end = slot_start + datetime.timedelta(minutes=block_size)
360
+ # Stop if slot_end bleeds into the next calendar day
361
+ if slot_end.date() != date:
362
+ break
363
+ slots.append((slot_start, slot_end))
364
+ current_offset += block_size
365
+ return slots
366
+
367
+ # Build free slots for each day in [today, end_day]
368
+ for i in range(num_days):
369
+ day = today + datetime.timedelta(days=i)
370
+ all_slots = build_time_slots(day, block_minutes)
371
+
372
+ # The reservations for the chosen device on this day:
373
+ key = (str(chosen_device_id), day)
374
+ day_reservations = reservations_range.get(key, [])
375
+
376
+ for slot in all_slots:
377
+ slot_start, slot_end = slot
378
+ # Skip if it's for "today" and the slot ends in the past
379
+ if day == today and slot_end <= now:
380
+ continue
381
+
382
+ # Check for conflict
383
+ if not is_slot_conflicting(slot, day_reservations):
384
+ available_slots.append((day, slot))
385
+
386
+ if not available_slots:
387
+ print(f"No available time slots for device {chosen_device_id} in the next {num_days} days.")
388
+ return
389
+
390
+ # Sort by day, then by slot start time
391
+ available_slots.sort(key=lambda x: (x[0], x[1][0]))
392
+
393
+ # --- Display the available slots, using 0-based index ---
394
+ print(f"\nAvailable time slots for device {chosen_device_id} over the next {num_days} days:")
395
+ last_day = None
396
+ for idx, (day, slot) in enumerate(available_slots):
397
+ slot_start_str = slot[0].strftime('%I:%M %p')
398
+ slot_end_str = slot[1].strftime('%I:%M %p')
399
+ if day != last_day:
400
+ # Print a header for the day
401
+ day_header = f"{day.strftime('%Y-%m-%d')} ({day.strftime('%a')}) {day.strftime('%b')}. {day.day}"
402
+ print("\n" + day_header)
403
+ last_day = day
404
+
405
+ print(f" {idx}. {slot_start_str} - {slot_end_str}")
406
+
407
+ # Prompt user to pick a slot by 0-based index
408
+ selection = input("Select a slot by index: ")
409
+ try:
410
+ selection = int(selection)
411
+ if selection < 0 or selection >= len(available_slots):
412
+ print("Invalid selection.")
413
+ return
414
+ except ValueError:
415
+ print("Invalid input. Please enter a number.")
416
+ return
417
+
418
+ chosen_day, chosen_slot = available_slots[selection]
419
+ slot_start_str = chosen_slot[0].strftime('%I:%M %p')
420
+ slot_end_str = chosen_slot[1].strftime('%I:%M %p')
421
+
422
+ confirmation = input(
423
+ f"You have selected a reservation on {chosen_day.strftime('%Y-%m-%d')} "
424
+ f"from {slot_start_str} to {slot_end_str} on device {chosen_device_id}. "
425
+ f"Confirm reservation? (y/n): "
426
+ ).strip().lower()
427
+
428
+ if confirmation != 'y':
429
+ print("Reservation cancelled.")
430
+ return
431
+
432
+ # print(f"device_id : {chosen_device_id}, start_time : {chosen_slot[0]}, end_time : {chosen_slot[1]}")
433
+
434
+ # --- 6) Reserve the chosen slot on the chosen device ---
435
+ token = account.reserve_device(int(chosen_device_id), chosen_slot[0], chosen_slot[1])
436
+ if token:
437
+ print(f"Reservation successful on device {chosen_device_id} for "
438
+ f"{chosen_day.strftime('%Y-%m-%d')} {slot_start_str}-{slot_end_str}.")
439
+ print(f"Thy Token -> {token}")
440
+ print("Please keep this token safe, as it is not saved on server side "
441
+ "and cannot be retrieved again.")
442
+
443
+ except Exception as e:
444
+ print(f"Error: {e}")
445
+
446
+ welcome()
447
+ clear()
448
+
449
+ while True:
450
+ try:
451
+ inpu = session.prompt(stylize(f'{account.username}@remote_rf: ', Sty.BLUE))
452
+ if inpu == "clear":
453
+ clear()
454
+ elif inpu == "getdev":
455
+ devices()
456
+ elif inpu == "help" or inpu == "h":
457
+ commands()
458
+ elif inpu == "perms":
459
+ perms()
460
+ elif inpu == "quit" or inpu == "exit":
461
+ break
462
+ elif inpu == "getres":
463
+ reservations()
464
+ elif inpu == "myres":
465
+ my_reservations()
466
+ # elif inpu == "resdev s":
467
+ # interactive_reserve_all()
468
+ elif inpu == "resdev":
469
+ interactive_reserve_next_days(block_minutes=30) # 30 minutes FOR NOW (change if need be)
470
+ elif inpu == 'cancelres':
471
+ cancel_my_reservation()
472
+ elif inpu == 'resdev -n':
473
+ # check if user is admin
474
+ # if account.get_perms().results['UC'] == 'Admin':
475
+ reserve()
476
+ else:
477
+ print(f"Unknown command: {inpu}")
478
+ except KeyboardInterrupt:
479
+ break
480
+ except EOFError:
481
+ break
File without changes
@@ -0,0 +1,32 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIFmzCCA4OgAwIBAgIURcP62Zj3L/2bVIIdFu+UcAMklBQwDQYJKoZIhvcNAQEL
3
+ BQAwXTELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVN0YXRlMQ0wCwYDVQQHDARDaXR5
4
+ MRUwEwYDVQQKDAxDb21wYW55IE5hbWUxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNv
5
+ bTAeFw0yNDA2MjcyMDQ3MTNaFw0yNTA2MjcyMDQ3MTNaMF0xCzAJBgNVBAYTAlVT
6
+ MQ4wDAYDVQQIDAVTdGF0ZTENMAsGA1UEBwwEQ2l0eTEVMBMGA1UECgwMQ29tcGFu
7
+ eSBOYW1lMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEB
8
+ AQUAA4ICDwAwggIKAoICAQCc92USDLn60Ju8+/fIMMsgIRD71cfuO2R0nD0+Tfe7
9
+ QOvnGpY7xSmtFbzjXadqjjqM8JsADyOJzudYf+KhfbfMcX6WYj1Flx3XVrjws5Nf
10
+ XPSYYT/uo+vBKJl7rFCYdrGFPVTI8oBz9EsdURriXOGn+rhUP4vIcx/0SKYQvWgI
11
+ oJ8huQ1A7bgrfl2qhyjYa+4AhMAF+YtWSI4fsSR3hwb2wR2Xb8zenVvaTAoc0GvY
12
+ TgxQ5Xue2UD/qR/wezGDQozPIsLXAYiK7fIvHxq1rzhAOOIGEtyp2uMAoq7NtYfu
13
+ 5ZgRcoD/O6pAPKZKdpC6toGu3kqj2W7bAWAeZzMOCa3DxYCa+r+dW96fhGhA5HLc
14
+ 4rwZDVa3hK1d8n0NmkkX2LUdFT5KXuB6InyeXKK/ZKNEAnxSn3cdaqKZWr9Bxbsz
15
+ G9osCNOzN8IQGILTGdQlGirraCQM+P0SvVFj8C22Mo5tuBG1eal1vFvO9LMwl2GP
16
+ SnZ4QB8BXpwAVEpOWe72lLRE99+5GhZvWQAi4RQ+0Mn2xwyJY8gkrK5i5m8kHKzs
17
+ naIfpRrtZ9oo821WTisVYQq5U7QUbPaiE4xEOMEDTiOSatvxQMqu6OGDWLxlqcgv
18
+ Fh317R+H6dhn+hLTGe6wnCozPTHqZoqv664gTs7KFHUgI/gU/dBc3oI/VEyrmuTI
19
+ GwIDAQABo1MwUTAdBgNVHQ4EFgQU/iskMPrT7yToKDJudHOUHRhnRG0wHwYDVR0j
20
+ BBgwFoAU/iskMPrT7yToKDJudHOUHRhnRG0wDwYDVR0TAQH/BAUwAwEB/zANBgkq
21
+ hkiG9w0BAQsFAAOCAgEAJpU4vErO68CduIzqr925gmKzUeSOqoXCLJGvlbUl3HWa
22
+ ieba6oL33UjB/6s5BUHjqTtUiYa1hHoPsI6S9HC7cCaykdWzrtPOrXpF/G4clT8H
23
+ 3xkk7lQNwYH0+OP3ITbrY0OiqsTBjVY0ltKOOqzrzRMHcAw6Jc1Zp/7tYv9ZzqYx
24
+ NiwDYlGO8rhyGa2k1zNazJbh7YT0hBKPYkhqF/jheMFBwT3cpw6rJomP3rcSUaK2
25
+ 0DP+v4taW7xxfxf8vI2Xdhy9XLdqyVNq0btFxy2cAOj19zSjnHvPlwXSjuRPht0W
26
+ 4ZV7moOQYNAGG2376j/LFD5tojkJLWEsiOAd5ve/6FovkPiDfVnPpvTCsidnvqA3
27
+ nNvTV5UJOBYzM1zI8xfDRa5Mg2ggQR75fvXjTo2Jo/FDx+PN70brXJM/1zuH0Znh
28
+ z7Y03uS8cbkLiXgtp/8x9KIRASG/WFMMNtG/YmPcufCGhHlAELI6iKLdcQ5+8dHk
29
+ pmDiRWixBnkyNXu152TZBLvGUHtOAzw3aTZsir+CCdlNeNNqEW1FV21WAsYzDT2M
30
+ TsCr/azaguNozPlapt+nORWMyMR1jr7zcE2XBfmMZzLzf5t7V8RC2UoeSy09fFjT
31
+ vA6swXwe32eKYfeNJSvjiajlqXhZUrQJFBCHhOBgKQxFvU4OzVpPy8q7yszRCtg=
32
+ -----END CERTIFICATE-----
@@ -0,0 +1,52 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ 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
51
+ dnNqQyFgF4k8C3gXyqzTr+Zlc4xaFQ==
52
+ -----END PRIVATE KEY-----
@@ -0,0 +1,19 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDFDCCAfygAwIBAgIUaORvuL3d7VVDuewDxgBibhqrWqkwDQYJKoZIhvcNAQEL
3
+ BQAwETEPMA0GA1UEAwwGdW51c2VkMB4XDTI0MDYyNzIxMDU1OVoXDTI1MDYyNzIx
4
+ MDU1OVowETEPMA0GA1UEAwwGdW51c2VkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
5
+ MIIBCgKCAQEAlT1YZUyg3YZXzHxP6/dS7vmH/unpODa5vSFTnKnOF+lR1GSCok4j
6
+ ItBS9LeUjFcCxAlDBXU+ICQZVGi65udELi00wdewMF/uQb/6dyAb6TVVZUf/LGrM
7
+ rgg4kGfZhSP8IoB+n5qMGIwsypi3Ta1SAKL8xDypSxqqfbC2jeYTJy/3OwNMMs2C
8
+ vqWshdgIHn+hgY0Ge2zkx4GLi6P4ubmSfog6Nxk/2OrCUKmfXn359WawKEzfrXaY
9
+ UOzW9HmfGfF40u66i1TpACNc/BDR4eYaRZEizPLDWdrpz7JWyHBxEojclwvbLfT5
10
+ fSza69x2XGSP39sb3L10dZA0TKe2+j8qJQIDAQABo2QwYjAdBgNVHQ4EFgQUUlVE
11
+ SRlVWR+2IYH8JwBmyy5ntP4wHwYDVR0jBBgwFoAUUlVESRlVWR+2IYH8JwBmyy5n
12
+ tP4wDwYDVR0TAQH/BAUwAwEB/zAPBgNVHREECDAGhwTAqAFrMA0GCSqGSIb3DQEB
13
+ CwUAA4IBAQAvTM1MsqhQo47SNWgn2coGyHHrKFmK7XnFgw9raN9EKJJA67dfv+rj
14
+ ttl+SXuxRFlkQjP8VbHkopyiiL8qNUjW4N4Un4RSEvHZG5oJtQ83a6pwjW3cud1J
15
+ O8+whCU0QCxsXIapNDvsZyaE9rnH+Quq5lyOxrxqGgpEtJG1dTU81Cgpk25ODH1n
16
+ JNxC9vm4bbOBjJdB3YcAJ/K6iIepyP//owN9U2IiIsmpxpdvJi1P/Lp4zD3EHhzF
17
+ MmTwJBCxjOkN66VFjecLXeLlYvs8Xx45BZav+3D3H45XUvafn2cqR2pcmdMOkZAC
18
+ JHTjecrfKzWmnSTxxiY7qWWvxJPUp5KC
19
+ -----END CERTIFICATE-----
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCVPVhlTKDdhlfM
3
+ fE/r91Lu+Yf+6ek4Nrm9IVOcqc4X6VHUZIKiTiMi0FL0t5SMVwLECUMFdT4gJBlU
4
+ aLrm50QuLTTB17AwX+5Bv/p3IBvpNVVlR/8sasyuCDiQZ9mFI/wigH6fmowYjCzK
5
+ mLdNrVIAovzEPKlLGqp9sLaN5hMnL/c7A0wyzYK+payF2Agef6GBjQZ7bOTHgYuL
6
+ o/i5uZJ+iDo3GT/Y6sJQqZ9effn1ZrAoTN+tdphQ7Nb0eZ8Z8XjS7rqLVOkAI1z8
7
+ ENHh5hpFkSLM8sNZ2unPslbIcHESiNyXC9st9Pl9LNrr3HZcZI/f2xvcvXR1kDRM
8
+ p7b6PyolAgMBAAECggEAIkNWhVFJuHpEs42R0siySWvQIYIF+ZI04/tgBR6GEr7O
9
+ Ou9Ff6plTjOabBUuvWanm6bNtJXViM8I4rR1vpf3cwuNaniQupZ3rrA6+nkMd2b3
10
+ f1x/dOzjJ4x7Igo5qiPYGfq6t31lrygVi4DyypphcoR4+Du+GWBapqc4zky1doAm
11
+ iXYU08/Q4hToP1VJGNo9chMuOcSrJeiA0RgYlnkCfbL591PGf7VuQzS+PcbcnbiA
12
+ ODOFdBez39+Dlo4nZosIlgLgFPSX/M57zP6WgRcVkLqL75rECqtcs/52dJ73uxMu
13
+ a5GukSY5z5A4r0hCGOZDDqpW2B+IRfAqzSL/ViS7gQKBgQDN0o7GgOsLBqeoj27W
14
+ xOzT1dX39AkFsvdI8f47B1blYFd3egN5y0nLWLEbK/LcpanrCX+nkRz/M51DNGKa
15
+ 1lvMDDwt/99wSKUJFhO1SvuA6SB1DlPgLNRqXZu2cwzpZs1xJU6oVyK70ih3uWmW
16
+ lmi109pDlOkBPSHkIUx5GNXQpQKBgQC5n28/R3VV0L4zzWokewWbHtXVp87owXlh
17
+ 6typ/Stz98kkMNmQNkkQyQ3SxeBNXMkItLA9yYw2MDhDm6ZdyP+ZUdTv+FwMjg5M
18
+ 1FEty94LUAscDbu4QSADR0cfNQH/oPavPMWoFj/eTGnRVY76uKAzgkIPZP112Gqg
19
+ IYaPcs87gQKBgQCtzFrbrAjNqrTwVQ3XNTp2Nl8TnXHw6gp+AjoXRj9OOWgib1l4
20
+ Av0xRJdoxlexkgJFgiPVL2g45zCoixeof9HMH5jBjwryGaWiYo4JzGNLm4/YyFxz
21
+ M+e6WYkfK09/11sra8FbzRh7WR7q2hobGq8YuufXoWqPrTttE+ErcJk8MQKBgCTq
22
+ qothQNrCWzGeRt/ef6zsIwcNCr+LywJIXX6JVV0JCL3j4UEnKrzl35PtusBoFatf
23
+ lDWVogcc6/O2Pw4j7YGmnrzjHht5HSr2hvaetxh04ODBcnYgrac5Q9HXDwCyGJ2d
24
+ booRcr5ZYCo74+XFVkcoPs8k/Ku1UO9r+4EICmMBAoGAdFXHggoQu7fz0maZoH1o
25
+ TgFVhD8p4McuN+L0ddOWvS7l+0Lz/9J2KKmHRElfpMvJsSoXGp7Anyymwqukw8zq
26
+ iD/ZqGavuzcRWPWO6W514asHU1AxLSYGFqNuCYag/jElcWhgQyHojPMypaDM2Xfv
27
+ rgkCz2uZ2Zg2/GJ65CtboCA=
28
+ -----END PRIVATE KEY-----
@@ -0,0 +1,19 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDJDCCAgygAwIBAgIUTLqudWuu46JkqxA1UOVcHkhZz0swDQYJKoZIhvcNAQEL
3
+ BQAwGTEXMBUGA1UEAwwOMTY0LjY3LjE5NS4yMDcwHhcNMjQxMDI1MjAzNTAzWhcN
4
+ MjUxMDI1MjAzNTAzWjAZMRcwFQYDVQQDDA4xNjQuNjcuMTk1LjIwNzCCASIwDQYJ
5
+ KoZIhvcNAQEBBQADggEPADCCAQoCggEBALCAm+cnf98MpcPLB9n6NEYoDU7ye/74
6
+ iEenNiFV440qKQ2y0fV9qZ5+AeaUpFbrZPyClOBQhJxg1SrZnhQkBJD2GOiX0vxh
7
+ LqugFCCgfoCJEyX/oJXogGcNPlcrkN5ATFfD7n/9MIvdcpSisF34/jQvqjZXzkd2
8
+ 1KpqHH+bwxCUCoe2YENIVpEs3gbojaPsgbsJECHy3CsG9pS7/FNPGnoI6UdXrXSl
9
+ RIQToERlyk0UgKsGWwj+FGdJavOlU/um7Q1C/oxNeCaZPGSQzJOrCiPt/HGimCAn
10
+ 2BMOro2X9KfKnT4cUMIZzeSvjdTx6IgrpjSN+XdzeFpcoUZRMpxtdPECAwEAAaNk
11
+ MGIwHQYDVR0OBBYEFIVpaHQqtgoiCyJQpsUZqAXEvTuUMB8GA1UdIwQYMBaAFIVp
12
+ aHQqtgoiCyJQpsUZqAXEvTuUMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0RBAgwBocE
13
+ pEPDzzANBgkqhkiG9w0BAQsFAAOCAQEAEUiXzwMbEry2ptVu/Q9FV8hmhbpgveve
14
+ Hh5PniP3UQfxlRZnZ4UEN14FHIV7d9o9FUedGmnC95hnURHd5YlLE3JTNTN5lyqp
15
+ zWySGS1oGsTog6ctl7Psey6Detgxj5B8lA+z3Tp7Ud2sANejFhoYNrzkFrbyLLnW
16
+ 1BjPJlMZBBW2+yVd8zQPXAfAQwdqeuBns9XSDuY5MvRaJd8yfXjP1SksBBaanqCN
17
+ 9Fj/LXtjZrTu1FqZ7I0rUp/obR+avoeu/qHx6TkZ741SDhJ1wGJzW/+21yDdQe7P
18
+ kf4iOINrN3FaQv35oo2fgINgWoZYRrEsKkRbEZvUX2/yAg2le1WkKA==
19
+ -----END CERTIFICATE-----
@@ -0,0 +1,28 @@
1
+ -----BEGIN PRIVATE KEY-----
2
+ MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCwgJvnJ3/fDKXD
3
+ ywfZ+jRGKA1O8nv++IhHpzYhVeONKikNstH1famefgHmlKRW62T8gpTgUIScYNUq
4
+ 2Z4UJASQ9hjol9L8YS6roBQgoH6AiRMl/6CV6IBnDT5XK5DeQExXw+5//TCL3XKU
5
+ orBd+P40L6o2V85HdtSqahx/m8MQlAqHtmBDSFaRLN4G6I2j7IG7CRAh8twrBvaU
6
+ u/xTTxp6COlHV610pUSEE6BEZcpNFICrBlsI/hRnSWrzpVP7pu0NQv6MTXgmmTxk
7
+ kMyTqwoj7fxxopggJ9gTDq6Nl/Snyp0+HFDCGc3kr43U8eiIK6Y0jfl3c3haXKFG
8
+ UTKcbXTxAgMBAAECggEAHlas9am7eBqTb7k5a0VvsNN3nideGvCbdD2Qt2AtEfm6
9
+ PsmK/3iPLFgaeYj5SpuBq0nCz1/nu32Fhq0LWAjs5AH5PBnEwW7u9783Vnhf5jYp
10
+ nXF4J+xkDdKf8Znid+Fzfe6G02cw7gmthVEFodGH2G6NAnRLV8tcOMKujVy3xeRz
11
+ XVqL9ttbllCboYQQ5yZH9+wahAV0YT5FogttvKhd3jiPRAZ5sITxq+ibnLx3upqc
12
+ Tzz4VSCymuoX5Aq010bjvrA9yWcFeP4lHru4ArTZS9zsZ9BgCoT2MxBv9qmg/fwv
13
+ /SZ+/WvHWj0dhSonh5TWv2be0JWWMZu6cWKoFAs68QKBgQDc9dmZZagY+y93frCj
14
+ 38MjVfFUtUbauXW2Q83EiMjOPU3UAH7igE564OPAM5YRTtbzT7qohwokHS6FrXgB
15
+ NEdes6qQfaCvaqnG75ylpRKKL1abWSBjb28jNYvSJdvM7z38+XjLNRXeoiDFju5g
16
+ 4nU7Yru4aXRlwvTCmLh6VSD9JQKBgQDMfe8zJHQHpMG/edcYE0858F/IsXZAVM4c
17
+ vnEwRGAEOvLRLbf2FkyC8UmQ0JxaXRCxyeSl5JRuMjpImmfvOEdI9OZvVolbuIM3
18
+ QrY7SL//CqcNuQWm6OvGy3+QrrFHEVsEdMKEB7bbDo0+Eyl87U+8sXge7wkTp7OW
19
+ 10uOm3F83QKBgHF5zROLcoXJ0jnDFYJDc1rdU0AWjNndbwd40N8DBGVudF7RFljK
20
+ XgObJTvbAlHHNHrmUk0kdN/RIMhEKyIrMBABozHrYq9Tzvc8rS0glmHjJ85GOmz2
21
+ mJPzdugoyzX3E9WsZQ2vKJkamEv9OI0HH/+smA2AEugD9GFPv0YMHBIFAoGAOxws
22
+ CJyA7bSyTKbrhgoO3LCe/2RMyku5SJXEIi+hkZd4mP6eLoRDmZYlrbafe39rU/kI
23
+ Huvz++aI8nOvl3atJGmmMojRK7IqO88M3hYpaY+qukzBVX3+qXgpZ6kXlXNu29rk
24
+ X0XblXafXVIsq+/tHJ4wGsD93rCbOP8C2DYWmAECgYEAn5KaWkAJCH1GGurJD/jU
25
+ w/M1eU4tMRecI/9E2J38PuANfcQ972Jl252ZK/1aR/rysFlrdkZSzDfEuiQFphhu
26
+ BmOqFELKbsst+ijc/jTR8KQLHqr4nFk0PCE8HwrLc2LBN45kr3LdqwmehobU80+s
27
+ nvDLTTO6AjP462kETu05Nrk=
28
+ -----END PRIVATE KEY-----