Django uses a reference graph to determine the order
in table deletions that occur. Do the same here.
This commit also adds in the `REGEXP` sqlite function,
exactly how Django uses it in its reference graphing.
Signed-off-by: Kevin Morris <kevr@0cost.org>
This rewrites the entire model base as declarative models.
This allows us to more easily customize overlay fields
in tables and is more common.
This effort also brought some DB violations to light which
this commit addresses.
Signed-off-by: Kevin Morris <kevr@0cost.org>
`ci` in this context means "Case Insensitive".
`cs` in this context means "Case Sensitive".
New models created:
- OfficialProvider
This was required to write a test for checking that
OfficialProviders behaves as we expect, which was the starter
for the original aurblup bug.
New tests created:
- test_official_provider
Modified tests:
- test_package_base: add ci test
- test_package: add ci test
- test_session: add cs test
- test_ssh_pub_key: add cs test
Signed-off-by: Kevin Morris <kevr@0cost.org>
First off: This commit changes the default development database
backend to mysql. sqlite, however, is still completely supported
with the caveat that a user must now modify config.dev to use
the sqlite backend.
While looking into this, it was discovered that our SQLAlchemy
backend for mysql (mysql-connector) completely broke model
attributes when we switched to utf8mb4_bin (binary) -- it does
not correct the correct conversion to and from binary utf8mb4.
The new, replacement dependency mysqlclient does. mysqlclient
is also recommended in SQLAlchemy documentation as the "best"
one available.
The mysqlclient backend uses a different exception flow then
sqlite, and so tests expecting IntegrityError has to be modified
to expect OperationalError from sqlalchemy.exc.
So, for each model that we define, check keys that can't be
NULL and raise sqlalchemy.exc.IntegrityError if we have to.
This way we keep our exceptions uniform.
Signed-off-by: Kevin Morris <kevr@0cost.org>
This fixes SQLAlchemy warnings related to primary keys not
having an auto_increment or nullable.
We've done this by making all foreign primary keys nullable.
In ApiRateLimit's case, we can set a default str to act as
a null, which seems a bit more sensible.
Signed-off-by: Kevin Morris <kevr@0cost.org>
Some of these tests were written before some of our convenient
tooling existed. Additionally, some of the tests were not
cooperating with PEP-8 guidelines or isorted.
This commit does the following:
- Replaces all calls to make_(user|session) with
aurweb.db.create(Model, ...).
- Replace calls to session.add(...) + session.commit() with
aurweb.db.create.
- Removes the majority of calls to (session|aurweb.db).delete(...).
- Replaces session.query calls with aurweb.db.query.
- Initializes all mutable globals in pytest fixture setup().
- Makes mutable global declarations more concise:
`var1, var2 = None, None` -> `var1 = var2 = None`
- Defines a warning exclusion for test/test_ssh_pub_key.py.
- Removes the aurweb.testing.models module.
- Removes some useless pytest.fixture yielding.
As of this commit, developers should use the following guidelines
when writing tests:
- Always use aurweb.db.(create|delete|query) for database
operations, where possible.
- Always define mutable globals in the style: `var1 = var2 = None`.
- `yield` the most dependent model in pytest setup fixture **iff**
you must delete records after test runs to maintain database
integrity. Example: test/test_account_type.py.
This all makes the test code look and behave much cleaner.
Previously, aurweb.testing.setup_test_db was buggy and leaving
objects around in SQLAlchemy's IdentityMap.
Signed-off-by: Kevin Morris <kevr@0cost.org>
We no longer need to delete records like this; in fact, it causes
errors now. Fix this by removing the deletions and allow
setup_test_db to do it's job.
We'll need to do this for other tests as well.
Signed-off-by: Kevin Morris <kevr@0cost.org>
Additionally, add an optional **kwargs passing via make_relationship.
This allows us to use things like `uselist=False`, which was needed
for test/test_package.py.
Signed-off-by: Kevin Morris <kevr@0cost.org>
AUR renders its own 404 Not Found page when a bad route
is encountered. Introducing the previous verification
caused an error in this case when setting a language
while viewing the Not Found page. So, instead of checking
through routes, just make sure that the next parameter
starts with a '/' character, which removes the possibility
of any cross attacks.
+ Removed aurweb.asgi.routes; no longer needed.
Signed-off-by: Kevin Morris <kevr@0cost.org>
* Added account_url filter to jinja2 environment. This produces a path
to the user's account url (/account/{username}).
* Updated archdev-navbar to link to new edit route.
+ Added migrate_cookies(request, response) to aurweb.util, a function
that simply migrates the request cookies to response and returns it.
+ Added account_edit tests to test_accounts_routes.py.
Signed-off-by: Kevin Morris <kevr@0cost.org>
* Added /register get and post routes.
+ Added default attributes to AnonymousUser, including a new
AnonymousList which behaves like an sqlalchemy relationship
list.
+ aurweb.util: Added validation functions for various user fields
used throughout registration.
+ test_accounts_routes: Added get|post register route tests.
Signed-off-by: Kevin Morris <kevr@0cost.org>
This CAPTCHA workflow is the same workflow used by our current
PHP implementation of account registration.
Signed-off-by: Kevin Morris <kevr@0cost.org>
This module includes timezone-based utilities for a FastAPI request.
This commit introduces use of the AURTZ cookie within get_request_timezone.
This cookie should be set to the user or session's timezone.
* `make_context` has been modified to parse the request's timezone
and include the "timezone" and "timezones" variables, along with
a timezone specified "now" date.
+ Added `Timezone` attribute to aurweb.testing.requests.Request.user.
Signed-off-by: Kevin Morris <kevr@0cost.org>
This clones the behavior already present in the PHP implementation,
but it uses a global dict with credential constant keys to
validation functions to determine if a given user has a credential.
Signed-off-by: Kevin Morris <kevr@0cost.org>
+ Use User.LangPreference when there is no set AURSID
if request.user.is_authenticated is true.
+ Updated post /language to update LangPreference when
request.user.is_authenticated.
+ Restore language during test where we change it.
+ Added the user attribute to aurweb.testing.requests.Request.
Signed-off-by: Kevin Morris <kevr@0cost.org>
Introduced `get|post` `/passreset` routes. These routes mimic the
behavior of the existing PHP implementation, with the exception of
HTTP status code returns.
Routes added:
GET /passreset
POST /passreset
Routers added:
aurweb.routers.accounts
* On an unknown user or mismatched resetkey (where resetkey must ==
user.resetkey), return HTTP status NOT_FOUND (404).
* On another error in the request, return HTTP status BAD_REQUEST (400).
Both `get|post` routes requires that the current user is **not**
authenticated, hence `@auth_required(False, redirect="/")`.
+ Added auth_required decorator to aurweb.auth.
+ Added some more utility to aurweb.models.user.User.
+ Added `partials/error.html` template.
+ Added `passreset.html` template.
+ Added aurweb.db.ConnectionExecutor functor for paramstyle logic.
Decoupling the executor logic from the database connection logic
is needed for us to easily use the same logic with a fastapi
database session, when we need to use aurweb.scripts modules.
At this point, notification configuration is now required to complete
tests involved with notifications properly, like passreset.
`conf/config.dev` has been modified to include [notifications] sendmail,
sender and reply-to overrides. Dockerfile and .gitlab-ci.yml have been
updated to setup /etc/hosts and start postfix before running tests.
* setup.cfg: ignore E741, C901 in aurweb.routers.accounts
These two warnings (shown in the commit) are not dangerous and a bi-product
of maintaining compatibility with our current code flow.
Signed-off-by: Kevin Morris <kevr@0cost.org>
+ Added route: GET `/login` via `aurweb.routers.auth.login_get`
+ Added route: POST `/login` via `aurweb.routers.auth.login_post`
+ Added route: GET `/logout` via `aurweb.routers.auth.logout`
+ Added route: POST `/logout` via `aurweb.routers.auth.logout_post`
* Modify archdev-navbar.html template to toggle displays on auth state
+ Added login.html template
Signed-off-by: Kevin Morris <kevr@0cost.org>
+ Added aurweb.auth.AnonymousUser
* An instance of this model is returned as the request user
when the request is not authenticated
+ Added aurweb.auth.BasicAuthBackend
+ Add starlette's AuthenticationMiddleware to app middleware,
which uses our BasicAuthBackend facility
+ Added User.is_authenticated()
+ Added User.authenticate(password)
+ Added User.login(request, password)
+ Added User.logout(request)
+ Added repr(User(...)) representation
+ Added aurweb.auth.auth_required decorator.
This change uses the same AURSID logic in the PHP implementation.
Additionally, introduce a few helpers for authentication,
one of which being `User.update_password(password, rounds = 12)`
where `rounds` is a configurable number of salt rounds.
Signed-off-by: Kevin Morris <kevr@0cost.org>
+ Added aurweb.util module.
- Added make_random_string function.
+ Added aurweb.db.make_random_value function.
- Takes a model and a column and introspects them to figure out the
proper column length to create a random string for; then creates
a unique string for that column.
Signed-off-by: Kevin Morris <kevr@0cost.org>
Takes sqlalchemy kwargs or stanzas:
query(Model, Model.Column == value)
query(Model, and_(Model.Column == value, Model.Column != "BAD!"))
Updated tests to reflect the new utility and a comment about upcoming
function deprecation is added to get_account_type().
From here on, phase out the use of get_account_type().
+ aurweb.db: Added create utility function
+ aurweb.db: Added delete utility function
The `delete` function can be used to delete a record by search
kwargs directly.
Example:
delete(User, User.ID == 6)
All three functions added in this commit are typically useful to
perform these operations without having to import aurweb.db.session.
Removes a bit of redundancy overall.
Signed-off-by: Kevin Morris <kevr@0cost.org>