Many fixes

* Profile.aspx:
* ProfileEdition.cs: Fixes the username modification

* Book-next.aspx: pollution

* NpgsqlMembershipProvider.cs: xmldoc

* NpgsqlProfileProvider.cs: use default values from configuration

* NpgsqlUserNameProvider.cs: Fixes the username detection

* test-domain-TestAPI.config: profile dates must be returned as
  DateTime

* instdbws.sql: The conversion to a valid .Net DateTime requires a
  credible date time as source value, the null one is not supported.

* style.css: Fixes the new notification style

* AccountController.cs: Fixes the profile edition.
Now using the anti forgery key at login time

* Book.aspx:
* LocalizedText.resx:
* LocalizedText.fr.resx:
* CalendarApi.cs:
* GoogleController.cs:
* LocalizedText.Designer.cs:
* LocalizedText.fr.Designer.cs: WIP booking

* HomeController.cs: code prettying

* Global.asax.cs: Limits the usage of titles in a route to the blog
  controller

* OAuth2.cs: Profile values may be of type DBNull ...

* T.cs: All translated strings will be Html encoded, as expected from
  an html helper

* YavscHelpers.cs: A new method to build a javascript string...

* App.master:
* AppAdmin.master: Notification.body is now a js string literal

* NoLogin.master: sync with the true master

* Login.aspx: Permits the anti forgery key usage

* Estimate.aspx: refactoring

* Web.config: Fixes a later commit on the catalog name space

* Web.csproj: An ajax helper to notify

* ChangePasswordModel.cs:
* RegisterClientModel.cs: A regexp for user name

* LoginModel.cs: A regexp for user name and password

* Profile.cs: A regexp for user name, and profile usage fixes

* UserManager.cs: Checks for username availability before trying to
  modify it

* YavscModel.csproj: `ProfileEdition` class addition

* ChangeLog: should not be indexed

* ChangeLog: useless here

* ValidateAjaxAttribute.cs: Fixes usage of HtmlFieldPrefix

* BookQuery.cs: Start, end hour and role are required

* OtherWebException.cs: useless
main
Paul Schneider 10 years ago
parent 0a91d3935b
commit d9d5bb308e
42 changed files with 441 additions and 275 deletions

@ -1,3 +1,12 @@
2015-11-01 Paul Schneider <paul@pschneider.fr>
* NpgsqlMembershipProvider.cs: xmldoc
* NpgsqlProfileProvider.cs: use default values from
configuration
* NpgsqlUserNameProvider.cs: Fixes the username detection
2015-10-28 Paul Schneider <paul@pschneider.fr> 2015-10-28 Paul Schneider <paul@pschneider.fr>
* NpgsqlProfileProvider.cs: Fixes the defaultValue * NpgsqlProfileProvider.cs: Fixes the defaultValue

@ -951,11 +951,13 @@ namespace Npgsql.Web
// //
// MembershipProvider.ValidateUser // MembershipProvider.ValidateUser
// //
/// <Docs>To be added.</Docs> /// <Docs>Validates an user identification by password,
/// and, when he's approuved, updates its last login date and
/// returns true.</Docs>
/// <summary> /// <summary>
/// Validates the user. /// Validates the user at login time.
/// </summary> /// </summary>
/// <returns><c>true</c>, if user was validated, <c>false</c> otherwise.</returns> /// <returns><c>true</c>, if user was approuved and its password is valid, <c>false</c> otherwise.</returns>
/// <param name="username">Username.</param> /// <param name="username">Username.</param>
/// <param name="password">Password.</param> /// <param name="password">Password.</param>
public override bool ValidateUser (string username, string password) public override bool ValidateUser (string username, string password)

@ -221,7 +221,7 @@ namespace Npgsql.Web
} else { } else {
foreach (SettingsProperty p in collection) { foreach (SettingsProperty p in collection) {
SettingsPropertyValue v = new SettingsPropertyValue (p); SettingsPropertyValue v = new SettingsPropertyValue (p);
v.PropertyValue = p.DefaultValue; v.PropertyValue = GetDefaultValue(p);
c.Add (v); c.Add (v);
} }
} }
@ -230,6 +230,24 @@ namespace Npgsql.Web
return c; return c;
} }
private object GetDefaultValue(SettingsProperty setting)
{
if (setting.PropertyType.IsEnum)
return Enum.Parse(setting.PropertyType, setting.DefaultValue.ToString());
// Return the default value if it is set
// Return the default value if it is set
if (setting.DefaultValue != null)
{
System.ComponentModel.TypeConverter tc = System.ComponentModel.TypeDescriptor.GetConverter(setting.PropertyType);
return tc.ConvertFromString(setting.DefaultValue.ToString());
}
else // If there is no default value return the default object
{
return Activator.CreateInstance(setting.PropertyType);
}
}
/// <summary> /// <summary>
/// Sets the property values. /// Sets the property values.
/// </summary> /// </summary>

