authz: Only repository owners can push changes Before all users could push changes to a repository. This was a shortcut which is changed now. For now only owners can push new changes to a repository. This isn't great either, as it doesn't allow for collaboration as of yet. However, it's a better default and allows nidobyte to be deployed on the internet soon after. As such this default has now been chosen, and will later be updated.
Dependencies
- [2]
GD7FCQ2Kui: Fix navigation issues To get the bare minimum working, this change adds some basic navigation to the applicaiton. It's far from perfect, but nonetheless, it's something. :) - [3]
CMY6YHG3auth: Allow HTTP basic auth for users This can be used soon to push data as a user from the terminal where the cookie isn't set like in the browser. - [4]
I43RAQTRclean code - [5]
NO2FEJLRtests: Reorganize the directory - [6]
DSWQKJRHusers: Introduce User guard for routes Rockets guards are very powerful to disallow users for certain routes. This far this wasn't implemented, and allowed no-one other than the first user to sign up. This change introduces the User guard and employs it for a few routes. The guard works by checking the encrypted cookie for the user_id, and perform a database lookup on it. - [7]
TWIZ7QV4db: Add interface to add a project Right now a project has a name, and an owner which is hardcoded to 1. This is because basically I'm speedrunning to implement push/pull of Pijul and then revisit to add depth to features and tests. Model code is now split into files properly too. - [8]
Z63HIZPStesting: Move tests to specific directory Tests I didn't really write until today, as I mostly didn't really know how to set it up. This is now partially mitigated, just by forcing myself to do it. There's a few problems still in the code; the database is shared with the dev application for instance. Though as a start I'll take it. - [9]
FS2NWBVNpijul: Start of push/pull work This change includes one API endpoint, .pijul. It allows for getting a channels remote ID. A lot of plumbing around repositories is added too, from init to opening pristine and actions like it. - [10]
S6TFYMRGroutes: Move pijul routes to controllers module As with the root routes, now the pijul routes are moved. The mounting of the routes is still done in main.rs though the controller module now collects them. This should DRY this code - [11]
JJQ4LMUMdependecy: Remove future No longer required, so cleaning it up right now. - [12]
W2ZEVC64pijul: HTTP push now works While missing Auth{n,z}, one can now push to the main channel. The patches are stored and normal Pijul command can be run in the repository on disk. - [13]
XFXPVFOStesting: Move tests to specific directory Tests I didn't really write until today, as I mostly didn't really know how to set it up. This is now partially mitigated, just by forcing myself to do it. There's a few problems still in the code; the database is shared with the dev application for instance. Though as a start I'll take it. - [14]
E4OBIIUBtemplates: Fix navigation mocks Cleans up the directory structure for templates and fixes the navigation bugs in the applications too. Includes a context! macro which is lifted from upstream, but is currently unreleased. When rocket_dyn_templates is updates, it could be DRY'ed out. - [15]
WSHUT37Cpijul: Pushes now work completely While still missing authn and authz, the flow of pushing now works. This enables validation of at least storing data. Later changes will show the data on the project page. - [*]
SZIYDOFDrefactor: Move User guard to the model The User model didn't have the FromRequest 'constructor' for the guard. This felt off. Now some Request knowledge leaks to the model, but still it seems better. - [*]
W3M3C7CCInitial commit This change includes a very small hello world application server written in Rust using Rocket.rs. Managing dependencies is done with Nix as that works well between Linux and Mac for me.
Change contents
- file addition: pijul_controller_tests.rs[6.17]
mod common;pub use common::*;use rocket::http::Status;#[tokio::test]async fn unauthenticated_apply_denied() {let client = common::testing_client().await;let db = rocket::State::get(&client.rocket()).expect("managed database");let project = common::project(db).await;let resp = client.post(format!("/{}/{}/.pijul?ABCD", project.owner(db).await.unwrap().name, project.name)).dispatch().await;assert_eq!(resp.status(), Status::NotFound);} - replacement in "tests/common/mod.rs" at line 13
use rand::Rng;const CHARSET: &[u8] = b"abcdefghijklmnopqrstuvwxyz0123456789";let mut rng = rand::thread_rng();let username: String = (0..12).map(|_| {let idx = rng.gen_range(0..CHARSET.len());CHARSET[idx] as char}).collect();let username = random_name(); - edit in "tests/common/mod.rs" at line 24[5.1739]
use nidobyte::models::projects;pub async fn project(db: &rocket::State<Database>) -> projects::Project {let owner = user(db).await;projects::create(db, owner.id, random_name()).await.unwrap()}use rand::Rng;fn random_name() -> String {const CHARSET: &[u8] = b"abcdefghijklmnopqrstuvwxyz0123456789";let mut rng = rand::thread_rng();(0..12) .map(|_| {let idx = rng.gen_range(0..CHARSET.len());CHARSET[idx] as char}).collect()} - edit in "src/models/users.rs" at line 118[17.1066]
impl PartialEq for User {fn eq(&self, other: &Self) -> bool {self.id == other.id}}impl Eq for User {} - edit in "src/models/projects.rs" at line 54
self.owner(db).await}pub async fn owner(&self, db: &State<Database>) -> Result<User> { - replacement in "src/models/projects.rs" at line 64
Ok(Repository::init_or_open(root, self.repo_path())?)Ok(Repository::init_or_open(self, root)?) - replacement in "src/models/projects.rs" at line 67
fn repo_path(&self) -> std::path::PathBuf {pub fn repo_path(&self) -> std::path::PathBuf { - replacement in "src/models/pijul/repositories.rs" at line 4
use crate::models::pijul::changestores::Changestore;use crate::models::{pijul::changestores::Changestore, users::User, projects::Project};use crate::database::Database; - replacement in "src/models/pijul/repositories.rs" at line 15
pub struct Repository {pub struct Repository<'r> { - edit in "src/models/pijul/repositories.rs" at line 18
project: &'r Project, - replacement in "src/models/pijul/repositories.rs" at line 24
impl Repository {impl <'r>Repository<'r> { - replacement in "src/models/pijul/repositories.rs" at line 77
fn new(full_path: PathBuf) -> Repository {fn new(project: &Project, full_path: PathBuf) -> Repository { - edit in "src/models/pijul/repositories.rs" at line 79
project: project, - replacement in "src/models/pijul/repositories.rs" at line 105
pub fn init_or_open(root: &PathBuf, repo_path: PathBuf) -> Result<Self, anyhow::Error> {let repo = Self::new(root.join(repo_path));pub fn init_or_open(project: &'r Project, root: &PathBuf) -> Result<Self, anyhow::Error> {let repo = Self::new(project, root.join(project.repo_path())); - edit in "src/models/pijul/repositories.rs" at line 163
pub async fn owner(&self, db: &rocket::State<Database>) -> anyhow::Result<User> {self.project.owner(db).await} - edit in "src/main.rs" at line 3
- edit in "src/lib.rs" at line 10
mod authz; - replacement in "src/controllers/pijul.rs" at line 60
// succeeded.// succeeded. When a user cannot be authenticated the status code is 404 to hide the existence of// the repository. - edit in "src/controllers/pijul.rs" at line 66
current_user: crate::models::users::User, - edit in "src/controllers/pijul.rs" at line 85
if !crate::authz::can_apply_patch(db, ¤t_user, &repo).await {return rocket::http::Status::Unauthorized;} - file addition: authz[18.179]
- file addition: mod.rs[0.2329]
use crate::models::{pijul::repositories::Repository, users::User};pub async fn can_apply_patch(db: &rocket::State<crate::database::Database>,user: &User,repo: &Repository<'_>,) -> bool {let owner = repo.owner(db).await;owner.is_ok() && owner.unwrap() == *user}