From 3355f9fed0009bebd682c1f6aa40a4148857350c Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Tue, 4 Aug 2015 02:10:28 +0200 Subject: [PATCH] * bg.gif: * asc.gif: * desc.gif: * style.css: moved to App_Themes * style.css: * bg.gif: * asc.gif: * bg.png: * rect.png: * asc.png: * desc.gif: * jquery-ui.css: * mdd_styles.css: * croix.png: * desc.png: * style.css: * jquery-ui.min.css: * mdd_gripper.png: * mdd_toolbar.png: * jquery.timepicker.css: * mdd_ajax_loader.gif: * mdd_modal_background.png: moved to /App_Themes * NpgsqlBlogProvider.cs: * Remove post by id * Manage collections of entries on a couple (user,title), not a single post * NpgsqlCircleProvider.cs: Fixes the "Match" method. * IDbModule.cs: * Edit.aspx: * Estimates.aspx: * WorkFlowManager.cs: * NpgsqlContentProvider.cs: refactoring * NpgsqlMRPProviders.csproj: new NpgsqlUserName provider * NpgsqlRoleProvider.cs: simpler init method * NpgsqlUserNameProvider.cs: impements a UserNameProvider * MyClass.cs: refactoring from Yavsc.Model * BlogsController.cs: access control simplified * FrontOfficeController.cs: Pdf generation made public ni case of formatting exception * mdd_styles.css: Theme -> App_Themes * style.css: yet another style impact * AccountController.cs: Fixes the user name modification * BlogsController.cs: * Fixes the removal process * On a title and user name, we get collection of posts, not only one. * Implements an Access on circle * FrontOfficeController.cs: * implements a new Get method. * ensure a membership existence before delivering an estimate. * GoogleController.cs: Fixes the user name modification on a Google account * ErrorHtmlFormatter.cs: nice error message in html (using Markdown helper) * FormatterException.cs: formatter exception exposes error and standard output of the process * TexToPdfFormatter.cs: * generates temporary files in the folder returned by Path.GetTempPath() * throws FormatterException * Global.asax.cs: new route map: Blogs/{action}/{user}/{title} Blog/{user}/{title} B/{id} {controller}/{action}/{id} * App.master: * refactoring: Theme moved to App_Themes * a link to the logged user's blog * * NoLogin.master: refactoring: Theme moved to App_Themes * Circles.aspx: refactoring : circles now are given as select items * Login.aspx: fixes the html presentation * Register.aspx: Fixes a Typo * Index.aspx: Implements a blog index, due to M&C changes with this commit * RemovePost.aspx: links to the new route to the "RemovePost" action, giving it a post id * RemoveTitle.aspx: fixes a not yet linked page to remove a post collection under a given title * EventPub.aspx: code refactoring * Writting.ascx: cleans the code * Web.config: fills the config with new names in the space * Web.config: configures the new NpgsqlUserNameProvider * Web.csproj: refactoring and others * BlogEntryCollection.cs: implement the BlogEntryCollection * BlogManager.cs: the manager helps to filter on access * BlogProvider.cs: The title is not unique anymore, and one can modify it, post a lot under it, drop all posts under it. A Post is deleted by id. * UUBlogEntryCollection.cs: implements a collection of post under a given user name. * UUTBlogEntryCollection.cs: implements a collection of post under a given couple (user name, title). * ListItem.cs: ListItem is declared obsolete in this model, helpers can build MVC SelectListItem on data returned by the manager. * LocalizedText.Designer.cs: * LocalizedText.fr.Designer.cs: autogenerated from xml * LocalizedText.resx: * LocalizedText.fr.resx: new labels * ChangeUserNameProvider.cs: xml doc * Profile.cs: the UserName property is read only, and comes from authentication, to change it, we set a Name and validate it agains the "Profile" method * UserManager.cs: simpler code a init time * IContentProvider.cs: implements the new IDataProvider interface * IDataProvider.cs: defines the new IDataProvider interface * YavscModel.csproj: includes new classes * UserPosts.aspx: adds a link to remove a post * UserPost.aspx: now uses the new BlogEntryCollection object --- NpgsqlBlogProvider/ChangeLog | 7 + NpgsqlBlogProvider/NpgsqlBlogProvider.cs | 109 +- NpgsqlContentProvider/ChangeLog | 6 + NpgsqlContentProvider/NpgsqlCircleProvider.cs | 2 +- .../NpgsqlContentProvider.cs | 10 +- NpgsqlMRPProviders/ChangeLog | 8 + NpgsqlMRPProviders/NpgsqlMRPProviders.csproj | 1 + NpgsqlMRPProviders/NpgsqlRoleProvider.cs | 45 +- NpgsqlMRPProviders/NpgsqlUserNameProvider.cs | 84 +- plugins/fortune/ChangeLog | 4 + plugins/fortune/MyClass.cs | 2 +- web/ApiControllers/BlogsController.cs | 26 +- web/ApiControllers/FrontOfficeController.cs | 46 +- web/App_Themes/mdd_styles.css | 8 +- web/App_Themes/style.css | 96 +- web/ChangeLog | 107 ++ web/Controllers/AccountController.cs | 43 +- web/Controllers/BlogsController.cs | 282 ++-- web/Controllers/FrontOfficeController.cs | 22 +- web/Controllers/GoogleController.cs | 6 +- web/Formatters/ErrorHtmlFormatter.cs | 4 +- web/Formatters/FormatterException.cs | 3 + web/Formatters/TexToPdfFormatter.cs | 56 +- web/Global.asax.cs | 24 +- web/Models/App.master | 50 +- web/Models/NoLogin.master | 4 +- web/Theme/blue/asc.gif | Bin 54 -> 0 bytes web/Theme/blue/bg.gif | Bin 64 -> 0 bytes web/Theme/blue/desc.gif | Bin 54 -> 0 bytes web/Theme/blue/style.css | 39 - web/Theme/dark/asc.gif | Bin 54 -> 0 bytes web/Theme/dark/bg.gif | Bin 64 -> 0 bytes web/Theme/dark/croix.png | Bin 172 -> 0 bytes web/Theme/dark/desc.gif | Bin 54 -> 0 bytes web/Theme/dark/rect.png | Bin 1617 -> 0 bytes web/Theme/green/asc.png | Bin 2665 -> 0 bytes web/Theme/green/bg.png | Bin 2655 -> 0 bytes web/Theme/green/desc.png | Bin 2662 -> 0 bytes web/Theme/green/style.css | 39 - web/Theme/jquery-ui.css | 1225 ----------------- web/Theme/jquery-ui.min.css | 7 - web/Theme/jquery.timepicker.css | 72 - web/Theme/md/mdd_ajax_loader.gif | Bin 2608 -> 0 bytes web/Theme/md/mdd_gripper.png | Bin 150 -> 0 bytes web/Theme/md/mdd_modal_background.png | Bin 173 -> 0 bytes web/Theme/md/mdd_toolbar.png | Bin 7051 -> 0 bytes web/Theme/mdd_styles.css | 198 --- web/Theme/style.css | 256 ---- web/Views/Account/Circles.aspx | 2 +- web/Views/Account/Login.aspx | 10 +- web/Views/Account/Register.aspx | 2 +- web/Views/Blogs/Edit.aspx | 11 +- web/Views/Blogs/Index.aspx | 44 +- web/Views/Blogs/RemovePost.aspx | 9 +- web/Views/Blogs/RemoveTitle.aspx | 6 +- web/Views/Blogs/UserPost.aspx | 66 +- web/Views/Blogs/UserPosts.aspx | 8 +- web/Views/FrontOffice/Estimates.aspx | 17 +- web/Views/FrontOffice/EventPub.aspx | 2 +- web/Views/FrontOffice/Writting.ascx | 1 - web/Views/Web.config | 3 + web/Web.config | 8 +- web/Web.csproj | 55 +- yavscModel/Blogs/BlogEntryCollection.cs | 150 ++ yavscModel/Blogs/BlogManager.cs | 161 ++- yavscModel/Blogs/BlogProvider.cs | 34 +- yavscModel/Blogs/UUBlogEntryCollection.cs | 12 +- yavscModel/Blogs/UUTBlogEntryCollection.cs | 59 +- yavscModel/ChangeLog | 45 + yavscModel/IDbModule.cs | 2 +- yavscModel/ListItem.cs | 1 + yavscModel/LocalizedText.Designer.cs | 30 +- yavscModel/LocalizedText.fr.Designer.cs | 30 +- yavscModel/LocalizedText.fr.resx | 5 +- yavscModel/LocalizedText.resx | 6 +- .../RolesAndMembers/ChangeUserNameProvider.cs | 12 +- yavscModel/RolesAndMembers/Profile.cs | 6 +- yavscModel/RolesAndMembers/UserManager.cs | 38 +- yavscModel/WorkFlow/IContentProvider.cs | 14 +- yavscModel/WorkFlow/IDataProvider.cs | 4 +- yavscModel/WorkFlow/WorkFlowManager.cs | 4 +- yavscModel/YavscModel.csproj | 8 +- 82 files changed, 1287 insertions(+), 2469 deletions(-) delete mode 100644 web/Theme/blue/asc.gif delete mode 100644 web/Theme/blue/bg.gif delete mode 100644 web/Theme/blue/desc.gif delete mode 100644 web/Theme/blue/style.css delete mode 100644 web/Theme/dark/asc.gif delete mode 100644 web/Theme/dark/bg.gif delete mode 100644 web/Theme/dark/croix.png delete mode 100644 web/Theme/dark/desc.gif delete mode 100644 web/Theme/dark/rect.png delete mode 100644 web/Theme/green/asc.png delete mode 100644 web/Theme/green/bg.png delete mode 100644 web/Theme/green/desc.png delete mode 100644 web/Theme/green/style.css delete mode 100644 web/Theme/jquery-ui.css delete mode 100644 web/Theme/jquery-ui.min.css delete mode 100755 web/Theme/jquery.timepicker.css delete mode 100644 web/Theme/md/mdd_ajax_loader.gif delete mode 100644 web/Theme/md/mdd_gripper.png delete mode 100644 web/Theme/md/mdd_modal_background.png delete mode 100644 web/Theme/md/mdd_toolbar.png delete mode 100644 web/Theme/mdd_styles.css delete mode 100644 web/Theme/style.css diff --git a/NpgsqlBlogProvider/ChangeLog b/NpgsqlBlogProvider/ChangeLog index 774ac7f7..383f59a6 100644 --- a/NpgsqlBlogProvider/ChangeLog +++ b/NpgsqlBlogProvider/ChangeLog @@ -1,3 +1,10 @@ +2015-08-04 Paul Schneider + + * NpgsqlBlogProvider.cs: * Remove post by id + * Manage collections of entries on a couple (user,title), not + a single post + + 2015-07-15 Paul Schneider * NpgsqlBlogProvider.csproj: Moves to Mono framework diff --git a/NpgsqlBlogProvider/NpgsqlBlogProvider.cs b/NpgsqlBlogProvider/NpgsqlBlogProvider.cs index 59ed4756..d38171a1 100644 --- a/NpgsqlBlogProvider/NpgsqlBlogProvider.cs +++ b/NpgsqlBlogProvider/NpgsqlBlogProvider.cs @@ -122,7 +122,13 @@ namespace Npgsql.Web.Blog /// Postid. public override void RemovePost (long postid) { - throw new NotImplementedException (); + using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) + using (NpgsqlCommand cmd = cnx.CreateCommand ()) { + cmd.CommandText = "delete from blog where _id = @id"; + cmd.Parameters.AddWithValue ("id", postid); + cnx.Open (); + cmd.ExecuteNonQuery(); + } } /// /// Comment the specified from, postid and content. @@ -136,7 +142,7 @@ namespace Npgsql.Web.Blog throw new ArgumentNullException("from"); if (content == null) throw new ArgumentNullException("content"); - bool visible = AutoValidateComment; + bool visible = AutoValidatesComments; using (NpgsqlConnection cnx= new NpgsqlConnection(connectionString)) using (NpgsqlCommand cmd = cnx.CreateCommand()) { @@ -181,7 +187,7 @@ namespace Npgsql.Web.Blog /// Gets or sets a value indicating whether this auto validate comment. /// /// true if auto validate comment; otherwise, false. - public override bool AutoValidateComment { + public override bool AutoValidatesComments { get { return autoValidateComment; } @@ -273,52 +279,62 @@ namespace Npgsql.Web.Blog /// The post. /// Username. /// Title. - public override BlogEntry GetPost (string username, string title) + public override UUTBlogEntryCollection GetPost (string username, string title) { - BlogEntry be = null; - using (NpgsqlConnection cnx=new NpgsqlConnection(connectionString)) - using (NpgsqlCommand cmd = cnx.CreateCommand()) { - cmd.CommandText = "select _id,bcontent,modified,posted,visible from blog " + - "where applicationname = :appname and username = :username and title = :title"; - cmd.Parameters.AddWithValue ("appname", applicationName); - cmd.Parameters.AddWithValue ("username", username); - cmd.Parameters.AddWithValue ("title", title); - cnx.Open (); - using (NpgsqlDataReader rdr = cmd.ExecuteReader()) { - if (rdr.Read ()) { - be = new BlogEntry (); - be.Title = title; - be.Content = rdr.GetString (rdr.GetOrdinal ("bcontent")); - be.UserName = username; - be.Modified = rdr.GetDateTime (rdr.GetOrdinal ("modified")); - be.Posted = rdr.GetDateTime (rdr.GetOrdinal ("posted")); - be.Visible = rdr.GetBoolean (rdr.GetOrdinal ("visible")); - be.Id = rdr.GetInt64 (rdr.GetOrdinal ("_id")); - } - rdr.Close (); - } - if (be != null) { - using (NpgsqlCommand cmdtags = cnx.CreateCommand ()) { - List tags = new List (); - cmd.CommandText = "select tag.name from tag,tagged where tag._id = tagged.tagid and tagged.postid = :pid"; - cmd.Parameters.AddWithValue ("pid", be.Id); - using (NpgsqlDataReader rdrt = cmd.ExecuteReader ()) { - while (rdrt.Read ()) { - tags.Add (rdrt.GetString (0)); - } + UUTBlogEntryCollection bec = new UUTBlogEntryCollection (username,title); + using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) { + using (NpgsqlCommand cmd = cnx.CreateCommand ()) { + cmd.CommandText = "select _id,bcontent,modified,posted,visible from blog " + + "where applicationname = :appname and username = :username and title = :title"; + cmd.Parameters.AddWithValue ("appname", applicationName); + cmd.Parameters.AddWithValue ("username", username); + cmd.Parameters.AddWithValue ("title", title); + cnx.Open (); + cmd.Prepare (); + using (NpgsqlDataReader rdr = cmd.ExecuteReader ()) { + while (rdr.Read ()) { + BlogEntry be = new BlogEntry (); + be.Title = title; + be.Content = rdr.GetString (rdr.GetOrdinal ("bcontent")); + be.UserName = username; + be.Modified = rdr.GetDateTime (rdr.GetOrdinal ("modified")); + be.Posted = rdr.GetDateTime (rdr.GetOrdinal ("posted")); + be.Visible = rdr.GetBoolean (rdr.GetOrdinal ("visible")); + be.Id = rdr.GetInt64 (rdr.GetOrdinal ("_id")); + bec.Add (be); } - be.Tags = tags.ToArray (); + rdr.Close (); } - SetCirclesOn (be); + + } + if (bec.Count != 0) { + using (NpgsqlCommand cmdtags = cnx.CreateCommand ()) { + long pid = 0; + cmdtags.CommandText = "select tag.name from tag,tagged where tag._id = tagged.tagid and tagged.postid = :postid"; + cmdtags.Parameters.AddWithValue ("postid", NpgsqlTypes.NpgsqlDbType.Bigint, pid); + cmdtags.Prepare (); + foreach (BlogEntry be in bec) { + List tags = new List (); + cmdtags.Parameters ["postid"].Value = be.Id; + using (NpgsqlDataReader rdrt = cmdtags.ExecuteReader ()) { + while (rdrt.Read ()) { + tags.Add (rdrt.GetString (0)); + } + } + be.Tags = tags.ToArray (); + } + } + + SetCirclesOn (bec); } } - return be; + return bec; } private void SetCirclesOn(BlogEntry be) { List circles = new List (); - using (NpgsqlConnection cnx=new NpgsqlConnection(connectionString)) + using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) using (NpgsqlCommand cmdcircles = cnx.CreateCommand ()) { cmdcircles.CommandText = "select a.circle_id from blog_access a " + "where a.post_id = :pid"; @@ -326,11 +342,18 @@ namespace Npgsql.Web.Blog cnx.Open (); using (NpgsqlDataReader rdr = cmdcircles.ExecuteReader ()) { while (rdr.Read ()) { - circles.Add ( rdr.GetInt64 (0) ); + circles.Add (rdr.GetInt64 (0)); } } } - be.AllowedCircles = circles.ToArray(); + be.AllowedCircles = circles.ToArray (); + } + + private void SetCirclesOn(BlogEntryCollection bec) + { + foreach (BlogEntry be in bec) { + SetCirclesOn (be); + } } /// /// Post the specified username, title, content and visible. @@ -460,6 +483,7 @@ namespace Npgsql.Web.Blog if (totalRecords >= firstrec && totalRecords <= lastrec) { BlogEntry be = new BlogEntry (); be.Title = rdr.GetString (rdr.GetOrdinal ("title")); + be.Id = rdr.GetInt64 (rdr.GetOrdinal ("_id")); be.Content = rdr.GetString (rdr.GetOrdinal ("bcontent")); be.UserName = rdr.GetString (rdr.GetOrdinal ("username")); be.Posted = rdr.GetDateTime (rdr.GetOrdinal ("posted")); @@ -482,7 +506,7 @@ namespace Npgsql.Web.Blog /// /// Username. /// Title. - public override void RemovePost (string username, string title) + public override void RemoveTitle (string username, string title) { using (NpgsqlConnection cnx=new NpgsqlConnection(connectionString)) using (NpgsqlCommand cmd = cnx.CreateCommand()) { @@ -531,6 +555,7 @@ namespace Npgsql.Web.Blog while (rdr.Read()) { if (totalRecords >= firstrec && totalRecords <= lastrec) { BlogEntry be = new BlogEntry (); + be.Id = rdr.GetInt64 (rdr.GetOrdinal ("_id")); be.Title = rdr.GetString (rdr.GetOrdinal ("title")); be.Content = rdr.GetString (rdr.GetOrdinal ("bcontent")); be.UserName = rdr.GetString (rdr.GetOrdinal ("username")); diff --git a/NpgsqlContentProvider/ChangeLog b/NpgsqlContentProvider/ChangeLog index 57739610..5acf5451 100644 --- a/NpgsqlContentProvider/ChangeLog +++ b/NpgsqlContentProvider/ChangeLog @@ -1,3 +1,9 @@ +2015-08-04 Paul Schneider + + * NpgsqlCircleProvider.cs: Fixes the "Match" method. + + * NpgsqlContentProvider.cs: refactoring + 2015-07-15 Paul Schneider * NpgsqlCircleProvider.cs: Makes Circles private, or not diff --git a/NpgsqlContentProvider/NpgsqlCircleProvider.cs b/NpgsqlContentProvider/NpgsqlCircleProvider.cs index 053ef303..d724126d 100644 --- a/NpgsqlContentProvider/NpgsqlCircleProvider.cs +++ b/NpgsqlContentProvider/NpgsqlCircleProvider.cs @@ -55,7 +55,7 @@ namespace WorkFlowProvider bool result=false; using (NpgsqlConnection cnx = new NpgsqlConnection (connectionString)) using (NpgsqlCommand cmd = cnx.CreateCommand ()) { - cmd.CommandText = "select count(*)>0 from circle_members where _id = :cid and m.member = :mbr"; + cmd.CommandText = "select count(*)>0 from circle_members where circle_id = :cid and member = :mbr"; cmd.Parameters.Add("cid",NpgsqlDbType.Bigint); cmd.Parameters.AddWithValue("mbr",member); cnx.Open (); diff --git a/NpgsqlContentProvider/NpgsqlContentProvider.cs b/NpgsqlContentProvider/NpgsqlContentProvider.cs index 31a2f2b6..2c3a514c 100644 --- a/NpgsqlContentProvider/NpgsqlContentProvider.cs +++ b/NpgsqlContentProvider/NpgsqlContentProvider.cs @@ -20,6 +20,8 @@ namespace Yavsc /// public class NpgsqlContentProvider: ProviderBase, IContentProvider { + + /// /// Registers the command. /// @@ -263,7 +265,7 @@ namespace Yavsc cnx.Close (); } foreach (long id in ids) - ests.Add(GetEstimate(id)); + ests.Add(Get(id)); return ests.ToArray(); } } @@ -306,7 +308,7 @@ namespace Yavsc rdr.Close (); } foreach (long id in ids) - ests.Add(GetEstimate(id)); + ests.Add(Get(id)); return ests.ToArray(); } } @@ -354,7 +356,7 @@ namespace Yavsc /// /// The estimate. /// Estimid. - public Estimate GetEstimate (long estimid) + public Estimate Get (long estimid) { Estimate est = null; using (NpgsqlConnection cnx = CreateConnection ()) { @@ -448,7 +450,7 @@ namespace Yavsc /// Saves the given Estimate object in database. /// /// the Estimate object. - public void UpdateEstimate (Estimate estim) + public void Update (Estimate estim) { using (NpgsqlConnection cnx = CreateConnection ()) { using (NpgsqlCommand cmd = cnx.CreateCommand ()) { diff --git a/NpgsqlMRPProviders/ChangeLog b/NpgsqlMRPProviders/ChangeLog index d0819b45..4ae9c1df 100644 --- a/NpgsqlMRPProviders/ChangeLog +++ b/NpgsqlMRPProviders/ChangeLog @@ -1,3 +1,11 @@ +2015-08-04 Paul Schneider + + * NpgsqlMRPProviders.csproj: new NpgsqlUserName provider + + * NpgsqlRoleProvider.cs: simpler init method + + * NpgsqlUserNameProvider.cs: impements a UserNameProvider + 2015-08-01 Paul Schneider * NpgsqlMembershipProvider.cs: Fixes the membership update. diff --git a/NpgsqlMRPProviders/NpgsqlMRPProviders.csproj b/NpgsqlMRPProviders/NpgsqlMRPProviders.csproj index 076cb50a..6087ecb3 100644 --- a/NpgsqlMRPProviders/NpgsqlMRPProviders.csproj +++ b/NpgsqlMRPProviders/NpgsqlMRPProviders.csproj @@ -36,6 +36,7 @@ + diff --git a/NpgsqlMRPProviders/NpgsqlRoleProvider.cs b/NpgsqlMRPProviders/NpgsqlRoleProvider.cs index 1408cf86..e233a7e4 100644 --- a/NpgsqlMRPProviders/NpgsqlRoleProvider.cs +++ b/NpgsqlMRPProviders/NpgsqlRoleProvider.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; using System.Linq; - +using System.Collections.Specialized; namespace Npgsql.Web { @@ -38,40 +38,19 @@ namespace Npgsql.Web /// /// Iname. /// Config. - public override void Initialize (string iname, System.Collections.Specialized.NameValueCollection config) + public override void Initialize (string iname, NameValueCollection config) { - try { - - name = iname ?? config ["name"]; - - connectionStringName = config ["connectionStringName"] ?? connectionStringName; - - applicationName = config ["applicationName"] ?? applicationName; - - if (applicationName.Length > 250) - throw new ProviderException ("The maximum length for an application name is 250 characters."); - - var cs = ConfigurationManager.ConnectionStrings [connectionStringName]; - if (cs == null || string.IsNullOrEmpty (cs.ConnectionString)) { - throw new ProviderException ( - string.Format ("The role provider connection string, '{0}', is not defined.", connectionStringName)); - } - - connectionString = ConfigurationManager.ConnectionStrings [connectionStringName].ConnectionString; - if (string.IsNullOrEmpty (connectionString)) - throw new ConfigurationErrorsException ( - string.Format ( - "The connection string for the given name ({0})" + - "must be specified in the " + - "configuration bloc. Aborting.", connectionStringName) - ); - - } catch (Exception ex) { - var message = "Error initializing the role configuration settings"; - throw new ProviderException (message, ex); - } + // get the + // - application name + // - connection string name + // - the connection string from its name + string cnxName = config ["connectionStringName"]; + connectionString = ConfigurationManager.ConnectionStrings [cnxName].ConnectionString; + config.Remove ("connectionStringName"); + applicationName = config ["applicationName"]; + config.Remove ("applicationName"); + base.Initialize (iname, config); } - /// To be added. /// /// Adds the users to roles. diff --git a/NpgsqlMRPProviders/NpgsqlUserNameProvider.cs b/NpgsqlMRPProviders/NpgsqlUserNameProvider.cs index a5f281e6..49692be4 100644 --- a/NpgsqlMRPProviders/NpgsqlUserNameProvider.cs +++ b/NpgsqlMRPProviders/NpgsqlUserNameProvider.cs @@ -18,34 +18,86 @@ // // You should have received a copy of the GNU Lesser General Public License // along with this program. If not, see . - -using System.Web.Security; -using System.Configuration.Provider; -using System.Collections.Specialized; using System; -using System.Data; -using Npgsql; -using NpgsqlTypes; +using System.Collections.Specialized; using System.Configuration; -using System.Diagnostics; -using System.Web; -using System.Globalization; -using System.Security.Cryptography; -using System.Text; -using System.Web.Configuration; -namespace Npgsql.Web +namespace Npgsql.Web.RolesAndMembers { using Yavsc.Model.RolesAndMembers; + + /// + /// Npgsql user name provider. + /// public class NpgsqlUserNameProvider: ChangeUserNameProvider { + private string applicationName; + private string connectionString; + /// + /// Initialize the specified iname and config. + /// + /// Iname. + /// Config. + public override void Initialize (string iname, NameValueCollection config) + { + // get the + // - application name + // - connection string name + // - the connection string from its name + string cnxName = config ["connectionStringName"]; + connectionString = ConfigurationManager.ConnectionStrings [cnxName].ConnectionString; + config.Remove ("connectionStringName"); + applicationName = config ["applicationName"]; + config.Remove ("applicationName"); + base.Initialize (iname, config); + + } + private string GetConfigValue (string configValue, string defaultValue) + { + if (String.IsNullOrEmpty (configValue)) + return defaultValue; + + return configValue; + } + #region implemented abstract members of ChangeUserNameProvider + /// + /// Changes the name. + /// + /// Old name. + /// New name. public override void ChangeName (string oldName, string newName) { - throw new NotImplementedException (); + using (NpgsqlConnection conn = new NpgsqlConnection (connectionString)) { + conn.Open (); + using (NpgsqlCommand cmd = new NpgsqlCommand ( + "UPDATE users set " + + "username = :uname where username = :oname" + + " AND ApplicationName = :appname ", conn)) { + cmd.Parameters.AddWithValue ("uname", newName); + cmd.Parameters.AddWithValue ("oname", oldName); + cmd.Parameters.AddWithValue ("appname", this.applicationName); + cmd.ExecuteNonQuery (); + } + } } + /// + /// Determines whether this instance is name available the specified name. + /// + /// true + /// false + /// Name. public override bool IsNameAvailable (string name) { - throw new NotImplementedException (); + using (NpgsqlConnection conn = new NpgsqlConnection (connectionString)) { + conn.Open (); + using (NpgsqlCommand cmd = new NpgsqlCommand ( + "SELECT count(*)>0 FROM users " + + "WHERE username = :uname AND ApplicationName = :appname", conn)) { + cmd.Parameters.AddWithValue ("uname", name); + cmd.Parameters.AddWithValue ("appname", this.applicationName); + return (bool) cmd.ExecuteScalar (); + } + } } #endregion } diff --git a/plugins/fortune/ChangeLog b/plugins/fortune/ChangeLog index 9fd827de..5e39aefc 100644 --- a/plugins/fortune/ChangeLog +++ b/plugins/fortune/ChangeLog @@ -1,3 +1,7 @@ +2015-08-04 Paul Schneider + + * MyClass.cs: refactoring from Yavsc.Model + 2015-07-15 Paul Schneider * fortune.csproj: Moves to Mono framework diff --git a/plugins/fortune/MyClass.cs b/plugins/fortune/MyClass.cs index 1fdc5f5f..cd08cf19 100644 --- a/plugins/fortune/MyClass.cs +++ b/plugins/fortune/MyClass.cs @@ -12,7 +12,7 @@ namespace fortune public string Body{ get; set; } } - public class MyClass : IModule + public class MyClass : IDbModule { public MyClass () { diff --git a/web/ApiControllers/BlogsController.cs b/web/ApiControllers/BlogsController.cs index 531dd03d..3c497fef 100644 --- a/web/ApiControllers/BlogsController.cs +++ b/web/ApiControllers/BlogsController.cs @@ -6,6 +6,7 @@ using System.Web.Security; using System.Web.Http; using Npgsql.Web.Blog; using Yavsc.Model.Blogs; +using System.IO; namespace Yavsc.ApiControllers { @@ -34,37 +35,26 @@ namespace Yavsc.ApiControllers /// Postid. /// Tag. public long Tag (long postid,string tag) { - BlogEntry e = BlogManager.GetPost (postid); - if (!Roles.IsUserInRole ("Admin")) { - string rguser = Membership.GetUser ().UserName; - if (rguser != e.UserName) { - throw new AccessViolationException ( - string.Format ( - "Vous n'avez pas le droit de tagger des billets du Blog de {0}", - e.UserName)); - } - } + BlogManager.GetForEditing (postid); return BlogManager.Tag (postid, tag); } + /// /// Removes the post. /// /// User. /// Title. - public void RemovePost(string user, string title) { - BlogEntry e = BlogManager.GetPost (user, title); - if (e == null) { - throw new KeyNotFoundException ( - string.Format("Aucun post portant le titre \"{0}\" pour l'utilisateur {1}", - title, user)); - } - BlogManager.RemovePost (user, title); + [Authorize] + public void RemoveTitle(string user, string title) { + BlogManager.CheckAuthCanEdit (user,title); + BlogManager.RemoveTitle (user, title); } /// /// Removes the tag. /// /// Tagid. public void RemoveTag(long tagid) { + throw new NotImplementedException (); } } diff --git a/web/ApiControllers/FrontOfficeController.cs b/web/ApiControllers/FrontOfficeController.cs index fecbdb84..a7c43f12 100644 --- a/web/ApiControllers/FrontOfficeController.cs +++ b/web/ApiControllers/FrontOfficeController.cs @@ -16,6 +16,8 @@ using System.IO; namespace Yavsc.ApiControllers { + + /// /// Front office controller. /// @@ -58,18 +60,6 @@ namespace Yavsc.ApiControllers return CatalogManager.GetCatalog ().GetBrand (brandName).GetProductCategory (prodCategorie); } - /// - /// Authorization denied. - /// - public class AuthorizationDenied : HttpRequestException { - /// - /// Initializes a new instance of the class. - /// - /// Message. - public AuthorizationDenied(string msg) : base(msg) - { - } - } /// /// Gets the estimate. @@ -80,7 +70,7 @@ namespace Yavsc.ApiControllers [HttpGet] public Estimate GetEstimate (long id) { - Estimate est = wfmgr.ContentProvider.GetEstimate (id); + Estimate est = wfmgr.ContentProvider.Get (id); string username = Membership.GetUser ().UserName; if (est.Client != username) if (!Roles.IsUserInRole("Admin")) @@ -135,7 +125,7 @@ namespace Yavsc.ApiControllers tmpe.Session.Add ("from", prpro); tmpe.Session.Add ("to", prcli); tmpe.Session.Add ("efrom", Membership.GetUser (e.Responsible).Email); - tmpe.Session.Add ("efrom", Membership.GetUser (e.Client).Email); + tmpe.Session.Add ("eto", Membership.GetUser (e.Client).Email); tmpe.Init (); return tmpe.TransformText (); } @@ -173,15 +163,29 @@ namespace Yavsc.ApiControllers }; var memPdf = new MemoryStream (); - HttpResponseMessage result = new HttpResponseMessage (); + try { new TexToPdfFormatter ().WriteToStream ( typeof(string), texest, memPdf,null); - memPdf.Position = 0; - var sr = new StreamReader(memPdf); - var str = sr.ReadToEnd(); - result.Content = new StringContent (str); - TexToPdfFormatter.SetFileName (result.Content.Headers, "estimate-" + id.ToString ()); - result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/x-tex"); + } + catch (FormatterException ex) { + return new HttpResponseMessage (HttpStatusCode.OK) { Content = + new ObjectContent (typeof(string), ex.Message+"\n\n"+ex.Output+"\n\n"+ex.Error, + new ErrorHtmlFormatter (HttpStatusCode.InternalServerError, + LocalizedText.InternalServerError)) + }; + } + + var result = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = new ByteArrayContent(memPdf.GetBuffer()) + }; + + result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue ("attachment") { + FileName = String.Format ( + "Estimation-{0}.pdf", + id) + }; + return result; } diff --git a/web/App_Themes/mdd_styles.css b/web/App_Themes/mdd_styles.css index dd984fb9..2474b5df 100644 --- a/web/App_Themes/mdd_styles.css +++ b/web/App_Themes/mdd_styles.css @@ -10,7 +10,7 @@ div.mdd_modal z-index:1000; display:none; font-size:10pt; - background-image:url(/Theme/md/mdd_modal_background.png); + background-image:url(/App_Themes/md/mdd_modal_background.png); } div.mdd_modal_frame { @@ -64,7 +64,7 @@ div.mdd_modal_content div.mdd_ajax_loader { background-position: center center; - background-image: url(/Theme/md/mdd_ajax_loader.gif); + background-image: url(/App_Themes/md/mdd_ajax_loader.gif); background-repeat: no-repeat; width:100%; height:200px; @@ -119,7 +119,7 @@ div.mdd_toolbar li div.mdd_toolbar a.mdd_button { - background-image:url(/Theme/md/mdd_toolbar.png); + background-image:url(/App_Themes/md/mdd_toolbar.png); width:20px; height:20px; display:block; @@ -184,7 +184,7 @@ textarea.mdd_editor div.mdd_resizer { background:#f8f8f8; - background-image:url("/Theme/md/mdd_gripper.png"); + background-image:url("/App_Themes/md/mdd_gripper.png"); background-position:center center; background-repeat:no-repeat; width:100%; diff --git a/web/App_Themes/style.css b/web/App_Themes/style.css index 46d58c81..ce97cf3b 100644 --- a/web/App_Themes/style.css +++ b/web/App_Themes/style.css @@ -5,8 +5,8 @@ body { background-repeat: no-repeat; color: #D0FFD0; font-family: 'Arial', cursive; - padding: .5em; - margin-bottom:2.8em; + padding: 0em; + margin-bottom:3em; } textarea { @@ -20,10 +20,8 @@ input, textarea, checkbox { } main { - background-color: rgba(17,0,23,0.65); - float:left; -} - + margin:1em; + } fieldset { background-color: rgba(32,16,16,0.8); border-radius:5px; border: solid 1px #000060; @@ -46,7 +44,6 @@ footer { z-index:-1; font-size: smaller; } - .thanks { max-width: 10%; text-align: center; @@ -59,12 +56,14 @@ footer { #logo { float: left; + max-height: 25%; + max-width: 25%; } .panel,.bshpanel,aside { background-color: rgba(32,16,16,0.8); border-radius:5px; border: solid 1px #000060; - float: right; + float: left; margin:.5em; padding: .5em; } @@ -72,23 +71,29 @@ footer { .bsh { float: right; } #login { + position: fixed; + margin:0em; + padding:0em; top:0; right:0; - background-color:rgba(16,16,0,0.8); justify-content: space-around; text-align: center; + max-width:40%; + font-size:75%; } + #login img { max-height:5em; max-width:5em; } header { background-color:rgba(16,16,0,0.8); top:0; left:0; - right:0; + margin:0em; + padding:0em; text-align: center; + max-width:55%; } - h1 img { vertical-align: text-top; } - +h1 img { vertical-align: text-top; } a { text-decoration: none; @@ -135,7 +140,15 @@ label { .blogtitle { display:inline; } - +.blogpost { + display:block; + margin:1em; + padding:1em; + border: solid 2px blue; + background-color: #090609; + color: #aaa; + border-radius:5px; +} .contenu { padding-left: 20px; } @@ -158,14 +171,13 @@ ul.preview li:nth-child(n) { .actionlink { color: #B0B080; border: solid 1px rgb(128,128,128); - border-radius:5px; + border-radius: 5px; background-color:rgba(0,0,32,0.8); - font-size:large; cursor: pointer; font-family: 'Arial', cursive; } - input, select { +input, select { color: #B0B080; border: solid 1px rgb(128,128,128); border-radius:5px; @@ -193,46 +205,30 @@ a.actionlink img { top:4px; } max-height: 64px; } -.hidden { - display:none; - } - - .shoh { display:inline; } - - -.hiduh { - display:none; - } - .shoh:hover { - background-color: rgba(0,60,40,.3); - border: solid rgb(256,256,0); - } -.shoh:hover + .hiduh { - display:block; position:absolute; left:20px; right:20px; - background-color: rgb(0,0,40); border: solid rgb(256,256,0); - } - .comment { border-radius:25px; border-width:1px; - border-style: solid; + border-style: solid; border-color:rgb(0,64,0); font-size: smaller; } -.hidcom { - display:none; position:fixed; z-index:2; +.onhover { + display:none; + position: absolute; +} + +.ohafter:hover + .onhover, .ohinside:hover > .onhover { + display:block; + z-index:2; padding:5px; margin:5px; background-color: rgba(0,0,40,.8); } -a.actionlink:hover + .hidcom { - display:block; -} - .input-validation-error { border: solid 1px red; } .field-validation-error { color: red; } - +.c2 { font-size: small; font-style: italic; } +.c3 { font-size: x-small; font-style: italic; } @media print { body {background-color:white;color:black;} header,footer,.postcomment,.actionlink,.metablog,#login{ display:none;} @@ -240,26 +236,28 @@ a.actionlink:hover + .hidcom { @media all and (min-width: 641px) { .bshpanel { display:block; } .bsh { display: none; } + .c3 { display:initial; } + .c3-alt { display:none; } } @media all and (max-width: 640px) { .bshpanel { cursor:zoom-in; } -.bshd:hover > .bshpanel { - display: block; - } - .bshd:hover > .bsh { - display: none; - } footer { font-size: x-small; } body { font-size: smaller; } + .c2 { display:initial; } + .c2-alt { display:none; } + .c3 { display:none; } + .c3-alt { display:initial; } } @media all and (max-width: 350px) { footer { font-size: xx-small; } + .c2 { display:none; } + .c2-alt { display:initial; } } } diff --git a/web/ChangeLog b/web/ChangeLog index a30d8dcd..ed23ebe2 100644 --- a/web/ChangeLog +++ b/web/ChangeLog @@ -1,3 +1,110 @@ +2015-08-04 Paul Schneider + + * bg.gif: + * asc.gif: + * desc.gif: + * style.css: moved to App_Themes + + * style.css: + * bg.gif: + * asc.gif: + * bg.png: + * rect.png: + * asc.png: + * desc.gif: + * jquery-ui.css: + * mdd_styles.css: + * croix.png: + * desc.png: + * style.css: + * jquery-ui.min.css: + * mdd_gripper.png: + * mdd_toolbar.png: + * jquery.timepicker.css: + * mdd_ajax_loader.gif: + * mdd_modal_background.png: moved to /App_Themes + + * BlogsController.cs: access control simplified + + * FrontOfficeController.cs: Pdf generation made public ni case + of formatting exception + + * mdd_styles.css: Theme -> App_Themes + + * style.css: yet another style impact + + * AccountController.cs: Fixes the user name modification + + * BlogsController.cs: * Fixes the removal process + * On a title and user name, we get collection of posts, not + only one. + * Implements an Access on circle + + + * FrontOfficeController.cs: * implements a new Get method. + * ensure a membership existence before delivering an estimate. + + + * GoogleController.cs: Fixes the user name modification on a + Google account + + * ErrorHtmlFormatter.cs: nice error message in html (using + Markdown helper) + + * FormatterException.cs: formatter exception exposes error and + standard output of the process + + * TexToPdfFormatter.cs: * generates temporary files in the + folder returned by Path.GetTempPath() + * throws FormatterException + + * Global.asax.cs: new route map: + Blogs/{action}/{user}/{title} + Blog/{user}/{title} + B/{id} + {controller}/{action}/{id} + + + * App.master: * refactoring: Theme moved to App_Themes + * a link to the logged user's blog + * + + * NoLogin.master: refactoring: Theme moved to App_Themes + + * Circles.aspx: refactoring : circles now are given as select + items + + * Login.aspx: fixes the html presentation + + * Register.aspx: Fixes a Typo + + * Edit.aspx: + * Estimates.aspx: refactoring + + * Index.aspx: Implements a blog index, due to M&C changes with + this commit + + * RemovePost.aspx: links to the new route to the "RemovePost" + action, giving it a post id + + + * RemoveTitle.aspx: fixes a not yet linked page to remove a + post collection under a given title + + * EventPub.aspx: code refactoring + + * Writting.ascx: cleans the code + + * Web.config: fills the config with new names in the space + + * Web.config: configures the new NpgsqlUserNameProvider + + * Web.csproj: refactoring and others + + * UserPosts.aspx: adds a link to remove a post + + * UserPost.aspx: now uses the new BlogEntryCollection object + 2015-07-23 Paul Schneider * Web.config: Trace may be enabled, as long it is in local diff --git a/web/Controllers/AccountController.cs b/web/Controllers/AccountController.cs index 0dc36fd1..b183b9ac 100644 --- a/web/Controllers/AccountController.cs +++ b/web/Controllers/AccountController.cs @@ -219,15 +219,13 @@ namespace Yavsc.Controllers /// User name. [Authorize] [HttpGet] - public ActionResult Profile (string user) + public ActionResult Profile (string id) { - ViewData ["ProfileUserName"] = user; - string logdu = Membership.GetUser ().UserName; - ViewData ["UserName"] = logdu; - if (user == null) - user = logdu; - Profile model = new Profile (ProfileBase.Create (user)); - model.RememberMe = FormsAuthentication.GetAuthCookie (user, true) == null; + if (id == null) + id = Membership.GetUser ().UserName; + ViewData ["UserName"] = id; + Profile model = new Profile (ProfileBase.Create (id)); + model.RememberMe = FormsAuthentication.GetAuthCookie (id, true) == null; return View (model); } @@ -239,14 +237,14 @@ namespace Yavsc.Controllers /// Avatar file. [Authorize] [HttpPost] - public ActionResult Profile (string user, Profile model, HttpPostedFileBase AvatarFile) + public ActionResult Profile (string id, Profile model, HttpPostedFileBase AvatarFile) { // ASSERT("Membership.GetUser ().UserName is made of simple characters, no slash nor backslash" string logdu = Membership.GetUser ().UserName; - ViewData ["UserName"] = logdu; - bool editsMyProfile = (user == logdu); - if (!editsMyProfile) + ViewData ["UserName"] = id; + bool editsMyName = (id != model.Name); + if (!editsMyName) if (!Roles.IsUserInRole ("Admin")) if (!Roles.IsUserInRole ("FrontOffice")) throw new UnauthorizedAccessException ("Your are not authorized to modify this profile"); @@ -257,9 +255,9 @@ namespace Yavsc.Controllers // else invalidate the model if (AvatarFile.ContentType == "image/png") { string avdir = Server.MapPath (AvatarDir); - string avpath = Path.Combine (avdir, user + ".png"); + string avpath = Path.Combine (avdir, id + ".png"); AvatarFile.SaveAs (avpath); - model.avatar = Request.Url.Scheme + "://" + Request.Url.Authority + AvatarDir.Substring (1) + "/" + user + ".png"; + model.avatar = Request.Url.Scheme + "://" + Request.Url.Authority + AvatarDir.Substring (1) + "/" + id + ".png"; } else ModelState.AddModelError ("Avatar", string.Format ("Image type {0} is not supported (suported formats : {1})", @@ -270,7 +268,8 @@ namespace Yavsc.Controllers if (cAvat != null) if (model.avatar == null) model.avatar = cAvat; */ if (ModelState.IsValid) { - ProfileBase prf = ProfileBase .Create (model.UserName); + ProfileBase prf = ProfileBase .Create (id); + prf.SetPropertyValue ("Name", model.Name); prf.SetPropertyValue ("BlogVisible", model.BlogVisible); prf.SetPropertyValue ("BlogTitle", model.BlogTitle); if (AvatarFile != null) { @@ -295,10 +294,11 @@ namespace Yavsc.Controllers prf.SetPropertyValue ("gcalid", model.GoogleCalendar); prf.Save (); - // only do the following if this profile belongs to current user - if (editsMyProfile) - FormsAuthentication.SetAuthCookie (user, model.RememberMe); - ViewData ["Message"] = "Profile enregistré"+((editsMyProfile)?", cookie modifié.":""); + if (editsMyName) { + UserManager.ChangeName (id, model.Name); + FormsAuthentication.SetAuthCookie (model.Name, model.RememberMe); + } + ViewData ["Message"] = "Profile enregistré"+((editsMyName)?", nom public inclus.":""); } return View (model); } @@ -309,7 +309,10 @@ namespace Yavsc.Controllers public ActionResult Circles () { string user = Membership.GetUser ().UserName; - ViewData["Circles"] = CircleManager.DefaultProvider.List (user); + ViewData["Circles"] = CircleManager.DefaultProvider.List (user).Select (x => new SelectListItem { + Value = x.Value, + Text = x.Text + });; return View (); } /// diff --git a/web/Controllers/BlogsController.cs b/web/Controllers/BlogsController.cs index 5719a329..c04956dc 100644 --- a/web/Controllers/BlogsController.cs +++ b/web/Controllers/BlogsController.cs @@ -39,6 +39,7 @@ namespace Yavsc.Controllers get { return avatarDir; } set { avatarDir = value; } } + /// /// Initializes a new instance of the class. /// @@ -50,6 +51,7 @@ namespace Yavsc.Controllers defaultAvatar = defaultAvatarSpec [0]; defaultAvatarMimetype = defaultAvatarSpec [1]; } + /// /// Index the specified user, title, pageIndex and pageSize. /// @@ -57,14 +59,14 @@ namespace Yavsc.Controllers /// Title. /// Page index. /// Page size. - public ActionResult Index (string user = null, string title = null, int pageIndex=0, int pageSize=10) + public ActionResult Index (string user = null, string title = null, int pageIndex = 0, int pageSize = 10) { if (string.IsNullOrEmpty (user)) { return BlogList (pageIndex, pageSize); } else { MembershipUser u = null; - if (Membership.FindUsersByName (user) != null) - u= Membership.GetUser (user, false); + if (Membership.FindUsersByName (user) != null) + u = Membership.GetUser (user, false); if (u == null) { ModelState.AddModelError ("UserName", string.Format ("Utilisateur inconu : {0}", user)); @@ -72,12 +74,11 @@ namespace Yavsc.Controllers } else { if (string.IsNullOrEmpty (title)) return UserPosts (user, pageIndex, pageSize); - return UserPost (user, title); + return UserPost (user, title, pageIndex, pageSize); } - - } } + /// /// Blogs the list. /// @@ -88,11 +89,11 @@ namespace Yavsc.Controllers { ViewData ["SiteName"] = sitename; int totalRecords; - BlogEntryCollection bs = BlogManager.LastPosts (pageIndex, pageSize, out totalRecords); + var bs = BlogManager.LastPosts (pageIndex, pageSize, out totalRecords); ViewData ["RecordCount"] = totalRecords; - ViewData ["PageSize"] = pageSize; + ViewData ["pageSize"] = pageSize; ViewData ["PageIndex"] = pageIndex; - return View ("Index", bs); + return View ("Index", new BlogEntryCollection(bs) ); } /// @@ -111,6 +112,8 @@ namespace Yavsc.Controllers ViewData ["SiteName"] = sitename; ViewData ["BlogUser"] = user; string readersName = null; + ViewData ["PageIndex"] = pageIndex; + ViewData ["pageSize"] = pageSize; // displays invisible items when the logged user is also the author if (u != null) { if (u.UserName == user || Roles.IsUserInRole ("Admin")) @@ -118,106 +121,135 @@ namespace Yavsc.Controllers readersName = u.UserName; } // find entries - BlogEntryCollection c = BlogManager.FindPost (readersName, user, sf, pageIndex, pageSize, out tr); + BlogEntryCollection c = + BlogManager.FindPost (readersName, user, sf, pageIndex, pageSize, out tr); // Get author's meta data Profile bupr = new Profile (ProfileBase.Create (user)); ViewData ["BlogUserProfile"] = bupr; // Inform of listing meta data ViewData ["BlogTitle"] = bupr.BlogTitle; ViewData ["Avatar"] = bupr.avatar; - ViewData ["PageIndex"] = pageIndex; - ViewData ["PageSize"] = pageSize; ViewData ["RecordCount"] = tr; - return View ("UserPosts", c); - + UUBlogEntryCollection uuc = new UUBlogEntryCollection (user, c); + if (uuc.ConcernsAUniqueTitle) + if (uuc.Count>0) + return View ("UserPost", new UUTBlogEntryCollection(uuc.UserName, + uuc[0].Title,uuc)); + return View ("Index", uuc); } + /// /// Removes the comment. /// /// The comment. /// Cmtid. [Authorize] - public ActionResult RemoveComment(long cmtid) + public ActionResult RemoveComment (long cmtid) { long postid = BlogManager.RemoveComment (cmtid); - return UserPost (postid); + return GetPost (postid); } - private ActionResult UserPost (long id) + /// + /// Returns the post. + /// + /// The post. + /// Identifier. + public ActionResult GetPost (long id) { - ViewData ["PostId"] = id; - BlogEntry e = BlogManager.GetPost (id); - return UserPost (e); - } - - private ActionResult UserPost (BlogEntry e) - { - if (e == null) - return View ("TitleNotFound"); - Profile pr = new Profile (ProfileBase.Create (e.UserName)); - if (pr==null) + ViewData ["id"] = id; + BlogEntry e = BlogManager.GetForReading (id); + UUTBlogEntryCollection c = new UUTBlogEntryCollection (e.UserName,e.Title); + c.Add (e); + ViewData ["user"] = c.UserName; + ViewData ["title"] = c.Title; + Profile pr = new Profile (ProfileBase.Create (c.UserName)); + if (pr == null) + // the owner's profile must exist + // in order to publish its bills return View ("NotAuthorized"); ViewData ["BlogUserProfile"] = pr; - ViewData ["BlogTitle"] = pr.BlogTitle; ViewData ["Avatar"] = pr.avatar; - MembershipUser u = Membership.GetUser (); - if (u != null) - ViewData ["UserName"] = u.UserName; - if (!e.Visible || !pr.BlogVisible) { - // only deliver to admins or owner - if (u == null) + ViewData ["BlogTitle"] = pr.BlogTitle; + return View (c); + } + + /// + /// Users the post. + /// Assume that : + /// * bec.Count > O + /// * bec.All(x=>x.UserName == bec[0].UserName) ; + /// + /// The post. + /// Bec. + private ActionResult UserPosts (UUTBlogEntryCollection bec) + { + if (ModelState.IsValid) + if (bec.Count > 0) { + Profile pr = new Profile (ProfileBase.Create (bec.UserName)); + if (pr == null) + // the owner's profile must exist + // in order to publish its bills return View ("NotAuthorized"); - else { - if (u.UserName != e.UserName) - if (!Roles.IsUserInRole (u.UserName, "Admin")) + ViewData ["BlogUserProfile"] = pr; + ViewData ["Avatar"] = pr.avatar; + ViewData ["BlogTitle"] = pr.BlogTitle; + MembershipUser u = Membership.GetUser (); + if (u != null) + ViewData ["UserName"] = u.UserName; + if (!pr.BlogVisible) { + // only deliver to admins or owner + if (u == null) return View ("NotAuthorized"); + else { + if (u.UserName != bec.UserName) + if (!Roles.IsUserInRole (u.UserName, "Admin")) + return View ("NotAuthorized"); + } } - } else { - if (!CanViewPost(e,u)) - return View ("NotAuthorized"); } - ViewData ["Comments"] = BlogManager.GetComments (e.Id); - return View ("UserPost", e); - } - private bool CanViewPost (BlogEntry e, MembershipUser u=null) { - if (e.AllowedCircles!=null && e.AllowedCircles.Length > 0) { - // only deliver to admins, owner, or specified circle memebers - if (u == null) - return false; - if (u.UserName != e.UserName) - if (!Roles.IsUserInRole (u.UserName, "Admin")) - if (!CircleManager.DefaultProvider.Matches (e.AllowedCircles, u.UserName)) - return false; - } - return true; + return View (BlogManager.FilterOnReadAccess(bec as UUTBlogEntryCollection)); } + /// /// Users the post. /// /// The post. /// User. /// Title. - public ActionResult UserPost (string user, string title) + /// Page index. + /// Page size. + public ActionResult UserPost (string user, string title, int pageIndex = 0, int pageSize = 10) { - ViewData ["BlogUser"] = user; - ViewData ["PostTitle"] = title; - int postid = 0; - if (string.IsNullOrEmpty (title)) { - if (int.TryParse (user, out postid)) { - return UserPost (BlogManager.GetPost (postid)); - } - } - return UserPost (BlogManager.GetPost (user, title)); + ViewData ["user"] = user; + ViewData ["title"] = title; + ViewData ["PageIndex"] = pageIndex; + ViewData ["pageSize"] = pageSize; + var pb = ProfileBase.Create (user); + if (pb == null) + // the owner's profile must exist + // in order to publish its bills + return View ("NotAuthorized"); + Profile pr = new Profile (pb); + ViewData ["BlogUserProfile"] = pr; + ViewData ["Avatar"] = pr.avatar; + ViewData ["BlogTitle"] = pr.BlogTitle; + UUTBlogEntryCollection c = new UUTBlogEntryCollection (user, title); + c.AddRange ( BlogManager.FilterOnReadAccess (BlogManager.GetPost (user, title))); + return View ("UserPost",c); } + /// /// Post the specified user and title. /// /// User. /// Title. [Authorize, - ValidateInput(false)] + ValidateInput (false)] public ActionResult Post (string user, string title) { + ViewData ["BlogUser"] = user; + ViewData ["PostTitle"] = title; ViewData ["SiteName"] = sitename; string un = Membership.GetUser ().UserName; if (String.IsNullOrEmpty (user)) @@ -225,7 +257,7 @@ namespace Yavsc.Controllers if (String.IsNullOrEmpty (title)) title = ""; ViewData ["UserName"] = un; - ViewData["AllowedCircles"] = CircleManager.DefaultProvider.List (Membership.GetUser ().UserName).Select (x => new SelectListItem { + ViewData ["AllowedCircles"] = CircleManager.DefaultProvider.List (Membership.GetUser ().UserName).Select (x => new SelectListItem { Value = x.Value, Text = x.Text }); @@ -239,57 +271,45 @@ namespace Yavsc.Controllers /// The edit. /// Model. [Authorize, - ValidateInput(false)] + ValidateInput (false)] public ActionResult ValidateEdit (BlogEntry model) { ViewData ["SiteName"] = sitename; ViewData ["BlogUser"] = Membership.GetUser ().UserName; if (ModelState.IsValid) { - if (model.Id != 0) - BlogManager.UpdatePost (model.Id, model.Title, model.Content, model.Visible, model.AllowedCircles); - else + if (model.Id != 0) + BlogManager.UpdatePost (model.Id, model.Title, model.Content, model.Visible, model.AllowedCircles); + else model.Id = BlogManager.Post (model.UserName, model.Title, model.Content, model.Visible, model.AllowedCircles); - return RedirectToAction ("UserPost",new { user = model.UserName, title = model.Title }); + return RedirectToAction ("UserPosts", new { user = model.UserName, title = model.Title }); } return View ("Edit", model); } /// - /// Edit the specified model. + /// Edit the specified bill /// - /// Model. - [Authorize, - ValidateInput(false)] - public ActionResult Edit (BlogEntry model) + /// Identifier. + [Authorize, ValidateInput (false)] + public ActionResult Edit (long id) { - string user = Membership.GetUser ().UserName; - Profile pr = new Profile (HttpContext.Profile); - - ViewData ["BlogTitle"] = pr.BlogTitle; - ViewData ["UserName"] = user; - if (model.UserName == null) { - model.UserName = user; - } - BlogEntry e = BlogManager.GetPost (model.UserName, model.Title); - if (e != null) { - if (e.UserName != user) { - return View ("NotAuthorized"); - } - model = e; - ModelState.Clear (); - TryValidateModel (model); - } - - if (model.AllowedCircles==null) - model.AllowedCircles = new long[0]; - ViewData["AllowedCircles"] = CircleManager.DefaultProvider.List (Membership.GetUser ().UserName).Select (x => new SelectListItem { + BlogEntry e = BlogManager.GetForEditing (id); + string user = Membership.GetUser ().UserName; + Profile pr = new Profile (ProfileBase.Create(e.UserName)); + ViewData ["BlogTitle"] = pr.BlogTitle; + ViewData ["LOGIN"] = user; + // Populates the circles combo items + + if (e.AllowedCircles == null) + e.AllowedCircles = new long[0]; + + ViewData ["AllowedCircles"] = CircleManager.DefaultProvider.List (Membership.GetUser ().UserName).Select (x => new SelectListItem { Value = x.Value, Text = x.Text, - Selected = model.AllowedCircles.Contains(long.Parse(x.Value)) + Selected = e.AllowedCircles.Contains (long.Parse (x.Value)) }); - - return View (model); + return View (e); } /// @@ -297,17 +317,19 @@ namespace Yavsc.Controllers /// /// Model. [Authorize] - public ActionResult Comment (Comment model) { + public ActionResult Comment (Comment model) + { string username = Membership.GetUser ().UserName; ViewData ["SiteName"] = sitename; if (ModelState.IsValid) { - BlogManager.Comment(username, model.PostId, model.CommentText, model.Visible); - return UserPost (model.PostId); + BlogManager.Comment (username, model.PostId, model.CommentText, model.Visible); + return GetPost (model.PostId); } - return UserPost (model.PostId); + return GetPost (model.PostId); } string defaultAvatar; + /// /// Avatar the specified user. /// @@ -316,20 +338,20 @@ namespace Yavsc.Controllers public ActionResult Avatar (string user) { ProfileBase pr = ProfileBase.Create (user); - string avpath = (string) pr.GetPropertyValue ("avatar"); - if (avpath==null) { + string avpath = (string)pr.GetPropertyValue ("avatar"); + if (avpath == null) { FileInfo fia = new FileInfo (Server.MapPath (defaultAvatar)); return File (fia.OpenRead (), defaultAvatarMimetype); } if (avpath.StartsWith ("~/")) { } - WebRequest wr = WebRequest.Create(avpath); + WebRequest wr = WebRequest.Create (avpath); FileContentResult res; using (WebResponse resp = wr.GetResponse ()) { using (Stream str = resp.GetResponseStream ()) { - byte [] content = new byte[str.Length]; - str.Read (content, 0, (int) str.Length); + byte[] content = new byte[str.Length]; + str.Read (content, 0, (int)str.Length); res = File (content, resp.ContentType); wr.Abort (); return res; @@ -347,26 +369,46 @@ namespace Yavsc.Controllers /// Return URL. /// If set to true confirm. [Authorize] - public ActionResult RemovePost (string user, string title, string returnUrl, bool confirm=false) + public ActionResult RemoveTitle (string user, string title, string returnUrl, bool confirm = false) { if (returnUrl == null) - if (Request.UrlReferrer!=null) + if (Request.UrlReferrer != null) returnUrl = Request.UrlReferrer.AbsoluteUri; - ViewData["returnUrl"]=returnUrl; + ViewData ["returnUrl"] = returnUrl; + ViewData ["UserName"] = user; + ViewData ["Title"] = title; + BlogManager.CheckAuthCanEdit (user, title); if (!confirm) - return View ("RemovePost"); - BlogManager.RemovePost (user,title); + return View ("RemoveTitle"); + BlogManager.RemoveTitle (user, title); if (returnUrl == null) - RedirectToAction ("Index",new { user = user }); + RedirectToAction ("Index", new { user = user }); return Redirect (returnUrl); } - private ActionResult Return (string returnUrl) + /// + /// Removes the post. + /// + /// The post. + /// Identifier. + /// Return URL. + /// If set to true confirm. + [Authorize] + public ActionResult RemovePost (long id, string returnUrl, bool confirm = false) { - if (!string.IsNullOrEmpty (returnUrl)) - return Redirect (returnUrl); - else + BlogEntry e = BlogManager.GetForEditing (id); + if (e == null) + return new HttpNotFoundResult ("post id "+id.ToString()); + ViewData ["id"] = id; + ViewData ["returnUrl"] = string.IsNullOrWhiteSpace(returnUrl)? + Request.UrlReferrer.AbsoluteUri.ToString(): returnUrl; + // TODO: cleaner way to disallow deletion + if (!confirm) + return View ("RemovePost",e); + BlogManager.RemovePost (id); + if (string.IsNullOrWhiteSpace(returnUrl)) return RedirectToAction ("Index"); + return Redirect (returnUrl); } } } diff --git a/web/Controllers/FrontOfficeController.cs b/web/Controllers/FrontOfficeController.cs index f2330a10..3711e7ff 100644 --- a/web/Controllers/FrontOfficeController.cs +++ b/web/Controllers/FrontOfficeController.cs @@ -13,6 +13,7 @@ using System.Threading; using Yavsc.Model.FrontOffice; using Yavsc.Model.FileSystem; using Yavsc.Model.Calendar; +using System.Configuration; namespace Yavsc.Controllers { @@ -59,7 +60,11 @@ namespace Yavsc.Controllers [Authorize] public ActionResult Estimates (string client) { - string username = Membership.GetUser ().UserName; + var u = Membership.GetUser (); + if (u == null) // There was no redirection to any login page + throw new ConfigurationErrorsException ("no redirection to any login page"); + + string username = u.UserName; Estimate [] estims = wfmgr.GetUserEstimates (username); ViewData ["UserName"] = username; ViewData ["ResponsibleCount"] = @@ -73,6 +78,21 @@ namespace Yavsc.Controllers return View (estims); } + + /// + /// Estimate the specified id. + /// + /// Identifier. + public ActionResult Get (long id) + { + Estimate f = wfmgr.GetEstimate (id); + if (f == null) { + ModelState.AddModelError ("Id", "Wrong Id"); + return View (new Estimate () { Id=id } ); + } + return View (f); + } + /// /// Estimate the specified model and submit. /// diff --git a/web/Controllers/GoogleController.cs b/web/Controllers/GoogleController.cs index 9862bbb0..ef84deb5 100644 --- a/web/Controllers/GoogleController.cs +++ b/web/Controllers/GoogleController.cs @@ -150,9 +150,11 @@ namespace Yavsc.Controllers if (mbrs.Count == 1) { // TODO check the google id // just set this user as logged on - FormsAuthentication.SetAuthCookie (me.displayName, true); + foreach (MembershipUser u in mbrs) { + string username = u.UserName; + FormsAuthentication.SetAuthCookie (username, true); + } Session ["returnUrl"] = null; - return Redirect (returnUrl); } // else create the account diff --git a/web/Formatters/ErrorHtmlFormatter.cs b/web/Formatters/ErrorHtmlFormatter.cs index 8ae1441d..8f823547 100644 --- a/web/Formatters/ErrorHtmlFormatter.cs +++ b/web/Formatters/ErrorHtmlFormatter.cs @@ -27,6 +27,8 @@ using System.IO; using System.Net.Http; using System.Web.Mvc; using System.Net; +using MarkdownDeep; +using Yavsc.Helpers; namespace Yavsc.Formatters { @@ -84,7 +86,7 @@ namespace Yavsc.Formatters "href=\"/Theme/style.css\" />" + ""; - p.InnerHtml = MvcHtmlString.Create (message).ToHtmlString(); + p.InnerHtml = MarkdownHelper.Markdown(message).ToHtmlString(); h1.InnerHtml = MvcHtmlString.Create (Title).ToHtmlString(); body.InnerHtml = h1.ToString()+p.ToString (); doc.InnerHtml = head.ToString()+"\n"+body.ToString (); diff --git a/web/Formatters/FormatterException.cs b/web/Formatters/FormatterException.cs index 5f827d00..08725d8e 100644 --- a/web/Formatters/FormatterException.cs +++ b/web/Formatters/FormatterException.cs @@ -50,5 +50,8 @@ namespace Yavsc.Formatters public FormatterException(string message,Exception innerException):base(message,innerException) { } + + public string Output { get; set; } + public string Error { get; set; } } } diff --git a/web/Formatters/TexToPdfFormatter.cs b/web/Formatters/TexToPdfFormatter.cs index 7125c8dc..fe5c6ad4 100644 --- a/web/Formatters/TexToPdfFormatter.cs +++ b/web/Formatters/TexToPdfFormatter.cs @@ -77,38 +77,46 @@ namespace Yavsc.Formatters /// Content headers. public override void WriteToStream (Type type, object value, Stream stream, HttpContentHeaders contentHeaders) { - + string temp = Path.GetTempPath (); string cntStr = value as string; string name = "tmpdoc-"+Guid.NewGuid().ToString(); - string fullname = Path.Combine ( - HttpRuntime.CodegenDir, name); + string fullname = Path.Combine (temp, name); FileInfo fi = new FileInfo(fullname + ".tex"); - FileInfo fo = new FileInfo(fullname + ".pdf"); - using (StreamWriter sw = new StreamWriter (fi.FullName)) + FileInfo fo = null; + using (StreamWriter sw = new StreamWriter (fi.OpenWrite())) { sw.Write (cntStr); - } - using (Process p = new Process ()) { - p.StartInfo.WorkingDirectory = HttpRuntime.CodegenDir; - p.StartInfo = new ProcessStartInfo (); - p.StartInfo.UseShellExecute = false; - p.StartInfo.FileName = "/usr/bin/texi2pdf"; - p.StartInfo.Arguments = - string.Format ("--batch --build-dir={2} -o {0} {1}", - fo.FullName, - fi.FullName,HttpRuntime.CodegenDir); - p.Start (); - p.WaitForExit (); - if (p.ExitCode != 0) - throw new FormatterException ("Pdf generation failed with exit code:" + p.ExitCode); + sw.Close (); } - using (StreamReader sr = new StreamReader (fo.FullName)) { - byte[] buffer = File.ReadAllBytes (fo.FullName); - stream.Write(buffer,0,buffer.Length); + using (Process p = new Process ()) { + + Directory.SetCurrentDirectory (temp); + + p.StartInfo.WorkingDirectory = temp; + p.StartInfo = new ProcessStartInfo (); + p.StartInfo.UseShellExecute = false; + p.StartInfo.FileName = "texi2pdf"; + p.StartInfo.Arguments = + string.Format ("--batch {0}", + fi.FullName); + p.StartInfo.RedirectStandardOutput = true; + p.StartInfo.RedirectStandardError = true; + + p.Start (); + p.WaitForExit (); + + if (p.ExitCode != 0) { + var ex = new FormatterException ("Pdf generation failed with exit code:" + p.ExitCode); + ex.Output = p.StandardOutput.ReadToEnd ()+"\nCWD:"+temp; + ex.Error = p.StandardError.ReadToEnd (); + throw ex; + } + fo = new FileInfo(name + ".pdf"); } - fi.Delete(); - fo.Delete(); + + byte[] buffer = File.ReadAllBytes (fo.Name); + stream.Write(buffer,0,buffer.Length); if (contentHeaders != null) SetFileName(contentHeaders, value.GetHashCode ().ToString ()); } diff --git a/web/Global.asax.cs b/web/Global.asax.cs index 892fcf71..579820de 100644 --- a/web/Global.asax.cs +++ b/web/Global.asax.cs @@ -45,28 +45,28 @@ namespace Yavsc routes.IgnoreRoute ("favicon.ico"); routes.IgnoreRoute ("favicon.png"); routes.IgnoreRoute ("robots.txt"); - routes.MapRoute ( - "Blog", - "Blog/{user}/{title}", - new { controller = "Blogs", action = "Index", user=UrlParameter.Optional, title = UrlParameter.Optional } - ); routes.MapRoute ( "Blogs", "Blogs/{action}/{user}/{title}", new { controller = "Blogs", action = "Index", user=UrlParameter.Optional, title = UrlParameter.Optional } ); - /*routes.MapRoute ( - "Account", - "Account/{action}/{user}", - new { controller = "Account", action = "Index", user=UrlParameter.Optional } - ); */ + routes.MapRoute ( + "BlogByTitleRO", + "Blog/{user}/{title}", + new { controller = "Blogs", action = "Index", user=UrlParameter.Optional, title = UrlParameter.Optional } + ); + routes.MapRoute ( + "BlogById", + "B/{action}/{id}", + new { controller = "Blogs", action = "UserPost", id = UrlParameter.Optional } + ); routes.MapRoute ( "Default", - "{controller}/{action}/{user}/{title}", + "{controller}/{action}/{id}", new { controller = defaultController, action = "Index", user=UrlParameter.Optional, - title = UrlParameter.Optional } + id = UrlParameter.Optional } ); } diff --git a/web/Models/App.master b/web/Models/App.master index 23401285..b8fa120d 100644 --- a/web/Models/App.master +++ b/web/Models/App.master @@ -1,4 +1,4 @@ -<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %> +<%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %> @@ -9,9 +9,9 @@ ViewState["orgtitle"] = T.GetString(Page.Title); - + - + @@ -19,9 +19,10 @@ ViewState["orgtitle"] = T.GetString(Page.Title);
-

<%=ViewState["orgtitle"]%> - +

<%=ViewState["orgtitle"]%> + - "><%= YavscHelpers.SiteName %> -

+
<% if (ViewData["Error"]!=null) { %>
<%= Html.Encode(ViewData["Error"]) %> @@ -36,28 +37,21 @@ ViewState["orgtitle"] = T.GetString(Page.Title); - +
<%= Html.ActionLink("Authentification", "Login", "Account", new { returnUrl=Request.Url.PathAndQuery },null) %> + Pourquoi s'authentifier?

+<% } else { %> + <%= Html.ActionLink(HttpContext.Current.User.Identity.Name, "Profile", "Account", new { id = HttpContext.Current.User.Identity.Name }, null) %> + Édition de votre profile
+ Poster + Édition d'un nouveau billet
+ <%= Html.ActionLink( "Deconnexion", "Logout", "Account", new { returnUrl=Request.Url.PathAndQuery }, null) %> +<% } %>