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.

zj
Oct 26, 2021, 11:37 AM
RYCS2BYFBJYX4ORZZ7GRWV2LW6B7FUGZYKZQFELANAUEVMKTHJNAC

Dependencies

  • [2] GD7FCQ2K ui: 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] CMY6YHG3 auth: 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] I43RAQTR clean code
  • [5] NO2FEJLR tests: Reorganize the directory
  • [6] DSWQKJRH users: 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] TWIZ7QV4 db: 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] Z63HIZPS testing: 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] FS2NWBVN pijul: 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] S6TFYMRG routes: 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] JJQ4LMUM dependecy: Remove future No longer required, so cleaning it up right now.
  • [12] W2ZEVC64 pijul: 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] XFXPVFOS testing: 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] E4OBIIUB templates: 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] WSHUT37C pijul: 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.
  • [*] SZIYDOFD refactor: 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.
  • [*] W3M3C7CC Initial 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
    [5.1255][5.1255:1554]()
    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();
    [5.1255]
    [5.1554]
    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
    [2.1160]
    [2.1160]
    self.owner(db).await
    }
    pub async fn owner(&self, db: &State<Database>) -> Result<User> {
  • replacement in "src/models/projects.rs" at line 64
    [6.2265][6.2265:2327]()
    Ok(Repository::init_or_open(root, self.repo_path())?)
    [6.2265]
    [6.2327]
    Ok(Repository::init_or_open(self, root)?)
  • replacement in "src/models/projects.rs" at line 67
    [6.4043][6.2334:2382]()
    fn repo_path(&self) -> std::path::PathBuf {
    [6.4043]
    [6.2382]
    pub fn repo_path(&self) -> std::path::PathBuf {
  • replacement in "src/models/pijul/repositories.rs" at line 4
    [6.939][6.939:992]()
    use crate::models::pijul::changestores::Changestore;
    [6.939]
    [6.2596]
    use crate::models::{pijul::changestores::Changestore, users::User, projects::Project};
    use crate::database::Database;
  • replacement in "src/models/pijul/repositories.rs" at line 15
    [6.2705][6.2705:2729]()
    pub struct Repository {
    [6.2705]
    [6.2729]
    pub struct Repository<'r> {
  • edit in "src/models/pijul/repositories.rs" at line 18
    [6.2807]
    [6.2807]
    project: &'r Project,
  • replacement in "src/models/pijul/repositories.rs" at line 24
    [6.2888][6.2888:2906]()
    impl Repository {
    [6.2888]
    [6.2906]
    impl <'r>Repository<'r> {
  • replacement in "src/models/pijul/repositories.rs" at line 77
    [6.3299][6.3299:3346]()
    fn new(full_path: PathBuf) -> Repository {
    [6.3299]
    [6.3346]
    fn new(project: &Project, full_path: PathBuf) -> Repository {
  • edit in "src/models/pijul/repositories.rs" at line 79
    [6.3367]
    [6.2719]
    project: project,
  • replacement in "src/models/pijul/repositories.rs" at line 105
    [6.1308][6.4070:4215](),[6.4070][6.4070:4215]()
    pub fn init_or_open(root: &PathBuf, repo_path: PathBuf) -> Result<Self, anyhow::Error> {
    let repo = Self::new(root.join(repo_path));
    [6.1308]
    [6.4215]
    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
    [6.3851]
    [6.5177]
    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
    [6.3780][4.0:1]()
  • edit in "src/lib.rs" at line 10
    [6.993]
    [3.707]
    mod authz;
  • replacement in "src/controllers/pijul.rs" at line 60
    [6.1759][6.1759:1773]()
    // succeeded.
    [6.1759]
    [6.1773]
    // 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
    [6.1913]
    [6.1913]
    current_user: crate::models::users::User,
  • edit in "src/controllers/pijul.rs" at line 85
    [6.2469]
    [6.2469]
    if !crate::authz::can_apply_patch(db, &current_user, &repo).await {
    return rocket::http::Status::Unauthorized;
    }
  • file addition: authz (d--r------)
    [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
    }