diff --git a/admin.py b/admin.py index 897b588..45d383a 100644 --- a/admin.py +++ b/admin.py @@ -12,17 +12,37 @@ import json bp = Blueprint("admin", url_prefix="/manage/admin") -def credentialsCheck (request, order:Order): +def credentialsCheck(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!") + if EXTRA_PRINTS: + print(f"Checking admin credentials of {order.code} with secret {order.secret}") if not order.isAdmin() : raise exceptions.Forbidden("Birichino :)") + + @bp.get('/cache/clear') async def clearCache(request, order:Order): credentialsCheck(request, order) await request.app.ctx.om.fill_cache() return redirect(f'/manage/admin') +@bp.get('/loginas/') +async def loginAs(request, code, order:Order): + credentialsCheck(request, order) + dOrder = await getOrderByCode(request, code, throwException=True) + if(dOrder.isAdmin()): + raise exceptions.Forbidden("You can't login as another admin!") + + if EXTRA_PRINTS: + print(f"Swapping login: {order.secret} {order.code} -> {dOrder.secret} {code}") + r = redirect(f'/manage/welcome') + r.cookies['foxo_code_ORG'] = order.code + r.cookies['foxo_secret_ORG'] = order.secret + r.cookies['foxo_code'] = code + r.cookies['foxo_secret'] = dOrder.secret + return r + @bp.get('/room/unconfirm/') async def unconfirmRoom(request, code, order:Order): credentialsCheck(request, order) diff --git a/app.py b/app.py index 2633634..5a1c833 100644 --- a/app.py +++ b/app.py @@ -49,7 +49,7 @@ async def clear_session(request, exception): async def main_start(*_): print(">>>>>> main_start <<<<<<") - app.config.REQUEST_MAX_SIZE = 1024 * 1024 * 5 # 5 MB + app.config.REQUEST_MAX_SIZE = PROPIC_MAX_FILE_SIZE * 3 app.ctx.om = OrderManager() if FILL_CACHE: @@ -167,13 +167,25 @@ async def admin(request, order: Order): await request.app.ctx.om.updateCache() if not order: raise exceptions.Forbidden("You have been logged out. Please access the link in your E-Mail to login again!") + if EXTRA_PRINTS: + print(f"Checking admin credentials of {order.code} with secret {order.secret}") if not order.isAdmin(): raise exceptions.Forbidden("Birichino :)") tpl = app.ctx.tpl.get_template('admin.html') return html(tpl.render(order=order)) @app.route("/manage/logout") async def logour(request): + orgCode = request.cookies.get("foxo_code_ORG") + orgSecret = request.cookies.get("foxo_secret_ORG") + if orgCode != None and orgSecret != None: + r = redirect(f'/manage/welcome') + r.cookies['foxo_code'] = orgCode + r.cookies['foxo_secret'] = orgSecret + r.delete_cookie("foxo_code_ORG") + r.delete_cookie("foxo_secret_ORG") + return r + raise exceptions.Forbidden("You have been logged out.") if __name__ == "__main__": - app.run(host="0.0.0.0", port=8188, dev=DEV_MODE) + app.run(host="0.0.0.0", port=8188, dev=DEV_MODE, access_log=ACCESS_LOG) diff --git a/config.example.py b/config.example.py index 77cece6..d2b3985 100644 --- a/config.example.py +++ b/config.example.py @@ -16,6 +16,8 @@ FILL_CACHE = True CACHE_EXPIRE_TIME = 60 * 60 * 4 DEV_MODE = True +ACCESS_LOG = True +EXTRA_PRINTS = True # Metadata property for item-id mapping METADATA_NAME = "item_name" diff --git a/ext.py b/ext.py index cdf335f..7a48a31 100644 --- a/ext.py +++ b/ext.py @@ -15,7 +15,8 @@ class Order: self.time = time() self.data = data self.status = {'n': 'pending', 'p': 'paid', 'e': 'expired', 'c': 'canceled'}[self.data['status']] - + self.secret = data['secret'] + if not len(self.data['positions']): self.status = 'canceled' @@ -119,7 +120,7 @@ class Order: self.pending_room = self.ans('pending_room') self.pending_roommates = self.ans('pending_roommates').split(',') if self.ans('pending_roommates') else [] self.room_members = self.ans('room_members').split(',') if self.ans('room_members') else [] - self.room_owner = (self.code == self.room_id) + self.room_owner = (self.code is not None and self.room_id is not None and self.code.strip() == self.room_id.strip()) self.room_secret = self.ans('room_secret') self.app_token = self.ans('app_token') self.nfc_id = self.ans('nfc_id') diff --git a/logOrders.py b/logOrders.py new file mode 100644 index 0000000..9d2b607 --- /dev/null +++ b/logOrders.py @@ -0,0 +1,78 @@ +from config import * +import requests +import datetime +import time + +ROOM_CAPACITY_MAP = { + 0: 0, + # SACRO CUORE + 83: 11, + 67: 50, + 68: 45, + 69: 84, + 70: 10, + + # OVERFLOW 1 + 75: 50 +} + +def ans(data, name): + for p in data['positions']: + for a in p['answers']: + if a.get('question_identifier', None) == name: + if a['answer'] in ['True', 'False']: + return bool(a['answer'] == 'True') + return a['answer'] + return None + +def getOrders(): + ret = [] + p = 0 + + while 1: + p += 1 + res = requests.get(f"{base_url_event}orders/?page={p}", headers=headers) + + if res.status_code == 404: break + + data = res.json() + for o in data['results']: + + roomType = 0 + + for pos in o['positions']: + if pos['item'] == ITEMS_ID_MAP['bed_in_room']: + roomType = pos['variation'] + + ret.append({"code": o['code'], "fname": ans(o, 'fursona_name'), "rType": roomType, "date": o['datetime']}) + return ret + +ordersCode = set() +ordersTime = set() +ordersFName = set() +while True: + #try: + newOrders = getOrders() + shouldSleep = True + for o in newOrders: + if o['code'] not in ordersCode and not o['date'] in ordersTime and not o['fname'] in ordersFName: + + remainingInRoomType = ROOM_CAPACITY_MAP[o['rType']] + remainingInRoomType -= 1 + ROOM_CAPACITY_MAP[o['rType']] = remainingInRoomType + + roomCapacitiesStr = ", ".join(str(x).rjust(2, "0") for x in ROOM_CAPACITY_MAP.values()) + #dateStr = datetime.datetime.now().isoformat() + + print(f"[{o['date']}] {len(ordersCode)} - [{o['code']}] New order! FursonaName: {o['fname'].ljust(24)} - Room capacities: {roomCapacitiesStr}") + + shouldSleep = False + time.sleep(0.05) + ordersCode.add(o['code']) + ordersTime.add(o['date']) + ordersFName.add(o['fname']) + #except: + # print("Exception occurred!") + # pass + if shouldSleep: + time.sleep(1) diff --git a/propic.py b/propic.py index c900976..91adee7 100644 --- a/propic.py +++ b/propic.py @@ -12,14 +12,21 @@ bp = Blueprint("propic", url_prefix="/manage/propic") async def resetDefaultPropic(request, order: Order, isFursuiter, sendAnswer=True): s = "_fursuiter" if isFursuiter else "" - if (DEV_MODE): + if (EXTRA_PRINTS): print("Resetting {fn} picture for {orderCod}".format(fn="Badge" if not isFursuiter else "fursuit", orderCod = order.code)) with open("res/propic/default.png", "rb") as f: data = f.read() f.close() - os.remove(f"res/propic/{order.ans(f'propic{s}')}") # converted file - filenameNoExt = order.ans(f'propic{s}').split(".jpg")[0] - os.remove(f"res/propic/{filenameNoExt}_original.jpg") # original file + + convertedFilename = order.ans(f'propic{s}') + if convertedFilename is not None: + convertedFilename = f"res/propic/{convertedFilename}" + if os.path.exists(convertedFilename): + os.remove(convertedFilename) # converted file + originalFilename = f"res/propic/propic{s}_{order.code}_original" + if os.path.exists(originalFilename): + os.remove(originalFilename) # original file + await order.edit_answer_fileUpload(f'propic{s}_file', f'propic{s}_file_{order.code}_default.png', 'image/png', data) if(sendAnswer): await order.send_answers() @@ -35,11 +42,11 @@ async def upload_propic(request, order: Order): raise exceptions.BadRequest("The deadline has passed. You cannot modify the badges at this moment.") if request.form.get('submit') == 'Delete main image': - await order.edit_answer('propic', None) await resetDefaultPropic(request, order, False, sendAnswer=False) + await order.edit_answer('propic', None) #This MUST come after the reset default propic! elif request.form.get('submit') == 'Delete fursuit image': - await order.edit_answer('propic_fursuiter', None) await resetDefaultPropic(request, order, True, sendAnswer=False) + await order.edit_answer('propic_fursuiter', None) #This MUST come after the reset default propic! else: for fn, body in request.files.items(): if fn not in ['propic', 'propic_fursuiter']: @@ -48,13 +55,18 @@ async def upload_propic(request, order: Order): if not body[0].body: continue # Check max file size + if EXTRA_PRINTS: + print(f"Image {fn} weight: {len(body[0].body)} bytes") if len(body[0].body) > PROPIC_MAX_FILE_SIZE: raise exceptions.BadRequest("File size too large for " + ("Profile picture" if fn == 'propic' else 'Fursuit picture')) - h = sha224(body[0].body).hexdigest()[:32] errorDetails = '' + bodyBytesBuff = None + imgBytesBuff = None + img = None try: - img = Image.open(BytesIO(body[0].body)) + bodyBytesBuff = BytesIO(body[0].body) + img = Image.open(bodyBytesBuff) width, height = img.size # Checking for min / max size if width < PROPIC_MIN_SIZE[0] or height < PROPIC_MIN_SIZE[1]: @@ -66,7 +78,7 @@ async def upload_propic(request, order: Order): raise exceptions.BadRequest(errorDetails) - with open(f"res/propic/{fn}_{order.code}_original.jpg", "wb") as f: + with open(f"res/propic/{fn}_{order.code}_original", "wb") as f: f.write(body[0].body) aspect_ratio = width/height @@ -81,19 +93,28 @@ async def upload_propic(request, order: Order): width, height = img.size img.thumbnail((512,512)) - imgBytes = BytesIO() - img.save(imgBytes, format='jpeg') - imgBytes = imgBytes.getvalue() - with open(f"res/propic/{fn}_{order.code}_{h}.jpg", "wb") as f: + imgBytesBuff = BytesIO() + img.save(imgBytesBuff, format='jpeg') + imgBytes = imgBytesBuff.getvalue() + with open(f"res/propic/{fn}_{order.code}.jpg", "wb") as f: f.write(imgBytes) - await order.edit_answer_fileUpload(f'{fn}_file', f'{fn}_file_{order.code}_{h}.jpg', 'image/jpeg', imgBytes) + await order.edit_answer_fileUpload(f'{fn}_file', f'{fn}_file_{order.code}.jpg', 'image/jpeg', imgBytes) except Exception: import traceback - if DEV_MODE: print(traceback.format_exc()) + if EXTRA_PRINTS: print(traceback.format_exc()) raise exceptions.BadRequest(errorDetails if errorDetails else "The image you uploaded is not valid.") else: - await order.edit_answer(fn, f"{fn}_{order.code}_{h}.jpg") + await order.edit_answer(fn, f"{fn}_{order.code}.jpg") + + if img is not None: + img.close() + if bodyBytesBuff is not None: + bodyBytesBuff.flush() + bodyBytesBuff.close() + if imgBytesBuff is not None: + imgBytesBuff.flush() + imgBytesBuff.close() await order.send_answers() return redirect("/manage/welcome#badge") diff --git a/res/scripts/roomManager.js b/res/scripts/roomManager.js index 0995ae9..29537bf 100644 --- a/res/scripts/roomManager.js +++ b/res/scripts/roomManager.js @@ -7,7 +7,8 @@ function confirmAction (intent, sender) { let intentFormAction = document.querySelector("#intentFormAction") let intentSend = document.querySelector("#intentSend") // Resetting ui - intentEdit.setAttribute('required', false) + intentEdit.removeAttribute('required') + intentEdit.removeAttribute('minlength') intentFormAction.setAttribute('method', 'GET') intentEditPanel.style.display = 'none'; @@ -17,6 +18,7 @@ function confirmAction (intent, sender) { case 'rename': intentEditPanel.style.display = 'block'; intentEdit.setAttribute('required', true) + intentEdit.setAttribute('minlength', 4) intentFormAction.setAttribute('method', 'POST') document.getElementById("intentRename").value = sender.parentElement.parentElement.querySelector("span").innerText; break diff --git a/res/styles/propic.css b/res/styles/propic.css index 57e8168..917cd3f 100644 --- a/res/styles/propic.css +++ b/res/styles/propic.css @@ -58,12 +58,12 @@ svg.propic-border-filter { .propic-border.propic-animated-super .propic-border-animation { background: linear-gradient(90deg, #FA5E00 20%, #FAAA00 40%, #FB8C00 60%, #FA3200 80%, #FAC800 100%); - animation: border-animation 1s linear 0ms infinite; + animation: border-animation 2.5s linear 0ms infinite; } .propic-border.propic-animated-normal .propic-border-animation { background: linear-gradient(90deg, #6124AB 20%, #AB248F 40%, #8E24AA 60%, #3524AB 80%, #AB243E 100%); - animation: border-animation 1s linear 0ms infinite; + animation: border-animation 2.5s linear 0ms infinite; } @keyframes border-animation { diff --git a/res/styles/room.css b/res/styles/room.css index 700af6c..6460419 100644 --- a/res/styles/room.css +++ b/res/styles/room.css @@ -11,4 +11,10 @@ span.nsc-room-counter { div.room-actions a>span { display: none; } +} + +#room a[role=button] { + display: inline-flex; + justify-content: space-around; + align-items: center; } \ No newline at end of file diff --git a/room.py b/room.py index 4f0f118..0f23116 100644 --- a/room.py +++ b/room.py @@ -49,7 +49,7 @@ async def delete_room(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!") - if order.room_owner: + if not order.room_owner: raise exceptions.BadRequest("You are not allowed to delete room of others.") if order.ans('room_confirmed'): diff --git a/tpl/base.html b/tpl/base.html index 3dfc06c..075818c 100644 --- a/tpl/base.html +++ b/tpl/base.html @@ -51,6 +51,11 @@ .tag {background:var(--primary);color:var(--contrast);font-size:0.8em;font-weight:600;padding:0.1em 0.3em;border-radius:3px;} + .grid_2x2 { + grid-template-columns: repeat(2, 1fr); + grid-template-rows: repeat(2, 1fr); + } + .rainbow-text { background-image: repeating-linear-gradient(90deg, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff, #ff0000, #ffff00, #00ff00, #00ffff, #0000ff, #ff00ff); text-align: center; @@ -119,7 +124,7 @@ }); diff --git a/tpl/blocks/badge.html b/tpl/blocks/badge.html index c553a99..91baf5b 100644 --- a/tpl/blocks/badge.html +++ b/tpl/blocks/badge.html @@ -42,16 +42,10 @@