@ -91,7 +91,7 @@ namespace Npgsql.Web.RolesAndMembers
using (NpgsqlConnection conn = new NpgsqlConnection (connectionString)) { using (NpgsqlConnection conn = new NpgsqlConnection (connectionString)) {
conn.Open (); conn.Open ();
using (NpgsqlCommand cmd = new NpgsqlCommand ( using (NpgsqlCommand cmd = new NpgsqlCommand (
"SELECT count(*)>0 FROM users " + "SELECT count(*)=0 FROM users " +
"WHERE username = :uname AND ApplicationName = :appname", conn)) { "WHERE username = :uname AND ApplicationName = :appname", conn)) {
cmd.Parameters.AddWithValue ("uname", name); cmd.Parameters.AddWithValue ("uname", name);
cmd.Parameters.AddWithValue ("appname", this.applicationName); cmd.Parameters.AddWithValue ("appname", this.applicationName);

@ -1,3 +1,8 @@
2015-11-01 Paul Schneider <paul@pschneider.fr>
* test-domain-TestAPI.config: profile dates must be returned
as DateTime
2015-10-17 Paul Schneider <paul@pschneider.fr> 2015-10-17 Paul Schneider <paul@pschneider.fr>
* AllTests.cs: * AllTests.cs:

@ -92,8 +92,8 @@
<add name="gtoken" /> <add name="gtoken" />
<add name="grefreshtoken" /> <add name="grefreshtoken" />
<add name="gtokentype" /> <add name="gtokentype" />
<add name="gtokenexpir" /> <add name="gtokenexpir" type="System.DateTime"/>
<add name="gcalapi" /> <add name="gcalapi" type="System.Boolean"/>
<add name="gcalid" /> <add name="gcalid" />
<add name="gregid" /> <add name="gregid" />
</properties> </properties>

@ -118,7 +118,7 @@ CREATE TABLE profiledata
grefreshtoken character varying(512), -- Google refresh token grefreshtoken character varying(512), -- Google refresh token
gtokentype character varying(256), -- Google access token type gtokentype character varying(256), -- Google access token type
gcalid character varying(255), -- Google calendar identifier gcalid character varying(255), -- Google calendar identifier
gtokenexpir timestamp with time zone, -- Google access token expiration date gtokenexpir timestamp with time zone NOT NULL DEFAULT now(), -- Google access token expiration date
avatar character varying(512), -- url for an avatar avatar character varying(512), -- url for an avatar
gcalapi boolean NOT NULL DEFAULT false, gcalapi boolean NOT NULL DEFAULT false,
gregid character varying(1024), -- Google Cloud Message registration identifier gregid character varying(1024), -- Google Cloud Message registration identifier
@ -211,7 +211,7 @@ CREATE TABLE commandes
id bigserial NOT NULL, -- Identifiant unique de commande e, cours id bigserial NOT NULL, -- Identifiant unique de commande e, cours
validation date, -- Date de validation validation date, -- Date de validation
prdref character varying(255) NOT NULL, -- Product reference from the unique valid catalog at the validation date prdref character varying(255) NOT NULL, -- Product reference from the unique valid catalog at the validation date
creation timestamp with time zone, -- creation date creation timestamp with time zone NOT NULL, -- creation date
clientname character varying(255), -- user who created the command, client of this command clientname character varying(255), -- user who created the command, client of this command
applicationname character varying(255), -- application concerned by this command applicationname character varying(255), -- application concerned by this command
params json, params json,

@ -34,8 +34,7 @@ body {
z-index: 1000; z-index: 1000;
top: 0; top: 0;
left: 0; left: 0;
height: 100%; right: 0;
width: 100%;
overflow: scroll; overflow: scroll;
} }
@ -60,7 +59,7 @@ header {
transition: margin 2s, padding 2s; transition: margin 2s, padding 2s;
padding: 0; padding: 0;
margin: 0; margin: 0;
padding-top: 201px; padding-top: 2em;
padding-bottom:2em; padding-bottom:2em;
display: block; display: block;
background: url("/images/star-939235_1280.jpg") -3em -3em no-repeat fixed; background: url("/images/star-939235_1280.jpg") -3em -3em no-repeat fixed;
@ -145,8 +144,8 @@ aside {
border-radius:1em; border-radius:1em;
} }
.postpreview video, .postpreview img { .postpreview video, .postpreview img {
max-width:100%; max-width: 100%;
max-height:5em; padding: 1em;
} }
.post { .post {
display:block; display:block;
@ -266,7 +265,7 @@ a {
.actionlink, .menuitem, a { .actionlink, .menuitem, a {
display:inline-block; display:inline-block;
color: white; color: yellow;
border-radius:1em; border-radius:1em;
border: solid black 1px; border: solid black 1px;
background-color: rgba(20,20,20,.8); background-color: rgba(20,20,20,.8);
@ -340,6 +339,7 @@ a:active {
@media all and (max-width: 640px) { @media all and (max-width: 640px) {
header { header {
padding-top:1em;
padding-bottom:1em; padding-bottom:1em;
background: url("/images/star-939235_1280.s.jpg") 0 0 no-repeat fixed; background: url("/images/star-939235_1280.s.jpg") 0 0 no-repeat fixed;
} }
@ -394,8 +394,8 @@ header h1, header a , .actionlink, .menuitem, a { padding:.5em;}
@media all and (max-width: 350px) { @media all and (max-width: 350px) {
header { header {
padding-top: 101px; padding-top:.5em;
padding-bottom:1em; padding-bottom:.5em;
background: url("/images/star-939235_1280.xxs.jpg") 0 0 no-repeat fixed; background: url("/images/star-939235_1280.xxs.jpg") 0 0 no-repeat fixed;
} }
header h1, header a { padding:.2em;} header h1, header a { padding:.2em;}

@ -1,3 +1,72 @@
2015-11-01 Paul Schneider <paul@pschneider.fr>
* Book-next.aspx: pollution
* instdbws.sql: The conversion to a valid .Net DateTime
requires a credible date time as source value, the null one is
not supported.
* style.css: Fixes the new notification style
* AccountController.cs: Fixes the profile edition.
Now using the anti forgery key at login time
* Book.aspx:
* CalendarApi.cs:
* GoogleController.cs: WIP booking
* HomeController.cs: code prettying
* Global.asax.cs: Limits the usage of titles in a route to the
blog controller
* OAuth2.cs: Profile values may be of type DBNull ...
* T.cs: All translated strings will be Html encoded, as
expected from an html helper
* YavscHelpers.cs: A new method to build a javascript
string...
* App.master:
* AppAdmin.master: Notification.body is now a js string
literal
* NoLogin.master: sync with the true master
* Login.aspx: Permits the anti forgery key usage
* Profile.aspx: Fixes the username modification
* Estimate.aspx: refactoring
* Web.config: Fixes a later commit on the catalog name space
* Web.csproj: An ajax helper to notify
* ChangeLog: should not be indexed
* ValidateAjaxAttribute.cs: Fixes usage of HtmlFieldPrefix
2015-10-31 Paul Schneider <paul@pschneider.fr>
* Web.csproj:
* Web.config:
* T.cs:
* Global.asax.cs:
* App.master:
* Book.aspx:
* YavscHelpers.cs:
* OAuth2.cs:
* Profile.aspx:
* YavscAjaxHelper.cs:
* Book-next.aspx:
* CalendarApi.cs:
* HomeController.cs:
* GoogleController.cs:
* Estimate.aspx:
* AccountController.cs:
2015-10-30 Paul Schneider <paul@pschneider.fr> 2015-10-30 Paul Schneider <paul@pschneider.fr>
* packages.config: * packages.config:

@ -16,6 +16,7 @@ using System.Collections.Specialized;
using System.Text; using System.Text;
using System.Net; using System.Net;
using System.Configuration; using System.Configuration;
using Yavsc.Model;
namespace Yavsc.Controllers namespace Yavsc.Controllers
{ {
@ -61,7 +62,7 @@ namespace Yavsc.Controllers
/// <returns>The login.</returns> /// <returns>The login.</returns>
/// <param name="model">Model.</param> /// <param name="model">Model.</param>
/// <param name="returnUrl">Return URL.</param> /// <param name="returnUrl">Return URL.</param>
[HttpPost] [HttpPost,ValidateAntiForgeryToken]
public ActionResult Login (LoginModel model, string returnUrl) public ActionResult Login (LoginModel model, string returnUrl)
{ {
if (ModelState.IsValid) { if (ModelState.IsValid) {
@ -187,7 +188,7 @@ namespace Yavsc.Controllers
ViewData ["UserName"] = id; ViewData ["UserName"] = id;
if (!confirmed) if (!confirmed)
return View (); return View ();
string logged = Membership.GetUser ().UserName; string logged = this.User.Identity.Name;
if (logged != id) if (logged != id)
if (!Roles.IsUserInRole ("Admin")) if (!Roles.IsUserInRole ("Admin"))
throw new Exception ("Unregister another user"); throw new Exception ("Unregister another user");
@ -250,7 +251,7 @@ namespace Yavsc.Controllers
if (id == null) if (id == null)
id = Membership.GetUser ().UserName; id = Membership.GetUser ().UserName;
ViewData ["UserName"] = id; ViewData ["UserName"] = id;
Profile model = new Profile (ProfileBase.Create (id)); ProfileEdition model = new ProfileEdition (ProfileBase.Create (id));
model.RememberMe = FormsAuthentication.GetAuthCookie (id, true) == null; model.RememberMe = FormsAuthentication.GetAuthCookie (id, true) == null;
return View (model); return View (model);
} }
@ -265,20 +266,32 @@ namespace Yavsc.Controllers
/// <param name="AvatarFile">Avatar file.</param> /// <param name="AvatarFile">Avatar file.</param>
[Authorize] [Authorize]
[HttpPost] [HttpPost]
public ActionResult Profile (string id, Profile model, HttpPostedFileBase AvatarFile) public ActionResult Profile (string id, ProfileEdition model, HttpPostedFileBase AvatarFile)
{ {
// ASSERT("Membership.GetUser ().UserName is made of simple characters, no slash nor backslash" string logdu = User.Identity.Name;
if (string.IsNullOrWhiteSpace (id)) {
string logdu = Membership.GetUser ().UserName; if (string.IsNullOrWhiteSpace (model.UserName)) {
if (string.IsNullOrWhiteSpace (id)) model.UserName = logdu;
return View (model);
} else {
id = logdu; id = logdu;
}
}
ViewData ["UserName"] = id; ViewData ["UserName"] = id;
bool editsMyName = (string.Compare(id,logdu)==0); bool editsTheUserName = model.NewUserName!=null&&(string.Compare(id,model.NewUserName)!=0);
if (!editsMyName) // Checks authorisation
if (logdu!=id)
if (!Roles.IsUserInRole ("Admin")) if (!Roles.IsUserInRole ("Admin"))
if (!Roles.IsUserInRole ("FrontOffice")) if (!Roles.IsUserInRole ("FrontOffice"))
throw new UnauthorizedAccessException ("Your are not authorized to modify this profile"); throw new UnauthorizedAccessException ("Your are not authorized to modify this profile");
// checks availability of a new username
if (editsTheUserName)
if (!UserManager.IsAvailable (model.NewUserName))
ModelState.AddModelError ("UserName",
string.Format (
LocalizedText.DuplicateUserName,
model.NewUserName
));
if (AvatarFile != null) { if (AvatarFile != null) {
// if said valid, move as avatar file // if said valid, move as avatar file
// else invalidate the model // else invalidate the model
@ -295,10 +308,6 @@ namespace Yavsc.Controllers
string.Format ("Image type {0} is not supported (suported formats : {1})", string.Format ("Image type {0} is not supported (suported formats : {1})",
AvatarFile.ContentType, "image/png")); AvatarFile.ContentType, "image/png"));
} }
/* Sync the property in the Profile model to display :
* string cAvat = HttpContext.Profile.GetPropertyValue ("Avatar") as string;
if (cAvat != null) if (model.avatar == null) model.avatar = cAvat;
*/
if (ModelState.IsValid) { if (ModelState.IsValid) {
ProfileBase prf = ProfileBase .Create (id); ProfileBase prf = ProfileBase .Create (id);
prf.SetPropertyValue ("Name", model.Name); prf.SetPropertyValue ("Name", model.Name);
@ -328,11 +337,12 @@ namespace Yavsc.Controllers
prf.SetPropertyValue ("gcalid", model.GoogleCalendar); prf.SetPropertyValue ("gcalid", model.GoogleCalendar);
prf.Save (); prf.Save ();
if (editsMyName) { if (editsTheUserName) {
UserManager.ChangeName (id, model.Name); UserManager.ChangeName (id, model.NewUserName);
FormsAuthentication.SetAuthCookie (model.Name, model.RememberMe); FormsAuthentication.SetAuthCookie (model.NewUserName, model.RememberMe);
model.UserName = model.NewUserName;
} }
YavscHelpers.Notify(ViewData, "Profile enregistré"+((editsMyName)?", nom public inclu.":"")); YavscHelpers.Notify(ViewData, "Profile enregistré"+((editsTheUserName)?", nom public inclu.":""));
} }
return View (model); return View (model);
} }

@ -112,7 +112,7 @@ namespace Yavsc.Controllers
YavscHelpers.Notify(ViewData, msg); YavscHelpers.Notify(ViewData, msg);
return View ("Auth"); return View ("Auth");
} }
SaveToken (gat); SaveToken (HttpContext.Profile,gat);
HttpContext.Profile.SetPropertyValue ("gcalapi", true); HttpContext.Profile.SetPropertyValue ("gcalapi", true);
string returnUrl = (string)Session ["returnUrl"]; string returnUrl = (string)Session ["returnUrl"];
Session ["returnUrl"] = null; Session ["returnUrl"] = null;
@ -126,14 +126,14 @@ namespace Yavsc.Controllers
/// order to save a descent value as expiration date. /// order to save a descent value as expiration date.
/// </summary> /// </summary>
/// <param name="gat">Gat.</param> /// <param name="gat">Gat.</param>
private void SaveToken (AuthToken gat) private void SaveToken (ProfileBase pr, AuthToken gat)
{ {
HttpContext.Profile.SetPropertyValue ("gtoken", gat.access_token); pr.SetPropertyValue ("gtoken", gat.access_token);
if (gat.refresh_token != null) if (gat.refresh_token != null)
HttpContext.Profile.SetPropertyValue ("grefreshtoken", gat.refresh_token); pr.SetPropertyValue ("grefreshtoken", gat.refresh_token);
HttpContext.Profile.SetPropertyValue ("gtokentype", gat.token_type); pr.SetPropertyValue ("gtokentype", gat.token_type);
HttpContext.Profile.SetPropertyValue ("gtokenexpir", DateTime.Now.AddSeconds (gat.expires_in)); pr.SetPropertyValue ("gtokenexpir", DateTime.Now.AddSeconds (gat.expires_in));
HttpContext.Profile.Save (); pr.Save ();
} }
/// <summary> /// <summary>
@ -162,6 +162,8 @@ namespace Yavsc.Controllers
foreach (MembershipUser u in mbrs) { foreach (MembershipUser u in mbrs) {
string username = u.UserName; string username = u.UserName;
FormsAuthentication.SetAuthCookie (username, true); FormsAuthentication.SetAuthCookie (username, true);
/* var upr = ProfileBase.Create (username);
SaveToken (upr,gat); */
} }
Session ["returnUrl"] = null; Session ["returnUrl"] = null;
return Redirect (returnUrl); return Redirect (returnUrl);
@ -230,7 +232,7 @@ namespace Yavsc.Controllers
} }
if (me.url != null) if (me.url != null)
HttpContext.Profile.SetPropertyValue ("WebSite", me.url); HttpContext.Profile.SetPropertyValue ("WebSite", me.url);
SaveToken (gat); SaveToken (HttpContext.Profile,gat);
// already done in SaveToken: HttpContext.Profile.Save (); // already done in SaveToken: HttpContext.Profile.Save ();
return Redirect (returnUrl); return Redirect (returnUrl);
} }
@ -256,7 +258,6 @@ namespace Yavsc.Controllers
[HttpGet] [HttpGet]
public ActionResult ChooseCalendar (string returnUrl) public ActionResult ChooseCalendar (string returnUrl)
{ {
bool hasCalAuth = (bool)HttpContext.Profile.GetPropertyValue ("gcalapi"); bool hasCalAuth = (bool)HttpContext.Profile.GetPropertyValue ("gcalapi");
if (!hasCalAuth) { if (!hasCalAuth) {
Session ["returnUrl"] = Request.Url.Scheme + "://" + Request.Url.Authority + "/Google/ChooseCalendar"; Session ["returnUrl"] = Request.Url.Scheme + "://" + Request.Url.Authority + "/Google/ChooseCalendar";
@ -296,8 +297,7 @@ namespace Yavsc.Controllers
/// Dates the query. /// Dates the query.
/// </summary> /// </summary>
/// <returns>The query.</returns> /// <returns>The query.</returns>
[Authorize] [Authorize,HttpGet]
[HttpGet]
public ActionResult Book () public ActionResult Book ()
{ {
return View (new BookQuery ()); return View (new BookQuery ());
@ -308,42 +308,50 @@ namespace Yavsc.Controllers
/// </summary> /// </summary>
/// <returns>The query.</returns> /// <returns>The query.</returns>
/// <param name="model">Model.</param> /// <param name="model">Model.</param>
[Authorize] [Authorize,HttpPost]
[HttpPost]
public ActionResult Book (BookQuery model) public ActionResult Book (BookQuery model)
{ {
if (ModelState.IsValid) { if (ModelState.IsValid) {
DateTime mindate = DateTime.Now; DateTime mindate = DateTime.Now;
if (model.StartDate < mindate) if (model.StartDate < mindate){
model.StartDate = mindate; ModelState.AddModelError ("StartDate", LocalizedText.FillInAFutureDate);
if (model.EndDate < mindate) }
model.EndDate = mindate.AddYears (1).Date; if (model.EndDate < model.StartDate)
ModelState.AddModelError ("EndDate", LocalizedText.StartDateAfterEndDate);
var muc = Membership.FindUsersByName (model.Person); var muc = Membership.FindUsersByName (model.Person);
if (muc.Count == 0) { if (muc.Count == 0) {
ModelState.AddModelError ("Person", LocalizedText.Non_existent_user); ModelState.AddModelError ("Person", LocalizedText.Non_existent_user);
return View (model);
} }
if (!Roles.IsUserInRole (model.Role)) { if (!Roles.IsUserInRole (model.Role)) {
ModelState.AddModelError ("Role", LocalizedText.UserNotInThisRole); ModelState.AddModelError ("Role", LocalizedText.UserNotInThisRole);
return View (model);
} }
ProfileBase upr = ProfileBase.Create (model.Person); ProfileBase upr = ProfileBase.Create (model.Person);
var gcalid = upr.GetPropertyValue ("gcalid");
string calid = (string)upr.GetPropertyValue ("gcalid"); if (gcalid is DBNull)
if (string.IsNullOrWhiteSpace (calid)) {
ModelState.AddModelError ("Person", LocalizedText.No_calendar_for_this_user); ModelState.AddModelError ("Person", LocalizedText.No_calendar_for_this_user);
return View (model); if (ModelState.IsValid) {
} string calid = (string) gcalid;
DateTime maxdate = model.EndDate; DateTime maxdate = model.EndDate;
CalendarApi c = new CalendarApi (); CalendarApi c = new CalendarApi ();
CalendarEventList res; CalendarEventList events;
try { try {
var events = c.GetCalendar (calid, mindate, maxdate, upr); events = c.GetCalendar (calid, mindate, maxdate, upr);
YavscHelpers.Notify (ViewData, "Google calendar API call success");
} catch (OtherWebException ex) { } catch (WebException ex) {
return View ("OtherWebException", ex); string response;
using (var stream = ex.Response.GetResponseStream())
using (var reader = new StreamReader(stream))
{
response = reader.ReadToEnd();
}
YavscHelpers.Notify (ViewData,
string.Format(
"Google calendar API exception {0} : {1}<br><pre>{2}</pre>",
ex.Status.ToString(),
ex.Message,
response));
}
} }
} }
return View (model); return View (model);

@ -92,7 +92,8 @@ namespace Yavsc.Controllers
if (!Request.IsAuthenticated) { if (!Request.IsAuthenticated) {
ProfileBase anonymousProfile = ProfileBase.Create(anonid); ProfileBase anonymousProfile = ProfileBase.Create(anonid);
object ac = anonymousProfile.GetPropertyValue ("allowcookies"); object ac = anonymousProfile.GetPropertyValue ("allowcookies");
if (ac is string && ac!="true")
if (ac is string && ((string)ac)!="true")
YavscHelpers.Notify (ViewData, LocalizedText.ThisSiteUsesCookies, YavscHelpers.Notify (ViewData, LocalizedText.ThisSiteUsesCookies,
"function(){Yavsc.ajax(\"/Yavsc/AllowCookies\", { id:'"+anonid+"' });}"); "function(){Yavsc.ajax(\"/Yavsc/AllowCookies\", { id:'"+anonid+"' });}");
} }

@ -77,8 +77,8 @@ namespace Yavsc
); );
routes.MapRoute ( routes.MapRoute (
"BackCompat", "BackCompat",
"{controller}/{action}/{user}/{title}", "Blogs/{action}/{user}/{title}",
new { controller = "Home", action = "Index", user = UrlParameter.Optional, title = UrlParameter.Optional } new { controller = "Blogs", action = "Index", user = UrlParameter.Optional, title = UrlParameter.Optional }
); );
routes.MapRoute ( routes.MapRoute (

@ -106,18 +106,18 @@ namespace Yavsc.Helpers.Google
using (Stream respstream = resp.GetResponseStream ()) { using (Stream respstream = resp.GetResponseStream ()) {
try { try {
res = (CalendarEventList) new DataContractJsonSerializer(typeof(CalendarEventList)).ReadObject (respstream); res = (CalendarEventList) new DataContractJsonSerializer(typeof(CalendarEventList)).ReadObject (respstream);
} catch (Exception ex) { } catch (Exception ) {
respstream.Close (); respstream.Close ();
resp.Close (); resp.Close ();
webreq.Abort (); webreq.Abort ();
throw ex; throw ;
} }
} }
resp.Close (); resp.Close ();
} }
} catch (WebException ex) { } catch (WebException ) {
webreq.Abort (); webreq.Abort ();
throw new OtherWebException (ex); throw;
} }
webreq.Abort (); webreq.Abort ();
return res; return res;

@ -226,16 +226,15 @@ namespace Yavsc.Helpers.Google
public static string GetFreshGoogleCredential (ProfileBase pr) public static string GetFreshGoogleCredential (ProfileBase pr)
{ {
string token = (string)pr.GetPropertyValue ("gtoken"); string token = (string)pr.GetPropertyValue ("gtoken");
string token_type = (string)pr.GetPropertyValue ("gtokentype"); string token_type = (string) pr.GetPropertyValue ("gtokentype");
DateTime token_exp = (DateTime)pr.GetPropertyValue ("gtokenexpir"); DateTime token_exp = (DateTime) pr.GetPropertyValue ("gtokenexpir");
if (token_exp < DateTime.Now) { if (token_exp < DateTime.Now) {
object ort = pr.GetPropertyValue ("grefreshtoken"); object ort = pr.GetPropertyValue ("grefreshtoken");
if (ort == null) { if (ort == null || ort is DBNull) {
throw new InvalidOAuth2RefreshToken ("Google"); throw new InvalidOAuth2RefreshToken ("Google");
} }
else { else {
string refresh_token = ort as string; string refresh_token = ort as string;
AuthToken gat = OAuth2.GetTokenPosting ( AuthToken gat = OAuth2.GetTokenPosting (
string.Format ("grant_type=refresh_token&client_id={0}&client_secret={1}&refresh_token={2}", string.Format ("grant_type=refresh_token&client_id={0}&client_secret={1}&refresh_token={2}",
CLIENT_ID, CLIENT_SECRET, refresh_token)); CLIENT_ID, CLIENT_SECRET, refresh_token));

@ -33,10 +33,10 @@ namespace Yavsc.Helpers
/// </summary> /// </summary>
/// <param name="helper">Helper.</param> /// <param name="helper">Helper.</param>
/// <param name="text">Text.</param> /// <param name="text">Text.</param>
public static string Translate(this HtmlHelper helper, string text) public static IHtmlString Translate(this HtmlHelper helper, string text)
{ {
// Just call the other one, to avoid having two copies (we don't use the HtmlHelper). // Just call the other one, to avoid having two copies (we don't use the HtmlHelper).
return GetString(text); return new MvcHtmlString(helper.Encode(GetString(text)));
} }
} }

@ -20,7 +20,6 @@ using Yavsc.Model.Messaging;
namespace Yavsc.Helpers namespace Yavsc.Helpers
{ {
/// <summary> /// <summary>
/// Yavsc helpers. /// Yavsc helpers.
/// </summary> /// </summary>
@ -62,7 +61,7 @@ namespace Yavsc.Helpers
{ {
SendActivationMessage (helper.Route("Default", new { controller="Account", SendActivationMessage (helper.Route("Default", new { controller="Account",
action = "Validate", action = "Validate",
key=user.ProviderUserKey.ToString() } ) key=user.ProviderUserKey.ToString(), id = user.UserName } )
, WebConfigurationManager.AppSettings ["RegistrationMessage"], , WebConfigurationManager.AppSettings ["RegistrationMessage"],
user); user);
} }
@ -73,7 +72,12 @@ namespace Yavsc.Helpers
/// <param name="user">User.</param> /// <param name="user">User.</param>
public static void SendActivationMessage(this System.Web.Mvc.UrlHelper helper, MembershipUser user) public static void SendActivationMessage(this System.Web.Mvc.UrlHelper helper, MembershipUser user)
{ {
SendActivationMessage (helper.Content("~/Account/Validate/"+user.UserName+"/?key="+user.ProviderUserKey.ToString()) SendActivationMessage (
string.Format("{2}://{3}/Account/Validate/{1}?key={0}",
user.ProviderUserKey.ToString(), user.UserName ,
helper.RequestContext.HttpContext.Request.Url.Scheme,
helper.RequestContext.HttpContext.Request.Url.Authority
)
, WebConfigurationManager.AppSettings ["RegistrationMessage"], , WebConfigurationManager.AppSettings ["RegistrationMessage"],
user); user);
} }
@ -221,25 +225,11 @@ namespace Yavsc.Helpers
JavaScriptSerializer serializer = new JavaScriptSerializer(); JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(obj); return serializer.Serialize(obj);
} }
public static void Notify(ViewDataDictionary ViewData, string message, string click_action=null) {
/// <summary> if (ViewData ["Notifications"] == null)
/// Notify the specified helper and message. ViewData ["Notifications"] = new List<Notification> ();
/// </summary> (ViewData ["Notifications"] as List<Notification>).Add (
/// <param name="helper">Helper.</param> new Notification { body = YavscAjaxHelper.QuoteJavascriptString(message),
/// <param name="message">Message.</param>
public static void Notify (this HtmlHelper helper, string message) {
Notify (helper.ViewData, message);
}
/// <summary>
/// Notify the specified viewData and message.
/// </summary>
/// <param name="viewData">View data.</param>
/// <param name="message">Message.</param>
public static void Notify(ViewDataDictionary viewData, string message, string click_action=null) {
if (viewData ["Notifications"] == null)
viewData ["Notifications"] = new List<Notification> ();
(viewData ["Notifications"] as List<Notification>).Add (
new Notification { body = message.Replace("\'","\\\'"),
click_action = click_action } ) ; click_action = click_action } ) ;
} }
/// <summary> /// <summary>
@ -339,7 +329,7 @@ namespace Yavsc.Helpers
} }
} }
if (ResultCount == 0) { if (ResultCount == 0) {
writer.Write (none); writer.WriteEncodedText(none);
} }
return new MvcHtmlString(strwr.ToString()); return new MvcHtmlString(strwr.ToString());
} }

@ -40,8 +40,8 @@ var apiBaseUrl = '<%=Url.Content(Yavsc.WebApiConfig.UrlPrefixRelative)%>';
<script> <script>
$(document).ready(function(){ $(document).ready(function(){
<% foreach (Notification note in (IEnumerable<Notification>) ViewData ["Notifications"] ) { <% foreach (Notification note in (IEnumerable<Notification>) ViewData ["Notifications"] ) {
if (note.click_action == null) {%> Yavsc.notice('<%=note.body%>'); <% } if (note.click_action == null) {%> Yavsc.notice(<%=note.body%>); <% }
else {%> Yavsc.notice('<%=note.body%>', <%=note.click_action%>); <% } %> else {%> Yavsc.notice(<%=note.body%>, <%=note.click_action%>); <% } %>
<% } %> <% } %>
}); });
</script> </script>

@ -36,11 +36,12 @@ var apiBaseUrl = '<%=Url.Content(Yavsc.WebApiConfig.UrlPrefixRelative)%>';
</asp:ContentPlaceHolder> </asp:ContentPlaceHolder>
<asp:ContentPlaceHolder ID="header" runat="server"></asp:ContentPlaceHolder> <asp:ContentPlaceHolder ID="header" runat="server"></asp:ContentPlaceHolder>
<div id="notifications"></div> <div id="notifications"></div>
<%if (ViewData ["Notifications"]!=null) { %> <% if (ViewData ["Notifications"]!=null) { %>
<script> <script>
$(document).ready(function(){ $(document).ready(function(){
<% foreach (string note in (IEnumerable<string>) ViewData ["Notifications"] ) { %> <% foreach (Notification note in (IEnumerable<Notification>) ViewData ["Notifications"] ) {
Yavsc.notice('<%=note%>'); if (note.click_action == null) {%> Yavsc.notice(<%=note.body%>); <% }
else {%> Yavsc.notice(<%=note.body%>, <%=note.click_action%>); <% } %>
<% } %> <% } %>
}); });
</script> </script>

@ -1,65 +1,69 @@
<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %> <%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %>
<!DOCTYPE html> <!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<% ViewState["orgtitle"] = Html.Translate(Page.Title); %>
<% Page.Title = ViewState["orgtitle"] + " - " + YavscHelpers.SiteName; %>
<asp:ContentPlaceHolder id="init" runat="server"> <asp:ContentPlaceHolder id="init" runat="server">
</asp:ContentPlaceHolder><% </asp:ContentPlaceHolder><head runat="server">
ViewState["orgtitle"] = T.GetString(Page.Title);
Page.Title = ViewState["orgtitle"] + " - " + YavscHelpers.SiteName;
%><head runat="server">
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="/App_Themes/style.css" /> <link rel="stylesheet" href="<%=Url.Content("~/App_Themes/style.css")%>" />
<link rel="stylesheet" href="<%=Url.Content("~/App_Themes/font-awesome.css")%>" />
<link rel="stylesheet" href="<%=Url.Content("~/App_Themes/jquery-ui.css")%>" />
<link rel="stylesheet" href="<%=Url.Content("~/App_Themes/prettify.css")%>" />
<link rel="stylesheet" href="<%=Url.Content("~/App_Themes/doxy.css")%>" />
<link rel="icon" type="image/png" href="/favicon.png?v=3" /> <link rel="icon" type="image/png" href="/favicon.png?v=3" />
<script type="text/javascript" src="<%=Url.Content("~/Scripts/jquery-2.1.4.min.js")%>"></script> <script src="<%=Url.Content("~/Scripts/jquery-2.1.4.min.js")%>"></script>
<script src="<%=Url.Content("~/Scripts/jquery-ui-1.11.4.js")%>"></script>
<script src="<%=Url.Content("~/Scripts/parallax.js")%>"></script>
<script src="<%=Url.Content("~/Scripts/Prettify/run_prettify.js")%>"></script>
<script type="text/javascript">
var apiBaseUrl = '<%=Url.Content(Yavsc.WebApiConfig.UrlPrefixRelative)%>';
</script>
<script src="<%=Url.Content("~/Scripts/yavsc.js")%>"></script>
<script src="<%=Url.Content("~/Scripts/yavsc.tags.js")%>"></script>
<asp:ContentPlaceHolder id="head" runat="server"> <asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder> </asp:ContentPlaceHolder>
<link href='http://fonts.googleapis.com/css?family=Dancing+Script:400,700' rel='stylesheet' type='text/css'/>
</head> </head>
<body> <body>
<header> <header data-type="background" data-speed="8" >
<asp:ContentPlaceHolder ID="overHeaderOne" runat="server"> <asp:ContentPlaceHolder ID="overHeaderOne" runat="server">
<h1><a href="<%= Html.Encode(Request.Url.AbsoluteUri.ToString()) %>"> <%=ViewState["orgtitle"]%> </a> - <h1><a href="<%= Url.RouteUrl("Default") %>">
<a href="<%=Request.Url.Scheme + "://" + Request.Url.Authority%>"><%= YavscHelpers.SiteName %></a> <%=ViewState["orgtitle"]%></a>
</h1> - <a href="<%= Url.RouteUrl("Default", new {controller = "Home" , action = "Index" }) %>"><%= YavscHelpers.SiteName %></a>
</asp:ContentPlaceHolder><asp:ContentPlaceHolder ID="header" runat="server"></asp:ContentPlaceHolder><% </h1>
if (ViewData["Error"]!=null) { </asp:ContentPlaceHolder>
%><div class="error"><%= Html.Encode(ViewData["Error"]) %> <asp:ContentPlaceHolder ID="header" runat="server"></asp:ContentPlaceHolder>
</div><% } <div id="notifications"></div>
if (ViewData["Message"]!=null) { <% if (ViewData ["Notifications"]!=null) { %>
%><div class="message"><%= Html.Encode(ViewData["Message"]) %></div><% } <script>
%> $(document).ready(function(){
<% foreach (Notification note in (IEnumerable<Notification>) ViewData ["Notifications"] ) {
if (note.click_action == null) {%> Yavsc.notice(<%=note.body%>); <% }
else {%> Yavsc.notice(<%=note.body%>, <%=note.click_action%>); <% } %>
<% } %>
});
</script>
<% } %>
</header> </header>
<main> <main data-type="background" data-speed="10" data-emheight="10" data-posx="0" data-posy="22" >
<asp:ContentPlaceHolder ID="MainContent" runat="server"> <asp:ContentPlaceHolder ID="MainContent" runat="server">
</asp:ContentPlaceHolder> </asp:ContentPlaceHolder>
</main> </main>
<asp:ContentPlaceHolder ID="MASContent" runat="server"> <asp:ContentPlaceHolder ID="MASContent" runat="server">
</asp:ContentPlaceHolder> </asp:ContentPlaceHolder>
<footer data-type="background" data-speed="5" >
<footer> <div id="copyr">
<script src="https://apis.google.com/js/platform.js" async defer> <a href="http://yavsc.pschneider.fr/Blogs/UserPost/paul/License">© 2015 GNU GENERAL PUBLIC LICENSE <i>Version 3, 29 June 2007</i></a>
{lang: 'fr'} </div>
</script> <%= Html.ActionLink("Formulaire de contact","Contact","Home",null, new { @class="thanks" }) %>
<%= Html.ActionLink("Contact","Contact","Home",null, new { @class="thanks" }) %>
<% foreach ( Link link in Html.Thanks()) { %> <% foreach ( Link link in Html.Thanks()) { %>
<a class="thanks" href="<%=link.Url%>"><% if (link.Image !=null) { <a class="thanks" href="<%=link.Url%>"><% if (link.Image !=null) {
%><img src="<%= link.Image %>" alt="<%= link.Text %>"/></a><% %><img src="<%= link.Image %>" alt="<%= link.Text %>"/></a>
} else { %><a class="thanks" href="<%=link.Url%>"><%= link.Text %></a><% }} %> <% } else { %>
<div class="g-plusone" data-annotation="inline" data-width="230"></div> <a class="thanks" href="<%=link.Url%>"><%= link.Text %></a>
</footer> <% }} %>
<script type="text/javascript"> </footer><div class="modal"></div>
var apiBaseUrl = '<%=Url.Content(Yavsc.WebApiConfig.UrlPrefixRelative)%>';
</script> <script>
$( ".bshd" ).on("click",function(e) {
if (e.target == "[object HTMLElement]") {
var panel = $(this).children(".bshpanel");
if (panel.hasClass("hidden")) panel.css("cursor","zoom-out");
else panel.css("cursor","zoom-in");
panel.toggleClass("hidden");
$(this).children(".bsh").toggleClass("hidden");
} });
</script>
</body> </body>
</html> </html>

@ -43,7 +43,8 @@ namespace Yavsc
where modelState[x].Errors.Count > 0 where modelState[x].Errors.Count > 0
select new select new
{ {
key = x, // FIXME why?
key = x.Replace(".","_"),
errors = modelState[x].Errors. errors = modelState[x].Errors.
Select(y => y.ErrorMessage). Select(y => y.ErrorMessage).
ToArray() ToArray()

@ -16,6 +16,7 @@
<%= Html.CheckBox("RememberMe") %> <%= Html.CheckBox("RememberMe") %>
<%= Html.ValidationMessage("RememberMe", "") %><br/> <%= Html.ValidationMessage("RememberMe", "") %><br/>
<%= Html.Hidden("returnUrl",ViewData["returnUrl"]) %> <%= Html.Hidden("returnUrl",ViewData["returnUrl"]) %>
<%= Html.AntiForgeryToken() %>
<!-- Html.AntiForgeryToken() --> <!-- Html.AntiForgeryToken() -->
<input type="submit"/> <input type="submit"/>
<% } %></div> <% } %></div>

@ -1,4 +1,4 @@
<%@ Page Title="Profile_edition" Language="C#" MasterPageFile="~/Models/App.master" Inherits="System.Web.Mvc.ViewPage<Profile>" %> <%@ Page Title="Profile_edition" Language="C#" MasterPageFile="~/Models/App.master" Inherits="System.Web.Mvc.ViewPage<ProfileEdition>" %>
<asp:Content ContentPlaceHolderID="init" ID="init1" runat="server"> <asp:Content ContentPlaceHolderID="init" ID="init1" runat="server">
<% Title = ViewData["UserName"] + " : " +Html.Translate("Profile_edition"); %> <% Title = ViewData["UserName"] + " : " +Html.Translate("Profile_edition"); %>
@ -18,9 +18,9 @@ table.layout TR TD { max-width:40%; }
<fieldset><legend>Informations publiques</legend> <fieldset><legend>Informations publiques</legend>
<%= Html.LabelFor(model => model.Name) %> : <%= Html.LabelFor(model => model.NewUserName) %> :
<%= Html.TextBox("Name") %> <%= Html.TextBox("NewUserName") %>
<%= Html.ValidationMessage("Name", "*") %> <%= Html.ValidationMessage("NewUserName", "*") %>
<br> <br>
<%= Html.LabelFor(model => model.WebSite) %> : <%= Html.LabelFor(model => model.WebSite) %> :
@ -34,7 +34,11 @@ Avatar : <img src="<%=Url.AvatarUrl(HttpContext.Current.User.Identity.Name)%>" a
<%= Html.ValidationMessage("AvatarFile", "*") %> <%= Html.ValidationMessage("AvatarFile", "*") %>
</fieldset> </fieldset>
<fieldset><legend>Informations administratives</legend>
<%= Html.LabelFor(model => model.Name) %> :
<%= Html.TextBox("Name") %>
<%= Html.ValidationMessage("Name", "*") %>
</fieldset>
<fieldset><legend>Blog</legend> <fieldset><legend>Blog</legend>
<div class="spanel"> <div class="spanel">
<%= Html.LabelFor(model => model.BlogVisible) %> : <%= Html.LabelFor(model => model.BlogVisible) %> :
@ -117,7 +121,7 @@ Avatar : <img src="<%=Url.AvatarUrl(HttpContext.Current.User.Identity.Name)%>" a
<% } %> <% } %>
<aside> <aside>
<%= Html.ActionLink("Changer de mot de passe","ChangePassword", "Account",null, new { @class="actionlink" })%> <%= Html.ActionLink("Changer de mot de passe","ChangePassword", "Account",null, new { @class="actionlink" })%>
<%= Html.ActionLink("Désincription","Unregister", "Account", new { id=ViewData["UserName"] } , new { @class="actionlink" })%> <%= Html.ActionLink("Désincription", "Unregister", "Account", new { id = ViewData["UserName"] } , new { @class="actionlink" })%>
</aside> </aside>
<aside> <aside>
<% if (Roles.IsUserInRole((string)ViewData ["UserName"],"Admin")) { %> <% if (Roles.IsUserInRole((string)ViewData ["UserName"],"Admin")) { %>

@ -308,11 +308,7 @@ function addRow(){
message(false); message(false);
}, },
statusCode: { statusCode: {
400: function(data) { 400: Yavsc.onAjaxBadInput
$.each(data.responseJSON, function (key, value) {
document.getElementById("Err_wr_" + value.key).innerHTML=value.errors.join("<br/>");
});
}
}, },
error: function (xhr, ajaxOptions, thrownError) { error: function (xhr, ajaxOptions, thrownError) {
if (xhr.status!=400) if (xhr.status!=400)

@ -1,73 +0,0 @@
<%@ Page Title="Booking" Language="C#" Inherits="System.Web.Mvc.ViewPage<BookQuery>" MasterPageFile="~/Models/App.master" %>
<asp:Content ContentPlaceHolderID="head" ID="headContent" runat="server">
<link rel='stylesheet' href='/Scripts/fullcalendar/fullcalendar.css' />
<script type="text/javascript" src="/Scripts/jquery.mousewheel.js"></script>
<link rel="stylesheet" type="text/css" href="/App_Themes/jquery.timepicker.css" />
<script type="text/javascript" src="/Scripts/globalize/globalize.js"></script>
<script type="text/javascript" src="/Scripts/globalize/cultures/globalize.culture.fr.js"></script>
<script type="text/javascript" src="/Scripts/datepicker-fr.js"></script>
<script type="text/javascript" src="/Scripts/datepicker-en-GB.js"></script>
<script type="text/javascript" src="/Scripts/datepair.js"></script>
<script type="text/javascript" src="/Scripts/jquery.timepicker.min.js"></script>
<script type="text/javascript" src="/Scripts/jquery.datepair.min.js"></script>
</asp:Content>
<asp:Content ContentPlaceHolderID="MainContent" ID="MainContentContent" runat="server">
<% using ( Html.BeginForm("Book","Google") ) { %>
<div id="book" ><fieldset>
<legend>Date d'intervention</legend>
Intervention souhaitée entre le
<input type="text" id="StartDate" class="start date" value="<%= DateTime.Now.ToString("yyyy/MM/dd")%>">
<%= Html.ValidationMessageFor(model=>model.StartDate) %>
et le
<input type="text" id="EndDate" class="end date" value="<%= DateTime.Now.AddDays(2).ToString("yyyy/MM/dd")%>">
<%= Html.ValidationMessageFor(model=>model.EndDate) %>
</fieldset>
<fieldset >
<legend>Heure et durée d'intervention souhaitée</legend>
<%= Html.LabelFor(model=>model.StartHour) %>
<input type="text" id="StartHour" class="start time" value="<%= DateTime.Now.ToString("H:mm")%>">
<%= Html.ValidationMessageFor(model=>model.StartHour) %>
<%= Html.LabelFor(model=>model.EndHour) %>
<input type="text" id="EndHour" class="end time" value="<%= DateTime.Now.AddMinutes(30).ToString("H:mm")%>">
<%= Html.ValidationMessageFor(model=>model.EndHour) %>
</fieldset>
</div>
<fieldset>
<legend>Intervenant</legend>
<%= Html.LabelFor(model=>model.Role) %>:
<%= Html.TextBoxFor(model=>model.Role) %>
<%= Html.ValidationMessageFor(model=>model.Role) %>
<br>
<%= Html.LabelFor(model=>model.Person) %>:
<%= Html.TextBoxFor(model=>model.Person) %>
<%= Html.ValidationMessageFor(model=>model.Person) %>
</fieldset>
<script>
$(function() {
var tpconfig = {
'timeFormat': 'H:i',
'showDuration': true,
'disableTimeRanges': [
['17:01pm', '24:01pm'],
['0am', '9am']
]};
// $.datepicker.setDefaults($.datepicker.regional[ "fr" ] );
var dpconfig = {
'format': 'yy/mm/dd',
'autoclose': true } ;
$('#book .time').timepicker(tpconfig);
$('#book .date').datepicker(dpconfig);
$('#book').datepair();
});
</script>
<input type="submit">
<% } %>
<pre><%= Html.Encode(ViewData["json"]) %></pre>
</asp:Content>

@ -16,19 +16,19 @@
<% using ( Html.BeginForm("Book","Google") ) { %> <% using ( Html.BeginForm("Book","Google") ) { %>
<div id="book" >Date d'intervention : <div id="book" >Date d'intervention :
Intervention souhaitée entre le Intervention souhaitée entre le
<input type="text" id="StartDate" class="start date" > <input type="text" id="StartDate" name="StartDate" class="start date" value="<%=Model.StartDate.ToString("yyyy/MM/dd")%>">
<%= Html.ValidationMessageFor(model=>model.StartDate) %> <%= Html.ValidationMessageFor(model=>model.StartDate) %>
et le et le
<input type="text" id="EndDate" class="end date" > <input type="text" id="EndDate" name="EndDate" class="end date" value="<%=Model.StartDate.ToString("yyyy/MM/dd")%>">
<%= Html.ValidationMessageFor(model=>model.EndDate) %> <%= Html.ValidationMessageFor(model=>model.EndDate) %>
<br> <br>
Heure et durée d'intervention souhaitée Heure et durée d'intervention souhaitée
<%= Html.LabelFor(model=>model.StartHour) %> <%= Html.LabelFor(model=>model.StartHour) %>
<input type="text" id="StartHour" class="start time" > <input type="text" id="StartHour" name="StartHour" class="start time" value="<%=Model.StartHour%>">
<%= Html.ValidationMessageFor(model=>model.StartHour) %> <%= Html.ValidationMessageFor(model=>model.StartHour) %>
<%= Html.LabelFor(model=>model.EndHour) %> <%= Html.LabelFor(model=>model.EndHour) %>
<input type="text" id="EndHour" class="end time" > <input type="text" id="EndHour" name="EndHour" class="end time" value="<%=Model.EndHour%>">
<%= Html.ValidationMessageFor(model=>model.EndHour) %> <%= Html.ValidationMessageFor(model=>model.EndHour) %>
</div> </div>

@ -23,7 +23,7 @@ http://msdn2.microsoft.com/en-us/library/b5ysx397.aspx
<sectionGroup name="system.web"> <sectionGroup name="system.web">
<section name="blog" type="Yavsc.Model.DataProviderConfigurationSection, YavscModel" allowLocation="true" requirePermission="false" allowDefinition="Everywhere" /> <section name="blog" type="Yavsc.Model.DataProviderConfigurationSection, YavscModel" allowLocation="true" requirePermission="false" allowDefinition="Everywhere" />
<section name="thanks" type="Yavsc.ThanksConfigurationSection, Yavsc" allowLocation="true" requirePermission="false" allowDefinition="Everywhere" /> <section name="thanks" type="Yavsc.ThanksConfigurationSection, Yavsc" allowLocation="true" requirePermission="false" allowDefinition="Everywhere" />
<section name="catalog" type="Yavsc.Model.FrontOffice.Configuration.CatalogProvidersConfigurationSection, YavscModel" allowLocation="true" requirePermission="false" allowDefinition="Everywhere" /> <section name="catalog" type="Yavsc.Model.FrontOffice.Catalog.Configuration.CatalogProvidersConfigurationSection, YavscModel" allowLocation="true" requirePermission="false" allowDefinition="Everywhere" />
<section name="workflow" type="Yavsc.Model.DataProviderConfigurationSection, YavscModel" allowLocation="true" requirePermission="false" allowDefinition="Everywhere" /> <section name="workflow" type="Yavsc.Model.DataProviderConfigurationSection, YavscModel" allowLocation="true" requirePermission="false" allowDefinition="Everywhere" />
<section name="circleProviders" type="Yavsc.Model.DataProviderConfigurationSection, YavscModel" /> <section name="circleProviders" type="Yavsc.Model.DataProviderConfigurationSection, YavscModel" />
<section name="userNameManager" type="Yavsc.Model.DataProviderConfigurationSection, YavscModel" /> <section name="userNameManager" type="Yavsc.Model.DataProviderConfigurationSection, YavscModel" />
@ -121,7 +121,7 @@ http://msdn2.microsoft.com/en-us/library/b5ysx397.aspx
<add name="Phone" /> <add name="Phone" />
<add name="Mobile" /> <add name="Mobile" />
<add name="Avatar" /> <add name="Avatar" />
<add name="BlogVisible" type="System.Boolean" /> <add name="BlogVisible" type="System.Boolean" defaultValue="false" />
<add name="BlogTitle" /> <add name="BlogTitle" />
<add name="WebSite" /> <add name="WebSite" />
<add name="Address" /> <add name="Address" />
@ -133,12 +133,12 @@ http://msdn2.microsoft.com/en-us/library/b5ysx397.aspx
<add name="BIC" /> <add name="BIC" />
<add name="WicketCode" /> <add name="WicketCode" />
<add name="AccountNumber" /> <add name="AccountNumber" />
<add name="BankedKey" /> <add name="BankedKey" type="System.Int32" defaultValue="0"/>
<add name="gtoken" /> <add name="gtoken" />
<add name="grefreshtoken" /> <add name="grefreshtoken" />
<add name="gtokentype" /> <add name="gtokentype" />
<add name="gtokenexpir" /> <add name="gtokenexpir" type="System.DateTime" defaultValue="2008-05-01 7:34:42Z" />
<add name="gcalapi" /> <add name="gcalapi" type="System.Boolean" defaultValue="false" />
<add name="gcalid" /> <add name="gcalid" />
<add name="gregid" /> <add name="gregid" />
<add name="allowcookies" type="System.Boolean" allowAnonymous="true" defaultValue="false"/> <add name="allowcookies" type="System.Boolean" allowAnonymous="true" defaultValue="false"/>
@ -167,6 +167,11 @@ http://msdn2.microsoft.com/en-us/library/b5ysx397.aspx
<!-- <machineKey validationKey="13CA2E37A5A99AD8CE4A6B895BAF0ED3A022AA584B8D922256BA072189CEB085EEB4E573CA833D9B34FBF68687F6A6B3E008FB4EB67585A4D90551B9D36D42A1" decryptionKey="DA89CC83F6FB2EB12D5929DABC89299AC3928E0751705D33D02DB4162ED56536" validation="SHA1" decryption="AES" /> --> <!-- <machineKey validationKey="13CA2E37A5A99AD8CE4A6B895BAF0ED3A022AA584B8D922256BA072189CEB085EEB4E573CA833D9B34FBF68687F6A6B3E008FB4EB67585A4D90551B9D36D42A1" decryptionKey="DA89CC83F6FB2EB12D5929DABC89299AC3928E0751705D33D02DB4162ED56536" validation="SHA1" decryption="AES" /> -->
<!--- <sessionState cookieless="true" regenerateExpiredSessionId="true" timeout="120"/> --> <!--- <sessionState cookieless="true" regenerateExpiredSessionId="true" timeout="120"/> -->
<trust level="High" /> <trust level="High" />
<catalog defaultProvider="XmlCatalogProvider">
<providers>
<add name="XmlCatalogProvider" connection="~/Catalog.xml" applicationName="/" type="SalesCatalog.XmlImplementation.XmlCatalogProvider, SalesCatalog" />
</providers>
</catalog>
</system.web> </system.web>
<system.codedom> <system.codedom>
<compilers> <compilers>
@ -193,11 +198,6 @@ http://msdn2.microsoft.com/en-us/library/b5ysx397.aspx
<add name="Npgsql Data Provider" invariant="Npgsql" support="FF" description=".Net Framework Data Provider for Postgresql Server" type="Npgsql.NpgsqlFactory, Npgsql" /> <add name="Npgsql Data Provider" invariant="Npgsql" support="FF" description=".Net Framework Data Provider for Postgresql Server" type="Npgsql.NpgsqlFactory, Npgsql" />
</DbProviderFactories> </DbProviderFactories>
</system.data> </system.data>
<catalog defaultProvider="XmlCatalogProvider">
<providers>
<add name="XmlCatalogProvider" connection="~/Catalog.xml" applicationName="/" type="SalesCatalog.XmlImplementation.XmlCatalogProvider, SalesCatalog" />
</providers>
</catalog>
<system.net> <system.net>
<!-- not supported: <defaultProxy enabled="true" /> --> <!-- not supported: <defaultProxy enabled="true" /> -->
<settings> <settings>

@ -206,6 +206,7 @@
<Compile Include="ApiControllers\PaypalController.cs" /> <Compile Include="ApiControllers\PaypalController.cs" />
<Compile Include="ApiControllers\AuthorizationDenied.cs" /> <Compile Include="ApiControllers\AuthorizationDenied.cs" />
<Compile Include="ApiControllers\YavscController.cs" /> <Compile Include="ApiControllers\YavscController.cs" />
<Compile Include="Helpers\YavscAjaxHelper.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="Views\Web.config" /> <Content Include="Views\Web.config" />
@ -467,7 +468,6 @@
<Content Include="Scripts\jquery.datepair.js" /> <Content Include="Scripts\jquery.datepair.js" />
<Content Include="Scripts\jquery.datepair.min.js" /> <Content Include="Scripts\jquery.datepair.min.js" />
<Content Include="Scripts\jquery-1.11.3.min.js" /> <Content Include="Scripts\jquery-1.11.3.min.js" />
<Content Include="Views\Google\Book-next.aspx" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" /> <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

@ -45,6 +45,7 @@ namespace Yavsc.Model.Calendar
/// <value>The minimum time.</value> /// <value>The minimum time.</value>
[RegularExpression("\\d\\d:\\d\\d")] [RegularExpression("\\d\\d:\\d\\d")]
[Display(ResourceType=typeof(LocalizedText),Name="StartHour")] [Display(ResourceType=typeof(LocalizedText),Name="StartHour")]
[Required(ErrorMessage= "S'il vous plait, saisissez une heure de début d'intervention")]
public string StartHour { get; set; } public string StartHour { get; set; }
/// <summary> /// <summary>
@ -62,7 +63,7 @@ namespace Yavsc.Model.Calendar
/// </summary> /// </summary>
/// <value>The duration.</value> /// <value>The duration.</value>
[RegularExpression("\\d\\d:\\d\\d")] [RegularExpression("\\d\\d:\\d\\d")]
[Required(ErrorMessage= "S'il vous plait, saisissez une durée minimale d'intervention")] [Required(ErrorMessage= "S'il vous plait, saisissez une heure de fin d'intervention")]
[Display(Name="EndHour",ResourceType=typeof(LocalizedText))] [Display(Name="EndHour",ResourceType=typeof(LocalizedText))]
public string EndHour { get; set; } public string EndHour { get; set; }
@ -77,6 +78,7 @@ namespace Yavsc.Model.Calendar
/// Gets or sets the role. /// Gets or sets the role.
/// </summary> /// </summary>
/// <value>The role.</value> /// <value>The role.</value>
[Required(ErrorMessage= "S'il vous plait, saisissez le type d'intervention souhaité")]
[Display(Name="Role",ResourceType=typeof(LocalizedText))] [Display(Name="Role",ResourceType=typeof(LocalizedText))]
public string Role { get; set; } public string Role { get; set; }
} }

@ -1,3 +1,39 @@
2015-11-01 Paul Schneider <paul@pschneider.fr>
* ProfileEdition.cs: Fixes the username modification
* LocalizedText.resx:
* LocalizedText.fr.resx:
* LocalizedText.Designer.cs:
* LocalizedText.fr.Designer.cs: WIP booking
* ChangePasswordModel.cs:
* RegisterClientModel.cs: A regexp for user name
* LoginModel.cs: A regexp for user name and password
* Profile.cs: A regexp for user name, and profile usage fixes
* UserManager.cs: Checks for username availability before
trying to modify it
* YavscModel.csproj: `ProfileEdition` class addition
* ChangeLog: useless here
* BookQuery.cs: Start, end hour and role are required
* OtherWebException.cs: useless
2015-10-31 Paul Schneider <paul@pschneider.fr>
* LocalizedText.resx:
* OtherWebException.cs:
* BookQuery.cs:
* LocalizedText.fr.resx:
* LocalizedText.Designer.cs:
* LocalizedText.fr.Designer.cs:
2015-10-30 Paul Schneider <paul@pschneider.fr> 2015-10-30 Paul Schneider <paul@pschneider.fr>
* LocalizedText.resx: * LocalizedText.resx:

@ -52,6 +52,12 @@ namespace Yavsc.Model {
} }
} }
public static string StartDateAfterEndDate {
get {
return ResourceManager.GetString("StartDateAfterEndDate", resourceCulture);
}
}
public static string ProviderId { public static string ProviderId {
get { get {
return ResourceManager.GetString("ProviderId", resourceCulture); return ResourceManager.GetString("ProviderId", resourceCulture);
@ -519,5 +525,11 @@ namespace Yavsc.Model {
return ResourceManager.GetString("Non_existent_user", resourceCulture); return ResourceManager.GetString("Non_existent_user", resourceCulture);
} }
} }
public static string FillInAFutureDate {
get {
return ResourceManager.GetString("FillInAFutureDate", resourceCulture);
}
}
} }
} }

@ -52,21 +52,21 @@ namespace Yavsc.Model {
} }
} }
public static string ProviderId { public static string StartDateAfterEndDate {
get { get {
return ResourceManager.GetString("ProviderId", resourceCulture); return ResourceManager.GetString("StartDateAfterEndDate", resourceCulture);
} }
} }
public static string Pdf_version { public static string ProviderId {
get { get {
return ResourceManager.GetString("Pdf_version", resourceCulture); return ResourceManager.GetString("ProviderId", resourceCulture);
} }
} }
public static string Location { public static string Pdf_version {
get { get {
return ResourceManager.GetString("Location", resourceCulture); return ResourceManager.GetString("Pdf_version", resourceCulture);
} }
} }
@ -286,9 +286,9 @@ namespace Yavsc.Model {
} }
} }
public static string StartHour { public static string Location {
get { get {
return ResourceManager.GetString("StartHour", resourceCulture); return ResourceManager.GetString("Location", resourceCulture);
} }
} }
@ -460,6 +460,12 @@ namespace Yavsc.Model {
} }
} }
public static string StartHour {
get {
return ResourceManager.GetString("StartHour", resourceCulture);
}
}
public static string Unitary_cost { public static string Unitary_cost {
get { get {
return ResourceManager.GetString("Unitary_cost", resourceCulture); return ResourceManager.GetString("Unitary_cost", resourceCulture);
@ -507,5 +513,11 @@ namespace Yavsc.Model {
return ResourceManager.GetString("Non_existent_user", resourceCulture); return ResourceManager.GetString("Non_existent_user", resourceCulture);
} }
} }
public static string FillInAFutureDate {
get {
return ResourceManager.GetString("FillInAFutureDate", resourceCulture);
}
}
} }
} }

