Skip to content

Commit de1bc10

Browse files
committed
added validation on server
1 parent ffed8f5 commit de1bc10

File tree

5 files changed

+79
-22
lines changed

5 files changed

+79
-22
lines changed

config.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import re
12
from pathlib import Path
23

34
# custom colours
@@ -24,7 +25,19 @@
2425
"milk": "#4BB3FF",
2526
}
2627

27-
# custom icons
28-
icons = [
28+
# custom icons from static/icons directory
29+
custom_icons = [
2930
f.stem for f in Path("static/icons").iterdir() if f.is_file() and f.suffix == ".svg"
3031
]
32+
33+
# phosphor icons from static/icons/phosphor-bold.css
34+
phosphor_icons = sorted(
35+
set(
36+
re.findall(
37+
r"\.ph-([a-z0-9-]+)::before",
38+
Path("static/icons/phosphor-bold.css").read_text(),
39+
)
40+
)
41+
)
42+
43+
icons = sorted(custom_icons + phosphor_icons)

events/api.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from flask import Blueprint, Response, jsonify, request
22

33
from auth.auth import valid_api_auth
4+
from config import colours, icons
45
from events.utils import (
56
create_event,
67
create_repeat_event,
@@ -661,3 +662,43 @@ def get_week_by_date(date_str: str) -> tuple[Response, int]:
661662
return jsonify({"error": "Week not found"}), 404
662663

663664
return jsonify(week.to_dict()), 200
665+
666+
667+
@events_api_bp.route("/colours", methods=["GET"])
668+
def get_colours() -> tuple[Response, int]:
669+
"""Get all available colours
670+
---
671+
security: []
672+
responses:
673+
200:
674+
description: A JSON object containing all available colours.
675+
schema:
676+
type: object
677+
additionalProperties:
678+
type: string
679+
404:
680+
description: No colours found.
681+
"""
682+
if not colours:
683+
return jsonify({"error": "No colours found"}), 404
684+
return jsonify(colours), 200
685+
686+
687+
@events_api_bp.route("/icons", methods=["GET"])
688+
def get_icons() -> tuple[Response, int]:
689+
"""Get all available icons
690+
---
691+
security: []
692+
responses:
693+
200:
694+
description: A JSON object containing all available icons.
695+
schema:
696+
type: object
697+
additionalProperties:
698+
type: string
699+
404:
700+
description: No icons found.
701+
"""
702+
if not icons:
703+
return jsonify({"error": "No icons found"}), 404
704+
return jsonify(icons), 200

events/utils.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import pytz
66
import requests
77

8+
from config import colours
89
from schema import Event, Tag, Week, db
910

1011

@@ -392,15 +393,11 @@ def validate_colour(text_colour: str | None, hex_colour: str | None) -> str | No
392393

393394
def get_hex_from_name(name: str) -> str | None:
394395
"""Get the hex colour from a name"""
395-
with Path("colours.json").open("r") as f:
396-
colours = load(f)
397-
return colours.get(name.lower(), None) # type: ignore
396+
return colours.get(name.lower(), None)
398397

399398

400399
def get_name_from_hex(hex_colour: str) -> str | None:
401400
"""Get the name of a colour from its hex code"""
402-
with Path("colours.json").open("r") as f:
403-
colours = load(f)
404401
for name, hex_code in colours.items():
405402
if hex_code.lower() == hex_colour.lower():
406403
return name

schema.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import re
22
from datetime import date, datetime, timedelta
3-
from json import load
4-
from pathlib import Path
53

64
import pytz
75
from flask import Flask
86
from flask_sqlalchemy import SQLAlchemy
97
from sqlalchemy import and_, func
108
from sqlalchemy.orm import foreign
119

10+
from config import colours, custom_icons, icons
11+
1212
db = SQLAlchemy()
1313

1414

@@ -180,15 +180,16 @@ def validate(self) -> str | None:
180180

181181
# check if colour is valid
182182
colour_regex = re.compile(r"^#[0-9a-fA-F]{6}$")
183-
if self.colour:
184-
if colour_regex.match(self.colour):
185-
return None
186-
with Path("colours.json").open("r") as f:
187-
colours = load(f)
188-
if self.colour in colours:
189-
return None
183+
if self.colour and (
184+
not colour_regex.match(self.colour) or self.colour not in colours
185+
):
186+
return "Colour must be a valid hex code or one of: " + ", ".join(colours)
187+
188+
# check if icon is valid
189+
if self.icon and self.icon not in icons:
190190
return (
191-
f"Colour must be one of {", ".join(colours.keys())} or a valid hex code"
191+
"Icon must be a phosphor icon (https://phosphoricons.com/) or one of: "
192+
+ ", ".join(custom_icons)
192193
)
193194

194195
return None

templates/events/form.html

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ <h1>Create Event</h1>
1717

1818
{% with messages = get_flashed_messages() %}
1919
{% if messages %}
20-
<div class="alert alert-danger col-12">
21-
{% for message in messages %}
22-
{{ message }}
23-
{% endfor %}
24-
</div>
20+
<div class="alert alert-danger col-12">
21+
{% for message in messages %}
22+
{{ message }}
23+
{% endfor %}
24+
</div>
2525
{% endif %}
2626
{% endwith %}
2727

@@ -161,6 +161,11 @@ <h1>Create Event</h1>
161161
<div class="form-floating col-md-8 offset-md-2">
162162
<input type="text" name="tags" id="tags" class="form-control no-validate" placeholder="tag1,tag2,tag3">
163163
<label for="tags">Tags</label>
164+
<datalist id="tags-list">
165+
{% for tag in tags %}
166+
<option value="{{ tag }}">
167+
{% endfor %}
168+
</datalist>
164169
</div>
165170

166171
<!-- submit -->

0 commit comments

Comments
 (0)