Commit graph

202 commits

Author SHA1 Message Date
Kevin Morris
eec09dec3e [FastAPI] add /rss and /rss/modified
There are slight differences in that, with `python-feedgen`,
an empty description field completely omits the description,
but includes the description when there is one.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-07-01 11:09:09 -07:00
Kevin Morris
021a1c8fb6 add /accounts/ (get, post) routes
Slight markup changes, same style overall and same
form parameters as the PHP implementation.

In addition, we've disabled the "left" and "right"
navigation buttons when we're at the border of the
table.

CSS Changes:

- Added similar styling to submit `<buttons>` that submit `<input>` had.
- Added .results tr td[align="{left,right}"] styling to align
  the result table's `More -->` button to the right of the table.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-07-01 11:08:56 -07:00
Kevin Morris
450469e3d6 add /addvote/ (get, post) routes
Another part of the "Trusted User" collection of routes.
This allows a Trusted User to create a proposal.

New Routes:

- get `/addvote/`
- post `/addvote/`

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-07-01 11:08:44 -07:00
Kevin Morris
f8d2d4c82a PackageBase.package -> PackageBase.packages
A PackageBase can have more than one package
associated with it.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-28 08:31:13 -07:00
Jelle van der Waa
12911a101e
Port homepage intro to fastapi
Port the main home page content to fastapi.
2021-06-27 15:17:04 +02:00
Kevin Morris
85ba4a33a8 add /tu/{proposal_id} (get, post) routes
This commit ports the `/tu/?id={proposal_id}` PHP routes to
FastAPI into two individual GET and POST routes.

With this port of the single proposal view and POST logic,
several things have changed.

- The only parameter used is now `decision`, which
  must contain `Yes`, `No`, or `Abstain` as a string.
  When an invalid value is given, a BAD_REQUEST response
  is returned in plaintext: Invalid 'decision' value.
- The `doVote` parameter has been removed.
- The details section has been rearranged into a set
  of divs with specific classes that can be used for
  testing. CSS has been added to persist the layout with
  the element changes.
- Several errors that can be discovered in the POST path
  now trigger their own non-200 HTTPStatus codes.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-26 01:11:52 -07:00
Kevin Morris
83c038a42a add TUVoteInfo.total_votes()
Returns the sum of TUVoteInfo.Yes, TUVoteInfo.No and
TUVoteInfo.Abstain.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-26 01:11:52 -07:00
Kevin Morris
ac1779b705 add util.number_format -> number_format Jinja2 filter
Implement a `number_format` equivalent to PHP's version.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-26 01:11:52 -07:00
Kevin Morris
dc4cc9b604 add aurweb.asgi.id_redirect_middleware
A new middleware which redirects requests going to '/route?id=some_id'
to '/route/some_id'. In the FastAPI application, we'll prefer using
restful layouts where possible where resource-based ids are
parameters of the request uri: '/route/{resource_id}'.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-26 01:11:52 -07:00
Kevin Morris
d674aaf736 add /tu/ (get) index
This commit implements the '/tu' Trusted User index page.

In addition to this functionality, this commit introduces
the following jinja2 filters:

- dt: util.timestamp_to_datetime
- as_timezone: util.as_timezone
- dedupe_qs: util.dedupe_qs
- urlencode: urllib.parse.quote_plus

There's also a new decorator that can be used to enforce
permissions: `account_type_required`. If a user does not
meet account type requirements, they are redirected to '/'.

```
@auth_required(True)
@account_type_required({"Trusted User"})
async def some_route(request: fastapi.Request):
    return Response("You are a Trusted User!")
```

Routes added:

- `GET /tu`: aurweb.routers.trusted_user.trusted_user

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-26 01:03:27 -07:00
Kevin Morris
d606ebc0f1 add User.is_trusted_user() and User.is_developer()
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-26 01:03:27 -07:00
Kevin Morris
4927a61378 add TUVoteInfo.is_running() method
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-26 01:03:27 -07:00
Kevin Morris
a36cc0c00a eradicate Term records after testing them
Otherwise, Terms can leak out into other tests causing /tos
redirects unexpectedly.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-24 19:52:17 -07:00
Kevin Morris
adb42882c5 [FastAPI] add /tos routes (get, post)
This clones the end goal behavior of PHP, but it does not
concern itself with the revision form array at all.

Since this page on PHP renders out the entire list of
terms that a user needs to accept, we can treat a
POST request with the "accept" checkbox enabled as a
request to accept all unaccepted (or outdated revision)
terms.

This commit also adds in a new http middleware used to
redirect authenticated users to '/tos' if they have not
yet accepted all terms.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-24 19:12:49 -07:00
Kevin Morris
5bd46d18a3 Improve Docker ecosystem
Instead of using Dockerfile for everything, we've introduced
a docker-compose.yml file and kept the Dockerfile to producing
a pure base image for the services defined.

