Update the task model with tasks from the server.
[milk] / src / milk-auth.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License as
4  * published by the Free Software Foundation; either version 2 of the
5  * License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  * General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public
13  * License along with this program; if not, write to the
14  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
15  * Boston, MA  02110-1301  USA
16  *
17  * Authors: Travis Reitter <treitter@gmail.com>
18  */
19
20 #include <config.h>
21
22 #include <glib.h>
23 #include <glib/gi18n.h>
24 #include <gtk/gtk.h>
25 #include <hildon/hildon.h>
26
27 #include <rtm-glib/rtm-error.h>
28 #include <rtm-glib/rtm-glib.h>
29
30 #include "milk-auth.h"
31 #include "milk-dialogs.h"
32
33 G_DEFINE_TYPE (MilkAuth, milk_auth, G_TYPE_OBJECT);
34
35 /* less expensive than G_TYPE_INSTANCE_GET_PRIVATE */
36 #define MILK_AUTH_PRIVATE(o) ((MILK_AUTH ((o)))->priv)
37
38 #define RTM_API_KEY "81f5c6c904aeafbbc914d9845d250ea8"
39 #define RTM_SHARED_SECRET "b08b15419378f913"
40
41 struct _MilkAuthPrivate
42 {
43         RtmGlib *rtm_glib;
44         char *api_key;
45         char *shared_secret;
46         char *frob;
47         MilkAuthState state;
48 };
49
50 enum {
51         PROP_API_KEY = 1,
52         PROP_SHARED_SECRET,
53         PROP_STATE,
54 };
55
56 static MilkAuth *default_auth = NULL;
57
58
59 MilkAuthState
60 milk_auth_get_state (MilkAuth *auth)
61 {
62         g_return_val_if_fail (auth, MILK_AUTH_STATE_DISCONNECTED);
63         g_return_val_if_fail (MILK_IS_AUTH (auth),
64                         MILK_AUTH_STATE_DISCONNECTED);
65
66         return MILK_AUTH_PRIVATE (auth)->state;
67 }
68
69 static void
70 milk_auth_get_property (GObject    *object,
71                         guint       property_id,
72                         GValue     *value,
73                         GParamSpec *pspec)
74 {
75         MilkAuthPrivate *priv = MILK_AUTH_PRIVATE (object);
76
77         switch (property_id)
78         {
79                 case PROP_API_KEY:
80                         g_value_set_string (value, priv->api_key);
81                 break;
82
83                 case PROP_SHARED_SECRET:
84                         g_value_set_string (value, priv->shared_secret);
85                 break;
86
87                 case PROP_STATE:
88                         g_value_set_int (value, priv->state);
89                 break;
90
91                 default:
92                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id,
93                                         pspec);
94         }
95 }
96
97 static void
98 milk_auth_set_property (GObject      *object,
99                         guint         property_id,
100                         const GValue *value,
101                         GParamSpec   *pspec)
102 {
103         MilkAuthPrivate *priv;
104         MilkAuth *auth;
105
106         auth = MILK_AUTH (object);
107         priv = MILK_AUTH_PRIVATE (auth);
108
109         switch (property_id)
110         {
111                 case PROP_API_KEY:
112                         priv->api_key = g_value_dup_string (value);
113                 break;
114
115                 case PROP_SHARED_SECRET:
116                         priv->shared_secret = g_value_dup_string (value);
117                 break;
118
119                 case PROP_STATE:
120                         priv->state = g_value_get_int (value);
121                 break;
122
123                 default:
124                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id,
125                                         pspec);
126         }
127 }
128
129 static void
130 auth_response_cb (GtkWidget *dialog,
131                   int        response,
132                   MilkAuth  *auth)
133
134 {
135         MilkAuthPrivate *priv;
136         GError *error = NULL;
137         gchar *auth_token;
138         gchar *username;
139         MilkAuthState previous_state;
140
141         priv = MILK_AUTH_PRIVATE (auth);
142
143         previous_state = priv->state;
144         auth_token = rtm_glib_auth_get_token (priv->rtm_glib, priv->frob,
145                         &error);
146         if (error != NULL) {
147                 g_error ("%s", rtm_error_get_message (error));
148                 goto auth_response_cb_error_OUT;
149         }
150
151         if (!rtm_glib_auth_check_token (priv->rtm_glib, auth_token, NULL)) {
152                 g_error ("auth_token not valid!\n");
153                 goto auth_response_cb_error_OUT;
154         }
155         if (error != NULL) {
156                 g_error ("%s", rtm_error_get_message (error));
157                 goto auth_response_cb_error_OUT;
158         }
159         username = rtm_glib_test_login (priv->rtm_glib, auth_token, &error);
160
161         g_free (auth_token);
162
163         if (error != NULL) {
164                 g_error ("%s", rtm_error_get_message (error));
165                 goto auth_response_cb_error_OUT;
166         }
167
168         priv->state = MILK_AUTH_STATE_CONNECTED;
169         goto auth_response_cb_OUT;
170
171 auth_response_cb_error_OUT:
172         priv->state = MILK_AUTH_STATE_DISCONNECTED;
173
174 auth_response_cb_OUT:
175         if (priv->state != previous_state)
176                 g_object_notify (G_OBJECT (auth), "state");
177
178         gtk_widget_destroy (dialog);
179 }
180
181 GList *
182 milk_auth_get_tasks (MilkAuth *auth)
183 {
184         MilkAuthPrivate *priv;
185         GError *error = NULL;
186         GList *rtm_tasks;
187
188         g_return_val_if_fail (auth, NULL);
189         g_return_val_if_fail (MILK_IS_AUTH (auth), NULL);
190         g_return_val_if_fail (
191                         milk_auth_get_state (auth) == MILK_AUTH_STATE_CONNECTED,
192                         NULL);
193
194         priv = MILK_AUTH_PRIVATE (auth);
195
196         /* FIXME: cache this */
197         rtm_tasks = rtm_glib_tasks_get_list (priv->rtm_glib, NULL, NULL, NULL,
198                         &error);
199         if (error != NULL) {
200                 g_error ("%s", rtm_error_get_message (error));
201                 return NULL;
202         }
203         
204         return rtm_tasks;
205 }
206
207 void
208 milk_auth_log_in (MilkAuth *auth)
209 {
210         MilkAuthPrivate *priv;
211         GError *error = NULL;
212         gchar *url;
213         GtkDialog *dialog;
214
215         g_return_if_fail (auth);
216         g_return_if_fail (MILK_IS_AUTH (auth));
217
218         priv = MILK_AUTH_PRIVATE (auth);
219
220         if (rtm_glib_test_echo (priv->rtm_glib, &error)) {
221                 g_print ("Test echo OK!\n");
222         } else {
223                 g_print ("Test echo FAIL!\n");
224                 return;
225         }
226         if (error != NULL) {
227                 g_error ("%s", rtm_error_get_message (error));
228                 return;
229         }
230
231         /* FIXME: relocate this */
232         if (priv->frob)
233                 g_free (priv->frob);
234
235         priv->frob = rtm_glib_auth_get_frob (priv->rtm_glib, &error);
236         if (error != NULL) {
237                 g_error ("%s", rtm_error_get_message (error));
238                 return;
239         }
240         g_print ("Frob: %s\n", priv->frob);
241
242         url = rtm_glib_auth_get_login_url (priv->rtm_glib, priv->frob,
243                         "delete");
244         g_print ("URL: %s\n", url);
245
246         dialog = milk_dialogs_auth_prompt (NULL, url);
247
248         g_signal_connect (dialog, "response", G_CALLBACK (auth_response_cb),
249                         auth);
250 }
251
252 static void
253 milk_auth_constructed (GObject *object)
254 {
255         MilkAuthPrivate *priv = MILK_AUTH_PRIVATE (object);
256
257         priv->rtm_glib = rtm_glib_new (priv->api_key, priv->shared_secret);
258 }
259
260 static void
261 milk_auth_finalize (GObject *object)
262 {
263         MilkAuthPrivate *priv = MILK_AUTH_PRIVATE (object);
264
265         g_object_unref (priv->rtm_glib);
266
267         g_free (priv->api_key);
268         g_free (priv->shared_secret);
269         g_free (priv->frob);
270 }
271
272 static void
273 milk_auth_class_init (MilkAuthClass *klass)
274 {
275         GObjectClass *object_class = G_OBJECT_CLASS (klass);
276
277         g_type_class_add_private (klass, sizeof (MilkAuthPrivate));
278
279         object_class->get_property = milk_auth_get_property;
280         object_class->set_property = milk_auth_set_property;
281         object_class->constructed = milk_auth_constructed;
282         object_class->finalize = milk_auth_finalize;
283
284         /* FIXME: make these read-only */
285         g_object_class_install_property
286                 (object_class,
287                  PROP_API_KEY,
288                  g_param_spec_string
289                          ("api-key",
290                           "API authentication key",
291                           "Milk's API authentication key.",
292                           RTM_API_KEY,
293                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
294                           G_PARAM_STATIC_STRINGS));
295
296         g_object_class_install_property
297                 (object_class,
298                  PROP_SHARED_SECRET,
299                  g_param_spec_string
300                          ("shared-secret",
301                           "Shared secret",
302                           "Milk's shared secret with the server.",
303                           RTM_SHARED_SECRET,
304                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
305                           G_PARAM_STATIC_STRINGS));
306
307         g_object_class_install_property
308                 (object_class,
309                  PROP_STATE,
310                  g_param_spec_int
311                          ("state",
312                           "Authentication state",
313                           "Authentication/connection state with the server.",
314                           0, (NUM_MILK_AUTH_STATES-1),
315                           MILK_AUTH_STATE_DISCONNECTED,
316                           G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
317                           G_PARAM_STATIC_STRINGS));
318 }
319
320 static void
321 milk_auth_init (MilkAuth *self)
322 {
323         MilkAuthPrivate *priv;
324
325         self->priv = priv = G_TYPE_INSTANCE_GET_PRIVATE (
326                         self, MILK_TYPE_AUTH, MilkAuthPrivate);
327 }
328
329 MilkAuth*
330 milk_auth_get_default ()
331 {
332         if (!default_auth)
333                 default_auth = g_object_new (MILK_TYPE_AUTH, NULL);
334
335         return default_auth;
336 }