@ -36,6 +36,7 @@
<data name="Estimate_not_found"><value>Devis non trouvé</value></data> <data name="Estimate_not_found"><value>Devis non trouvé</value></data>
<data name="EventWebPage"><value>Page web de l'événement</value></data> <data name="EventWebPage"><value>Page web de l'événement</value></data>
<data name="ExistantDB"><value>Base de données éxistante</value></data> <data name="ExistantDB"><value>Base de données éxistante</value></data>
<data name="FillInAFutureDate"><value>Veuilliez, s'il vous plait, utiliser une date future.</value></data>
<data name="Google_calendar"><value>Agenda Google</value></data> <data name="Google_calendar"><value>Agenda Google</value></data>
<data name="Google_error"><value>Erreur Google : {0}</value></data> <data name="Google_error"><value>Erreur Google : {0}</value></data>
<data name="Hide_source"><value>Cacher le texte source du billet</value></data> <data name="Hide_source"><value>Cacher le texte source du billet</value></data>
@ -75,6 +76,7 @@
<data name="Remove"><value>Supprimer</value></data> <data name="Remove"><value>Supprimer</value></data>
<data name="role_created"><value>Rôle créé</value></data> <data name="role_created"><value>Rôle créé</value></data>
<data name="StartDate"><value>Date de début</value></data> <data name="StartDate"><value>Date de début</value></data>
<data name="StartDateAfterEndDate"><value>La date de fin doit être postérieure à la date de début.</value></data>
<data name="StartHour"><value>Heure de début</value></data> <data name="StartHour"><value>Heure de début</value></data>
<data name="Submit"><value>Soumettre</value></data> <data name="Submit"><value>Soumettre</value></data>
<data name="Tag_name"><value>Nom du tag</value></data> <data name="Tag_name"><value>Nom du tag</value></data>

