nextcloud_route_extractor/
route.rs

1use php_literal_parser::Value;
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4use std::fmt::{Debug, Display, Formatter};
5
6#[derive(Default, Debug, Clone, Deserialize, Serialize, PartialEq)]
7#[allow(dead_code)]
8pub struct AppRoutes {
9    #[serde(default)]
10    pub routes: Vec<Route>,
11    #[serde(default)]
12    pub ocs: Vec<Route>,
13}
14
15#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Default)]
16#[allow(dead_code)]
17pub struct Route {
18    #[serde(default)]
19    pub root: Option<String>,
20    pub url: String,
21    pub name: String,
22    #[serde(default)]
23    pub verb: Verb,
24    #[serde(default)]
25    pub requirements: HashMap<String, Value>,
26    #[serde(default)]
27    pub postfix: Option<String>,
28    #[serde(default)]
29    pub defaults: HashMap<String, Value>,
30}
31
32const ROOT_URL_APPS: &[&str] = &[
33    "cloud_federation_api",
34    "core",
35    "files_sharing",
36    "files",
37    "profile",
38    "settings",
39    "spreed",
40];
41
42impl Route {
43    pub fn frontpage_url(&self, app: &str) -> String {
44        let custom_root = app == "core" || (self.root.is_some() && ROOT_URL_APPS.contains(&app));
45        if custom_root {
46            format!("{}{}", self.root.as_deref().unwrap_or_default(), self.url)
47        } else {
48            format!("/apps/{app}{}", self.url)
49        }
50    }
51
52    pub fn ocs_url(&self, app: &str) -> String {
53        let custom_root = app == "core" || self.root.is_some();
54        if custom_root {
55            format!("{}{}", self.root.as_deref().unwrap_or_default(), self.url)
56        } else {
57            format!("/apps/{app}{}", self.url)
58        }
59    }
60
61    pub fn id(&self, app: &str) -> String {
62        let (page, method) = self.name.split_once('#').unwrap_or_default();
63        format!(
64            "{app}.{page}.{method}{}",
65            self.postfix.as_deref().unwrap_or_default()
66        )
67    }
68}
69
70#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Deserialize, Serialize)]
71#[serde(rename_all = "UPPERCASE")]
72pub enum Verb {
73    #[default]
74    Get,
75    Post,
76    Put,
77    Delete,
78    Head,
79    Options,
80    Patch,
81}
82
83impl Verb {
84    pub fn as_str(&self) -> &'static str {
85        match self {
86            Verb::Get => "GET",
87            Verb::Post => "POST",
88            Verb::Put => "PUT",
89            Verb::Delete => "DELETE",
90            Verb::Head => "HEAD",
91            Verb::Options => "OPTIONS",
92            Verb::Patch => "PATCH",
93        }
94    }
95}
96
97impl Display for Verb {
98    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
99        write!(f, "{}", self.as_str())
100    }
101}