]>
Commit | Line | Data |
---|---|---|
dc7a5b34 | 1 | use anyhow::{bail, format_err, Error}; |
7b22fb25 | 2 | use serde_json::Value; |
7e13b2d6 | 3 | |
dc7a5b34 | 4 | use proxmox_router::{Permission, Router, RpcEnvironment}; |
6ef1b649 | 5 | use proxmox_schema::api; |
a2479cfa | 6 | |
8cc3760e | 7 | use pbs_api_types::{ |
dc7a5b34 | 8 | Authid, NODE_SCHEMA, PRIV_SYS_AUDIT, PRIV_SYS_MODIFY, SUBSCRIPTION_KEY_SCHEMA, |
8cc3760e DM |
9 | }; |
10 | ||
a2479cfa | 11 | use crate::tools; |
dc7a5b34 | 12 | use crate::tools::subscription::{self, SubscriptionInfo, SubscriptionStatus}; |
ba3d7e19 | 13 | use pbs_config::CachedUserInfo; |
7e13b2d6 | 14 | |
1bfc1efa | 15 | #[api( |
113c9b59 SR |
16 | input: { |
17 | properties: { | |
18 | node: { | |
19 | schema: NODE_SCHEMA, | |
20 | }, | |
7b22fb25 TL |
21 | force: { |
22 | description: "Always connect to server, even if information in cache is up to date.", | |
23 | type: bool, | |
24 | optional: true, | |
25 | default: false, | |
26 | }, | |
113c9b59 SR |
27 | }, |
28 | }, | |
7b22fb25 TL |
29 | protected: true, |
30 | access: { | |
31 | permission: &Permission::Privilege(&["system"], PRIV_SYS_MODIFY, false), | |
32 | }, | |
33 | )] | |
34 | /// Check and update subscription status. | |
dc7a5b34 | 35 | pub fn check_subscription(force: bool) -> Result<(), Error> { |
7b22fb25 TL |
36 | let info = match subscription::read_subscription() { |
37 | Err(err) => bail!("could not read subscription status: {}", err), | |
38 | Ok(Some(info)) => info, | |
39 | Ok(None) => return Ok(()), | |
40 | }; | |
41 | ||
42 | let server_id = tools::get_hardware_address()?; | |
43 | let key = if let Some(key) = info.key { | |
44 | // always update apt auth if we have a key to ensure user can access enterprise repo | |
45 | subscription::update_apt_auth(Some(key.to_owned()), Some(server_id.to_owned()))?; | |
46 | key | |
47 | } else { | |
48 | String::new() | |
49 | }; | |
50 | ||
51 | if !force && info.status == SubscriptionStatus::ACTIVE { | |
6ef1b649 | 52 | let age = proxmox_time::epoch_i64() - info.checktime.unwrap_or(i64::MAX); |
7b22fb25 TL |
53 | if age < subscription::MAX_LOCAL_KEY_AGE { |
54 | return Ok(()); | |
55 | } | |
56 | } | |
57 | ||
58 | let info = subscription::check_subscription(key, server_id)?; | |
59 | ||
60 | subscription::write_subscription(info) | |
61 | .map_err(|e| format_err!("Error writing updated subscription status - {}", e))?; | |
62 | ||
63 | Ok(()) | |
64 | } | |
65 | ||
66 | #[api( | |
67 | input: { | |
1bfc1efa | 68 | properties: { |
7b22fb25 TL |
69 | node: { |
70 | schema: NODE_SCHEMA, | |
1bfc1efa DM |
71 | }, |
72 | }, | |
73 | }, | |
9b93c620 | 74 | returns: { type: SubscriptionInfo }, |
1bfc1efa | 75 | access: { |
9626c286 | 76 | permission: &Permission::Anybody, |
1bfc1efa DM |
77 | }, |
78 | )] | |
79 | /// Read subscription info. | |
652506e6 | 80 | pub fn get_subscription( |
9626c286 FG |
81 | _param: Value, |
82 | rpcenv: &mut dyn RpcEnvironment, | |
7b22fb25 TL |
83 | ) -> Result<SubscriptionInfo, Error> { |
84 | let url = "https://www.proxmox.com/en/proxmox-backup-server/pricing"; | |
85 | ||
86 | let info = match subscription::read_subscription() { | |
87 | Err(err) => bail!("could not read subscription status: {}", err), | |
88 | Ok(Some(info)) => info, | |
89 | Ok(None) => SubscriptionInfo { | |
90 | status: SubscriptionStatus::NOTFOUND, | |
91 | message: Some("There is no subscription key".into()), | |
92 | serverid: Some(tools::get_hardware_address()?), | |
dc7a5b34 | 93 | url: Some(url.into()), |
7b22fb25 TL |
94 | ..Default::default() |
95 | }, | |
96 | }; | |
97 | ||
e6dc35ac | 98 | let auth_id: Authid = rpcenv.get_auth_id().unwrap().parse()?; |
9626c286 | 99 | let user_info = CachedUserInfo::new()?; |
e6dc35ac | 100 | let user_privs = user_info.lookup_privs(&auth_id, &[]); |
7b22fb25 TL |
101 | |
102 | if (user_privs & PRIV_SYS_AUDIT) == 0 { | |
103 | // not enough privileges for full state | |
104 | return Ok(SubscriptionInfo { | |
105 | status: info.status, | |
106 | message: info.message, | |
107 | url: info.url, | |
108 | ..Default::default() | |
109 | }); | |
9626c286 | 110 | }; |
7e13b2d6 | 111 | |
7b22fb25 TL |
112 | Ok(info) |
113 | } | |
114 | ||
115 | #[api( | |
116 | input: { | |
117 | properties: { | |
118 | node: { | |
119 | schema: NODE_SCHEMA, | |
120 | }, | |
121 | key: { | |
926d2531 | 122 | schema: SUBSCRIPTION_KEY_SCHEMA, |
7b22fb25 TL |
123 | }, |
124 | }, | |
125 | }, | |
126 | protected: true, | |
127 | access: { | |
128 | permission: &Permission::Privilege(&["system"], PRIV_SYS_MODIFY, false), | |
129 | }, | |
130 | )] | |
131 | /// Set a subscription key and check it. | |
dc7a5b34 | 132 | pub fn set_subscription(key: String) -> Result<(), Error> { |
7b22fb25 TL |
133 | let server_id = tools::get_hardware_address()?; |
134 | ||
44288184 | 135 | let info = subscription::check_subscription(key, server_id)?; |
7b22fb25 TL |
136 | |
137 | subscription::write_subscription(info) | |
138 | .map_err(|e| format_err!("Error writing subscription status - {}", e))?; | |
139 | ||
140 | Ok(()) | |
141 | } | |
142 | ||
143 | #[api( | |
144 | input: { | |
145 | properties: { | |
146 | node: { | |
147 | schema: NODE_SCHEMA, | |
148 | }, | |
149 | }, | |
150 | }, | |
151 | protected: true, | |
152 | access: { | |
153 | permission: &Permission::Privilege(&["system"], PRIV_SYS_MODIFY, false), | |
154 | }, | |
155 | )] | |
156 | /// Delete subscription info. | |
652506e6 | 157 | pub fn delete_subscription() -> Result<(), Error> { |
7b22fb25 TL |
158 | subscription::delete_subscription() |
159 | .map_err(|err| format_err!("Deleting subscription failed: {}", err))?; | |
160 | ||
161 | Ok(()) | |
7e13b2d6 DM |
162 | } |
163 | ||
255f378a | 164 | pub const ROUTER: Router = Router::new() |
7b22fb25 TL |
165 | .post(&API_METHOD_CHECK_SUBSCRIPTION) |
166 | .put(&API_METHOD_SET_SUBSCRIPTION) | |
167 | .delete(&API_METHOD_DELETE_SUBSCRIPTION) | |
1bfc1efa | 168 | .get(&API_METHOD_GET_SUBSCRIPTION); |