docker-compose services:

- `mariadb` - Setup mariadb
- `sharness` - Run sharness suites
- `pytest-mysql` - Run pytest suites with MariaDB
- `pytest-sqlite` - Run pytest suites with SQLite
- `test` - Run all tests and produce a collective coverage report
    - This target mounts a cache volume and copies any successful
      coverage report back to `./cache/.coverage`. Users can run
      `./util/fix-coverage ./cache/.coverage` to rewrite source
      code paths and move coverage into place to view reports
      on your local system.

== Get Started ==

Build `aurweb:latest`.

    $ docker build -t aurweb:latest .

Run all tests via `docker-compose`.

    $ docker-compose up test

You can also purely run `pytest` in SQLite or MariaDB modes.

    $ docker-compose up pytest-sqlite
    $ docker-compose up pytest-mysql

Or `sharness` alone, which only uses SQLite internally.

    $ docker-compose up sharness

After running tests, coverage reports are stored in `./cache/.coverage`.
This database was most likely created in a different path, and so it
needs to be sanitized with `./util/fix-coverage`.

    $ ./util/fix-coverage cache/.coverage
    Copied coverage db to /path/to/aurweb/.coverage.
    $ coverage report
    ...
    $ coverage html
    $ coverage xml
    ...

Defined components:

**Entrypoints**

- mariadb-entrypoint.sh - setup mariadb and run its daemon
- test-mysql-entrypoint.sh - setup mysql configurations
- test-sqlite-entrypoint.sh - setup sqlite configurations
- tests-entrypoint.sh - setup mysql and sqlite configurations

**Scripts**

- run-mariadb.sh - setup databases
- run-pytests.sh - run pytest suites
- run-sharness.sh - run sharness suites
- run-tests.sh - run both pytests and sharness

**Health**

- mariadb.sh - A healthcheck script for the mariadb service
- pytest.sh - A healthcheck script for the pytest-* services
- sharness.sh - A healthcheck script for the sharness service

This Docker configuration is setup for tests, but should be
extendable for web and git servers.

**Changes to Makefile**

- Remove `.coverage` in the `clean` target
- Add a `coverage` target which prints a report and outputs xml

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-24 19:02:35 -07:00
Kevin Morris
3b8e3f3e4b test_db: remove user-configuration dependency
We should have been using a config that's stored in the
repo all along.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-24 19:02:35 -07:00
Kevin Morris
8abb096d7b use aurweb_test for default mysql dev database
This also updates `test/README.md` to be a bit more specific
and precise with our current state of testing.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-24 19:02:35 -07:00
Kevin Morris
55c0637b98 add logging.config.fileConfig
This resolves logging issues with alembic on aurweb.initdb
in addition to adding more logging utilities for aurweb
and tests in general.

Developers should fetch a logger for their specific module
via `logging.getLogger(__name__)`.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-24 18:56:38 -07:00
Kevin Morris
865c414504 aurweb.asgi: add security headers middleware
This commit introduces a middleware function which adds
the following security headers to each response:

- Content-Security-Policy
    - This includes a new `nonce`, which is tied to a user
      via authentication middleware. Both an anonymous user
      and an authenticated user recieve their own random nonces.
- X-Content-Type-Options
- Referrer-Policy
- X-Frame-Options

They are then tested for existence in test/test_routes.py.

Note: The overcomplicated-looking asyncio behavior in the
middleware function is used to avoid a warning about the old
coroutine awaits being deprecated. See
https://docs.python.org/3/library/asyncio-task.html#asyncio.wait
for more detail.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-22 20:33:45 -07:00
Kevin Morris
91dc3efc75 add util.add_samesite_fields(response, value)
This function adds f"SameSite={value}" to each cookie's header
stored in response.

This is needed because starlette does not currently support
the `samesite` argument in Response.set_cookie. It is merged,
however, and waiting for next release.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-22 20:33:20 -07:00
Kevin Morris
ec632a7091 use secure=True when options.disable_http_login is enabled
We'll piggyback off of the current existing configuration item,
`disable_http_login`, to decide how we should submit cookies to
an HTTP response.

Previously, in `sso.py`, the http schema was used to make this
decision. There is an issue with that, however: We cannot actually
test properly if we depend on the https schema.

This change allows us to toggle `disable_http_login` to modify
the behavior of cookies sent with an http response to be secure.

