gourami

[UNMAINTAINED] Activitypub server in Rust
Log | Files | Refs | README | LICENSE

commit 829bb64acc465268ab45bdab90f5e857d7881c0d
parent ec22e136bdb3c53221281f6bb7540465de94bcb9
Author: alex wennerberg <alex@alexwennerberg.com>
Date:   Fri, 17 Apr 2020 00:58:39 -0500

very basic read from db

Diffstat:
MCargo.toml | 2++
Mmigrations/2020-04-13-014917_initialize/up.sql | 2+-
Msrc/db/schema.rs | 2+-
Msrc/db/status.rs | 26+++++++++++++++++---------
Msrc/main.rs | 34++++++++++++++++++++++++++--------
Mtemplates/base.html | 6++++--
Mtemplates/timeline.html | 12+++++++-----
7 files changed, 58 insertions(+), 26 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml @@ -14,3 +14,5 @@ warp = "0.2" reqwest = "0.10" activitystreams = "0.4.0" chrono = "*" + +[dev-dependencies] diff --git a/migrations/2020-04-13-014917_initialize/up.sql b/migrations/2020-04-13-014917_initialize/up.sql @@ -15,7 +15,7 @@ CREATE TABLE notification ( -- media_attachments -CREATE TABLE status ( +CREATE TABLE note ( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, creator_id INTEGER, parent_id INTEGER, diff --git a/src/db/schema.rs b/src/db/schema.rs @@ -1,5 +1,5 @@ table! { - status (id) { + note (id) { id -> Integer, creator_id -> Integer, parent_id -> Nullable<Integer>, diff --git a/src/db/status.rs b/src/db/status.rs @@ -1,27 +1,35 @@ use chrono; -use activitystreams::object::streams::Note; +use activitystreams::object::streams; use diesel::sqlite::SqliteConnection; use diesel::deserialize::{Queryable}; -use super::schema::status; +use super::schema::note; +use super::schema::note::dsl::*; +use diesel::prelude::*; // Statuses are note activitystream object -#[derive(Queryable)] -pub struct Status { +#[derive(Queryable, Clone)] +pub struct Note { pub id: i32, pub creator_id: i32, pub parent_id: Option<i32>, pub content: String, - pub published: chrono::NaiveDateTime, + pub published: String, } -impl Status { - fn get_for_user(&self, conn: &SqliteConnection, user_id: &str) { +impl Note { + pub fn get_for_user(conn: &SqliteConnection, user_id: i32) -> Vec<Self> { + let results = note + .filter(creator_id.eq(user_id)) + .limit(5) + .load::<Self>(conn) + .expect("Error loading posts"); + results } } #[derive(Insertable, Clone)] -#[table_name = "status"] -pub struct StatusInput { +#[table_name = "note"] +pub struct NoteInput { pub id: i32, //unsigned? pub creator_id: i32, pub parent_id: Option<i32>, diff --git a/src/main.rs b/src/main.rs @@ -8,7 +8,9 @@ use warp::http::{self, header, StatusCode}; use warp::hyper::Body; use warp::reply::Response; use env_logger; -use db::status::Status; +use db::status::Note; +use diesel::prelude::*; +use diesel::sqlite::SqliteConnection; mod db; @@ -20,7 +22,7 @@ struct TimelineTemplate<'a>{ title: &'a str, username: &'a str, logged_in: bool, - statuses: Vec<&'a Status> + notes: Vec<Note> } // impl default @@ -31,7 +33,7 @@ struct NotificationTemplate<'a>{ name: &'a str, } -pub fn reply<T: askama::Template>(t: &T) -> Response { +pub fn render_template<T: askama::Template>(t: &T) -> Response { match t.render() { Ok(body) => http::Response::builder() .status(StatusCode::OK) @@ -63,28 +65,44 @@ fn outbox() { // ActivityPub inbox fn inbox() { } - #[tokio::main] async fn main() { env_logger::init(); + let notifications = warp::path("notifications"); + + // How does this interact with tokio? who knows! + // let url = ::std::env::var("DATABASE_URL").unwrap(); + // let conn = SqliteConnection::establish(&url).unwrap(); let test = warp::path("test").map(|| "Hello world"); + // post // user // default page -- timeline let home = warp::path::end() - .map(|| reply(&TimelineTemplate{ + .map(|| render_template(&TimelineTemplate{ page: "timeline", logged_in: true, - statuses: vec![], + notes: Note::get_for_user(&SqliteConnection::establish("sample.db").unwrap(), 1), username: "alex", title: "gourami"})); let static_files = warp::path("static") .and(warp::fs::dir("./static")); - let routes = warp::get().and(home.or(test).or(static_files)); + // TODO set content length limit + // TODO redirect via redirect in request + // TODO secure against xss + let create_note = warp::path("create_note") + .map(|| warp::redirect(warp::http::Uri::from_static("/"))); + + // catch all for any other paths + let not_found = warp::any().map(|| "404 not found"); + + let routes = warp::get().and( + home.or(test).or(static_files).or(not_found)) + .or(warp::post().and(create_note)); warp::serve(routes) .run(([127, 0, 0, 1], 3030)) .await; -} + } diff --git a/templates/base.html b/templates/base.html @@ -12,10 +12,12 @@ <div class="col-sm"> <div class="title">{{title}}/{{page}}</div> </div> - <div class="col-sm text-center">t n</div> + <div class="col-sm text-center"> + <a href="/">t</a> <a href="/test">n</a> + </div> <div class="col-sm text-right"> {% if logged_in %} - {{username}} + <a href="/user/{{username}}">{{username}}</a> {% else %} logged out {% endif %} diff --git a/templates/timeline.html b/templates/timeline.html @@ -2,15 +2,17 @@ {% block content %} <div class="container"> -<form method="POST"> -<textarea id="status-input" rows=3 placeholder="status"></textarea> +<form action="/create_note" method="POST"> +<textarea id="note-input" rows=3 placeholder="note"></textarea> <br> -<button id="post">post</button> +<button id="post">create note</button> </form> +{% for note in notes %} <div class="row"> - <div class="status"> - HL->post_id timestamp | user_id: post content delete button + <div class="note"> + <a href="/note/{{note.id}}">#{{note.id}}</a> {{note.published}} | {{note.content}} <a href=/delete_note/{{note.id}}>x</a> </div> </div> +{% endfor %} </div> {% endblock %}