refactor peach-web routes #1

Closed
opened 2021-10-25 09:49:08 +00:00 by notplants · 7 comments
Owner

** copying this issue over from github, to continue the discussion here (originally created by @glyph)

I'd like to refactor our web routes for better separation of concerns and logical consistency. We previously had profile, peers and messages as top-level routes but I think a forward-looking strategy is to move them under a /ssb route. That will allow us to neatly support other protocols in the future (for example, we could add /p2panda and then have /p2panda/profile etc.). Most of the other routes then end up being grouped into /settings and /status.

What do you think of the structure I've outlined?

Top-level Routes

/
/help
/scuttlebutt
/settings
/status

Scuttlebutt

/scuttlebutt/profile
/scuttlebutt/peers
/scuttlebutt/messages

Settings

/settings/network
/settings/network/ap/activate
/settings/network/dns
/settings/network/wifi
/settings/network/wifi/activate
/settings/network/wifi/add
/settings/network/wifi/connect
/settings/network/wifi/disconnect
/settings/network/wifi/forget
/settings/network/wifi/modify
/settings/network/wifi/usage
/settings/network/wifi/usage/reset

/settings/admin
/settings/admin/change_password
/settings/admin/reset_password
/settings/admin/send_password_reset
/settings/admin/power
/settings/admin/power/reboot
/settings/admin/power/shutdown

/settings/scuttlebutt

Status

/status/config
/status/device
/status/display
/status/dns
/status/network
/status/scuttlebutt

** copying this issue over from github, to continue the discussion here (originally created by @glyph) I'd like to refactor our web routes for better separation of concerns and logical consistency. We previously had `profile`, `peers` and `messages` as top-level routes but I think a forward-looking strategy is to move them under a `/ssb` route. That will allow us to neatly support other protocols in the future (for example, we could add `/p2panda` and then have `/p2panda/profile` etc.). Most of the other routes then end up being grouped into `/settings` and `/status`. What do you think of the structure I've outlined? # Top-level Routes / /help /scuttlebutt /settings /status # Scuttlebutt /scuttlebutt/profile /scuttlebutt/peers /scuttlebutt/messages # Settings /settings/network /settings/network/ap/activate /settings/network/dns /settings/network/wifi /settings/network/wifi/activate /settings/network/wifi/add /settings/network/wifi/connect /settings/network/wifi/disconnect /settings/network/wifi/forget /settings/network/wifi/modify /settings/network/wifi/usage /settings/network/wifi/usage/reset /settings/admin /settings/admin/change_password /settings/admin/reset_password /settings/admin/send_password_reset /settings/admin/power /settings/admin/power/reboot /settings/admin/power/shutdown /settings/scuttlebutt # Status /status/config /status/device /status/display /status/dns /status/network /status/scuttlebutt
Author
Owner

@glyph I think this route structure sounds good.

during the summer we were also having a converation about refactoring the peach-web code to follow a pattern more similar to flask blueprints, to keep the files from getting super big and make it easier to quickly add routes. I don't think we ever got around to fully looking into that. but that also woudn't conflict with this refactor at all... in fact in the blueprints model, one could even imagine each of these first parts of the path, to possibly be a blueprint

@glyph I think this route structure sounds good. during the summer we were also having a converation about refactoring the peach-web code to follow a pattern more similar to flask blueprints, to keep the files from getting super big and make it easier to quickly add routes. I don't think we ever got around to fully looking into that. but that also woudn't conflict with this refactor at all... in fact in the blueprints model, one could even imagine each of these first parts of the path, to possibly be a blueprint
glyph added the
refactor
label 2021-10-25 09:52:04 +00:00
Owner

@notplants

Oh yes, I'd completely forgotten about that! I'll look at some Flask blueprint resources to refresh my memory.

@notplants Oh yes, I'd completely forgotten about that! I'll look at some Flask blueprint resources to refresh my memory.
Owner

OK, I think I'm starting to get my head around this reorganisation. Here's one suggested structure to get the discussion ball rolling:

I believe this type of arrangement could be called a Functional structure.

We keep all the templates in templates, as they are now, but we group them into subdirectories. You have already started this pattern with templates/admin, templates/password and templates/snippets. The next question is: how to group the templates? I would be tempted to organise them according to the UI, ie:

templates/profile
templates/settings
etc.

I think static assets can stay where they are for now. We currently have static/css, static/icons, static/images and static/js.

Then we have all of the Rust code, currently organised between src/routes.rs, src/context.rs, src/json_api.rs etc. I suggest we bundle these into src/blueprints or (probably more inline with Rocket lingo) src/routes, and then have a subdirectory corresponding to each area of the UI:

src/routes/scuttlebutt
src/routes/settings
src/routes/status
etc.

The settings subdirectory would contain the following:

src/routes/settings/network.rs
src/routes/settings/sbot.rs
src/routes/settings/dyn_dns.rs

network.rs would contain the context object builders, HTML request handlers and JSON request handlers; all the Rust code required to interact with network settings.

The path / URL for each route in a blueprint will be a relative path. This can then be prepended with the appropriate prefix in src/lib.rs using the .mount() Rocket function. Here's a simple code-snippet example:

#[get("/")]
fn home() -> Template {
    let mut context = Context::new();
    context.insert("page_title", "home");
    Template::render("home", context.into_json())
}

#[get("/wifi/add")]
pub fn wifi_add() -> &'static str {
    "this will be called by /network/wifi/add"
}

#[get("/wifi/usage")]
pub fn wifi_usage() -> &'static str {
    "this will be called by /network/wifi/usage"
}

