16 dicembre 2014 13:19
Accedere ai Google Calendars con un ServiceAccount e le API v3
Mi sono trovato nell'obbligata necessità di dover aggiornare un mio piccolo progetto alla versione v3 delle Google API e più precisamente delle Google Calendar API. In breve si tratta di un servizio (scritto in C# e che sfrutta le Client Library .NET) che periodicamente legge i calendari di tutti i collaboratori e scrive alcuni impegni/appuntamenti sulla dashboard della nostra intranet.
Siccome la documentazione e gli esempi forniti da Google sono a mio avviso spesso deficitari e di scarsa qualità (da un mio tweet di ieri forse non si capiva bene che ritengo la documentazione di Microsoft di qualità notevolmente migliore!), cerco di riassumere qui gli step necessari per arrivare all'obiettivo.
Creare il progetto
E' ora obbligatorio creare nella Developers Console il proprio progetto; Google infatti si riserva di monetizzare l'uso delle proprie API se queste superano il numero massimo di chiamate/connessioni e quindi diventa obbligatorio far tracciare la propria applicazione.
Una volta creato è necessario abilitare le Google Calendar API per quel progetto in quanto non lo sono per default
Successivamente dobbiamo creare un Service Account, dal menu Credentials
Che ci fornirà 3 informazioni che ci saranno utili dopo: il ClientID, un emailAddress e un file .p12 per il certificato X-509
Google Apps Admin Settings
L'amministratore del dominio delle Google Apps, deve fare queste due modifiche nella console di Admin:
Sotto Security (se non la vedete nelal pagina iniziale cliccate in basso more), scegliere Advanced Settings (ancora una votla premere more se è nascosta) e il punto di menu Manage API client access
Autorizzare il nostro client inserendo il ClientID ottenuto prima e come scope quello che ci serve (read/write o read-only)
Siccome il servizio deve poter leggere tutte le informazioni dell'evento (non solo la data) sarà necessario che ogni utente autorizzi quell'email @developer.gserviceaccount.com al setting "See all event details".
Per fare ciò prima però l'admin di dominio deve andare sotto Apps > Google Apps > Calendar e sotto Sharing Settings attivare l'opzione di Share all information anche per gli "external sharing" (di default sono disattivati)
Personal Calendar Settings
Come appena specificato, ogni persona deve autorizzare dal proprio calendario l'utente applicativo, tramite la sua email @developer.gserviceaccount.com, a vedere i propri eventi.
Codice .NET
Prima di tutto bisogna autorizzare il nostro client ad accedere alle API tramite le informazioni che abbiamo ricavato dai punti sopra
string serviceAccountEmail = "...fifk39l0@developer.gserviceaccount.com";
string filepath = "MyKeyFile.p12";
var certificate = new X509Certificate2(filepath, "mysecretpwd", X509KeyStorageFlags.Exportable);
ServiceAccountCredential credential = new ServiceAccountCredential(new
ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes =
new[] { CalendarService.Scope.Calendar }
}.FromCertificate
(certificate));
BaseClientService.Initializer initializer = new
BaseClientService.Initializer();
initializer.HttpClientInitializer = credential;
initializer.ApplicationName = "IntranetGCal";
CalendarService calservice = new CalendarService(initializer);
Poi andremo a fare la richiesta vera e propria (nell'esempio gli eventi da oggi a +7 giorni)
EventsResource.ListRequest req = calservice.Events.List("myEmail@myDomain.com");
req.TimeMin = DateTime.Now.Date;
req.TimeMax = DateTime.Now.AddDays(7).Date;
req.SingleEvents = true;
req.OrderBy = EventsResource.ListRequest.OrderByEnum.StartTime;
Events events = req.Execute();
Otterremo una lista di Event con tutte le proprietà che ci servono; nell'esempio sottostante riempio una mia custom entity CalendarEvent con alcune di esse.
foreach (Google.Apis.Calendar.v3.Data.Event eventdata in events.Items)
{
if (eventdata.Visibility != "private")
{
CalendarEvent item = new CalendarEvent
{
GoogleUniqueID = eventdata.Id,
Title = eventdata.Summary,
Description = eventdata.Description,
Location = eventdata.Location,
};
EventDateTime start = eventdata.Start;
item.DateFrom = start.DateTime.HasValue ? start.DateTime : Convert.ToDateTime(start.Date);
EventDateTime end = eventdata.End;
item.DateTo = end.DateTime.HasValue ? end.DateTime : Convert.ToDateTime(end.Date);
item.isAllDay = (start.DateTime == null);
//...
}
}
Ultima nota: per l'uso delle Google API su una macchina che ha solo il framework 4.0 è necessaria la patch KB2468871:
http://www.microsoft.com/en-us/download/details.aspx?id=3556