WIP
test / test (push) Failing after 38s
Details
test / test (push) Failing after 38s
Details
This commit is contained in:
parent
8d25de682a
commit
1b22ce6d22
27
README.md
27
README.md
|
@ -8,27 +8,10 @@ gleam test # Run the tests
|
|||
gleam shell # Run an Erlang shell
|
||||
```
|
||||
|
||||
## Flow
|
||||
|
||||
### Upload
|
||||
|
||||
take file upload
|
||||
-> get hash of file
|
||||
-> test against CSAM hash list
|
||||
-> generate UUID
|
||||
-> point UUID at hash of file
|
||||
-> save file if hash doesn't exist
|
||||
-> return UUID
|
||||
|
||||
### Download
|
||||
|
||||
take file UUID
|
||||
-> search for UUID in table and get hash
|
||||
-> return file if hash exists
|
||||
|
||||
## TODO
|
||||
|
||||
- [] Handle file upload
|
||||
- [] Handle file download
|
||||
- [] Testing against CSAM hash list
|
||||
- [] Logging IPs (up and down) of detected CSAM uploads
|
||||
- [X] Handle link GET
|
||||
- [X] Handle link POST
|
||||
- [] Handle file POST
|
||||
- [] Handle file GET
|
||||
- [] Web Frontend
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
import envoy
|
||||
import gleam/int
|
||||
import gleam/pgo
|
||||
import gleam/result.{unwrap}
|
||||
import wisp
|
||||
|
||||
pub type Context {
|
||||
Context(db: pgo.Connection, config: Config)
|
||||
}
|
||||
|
||||
pub type Config {
|
||||
Config(
|
||||
port: Int,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import app/config.{type Config}
|
||||
import app/web.{type Context}
|
||||
import app/config.{type Context}
|
||||
import app/web
|
||||
import app/web/file
|
||||
import app/web/link
|
||||
import app/web/root
|
||||
import wisp.{type Request, type Response}
|
||||
|
||||
pub fn handle_request(req: Request, config: Config) -> Response {
|
||||
use req: Request, ctx: Context <- web.middleware(req, config)
|
||||
pub fn handle_request(req: Request, ctx: Context) -> Response {
|
||||
use req: Request <- web.middleware(req)
|
||||
|
||||
case wisp.path_segments(req) {
|
||||
["f", ..] -> file.handle_request(req, ctx)
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import app/config.{type Config}
|
||||
import gleam/pgo
|
||||
import wisp.{type Request, type Response}
|
||||
|
||||
pub const html_head = "
|
||||
|
@ -18,27 +16,13 @@ pub const html_tail = "
|
|||
</html>
|
||||
"
|
||||
|
||||
pub type Context {
|
||||
Context(db: pgo.Connection, config: Config)
|
||||
}
|
||||
|
||||
pub fn middleware(
|
||||
req: Request,
|
||||
config: Config,
|
||||
handle_request: fn(Request, Context) -> Response,
|
||||
handle_request: fn(Request) -> Response,
|
||||
) -> Response {
|
||||
let req = wisp.method_override(req)
|
||||
use <- wisp.log_request(req)
|
||||
use <- wisp.rescue_crashes
|
||||
use req <- wisp.handle_head(req)
|
||||
let db =
|
||||
pgo.connect(
|
||||
pgo.Config(
|
||||
..pgo.default_config(),
|
||||
host: config.postgres_host,
|
||||
database: config.postgres_db,
|
||||
pool_size: config.postgres_pool_size,
|
||||
),
|
||||
)
|
||||
handle_request(req, Context(db, config))
|
||||
handle_request(req)
|
||||
}
|
||||
|
|
|
@ -1,43 +1,49 @@
|
|||
import app/web.{type Context}
|
||||
import app/config.{type Context}
|
||||
import gleam/dynamic
|
||||
import gleam/http.{Get, Post}
|
||||
import gleam/list
|
||||
import gleam/pgo
|
||||
import gleam/result
|
||||
import gleam/string
|
||||
import wisp.{type Request, type Response}
|
||||
|
||||
const schema = "
|
||||
CREATE TABLE IF NOT EXISTS `FileReference` (
|
||||
nanoid TEXT <<key>>
|
||||
PathID INT
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS `FilePath` (
|
||||
PathID INT <<key>>
|
||||
md5_hash BLOB
|
||||
banned BOOLEAN
|
||||
CREATE TABLE IF NOT EXISTS \"File\" (
|
||||
nanoid VARCHAR(21) PRIMARY KEY,
|
||||
md5_hash BYTEA
|
||||
);
|
||||
"
|
||||
|
||||
type File {
|
||||
Reference(md5_hash: BitArray, nanoid: String)
|
||||
Path(md5_hash: String, banned: Bool)
|
||||
pub type File {
|
||||
File(md5_hash: BitArray, nanoid: String)
|
||||
}
|
||||
|
||||
fn hash_to_path(hash: String) -> List(String) {
|
||||
pub fn prepare_database(ctx: Context) -> Result(Nil, pgo.QueryError) {
|
||||
pgo.execute(schema, ctx.db, [], dynamic.dynamic)
|
||||
|> result.map(fn(_) { Nil })
|
||||
}
|
||||
|
||||
pub fn hash_to_path(hash: String) -> List(String) {
|
||||
list.new()
|
||||
|> list.append([hash |> string.slice(0, 2)])
|
||||
|> list.append([hash |> string.slice(2, 2)])
|
||||
|> list.append([hash |> string.slice(4, { hash |> string.length } - 4)])
|
||||
}
|
||||
|
||||
pub fn handle_request(req: Request, ctx: Context) -> Response {
|
||||
todo
|
||||
}
|
||||
|
||||
fn serve_file(req, uuid: String) -> Response {
|
||||
fn handle_nano_id(req: Request, nano_id: String, ct: Context) -> Response {
|
||||
use <- wisp.require_method(req, Get)
|
||||
todo as "implement serve_file"
|
||||
}
|
||||
|
||||
fn receive_file(req: Request) -> Response {
|
||||
fn handle_root(req: Request, ctx: Context) -> Response {
|
||||
use <- wisp.require_method(req, Post)
|
||||
todo as "implement receive_file"
|
||||
}
|
||||
|
||||
pub fn handle_request(req: Request, ctx: Context) -> Response {
|
||||
case wisp.path_segments(req) {
|
||||
["f"] -> handle_root(req, ctx)
|
||||
["f", nano_id] -> handle_nano_id(req, nano_id, ctx)
|
||||
_ -> wisp.not_found()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import app/web.{type Context}
|
||||
import app/config.{type Context}
|
||||
import gleam/dynamic
|
||||
import gleam/http.{Get, Post}
|
||||
import gleam/int
|
||||
|
|
|
@ -1,14 +1,33 @@
|
|||
import app/config
|
||||
import app/config.{type Config, type Context, Context}
|
||||
import app/router
|
||||
import gleam/erlang/process
|
||||
import gleam/pgo
|
||||
import mist
|
||||
import wisp
|
||||
|
||||
pub fn main() {
|
||||
wisp.configure_logger()
|
||||
let config = config.load_config_from_env()
|
||||
fn with_context(config: Config, next: fn(Context) -> Nil) -> Nil {
|
||||
let db =
|
||||
pgo.connect(
|
||||
pgo.Config(
|
||||
..pgo.default_config(),
|
||||
host: config.postgres_host,
|
||||
database: config.postgres_db,
|
||||
pool_size: config.postgres_pool_size,
|
||||
),
|
||||
)
|
||||
let ctx = Context(db: db, config: config)
|
||||
|
||||
let entrypoint = router.handle_request(_, config)
|
||||
next(ctx)
|
||||
|
||||
ctx.db |> pgo.disconnect
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let config = config.load_config_from_env()
|
||||
use ctx: Context <- with_context(config)
|
||||
|
||||
wisp.configure_logger()
|
||||
let entrypoint = router.handle_request(_, ctx)
|
||||
let assert Ok(_) =
|
||||
wisp.mist_handler(entrypoint, config.secret_key_base)
|
||||
|> mist.new
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
import app/config.{type Context, Config, Context}
|
||||
import app/web/file
|
||||
import gleam/dynamic
|
||||
import gleam/option.{None, Some}
|
||||
import gleam/pgo
|
||||
import gleam/string
|
||||
import gleeunit/should
|
||||
|
||||
const test_config = Config(
|
||||
port: 8080,
|
||||
max_bytes: 52_428_800,
|
||||
url_root: "http://localhost",
|
||||
secret_key_base: "cDv6ikrODZKjKbwSBBwspXInc61MYpCzQ8My9gW2QpQg3Y3lT7IJ5RJlzRN5HZK0",
|
||||
postgres_db: "dumptruck",
|
||||
postgres_user: "dumptruck",
|
||||
postgres_password: "dumptruck",
|
||||
postgres_host: "localhost",
|
||||
postgres_pool_size: 15,
|
||||
postgres_port: 5432,
|
||||
)
|
||||
|
||||
fn with_context(testcase: fn(Context) -> t) -> t {
|
||||
let ctx =
|
||||
Context(
|
||||
db: pgo.Config(
|
||||
..pgo.default_config(),
|
||||
database: test_config.postgres_db,
|
||||
password: test_config.postgres_password |> Some,
|
||||
user: test_config.postgres_user,
|
||||
host: test_config.postgres_host,
|
||||
pool_size: test_config.postgres_pool_size,
|
||||
port: 5432,
|
||||
)
|
||||
|> pgo.connect,
|
||||
config: test_config,
|
||||
)
|
||||
|
||||
case file.prepare_database(ctx) {
|
||||
Ok(_) -> {
|
||||
let ret = testcase(ctx)
|
||||
|
||||
ctx.db |> pgo.disconnect
|
||||
|
||||
ret
|
||||
}
|
||||
Error(e) -> {
|
||||
e |> string.inspect |> panic
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn null_test() {
|
||||
use ctx <- with_context()
|
||||
|
||||
pgo.execute(
|
||||
"select $1",
|
||||
ctx.db,
|
||||
[pgo.null()],
|
||||
dynamic.element(0, dynamic.optional(dynamic.int)),
|
||||
)
|
||||
|> should.equal(Ok(pgo.Returned(count: 1, rows: [None])))
|
||||
}
|
||||
|
||||
pub fn hash_to_path_test() {
|
||||
"f7b478961451483b8c251c788750d5ef"
|
||||
|> file.hash_to_path
|
||||
|> should.equal(["f7", "b4", "78961451483b8c251c788750d5ef"])
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
import app/config.{Config}
|
||||
import app/web.{type Context, Context}
|
||||
import app/config.{type Context, Config, Context}
|
||||
import app/web/link.{Link}
|
||||
import gleam/dynamic
|
||||
import gleam/io
|
||||
import gleam/option.{None, Some}
|
||||
import gleam/pgo
|
||||
import gleam/result
|
||||
|
|
Loading…
Reference in New Issue