diff --git a/admin.py b/admin.py index cc8d3aa..315316e 100644 --- a/admin.py +++ b/admin.py @@ -62,13 +62,14 @@ async def unconfirm_room(request, code, order:Order): return redirect(f'/manage/nosecount') @bp.get('/room/autoconfirm') -async def autoconfirm_room(request, code, order:Order): +async def autoconfirm_room(request, order:Order): await clear_cache(request, order) orders = request.app.ctx.om.cache.values() for order in orders: if(order.code == order.room_id and not order.room_confirmed and len(order.room_members) == order.room_person_no): logger.info(f"Auto-Confirming room {order.room_id}") await confirm_room_by_order(order, request) + await clear_cache(request, order) return redirect(f'/manage/admin') @bp.get('/room/delete/') @@ -111,12 +112,12 @@ async def room_wizard(request, order:Order): await clear_cache(request, order) #Separate orders which have incomplete rooms and which have no rooms - all_orders = {key:value for key,value in sorted(request.app.ctx.om.cache.items(), key=lambda x: len(x[1].room_members), reverse=True) if value.status not in ['c', 'e'] and not value.daily} + all_orders = {key:value for key,value in sorted(request.app.ctx.om.cache.items(), key=lambda x: (x[1].room_person_no, len(x[1].room_members)), reverse=True) if (value.status not in ['canceled', 'expired'] and not value.daily and value.bed_in_room != ITEM_VARIATIONS_MAP["bed_in_room"]["bed_in_room_no_room"])} orders = {key:value for key,value in sorted(all_orders.items(), key=lambda x: x[1].ans('fursona_name')) if not value.room_confirmed} # Orders with incomplete rooms incomplete_orders = {key:value for key,value in orders.items() if value.code == value.room_id and (value.room_person_no - len(value.room_members)) > 0} # Roomless furs - roomless_orders = {key:value for key,value in orders.items() if not value.room_id and not value.daily} + roomless_orders = {key:value for key,value in orders.items() if(not value.room_id and not value.daily and value.bed_in_room != ITEM_VARIATIONS_MAP["bed_in_room"]["bed_in_room_no_room"])} # Result map result_map = {} @@ -124,10 +125,13 @@ async def room_wizard(request, order:Order): # Check overflows room_quota_overflow = {} for key, value in ITEM_VARIATIONS_MAP['bed_in_room'].items(): - room_quota = get_quota(ITEMS_ID_MAP['bed_in_room'], value) - capacity = ROOM_CAPACITY_MAP[key] if key in ROOM_CAPACITY_MAP else 1 - current_quota = len(list(filter(lambda y: y.bed_in_room == value and y.room_owner == True, orders.values()))) - room_quota_overflow[value] = current_quota - int(room_quota.size / capacity) if room_quota else 0 + if key != "bed_in_room_no_room": + room_quota = get_quota(ITEMS_ID_MAP['bed_in_room'], value) + capacity = ROOM_CAPACITY_MAP[key] if key in ROOM_CAPACITY_MAP else 1 + current_quota = len(list(filter(lambda y: y.bed_in_room == value and y.room_owner == True, all_orders.values()))) + room_quota_overflow[value] = current_quota - int(room_quota.size / capacity) if room_quota else 0 + if DEV_MODE and EXTRA_PRINTS: + print(f"There are {current_quota} of room type {key} out of a total of ({room_quota.size} / {capacity})") # Init rooms to remove result_map["void"] = [] @@ -135,6 +139,7 @@ async def room_wizard(request, order:Order): # Remove rooms that are over quota for room_type, overflow_qty in {key:value for key,value in room_quota_overflow.items() if value > 0}.items(): sorted_rooms = sorted(incomplete_orders.values(), key=lambda r: len(r.room_members)) + sorted_rooms = [r for r in sorted_rooms if r.bed_in_room == room_type] for room_to_remove in sorted_rooms[:overflow_qty]: # Room codes to remove result_map["void"].append(room_to_remove.code) @@ -147,8 +152,10 @@ async def room_wizard(request, order:Order): for room_order in incomplete_orders.items(): room = room_order[1] to_add = [] - missing_slots = room.room_person_no - len(room.room_members) - for i in range(missing_slots): + count = room.room_person_no + alreadyPresent = len(room.room_members) + missing_slots = count - alreadyPresent + for _ in range(missing_slots): compatible_roomates = {key:value for key,value in roomless_orders.items() if value.bed_in_room == room.bed_in_room} if len(compatible_roomates.items()) == 0: break # Try picking a roomate that's from the same country and room type @@ -165,7 +172,9 @@ async def room_wizard(request, order:Order): del roomless_orders[code_to_add] result_map[room.code] = { 'type': 'add_existing', - 'to_add': to_add + 'to_add': to_add, + 'count': count, + 'previouslyPresent': alreadyPresent } generated_counter = 0 @@ -173,8 +182,10 @@ async def room_wizard(request, order:Order): while len(roomless_orders.items()) > 0: room = list(roomless_orders.items())[0][1] to_add = [] - missing_slots = room.room_person_no - len(room.room_members) - for i in range(missing_slots): + count = room.room_person_no + alreadyPresent = len(room.room_members) + missing_slots = count - alreadyPresent + for _ in range(missing_slots): compatible_roomates = {key:value for key,value in roomless_orders.items() if value.bed_in_room == room.bed_in_room} if len(compatible_roomates.items()) == 0: break # Try picking a roomate that's from the same country and room type @@ -194,17 +205,20 @@ async def room_wizard(request, order:Order): 'type': 'new', 'room_name': f'Generated Room {generated_counter}', 'room_type': room.bed_in_room, - 'to_add': to_add + 'to_add': to_add, + 'count': count, + 'previouslyPresent': alreadyPresent } result_map["infinite"] = { 'to_add': [] } + result_map = {k: v for k, v in sorted(result_map.items(), key=lambda x: ((x[1]["count"], x[1]["previouslyPresent"]) if("count" in x[1] and "previouslyPresent" in x[1]) else (4316, 0) ))} tpl = request.app.ctx.tpl.get_template('wizard.html') return html(tpl.render(order=order, all_orders=all_orders, unconfirmed_orders=orders, data=result_map, jsondata=json.dumps(result_map, skipkeys=True, ensure_ascii=False))) @bp.post('/room/wizard/submit') async def submit_from_room_wizard(request:Request, order:Order): '''Will apply changes to the rooms''' - await request.app.ctx.om.fill_cache() + await clear_cache(request, order) data = json.loads(request.body) @@ -253,7 +267,7 @@ async def submit_from_room_wizard(request:Request, order:Order): pending_member = await request.app.ctx.om.get_order(code=new_member_code) # Preconditions if pending_member.daily == True: raise exceptions.BadRequest(f"Order {pending_member.code} is daily.") - if pending_member.status != 'paid': raise exceptions.BadRequest(f"Order {new_member_code} hasn't paid.") + #if pending_member.status != 'paid': raise exceptions.BadRequest(f"Order {new_member_code} hasn't paid.") # Since we don't confirm rooms anymore, we don't need to check if they're paid or not if pending_member.bed_in_room != room_order.bed_in_room: raise exceptions.BadRequest(f"Order {new_member_code} has a different room type than {room_code}.") if pending_member.room_owner: exceptions.BadRequest(f"Order {new_member_code} is already a room owner.") if pending_member.room_id and pending_member.room_id not in data['void']: exceptions.BadRequest(f"Order {new_member_code} is in another room.") @@ -270,10 +284,10 @@ async def submit_from_room_wizard(request:Request, order:Order): else: raise exceptions.BadRequest(f"Unexpected type ({value['type']})") await room_order.edit_answer('pending_room', None) await room_order.edit_answer('pending_roommates', None) - await room_order.edit_answer('room_confirmed', "True") + # await room_order.edit_answer('room_confirmed', "True") Use the autoconfirm button in the admin panel await room_order.edit_answer('room_members', ','.join(list(set([*room_order.room_members, room_order.code, *value['to_add']])))) await room_order.send_answers() - await request.app.ctx.om.fill_cache() + await clear_cache(request, order) return text('done', status=200) diff --git a/api.py b/api.py index d14f5a5..c6e197a 100644 --- a/api.py +++ b/api.py @@ -34,7 +34,8 @@ async def api_members(request): 'propic_fursuiter': o.ans('propic_fursuiter'), 'staff_role': o.ans('staff_role'), 'country': o.country, - 'is_checked_in': False, + 'room_id': o.room_id, + 'is_checked_in': o.checked_in, 'points': random.randint(0,50) if random.random() > 0.3 else 0 }) @@ -112,6 +113,10 @@ async def token_test(request): return response.json({'ok': False, 'error': 'The token you have provided is not correct.'}, status=401) return response.json({'ok': True, 'message': 'This token is valid :)'}) + +@bp.get("/ping") +async def ping(request): + return response.text("pong") @bp.get("/welcome") async def welcome_app(request): @@ -139,15 +144,18 @@ async def welcome_app(request): 'propic_fursuiter': o.ans('propic_fursuiter'), 'staff_role': o.ans('staff_role'), 'country': o.country, - 'is_checked_in': False, + 'is_checked_in': o.checked_in, 'points': random.randint(0,50) if random.random() > 0.3 else 0, 'can_scan_nfc': o.can_scan_nfc, + 'room_id': o.room_id, + #'mail': o.email, 'actual_room_id': o.actual_room, **ret }) @bp.get("/scan/") async def nfc_scan(request, nfc_id): + return response.text("Nope") if not request.token: return response.json({'ok': False, 'error': 'You need to provide a token.'}, status=401) @@ -174,11 +182,12 @@ async def nfc_scan(request, nfc_id): 'propic_fursuiter': o.ans('propic_fursuiter'), 'staff_role': o.ans('staff_role'), 'country': o.country, - 'is_checked_in': False, + 'is_checked_in': o.checked_in, 'points': random.randint(0,50) if random.random() > 0.3 else 0, 'comment': o.comment, 'actual_room_id': o.actual_room, 'phone': o.phone, + 'room_id': o.room_id, 'telegram_username': o.telegram_username, 'roommates': {x: (await request.app.ctx.om.get_order(code=x, cached=True)).name for x in room_owner.room_members if x != o.code} }) diff --git a/app.py b/app.py index 065116e..4b52b1c 100644 --- a/app.py +++ b/app.py @@ -16,10 +16,12 @@ import requests import sys from sanic.log import logger, logging, access_logger from metrics import * +from utils import isSessionAdmin from email_util import killSmptClient import pretixClient import traceback + app = Sanic(__name__) app.static("/res", "res/") @@ -80,6 +82,7 @@ async def main_start(*_): app.ctx.tpl = Environment(loader=FileSystemLoader("tpl"), autoescape=True) app.ctx.tpl.globals.update(time=time) app.ctx.tpl.globals.update(PROPIC_DEADLINE=PROPIC_DEADLINE) + app.ctx.tpl.globals.update(ROOM_DEADLINE=ROOM_DEADLINE) app.ctx.tpl.globals.update(LOCALES=LOCALES) app.ctx.tpl.globals.update(ITEMS_ID_MAP=ITEMS_ID_MAP) app.ctx.tpl.globals.update(ITEM_VARIATIONS_MAP=ITEM_VARIATIONS_MAP) @@ -98,11 +101,6 @@ async def gen_barcode(request, code): return raw(img.getvalue(), content_type="image/png") -@app.route("/manage/lol") -async def lol(request: Request): - await get_quotas(request) - return text('hi') - @app.route(f"/{ORGANIZER}/{EVENT_NAME}/order///open/") async def redirect_explore(request, code, secret, order: Order, secret2=None): @@ -161,7 +159,7 @@ async def welcome(request, order: Order, quota: Quotas): room_members.append(await app.ctx.om.get_order(code=member_id, cached=True)) tpl = app.ctx.tpl.get_template('welcome.html') - return html(tpl.render(order=order, quota=quota, room_members=room_members, pending_roommates=pending_roommates, ROOM_ERROR_MESSAGES=ROOM_ERROR_TYPES)) + return html(tpl.render(order=order, quota=quota, room_members=room_members, pending_roommates=pending_roommates, ROOM_ERROR_MESSAGES=ROOM_ERROR_TYPES, isSessionAdmin=await isSessionAdmin(request, order))) @app.route("/manage/download_ticket") diff --git a/config.example.py b/config.example.py index acde031..5cf1f4e 100644 --- a/config.example.py +++ b/config.example.py @@ -17,6 +17,8 @@ PROPIC_MAX_FILE_SIZE = 5 * 1024 * 1024 # 5MB PROPIC_MAX_SIZE = (2048, 2048) # (Width, Height) PROPIC_MIN_SIZE = (125, 125) # (Width, Height) +ROOM_DEADLINE = 9999999999 + # This is used for feedback sending inside of the app. Feedbacks will be sent to the specified chat using the bot api id. TG_BOT_API = '123456789:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' TG_CHAT_ID = -1234567 diff --git a/email_util.py b/email_util.py index 3ba60fb..bf68a96 100644 --- a/email_util.py +++ b/email_util.py @@ -15,30 +15,44 @@ def killSmptClient(): global sslLock global sslTimer global smptSender + logger.info(f"[SMPT] killSmptClient: Lock status: {sslLock.locked()}") sslTimer.cancel() sslLock.acquire() + exp = None if(smptSender is not None): logger.debug('[SMPT] Closing smpt client') - smptSender.quit() # it calls close() inside + try: + smptSender.quit() # it calls close() inside + except Exception as e: + exp = e smptSender = None sslLock.release() + if(exp != None): + raise exp async def openSmptClient(): global sslLock global sslTimer global sslContext global smptSender + logger.info(f"[SMPT] openSmptClient: Lock status: {sslLock.locked()}") sslTimer.cancel() sslLock.acquire() - if(smptSender is None): - logger.debug('[SMPT] Opening smpt client') - client : smtplib.SMTP = smtplib.SMTP(SMTP_HOST, SMTP_PORT) - client.starttls(context=sslContext) - client.login(SMTP_USER, SMTP_PASSWORD) - smptSender = client + exp = None + try: + if(smptSender is None): + logger.debug('[SMPT] Opening smpt client') + client : smtplib.SMTP = smtplib.SMTP(SMTP_HOST, SMTP_PORT) + client.starttls(context=sslContext) + client.login(SMTP_USER, SMTP_PASSWORD) + smptSender = client + except Exception as e: + exp = e sslLock.release() sslTimer = createTimer() sslTimer.start() + if(exp != None): + raise exp def createTimer(): return Timer(SMPT_CLIENT_CLOSE_TIMEOUT, killSmptClient) @@ -51,9 +65,16 @@ async def sendEmail(message : MIMEMultipart): message['From'] = f'{EMAIL_SENDER_NAME} <{EMAIL_SENDER_MAIL}>' await openSmptClient() logger.debug(f"[SMPT] Sending mail {message['From']} -> {message['to']} '{message['Subject']}'") + logger.info(f"[SMPT] sendEmail: Lock status: {sslLock.locked()}") + exp = None sslLock.acquire() - smptSender.sendmail(message['From'], message['to'], message.as_string()) + try: + smptSender.sendmail(message['From'], message['to'], message.as_string()) + except Exception as e: + exp = e sslLock.release() + if(exp != None): + raise exp def render_email_template(title = "", body = ""): tpl = Environment(loader=FileSystemLoader("tpl"), autoescape=False).get_template('email/comunication.html') diff --git a/ext.py b/ext.py index 7d0a35c..2664e44 100644 --- a/ext.py +++ b/ext.py @@ -282,9 +282,12 @@ class Quota: return f'Quota [items={self.items}, variations={self.variations}] [{self.available_number}/{self.size}]' def get_quota(item: int, variation: int = None) -> Quota: + ret : Quota = None for q in QUOTA_LIST: - if (q.has_item(item, variation)): return q - return None + if (q.has_item(item, variation)): + if(ret == None or (q.size != None and q.size < ret.size)): + ret = q + return ret @dataclass class Quotas: @@ -364,9 +367,24 @@ class OrderManager: del cache[code] orderList.remove(code) + async def fill_cache(self, check_itemsQuestions=False) -> bool: # Check cache lock + logger.info(f"[CACHE] Lock status: {self.updating.locked()}") self.updating.acquire() + ret = False + exp = None + try: + ret = await self.fill_cache_INTERNAL(check_itemsQuestions=check_itemsQuestions) + except Exception as e: + exp = e + self.updating.release() + logger.info(f"[CACHE] Ret status: {ret}. Exp: {exp}") + if(exp != None): + raise exp + return ret + + async def fill_cache_INTERNAL(self, check_itemsQuestions=False) -> bool: start_time = time() logger.info("[CACHE] Filling cache...") # Index item's ids @@ -409,8 +427,6 @@ class OrderManager: except Exception: logger.error(f"[CACHE] Error while refreshing cache.\n{traceback.format_exc()}") success = False - finally: - self.updating.release() # Apply new cache if there were no errors if(success): diff --git a/karaoke.py b/karaoke.py index cf92500..be701cf 100644 --- a/karaoke.py +++ b/karaoke.py @@ -3,6 +3,7 @@ from sanic import Blueprint, exceptions, response from ext import * from urllib.parse import unquote from config import ADMINS +from utils import isSessionAdmin import json bp = Blueprint("karaoke", url_prefix="/manage/karaoke") @@ -10,7 +11,7 @@ bp = Blueprint("karaoke", url_prefix="/manage/karaoke") @bp.get("/admin") async def show_songs(request, order: Order): - if not order.isAdmin(): + if not await isSessionAdmin(request, order): raise exceptions.Forbidden("Birichino") orders = [x for x in request.app.ctx.om.cache.values() if x.karaoke_songs] @@ -28,7 +29,7 @@ async def show_songs(request, order: Order): @bp.post("/approve") async def approve_songs(request, order: Order): - if not order.isAdmin(): + if not await isSessionAdmin(request, order): raise exceptions.Forbidden("Birichino") for song in request.form: @@ -44,7 +45,7 @@ async def sing_song(request, order: Order, songname): if not order: raise exceptions.Forbidden("You have been logged out. Please access the link in your E-Mail to login again!") - if not order.isAdmin(): + if not await isSessionAdmin(request, order): raise exceptions.Forbidden("Birichino") songname = unquote(songname) diff --git a/propic.py b/propic.py index 3c4138a..d052054 100644 --- a/propic.py +++ b/propic.py @@ -6,6 +6,7 @@ from PIL import Image from io import BytesIO from hashlib import sha224 from time import time +from utils import isSessionAdmin import os bp = Blueprint("propic", url_prefix="/manage/propic") @@ -38,7 +39,7 @@ async def upload_propic(request, order: Order): if order.propic_locked: raise exceptions.BadRequest("You have been limited from further editing the propic.") - if request.form.get('submit') != 'Upload' and time() > PROPIC_DEADLINE: + if request.form.get('submit') != 'Upload' and (time() > PROPIC_DEADLINE and not await isSessionAdmin(request, order)): raise exceptions.BadRequest("The deadline has passed. You cannot modify the badges at this moment.") if request.form.get('submit') == 'Delete main image': diff --git a/room.py b/room.py index a0f41c2..2fa7024 100644 --- a/room.py +++ b/room.py @@ -6,9 +6,18 @@ from config import headers import os from image_util import generate_room_preview, get_room from utils import confirm_room_by_order +from time import time bp = Blueprint("room", url_prefix="/manage/room") +@bp.middleware +async def deadline_check(request: Request): + order = await get_order(request) + if not order: + raise exceptions.Forbidden("You have been logged out. Please access the link in your E-Mail to login again!") + if time() > ROOM_DEADLINE and not await isSessionAdmin(request, order): + raise exceptions.BadRequest("The deadline has passed. You cannot modify the room at this moment.") + @bp.post("/create") async def room_create_post(request, order: Order): if not order: raise exceptions.Forbidden("You have been logged out. Please access the link in your E-Mail to login again!") @@ -304,7 +313,7 @@ async def confirm_room(request, order: Order, quotas: Quotas): #if quotas.get_left(len(order.room_members)) == 0: # raise exceptions.BadRequest("There are no more rooms of this size to reserve.") - confirm_room_by_order(order, request) + await confirm_room_by_order(order, request) return redirect('/manage/welcome') diff --git a/stuff/runBackup.py b/stuff/runBackup.py index 740a1b3..ca515e0 100644 --- a/stuff/runBackup.py +++ b/stuff/runBackup.py @@ -1,21 +1,28 @@ #!/usr/bin/python -from os import listdir, remove +from os import listdir, remove, getenv from os.path import isfile, join import datetime import subprocess PRETIX_BACKUP = False WEBINT_BACKUP = False +WP_BACKUP = False +STUFF_BACKUP = False BACKUP_DIR_PRETIX = "/home/pretix/backups/" BACKUP_DIR_WEBINT = "/home/webint/backups/" +BACKUP_DIR_WP = "/home/worcopio/backups/" +BACKUP_DIR_STUFF = "/root/backups/" -MAX_FILE_NO = 14 +MAX_FILE_NO = 7 COMMAND_PRETIX_POSTGRES = "pg_dump -F p pretix | gzip > %s" # Restore with psql -f %s -COMMAND_PRETIX_DATA = "tar -cf %s /var/pretix-data" # Restore with tar -xvf %s. To make .secret readable I used setfacl -m u:pretix:r /var/pretix-data/.secret -COMMAND_WEBINT = "tar -cf %s /home/webint/furizon_webint" # Restore with tar -xvf %s +COMMAND_PRETIX_DATA = "tar -czf %s /var/pretix-data" # Restore with tar -xvf %s. To make .secret readable I used setfacl -m u:pretix:r /var/pretix-data/.secret +COMMAND_WEBINT = "tar -czf %s /home/webint/furizon_webint" # Restore with tar -xvf %s +COMMAND_WP_MYSQL = "mysqldump -h 127.0.0.1 -P 5688 -u root --password=__PASSWORD__ --all-databases | gzip > %s" # Restore with zcat %s | mysql -h 127.0.0.1 -P 5688 -u root +COMMAND_WP_DATA = "tar -czf %s /var/lib/docker/volumes/worcopio-docker_wordpress/_data" # Restore with tar -xvf %s +COMMAND_STUFF = "tar -czf %s /etc/ /var/backups/ /var/log/ /var/mail/ /var/pretix-data/ /var/prometheus-data/ /var/spool/ /var/www/ /var/lib/grafana/ /var/lib/redis/" # Restore with tar -xvf %s def deleteOlder(path : str, prefix : str, postfix : str): @@ -41,4 +48,19 @@ if(PRETIX_BACKUP): runBackup("pretix_data", "backup.tar.gz", join(BACKUP_DIR_PRETIX, "data"), COMMAND_PRETIX_DATA) if(WEBINT_BACKUP): - runBackup("webint_full", "backup.tar.gz", BACKUP_DIR_WEBINT, COMMAND_WEBINT) \ No newline at end of file + runBackup("webint_full", "backup.tar.gz", BACKUP_DIR_WEBINT, COMMAND_WEBINT) + +if(WP_BACKUP): + mysqlCmd = COMMAND_WP_MYSQL + mysqlPwd = getenv("MYSQL_PWD") + if(mysqlPwd != None and mysqlPwd.strip() != ""): + mysqlPwd = mysqlPwd.strip() + print(f"Running with password `{mysqlPwd}`") + mysqlCmd = mysqlCmd.replace("__PASSWORD__", mysqlPwd) + runBackup("wp_mysql", "backup.sql.gz", join(BACKUP_DIR_WP, "mysql"), mysqlCmd) + else: + print("Backup run without the $MYSQL_PWD env var set. Skipping wp_mysql backup") + runBackup("wp_wp", "backup.tar.gz", join(BACKUP_DIR_WP, "wp"), COMMAND_WP_DATA) + +if(STUFF_BACKUP): + runBackup("stuff", "backup.tar.gz", BACKUP_DIR_STUFF, COMMAND_STUFF) diff --git a/stuff/testAsyncio.py b/stuff/testAsyncio.py new file mode 100644 index 0000000..01e0ec9 --- /dev/null +++ b/stuff/testAsyncio.py @@ -0,0 +1,11 @@ +# python merda +import asyncio + +async def a(): + print("a") + +def b(): + loop = asyncio.get_event_loop() + print(loop) + +b() \ No newline at end of file diff --git a/tpl/blocks/badge.html b/tpl/blocks/badge.html index a123d87..ceb6c6e 100644 --- a/tpl/blocks/badge.html +++ b/tpl/blocks/badge.html @@ -32,7 +32,7 @@ {% endif %} - {% if time() > PROPIC_DEADLINE %} + {% if time() > PROPIC_DEADLINE and not isSessionAdmin %}

