diff options
Diffstat (limited to 'gdata/services')
-rw-r--r-- | gdata/services/calendar/gdata-calendar-access-rule.c | 322 | ||||
-rw-r--r-- | gdata/services/calendar/gdata-calendar-access-rule.h | 125 | ||||
-rw-r--r-- | gdata/services/calendar/gdata-calendar-calendar.c | 60 | ||||
-rw-r--r-- | gdata/services/calendar/gdata-calendar-calendar.h | 46 |
4 files changed, 505 insertions, 48 deletions
diff --git a/gdata/services/calendar/gdata-calendar-access-rule.c b/gdata/services/calendar/gdata-calendar-access-rule.c new file mode 100644 index 00000000..5e46f487 --- /dev/null +++ b/gdata/services/calendar/gdata-calendar-access-rule.c @@ -0,0 +1,322 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * GData Client + * Copyright (C) Philip Withnall 2015 <philip@tecnocode.co.uk> + * + * GData Client is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * GData Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with GData Client. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * SECTION:gdata-calendar-access-rule + * @short_description: GData Calendar access rule object + * @stability: Stable + * @include: gdata/services/calendar/gdata-access-rule.h + * + * #GDataCalendarAccessRule is a subclass of #GDataAccessRule to represent a TODO generic access rule from an access control list (ACL). + * It is returned by the ACL methods implemented in the #GDataAccessHandler interface. + * + * Access rules should be inserted to the %GDATA_LINK_ACCESS_CONTROL_LIST URI of the feed or entry they should be applied to. This will return a + * %GDATA_SERVICE_ERROR_CONFLICT error if a rule already exists on that feed or entry for that scope type and value. + * + * TODO + * <example> + * <title>Adding a Rule to the Access Control List for an Entry</title> + * <programlisting> + * GDataService *service; + * GDataEntry *entry; + * GDataFeed *acl_feed; + * GDataAccessRule *rule, *new_rule; + * GError *error = NULL; + * + * /<!-- -->* Retrieve a GDataEntry which will have a new rule inserted into its ACL. *<!-- -->/ + * service = build_my_service (); + * entry = get_the_entry (service); + * + * /<!-- -->* Create and insert a new access rule for example@gmail.com which grants them _no_ permissions on the entry. + * * In a real application, the GDataEntry subclass would define its own access roles which are more useful. For example, + * * GDataDocumentsEntry defines access roles for users who can read (but not write) a Google Document, and users who + * * can also write to the document. *<!-- -->/ + * rule = gdata_access_rule_new (NULL); + * gdata_access_rule_set_role (rule, GDATA_ACCESS_ROLE_NONE); /<!-- -->* or, for example, GDATA_DOCUMENTS_ACCESS_ROLE_READER *<!-- -->/ + * gdata_access_rule_set_scope (rule, GDATA_ACCESS_SCOPE_USER, "example@gmail.com"); /<!-- -->* e-mail address of the user the ACL applies to *<!-- -->/ + * + * acl_link = gdata_entry_look_up_link (entry, GDATA_LINK_ACCESS_CONTROL_LIST); + * new_rule = GDATA_ACCESS_RULE (gdata_service_insert_entry (GDATA_SERVICE (service), gdata_link_get_uri (acl_link), GDATA_ENTRY (rule), + * NULL, &error)); + * g_object_unref (acl_link); + * + * g_object_unref (rule); + * g_object_unref (entry); + * g_object_unref (service); + * + * if (error != NULL) { + * g_error ("Error inserting access rule: %s", error->message); + * g_error_free (error); + * return; + * } + * + * /<!-- -->* Potentially do something with the new_rule here, such as store its ID for later use. *<!-- -->/ + * + * g_object_unref (new_rule); + * </programlisting> + * </example> + * + * Since: UNRELEASED + */ + +#include <config.h> +#include <glib.h> +#include <glib/gi18n-lib.h> +#include <string.h> + +#include "gdata-access-rule.h" +#include "gdata-parser.h" +#include "gdata-types.h" +#include "gdata-private.h" +#include "gdata-calendar-access-rule.h" + +static gboolean +parse_json (GDataParsable *parsable, JsonReader *reader, gpointer user_data, + GError **error); +static gboolean +post_parse_json (GDataParsable *parsable, gpointer user_data, GError **error); +static void +get_json (GDataParsable *parsable, JsonBuilder *builder); +static const gchar * +get_content_type (void); + +G_DEFINE_TYPE (GDataCalendarAccessRule, gdata_calendar_access_rule, + GDATA_TYPE_ACCESS_RULE) + +static void +gdata_calendar_access_rule_class_init (GDataCalendarAccessRuleClass *klass) +{ + GDataParsableClass *parsable_class = GDATA_PARSABLE_CLASS (klass); + GDataEntryClass *entry_class = GDATA_ENTRY_CLASS (klass); + + parsable_class->parse_json = parse_json; + parsable_class->post_parse_json = post_parse_json; + parsable_class->get_json = get_json; + parsable_class->get_content_type = get_content_type; + + entry_class->kind_term = "calendar#aclRule"; + + /* TODO: Add a self link for deletions? */ +} + +static void +gdata_calendar_access_rule_init (GDataCalendarAccessRule *self) +{ + /* Nothing to do here. */ +} + +/* TODO: references */ +const struct { + const gchar *v3; + const gchar *v2; +} role_pairs[] = { + { "none", "none" }, + { "freeBusyReader", "http://schemas.google.com/gCal/2005#freebusy" }, + { "reader", "http://schemas.google.com/gCal/2005#read" }, + { "writer", "http://schemas.google.com/gCal/2005#editor" }, + { "owner", "http://schemas.google.com/gCal/2005#owner" }, +}; + +static const gchar * +role_v3_to_v2 (const gchar *v3_role) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (role_pairs); i++) { + if (g_strcmp0 (v3_role, role_pairs[i].v3) == 0) { + return role_pairs[i].v2; + } + } + + /* Fallback. */ + return v3_role; +} + +static const gchar * +role_v2_to_v3 (const gchar *v2_role) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (role_pairs); i++) { + if (g_strcmp0 (v2_role, role_pairs[i].v2) == 0) { + return role_pairs[i].v3; + } + } + + /* Fallback. */ + return v2_role; +} + +static const gchar * +scope_type_v3_to_v2 (const gchar *v3_scope_type) +{ + /* Surprisingly, they have not changed from v2 to v3. */ + return v3_scope_type; +} + +static const gchar * +scope_type_v2_to_v3 (const gchar *v2_scope_type) +{ + /* Surprisingly, they have not changed from v2 to v3. */ + return v2_scope_type; +} + +static gboolean +parse_json (GDataParsable *parsable, JsonReader *reader, gpointer user_data, GError **error) +{ + gboolean success; + + if (g_strcmp0 (json_reader_get_member_name (reader), "role") == 0) { + gchar *role = NULL; /* owned */ + + g_assert (gdata_parser_string_from_json_member (reader, "role", + P_REQUIRED | + P_NON_EMPTY, + &role, &success, + error)); + + if (!success) { + return FALSE; + } + + gdata_access_rule_set_role (GDATA_ACCESS_RULE (parsable), + role_v3_to_v2 (role)); + g_free (role); + + return TRUE; + } else if (g_strcmp0 (json_reader_get_member_name (reader), + "scope") == 0) { + const gchar *scope_type; + const gchar *scope_value; + + /* Check this is an object. */ + if (!json_reader_is_object (reader)) { + return gdata_parser_error_required_json_content_missing (reader, + error); + } + + json_reader_read_member (reader, "type"); + scope_type = json_reader_get_string_value (reader); + json_reader_end_member (reader); + + json_reader_read_member (reader, "value"); + scope_value = json_reader_get_string_value (reader); + json_reader_end_member (reader); + + /* Scope type is required. */ + if (scope_type == NULL) { + return gdata_parser_error_required_json_content_missing (reader, + error); + } + + gdata_access_rule_set_scope (GDATA_ACCESS_RULE (parsable), + scope_type_v3_to_v2 (scope_type), + scope_value); + + return TRUE; + } + + return GDATA_PARSABLE_CLASS (gdata_calendar_access_rule_parent_class)->parse_json (parsable, reader, user_data, error); +} + +static gboolean +post_parse_json (GDataParsable *parsable, gpointer user_data, GError **error) +{ + /* Do _not_ chain up. */ + return TRUE; +} + +static void +get_json (GDataParsable *parsable, JsonBuilder *builder) +{ + GDataAccessRule *access_rule; + const gchar *id, *etag, *role, *scope_type, *scope_value; + + access_rule = GDATA_ACCESS_RULE (parsable); + + id = gdata_entry_get_id (GDATA_ENTRY (parsable)); + if (id != NULL) { + json_builder_set_member_name (builder, "id"); + json_builder_add_string_value (builder, id); + } + + json_builder_set_member_name (builder, "kind"); + json_builder_add_string_value (builder, "calendar#aclRule"); + + /* Add the ETag, if available. */ + etag = gdata_entry_get_etag (GDATA_ENTRY (parsable)); + if (etag != NULL) { + json_builder_set_member_name (builder, "etag"); + json_builder_add_string_value (builder, etag); + } + + role = gdata_access_rule_get_role (access_rule); + if (role != NULL) { + json_builder_set_member_name (builder, "role"); + json_builder_add_string_value (builder, role_v2_to_v3 (role)); + } + + gdata_access_rule_get_scope (access_rule, &scope_type, &scope_value); + if (scope_type != NULL || scope_value != NULL) { + json_builder_set_member_name (builder, "scope"); + json_builder_begin_object (builder); + + if (scope_type != NULL) { + json_builder_set_member_name (builder, "type"); + json_builder_add_string_value (builder, + scope_type_v2_to_v3 (scope_type)); + } + + if (scope_value != NULL) { + json_builder_set_member_name (builder, "value"); + json_builder_add_string_value (builder, scope_value); + } + + json_builder_end_object (builder); + } +} + +static const gchar * +get_content_type (void) +{ + return "application/json"; +} + +/** + * gdata_calendar_access_rule_new: + * @id: the access rule's ID, or %NULL + * + * Creates a new #GDataCalendarAccessRule with the given ID and default + * properties. + * + * Return value: (transfer full): a new #GDataCalendarAccessRule; unref with + * g_object_unref() + * + * Since: UNRELEASED + */ +GDataCalendarAccessRule * +gdata_calendar_access_rule_new (const gchar *id) +{ + GObject *retval = NULL; /* owned */ + + retval = g_object_new (GDATA_TYPE_CALENDAR_ACCESS_RULE, + "id", id, + NULL); + return GDATA_CALENDAR_ACCESS_RULE (retval); +} diff --git a/gdata/services/calendar/gdata-calendar-access-rule.h b/gdata/services/calendar/gdata-calendar-access-rule.h new file mode 100644 index 00000000..d1d202cb --- /dev/null +++ b/gdata/services/calendar/gdata-calendar-access-rule.h @@ -0,0 +1,125 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * GData Client + * Copyright (C) Philip Withnall 2015 <philip@tecnocode.co.uk> + * + * GData Client is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * GData Client is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with GData Client. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef GDATA_CALENDAR_ACCESS_RULE_H +#define GDATA_CALENDAR_ACCESS_RULE_H + +#include <glib.h> +#include <glib-object.h> + +#include <gdata/gdata-access-rule.h> + +G_BEGIN_DECLS + +/** + * GDATA_CALENDAR_ACCESS_ROLE_READ: + * + * The users specified by the #GDataCalendarAccessRule have read-only access to + * the calendar. + * + * Since: 0.7.0 + */ +#define GDATA_CALENDAR_ACCESS_ROLE_READ "http://schemas.google.com/gCal/2005#read" + +/** + * GDATA_CALENDAR_ACCESS_ROLE_FREE_BUSY: + * + * The users specified by the #GDataCalendarAccessRule can only see the + * free/busy information on the calendar; not event details. + * + * Since: 0.7.0 + */ +#define GDATA_CALENDAR_ACCESS_ROLE_FREE_BUSY "http://schemas.google.com/gCal/2005#freebusy" + +/** + * GDATA_CALENDAR_ACCESS_ROLE_EDITOR: + * + * The users specified by the #GDataCalendarAccessRule have full edit access to + * the calendar, except they can’t change the calendar’s access rules. + * + * Since: 0.7.0 + */ +#define GDATA_CALENDAR_ACCESS_ROLE_EDITOR "http://schemas.google.com/gCal/2005#editor" + +/** + * GDATA_CALENDAR_ACCESS_ROLE_OWNER: + * + * The users specified by the #GDataCalendarAccessRule have full owner access + * to the calendar. + * + * Since: 0.7.0 + */ +#define GDATA_CALENDAR_ACCESS_ROLE_OWNER "http://schemas.google.com/gCal/2005#owner" + +/** + * GDATA_CALENDAR_ACCESS_ROLE_ROOT: + * + * The users specified by the #GDataCalendarAccessRule have full administrator + * access to the calendar server. This is only available in Google Apps For + * Your Domain. + * + * Since: 0.7.0 + */ +#define GDATA_CALENDAR_ACCESS_ROLE_ROOT "http://schemas.google.com/gCal/2005#root" + +#define GDATA_TYPE_CALENDAR_ACCESS_RULE (gdata_calendar_access_rule_get_type ()) +#define GDATA_CALENDAR_ACCESS_RULE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDATA_TYPE_CALENDAR_ACCESS_RULE, GDataCalendarAccessRule)) +#define GDATA_CALENDAR_ACCESS_RULE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDATA_TYPE_CALENDAR_ACCESS_RULE, GDataCalendarAccessRuleClass)) +#define GDATA_IS_CALENDAR_ACCESS_RULE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDATA_TYPE_CALENDAR_ACCESS_RULE)) +#define GDATA_IS_CALENDAR_ACCESS_RULE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDATA_TYPE_CALENDAR_ACCESS_RULE)) +#define GDATA_CALENDAR_ACCESS_RULE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDATA_TYPE_CALENDAR_ACCESS_RULE, GDataCalendarAccessRuleClass)) + +/** + * GDataCalendarAccessRule: + * + * All the fields in the #GDataCalendarAccessRule structure are private and + * should never be accessed directly. + * + * Since: UNRELEASED + */ +typedef struct { + GDataAccessRule parent; +} GDataCalendarAccessRule; + +/** + * GDataCalendarAccessRuleClass: + * + * All the fields in the #GDataCalendarAccessRuleClass structure are private + * and should never be accessed directly. + * + * Since: UNRELEASED + */ +typedef struct { + /*< private >*/ + GDataAccessRuleClass parent; + + /*< private >*/ + /* Padding for future expansion */ + void (*_g_reserved0) (void); + void (*_g_reserved1) (void); +} GDataCalendarAccessRuleClass; + +GType gdata_calendar_access_rule_get_type (void) G_GNUC_CONST; + +GDataCalendarAccessRule * +gdata_calendar_access_rule_new (const gchar *id) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC; + +G_END_DECLS + +#endif /* !GDATA_CALENDAR_ACCESS_RULE_H */ diff --git a/gdata/services/calendar/gdata-calendar-calendar.c b/gdata/services/calendar/gdata-calendar-calendar.c index 9d7204b3..31cc922d 100644 --- a/gdata/services/calendar/gdata-calendar-calendar.c +++ b/gdata/services/calendar/gdata-calendar-calendar.c @@ -86,6 +86,7 @@ #include "gdata-types.h" #include "gdata-access-handler.h" #include "gdata-calendar-service.h" +#include "gdata-calendar-access-rule.h" static void gdata_calendar_calendar_access_handler_init (GDataAccessHandlerIface *iface); static void gdata_calendar_calendar_finalize (GObject *object); @@ -252,11 +253,56 @@ get_authorization_domain (GDataAccessHandler *self) return gdata_calendar_service_get_primary_authorization_domain (); } +static GDataFeed * +get_rules (GDataAccessHandler *self, + GDataService *service, + GCancellable *cancellable, + GDataQueryProgressCallback progress_callback, + gpointer progress_user_data, + GError **error) +{ + GDataAccessHandlerIface *iface; + GDataAuthorizationDomain *domain = NULL; + GDataFeed *feed; + GDataLink *_link; + SoupMessage *message; + + _link = gdata_entry_look_up_link (GDATA_ENTRY (self), + GDATA_LINK_ACCESS_CONTROL_LIST); + g_assert (_link != NULL); + + iface = GDATA_ACCESS_HANDLER_GET_IFACE (self); + if (iface->get_authorization_domain != NULL) { + domain = iface->get_authorization_domain (self); + } + + message = _gdata_service_query (service, domain, + gdata_link_get_uri (_link), NULL, + cancellable, error); + if (message == NULL) { + return NULL; + } + + g_assert (message->response_body->data != NULL); + + feed = _gdata_feed_new_from_json (GDATA_TYPE_FEED, + message->response_body->data, + message->response_body->length, + GDATA_TYPE_CALENDAR_ACCESS_RULE, + progress_callback, progress_user_data, + error); + + g_object_unref (message); + + return feed; +} + static void gdata_calendar_calendar_access_handler_init (GDataAccessHandlerIface *iface) { iface->is_owner_rule = is_owner_rule; iface->get_authorization_domain = get_authorization_domain; + iface->get_rules = get_rules; } static void @@ -443,15 +489,25 @@ parse_json (GDataParsable *parsable, JsonReader *reader, gpointer user_data, GEr const gchar *id; gchar *uri; - /* Calendar entries don’t contain their own selfLink, so we have - * to add one manually. */ id = json_reader_get_string_value (reader); if (id != NULL && *id != '\0') { + /* Calendar entries don’t contain their own selfLink, + * so we have to add one manually. */ uri = g_strconcat ("https://www.googleapis.com/calendar/v3/calendars/", id, NULL); _link = gdata_link_new (uri, GDATA_LINK_SELF); gdata_entry_add_link (GDATA_ENTRY (parsable), _link); g_object_unref (_link); g_free (uri); + + /* Similarly for the ACL link. */ + uri = g_strconcat ("https://www.googleapis.com" + "/calendar/v3/calendars/", id, + "/acl", NULL); + _link = gdata_link_new (uri, + GDATA_LINK_ACCESS_CONTROL_LIST); + gdata_entry_add_link (GDATA_ENTRY (parsable), _link); + g_object_unref (_link); + g_free (uri); } return GDATA_PARSABLE_CLASS (gdata_calendar_calendar_parent_class)->parse_json (parsable, reader, user_data, error); diff --git a/gdata/services/calendar/gdata-calendar-calendar.h b/gdata/services/calendar/gdata-calendar-calendar.h index 37a368ff..01106e2d 100644 --- a/gdata/services/calendar/gdata-calendar-calendar.h +++ b/gdata/services/calendar/gdata-calendar-calendar.h @@ -28,52 +28,6 @@ G_BEGIN_DECLS -/** - * GDATA_CALENDAR_ACCESS_ROLE_READ: - * - * The users specified by the #GDataAccessRule have read-only access to the calendar. - * - * Since: 0.7.0 - **/ -#define GDATA_CALENDAR_ACCESS_ROLE_READ "http://schemas.google.com/gCal/2005#read" - -/** - * GDATA_CALENDAR_ACCESS_ROLE_FREE_BUSY: - * - * The users specified by the #GDataAccessRule can only see the free/busy information on the calendar; not event details. - * - * Since: 0.7.0 - **/ -#define GDATA_CALENDAR_ACCESS_ROLE_FREE_BUSY "http://schemas.google.com/gCal/2005#freebusy" - -/** - * GDATA_CALENDAR_ACCESS_ROLE_EDITOR: - * - * The users specified by the #GDataAccessRule have full edit access to the calendar, except they can't change the calendar's access rules. - * - * Since: 0.7.0 - **/ -#define GDATA_CALENDAR_ACCESS_ROLE_EDITOR "http://schemas.google.com/gCal/2005#editor" - -/** - * GDATA_CALENDAR_ACCESS_ROLE_OWNER: - * - * The users specified by the #GDataAccessRule have full owner access to the calendar. - * - * Since: 0.7.0 - **/ -#define GDATA_CALENDAR_ACCESS_ROLE_OWNER "http://schemas.google.com/gCal/2005#owner" - -/** - * GDATA_CALENDAR_ACCESS_ROLE_ROOT: - * - * The users specified by the #GDataAccessRule have full administrator access to the calendar server. - * This is only available in Google Apps For Your Domain. - * - * Since: 0.7.0 - **/ -#define GDATA_CALENDAR_ACCESS_ROLE_ROOT "http://schemas.google.com/gCal/2005#root" - #define GDATA_TYPE_CALENDAR_CALENDAR (gdata_calendar_calendar_get_type ()) #define GDATA_CALENDAR_CALENDAR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDATA_TYPE_CALENDAR_CALENDAR, GDataCalendarCalendar)) #define GDATA_CALENDAR_CALENDAR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDATA_TYPE_CALENDAR_CALENDAR, GDataCalendarCalendarClass)) |