Skip to content

Commit

Permalink
Merge pull request #12 from tucked/admin
Browse files Browse the repository at this point in the history
Add paste info and remove commands to the CLI
  • Loading branch information
tucked authored May 4, 2023
2 parents d5a4b01 + 5f4d029 commit 63b0a68
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 2 deletions.
56 changes: 56 additions & 0 deletions pbnh/cli.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import hashlib

import click
from flask import Blueprint

Expand All @@ -15,3 +17,57 @@ def db() -> None:
def init() -> None:
pbnh.db.init_db()
click.echo("initialized the database successfully")


@blueprint.cli.group() # type: ignore
@click.pass_context
def paste(ctx: click.Context) -> None:
ctx.obj.data["paster"] = ctx.with_resource(pbnh.db.paster_context())


@paste.command() # type: ignore
@click.option(
"--show-data/--no-show-data",
help="whether to show paste data",
default=False,
show_default=True,
)
@click.argument("hashids", type=str, nargs=-1)
@click.pass_context
def info(ctx: click.Context, show_data: bool, hashids: tuple[str]) -> None:
"""Get info on pastes."""
for multiple_hashids, hashid in enumerate(hashids):
if multiple_hashids:
click.echo("=" * 80)
paste = ctx.obj.data["paster"].query(hashid=hashid)
if paste is None:
click.echo(f"{hashid} not found")
continue
value = paste["hashid"]
hashid = hashlib.sha1(paste["data"], usedforsecurity=False).hexdigest()
if value != hashid:
value += click.style(
f" (WARNING: expected {hashid})",
fg="yellow",
)
for column, value in (
[("hashid", value)]
+ [
(column, value)
for column, value in paste.items()
if column not in {"data", "hashid"}
]
+ [("data", paste["data"] if show_data else f"({len(value)} bytes)")]
):
click.echo(f"{column + ':':>15} {value}")


@paste.command() # type: ignore
@click.argument("hashids", type=str, nargs=-1)
@click.pass_context
def remove(ctx: click.Context, hashids: tuple[str]) -> None:
"""Remove pastes."""
for hashid in hashids:
removed = ctx.obj.data["paster"].delete(hashid=hashid)
message = "removed" if removed else "not found"
click.echo(f"{hashid} {message}")
4 changes: 3 additions & 1 deletion pbnh/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,13 @@ def query(self, *, hashid: str) -> dict[str, Any] | None:
}
return None

def delete(self, *, hashid: str) -> None:
def delete(self, *, hashid: str) -> bool:
with self._session.begin():
result = self._query(hashid=hashid)
if result:
self._session.delete(result)
return True
return False


def _get_engine() -> Engine:
Expand Down
57 changes: 57 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
import contextlib
import unittest.mock

import pytest


def fake_paster_context_factory(hashid, data):
@contextlib.contextmanager
def fake_paster_context():
mock = unittest.mock.Mock()
mock.query.return_value = {
"hashid": hashid,
"data": data,
}
yield mock

return fake_paster_context


@pytest.fixture
def test_cli_runner(app):
"""A test runner for the app's Click commands."""
Expand All @@ -18,3 +34,44 @@ def fake_init_db():
result = test_cli_runner.invoke(args=["db", "init"])
assert init_db_called
assert "initialized" in result.output


def test_cli_paste_info(test_cli_runner, monkeypatch):
"""Pastes can be looked up from the CLI."""
data = b"Example Data"
hashid = "3eb000f2018951656c8c27c5dc2a37445d029128"
monkeypatch.setattr(
"pbnh.db.paster_context", fake_paster_context_factory(hashid, data)
)
result = test_cli_runner.invoke(args=["paste", "info", hashid, hashid])
assert hashid in result.output
assert "data" in result.output


def test_cli_paste_info_not_found(app, test_cli_runner):
"""Looking up a nonexistent paste is handled gracefully."""
hashid = "abc123"
with app.app_context():
result = test_cli_runner.invoke(args=["paste", "info", hashid])
assert hashid in result.output
assert "not found" in result.output


def test_cli_paste_info_hash_mismatch(test_cli_runner, monkeypatch):
"""A warning is emitted if a paste hashid doesn't match the data."""
data = b"Example Data"
hashid = "hash-does-not-match"
monkeypatch.setattr(
"pbnh.db.paster_context", fake_paster_context_factory(hashid, data)
)
result = test_cli_runner.invoke(args=["paste", "info", hashid])
assert hashid in result.output
assert "WARNING" in result.output


def test_cli_paste_remove(app, test_cli_runner):
"""Pastes can be removed from the cLI."""
hashid = "abc123"
with app.app_context():
result = test_cli_runner.invoke(args=["paste", "remove", hashid])
assert hashid in result.output
2 changes: 1 addition & 1 deletion tests/test_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,4 @@ def test_delete(paster):

def test_delete_nonexistent(paster):
with paster as p:
assert p.delete(hashid="nonexistent") is None
assert not p.delete(hashid="nonexistent")

0 comments on commit 63b0a68

Please sign in to comment.