{% endif %} -
- {% if order.ans('propic') %} - PROPIC_DEADLINE else ''}} /> - {% endif %} - {% if order.ans('propic_fursuiter') %} - PROPIC_DEADLINE else ''}} /> - {% endif %} - {% if not order.ans('propic') or (order.is_fursuiter and not order.ans('propic_fursuiter')) %} - - {% endif %} +
+ + PROPIC_DEADLINE or not order.ans('propic')) else ''}} /> + PROPIC_DEADLINE or not order.ans('propic_fursuiter')) else ''}} />
diff --git a/tpl/blocks/propic.html b/tpl/blocks/propic.html index cd78b0f..3f5a48e 100644 --- a/tpl/blocks/propic.html +++ b/tpl/blocks/propic.html @@ -8,7 +8,7 @@
{% endif %} Your own profile picture - + {% if flag %} flag {% endif %} diff --git a/tpl/blocks/room.html b/tpl/blocks/room.html index fa95b56..dbf1c80 100644 --- a/tpl/blocks/room.html +++ b/tpl/blocks/room.html @@ -75,19 +75,15 @@ {% endif %} {% endif %} -

+

{% if order.room_owner %} {% if not order.room_confirmed %} - - {% if len(room_members) == 1 %} - Delete room - {% endif %} - {# 0 %}href="javascript:document.getElementById('modal-roomconfirm').setAttribute('open', 'true');"{% endif %}>Confirm {{[None,'single','double','triple','quadruple','quintuple'][len(room_members)]}} room #} - Confirm {{[None,'single','double','triple','quadruple','quintuple'][order.room_person_no]}} room - - Rename room {{[None,'single','double','triple','quadruple','quintuple'][order.room_person_no]}} room + + Rename room + 1) else ''}} >Delete room + Confirm {{[None,'single','double','triple','quadruple','quintuple'][order.room_person_no]}} room {% endif %} {% else %} {% if order.room_id and not order.room_confirmed %} diff --git a/tpl/nosecount.html b/tpl/nosecount.html index ff91a1b..019ccfb 100644 --- a/tpl/nosecount.html +++ b/tpl/nosecount.html @@ -114,7 +114,7 @@

- +