#[get("/peers/followers")]
pub fn followers() -> &'static str {
    "this will be called by /peers/followers"
}

#[launch]
fn rocket() -> _ {
    env_logger::init();

    info!("Launching Rocket server.");
    rocket::build()
        .mount("/", routes![home])
        .mount("/", FileServer::from(relative!("static")))
        .mount("/network", routes![wifi_add, wifi_usage])
        .mount("/scuttlebutt", routes![followers])
        .attach(Template::fairing())
}
OK, I think I'm starting to get my head around this reorganisation. Here's one suggested structure to get the discussion ball rolling: I believe this type of arrangement could be called a [Functional structure](https://exploreflask.com/en/latest/blueprints.html#functional-structure). We keep all the templates in `templates`, as they are now, but we group them into subdirectories. You have already started this pattern with `templates/admin`, `templates/password` and `templates/snippets`. The next question is: how to group the templates? I would be tempted to organise them according to the UI, ie: `templates/profile` `templates/settings` etc. I think `static` assets can stay where they are for now. We currently have `static/css`, `static/icons`, `static/images` and `static/js`. Then we have all of the Rust code, currently organised between `src/routes.rs`, `src/context.rs`, `src/json_api.rs` etc. I suggest we bundle these into `src/blueprints` or (probably more inline with Rocket lingo) `src/routes`, and then have a subdirectory corresponding to each area of the UI: `src/routes/scuttlebutt` `src/routes/settings` `src/routes/status` etc. The `settings` subdirectory would contain the following: `src/routes/settings/network.rs` `src/routes/settings/sbot.rs` `src/routes/settings/dyn_dns.rs` `network.rs` would contain the context object builders, HTML request handlers and JSON request handlers; all the Rust code required to interact with network settings. The path / URL for each route in a blueprint will be a relative path. This can then be prepended with the appropriate prefix in `src/lib.rs` using the `.mount()` Rocket function. Here's a simple code-snippet example: ```rust #[get("/")] fn home() -> Template { let mut context = Context::new(); context.insert("page_title", "home"); Template::render("home", context.into_json()) } #[get("/wifi/add")] pub fn wifi_add() -> &'static str { "this will be called by /network/wifi/add" } #[get("/wifi/usage")] pub fn wifi_usage() -> &'static str { "this will be called by /network/wifi/usage" } #[get("/peers/followers")] pub fn followers() -> &'static str { "this will be called by /peers/followers" } #[launch] fn rocket() -> _ { env_logger::init(); info!("Launching Rocket server."); rocket::build() .mount("/", routes![home]) .mount("/", FileServer::from(relative!("static"))) .mount("/network", routes![wifi_add, wifi_usage]) .mount("/scuttlebutt", routes![followers]) .attach(Template::fairing()) } ```
Author
Owner

@glyph I will make a short reply, because I agree and don't have much to add. This is also what I was thinking from my browsing around repos.

This is also what they do in the plume repo you linked,
for example if you go to line 386 in this file https://github.com/Plume-org/Plume/blob/main/src/routes/user.rs

you can see where they define a few functions, and a data structure,
and then use them in the route directly afterwards.

I like that this means editing fewer files to add a route,
and then we can additionaly have a common or utils folder, where we define things that get used by multiple routes... I imagine some of these common functions may even just go in peach-lib

@glyph I will make a short reply, because I agree and don't have much to add. This is also what I was thinking from my browsing around repos. This is also what they do in the plume repo you linked, for example if you go to line 386 in this file https://github.com/Plume-org/Plume/blob/main/src/routes/user.rs you can see where they define a few functions, and a data structure, and then use them in the route directly afterwards. I like that this means editing fewer files to add a route, and then we can additionaly have a common or utils folder, where we define things that get used by multiple routes... I imagine some of these common functions may even just go in peach-lib
Author
Owner

with subdirectories,
in both templates
and in src/routes,

could also consider not having a strict rule that you "need" a subdirectory.

if there is a natural grouping, can put things together into a subdirectory,
e.g.

src/routes/scuttlebutt
src/routes/settings
src/routes/status

but if it would be a situation where the subdirectory would just contain one file,
then it could exist as a single file at the "root" level
e.g. maybe, not_found.html.tera

then over time we can kind of group things and re-group things in an organic way

with subdirectories, in both templates and in src/routes, could also consider not having a strict rule that you "need" a subdirectory. if there is a natural grouping, can put things together into a subdirectory, e.g. ``` src/routes/scuttlebutt src/routes/settings src/routes/status ``` but if it would be a situation where the subdirectory would just contain one file, then it could exist as a single file at the "root" level e.g. maybe, not_found.html.tera then over time we can kind of group things and re-group things in an organic way
Owner

Awesome, that was easy :)

then we can additionaly have a common or utils folder, where we define things that get used by multiple routes... I imagine some of these common functions may even just go in peach-lib

+1

could also consider not having a strict rule that you "need" a subdirectory.

This sounds like a healthy degree of flexibility to me. I'm down.

Awesome, that was easy :) > then we can additionaly have a common or utils folder, where we define things that get used by multiple routes... I imagine some of these common functions may even just go in peach-lib +1 > could also consider not having a strict rule that you "need" a subdirectory. This sounds like a healthy degree of flexibility to me. I'm down.
Owner

Implemented in PR#28.

Implemented in [PR#28](https://git.coopcloud.tech/PeachCloud/peach-workspace/pulls/28).
glyph closed this issue 2021-11-16 07:46:18 +00:00
Sign in to join this conversation.
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: PeachCloud/peach-workspace#1
No description provided.