⚠️ The deadline to upload pictures for the badge has expired. For last-minute changes, please contact the support over at info@furizon.net. If your badge has been printed already, changing it will incur in a 2€ fee. You can also get extra badges at the reception for the same price. If you upload a propic now, it might not be printed on time.

{% else %}

@@ -43,9 +43,9 @@ {% endif %}

- - PROPIC_DEADLINE or not order.ans('propic')) else ''}} /> - PROPIC_DEADLINE or not order.ans('propic_fursuiter')) else ''}} /> + PROPIC_DEADLINE and not isSessionAdmin) else ''}} /> + PROPIC_DEADLINE and not isSessionAdmin) or not order.ans('propic')) else ''}} /> + PROPIC_DEADLINE and not isSessionAdmin) or not order.ans('propic_fursuiter')) else ''}} />
diff --git a/tpl/blocks/room.html b/tpl/blocks/room.html index 4fca1dd..5f6fbe4 100644 --- a/tpl/blocks/room.html +++ b/tpl/blocks/room.html @@ -8,17 +8,24 @@

Check here for any fur who share your room type.

{% endif %} - {# Show alert if room owner has wrong people inside #} + {% if time() > ROOM_DEADLINE %} +

⚠️ The deadline to edit your room has passed. If your room is not full it will be subject to changes by the staff as we optimize for hotel capacity.

- {# {% if room_members and quota.get_left(len(room_members)) == 0 and (not order.room_confirmed) %} #} - {#

⚠️ Your room contains {{len(room_members)}} people inside, but sadly there are no more {{[None,'single','double','triple','quadruple','quintuple'][len(room_members)]}} rooms. You need to add or remove people until you reach the size of an available room if you want to confirm it.

#} - {# {% endif %} #} + {% else %} - {# Show alert if room was not confirmed #} - {% if order.room_id and not order.room_confirmed %} -

⚠️ Your room hasn't been confirmed yet. Unconfirmed rooms are subject to changes by the staff as we optimize for hotel capacity.

+ {# Show alert if room owner has wrong people inside #} + + {# {% if room_members and quota.get_left(len(room_members)) == 0 and (not order.room_confirmed) %} #} + {#

⚠️ Your room contains {{len(room_members)}} people inside, but sadly there are no more {{[None,'single','double','triple','quadruple','quintuple'][len(room_members)]}} rooms. You need to add or remove people until you reach the size of an available room if you want to confirm it.

#} + {# {% endif %} #} + + {# Show alert if room was not confirmed #} + {% if order.room_id and not order.room_confirmed %} +

⚠️ Your room hasn't been confirmed yet. Unconfirmed rooms are subject to changes by the staff as we optimize for hotel capacity.

+ {% endif %} + {% endif %} - + {# Show notice if the room is confirmed #} {% if order.room_confirmed %} {#

✅ Your {{[None,'single','double','triple','quadruple','quintuple'][len(room_members)]}} room has been confirmed

#} @@ -40,7 +47,7 @@ {% if person.status == 'pending' %}

UNPAID

{% endif %} - {% if order.room_owner and person.code != order.code and (not order.room_confirmed) %}KICK{% endif %} + {% if order.room_owner and person.code != order.code and (not order.room_confirmed) and (time() <= ROOM_DEADLINE or isSessionAdmin) %}KICK{% endif %} {% if person.status != 'paid' %} @@ -51,7 +58,7 @@ {# {% if order.room_id == order.code and not order.room_confirmed and len(room_members) < 5%} #} {% if order.room_id == order.code and not order.room_confirmed and len(room_members) < order.room_person_no %}
- +

Invite

@@ -63,13 +70,13 @@
{% elif order.pending_room %}

You have have asked to join the room of another member. Wait for them to confirm or reject your request.

-
Cancel pending join request + ROOM_DEADLINE and not isSessionAdmin else ''}}>Cancel pending join request {% else %}

🎲 If you don't join a room or create your one within the room deadline, we will randomly put you into a room with free spots.

To join a room, ask somebody to send you their room code.

- Create a room - Join a room + ROOM_DEADLINE and not isSessionAdmin else ''}}>Create a room + ROOM_DEADLINE and not isSessionAdmin else ''}}>Join a room

