Line | Branch | Exec | Source |
---|---|---|---|
1 | /* Copyright 2024 Jan-Michael Brummer | ||
2 | * | ||
3 | * This program is free software: you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU Lesser General Public License as published by | ||
5 | * the Free Software Foundation, either version 3 of the License, or | ||
6 | * (at your option) any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU Lesser General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU Lesser General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <libsoup/soup.h> | ||
18 | #include <json-glib/json-glib.h> | ||
19 | |||
20 | #include <stdio.h> | ||
21 | |||
22 | #include "msg-authorizer.h" | ||
23 | #include "msg-error.h" | ||
24 | #include "msg-private.h" | ||
25 | #include "msg-service.h" | ||
26 | #include "msg-user.h" | ||
27 | #include "msg-user-service.h" | ||
28 | #include "msg-user-contact-folder.h" | ||
29 | |||
30 | struct _MsgUserService { | ||
31 | MsgService parent_instance; | ||
32 | }; | ||
33 | |||
34 |
5/6✓ Branch 0 taken 2 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 8 times.
|
14 | G_DEFINE_TYPE (MsgUserService, msg_user_service, MSG_TYPE_SERVICE); |
35 | |||
36 | static void | ||
37 | 1 | msg_user_service_init (__attribute__ ((unused)) MsgUserService *self) | |
38 | { | ||
39 | 1 | } | |
40 | |||
41 | static void | ||
42 | 2 | msg_user_service_class_init (__attribute__ ((unused)) MsgUserServiceClass *class) | |
43 | { | ||
44 | 2 | } | |
45 | |||
46 | MsgUserService * | ||
47 | 1 | msg_user_service_new (MsgAuthorizer *authorizer) | |
48 | { | ||
49 | 1 | return g_object_new (MSG_TYPE_USER_SERVICE, "authorizer", authorizer, NULL); | |
50 | } | ||
51 | |||
52 | /** | ||
53 | * msg_user_service_get_user: | ||
54 | * @self: a #MsgUserService | ||
55 | * @name: user name (%NULL for me) | ||
56 | * @cancellable: a #GCancellable | ||
57 | * @error: a #GError | ||
58 | * | ||
59 | * Get user information | ||
60 | * | ||
61 | * Returns: (transfer full): request user | ||
62 | */ | ||
63 | MsgUser * | ||
64 | 3 | msg_user_service_get_user (MsgUserService *self, | |
65 | const char *name, | ||
66 | GCancellable *cancellable, | ||
67 | GError **error) | ||
68 | { | ||
69 | 3 | g_autoptr (SoupMessage) message = NULL; | |
70 | 3 | JsonObject *root_object = NULL; | |
71 | 3 | g_autofree char *url = NULL; | |
72 | 3 | g_autoptr (GBytes) response = NULL; | |
73 | 3 | g_autoptr (JsonParser) parser = NULL; | |
74 | |||
75 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
76 | ✗ | return NULL; | |
77 | |||
78 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 times.
|
3 | if (!name) |
79 | 2 | url = g_strconcat (MSG_API_ENDPOINT, "/me", NULL); | |
80 | else | ||
81 | 1 | url = g_strconcat (MSG_BETA_API_ENDPOINT, "/me/contacts/users/", name, NULL); | |
82 | |||
83 | 3 | message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL, FALSE); | |
84 | 3 | parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error); | |
85 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | if (!parser) |
86 | 1 | return NULL; | |
87 | |||
88 | 2 | return msg_user_new_from_json (root_object, error); | |
89 | } | ||
90 | |||
91 | /** | ||
92 | * msg_user_service_get_photo: | ||
93 | * @self: a #MsgUserService | ||
94 | * @mail: mail address | ||
95 | * @cancellable: a #GCancellable | ||
96 | * @error: a #GError | ||
97 | * | ||
98 | * Try to load user photo using provided %mail address. | ||
99 | * | ||
100 | * Returns: (transfer full): user photo or %NULL if not found. | ||
101 | */ | ||
102 | GBytes * | ||
103 | 2 | msg_user_service_get_photo (MsgUserService *self, | |
104 | const char *mail, | ||
105 | GCancellable *cancellable, | ||
106 | GError **error) | ||
107 | { | ||
108 | 2 | g_autoptr (SoupMessage) message = NULL; | |
109 | 2 | g_autofree char *url = NULL; | |
110 | 2 | g_autoptr (GBytes) photo = NULL; | |
111 | |||
112 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
113 | ✗ | return NULL; | |
114 | |||
115 | 2 | url = g_strconcat (MSG_API_ENDPOINT, "/users/", mail, "/photo/$value", NULL); | |
116 | |||
117 | 2 | message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL, FALSE); | |
118 | 2 | photo = msg_service_send_and_read (MSG_SERVICE (self), message, cancellable, error); | |
119 | |||
120 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (soup_message_get_status (message) == SOUP_STATUS_OK) { |
121 | 1 | return g_steal_pointer (&photo); | |
122 | } | ||
123 | |||
124 | 1 | g_set_error (error, | |
125 | msg_error_quark (), | ||
126 | MSG_ERROR_FAILED, | ||
127 | "Could not load photo"); | ||
128 | |||
129 | 1 | return NULL; | |
130 | } | ||
131 | |||
132 | /** | ||
133 | * msg_user_service_get_contact_folders: | ||
134 | * @self: a #MsgUserService | ||
135 | * @cancellable: a #GCancellable | ||
136 | * @error: a #GError | ||
137 | * | ||
138 | * Get all folders for given service | ||
139 | * | ||
140 | * Returns: (element-type MsgUserContactFolder) (transfer full): all user contact folders the user can access | ||
141 | */ | ||
142 | GList * | ||
143 | 1 | msg_user_service_get_contact_folders (MsgUserService *self, | |
144 | GCancellable *cancellable, | ||
145 | GError **error) | ||
146 | { | ||
147 | 1 | JsonObject *root_object = NULL; | |
148 | 1 | g_autofree char *url = NULL; | |
149 | 1 | g_autolist (MsgUserContactFolder) list = NULL; | |
150 | 1 | JsonArray *array = NULL; | |
151 | 1 | guint array_length = 0, index = 0; | |
152 | 1 | g_autoptr (GBytes) response = NULL; | |
153 | 1 | g_autoptr (JsonParser) parser = NULL; | |
154 | |||
155 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
156 | ✗ | return NULL; | |
157 | |||
158 | 1 | url = g_strconcat (MSG_API_ENDPOINT, "/me/contactFolders", NULL); | |
159 | |||
160 | do { | ||
161 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | g_autoptr (SoupMessage) message = NULL; |
162 | |||
163 | 1 | message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL, FALSE); | |
164 | 1 | parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error); | |
165 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!parser) |
166 | ✗ | return NULL; | |
167 | |||
168 | 1 | array = json_object_get_array_member (root_object, "value"); | |
169 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | g_assert (array != NULL); |
170 | |||
171 | 1 | array_length = json_array_get_length (array); | |
172 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | for (index = 0; index < array_length; index++) { |
173 | ✗ | g_autoptr (GError) local_error = NULL; | |
174 | ✗ | MsgUserContactFolder *folder = NULL; | |
175 | ✗ | JsonObject *object = NULL; | |
176 | |||
177 | ✗ | object = json_array_get_object_element (array, index); | |
178 | |||
179 | ✗ | folder = msg_user_contact_folder_new_from_json (object, &local_error); | |
180 | ✗ | if (folder) { | |
181 | ✗ | list = g_list_append (list, folder); | |
182 | } else { | ||
183 | ✗ | g_warning ("Could not parse contact folder object: %s", local_error->message); | |
184 | ✗ | g_clear_error (&local_error); | |
185 | } | ||
186 | } | ||
187 | |||
188 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | g_clear_pointer (&url, g_free); |
189 | 1 | url = msg_service_get_next_link (root_object); | |
190 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | } while (url != NULL); |
191 | |||
192 | 1 | return g_steal_pointer (&list); | |
193 | } | ||
194 | |||
195 | /** | ||
196 | * msg_user_service_get_contacts: | ||
197 | * @self: a #MsgUserService | ||
198 | * @cancellable: a #GCancellable | ||
199 | * @error: a #GError | ||
200 | * | ||
201 | * Get all contats within users 'Contact' folder. | ||
202 | * | ||
203 | * Returns: (element-type MsgUserContactFolder) (transfer full): all contact in users contact folder | ||
204 | */ | ||
205 | GList * | ||
206 | 1 | msg_user_service_get_contacts (MsgUserService *self, | |
207 | GCancellable *cancellable, | ||
208 | GError **error) | ||
209 | { | ||
210 | 1 | g_autoptr (SoupMessage) soup_message = NULL; | |
211 | 1 | g_autofree char *url = NULL; | |
212 | 1 | JsonObject *root_object = NULL; | |
213 | 1 | g_autolist (MsgUser) list = NULL; | |
214 | 1 | JsonArray *array = NULL; | |
215 | 1 | guint array_length = 0, index = 0; | |
216 | 1 | g_autoptr (GBytes) response = NULL; | |
217 | 1 | g_autoptr (JsonParser) parser = NULL; | |
218 | |||
219 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
220 | ✗ | return NULL; | |
221 | |||
222 | 1 | url = g_strconcat (MSG_API_ENDPOINT, "/me/contacts/", NULL); | |
223 | |||
224 | do { | ||
225 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | g_autoptr (SoupMessage) message = NULL; |
226 | |||
227 | 1 | message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL, FALSE); | |
228 | 1 | parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error); | |
229 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!parser) |
230 | ✗ | return NULL; | |
231 | |||
232 | 1 | array = json_object_get_array_member (root_object, "value"); | |
233 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | g_assert (array != NULL); |
234 | |||
235 | 1 | array_length = json_array_get_length (array); | |
236 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | for (index = 0; index < array_length; index++) { |
237 | 1 | g_autoptr (GError) local_error = NULL; | |
238 | 1 | MsgUser *user = NULL; | |
239 | 1 | JsonObject *object = NULL; | |
240 | |||
241 | 1 | object = json_array_get_object_element (array, index); | |
242 | |||
243 | 1 | user = msg_user_new_from_json (object, &local_error); | |
244 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (user) { |
245 | 1 | list = g_list_append (list, user); | |
246 | } else { | ||
247 | ✗ | g_warning ("Could not parse contact user object: %s", local_error->message); | |
248 | ✗ | g_clear_error (&local_error); | |
249 | } | ||
250 | } | ||
251 | |||
252 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | g_clear_pointer (&url, g_free); |
253 | 1 | url = msg_service_get_next_link (root_object); | |
254 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | } while (url != NULL); |
255 | |||
256 | 1 | return g_steal_pointer (&list); | |
257 | } | ||
258 | |||
259 | /** | ||
260 | * msg_user_service_find_users: | ||
261 | * @self: a #MsgUserService | ||
262 | * @name: name to search | ||
263 | * @cancellable: a #GCancellable | ||
264 | * @error: a #GError | ||
265 | * | ||
266 | * Find all users with the given @name. (Business accounts only!) | ||
267 | * | ||
268 | * Returns: (element-type MsgUser) (transfer full): a list of contacts with the given name. | ||
269 | */ | ||
270 | GList * | ||
271 | 1 | msg_user_service_find_users (MsgUserService *self, | |
272 | const char *display_name, | ||
273 | GCancellable *cancellable, | ||
274 | GError **error) | ||
275 | { | ||
276 | 1 | g_autoptr (SoupMessage) soup_message = NULL; | |
277 | 1 | g_autofree char *url = NULL; | |
278 | 1 | JsonObject *root_object = NULL; | |
279 | 1 | g_autolist (MsgUser) list = NULL; | |
280 | 1 | JsonArray *array = NULL; | |
281 | 1 | guint array_length = 0, index = 0; | |
282 | 1 | g_autoptr (GBytes) response = NULL; | |
283 | 1 | g_autoptr (JsonParser) parser = NULL; | |
284 | |||
285 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!msg_service_refresh_authorization (MSG_SERVICE (self), cancellable, error)) |
286 | ✗ | return NULL; | |
287 | |||
288 | 1 | url = g_strconcat (MSG_API_ENDPOINT, "/users?$search=\"displayName:", display_name, "\"", NULL); | |
289 | |||
290 | do { | ||
291 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | g_autoptr (SoupMessage) message = NULL; |
292 | |||
293 | 1 | message = msg_service_build_message (MSG_SERVICE (self), "GET", url, NULL, FALSE); | |
294 | 1 | soup_message_headers_append (soup_message_get_request_headers (message), "ConsistencyLevel", "eventual"); | |
295 | 1 | parser = msg_service_send_and_parse_response (MSG_SERVICE (self), message, &root_object, cancellable, error); | |
296 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (!parser) |
297 | 1 | return NULL; | |
298 | |||
299 | ✗ | array = json_object_get_array_member (root_object, "value"); | |
300 | ✗ | g_assert (array != NULL); | |
301 | |||
302 | ✗ | array_length = json_array_get_length (array); | |
303 | ✗ | for (index = 0; index < array_length; index++) { | |
304 | ✗ | g_autoptr (GError) local_error = NULL; | |
305 | ✗ | MsgUser *user = NULL; | |
306 | ✗ | JsonObject *object = NULL; | |
307 | |||
308 | ✗ | object = json_array_get_object_element (array, index); | |
309 | |||
310 | ✗ | user = msg_user_new_from_json (object, &local_error); | |
311 | ✗ | if (user) { | |
312 | ✗ | list = g_list_append (list, user); | |
313 | } else { | ||
314 | ✗ | g_warning ("Could not parse contact user object: %s", local_error->message); | |
315 | ✗ | g_clear_error (&local_error); | |
316 | } | ||
317 | } | ||
318 | |||
319 | ✗ | g_clear_pointer (&url, g_free); | |
320 | ✗ | url = msg_service_get_next_link (root_object); | |
321 | ✗ | } while (url != NULL); | |
322 | |||
323 | ✗ | return g_steal_pointer (&list); | |
324 | } | ||
325 |