From e6c65019b03fb43f8c4da5ee9c679806960cc055 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sun, 1 Nov 2015 23:05:17 +0100 Subject: [PATCH] WIP booking * CalAuth.aspx: A view ... still unused * style.css: css overflow-y auto, the container making it modal has no margin. * GoogleController.cs: Fixes again the calendar usage, uses Google API key and client credentials found in configuration file * ApiClient.cs: Google API key and client credentials are now found in configuration file * CalendarApi.cs: Let the controller build the credential string from thr profile object. * OAuth2.cs: The OAuth2 Client only needs a client id and secret * yavsc.js: Fixes some css flipping * ValidateAjaxAttribute.cs: A FIXME * Web.config: Google key, client id and secret come from application settings * Web.csproj: a page in more * YavscModel.csproj: * PostInfoByUser.cs: * PostInfoByTitle.cs: * BlogEntryCollection.cs: refactoring --- web/App_Themes/style.css | 13 +++--- web/ChangeLog | 29 ++++++++++++++ web/Controllers/GoogleController.cs | 53 ++++++++++++++----------- web/Helpers/Google/ApiClient.cs | 7 ++-- web/Helpers/Google/CalendarApi.cs | 13 ++++-- web/Helpers/Google/OAuth2.cs | 28 ++++++------- web/Scripts/yavsc.js | 2 +- web/ValidateAjaxAttribute.cs | 2 +- web/Views/Google/CalAuth.aspx | 5 +++ web/Web.config | 5 ++- web/Web.csproj | 1 + yavscModel/Blogs/BlogEntryCollection.cs | 10 ++--- yavscModel/Blogs/PostInfoByTitle.cs | 44 -------------------- yavscModel/Blogs/PostInfoByUser.cs | 43 -------------------- yavscModel/ChangeLog | 7 ++++ yavscModel/YavscModel.csproj | 2 - 16 files changed, 117 insertions(+), 147 deletions(-) create mode 100644 web/Views/Google/CalAuth.aspx delete mode 100644 yavscModel/Blogs/PostInfoByTitle.cs delete mode 100644 yavscModel/Blogs/PostInfoByUser.cs diff --git a/web/App_Themes/style.css b/web/App_Themes/style.css index def6e990..abb81380 100644 --- a/web/App_Themes/style.css +++ b/web/App_Themes/style.css @@ -27,7 +27,7 @@ body { url('/images/FhHRx.gif') 50% 50% no-repeat; - overflow: scroll; + overflow: auto; } .dispmodal { position: fixed; @@ -35,7 +35,9 @@ body { top: 0; left: 0; right: 0; - overflow: scroll; + width: 100%; + overflow-y: auto; + overflow-x: hidden; } body.loading { @@ -218,9 +220,6 @@ label { border-radius: 1em; border: dashed rgb(020,20,256) 2px; } -#notifications { - padding: 1em; - } .notification { font-size: large; @@ -368,7 +367,8 @@ header h1, header a , .actionlink, .menuitem, a { padding:.5em;} margin:.5em; padding:.5em; } - #notifications { + + .notification { padding: .5em; border-radius:.5em; margin:.5em; @@ -398,6 +398,7 @@ header { padding-bottom:.5em; background: url("/images/star-939235_1280.xxs.jpg") 0 0 no-repeat fixed; } + header h1, header a { padding:.2em;} nav { diff --git a/web/ChangeLog b/web/ChangeLog index 07581992..3c949cc2 100644 --- a/web/ChangeLog +++ b/web/ChangeLog @@ -1,3 +1,32 @@ +2015-11-01 Paul Schneider + + * CalAuth.aspx: A view ... still unused + + * style.css: css overflow-y auto, the container making it + modal has no margin. + + * GoogleController.cs: Fixes again the calendar usage, + uses Google API key and client credentials found in + configuration file + + * ApiClient.cs: Google API key and client credentials are now + found in configuration file + + * CalendarApi.cs: Let the controller build the credential + string from thr profile object. + + * OAuth2.cs: The OAuth2 Client only needs a client id and + secret + + * yavsc.js: Fixes some css flipping + + * ValidateAjaxAttribute.cs: A FIXME + + * Web.config: Google key, client id and secret come from + application settings + + * Web.csproj: a page in more + 2015-11-01 Paul Schneider * Book-next.aspx: pollution diff --git a/web/Controllers/GoogleController.cs b/web/Controllers/GoogleController.cs index 5fefd126..332016d0 100644 --- a/web/Controllers/GoogleController.cs +++ b/web/Controllers/GoogleController.cs @@ -78,10 +78,12 @@ namespace Yavsc.Controllers if (string.IsNullOrWhiteSpace (returnUrl)) returnUrl = "/"; Session ["returnUrl"] = returnUrl; - OAuth2 oa = new OAuth2 (AuthGRU); + OAuth2 oa = new OAuth2 (AuthGRU,clientId,clientSecret); oa.Login (Response, SetSessionSate ()); } - + private string clientId = ConfigurationManager.AppSettings ["GOOGLE_CLIENT_ID"]; + private string clientSecret = ConfigurationManager.AppSettings ["GOOGLE_CLIENT_SECRET"]; + private string clientApiKey = ConfigurationManager.AppSettings ["GOOGLE_API_KEY"]; /// /// Gets the cal auth. /// @@ -91,8 +93,8 @@ namespace Yavsc.Controllers if (string.IsNullOrWhiteSpace (returnUrl)) returnUrl = "/"; Session ["returnUrl"] = returnUrl; - OAuth2 oa = new OAuth2 (CalendarGRU); - oa.GetCalAuth (Response, SetSessionSate ()); + OAuth2 oa = new OAuth2 (CalendarGRU,clientId,clientSecret); + oa.GetCalendarScope (Response, SetSessionSate ()); } /// @@ -105,16 +107,16 @@ namespace Yavsc.Controllers public ActionResult CalAuth () { string msg; - OAuth2 oa = new OAuth2 (CalendarGRU); + OAuth2 oa = new OAuth2 (CalendarGRU,clientId,clientSecret); - AuthToken gat = oa.GetToken (Request, (string)Session ["state"], out msg); + AuthToken gat = oa.GetToken (Request, (string) Session ["state"], out msg); if (gat == null) { YavscHelpers.Notify(ViewData, msg); return View ("Auth"); } SaveToken (HttpContext.Profile,gat); HttpContext.Profile.SetPropertyValue ("gcalapi", true); - string returnUrl = (string)Session ["returnUrl"]; + string returnUrl = (string) Session ["returnUrl"]; Session ["returnUrl"] = null; return Redirect (returnUrl); } @@ -143,7 +145,7 @@ namespace Yavsc.Controllers public ActionResult Auth () { string msg; - OAuth2 oa = new OAuth2 (AuthGRU); + OAuth2 oa = new OAuth2 (AuthGRU,clientId,clientSecret); AuthToken gat = oa.GetToken (Request, (string)Session ["state"], out msg); if (gat == null) { YavscHelpers.Notify(ViewData, msg); @@ -188,8 +190,8 @@ namespace Yavsc.Controllers ModelState.AddModelError ("UserName", "This user name already is in use"); return View (); } - string returnUrl = (string)Session ["returnUrl"]; - AuthToken gat = (AuthToken)Session ["GoogleAuthToken"]; + string returnUrl = (string) Session ["returnUrl"]; + AuthToken gat = (AuthToken) Session ["GoogleAuthToken"]; People me = (People)Session ["me"]; if (gat == null || me == null) throw new InvalidDataException (); @@ -232,8 +234,9 @@ namespace Yavsc.Controllers } if (me.url != null) HttpContext.Profile.SetPropertyValue ("WebSite", me.url); - SaveToken (HttpContext.Profile,gat); - // already done in SaveToken: HttpContext.Profile.Save (); + // Will be done in SaveToken: HttpContext.Profile.Save (); + SaveToken (HttpContext.Profile, gat); + Session ["returnUrl"] = null; return Redirect (returnUrl); } ViewData ["returnUrl"] = returnUrl; @@ -258,19 +261,17 @@ namespace Yavsc.Controllers [HttpGet] public ActionResult ChooseCalendar (string returnUrl) { - bool hasCalAuth = (bool)HttpContext.Profile.GetPropertyValue ("gcalapi"); - if (!hasCalAuth) { - Session ["returnUrl"] = Request.Url.Scheme + "://" + Request.Url.Authority + "/Google/ChooseCalendar"; + if (returnUrl != null) { + Session ["chooseCalReturnUrl"] = returnUrl; return RedirectToAction ("GetCalAuth", new { - returnUrl = "ChooseCalendar?returnUrl="+HttpUtility.UrlEncode(returnUrl) + returnUrl = Url.Action ("ChooseCalendar") // "ChooseCalendar?returnUrl="+HttpUtility.UrlEncode(returnUrl) }); } string cred = OAuth2.GetFreshGoogleCredential (HttpContext.Profile); - - CalendarApi c = new CalendarApi (); + CalendarApi c = new CalendarApi (clientApiKey); CalendarList cl = c.GetCalendars (cred); - ViewData ["returnUrl"] = returnUrl; + ViewData ["returnUrl"] = Session ["chooseCalReturnUrl"]; return View (cl); } @@ -300,7 +301,12 @@ namespace Yavsc.Controllers [Authorize,HttpGet] public ActionResult Book () { - return View (new BookQuery ()); + var model = new BookQuery (); + model.StartDate = DateTime.Now; + model.EndDate = model.StartDate.AddDays(2); + model.StartHour = DateTime.Now.ToString("HH:mm"); + model.EndHour = DateTime.Now.AddHours(1).ToString("HH:mm"); + return View (model); } /// @@ -313,7 +319,7 @@ namespace Yavsc.Controllers { if (ModelState.IsValid) { DateTime mindate = DateTime.Now; - if (model.StartDate < mindate){ + if (model.StartDate.Date < mindate.Date){ ModelState.AddModelError ("StartDate", LocalizedText.FillInAFutureDate); } if (model.EndDate < model.StartDate) @@ -333,10 +339,11 @@ namespace Yavsc.Controllers if (ModelState.IsValid) { string calid = (string) gcalid; DateTime maxdate = model.EndDate; - CalendarApi c = new CalendarApi (); + CalendarApi c = new CalendarApi (clientApiKey); CalendarEventList events; try { - events = c.GetCalendar (calid, mindate, maxdate, upr); + string creds = OAuth2.GetFreshGoogleCredential (upr); + events = c.GetCalendar (calid, mindate, maxdate, creds); YavscHelpers.Notify (ViewData, "Google calendar API call success"); } catch (WebException ex) { string response; diff --git a/web/Helpers/Google/ApiClient.cs b/web/Helpers/Google/ApiClient.cs index 3e7ac935..6c4ca425 100644 --- a/web/Helpers/Google/ApiClient.cs +++ b/web/Helpers/Google/ApiClient.cs @@ -40,16 +40,17 @@ namespace Yavsc.Helpers.Google /// /// The CLIENT Id. /// - protected static string CLIENT_ID = "325408689282-6bekh7p3guj4k0f3301a6frf025cnrk1.apps.googleusercontent.com"; + public static string CLIENT_ID { get ; set ; } + /// /// The CLIENt SECREt /// - protected static string CLIENT_SECRET = "MaxYcvJJCs2gDGvaELZbzwfL"; + public static string CLIENT_SECRET { get ; set ; } /// /// The API KEY. /// - protected static string API_KEY="AIzaSyBV_LQHb22nGgjNvFzZwnQHjao3Q7IewRw"; + public static string API_KEY { get ; set ; } /* // to use in descendence * protected static string getPeopleUri = "https://www.googleapis.com/plus/v1/people"; diff --git a/web/Helpers/Google/CalendarApi.cs b/web/Helpers/Google/CalendarApi.cs index 1f686936..a0d5d1cf 100644 --- a/web/Helpers/Google/CalendarApi.cs +++ b/web/Helpers/Google/CalendarApi.cs @@ -36,8 +36,12 @@ namespace Yavsc.Helpers.Google /// /// Google Calendar API client. /// - public class CalendarApi: ApiClient + public class CalendarApi : ApiClient { + public CalendarApi(string apiKey) + { + API_KEY = apiKey; + } /// /// The get cal list URI. /// @@ -87,8 +91,11 @@ namespace Yavsc.Helpers.Google /// Mindate. /// Maxdate. /// Upr. - public CalendarEventList GetCalendar (string calid, DateTime mindate, DateTime maxdate, ProfileBase upr) + public CalendarEventList GetCalendar (string calid, DateTime mindate, DateTime maxdate,string cred) { + if (string.IsNullOrWhiteSpace (calid)) + throw new Exception ("the calendar identifier is not specified"); + string uri = string.Format ( getCalEntriesUri, HttpUtility.UrlEncode (calid)) + string.Format ("?orderBy=startTime&singleEvents=true&timeMin={0}&timeMax={1}&key=" + API_KEY, @@ -96,7 +103,7 @@ namespace Yavsc.Helpers.Google HttpUtility.UrlEncode (maxdate.ToString (dateFormat) + timeZone)); HttpWebRequest webreq = WebRequest.CreateHttp (uri); - string cred = OAuth2.GetFreshGoogleCredential (upr); + webreq.Headers.Add (HttpRequestHeader.Authorization, cred); webreq.Method = "GET"; webreq.ContentType = "application/http"; diff --git a/web/Helpers/Google/OAuth2.cs b/web/Helpers/Google/OAuth2.cs index f1a5bffc..129b74f7 100644 --- a/web/Helpers/Google/OAuth2.cs +++ b/web/Helpers/Google/OAuth2.cs @@ -36,7 +36,7 @@ namespace Yavsc.Helpers.Google /// /// Google O auth2 client. /// - public class OAuth2:ApiClient + public class OAuth2 : ApiClient { /// /// The URI used to get tokens. @@ -58,9 +58,11 @@ namespace Yavsc.Helpers.Google /// Initializes a new instance of the class. /// /// Redirect URI. - public OAuth2 (string redirectUri) + public OAuth2 (string redirectUri, string clientId, string clientSecret) { RedirectUri = redirectUri; + CLIENT_ID = clientId; + CLIENT_SECRET = clientSecret; } /// @@ -84,12 +86,10 @@ namespace Yavsc.Helpers.Google /// /// Bresp. /// State. - public void GetCalAuth (HttpResponseBase bresp, string state) + public void GetCalendarScope (HttpResponseBase bresp, string state) { - string scope = string.Join ("%20", scopeOpenid); - scope = string.Join ("%20", scopeCalendar); - string prms = String.Format ("response_type=code&client_id={0}&redirect_uri={1}&scope={2}&state={3}&include_granted_scopes=false&access_type=offline", - CLIENT_ID, RedirectUri, scope, state); + string prms = String.Format ("response_type=code&client_id={0}&redirect_uri={1}&scope={2}&state={3}&include_granted_scopes=true&access_type=offline&approval_prompt=force", + CLIENT_ID, RedirectUri, scopeCalendar, state); GetAuthResponse (bresp, prms); } @@ -230,16 +230,14 @@ namespace Yavsc.Helpers.Google DateTime token_exp = (DateTime) pr.GetPropertyValue ("gtokenexpir"); if (token_exp < DateTime.Now) { object ort = pr.GetPropertyValue ("grefreshtoken"); - if (ort == null || ort is DBNull) { + if (ort is DBNull || string.IsNullOrWhiteSpace((string)ort)) { throw new InvalidOAuth2RefreshToken ("Google"); } - else { - string refresh_token = ort as string; - AuthToken gat = OAuth2.GetTokenPosting ( - string.Format ("grant_type=refresh_token&client_id={0}&client_secret={1}&refresh_token={2}", - CLIENT_ID, CLIENT_SECRET, refresh_token)); - token = gat.access_token; - } + string refresh_token = ort as string; + AuthToken gat = OAuth2.GetTokenPosting ( + string.Format ("grant_type=refresh_token&client_id={0}&client_secret={1}&refresh_token={2}", + CLIENT_ID, CLIENT_SECRET, refresh_token)); + token = gat.access_token; pr.SetPropertyValue ("gtoken", token); pr.Save (); // ASSERT gat.token_type == pr.GetPropertyValue("gtokentype") diff --git a/web/Scripts/yavsc.js b/web/Scripts/yavsc.js index be74cfde..52b72288 100644 --- a/web/Scripts/yavsc.js +++ b/web/Scripts/yavsc.js @@ -47,7 +47,7 @@ self.ajax = function (method,data,callback) { self.onScroll = function() { var $notifications = $('#notifications'); if ($notifications.has('*').length>0) { - if ($(window).scrollTop()>100) { + if ($(window).scrollTop()>0) { $notifications.addClass("dispmodal"); } else { diff --git a/web/ValidateAjaxAttribute.cs b/web/ValidateAjaxAttribute.cs index 66b51ec6..391b3d4d 100644 --- a/web/ValidateAjaxAttribute.cs +++ b/web/ValidateAjaxAttribute.cs @@ -43,7 +43,7 @@ namespace Yavsc where modelState[x].Errors.Count > 0 select new { - // FIXME why? + // FIXME why not directly underscores? key = x.Replace(".","_"), errors = modelState[x].Errors. Select(y => y.ErrorMessage). diff --git a/web/Views/Google/CalAuth.aspx b/web/Views/Google/CalAuth.aspx new file mode 100644 index 00000000..7825a886 --- /dev/null +++ b/web/Views/Google/CalAuth.aspx @@ -0,0 +1,5 @@ +<%@ Page Title="Catalog" Language="C#" Inherits="System.Web.Mvc.ViewPage" MasterPageFile="~/Models/App.master" %> + + + + diff --git a/web/Web.config b/web/Web.config index f9803808..e254f986 100644 --- a/web/Web.config +++ b/web/Web.config @@ -267,5 +267,8 @@ http://msdn2.microsoft.com/en-us/library/b5ysx397.aspx - + + + + diff --git a/web/Web.csproj b/web/Web.csproj index 2d99aaae..05c7f73a 100644 --- a/web/Web.csproj +++ b/web/Web.csproj @@ -468,6 +468,7 @@ + diff --git a/yavscModel/Blogs/BlogEntryCollection.cs b/yavscModel/Blogs/BlogEntryCollection.cs index f2c8ffaa..02b48d17 100644 --- a/yavscModel/Blogs/BlogEntryCollection.cs +++ b/yavscModel/Blogs/BlogEntryCollection.cs @@ -82,13 +82,13 @@ namespace Yavsc.Model.Blogs /// /// Groups by title. /// - public IEnumerable> GroupByTitle () + public IEnumerable> GroupByTitle () { bool truncated; return from be in this orderby be.Posted descending - group - new PostInfoByTitle { Author = be.Author, Id = be.Id, + group + new BasePostInfo { Author = be.Author, Id = be.Id, Posted = be.Posted, Modified = be.Modified, Intro = MarkdownHelper.MarkdownIntro (be.Content, out truncated), Visible = be.Visible, @@ -103,13 +103,13 @@ namespace Yavsc.Model.Blogs /// Groups by user. /// /// The by user. - public IEnumerable> GroupByUser () + public IEnumerable> GroupByUser () { bool truncated; return from be in this orderby be.Posted descending group - new PostInfoByUser { + new BasePostInfo { Title = be.Title, Id = be.Id, Posted = be.Posted, diff --git a/yavscModel/Blogs/PostInfoByTitle.cs b/yavscModel/Blogs/PostInfoByTitle.cs deleted file mode 100644 index 339f8a67..00000000 --- a/yavscModel/Blogs/PostInfoByTitle.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// PostInfoByTitle.cs -// -// Author: -// Paul Schneider -// -// Copyright (c) 2015 GNU GPL -// -// This program 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 3 of the License, or -// (at your option) any later version. -// -// This program 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 this program. If not, see . - -using System; -using System.Configuration; -using System.Collections.Generic; -using Yavsc.Model.Blogs; -using System.Linq; -using Yavsc.Model.Circles; - -namespace Yavsc.Model.Blogs -{ - - /// - /// Post info. - /// - public class PostInfoByTitle : BasePostInfo { - - /// - /// The name of the user. - /// - public string Author; - - } - -} diff --git a/yavscModel/Blogs/PostInfoByUser.cs b/yavscModel/Blogs/PostInfoByUser.cs deleted file mode 100644 index ef938ff2..00000000 --- a/yavscModel/Blogs/PostInfoByUser.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// PostInfoByUser.cs -// -// Author: -// Paul Schneider -// -// Copyright (c) 2015 GNU GPL -// -// This program 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 3 of the License, or -// (at your option) any later version. -// -// This program 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 this program. If not, see . - -using System; -using System.Configuration; -using System.Collections.Generic; -using Yavsc.Model.Blogs; -using System.Linq; -using Yavsc.Model.Circles; - -namespace Yavsc.Model.Blogs -{ - - /// - /// Post info by user. - /// - public class PostInfoByUser : BasePostInfo { - - /// - /// The name of the user. - /// - public string Title; - } - -} diff --git a/yavscModel/ChangeLog b/yavscModel/ChangeLog index 2dfdca51..332ce831 100644 --- a/yavscModel/ChangeLog +++ b/yavscModel/ChangeLog @@ -1,3 +1,10 @@ +2015-11-01 Paul Schneider + + * YavscModel.csproj: + * PostInfoByUser.cs: + * PostInfoByTitle.cs: + * BlogEntryCollection.cs: refactoring + 2015-11-01 Paul Schneider * ProfileEdition.cs: Fixes the username modification diff --git a/yavscModel/YavscModel.csproj b/yavscModel/YavscModel.csproj index c9db0b94..5780f8f9 100644 --- a/yavscModel/YavscModel.csproj +++ b/yavscModel/YavscModel.csproj @@ -170,8 +170,6 @@ - -