@ -36,6 +36,7 @@
<data name="Estimate_not_found"><value>Estimate not found</value></data> <data name="Estimate_not_found"><value>Estimate not found</value></data>
<data name="EventWebPage"><value>Event Web page</value></data> <data name="EventWebPage"><value>Event Web page</value></data>
<data name="ExistantDB"><value>Existant data base</value></data> <data name="ExistantDB"><value>Existant data base</value></data>
<data name="FillInAFutureDate"><value>Please, use a date in the future as starting date.</value></data>
<data name="Home"><value>Home</value></data> <data name="Home"><value>Home</value></data>
<data name="Hide"><value>Hide</value></data> <data name="Hide"><value>Hide</value></data>
<data name="Hide_source"><value>Hide the bill source text</value></data> <data name="Hide_source"><value>Hide the bill source text</value></data>
@ -80,6 +81,7 @@
<data name="Submit"><value>Submit</value></data> <data name="Submit"><value>Submit</value></data>
<data name="StartHour"><value>Start hour</value></data> <data name="StartHour"><value>Start hour</value></data>
<data name="StartDate"><value>Start date</value></data> <data name="StartDate"><value>Start date</value></data>
<data name="StartDateAfterEndDate"><value>The ending date must be later than the starting one.</value></data>
<data name="Tag_name"><value>Tag name</value></data> <data name="Tag_name"><value>Tag name</value></data>
<data name="Tex_version"><value>LaTeX version</value></data> <data name="Tex_version"><value>LaTeX version</value></data>
<data name="ThisSiteUsesCookies"><value>This site uses cookies</value></data> <data name="ThisSiteUsesCookies"><value>This site uses cookies</value></data>