We test this behavior in test/test_auth_routes.py#L81:
`test_secure_login(mock)`.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-22 20:33:19 -07:00
Kevin Morris
763b84d0b9 Merge branch 'master' into pu 2021-06-22 19:39:31 -07:00
Kristian Klausen
959e535126 Use the real ml email address instead of alias
All the arch-x@archlinux.org -> arch-x@lists.archlinux.org aliases will
be dropped soon[1].

[1] https://lists.archlinux.org/pipermail/arch-dev-public/2021-June/030462.html
2021-06-23 03:21:06 +02:00
Kevin Morris
af76e660d0 auth_required: allow formattable template tuples
See docstring for updates.

template= has been modified.
status_code= has been added as an optional template status_code.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-21 21:37:10 -07:00
Kevin Morris
d5e650a339 add util.dedupe_qs -> dedupe_qs Jinja2 filter
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-19 09:53:59 -07:00
Kevin Morris
b1baf76998 add util.as_timezone -> as_timezone Jinja2 filter
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-19 09:53:48 -07:00
Kevin Morris
ac67268a28 add util.timezone_to_datetime -> dt Jinja2 filter
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-19 09:53:30 -07:00
Kevin Morris
40448ccd34 aurweb.db: add commit(), add() and autocommit arg
With the addition of these two, some code has been swapped
to use these in some of the other db wrappers with an additional
autocommit kwarg in create and delete, to control batch
transactions.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-19 09:08:09 -07:00
Kevin Morris
bd8f528011 add Base.as_dict() and Base.json()
Two utility functions for all of our ORM models that will
allow us to easily convert them to Python structures and
JSON data.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-13 10:48:31 -07:00
Kevin Morris
0c1241f8bb add TUVote SQLAlchemy ORM model
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-11 22:14:38 -07:00
Kevin Morris
8c345a0448 TUVoteInfo: generalize Quorum
SQLite does not support native DECIMAL columns, and for that
reason, we had to switch to using Strings that can hold the data
in the case we are using sqlite.

This commit sets the TUVoteInfo model up in a generic way, that
it always converts to string when setting Quorum (OK for DECIMAL)
and always converts to float when getting Quorum.

This way, we can treat TUVoteInfo.Quorum as the same thing
everywhere.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-11 21:48:39 -07:00
Kevin Morris
541c978ac4 add PackageRequest SQLAlchemy ORM model
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-11 21:21:38 -07:00
Kevin Morris
809939ab03 add TUVoteInfo SQLAlchemy ORM model
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-11 21:00:26 -07:00
Kevin Morris
3bf4b3717a add RequestType SQLAlchemy ORM model
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-11 17:37:51 -07:00
Kevin Morris
511f174c8b add PackageBlacklist SQLAlchemy ORM model
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-11 17:28:08 -07:00
Kevin Morris
163e4d7389 test_package_comaintainer: sanitize newlines
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-11 17:15:18 -07:00
Kevin Morris
5b856c7af2 add PackageNotification SQLAlchemy ORM model
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-11 17:14:28 -07:00
Kevin Morris
229df1adef test_package_vote: remove useless stuff
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-11 16:56:15 -07:00
Kevin Morris
ebd216edfd add PackageComaintainer SQLAlchemy ORM model
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-11 16:52:45 -07:00
Kevin Morris
fc28c1e5fd add PackageComment SQLAlchemy ORM model
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-11 00:35:18 -07:00
Kevin Morris
11c4926502 add PackageSource SQLAlchemy ORM model
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-10 17:46:29 -07:00
Kevin Morris
d18cfad63e use djangos method of wiping sqlite3 tables
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>
2021-06-10 17:26:34 -07:00
Kevin Morris
5de7ff64df add PackageVote SQLAlchemy ORM model
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-10 13:55:07 -07:00
Kevin Morris
888cf5118a use declarative_base for all ORM models
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>
2021-06-10 13:54:27 -07:00
Kevin Morris
1874e821f5 add case [in]sensitivity tests + add OfficialProvider model
`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>
2021-06-05 23:20:18 -07:00
Kevin Morris
5ceeb88bee remove unused imports, rectify isort violations
Files got into the branch that violate both PEP-8 guidelines
and isorts. This fixes them.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-05 21:27:39 -07:00
Kevin Morris
62e58b122f fix test_accounts_routes test coverage
Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-05 20:17:48 -07:00
Kevin Morris
228bc8fe7c fix aurweb.auth test coverage
With mysqlclient, we no longer need to account for a user not existing
when an ssh key is found.

Signed-off-by: Kevin Morris <kevr@0cost.org>
2021-06-05 20:17:48 -07:00
Kevin Morris
aecb649473 use mysql backend in config.dev
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>
2021-06-05 20:17:48 -07:00
Kevin Morris
d7481b9649 modify schema primary keys to be nullable+defaulted
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>
2021-06-05 20:11:17 -07:00