Currently there aren't any permission checks based on folder IDs in
the admin app or the API, so it's possible for a user to modify the
folder ID to perform operations on folders outside their service.
Our usual way to avoid this is to always use service_id filter when
fetching objects from the database.
Since template folders are only linked by ID to their parent we need
to check that the parent folder belongs to the same service as the
one being created. Otherwise, admin users could modify parent ID to
create a folder outside their service.
Ideally, this check would be performed by a DB constraint, but since
parent_id can be nullable this is only possible to express using DB
triggers.
Instead, we perform the check in the API endpoint code.
This commit modifies the code paths the admin app uses to send one off
emails and text messages to also accept letters.
This mostly worked already, the two changes were:
- making sure that one-off letters are processed by the correct task,
from the correct queue
- one-off letters sent from a service in research mode don’t get put on
a queue and go straight to `delivered` (because we don’t want to send
them for real)
* create template folder
* rename template folder
* get list of template folders for service (not nested/presented in any
particular way)
* delete template folder
Also removed `lazy=dynamic` from the `template_folder.templates`
relationship. lazy=dynamic returns a query object (which you can then
filter further). We just want to return the entire fetched list, at
least for now.
The `@version_class` decorator looks at every dirty (modified) model in
the session to work out which new history models to create. However, if
there are dirty items in the session, sqlalchemy might flush to the
database, clearing the whole session.
We ran into problems with the archive service function, which is
versioned for api keys, templates and services. When constructing the
TemplateHistory objects, `history_meta.py::create_history` would call
getattr on `Template.folders`, which would make a database call to join
across to the TemplateFolder objects - this would then flush the dirty
Service object from the session before the ServiceHistory object was
created.
To get around this, we eager load the Template.folder object, joining
on to it automatically when the Template is fetched. That way, it
doesn't make a SELECT mid-way through the version decorator, and the
history is preserved.
Note: This relationship is only on Template, not TemplateHistory - so
we're not doing this join every single time we send a message.
paas were trying to ascertain if notify was up by looking at '/', for cert
renewal. This commit adds the status endpoint to '/', so we're not mistakenly
left for our cert to expire
a TemplateFolder has a service, a name, and a parent. Parent is a
nullable foreign key pointing to another TemplateFolder instance. We
don't do any checks here for cyclical or otherwise invalid folder
structures so keep your data clean, folks!
Unsurprisingly, a Template can be part of a TemplateFolder - there's a
mapping class (template_folder_map to avoid giving it a dumb name) -
this mapping table shouldn't be interacted with directly - rather, you
should use the `Template.folder` or `TemplateFolder.templates`
relationship.