The goals of captura are the following:
- As a Base for/Enhancement of other apps:
- Extensibility using plugins. For instance, setting a schema for the
content
sections of any of the 'first class' tables or adding additional granting functionality. - Make it easy to add sharing between application users to existing
services. This is done using the
content
sections of the various tables where users can choose how to shape their data.
- Extensibility using plugins. For instance, setting a schema for the
- Control of Permissions and Visibility:
- Delegate various levels of permissions in sharing, e.g.
view
,modify
, orown
.documents
can be public or private. - Organize
documents
intocollections
andcollections
incollections
.
- Delegate various levels of permissions in sharing, e.g.
- Emmit events for those who desire them.
See the next section.
First, git clone
this project and go to the cloned directory. Then run
mkdir ./configs ./logs
A docker compose project is included so that it is easy to get a server and
database up and running. The defaults included in ./src/app/config.py
will
work for the compose projects mysql instance. To start the compose project do
# Start the docker compose project.
docker compose --file=docker/docker-compose.yaml up --detach
docker compose --file=docker/docker-compose.yaml exec bash
and then
python -m venv .venv
source .venv/bin/activate
python -m pip install --editable .
and then create your application configuration.
Captura is built with configurability in mind. All configuration can be written
using YAML
or JSON
. Configuration is by default contained in the
./configs
directory, but the locations (paths of) of these configurations
can be set using
CAPTURA_CONFIG_APP
CAPTURA_CONFIG_CLIENT
CAPTURA_LOG_CONFIG
To see if these are set as desired, using the captura command as follows:
captura config --envvars
There are a few important pieces of information that captura will require to run the compose project. A minimal configuration should look something like this:
# ./configs/app.yaml
auth0:
use: False
issuer: auth.example.org
registration_code_salt: <big nasty string>
api:
audience: example.com
app:
client_id: <big nasty string>
client_secret: <big nasty string>
mysql: {}
app:
environment: development
host_scheme: http://
This configuration can be validated using the following command:
captura config
This will generate an error that can guide you on how to configure the app if the configuration is malformed. Otherwise, your configuration will be printed (with sensored secrets thanks to pydantic) to the terminal.
Once your configuration is valid then ensure that captura will run:
captura run
This clients configuration is inspired by kubectl
. This is because when
using kubernetes I found it extermely convenient to be able to switch out this
host used without directly editting configuration.
The following instructions require that captura is not run in auth0 mode. To do so run
CAPTURA_AUTH0__USE=false captura run
this will make it such that test tokens can be generated using captura itself. DO NOT USE PYTEST MODE IN PRODUCTION! ANYBODY CAN MAKE TOKENS IF THEY DESIRE TO! To create your first token do:
legere tokens register \
--name "example" \
--description "example" \
--url "example.com" \
--email "[email protected]"
For subsequent tokens use legere tokens create
. With this token, create
a client configuration. A minimal configuration should look like
# ./config/client.yaml
hosts:
docker_self:
host: http://localhost:8080
remote: true # Requires that ``captura run`` is invoked in the container
docker_hostless:
host: http://localhost:8080
remote: false # Client uses an app instance directly.
profiles:
docker_self:
token: *************
remote: true
use:
host: docker_self
profile: docker_self
and can be validated as follows:
legere config show
# List the hosts configured
legere config hosts --all
# List the profiles configured
legere config profiles --all
# Change the host
legere config use --host docker_hostless
To use the client on the docker host (instead of in the container, as above) install this project and run:
# Get the host into client.yaml legere config docker-host --config-out configs/client.yaml # Use this host by default legere config use --host docker --config-out ./configs/client.yaml # Verify legere config show
Finally, the output format may be configured:
...
output:
decorate: false
output: yaml
output_fallback: json
rich_theme: fruity
You probably won't need dummies. If you do, add
dummies:
dummy:
collections:
minimum: 4
maximum: 8
documents:
minimum: 9
maximum: 16
grants:
minimum_self: 25
maximum_self: 36
minimum_other: 25
maximum_other: 36
users:
minimum: 75
maximum_uses: 100
to your application configuration and configure it to your liking. This configuration may be validated like
simulatus preview
and controls the simulatus
command, which can be used to assess the database
as a whole or per user and debug assist in debugging of tests.
The database only requires six tables for the time being:
- Users. A list of user profiles. These should not contain credentials, authentication will be outsourced to Auth0.
- Collections. These should be collections of individual documents. Some collections will belong to a user where others will not.
- Documents. Should contain the documents belonging to possibly many collections. Documents should be modifyable, and updates will be logged in DocumentHistories. A document should belong to one or many users, with the initial user being given admin permissions.
- Grants. Associtions between users and documents.
- Assignments. Associtions between collections and documents.
- Events. Eventually this will be used to stream events.
- Demos. This is to have a record of who has requested a demo. This will eventually be a plugin and therefore this table will be optional.
Other tables may be added by plugins or other parts of the code. For instance,
the dummy
module will require the reports
and reports_grants
table.
Captura's database model is designed to make it easy to layer on top of existing services - essentially the goals are the following:
First of all, request a demo at captura.acederberg.io/demo
. An admin will
likely accept your demo account if you are not a bot.
After your demo account is created, create your account by going to /login
.
This will allow you to customize your user to your liking. After this, you will
be redirected to your profile where you can obtain an authorization token.
Using this token, your client configuration should look something like:
# ~/.captura/client.yaml
hosts:
production:
host: https://captura.acederberg.io
remote: true
profiles:
production:
token: <TOKEN FROM ABOVE STEP>
use:
host: production
profile: production
If you don't want to run and configure your own instance, follow the steps
above. If you really want to go this way, see Installation
.
Grants can be initiated two ways: by owners inviting others and acceptance of invitations by these others, or by non-owners requesting a level of access and an owner accepting their request.
Document owner invites others. If pending grants exist, the invitations (in the form of events) are not recreated. If the grants are deleted and pending deletion, then adding the force parameter will be necessary.
client --profile granter grant documents create --uuid-user $UUID_USER $UUID_DOCUMENT
A user can read their own invitations like
client --profile grantee \
grants users read \
--pending $UUID_USER
Either of these will return an array of pending grants. A user can accept an invitation by sending a patch with grant uuids obtained from the above requests:
client --profile grantee grants users accept --uuid-grant $UUID_GRANT $UUID_USER
A user can ask for a grant to many (only public) documents like
client --profile grantee grants users --uuid-document $UUID_DOCUMENT $UUID_USER
Note that UUID_USER
must be the uuid of the grantee. Only admins can request
grants for users besides their own. The document holder can then view their
pending grants:
client --profile granter grants documents read --pending $UUID_DOCUMENT
which will return the pending grants. From this a granter can obtain grant uuids and accept it:
client --profile grantee grants documents accept $UUID_GRANT