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