Skip to content

Commit 0237670

Browse files
committed
feat(backend): implement a claim system
This allows to get a token once for each project. This token can then be used for operations which require more permissions like overriding stuff or deleting files/tags.
1 parent f673cf1 commit 0237670

File tree

9 files changed

+63
-3
lines changed

9 files changed

+63
-3
lines changed

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ docker run \
1717
--detach \
1818
--volume /path/to/doc:/var/docat/doc/ \
1919
--volume /path/to/locations:/etc/nginx/locations.d/ \
20+
--volume /path/to/db.json:/app/docat/db.json
2021
--publish 8000:80 \
2122
randombenj/docat
2223
```

Diff for: docat/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ __pycache__
44
upload
55
.tox
66
.coverage
7+
db.json

Diff for: docat/app.py

+19
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,20 @@
99
"""
1010

1111
import os
12+
import secrets
1213
from http import HTTPStatus
1314
from pathlib import Path
1415

1516
from flask import Flask, request, send_from_directory
17+
from tinydb import Query, TinyDB
1618
from werkzeug.utils import secure_filename
1719

1820
from docat.docat.utils import create_nginx_config, create_symlink, extract_archive
1921

2022
app = Flask(__name__)
2123
app.config["UPLOAD_FOLDER"] = os.getenv("DOCAT_DOC_PATH", "/var/docat/doc")
2224
app.config["MAX_CONTENT_LENGTH"] = 100 * 1024 * 1024 # 100M
25+
app.db = TinyDB('db.json')
2326

2427

2528
@app.route("/api/<project>/<version>", methods=["POST"])
@@ -63,6 +66,22 @@ def tag(project, version, new_tag):
6366
HTTPStatus.CONFLICT,
6467
)
6568

69+
@app.route("/api/<project>/claim", methods=["GET"])
70+
def claim(project):
71+
Project = Query()
72+
table = app.db.table('claims')
73+
result = table.search(Project.name == project)
74+
if result:
75+
return (
76+
{"message": f"Project {project} is already claimed!"},
77+
HTTPStatus.CONFLICT,
78+
)
79+
80+
token = secrets.token_hex(16)
81+
table.insert({"name": project, "token": token})
82+
return {"message": f"Project {project} successfully claimed", "token": token}, HTTPStatus.CREATED
83+
84+
6685

6786
# serve_local_docs for local testing without a nginx
6887
if os.environ.get("DOCAT_SERVE_FILES"):

Diff for: docat/poetry.lock

+13-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: docat/pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ license = "MIT"
88
[tool.poetry.dependencies]
99
python = ">=3.6"
1010
flask = "*"
11+
tinydb = "*"
1112

1213
[tool.poetry.dev-dependencies]
1314
flake8 = "*"

Diff for: docat/tests/__init__.py

Whitespace-only changes.

Diff for: docat/tests/conftest.py

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import pytest
2+
from tinydb import TinyDB
3+
from tinydb.storages import MemoryStorage
4+
5+
from app import app
6+
7+
8+
@pytest.fixture
9+
def client():
10+
app.config["TESTING"] = True
11+
app.db = TinyDB(storage=MemoryStorage)
12+
yield app.test_client()
13+
app.db = None
14+

Diff for: docat/tests/test_claim.py

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
def test_successfully_claim_token(client):
2+
3+
rv = client.get("/api/some-project/claim")
4+
assert b"Project some-project successfully claimed" in rv.data
5+
assert b"token" in rv.data
6+
7+
8+
def test_already_claimed(client):
9+
10+
rv = client.get("/api/some-project/claim")
11+
rv = client.get("/api/some-project/claim")
12+
assert b"Project some-project is already claimed!" in rv.data

Diff for: docat/tests/test_utils.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from mock import MagicMock, mock_open, patch
44

5-
from docat.utils import create_nginx_config, create_symlink, extract_archive
5+
from docat.docat.utils import create_nginx_config, create_symlink, extract_archive
66

77

88
def test_symlink_creation():
@@ -90,7 +90,7 @@ def test_not_overwrite_nginx_config():
9090
def test_archive_artifact():
9191
target_file = Path("/some/zipfile.zip")
9292
destination = "/tmp/null"
93-
with patch.object(Path, "unlink") as mock_unlink, patch("docat.utils.ZipFile") as mock_zip:
93+
with patch.object(Path, "unlink") as mock_unlink, patch("docat.docat.utils.ZipFile") as mock_zip:
9494
mock_zip_open = MagicMock()
9595
mock_zip.return_value.__enter__.return_value.extractall = mock_zip_open
9696

0 commit comments

Comments
 (0)