odoo_api/service/web.rs
1//! The Odoo "Web" pseudo-service
2//!
3//! This isn't actually a service, but a set of JSON-RPC compatible endpoints
4//! that Odoo exposes. Generally these are used by the webclient, and offer
5//! functionality that can be achieved with `execute` and `execute_kw`
6
7use crate::jsonrpc::OdooWebMethod;
8use crate::service::common::ServerVersionInfo;
9use crate::{self as odoo_api, OdooId};
10use odoo_api_macros::odoo_web;
11use serde::ser::SerializeTuple;
12use serde::{Deserialize, Serialize};
13use serde_json::{Map, Value};
14
15//TODO: /web/session/get_lang_list (only v15+?)
16//TODO: /web/session/check
17//TODO: /web/session/change_password
18//TODO: /web/session/get_session_info
19//TODO: /web/session/modules
20//TODO: /web/session/modules
21//TODO: /web/session/destroy
22//TODO: /web/session/logout
23//TODO: /web/dataset/resequence
24//TODO: /web/dataset/call
25//TODO: /web/dataset/call_kw
26//TODO: /web/dataset/load
27//TODO: /web/dataset/search_read
28
29/// Authenticate to an Odoo database
30///
31/// This method performs a bona-fide Odoo "authentication"; it checks the user
32/// name/password, and creates a new `session_id` (which is returned via the
33/// `Set-Cookie` header).
34///
35/// Note that by itself, this function isn't able to parse the `session_id` token,
36/// so it probably isn't very useful.
37///
38/// See [`authenticate`](crate::client::OdooClient::authenticate) if you'd like to
39/// authenticate an `OdooClient`.
40///
41/// Reference: [web/controllers/session.py](https://github.com/odoo/odoo/blob/b6e195ccb3a6c37b0d980af159e546bdc67b1e42/addons/web/controllers/session.py#L29-L43)
42#[odoo_web(
43 path = "/web/session/authenticate",
44 name = "web_session_authenticate",
45 auth = false
46)]
47#[derive(Debug, Serialize)]
48pub struct SessionAuthenticate {
49 pub(crate) db: String,
50 pub(crate) login: String,
51 pub(crate) password: String,
52}
53
54/// Represents the response to an Odoo [`SessionAuthenticate`] call
55///
56/// Note that the generated `session_id` is not returned here. The response
57/// data contains some information about the Odoo session.
58#[derive(Debug, Serialize, Deserialize)]
59#[serde(transparent)]
60pub struct SessionAuthenticateResponse {
61 pub data: Value,
62}
63
64/// List the available databases
65///
66/// Reference: [web/controller/database.py](https://github.com/odoo/odoo/blob/b6e195ccb3a6c37b0d980af159e546bdc67b1e42/addons/web/controllers/database.py#L176-L183)
67#[odoo_web(path = "/web/database/list", name = "web_database_list", auth = false)]
68#[derive(Debug)]
69pub struct DatabaseList {}
70
71// DatabaseList has no fields, but needs to output in JSON: `[]`
72impl Serialize for DatabaseList {
73 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
74 where
75 S: serde::Serializer,
76 {
77 let state = serializer.serialize_tuple(0)?;
78 state.end()
79 }
80}
81
82/// Represents the response to an Odoo [`DatabaseList`] call
83#[derive(Debug, Serialize, Deserialize)]
84#[serde(transparent)]
85pub struct DatabaseListResponse {
86 pub databases: Vec<String>,
87}
88
89/// Fetch session information
90///
91/// Reference: [web/controllers/session.py](https://github.com/odoo/odoo/blob/b6e195ccb3a6c37b0d980af159e546bdc67b1e42/addons/web/controllers/session.py#L23-L27)
92#[odoo_web(
93 path = "/web/session/get_session_info",
94 name = "web_get_session_info",
95 auth = false
96)]
97#[derive(Debug)]
98pub struct GetSessionInfo {}
99
100// GetSessionInfo has no fields, but needs to output in JSON: `[]`
101impl Serialize for GetSessionInfo {
102 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
103 where
104 S: serde::Serializer,
105 {
106 let state = serializer.serialize_tuple(0)?;
107 state.end()
108 }
109}
110
111/// The response to a `GetSessionInfo` request
112///
113/// Reference: [web/controllers/session.py](https://github.com/odoo/odoo/blob/b6e195ccb3a6c37b0d980af159e546bdc67b1e42/addons/web/controllers/session.py#L27)
114/// See also: [web/models/ir_http.py](https://github.com/odoo/odoo/blob/b6e195ccb3a6c37b0d980af159e546bdc67b1e42/addons/web/models/ir_http.py#L67-L146)
115#[derive(Debug, Serialize, Deserialize)]
116pub struct GetSessionInfoResponse {
117 /// The authenticated users' ID
118 uid: OdooId,
119
120 /// Is the "system" user logged-in?
121 ///
122 /// This is equivalent to `res.users._is_system()`
123 is_system: bool,
124
125 /// Is the "admin" user logged-in?
126 ///
127 /// This is equivalent to `res.users._is_admin()`
128 is_admin: bool,
129
130 //TODO: more docs!
131 /// The "user context"
132 user_context: Map<String, Value>,
133
134 /// The database that is currently bound
135 db: String,
136
137 /// Server version information (basic)
138 ///
139 /// Example: `14.0+e`
140 server_version: String,
141
142 /// Server version information (extended)
143 ///
144 /// See the `ServerVersionInfo` struct for more information
145 server_version_info: ServerVersionInfo,
146
147 /// The logged-in users' name
148 ///
149 /// Note that this corresponds with the `res.users.name` field, which
150 /// is related to `res.users.partner_id.name` (e.g., it is the "pretty"
151 /// name for the user, **not** the username/login)
152 name: String,
153
154 /// The logged-in users' username/login
155 username: String,
156
157 /// The logged-in users' display name
158 ///
159 /// Note that this corresponds with the related `res.users.partner_id.display_name`
160 /// field.
161 partner_display_name: String,
162
163 /// The logged-in users' primary company
164 ///
165 /// **Note**: This is NOT the primary active company - it literally corresponds
166 /// with the `res.users.company_id` field (or "Primary Company" in the user
167 /// config). This field probably isn't very useful.
168 company_id: OdooId,
169
170 /// The logged-in users' related partner
171 ///
172 /// Every Odoo user has a "related partner"; the mapping is one2one - each
173 /// user has exactly 1 partner, and each partner has at-most 1 user.
174 ///
175 /// Some "pretty" information is stored on the partner rather than the user:
176 /// - Display Name
177 /// - Timezone
178 /// - Email
179 /// - Address info
180 partner_id: OdooId,
181
182 /// The `web.base.url` config parameter
183 #[serde(rename = "web.base.url")]
184 web_base_url: String,
185
186 //TODO: store this as a u32, convert on deserialize
187 /// The `web.active_ids_limit` config parameter
188 active_ids_limit: String,
189
190 //TODO: store this as a u32/i32?
191 /// The `web.max_file_upload_size` config parameter
192 ///
193 /// If the paramter is not defined, then 128MiB is used as the default
194 max_file_upload_size: String,
195
196 /// Multi-company information
197 ///
198 /// Only present when authenticated as an internal user (e.g., a user with
199 /// the `base.group_user` group).
200 user_companies: Option<MultiCompanyInfo>,
201
202 /// TBC
203 ///
204 /// Only present when authenticated as an internal user (e.g., a user with
205 /// the `base.group_user` group).
206 show_effect: Option<bool>,
207
208 /// Should the switch-company menu be shown?
209 ///
210 /// E.g., `len(allowed_company_ids) > 1`
211 ///
212 /// Only present when authenticated as an internal user (e.g., a user with
213 /// the `base.group_user` group).
214 display_switch_company_menu: Option<bool>,
215
216 ///
217 /// Only present when authenticated as an internal user (e.g., a user with
218 /// the `base.group_user` group).
219 cache_hashes: Option<Value>,
220}
221
222/// Multi-company information
223#[derive(Debug, Serialize, Deserialize)]
224pub struct MultiCompanyInfo {
225 current_company: MultiCompanyInfoCurrent,
226 allowed_companies: Vec<MultiCompanyInfoAllowed>,
227}
228
229#[derive(Debug, Serialize, Deserialize)]
230pub enum MultiCompanyInfoCurrent {
231 NameAndId((OdooId, String)),
232 Id(OdooId),
233}
234
235#[derive(Debug, Serialize, Deserialize)]
236pub struct MultiCompanyInfoAllowed {
237 id: OdooId,
238 name: String,
239 sequence: Option<u32>,
240}