feat: improve homepage:sys protocol to add capabilities for setting system stylesheet and removing other apps' homepage icons!

This commit is contained in:
dr-frmr 2024-11-21 17:20:05 -05:00
parent 191cb5b6fd
commit a3acea3fbd
No known key found for this signature in database
11 changed files with 85 additions and 25 deletions

2
Cargo.lock generated
View File

@ -3136,7 +3136,7 @@ dependencies = [
[[package]]
name = "homepage"
version = "0.1.1"
version = "0.1.2"
dependencies = [
"anyhow",
"bincode",

View File

@ -305,7 +305,7 @@ fn serve_paths(
}
Method::DELETE => {
// uninstall an app
crate::utils::uninstall(state, &package_id)?;
crate::utils::uninstall(our, state, &package_id)?;
println!("successfully uninstalled {:?}", package_id);
Ok((
StatusCode::NO_CONTENT,

View File

@ -283,7 +283,7 @@ fn handle_local_request(
None,
),
LocalRequest::Uninstall(package_id) => (
match utils::uninstall(state, &package_id.clone().to_process_lib()) {
match utils::uninstall(our, state, &package_id.clone().to_process_lib()) {
Ok(()) => {
println!(
"successfully uninstalled package: {:?}",

View File

@ -8,8 +8,8 @@ use {
VFS_TIMEOUT,
},
kinode_process_lib::{
get_blob, kernel_types as kt, println, vfs, Address, LazyLoadBlob, PackageId, ProcessId,
Request,
get_blob, kernel_types as kt, println, vfs, Address, Capability, LazyLoadBlob, PackageId,
ProcessId, Request,
},
std::collections::{HashMap, HashSet},
};
@ -404,7 +404,7 @@ pub fn install(
/// given a `PackageId`, read its manifest, kill all processes declared in it,
/// then remove its drive in the virtual filesystem.
pub fn uninstall(state: &mut State, package_id: &PackageId) -> anyhow::Result<()> {
pub fn uninstall(our: &Address, state: &mut State, package_id: &PackageId) -> anyhow::Result<()> {
if !state.packages.contains_key(package_id) {
return Err(anyhow::anyhow!("package not found"));
}
@ -426,12 +426,29 @@ pub fn uninstall(state: &mut State, package_id: &PackageId) -> anyhow::Result<()
let manifest = serde_json::from_slice::<Vec<kt::PackageManifestEntry>>(&blob.bytes)?;
// reading from the package manifest, kill every process named
// *and* remove it from the homepage!
for entry in &manifest {
kernel_request(kt::KernelCommand::KillProcess(ProcessId::new(
let process_id = ProcessId::new(
Some(&entry.process_name),
package_id.package(),
package_id.publisher(),
)))
);
kernel_request(kt::KernelCommand::KillProcess(process_id.clone())).send()?;
// we have a unique capability that allows this, which we must attach
Request::to(("our", "homepage", "homepage", "sys"))
.body(
serde_json::json!({
"RemoveOther": process_id,
})
.to_string()
.as_bytes(),
)
.capabilities(vec![Capability::new(
Address::new(&our.node, ("homepage", "homepage", "sys")),
"\"RemoveOther\"".to_string(),
)])
.send()?;
}

View File

@ -65,6 +65,10 @@
"terminal:terminal:sys",
"filesystem:distro:sys",
"homepage:homepage:sys",
{
"process": "homepage:homepage:sys",
"params": "RemoveOther"
},
"http_server:distro:sys",
"http_client:distro:sys",
"net:distro:sys",

View File

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "addr2line"
@ -1248,7 +1248,7 @@ dependencies = [
[[package]]
name = "homepage"
version = "0.1.1"
version = "0.1.2"
dependencies = [
"anyhow",
"bincode",

View File

@ -1,4 +1,9 @@
interface homepage {
enum capability {
remove-other,
set-stylesheet,
}
/// The request format to add or remove an app from the homepage. You must have messaging
/// access to `homepage:homepage:sys` in order to perform this. Serialize using serde_json.
variant request {
@ -6,9 +11,15 @@ interface homepage {
/// the path will automatically have the process_id prepended.
/// the icon is a base64 encoded image.
add(add-request),
/// remove ourself from homepage (message source will be item removed)
remove,
/// ONLY settings:settings:sys may call this request
/// (this is checked in-code)
/// remove another app from homepage
/// using this requires RemoveOther capability
/// app store uses this to remove apps on uninstall
remove-other(string),
/// set the stylesheet for the homepage
/// using this requires SetStylesheet capability
/// settings:settings:sys uses this to set the stylesheet
set-stylesheet(string),
}
@ -20,7 +31,7 @@ interface homepage {
}
}
world homepage-sys-v0 {
world homepage-sys-v1 {
import homepage;
include process-v0;
}

View File

@ -1,6 +1,6 @@
[package]
name = "homepage"
version = "0.1.1"
version = "0.1.2"
edition = "2021"
[features]

View File

@ -1,6 +1,7 @@
use crate::kinode::process::homepage::{AddRequest, Request as HomepageRequest};
use crate::kinode::process::homepage;
use kinode_process_lib::{
await_message, call_init, get_blob, http, http::server, println, Address, LazyLoadBlob,
await_message, call_init, get_blob, http, http::server, println, Address, Capability,
LazyLoadBlob,
};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
@ -32,7 +33,7 @@ type PersistedAppOrder = HashMap<String, u32>;
wit_bindgen::generate!({
path: "target/wit",
world: "homepage-sys-v0",
world: "homepage-sys-v1",
generate_unused_types: true,
additional_derives: [serde::Deserialize, serde::Serialize],
});
@ -266,9 +267,9 @@ fn init(our: Address) {
} else {
// handle messages to add or remove an app from the homepage.
// they must have messaging access to us in order to perform this.
if let Ok(request) = serde_json::from_slice::<HomepageRequest>(message.body()) {
if let Ok(request) = serde_json::from_slice::<homepage::Request>(message.body()) {
match request {
HomepageRequest::Add(AddRequest {
homepage::Request::Add(homepage::AddRequest {
label,
icon,
path,
@ -302,16 +303,34 @@ fn init(our: Address) {
},
);
}
HomepageRequest::Remove => {
homepage::Request::Remove => {
let id = message.source().process.to_string();
app_data.remove(&id);
persisted_app_order.remove(&id);
}
HomepageRequest::SetStylesheet(new_stylesheet_string) => {
// ONLY settings:settings:sys may call this request
if message.source().process != "settings:settings:sys" {
homepage::Request::RemoveOther(id) => {
// caps check
let required_capability = Capability::new(
&our,
serde_json::to_string(&homepage::Capability::RemoveOther).unwrap(),
);
if !message.capabilities().contains(&required_capability) {
continue;
}
// end caps check
app_data.remove(&id);
persisted_app_order.remove(&id);
}
homepage::Request::SetStylesheet(new_stylesheet_string) => {
// caps check
let required_capability = Capability::new(
&our,
serde_json::to_string(&homepage::Capability::SetStylesheet).unwrap(),
);
if !message.capabilities().contains(&required_capability) {
continue;
}
// end caps check
kinode_process_lib::vfs::File {
path: "/homepage:sys/pkg/persisted-kinode.css".to_string(),
timeout: 5,

View File

@ -13,6 +13,10 @@
}
},
"homepage:homepage:sys",
{
"process": "homepage:homepage:sys",
"params": "SetStylesheet"
},
"http_server:distro:sys",
"kernel:distro:sys",
"net:distro:sys",

View File

@ -1,6 +1,7 @@
use kinode_process_lib::{
await_message, call_init, eth, get_blob, homepage, http, kernel_types, net, println, Address,
LazyLoadBlob, Message, NodeId, ProcessId, Request, Response, SendError, SendErrorKind,
Capability, LazyLoadBlob, Message, NodeId, ProcessId, Request, Response, SendError,
SendErrorKind,
};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
@ -429,6 +430,10 @@ fn handle_settings_request(
.to_string()
.as_bytes(),
)
.capabilities(vec![Capability::new(
Address::new(&state.our.node, ("homepage", "homepage", "sys")),
"\"SetStylesheet\"".to_string(),
)])
.send()
.unwrap();
state.stylesheet = Some(stylesheet);