@ -28,7 +28,7 @@ namespace Yavsc.Model
/// <summary> /// <summary>
/// Google error exception. /// Google error exception.
/// </summary> /// </summary>
public class OtherWebException : Exception public class OtherWebException : WebException
{ {
/// <summary> /// <summary>
/// Gets or sets the title. /// Gets or sets the title.

@ -12,7 +12,7 @@ namespace Yavsc.Model.RolesAndMembers
/// Gets or sets the username. /// Gets or sets the username.
/// </summary> /// </summary>
/// <value>The username.</value> /// <value>The username.</value>
[Required(ErrorMessage = "Please, enter your user name")] [Required(ErrorMessage = "Please, enter your user name"),RegularExpression("([a-z]|[A-Z]|[\\s-_.~]|[0-9])+")]
public string Username { get; set; } public string Username { get; set; }
/// <summary> /// <summary>

@ -15,7 +15,7 @@ namespace Yavsc.Model.RolesAndMembers
/// <value>The name of the user.</value> /// <value>The name of the user.</value>
[DisplayName("Nom d'utilisateur"), [DisplayName("Nom d'utilisateur"),
Required(ErrorMessage = "S'il vous plait, entrez un nom d'utilisateur ([a-z]|[A-Z]|[-_.~]|[0-9])+"), Required(ErrorMessage = "S'il vous plait, entrez un nom d'utilisateur ([a-z]|[A-Z]|[-_.~]|[0-9])+"),
RegularExpression("([a-z]|[A-Z]|[-_.~]|[0-9])+")] RegularExpression("([a-z]|[A-Z]|[0-9])+")]
public string UserName { get; set; } public string UserName { get; set; }
/// <summary> /// <summary>
@ -23,8 +23,7 @@ namespace Yavsc.Model.RolesAndMembers
/// </summary> /// </summary>
/// <value>The password.</value> /// <value>The password.</value>
[DisplayName("Mot de passe"), [DisplayName("Mot de passe"),
Required(ErrorMessage = "S'il vous plait, entez un mot de passe"), RegularExpression("([a-z]|[A-Z]|[\\s-_.~]|[0-9])+")]
RegularExpression("([a-z]|[A-Z]|[0-9]|[-_.~#{}`'\\^])+")]
public string Password { get; set; } public string Password { get; set; }
/// <summary> /// <summary>

@ -219,7 +219,11 @@ namespace Yavsc.Model.RolesAndMembers
/// Gets or sets the name of the user. /// Gets or sets the name of the user.
/// </summary> /// </summary>
/// <value>The name of the user.</value> /// <value>The name of the user.</value>
public string UserName { get { return userName; } } [Localizable(true), Required(ErrorMessage = "S'il vous plait, entrez un nom d'utilisateur valide")
,Display(ResourceType=typeof(LocalizedText),Name="User_name"),
RegularExpression("([a-z]|[A-Z]|[\\s-_.~]|[0-9])+")
]
public string UserName { get { return userName; } set { userName=value; } }
public Profile () : base () public Profile () : base ()
{ {
@ -276,7 +280,6 @@ namespace Yavsc.Model.RolesAndMembers
userName = profile.UserName; userName = profile.UserName;
s = profile.GetPropertyValue ("BankCode"); s = profile.GetPropertyValue ("BankCode");
BankCode = (s is DBNull) ? null : (string)s; BankCode = (s is DBNull) ? null : (string)s;
@ -290,11 +293,10 @@ namespace Yavsc.Model.RolesAndMembers
WicketCode = (s is DBNull) ? null : (string)s; WicketCode = (s is DBNull) ? null : (string)s;
s = profile.GetPropertyValue ("AccountNumber"); s = profile.GetPropertyValue ("AccountNumber");
this.AccountNumber = (s is DBNull) ? null : (string)s; AccountNumber = (s is DBNull) ? null : (string)s;
s = profile.GetPropertyValue ("BankedKey");
BankedKey = (s == null) ? 0 : (s is DBNull)? 0 : (int)s;
object o = profile.GetPropertyValue ("BankedKey");
BankedKey = (int)0;
s = profile.GetPropertyValue ("gcalid"); s = profile.GetPropertyValue ("gcalid");
GoogleCalendar = (s is DBNull)? null : (string) s; GoogleCalendar = (s is DBNull)? null : (string) s;
} }

@ -0,0 +1,46 @@
//
// ProfileEdition.cs
//
// Author:
// Paul Schneider <paul@pschneider.fr>
//
// 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 <http://www.gnu.org/licenses/>.
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Web.Profile;
namespace Yavsc.Model.RolesAndMembers
{
public class ProfileEdition : Profile
{
public ProfileEdition()
{}
public ProfileEdition(ProfileBase pr): base(pr)
{
NewUserName = UserName;
}
[Localizable(true), Required(ErrorMessage = "S'il vous plait, entrez un nom d'utilisateur valide")
,Display(ResourceType=typeof(LocalizedText),Name="User_name"),
RegularExpression("([a-z]|[A-Z]|[\\s-_.~]|[0-9])+")
]
public string NewUserName { get; set; }
}
}

@ -35,7 +35,8 @@ namespace Yavsc.Model.RolesAndMembers
/// </summary> /// </summary>
/// <value>The full name.</value> /// <value>The full name.</value>
[DisplayName("Nom complet")] [DisplayName("Nom complet")]
[Required(ErrorMessage="S'il vous plait, saisissez le nom complet")] [Required(ErrorMessage="S'il vous plait, saisissez le nom complet"),
RegularExpression("([a-z]|[A-Z]|[\\s-_.~]|[0-9])+")]
public string Name { get; set; } public string Name { get; set; }
/// <summary> /// <summary>
/// Gets or sets the address. /// Gets or sets the address.

@ -15,6 +15,12 @@ namespace Yavsc.Model.RolesAndMembers
/// <param name="oldName">Old name.</param> /// <param name="oldName">Old name.</param>
/// <param name="newName">New name.</param> /// <param name="newName">New name.</param>
public static void ChangeName (string oldName, string newName) { public static void ChangeName (string oldName, string newName) {
if (!IsAvailable (newName))
throw new Exception (
string.Format(
LocalizedText.DuplicateUserName,
newName
));
Provider.ChangeName (oldName, newName); Provider.ChangeName (oldName, newName);
} }

@ -179,6 +179,7 @@
<Compile Include="Calendar\ICalendarManager.cs" /> <Compile Include="Calendar\ICalendarManager.cs" />
<Compile Include="Messaging\Notification.cs" /> <Compile Include="Messaging\Notification.cs" />
<Compile Include="FileSystem\WebFileSystemManager.cs" /> <Compile Include="FileSystem\WebFileSystemManager.cs" />
<Compile Include="RolesAndMembers\ProfileEdition.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup> <ItemGroup>

Loading…