nextcloud_route_extractor/
route.rs1use 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}