diff options
-rw-r--r-- | .github/ISSUE_TEMPLATE/config.yml | 8 | ||||
-rw-r--r-- | SCHEMA.md | 15 | ||||
-rw-r--r-- | backend/models/form_response.py | 15 | ||||
-rw-r--r-- | backend/routes/forms/submit.py | 2 |
4 files changed, 32 insertions, 8 deletions
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..4b036ed --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: false +contact_links: + - name: Notion task board + url: https://www.notion.so/pythondiscord/2c44f303ec36425da23494f606973f14?v=39e0f16a1ffe4152b3dccb9d5bce9301 + about: Staff-only Notion task board for feature requests and bug reports. + - name: Public GitHub Discussions + url: https://github.com/python-discord/forms-backend/discussions + about: GitHub Discussions from external collaborators. @@ -127,13 +127,14 @@ Textareas require no additional configuration. ## Form response -| Field | Type | Description | -| ---------- | ---------------------------------------------------- | --------------------------------------------------------------------------- | -| `_id`/`id` | MongoDB ObjectID | Random identifier used for the response | -| `user` | Optional [user details object](#user-details-object) | An object describing the user that submitted if the form is not anonymous | -| `antispam` | Optional [anti spam object](#anti-spam-object) | An object containing information about the anti-spam on the form submission | -| `response` | Object | Object containing question IDs mapping to the users answer | -| `form_id` | String | ID of the form that the user is submitting to | +| Field | Type | Description | +| ----------- | ---------------------------------------------------- | --------------------------------------------------------------------------- | +| `_id`/`id` | MongoDB ObjectID | Random identifier used for the response | +| `user` | Optional [user details object](#user-details-object) | An object describing the user that submitted if the form is not anonymous | +| `antispam` | Optional [anti spam object](#anti-spam-object) | An object containing information about the anti-spam on the form submission | +| `response` | Object | Object containing question IDs mapping to the users answer | +| `form_id` | String | ID of the form that the user is submitting to | +| `timestamp` | String | ISO formatted string of submission time. | ### User details object diff --git a/backend/models/form_response.py b/backend/models/form_response.py index 8bc69e4..933f5e4 100644 --- a/backend/models/form_response.py +++ b/backend/models/form_response.py @@ -1,6 +1,7 @@ +import datetime import typing as t -from pydantic import BaseModel, Field +from pydantic import BaseModel, Field, validator from .antispam import AntiSpam from .discord_user import DiscordUser @@ -14,6 +15,18 @@ class FormResponse(BaseModel): antispam: t.Optional[AntiSpam] response: dict[str, t.Any] form_id: str + timestamp: str + + @validator("timestamp", pre=True) + def set_timestamp(cls, iso_string: t.Optional[str]) -> t.Optional[str]: + if iso_string is None: + return datetime.datetime.now(tz=datetime.timezone.utc).isoformat() + + elif not isinstance(iso_string, str): + raise ValueError("Submission timestamp must be a string.") + + # Convert to datetime and back to ensure string is valid + return datetime.datetime.fromisoformat(iso_string).isoformat() class Config: allow_population_by_field_name = True diff --git a/backend/routes/forms/submit.py b/backend/routes/forms/submit.py index 150a343..dfa0de6 100644 --- a/backend/routes/forms/submit.py +++ b/backend/routes/forms/submit.py @@ -59,6 +59,8 @@ class SubmitForm(Route): """Submit a response to the form.""" data = await request.json() + data["timestamp"] = None + if form := await request.state.db.forms.find_one( {"_id": request.path_params["form_id"], "features": "OPEN"} ): |