{% endif %} @@ -83,17 +90,17 @@ {% if order.room_owner %} {% if not order.room_confirmed %} - {# 0 %}href="javascript:document.getElementById('modal-roomconfirm').setAttribute('open', 'true');"{% endif %}>Confirm {{[None,'single','double','triple','quadruple','quintuple'][len(room_members)]}} room #} + {# ROOM_DEADLINE and not isSessionAdmin else ''}} {% if not room.forbidden and quota.get_left(len(room_members)) > 0 %}href="javascript:document.getElementById('modal-roomconfirm').setAttribute('open', 'true');"{% endif %}>Confirm {{[None,'single','double','triple','quadruple','quintuple'][len(room_members)]}} room #} - Rename room - 1) else ''}} >Delete room - Confirm {{[None,'single','double','triple','quadruple','quintuple'][order.room_person_no]}} room + ROOM_DEADLINE and not isSessionAdmin else ''}}>Rename room + 1) or (time() > ROOM_DEADLINE and not isSessionAdmin) else ''}} >Delete room + ROOM_DEADLINE and not isSessionAdmin else ''}} {% if not room.forbidden and len(room_members) == order.room_person_no %}href="javascript:document.getElementById('modal-roomconfirm').setAttribute('open', 'true');"{% endif %}>Confirm {{[None,'single','double','triple','quadruple','quintuple'][order.room_person_no]}} room {% else %} - {# Share #} + {# ROOM_DEADLINE and not isSessionAdmin else ''}} href="javascript:navigator.share({title: 'Furizon room', text:'Viewing room {{order.room_name}}', url: `${window.location.protocol}//${window.location.host}/manage/room/view/{{order.code}}}`});">Share #} {% endif %} {% else %} {% if order.room_id and not order.room_confirmed %} - Leave room + ROOM_DEADLINE and not isSessionAdmin else ''}}>Leave room {% endif %} {% endif %}

@@ -111,8 +118,8 @@ UNPAID {% endif %} {% if order.room_owner %} - Approve - Reject + ROOM_DEADLINE and not isSessionAdmin else ''}}>Approve + ROOM_DEADLINE and not isSessionAdmin else ''}}>Reject {% endif %}
diff --git a/tpl/wizard.html b/tpl/wizard.html index 9cef6cb..e4a4844 100644 --- a/tpl/wizard.html +++ b/tpl/wizard.html @@ -24,7 +24,7 @@ {%with room_order = unconfirmed_orders[room[0]] %}

- {{room_order.room_name if room_order.room_name else room[1]['room_name'] if room[1] and room[1]['room_name'] else ''}} + {{room_order.room_name if room_order.room_name else room[1]['room_name'] if room[1] and room[1]['room_name'] else ''}} - {{room_order.room_person_no}} People max

{% for m in room_order.room_members %} diff --git a/utils.py b/utils.py index e599fa7..ef1a609 100644 --- a/utils.py +++ b/utils.py @@ -287,6 +287,19 @@ async def validate_rooms(request, rooms, om): logger.info(f"[ROOM VALIDATION] Sent {sent_count} emails") +# Returns true if the logged used is an admin OR if it's an admin logged as another user +async def isSessionAdmin(request, order): + if(order.isAdmin()): return True + + orgCode = request.cookies.get("foxo_code_ORG") + orgSecret = request.cookies.get("foxo_secret_ORG") + if orgCode != None and orgSecret != None: + + user = await request.app.ctx.om.get_order(code=orgCode) + if(user == None): return False + if(user.secret != orgSecret): raise exceptions.Forbidden("Birichino :)") + return user.isAdmin() + async def check_room(request, order, om=None): room_errors = [] room_members = []