Compare commits

...

410 Commits

Author SHA1 Message Date
perploug fce31a2e02 7.1 beta 2014-03-07 15:26:28 +01:00
perploug b816e7f4db Fixes: sites cannot run the new installer if they have /install directory 2014-03-07 12:10:04 +01:00
perploug 45f6d4f911 ensures the installer clears angular cache 2014-03-07 12:10:00 +01:00
Shannon 6a9a1d1547 Merge branch '7.1.0' of https://github.com/umbraco/Umbraco-CMS into 7.1.0 2014-03-07 20:26:57 +11:00
perploug 391eb99e10 Installer facts typo 2014-03-07 10:18:36 +01:00
perploug 3b4487c836 Fixes: Weird merge issue with dashboard.config 2014-03-07 10:18:30 +01:00
perploug 46461c7c5d Fixes installer breaks with missing app_data/temp/installer folder 2014-03-07 10:18:08 +01:00
perploug 7104629ffd Fixes installer database dropdown default value 2014-03-07 10:17:46 +01:00
Shannon b46abecde5 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/EditProfile.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesOrderedByDate.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesOrderedByName.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesOrderedByProperty.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/ListChildPagesWithDoctype.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Login.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/LoginStatus.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Navigation.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/RegisterMember.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/SiteMap.cshtml
	src/Umbraco.Web.UI/umbraco/scripting/templates/cshtml/Navigation.cshtml
	src/Umbraco.Web.UI/umbraco/scripting/templates/cshtml/SiteMap.cshtml
2014-03-07 20:10:33 +11:00
Shannon e82795f798 Merge branch '7.1.0' of https://github.com/umbraco/Umbraco-CMS into 7.1.0 2014-03-07 20:09:32 +11:00
Shannon a6faf5b757 fixes build issue 2014-03-07 20:09:22 +11:00
Shannon 3e6e6faf03 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-03-07 20:08:22 +11:00
Shannon b3f18bc677 fixed an issue with setting password with legacy api 2014-03-07 20:08:10 +11:00
Sebastiaan Janssen a48fe40675 Also clean up v6 snippets 2014-03-07 09:46:45 +01:00
Shannon 74c777b1ae Ensures the built-in member controllers have the correct logic - somehow got reverted and then not merged. 2014-03-07 19:39:31 +11:00
perploug 1e955fa813 Tweaks startkits usercontrol style 2014-03-07 09:34:25 +01:00
Shannon bc371e69a3 Completes: U4-4227 Rename default member property aliases 2014-03-07 19:30:54 +11:00
Shannon 9a97b636eb Merge branch '7.1.0' of https://github.com/umbraco/Umbraco-CMS into 7.1.0 2014-03-07 19:15:38 +11:00
Shannon 878156e21e putting back what the UmbLoginController should be ... where in the hell has this been overwritten from??! 2014-03-07 19:13:25 +11:00
Sebastiaan Janssen af376d2837 Fix failing nuget build (now that \install is removed) 2014-03-07 09:06:06 +01:00
Shannon 9dd5f250c7 Fixes up the GetUrlWithTimeStamp to be called GetUrlWithCacheBust and another extension method to actually generate the hash which will be umb version + cdf version hashed or datetime.ticks if in debug mode. Updates the main view to use CDF to render the CSS which ensures compression/minification/combination + cache busting. 2014-03-07 11:03:13 +11:00
Shannon bb527996b9 Moves the JsNoCache to a real readable file instead of an embedded string (now an embedded file resource), updates it's logic to not append the hash to any dependencyhandler.axd request, fixes case sensitivity checking on the URLs, changes the cdf + umb version to be a nice shorter hash of the two. 2014-03-07 10:40:27 +11:00
Shannon 1a171161cd Merge remote-tracking branch 'origin/6.2.0' into 7.1.0 2014-03-07 10:11:36 +11:00
perploug d410663a68 Updates ImageProcessor 2014-03-06 22:54:51 +01:00
perploug 9e332ca0a4 Fixes: media unit test merge issue 2014-03-06 22:54:23 +01:00
perploug 02388a33ba Tweaks fileupload view 2014-03-06 22:54:05 +01:00
perploug 3f52364308 Fixes: FixNumber directive always dirtied the model 2014-03-06 22:53:51 +01:00
perploug e157837e0e Fixes merge issue in valformmanager 2014-03-06 22:53:13 +01:00
perploug c2318349e5 merge 2014-03-06 20:11:37 +01:00
perploug c540c74a04 merge 2014-03-06 20:10:17 +01:00
perploug e5b1271ce1 Fixes: U4-4205 Add item to multi node tree picker - Min/Max Items Issue 2014-03-06 14:38:03 +01:00
perploug dfaa15c6e7 Directive cleanup + button event js errors fix 2014-03-06 12:28:36 +01:00
perploug 4aa3e1368a Fixes scrollbar and database val msg 2014-03-06 12:27:46 +01:00
Shannon 25f10011fc Fixes merge issues 2014-03-06 20:38:23 +11:00
perploug d08f08ffaf Umbraco facts 2014-03-06 10:30:41 +01:00
Shannon 9a9237e78e Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs
	src/Umbraco.Core/Services/IMembershipUserService.cs
	src/Umbraco.Tests/PublishedContent/PublishedContentTestElements.cs
	src/Umbraco.Web.UI/config/trees.config
	src/Umbraco.Web.UI/config/umbracoSettings.config
	src/Umbraco.Web.UI/umbraco/controls/ContentTypeControlNew.ascx
	src/Umbraco.Web.UI/umbraco/developer/DataTypes/editDatatype.aspx
	src/Umbraco.Web.UI/umbraco/plugins/uGoLive/Dashboard.ascx
	src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs
	src/Umbraco.Web/Search/ExamineEvents.cs
	src/Umbraco.Web/Umbraco.Web.csproj
	src/Umbraco.Web/umbraco.presentation/content.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/cache/LegacyClasses.cs
2014-03-06 20:22:32 +11:00
Shannon 1511ad58b2 oops, put back the defaults for umbracoSettings 2014-03-06 20:16:55 +11:00
Shannon 2e9b751174 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-03-06 20:12:21 +11:00
Shannon d61ab97be3 Fixes: U4-4217 Ensure that the cmsTask data is cleared for any entity that uses umbracoNode table 2014-03-06 20:12:05 +11:00
Stephan dd40d73b71 Merge remote-tracking branch 'origin/6.2.0' into 6.2.0 2014-03-06 10:06:50 +01:00
Shannon 068bca84b7 Fixes: U4-156 Drag / drop support 2014-03-06 20:05:13 +11:00
Shannon 0fda528b94 Fixes: U4-1550 Publish notifications on a load balanced environment 2014-03-06 19:47:23 +11:00
Shannon 3552f63d87 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-03-06 19:29:35 +11:00
Shannon 01d04fde37 Fixes: U4-4060 Rollback feature does not show differences 2014-03-06 19:29:09 +11:00
Stephan 7f8c526136 Fix TryConvertTo handling of number decimal separator 2014-03-06 09:14:05 +01:00
Stephan ea4be14f0c Fix 026d040 - keep Standalone stuff internal 2014-03-06 09:10:14 +01:00
Stephan 20df48e2f0 Merge remote-tracking branch 'origin/6.2.0' into 6.2.0 2014-03-06 08:49:38 +01:00
Stephan 2c0f6f975c Bugfix UmbracoEntity ctor test 2014-03-06 08:42:41 +01:00
Shannon fa7f91b39d Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-03-06 18:26:10 +11:00
Shannon 72c5853fb1 Completes: U4-3937 Ensure media is indexed across all servers in LB environment with Distributed Cache calls
for members
2014-03-06 18:25:38 +11:00
Stephan f03b1a22f9 Merge remote-tracking branch 'origin/6.2.0' into 6.2.0 2014-03-06 08:12:51 +01:00
Shannon e7fb6e5beb Streamlines member and user services CreateMemberWithIdentity to be similar to media/content and not have a raise events flag. Also implements the CreateWithIdentity explicitly 2014-03-06 18:07:02 +11:00
Shannon d0cc93d6a2 Fixes: U4-3937 Ensure media is indexed across all servers in LB environment with Distributed Cache calls
This fix is for media indexes to be distributed properly and for unpublished content to be distributed properly, now to get members to do the same.
2014-03-06 17:50:08 +11:00
Shannon 4adc2562b1 Fixes issue with ugolive dashboard trying to load in knockout from a bundle which causes the examine mgr to fail 2014-03-06 17:49:09 +11:00
Shannon ba6878666c Fixes pretty ugly issue of the Saving/Saved events not being raised when using CreateWithIdentity 2014-03-06 17:35:47 +11:00
Shannon 30da7fb801 Merge branch '7.1.0-installer' into 7.1.0
Conflicts:
	src/Umbraco.Web.UI.Client/src/common/mocks/resources/entity.mocks.js
	src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js
	src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js
	src/Umbraco.Web.UI.Client/test/unit/app/media/edit-media-controller.spec.js
2014-03-06 12:28:50 +11:00
Shannon 7086a5153a Fixes js errors with apply since a digest is already in operation. 2014-03-06 12:25:45 +11:00
Shannon 37937e2c8e Fixes the user password validation to ensure it obeys what the membership provider's are configured for. 2014-03-06 12:11:14 +11:00
Shannon 7676099f2e small styling fix on db err msg 2014-03-06 11:14:41 +11:00
perploug 0d1bb355b5 merge 2014-03-05 20:12:45 +01:00
perploug 3276b8a4d8 Latest visual changes to installer + db validator 2014-03-05 20:03:45 +01:00
Stephan 792ab8d088 Introduce support for content fragments 2014-03-05 15:46:37 +01:00
Stephan 3d4409e52a Refactor CacheRefreshersResolver.CacheResolvers into .CacheRefreshers 2014-03-05 15:46:35 +01:00
Stephan acd377956f Improve how DomainHelper determines domain 2014-03-05 15:46:34 +01:00
Stephan 3b6dcc3421 Factor Dictionary.ReplaceKey method 2014-03-05 15:46:33 +01:00
Stephan cec4d41df7 Add comments to UmbracoViewPageOfTModel 2014-03-05 15:46:32 +01:00
Stephan ff0bcffefa Implement DefaultShortStringHelper.PostFilter to cut url segments at 240 chars 2014-03-05 15:46:31 +01:00
Stephan 5dbc72897a Add method to reset PublishedContentRequest template 2014-03-05 15:46:30 +01:00
Stephan 83736bec01 U4-4190 - enable retrieval of wildcard domains 2014-03-05 15:46:29 +01:00
Stephan 2f953c3819 Fix a38e0dc - use UInt64 instead of int 2014-03-05 15:46:28 +01:00
Stephan 026d040a62 Enable StandaloneApplication to work with Powershell 2014-03-05 15:39:16 +01:00
Stephan 7747b8f64f U4-3579 - support chars such as <, > or & in prevalues 2014-03-05 15:33:15 +01:00
Shannon feab2de260 Fixes up the starter kit installer in the back office with it's legacy implementation. Adds some handy methods for webapi routing for areas. 2014-03-05 22:42:51 +11:00
Shannon 24cc417395 Removed all the legacy files that we don't need - need to test the starter kit installation process in the back office though as some old files are still used there. 2014-03-05 19:47:00 +11:00
Shannon 56e1fc07e4 adds some notes on testing db connectivity. 2014-03-05 19:42:24 +11:00
Shannon fbd2b3a1e1 Gets the v7 upgrade report working on the new installer. 2014-03-05 18:23:50 +11:00
Shannon 8f7f761bb3 implements the file permissions report correctly and tests it. 2014-03-05 17:44:13 +11:00
Shannon a40ba2f27e Updates the RequiresExecution logic so we can skip steps based on some user input (i.e. skip the starter kit installation). Fixes the start kit js stuff to update the model correctly and continue. Fixes the error view to restart - it cannot just go back because there might not be a view there. 2014-03-05 14:30:17 +11:00
Shannon 893f86d34c Fixes installer service so that when forward is called and there are no more views to show the installer will automatically start. This will occur in cases where we are customizing the install but we don't want a starter kit installed since the server has detected that one has already been installed. This also prevents some JS errors and will improve the installer in the future if there might be more views. 2014-03-05 12:57:44 +11:00
Shannon ddd2ab463e Ensures that the starter kit view is not returned if there is one already installed 2014-03-05 12:44:38 +11:00
Shannon cbced2caed fixes db upgrade step to check for correct previous step 2014-03-05 12:21:49 +11:00
Shannon ce068a60d5 Removes default instructions from the installer service, passing in empty instructions is ok now and the server will assign defaults if they are empty. 2014-03-05 12:08:35 +11:00
Shannon 7f7f3202d2 fixes issue with checking starter kit steps, fixes issue with installer service code with the method param name being the same as the variable name and fixes the _find lookups to ensure a value is returned from the iteration. 2014-03-05 11:49:07 +11:00
Shannon 0227b800a0 Gets the installer steps working nicely and returning the next step to execute which now displays the current step details correctly and dequeues steps that are not required after the previous one has executed. 2014-03-05 11:34:42 +11:00
Shannon 8e89aa233c Merge branch '7.1.0-installer' of https://github.com/umbraco/Umbraco-CMS into 7.1.0-installer
Conflicts:
	src/Umbraco.Web.UI.Client/src/installer/installer.service.js
	src/Umbraco.Web/Install/Controllers/InstallApiController.cs
2014-03-05 10:34:27 +11:00
Shannon 24ceb5ce2d Updates to include returning the next step in sequence 2014-03-05 10:32:59 +11:00
perploug 923eb300e5 Updates grunt file to run vs file copy 2014-03-04 19:11:27 +01:00
Shannon 0d93db5f1f Fixes the order that descriptions are listed during install 2014-03-04 19:28:57 +11:00
Shannon d2aecd12eb Updates more installer logic, getting into the nitty gritty details with upgrades, etc... 2014-03-04 19:20:36 +11:00
Shannon 1e99c466ee Updates some tests and fixes a couple things 2014-03-04 16:40:23 +11:00
Shannon 71a9fb4f68 Updated more installer logic 2014-03-04 16:21:45 +11:00
Shannon 0497771750 fixed merge issues 2014-03-04 11:42:11 +11:00
Shannon 000b2b639f Merge branch '7.1.0-installer' of https://github.com/umbraco/Umbraco-CMS into 7.1.0-installer
Conflicts:
	src/Umbraco.Web/Install/Controllers/InstallApiController.cs
	src/Umbraco.Web/Install/InstallSteps/DatabaseConfigureStep.cs
	src/Umbraco.Web/Install/InstallSteps/DatabaseInstallStep.cs
	src/Umbraco.Web/Install/InstallSteps/DatabaseUpgradeStep.cs
	src/Umbraco.Web/Install/InstallSteps/FilePermissionsStep.cs
	src/Umbraco.Web/Install/InstallSteps/SetUmbracoVersionStep.cs
	src/Umbraco.Web/Install/InstallSteps/StarterKitCleanupStep.cs
	src/Umbraco.Web/Install/InstallSteps/StarterKitDownloadStep.cs
	src/Umbraco.Web/Install/InstallSteps/StarterKitInstallStep.cs
	src/Umbraco.Web/Install/InstallSteps/UserStep.cs
	src/Umbraco.Web/Install/Models/InstallSetupStep.cs
	src/Umbraco.Web/Install/Models/InstallSetupStepAttribute.cs
2014-03-04 11:20:52 +11:00
Shannon 885f691c0e Updated install steps, classes and logic 2014-03-04 11:16:42 +11:00
perploug 92f6b5564d Fixes failing js unit tests 2014-03-03 13:21:30 +01:00
perploug ce65ae8742 Updates to the installer UI
Adds database and packages step
2014-03-03 08:57:57 +01:00
Shannon 57c9d9ca7b Merge remote-tracking branch 'origin/6.2.0' into 7.1.0-installer
Conflicts:
	src/Umbraco.Tests/MockTests.cs
	src/Umbraco.Web/UmbracoContext.cs
2014-03-03 04:17:40 +01:00
Shannon feb9f40237 updates some ctors on umbraco context and routing context to have lazy overloads which allows us to more easily create/mock the umbraco context. 2014-03-03 04:16:09 +01:00
Shannon 3fc96a45a6 Merge branch '7.1.0-installer' of https://github.com/umbraco/Umbraco-CMS into 7.1.0-installer 2014-02-27 10:16:45 +01:00
Shannon 3b71a6c3a5 asfsafd 2014-02-27 10:16:30 +01:00
perploug 9c4212703b umbraco base url 2014-02-27 10:00:38 +01:00
Sebastiaan Janssen a20c11d438 Merge branch '7.1.0' of https://github.com/umbraco/Umbraco-CMS into 7.1.0 2014-02-26 22:52:38 +01:00
Sebastiaan Janssen 89b8d056a2 Fixes #U4-4310 Missing Curly Brace in Boolean Property Editor 2014-02-26 22:52:13 +01:00
Sebastiaan Janssen 8707348215 Merge pull request #307 from BatJan/7.1.0
U4-4295 typo on front of admin
2014-02-26 22:42:00 +01:00
Jan Skovgaard 70ba0cd592 U4-4295 typo on front of admin 2014-02-26 19:51:56 +01:00
Shannon 429b5f7c01 Updates the completion stage of the installer 2014-02-26 16:49:35 +01:00
Shannon db4a547801 Fixes build issues 2014-02-26 16:39:40 +01:00
Shannon a9916fc415 Installer logic working for a new installer on sqlce 2014-02-26 16:30:25 +01:00
Shannon 64a37209b8 Merge branch '7.1.0-installer' of https://github.com/umbraco/Umbraco-CMS into 7.1.0-installer 2014-02-26 16:01:48 +01:00
Shannon f9304d7f04 Gets lots of the new installer logic working 2014-02-26 16:01:31 +01:00
perploug 24ae424207 Fixed: U4-3851 More specific error when saving a user with no Section checkbox selected 2014-02-26 15:53:16 +01:00
Per Ploug Krogslund b86ef0d7ac Adds WIP installer files 2014-02-26 15:51:09 +01:00
Per Ploug Krogslund de97d8849a Fixes broken unit tests 2014-02-26 15:51:09 +01:00
Per Ploug Krogslund a3576d8564 Moves app controllers into seperate folder 2014-02-26 15:51:08 +01:00
Sebastiaan Janssen ffdf4e7256 Merge pull request #306 from coolmikkel/7.1.0
Name of Media items easyer to read
2014-02-26 09:46:19 +01:00
Shannon f9475305bb more install bits 2014-02-26 18:25:59 +11:00
coolmikkel 0a6208f3ef Name of Media items easyer to read
The contrast between the text color and background was to low. The text
color has to be darker - black would be the right one.
2014-02-25 22:11:38 +01:00
Shannon 00f2afe454 Creates Install MVC Area, creates new installer api controllers, moves old installer files to the new Area folder so that the /install path can route properly. 2014-02-26 04:15:14 +11:00
Shannon 3800ffc11c Fixes new membership providers to ensure no sql is run on init. Fixes the installer useLegacyEncoding setup to not attempt to set this when the legacy provider is enabled. 2014-02-26 02:57:05 +11:00
Shannon 2a9b1cb246 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs
2014-02-25 03:30:32 +11:00
Shannon 651182f5de Fixes sql statement - to be like we have in v7 that supports all sql servers 2014-02-25 02:37:48 +11:00
Shannon 784f873777 updated to use constant 2014-02-25 02:36:25 +11:00
Shannon a938605461 fixes merge issue 2014-02-25 02:33:48 +11:00
Shannon bb9c968d3a fixes merge issues 2014-02-25 02:30:05 +11:00
Shannon b8fe5df3c9 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/Umbraco.Core/Configuration/GlobalSettings.cs
	src/Umbraco.Core/Configuration/UmbracoSettings.cs
	src/Umbraco.Core/Models/Member.cs
	src/Umbraco.Core/Services/ContentService.cs
	src/Umbraco.Core/Services/MediaService.cs
	src/Umbraco.Core/Services/MemberService.cs
	src/Umbraco.Web.UI/config/ClientDependency.config
	src/Umbraco.Web.UI/config/Dashboard.Release.config
	src/Umbraco.Web.UI/config/feedProxy.config
	src/Umbraco.Web.UI/config/tinyMceConfig.config
	src/Umbraco.Web.UI/config/trees.config
	src/Umbraco.Web.UI/config/umbracoSettings.Release.config
	src/Umbraco.Web.UI/config/umbracoSettings.config
	src/Umbraco.Web.UI/config/xsltExtensions.config
	src/Umbraco.Web.UI/umbraco/config/create/UI.Release.xml
	src/Umbraco.Web/Strategies/Migrations/ClearMediaXmlCacheForDeletedItemsAfterUpgrade.cs
	src/umbraco.providers/members/UmbracoMembershipProvider.cs
2014-02-25 02:24:45 +11:00
Shannon 22b15a06f6 Fixes how member is approved is set by defaut and adds unit test for it. Also ensures that it returns true if the property value is invalid for whatever odd reason. 2014-02-25 02:10:25 +11:00
Shannon cb09795280 Removes new member service Creating event, as only Created makes sense. Deprecates the other 'Creating' events with a note to just use the Created event. 2014-02-25 01:45:41 +11:00
perploug 81dfd0c6bc #U4-3649 Fixed 2014-02-24 15:35:25 +01:00
perploug 9f028e6d61 Replace Crop() with GetCropUrl() 2014-02-24 15:35:24 +01:00
Sebastiaan Janssen ac57ec2211 Fixed U4-3648 v7, User without access to "Users" section can't change password
Added change password dashboard back
2014-02-24 13:15:45 +01:00
Sebastiaan Janssen 218bb28440 #U4-4245 Umbraco version number is really hard to see
Moved the version to the top when clicking "help", moved the css into main.less and made the text a little bit darker for contrast
2014-02-24 12:49:07 +01:00
Sebastiaan Janssen d02b230f71 Fixes #U4-4195 7.0.X PropertyValueEditor.GetDatabaseType FormatException on different regional settings 2014-02-24 12:08:33 +01:00
Sebastiaan Janssen 289361c02f Merge branch '7.1.0' of https://github.com/umbraco/Umbraco-CMS into 7.1.0 2014-02-24 11:59:05 +01:00
Sebastiaan Janssen fc3020ffa4 #U4-4153 Fixed Macro snippets refer to 'MediaCurrent' and 'Show', also polishes other snippets a bit 2014-02-24 11:58:25 +01:00
perploug 7c4c44cf7e Enables the breadcrumb nav on media edit 2014-02-24 11:55:54 +01:00
perploug 458c51a955 Implements IHtmlString on imagecropdataset 2014-02-24 10:42:29 +01:00
perploug f3d64bb85d Fixes broken file resolver due to wrong alias 2014-02-24 10:30:35 +01:00
perploug 8261a2b69b Fixes U4-4271 U7.1 Nightly build 16 YSOD when editing doc type 2014-02-24 09:36:10 +01:00
Sebastiaan Janssen a5637af2d8 Adding missing CreateMember method that also as a convenience allows you to pass in the member type alias instead of a whole membertype 2014-02-22 18:32:26 +01:00
Sebastiaan Janssen ac59c5deb0 Fixing some potential upgrade issues and two issues found with the legacy member API
- For legacy API we never had and "approved" checkbox, so the assumption is that members are always approved
- The RequiresUniqueEmail check was wrong, previously the assumption was: if there's no e-mail then don't check for uniqueness
2014-02-22 16:44:02 +01:00
Sebastiaan Janssen 683ddf6d34 Apparently we rely on <error404>1</error404> to be in umbracoSettings.config 2014-02-22 16:03:59 +01:00
Sebastiaan Janssen eda33b1ac4 Update incorrect summary 2014-02-22 14:47:59 +01:00
Sebastiaan Janssen ed0f884348 Been a while: properly syncing /config/*.config with /config/*.Release.config 2014-02-21 17:50:58 +01:00
Sebastiaan Janssen b561351340 Update UI.Release.xml with the correct Partial View references 2014-02-21 17:33:19 +01:00
Sebastiaan Janssen 690ab29863 Use the database "agnostic" query for this (see U4-3876) 2014-02-21 17:01:59 +01:00
Shannon a1b3345671 fixes last unit test 2014-02-21 18:09:46 +11:00
Shannon e1022bd5a1 fixes another test 2014-02-21 18:04:15 +11:00
Shannon 1f2c00e3be fixes another test 2014-02-21 18:03:26 +11:00
Shannon bf4c58a6f4 fixed some config unit tests 2014-02-21 18:01:23 +11:00
Shannon 9de0a62cff Fixes merge issues 2014-02-21 16:43:49 +11:00
Shannon 3c3f2d7c8d Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/Umbraco.Core/Constants-Conventions.cs
	src/Umbraco.Core/DateTimeExtensions.cs
	src/Umbraco.Core/Models/PropertyType.cs
	src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs
	src/Umbraco.Core/Persistence/Factories/PropertyGroupFactory.cs
	src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs
	src/Umbraco.Core/Persistence/Repositories/Interfaces/IUserRepository.cs
	src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs
	src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs
	src/Umbraco.Tests/App.config
	src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs
	src/Umbraco.Tests/UmbracoExamine/ExamineBaseTest.cs
	src/Umbraco.Tests/packages.config
	src/Umbraco.Web.UI/packages.config
	src/Umbraco.Web/Umbraco.Web.csproj
	src/Umbraco.Web/app.config
	src/Umbraco.Web/umbraco.presentation/umbraco/developer/Xslt/xsltInsertValueOf.aspx.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/umbracoField.aspx.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/members/EditMember.aspx.cs
	src/umbraco.MacroEngines/App.Config
	src/umbraco.providers/members/UmbracoMembershipProvider.cs
2014-02-21 16:32:53 +11:00
Shannon 27cb1d5223 completes: U4-4275 Hide built-in member type properties from the insert umbraco field list 2014-02-21 16:20:07 +11:00
Shannon c677f36f08 Changes some of the naming conventions for the underlying membership provider services bits. 2014-02-21 16:03:32 +11:00
Shannon 750f7a6b33 Updates some method names to be less confusing regarding permissions 2014-02-21 15:55:56 +11:00
Shannon dea804b402 fixes some permission logic and a unit test 2014-02-21 15:46:39 +11:00
Shannon 3803d1d7da fixes reflected property on dynamicnode and unit test 2014-02-21 15:22:02 +11:00
Shannon 3e67b3034d Added the ability to specify explicit db type's for a property type using an overloaded ctor argument. This allows us to specify explicit db types for properties without having them get overwritten during the repository saving logic which will always reset it to be the db type of the underlying property editor. In the case of our built-in membership properties we do not want this to happen. Fixes some unit tests. Removes built-in props from being included in the property types on the profile model on the front-end. 2014-02-21 12:56:00 +11:00
Shannon 1ada5210ad updated to latest examine 2014-02-21 09:54:53 +11:00
Shannon 92e1db1667 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0 2014-02-20 23:14:45 +11:00
Shannon f0258b2bce fixes merge issue 2014-02-20 23:14:39 +11:00
Shannon 9a608674eb fixes another test 2014-02-20 23:11:27 +11:00
Shannon 0fc5af5e17 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs
	src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs
	src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs
	src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs
	src/Umbraco.Core/Persistence/RepositoryFactory.cs
	src/Umbraco.Tests/packages.config
	src/Umbraco.Web.UI/packages.config
2014-02-20 23:06:13 +11:00
Shannon 7dae412a29 fixes most of the newly failing unit tests and adds better null checking 2014-02-20 23:00:04 +11:00
perploug c3471ffbc3 Cropsizes config and upload compatible
Refactors imagecropper and fileupload to use the samen metadata setting
extensions
2014-02-20 12:59:15 +01:00
perploug f8baf343bf Fixing totally broken merge 2014-02-20 12:59:11 +01:00
Shannon a1067e676f publicizes some repository factory methods and interfaces 2014-02-20 21:56:58 +11:00
Shannon ce649f54d7 Upgraded to latest examine, completes: U4-4240 Update with new examine version 0.1.53 2014-02-20 15:01:47 +11:00
Shannon 09b9056fb0 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0 2014-02-20 14:39:23 +11:00
Shannon 8da2c22a4e removes special default password check, this is no longer necessary. 2014-02-20 14:38:56 +11:00
Shannon d159792256 Updates last step of installer logic, we don't care about other providers as that would never have worked anyways 2014-02-20 14:38:00 +11:00
Shannon d08712306c updates logic for v7 new cols 2014-02-20 14:03:51 +11:00
Shannon 5e30fd4ced Merge remote-tracking branch 'origin/6.2.0' into 7.1.0 2014-02-20 13:56:37 +11:00
Shannon 314abde9ac fixes merge 2014-02-20 13:56:18 +11:00
Shannon 606b5aa60a fixes logic in membershiphelper updatemember 2014-02-20 13:55:56 +11:00
Shannon 5441c30780 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/Umbraco.Core/UriExtensions.cs
	src/Umbraco.Web.UI/install/Default.aspx.cs
	src/Umbraco.Web/UmbracoModule.cs
2014-02-20 13:42:02 +11:00
Shannon 2c563168e7 Merge remote-tracking branch 'origin/7.1.0' into 7.1.0 2014-02-20 13:40:56 +11:00
Shannon 59f8508332 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/Umbraco.Core/Attempt{T}.cs
	src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs
	src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs
	src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs
	src/Umbraco.Core/Umbraco.Core.csproj
	src/Umbraco.Web/umbraco.presentation/umbraco/members/EditMember.aspx.cs
2014-02-20 13:40:17 +11:00
Shannon a206652a0d updates login redirect logic to be more inline with v7, less greedy which is better. 2014-02-20 13:37:12 +11:00
Shannon 545040fdf0 Fixes installer upgrade 2014-02-20 13:09:54 +11:00
Sebastiaan Janssen 2954b31435 Enables change content type action for v7 as well (see issue 1468) 2014-02-19 21:48:17 +01:00
Shannon 40d1a09609 Updates the membership helper in how it updates the membership provider data, updates the editMember page to update the membership provider properties all via the membership provider 2014-02-19 23:49:53 +11:00
Shannon 2e25bc8fdb Moves all FindCOntrolRecursive calls to an extension method 2014-02-19 23:49:08 +11:00
Shannon 1618ac86b8 Adds implicit bool operator for Attempt, makes things nicer to check for success :) 2014-02-19 22:45:22 +11:00
Shannon a4adbca12c Removes the ability to edit the data type for a built-in membership property. Ensures that even if a data type is attempted to be changed with the API that the built-in properties are always persisted with the data type that we have defined by convention. 2014-02-19 21:56:33 +11:00
Shannon 8728e2f918 Fixes: U4-4260 When changing sort order on member type and saving, this doesn't get reflected on the member 2014-02-19 20:17:21 +11:00
Shannon d6b55c54e6 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0 2014-02-19 17:54:07 +11:00
Shannon cd53682ddb removes ability to configure custom fields for the new membership provider 2014-02-19 17:52:45 +11:00
Shannon d000b67703 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0 2014-02-19 17:27:42 +11:00
Shannon e2d5fbf545 Fixes issue with ensuring properties on entities when a new property type has been created - but if the property type doesn't have an id, we should ignore it. 2014-02-19 17:27:08 +11:00
Shannon a6c4ce3a31 fixes some merge issues 2014-02-19 17:26:19 +11:00
Shannon 64246b4eef fixes build 2014-02-19 17:08:55 +11:00
Shannon fe8098adac Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/Umbraco.Web.UI/umbraco/controls/GenericProperties/GenericProperty.ascx
	src/Umbraco.Web/umbraco.presentation/umbraco/controls/GenericProperties/GenericProperty.ascx.cs
2014-02-19 17:02:25 +11:00
Shannon d339e7c814 updates the property type editability for built in member types 2014-02-19 16:57:33 +11:00
Shannon 9860ffc3bf Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/Umbraco.Core/Constants-Conventions.cs
	src/Umbraco.Core/Models/Member.cs
	src/Umbraco.Core/Models/MemberType.cs
	src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs
	src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs
	src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs
	src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs
	src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs
	src/Umbraco.Core/Umbraco.Core.csproj
	src/Umbraco.Web.UI/umbraco/controls/GenericProperties/GenericProperty.ascx
	src/Umbraco.Web/Models/ProfileModel.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/controls/GenericProperties/GenericProperty.ascx.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/members/EditMember.aspx.cs
2014-02-19 16:55:56 +11:00
Shannon 7db829b2a3 updates convention data types 2014-02-19 16:50:45 +11:00
Shannon 10759773ca Merge branch '7.1.0' of https://github.com/umbraco/Umbraco-CMS into 7.1.0 2014-02-19 16:36:28 +11:00
Shannon 078deb704b Completes: U4-4255 Add readonly membership provider properties to the profile model 2014-02-19 16:27:14 +11:00
Shannon 6858eb3330 Fixes: U4-4257 Fix member type editor to not have to re-call 'Save' so many times,
streamlines how the show property and editable property on member type's are dealt with (removes tuples)
2014-02-19 16:14:34 +11:00
Shandem 16e16f9578 Merge pull request #299 from kgiszewski/feature-slider-fix
Fix broken path
2014-02-19 15:35:30 +11:00
Shannon e267b7700a Ensures that member properties are created when member type property type's are added (same as U4-1407), streamlines how this occurs on the base class. Streamlines how empty aliases are validated at the repo level for members, media, content. Makes built-in member property type's non-editable 2014-02-19 14:23:48 +11:00
perploug f780c21ef0 Removed crops from umbracoSettings.cfg 2014-02-19 00:19:18 +01:00
perploug 84e7396729 Ensure that umbracoFile doesnt try to process json as a filepath 2014-02-19 00:19:17 +01:00
perploug 7ed11c04c5 Updates yepnope cache in jsinit.cs to append correct rnd value 2014-02-19 00:19:16 +01:00
perploug 81305173ca Changes imagecropper to store config in its property data 2014-02-19 00:19:15 +01:00
perploug 6637ceaf41 Add support for looking up 3rd party editor file paths
Adds a file resolver on the mediaHelper, property editors can then
register a resolver to return file paths from whatever format
2014-02-19 00:19:13 +01:00
perploug 82d5f7b72b Adjusted assetsService to deal with weird yepnope behaivior 2014-02-19 00:19:12 +01:00
perploug e69dea26a5 Adds extra null checking when looking up active tree 2014-02-19 00:19:11 +01:00
Kevin Giszewski 85d6f1d54a Fix broken path 2014-02-18 11:07:14 -05:00
Shannon f168093b92 Merge commit 'f06c9e823545d8e86309bb751e63b99a2a3b1a18' into 7.1.0
Conflicts:
	src/Umbraco.Core/Models/Member.cs
	src/Umbraco.Core/Persistence/Querying/BaseExpressionHelper.cs
	src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs
	src/Umbraco.Core/Umbraco.Core.csproj
	src/Umbraco.Core/packages.config
	src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs
	src/Umbraco.Web.UI/config/ClientDependency.config
	src/Umbraco.Web/umbraco.presentation/umbraco/controls/passwordChanger.ascx.cs
2014-02-18 18:03:29 +11:00
Shannon 1e45abe71e oops, changes the failedpassattempts back to noedit 2014-02-18 17:58:57 +11:00
Shannon a556b4ed21 Logs warnings if accessing built-in properties on the member model but the underlying property type is missing. 2014-02-18 17:53:02 +11:00
Shannon 953c711ca4 Updates the default member type property types to use "Labels", then needed to update the member type repo and membertypereadonlyfactory to ensure that even though the underlying data type for the property exposes a different Db Type that we 'reset' that Db Type to what it always should be. This means that no matter what underlying data type a developer changes a property to, if it is a built-in membership property, the Db Type will always stay consistent and save in the correct column. Of course if someone enters some invalid data, then the data will not be saved. 2014-02-18 17:19:38 +11:00
Shannon f06c9e8235 Ensures the default member type properties are put on a custom tab 2014-02-18 15:39:00 +11:00
Shannon f1a439e851 removes version specific references to mysql in the proj files and web.config
ensures that escaping in the sql expression classes is done correctly without any double escaping. Also ensures that escaping is happening using the equals operator, not just the Equals() method and adds unit tests for them.
Fixes: U4-4232 Umbraco.Core.Persistence.Querying issue with backslashes
2014-02-18 14:57:03 +11:00
Shannon 20c2574f94 Merge remote-tracking branch 'origin/7.0.4' into 7.1.0
Conflicts:
	build/Build.bat
	src/Umbraco.Core/Configuration/UmbracoVersion.cs
	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
	src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs
	src/umbraco.providers/UsersMembershipProvider.cs
2014-02-18 11:11:57 +11:00
Shannon ab4c58b3a3 restores BuildBelle 2014-02-18 11:11:06 +11:00
Shannon cb63642ce9 Merge branch '7.1.0' of https://github.com/umbraco/Umbraco-CMS into 7.1.0 2014-02-18 10:48:51 +11:00
perploug 3fb756939e ImageProcessor config files 2014-02-17 16:17:18 +01:00
perploug ec14a16aec ImageCropper Razor models + helpers 2014-02-17 16:17:17 +01:00
perploug 6944f25c9f Fixes Assets.Service callback not firering 2014-02-17 16:17:16 +01:00
perploug 45c7699a33 Footer breadcrumb navigation 2014-02-17 16:17:09 +01:00
perploug 2bd2f12831 ImageCropper Upload enabled
The cropper can now fully replace the upload datatype
2014-02-17 16:17:02 +01:00
Shannon a0e496e589 Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-02-17 21:38:38 +11:00
Shannon e0dcc3afbc Streamlines how strings are escaped with the sql expression helpers and syntax providers. Fixes: U4-4232 Umbraco.Core.Persistence.Querying issue with backslashes 2014-02-17 21:38:13 +11:00
Stephan a4b1b31a24 U4-4241 - UrlAbsolute() returns relative urls 2014-02-17 10:49:26 +01:00
Stephan 3634a77d61 U4-4241 - UrlAbsolute() returns relative urls 2014-02-17 10:47:51 +01:00
Shannon 846f4b5b6c Removes the various old hacks for the legacy user's membership provider, now that we have the AllowManuallyChangingPassword flag, these hacks are not required. 2014-02-17 19:32:04 +11:00
Shannon 2869f17eff ensures the default property aliases are set during ctor 2014-02-17 18:02:29 +11:00
Shannon b73c39b4e9 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
	src/Umbraco.Core/Persistence/Repositories/Interfaces/IUserRepository.cs
	src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs
	src/Umbraco.Core/Services/UserService.cs
	src/Umbraco.Tests/Services/PerformanceTests.cs
	src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs
2014-02-17 17:48:16 +11:00
Shannon feefb052fd Updates the BulkInsertRecords method to optionally close the trans - shouldn't by default. Updates how permissions are handled in the new services and exposes another method, ensures it's all wrapped in trans and ensures that cache is cleared properly. Fixes: U4-4213 "Replace child node permissions" does not work if all permissions cleared 2014-02-17 17:45:59 +11:00
Shannon 87f93be6ba updates version 2014-02-17 16:06:46 +11:00
Shannon 7e7c4b52b6 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/Umbraco.Core/PluginManager.cs
2014-02-17 15:59:43 +11:00
Shannon 4d2d9156ba updates more plugin manager defs 2014-02-17 15:58:57 +11:00
Shannon a1603c3cbd Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/Umbraco.Core/Models/Membership/EntityPermission.cs
	src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
	src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs
	src/Umbraco.Core/PluginManager.cs
	src/Umbraco.Web.UI/config/trees.config
	src/Umbraco.Web/Search/ExamineEvents.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/Trees/TreeDefinitionCollection.cs
2014-02-17 15:56:48 +11:00
Shannon 82ba1a24a3 Ensures we perform null checks in both GetAll and GetByQuery as we never want to include a null item in the resultant collection - which could happen depending on what the sub class repository is doing.
Fixes: U4-3145 Cache file periodically becomes corrupted: "Oops: this document is published but is not in the cache (internal error)"
2014-02-17 15:45:36 +11:00
Shannon 357db9d0b6 completes: U4-3282 Expose permission assignment methods at the service layer 2014-02-17 15:33:17 +11:00
Shannon 61766287bc Cleans up some more of the old 'object' User Id references. 2014-02-17 15:26:38 +11:00
Shannon ffbf8b2fd6 completes: U4-4103 Publicize PluginManager for devs to use to create their own plugins 2014-02-17 15:08:27 +11:00
Shannon e8c25283b0 Fixes: U4-2876 Ensure runtime cache is cleared with ICacheRefreshers when macro's change since they use the RuntimeCacheProvider 2014-02-17 15:03:49 +11:00
Shannon f7a703195c Fixes: U4-4215 Tree.config registeres tree inconsistently 2014-02-17 14:56:12 +11:00
Shannon 848e8b5722 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0 2014-02-17 14:15:54 +11:00
Shannon 4d316c9671 fixing some casting 2014-02-17 14:15:40 +11:00
Shannon 509be9b431 Updates the underlying UmbracoServiceMembershipProvider to deal with 'object' for provider key, this then lets us deal with either guid or int for the new membership provider, just like the old one does. 2014-02-17 14:14:17 +11:00
Shannon 8154382fb1 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/umbraco.providers/members/UmbracoMembershipProvider.cs
2014-02-17 13:17:19 +11:00
Shannon 10ef5eb7bc adds new interface for members' membership providers to implement so we know what aliases to store data against. 2014-02-17 13:16:28 +11:00
Shannon f4c1c4578f adds some null checking 2014-02-17 12:56:37 +11:00
Shannon 6f15949af7 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0 2014-02-17 12:24:37 +11:00
Shannon 2849ecadb7 fix legacy member wrapping new api and mixing email/login name 2014-02-17 12:24:11 +11:00
Shannon 778c698ef7 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0 2014-02-17 12:10:12 +11:00
Shannon 697f93c3ce removes null check for LoginName, since it gets set to the name passed in if it is empty 2014-02-17 12:09:27 +11:00
Shannon e6c2f0ad70 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0 2014-02-17 11:50:39 +11:00
Shannon 13976559a8 Created a EntityNotFoundException to use when we are expecting an umbraco entity found. Updates some code to use this exception. 2014-02-17 11:50:13 +11:00
Shannon 18121e8726 Enxures user start node's are -1 by default when creating the model. 2014-02-17 11:48:32 +11:00
Shannon 8b6583b554 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0 2014-02-17 11:23:24 +11:00
Shannon 234d4cf427 Merge branch '7.1.0' of https://github.com/umbraco/Umbraco-CMS into 7.1.0
Conflicts:
	src/Umbraco.Core/Models/Template.cs
2014-02-17 11:23:02 +11:00
Shannon 81cdc71145 Ensures new user objects are approved by default. 2014-02-17 11:17:15 +11:00
Sebastiaan Janssen f822400036 Fix broken build 2014-02-15 14:24:40 +01:00
Shannon 2aae108cb4 Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/Umbraco.Web/Security/WebSecurity.cs
2014-02-13 17:21:30 +11:00
Shannon 4069fc8d1f fixes issue with legacy user.Password property and fixes comparison of sections 2014-02-13 17:19:28 +11:00
Shannon 643f05d949 fixes some more merge issues 2014-02-13 16:56:23 +11:00
Shannon d36cd035e9 Fixes merge issues 2014-02-13 16:46:52 +11:00
Shannon c4acbf0dbc Merge remote-tracking branch 'origin/6.2.0' into 7.1.0
Conflicts:
	src/Umbraco.Core/Configuration/ClientDependencyConfiguration.cs
	src/Umbraco.Core/Constants-Conventions.cs
	src/Umbraco.Core/Models/Member.cs
	src/Umbraco.Core/Models/Membership/IUser.cs
	src/Umbraco.Core/Models/Template.cs
	src/Umbraco.Core/Persistence/Factories/MemberReadOnlyFactory.cs
	src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs
	src/Umbraco.Core/Persistence/Repositories/Interfaces/IMemberRepository.cs
	src/Umbraco.Core/Persistence/Repositories/Interfaces/IUserRepository.cs
	src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs
	src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs
	src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs
	src/Umbraco.Core/Persistence/RepositoryFactory.cs
	src/Umbraco.Core/Services/ContentService.cs
	src/Umbraco.Core/Services/IMemberTypeService.cs
	src/Umbraco.Core/Services/IMembershipUserService.cs
	src/Umbraco.Core/Services/IUserService.cs
	src/Umbraco.Core/Services/MemberService.cs
	src/Umbraco.Core/Services/MemberTypeService.cs
	src/Umbraco.Core/Services/ServiceContext.cs
	src/Umbraco.Core/Services/UserService.cs
	src/Umbraco.Core/Umbraco.Core.csproj
	src/Umbraco.Tests/MockTests.cs
	src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs
	src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs
	src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs
	src/Umbraco.Tests/Persistence/Repositories/UserRepositoryTest.cs
	src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/EditProfile.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Login.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/LoginStatus.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/RegisterMember.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/Breadcrumb.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/EditProfile.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/ListAncestorsFromCurrentPage.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/ListChildPagesFromCurrentPage.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/ListChildPagesOrderedByDate.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/ListChildPagesOrderedByName.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/ListChildPagesWithDoctype.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/ListDescendantsFromCurrentPage.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/Login.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/LoginStatus.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/MultinodeTree-picker.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/Navigation.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/RegisterMember.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViews/Templates/SiteMap.cshtml
	src/Umbraco.Web.UI/Umbraco/create/PartialView.ascx.cs
	src/Umbraco.Web.UI/config/umbracoSettings.config
	src/Umbraco.Web/Cache/CacheRefresherEventHandler.cs
	src/Umbraco.Web/Controllers/UmbLoginController.cs
	src/Umbraco.Web/Controllers/UmbLoginStatusController.cs
	src/Umbraco.Web/Controllers/UmbProfileController.cs
	src/Umbraco.Web/Controllers/UmbRegisterController.cs
	src/Umbraco.Web/Models/LoginModel.cs
	src/Umbraco.Web/Models/LoginStatusModel.cs
	src/Umbraco.Web/Models/ProfileModel.cs
	src/Umbraco.Web/Models/RegisterModel.cs
	src/Umbraco.Web/Models/UmbracoProperty.cs
	src/Umbraco.Web/Mvc/UmbracoViewPageOfTModel.cs
	src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs
	src/Umbraco.Web/Security/WebSecurity.cs
	src/Umbraco.Web/Umbraco.Web.csproj
	src/Umbraco.Web/UmbracoModule.cs
	src/Umbraco.Web/WebApi/UmbracoApiController.cs
	src/Umbraco.Web/umbraco.presentation/library.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/controls/ContentTypeControlNew.ascx.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewMacrosTasks.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/create/PartialViewTasks.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/editContent.aspx.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/login.aspx.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/members/EditMember.aspx.cs
	src/Umbraco.Web/umbraco.presentation/umbraco/users/EditUser.aspx.cs
	src/Umbraco.Web/umbraco.presentation/umbracobase/baseLibrary.cs
	src/Umbraco.Web/umbraco.presentation/umbracobase/restExtension.cs
	src/umbraco.businesslogic/User.cs
	src/umbraco.providers/UsersMembershipProvider.cs
	src/umbraco.providers/members/UmbracoMembershipProvider.cs
2014-02-13 16:22:51 +11:00
Shannon 0a80c39962 Fixes merge 2014-02-13 15:25:57 +11:00
Florian Verdonck edee8134c2 Updated request after feedback 2014-02-13 15:21:40 +11:00
Shannon 2f66303b38 Merge branch 'KevinJump-7.0.2' into 7.1.0 2014-02-13 15:12:02 +11:00
Shannon 7102ed49ec Merge branch '7.0.3' of https://github.com/stevetemple/Umbraco-CMS into stevetemple-7.0.3
Conflicts:
	src/Umbraco.Web.UI.Client/src/views/propertyeditors/rte/rte.controller.js
2014-02-13 15:00:42 +11:00
Shandem f5d94c3a05 Merge pull request #294 from nojaf/patch-1
Changing MasterTemplateId to public
2014-02-13 14:48:24 +11:00
Shannon 92502f946b Merge branch '7.0.3' into 7.1.0 2014-02-13 14:49:00 +11:00
Shannon 30a73c0886 updated web.config template to use new role provider. 2014-02-13 14:45:24 +11:00
Shannon f5ee02a3e9 Updates the membership partial view templates to redirect to current page by default but allows this to be overridden. Creates a new RedirectToCurrentUmbracoUrl method which is slightly diff from RedirectToCurrentUmbracoPage since it doesn't care about the actual page item rendering, just the currently rendered URL which is useful if coming from a rewritten URL (which is what happens with public access rewrites) 2014-02-13 13:30:32 +11:00
Shannon 9827b40bea Fixes: U4-4223 MVC based forms with SurfaceControllers don't work when rendered in Webforms mode.
This slightly changes how the routing works in the module, now we always send the request to the RenderRouteHandler, this will first process the logic for route hijacking, then it will determine if the request was found to be a WebForms template, if so then we'll return the webforms handler. This also now allows us to have POSTed values to SurfaceController's from forms that have been rendered in Webforms whilst maintaining all viewdata, tempdata and model state on postback even when rendering in webforms!
2014-02-13 13:19:51 +11:00
Shannon 2de6f09634 Adds configuration section classes for the image cropping + unit tests. 2014-02-13 11:01:37 +11:00
Sebastiaan Janssen df16a69582 Merge pull request #295 from loedeman/patch-1
Update nl.xml
2014-02-12 13:37:09 +01:00
Stephan f9323c85e4 Fix issue with 9d7b3b96 in .designer.cs file 2014-02-12 13:22:35 +01:00
Stephan 2677672e50 Merge remote-tracking branch 'origin/6.2.0' into 6.2.0 2014-02-12 13:22:30 +01:00
Morten Christensen a38e0dcf86 Adding integer overload for UmbracoEntity so it can be used with a dynamic object containing either a boolean or integer retrieved from the database to initialize the UmbracoEntity object. 2014-02-12 12:47:47 +01:00
Stephan fdd7227494 Fix DynamicPublishedContent to use CleanStringType.ConvertCase 2014-02-12 10:46:57 +01:00
Stephan 6b74e14cdd Backport DefaultShortStringHelper from 7.1 2014-02-12 10:40:00 +01:00
Stephan db528d8d7a U4-4199 - undef debug code in release 2014-02-12 10:23:59 +01:00
Shannon 9d7b3b965a fixes some issues with new bundles. 2014-02-12 18:19:20 +11:00
Shannon 806008a7e9 Fixes issue with @ symbols in login name and a member group query 2014-02-12 18:02:00 +11:00
Shannon 45fa192c95 Fixes some unit tests 2014-02-12 17:25:45 +11:00
Shannon 92235128f1 Got new MemberGroupService done, completed the MemberService for role based stuff, created a member group cache refresher since we are caching member groups by name (probably should cache others too). Public access stuff changes if a name of a member group is changed which is now done with an event instead of coded into the biz logic. 2014-02-12 17:14:16 +11:00
loedeman 06cb7a529e Update nl.xml
I've updated the Dutch translation based on the current 7.0.2 English translation (en.xml) since I would rather not start liking the placeholders ;) ...
2014-02-11 19:56:08 +01:00
perploug fa4e9d0cd1 Merge remote-tracking branch 'origin/7.1.0-ImageCropper-WIP' into 7.1.0 2014-02-11 14:56:41 +01:00
perploug 764644fc5d Merge 2014-02-11 14:55:22 +01:00
perploug 0bf27f4371 Make sure the formcontroller reset dirty state on save 2014-02-11 14:48:06 +01:00
Shannon 7622937cfd implemented remaining methods for member groups/roles + unit tests 2014-02-11 20:38:48 +11:00
Shannon bf41694572 Fixed up some more of the member group + member stuff with more unit tests 2014-02-11 19:21:36 +11:00
Shannon 7b897ce64c Member group repo updated along with the member service to support roles, etc... got first of many unit tests passing. 2014-02-11 12:43:55 +11:00
perploug 36a8599e62 Adds cache bursting to production mode
Package installer bumps CDF version, we make sure to purge the angular
cache
initial js loader gets a cache burst as well
2014-02-10 13:02:16 +01:00
Shannon 1ca950f721 Starts creating the IMemberGroupService and supporting classes. 2014-02-10 19:48:16 +11:00
Shannon ffba271fd0 Creates the MemberGroupRepository and supporting models. 2014-02-10 19:35:32 +11:00
Shannon ec08d3e910 Updates MembershipHelper to not change the email/name if the value has not changed. Updates the templates to show only validation summaries for their own values/prefixes. Fixes some underlying MVC methods that merge view state to ensure the prefixes work with validation summaries properly when not showing property level errors. Updates the Umb controllers to add model level validation msgs when failed. 2014-02-10 18:34:12 +11:00
Shannon 0bfd032fad Obsoletes the RedirectOnSucces on the RegisterModel as it is not needed. Adds RedirectUrl to the ProfileModel and updates the controller to redirect properly (ensures it doesn't just redirect to home!) 2014-02-10 16:46:45 +11:00
Shannon 2bb58b6fca Updates MembershipHelper to ensure that the membership provider is used when updating a profile, specifically to deal with unique emails. Updates the profile edit template to have correct validation procedures. 2014-02-10 16:22:15 +11:00
Shannon 4d2d656b3d Moved ChangePassword method to MembershipHelper and makes it public, adds an overload. 2014-02-10 14:29:29 +11:00
Shannon fa625d72f9 updates some comments 2014-02-10 14:12:44 +11:00
Shannon 1991380e02 Changes CDF version to be the hash code of UTC now 2014-02-10 13:53:12 +11:00
Shannon 3b8d6dc2c7 Merge remote-tracking branch 'origin/6.2.0' into 6.2.0 2014-02-10 13:50:43 +11:00
Shannon 1faeb76c27 Removes the need for duplicate templates for partial views. Of course we can have partial view only templates if necessary but currently we just borrow them from the partial view macros and update the header 2014-02-10 13:50:31 +11:00
Florian Verdonck a064903e90 Updated request after feedback 2014-02-08 00:28:52 +01:00
perploug 2850c3c3de Improved caching in debug mode by adding global yepnope filter 2014-02-07 15:45:52 +01:00
Florian Verdonck 1fa7cd234d Changing MasterTemplateId to public
When you create a Template in code, I think there is no way to define a masterTemplate. If MasterTempateId were to be public it could be done.
2014-02-07 09:39:10 +01:00
perploug cec8001c38 Fixes issue with MediaHelper and complex property values 2014-02-07 09:16:05 +01:00
perploug 7dbd21a854 ImageCropper Added as a real property editor + polish
Polishing the UI, it can now edit actual image data and store crop
points / center point as json, next add configuration service
2014-02-07 09:15:44 +01:00
Sebastiaan Janssen 3a513668fd U4-4185 Log fails to show unicode (cyrillic) characters 2014-02-05 15:52:20 +01:00
perploug 9ff82f3a00 Removes unneeded loging in umbpanel.directive 2014-02-04 13:58:13 +01:00
perploug 25999be0c9 Improves sticky footer button detection
Refactored the event hooks, added a watch on the buttons position
2014-02-04 12:53:09 +01:00
perploug 853baf9462 Final tweaks to the unsaved changes dialog 2014-02-04 11:40:16 +01:00
Per Ploug Krogslund 6f36384a35 Merge branch '7.1.0-LocationChangeNotificatiion' into 7.1.0 2014-02-04 09:46:54 +01:00
Per Ploug Krogslund d55e492d17 Route change confirm notification dialog 2014-02-04 09:46:14 +01:00
Per Ploug Krogslund fcbdf6c635 Merge branch '7.1.0' of https://github.com/umbraco/Umbraco-CMS into 7.1.0 2014-02-03 21:50:30 +01:00
Per Ploug Krogslund 1fda22a4e0 Merge branch '7.1.0-LocationChangeNotificatiion' into 7.1.0 2014-02-03 21:48:23 +01:00
Per Ploug Krogslund deeaf724bd Fixes missing dependencies 2014-02-03 21:04:11 +01:00
Per Ploug Krogslund 34824ffbb0 Confirm navigating away from unsaved content 2014-02-03 21:03:43 +01:00
Per Ploug Krogslund 6f28a0a686 Updates NotificationService to support custom views
This allows us to inject small UI components as overlays ontop of
editors
2014-02-03 21:03:24 +01:00
Sebastiaan Janssen b3f6a8c71b Merge branch '7.0.3' into 7.1.0
Conflicts:
	.gitignore
	src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js
2014-02-03 11:52:36 +01:00
Steve Temple aad0e73fea Add customConfig back into rte 2014-01-31 23:18:49 +00:00
Per Ploug Krogslund 7d7fcd2093 Wip on dropper and gravity editor directives 2014-01-30 22:28:50 +01:00
Stephan 3ef51d7357 U4-2317 - issue with domains & languages management 2014-01-30 16:18:06 +01:00
Stephan 8b553dd067 U4-4144 - work around media cache exceptions on invalid properties 2014-01-29 19:30:17 +01:00
perploug c52123e878 adds mock cropper data for WIP prototype 2014-01-29 14:30:51 +01:00
perploug 4e6ca57f7a Chore: seperate media + image helpers into 2 files 2014-01-29 14:30:35 +01:00
perploug ce9cfbf071 Chore: update media+mediahelper mocks 2014-01-29 14:30:17 +01:00
perploug 8024bde429 Imaging directives (crop, gravity and preview) 2014-01-29 13:44:34 +01:00
perploug 9ce79e98a3 Final tweaks to TreeSource picker
Better help text, polish icons and margins, made sure it toggles UI
correctly for each type of tree
2014-01-29 11:21:54 +01:00
perploug 3e5553d9b0 Fixes weird issue with user language dropdown 2014-01-29 09:50:37 +01:00
Shannon ccaf82d797 Fixes object extensions for dates with a 'kind' specified. 2014-01-29 11:21:35 +11:00
perploug 5047c7bbe7 Fixes: U4-4155 Backend CSS Rich Text Editor Path Issue 2014-01-29 00:28:56 +01:00
perploug 0c45fb1b97 Merge branch '7.1.0' of https://github.com/umbraco/Umbraco-CMS into 7.1.0 2014-01-28 23:50:58 +01:00
perploug 7bd745a870 WIP: Tree icon colors 2014-01-28 23:50:25 +01:00
Tim Geyssens 93a4e8f426 Removes hard coded api url from rte embed 2014-01-28 16:18:30 +01:00
Tim Geyssens fcc115004e Updates server vars with embedApiBaseUrl 2014-01-28 16:11:57 +01:00
perploug 24062c0061 Rolls back listview items in dialog trees 2014-01-28 15:49:04 +01:00
perploug 06cbdc37b4 Fixes: U4-4143 In rich text editor, non ASCII characters in source code window are encoded
Also at the same time fixes missing config import from serverside config
2014-01-28 15:45:14 +01:00
Shannon f28ae52ae3 moved logic to update a profile to MembershipHelper. 2014-01-28 21:57:00 +11:00
Shannon cfd0973f00 Moves the registration logic to the MembershipHelper, fixes up the views to keep the indexes so props save. 2014-01-28 21:42:30 +11:00
Shannon 1bfdd83ba7 Cleans up more of the membership controllers and snippets to be using the membership helper and fixes up a few issues 2014-01-28 19:41:21 +11:00
Shannon 6fefcacc61 Adds more methods to the MembershipHelper, updates the RegisterModel and obsoletes the standard ctor so biz logic is not happening in the model, updates the snippets to use the correct way. Fixes an issue in the membership repo for persisting new members when the member type doesn't contain all the built-in props. 2014-01-28 18:59:27 +11:00
Shannon 3b639e61b2 Exposes MembershipHelper onthe UmbracoViewPage so people can use it directly in views. 2014-01-28 17:02:20 +11:00
Shannon 9959ff667e publicizes MembershipHelper and exposes it on the various base classes: SurfaceController, UmbracoApiController and UmbracoUserControl as the property "Members", will add more helper methods. 2014-01-28 16:58:55 +11:00
Shannon de1f86c7a1 adds logic to the membership helper to create a new LoginStatusModel with the values filled in, obsoletes the empty ctor on LoginStatusModel since that does some biz logic lookups, instead replaces it with a static method to create an empty one. 2014-01-28 16:30:58 +11:00
Shannon 28d8fd0531 Changes LoginStatusModel to use the correct api and updates the new membership provider stuff to ensure that the provideruserkey is the int id of the model for backwards compatibility. 2014-01-28 16:13:05 +11:00
Shannon e4e76eb0bf Backports commit: Prefixed built in controllers to better avoid conflicts with people's custom code
Conflicts:
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/EditProfile.cshtml
	src/Umbraco.Web.UI/Umbraco/PartialViewMacros/Templates/Login.cshtml
	src/Umbraco.Web/Controllers/UmbLoginController.cs
	src/Umbraco.Web/Controllers/UmbLoginStatusController.cs
	src/Umbraco.Web/Controllers/UmbProfileController.cs
	src/Umbraco.Web/Controllers/UmbRegisterController.cs
	src/Umbraco.Web/Umbraco.Web.csproj
2014-01-28 13:47:16 +11:00
Shannon 677cc8c8fd Fixes ProfileController to use normal .Net APIs and the new members service - also removes the Response.Redirect that was in there, why was it like that? 2014-01-28 13:35:43 +11:00
Shannon 3fa5c4e0b2 Updates RegisterController with the standard ASP.Net APIs to create and login a member. 2014-01-28 13:21:30 +11:00
Shannon 360393c464 Fixes LoginStatusController to use the standard ASP.Net APIs 2014-01-28 13:07:25 +11:00
Shannon d3daf88a8d Fixes the LoginController to use the correct APIs 2014-01-28 12:58:22 +11:00
Shannon 7a99ebd6d9 Starts the implementation of the new role provider. 2014-01-28 12:48:41 +11:00
Shannon a7298e2e5a Completes: U4-4148 Anytime RuntimeCacheProvider or InMemoryCacheProvider is used, a cache refresher will need to handle it's distribution! 2014-01-28 12:20:10 +11:00
Shannon 15d7443c61 Streamlines the content type cache refreshing, leaving some of the legacy cache clearing but that shouldn't really have an effect, with these new changes it should be guaranteed that the distributed cache is executed always for Doc, media and member types. 2014-01-28 12:13:27 +11:00
Shannon f2b7e27b34 Fixes: U4-2721 RuntimeCacheProvider is not cleared when data type changes and updates the repo factory to not use the InMemory cache provider since we should only ever use that for very very specific reasons since the memory can never auto-clear with that provider. 2014-01-28 11:30:02 +11:00
Shannon 690d08aa8c Completes wrapping the new IUserService from the legacy User object. Ensures User cache is handled correctly and distributed cache is updated for Users. 2014-01-28 10:46:59 +11:00
Shannon 6719d70cc0 Updates UserTypeCacheRefresher to clear the runtime cache accordingly. 2014-01-28 09:22:01 +11:00
Shannon 3cdcf513ec removes ancient test project 2014-01-28 09:00:17 +11:00
Shannon 23d9944a61 Merge branch '7.0.2' of https://github.com/kalletoxic/Umbraco-CMS into kalletoxic-7.0.2 2014-01-28 08:47:09 +11:00
perploug 31429ad9c8 Fixes treenodes with very long names breaking the tree 2014-01-27 22:09:16 +01:00
perploug 05a8d80284 Fixes broken refresh action
Refresh action referenced the tree, not its root node
2014-01-27 22:08:40 +01:00
perploug c2d978a0db Enables listview children in dialog trees
By default trees doesnt show children of listview nodes, this enables
them in dialog trees, otherwise content pickers cannot select childrens
of a listview node
2014-01-27 22:03:52 +01:00
perploug e17b32c6e5 Removes option to query media with Xpath on mntp
Only content can be queried with Xpath in a reasonable performant manner
as its the only type of data that is cached as xml
2014-01-27 13:49:09 +01:00
perploug de79512dd4 Adds overloads to relationService.AreRelated
Allows to lookup relations based on type and alias of type when doing
"AreReleated()" checks
2014-01-27 13:45:54 +01:00
perploug 2a81162756 Fixes inconsistently named private method
Replaces delegates with lambdas
2014-01-27 08:27:31 +01:00
perploug 0a7526601c Merge branch '7.1.0' of https://github.com/umbraco/Umbraco-CMS into 7.1.0 2014-01-24 18:41:46 +01:00
perploug 3e22598f4a fixes mntp filtering 2014-01-24 18:38:47 +01:00
perploug d842f0f5b7 Adds support for xpath root node selection on mntp 2014-01-24 18:38:39 +01:00
perploug 8258619055 adds getByQuery to entityService 2014-01-24 18:38:08 +01:00
perploug 7d2f6c13c3 Addss template clearing when in debugmode 2014-01-24 17:20:34 +01:00
Shannon b314bff127 Creates powershell file to do the build, this detects if you have sandcastle installed first, also overwrites the default TOC.css file with a custom slightly nicer version for the output. 2014-01-24 18:23:37 +11:00
Shannon d66e2e52e9 adds additional bat files to the sln files for editing, adds the sandcastle help file config file that can be used to build the docs when sandcastle is installed. 2014-01-24 16:31:49 +11:00
Shannon 43c426b46c Update booting.aspx
Throw the exception immediately if the parameter is not there or empty.

If the parameter is not there it's defaulted to the current url, and this will redirect to itself and create an endless loop here.
2014-01-24 12:36:02 +11:00
Shannon 0714aaa457 Merge remote-tracking branch 'origin/7.0.2' into 7.1.0 2014-01-24 12:34:40 +11:00
Shannon de6e0dc8d7 Merge branch '7.0.2' into 7.1.0 2014-01-24 12:32:07 +11:00
Kevin Jump 57c68daf38 Fix Template Import when template has no master
Importing a template with no master template (i.e when it's at the root)
caused an error. Added check for MasterTemplateId != null - (tried
.IsValueCreated but that generated a object not set exception)
2014-01-23 16:07:07 +00:00
Kevin Jump a705561a51 Fix Importing Macro when macro already exists
ParseMacroElement called by ImportMacro was no checking for to see if
the macro or properties already exists - caused SQL errors on import of
macro. Added check to look for existing macro, and only add new
properties on import (in line with other import methods)
2014-01-23 16:05:08 +00:00
Kevin Jump a7107f01e8 Single DataType import Fix
Importing a file with a single data type failed, because the DataType
element is at the root when exported.
2014-01-23 15:57:50 +00:00
Shannon e2ac82abca Gets most of the User and UserType legacy objects wrapping the new services, yay! Now just need to sort out all the caching stuff which I have tasks for. 2014-01-23 18:44:41 +11:00
Shannon 64d1a484bd Fixes User Id issues with HasIdentity, wraps legacy UserType to the new service, fixes the uninstalling db schema to not throw exceptions and clog up the unit test log. 2014-01-23 17:11:58 +11:00
Shannon 585b42af48 More Save()'s missing and removes the extra calls to XmlGenerate - should save some processing time. 2014-01-23 16:13:29 +11:00
Shannon 7c4412fc4b Ensures that Save() is called wherever member data is saved 2014-01-23 16:09:59 +11:00
Shannon 0be8039c8f Changes how IProfile works which is now just exposed by the IUser instead of implemented, this cleans up the Id situation. 2014-01-23 15:31:49 +11:00
Shannon 668265f1ac Allows forcing pass change with new provider, updates conventions to not allow editing of question/answer - unfortunately cannot make the other ones readonly because noEdit data type is the wrong clr type. 2014-01-23 15:11:54 +11:00
Shannon 4735f27a66 Fixes more naming conventions with CreateMemberWithIdentity, fixes memberTasks to ensure the name is set, fixes new membership providers which had the name/email call reversed. Updates the cache refresher event handler to listen to MemberService events instead of the old legacy API events. 2014-01-23 14:55:41 +11:00
Shannon 6377b9aa50 Fixes some underlying type conversions, fixes more of the member type wrapping, updates contenttypecontrolnew to work with member types properly, ensures the property type cache is cleared when member types change. 2014-01-23 13:33:58 +11:00
Shannon 011be60205 Finishes wrapping the member service and fixes a few bugs - ensures the RepositoryBase doesn't keep enumerating when getting all 2014-01-23 12:30:28 +11:00
Shannon a272675ed8 Wraps the MemberService from the legacy Member object 2014-01-23 11:41:01 +11:00
Shannon 80697cf9ca MemberType fully wraps new MemberTypeService 2014-01-23 10:57:24 +11:00
Shannon f4534aa94c adds unit tests for member type can view/can edit properties 2014-01-23 10:55:22 +11:00
Shannon 56dec485a5 Starts wrapping MemberTypeService from the legacy MemberType object. Changes the User.Id to an int - no more casting. Changes CreateMember to CreateMemberWithIdentity for consistency. Adds raiseEvent params to the create/save methods. Updates the MemberTypeService to have consistent naming conventions. Starts wrapping more of the MemberService from the legacy Member object. 2014-01-23 10:41:57 +11:00
Shannon ffde0f48cf Starts wrapping MemberTypeService from the legacy MemberType object. Changes the User.Id to an int - no more casting. Changes CreateMember to CreateMemberWithIdentity for consistency. Adds raiseEvent params to the create/save methods. Updates the MemberTypeService to have consistent naming conventions. Starts wrapping more of the MemberService from the legacy Member object. 2014-01-23 10:35:30 +11:00
Kevin Jump 5663b6890f Revert "Export Template fails when template has no master value"
This reverts commit a2905c13f6.
2014-01-22 21:35:16 +00:00
Kevin Jump a2905c13f6 Export Template fails when template has no master value 2014-01-22 21:29:49 +00:00
Kevin Jump e8f7a83f68 Fixed: U4-4119 - Export ContentType fails for Generic Properties
Adds Null checking for PropertyGroupID so that an exception is avoided
when the propertyType is in the Generic Properties group (and has no ID
assigned)
2014-01-22 19:50:21 +00:00
Shannon 2956aee4e3 Fixes: U4-4108 The backoffice should not be accessible when the app is not configured, it should redirect to the installer and U4-4106 Set the new membership providers to be shipped as default. 2014-01-22 15:26:45 +11:00
Shannon 9bd8d729fa publicizes user stuff, changes the IUser.Id to an int - no need for it to be an object and casted everywhere. Updates the login logic to perform the mapping logic for custom membership providers with an extension method. 2014-01-22 14:07:18 +11:00
Shannon fb9569d914 Fixes user membership providers to throw exceptions on duplicate emails when the provider is configured to not allow duplicates. 2014-01-22 13:20:00 +11:00
Shannon 47974d49fe obsoletes old providers, creates new membership role provider stub 2014-01-22 12:16:47 +11:00
Shannon 3f8b3031c2 completes: U4-3996 Fix EditUser to use the membership provider properly, U4-3997 Fix EditMember to use the membership provider properly 2014-01-22 11:57:33 +11:00
Shannon 7da41594fd re-publicizes member services, fixes: U4-4102 Un-obsolete ContentService.Publish 2014-01-22 11:27:44 +11:00
Shannon 9796b30bbb Fixes: U4-4104 Using strongly typed Html.Action<T> with a PluginController causes exception 2014-01-22 11:02:24 +11:00
Sebastiaan Janssen ead837f654 U4-4095 Missing Keys in English US Language File 2014-01-20 19:15:50 +01:00
Shannon 88182edf8f Merge remote-tracking branch 'origin/6.2.0' into 7.1.0 2014-01-20 18:34:11 +11:00
Shannon e456dd3886 Merge branch '7.0.2' into 7.1.0 2014-01-20 18:33:54 +11:00
Shannon c2c4763faa Ensures username is escaped in user service 2014-01-20 16:11:38 +11:00
Shannon c062d3b71b Merge branch '6.2.0' of https://github.com/umbraco/Umbraco-CMS into 6.2.0 2014-01-20 16:01:53 +11:00
Shannon ed83fb8216 updates user task creation for release 2014-01-20 16:00:19 +11:00
Shandem 80601abb27 Rename umbImageGravity.directive.js to umbimagegravity.directive.js
Changed file name to be consistent with the rest of our file names
2014-01-15 11:11:31 +11:00
Shandem 79384d8a0a Rename umbImageCrop.directive.js to umbimagecrop.directive.js
changed file name to be consistent with the rest of our file names
2014-01-15 11:11:02 +11:00
Shannon 793a1a9aa8 Adds comments to EntityController code to use UmbracoHelper 2014-01-15 11:08:02 +11:00
Shannon e3da493345 Re-adds all updates for the WIP for xpath/css filtering and the cropper. 2014-01-15 11:06:20 +11:00
633 changed files with 17366 additions and 19483 deletions
+1
View File
@@ -108,3 +108,4 @@ src/Umbraco.Web.UI/[Cc]onfig/connectionStrings.config
src/Umbraco.Web.UI/umbraco/plugins/*
src/Umbraco.Web.UI/umbraco/js/init.js
build/ApiDocs/*
build/ApiDocs/Output/*
+170
View File
@@ -0,0 +1,170 @@
/* File : TOC.css
// Author : Eric Woodruff (Eric@EWoodruff.us)
// Updated : 09/07/2007
//
// Stylesheet for the table of content
*/
*
{
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 0px;
}
body
{
font-family: Segoe UI, Arial, Verdana, Helvetica, sans-serif;
font-size: 0.9em;
background-color: white;
color: White;
overflow: hidden;
}
input
{
padding:5px;
margin: 3px 0px 3px 0px
}
img
{
border: 0;
margin-left: 5px;
margin-right: 2px;
}
img.TreeNodeImg
{
cursor: pointer;
}
img.TOCLink
{
cursor: pointer;
margin-left: 0;
margin-right: 0;
}
a.SelectedNode, a.UnselectedNode
{
color: #333;
text-decoration: none;
padding: 1px 3px 1px 3px;
white-space: nowrap;
}
a.SelectedNode
{
background-color: #ffffff;
border: solid 1px #999999;
padding: 0px 2px 0px 2px;
}
a.UnselectedNode:hover, a.SelectedNode:hover
{
background-color: #cccccc;
border: solid 1px #999999;
padding: 0px 2px 0px 2px;
}
.Visible
{
display: block;
margin-left: 2em;
}
.Hidden
{
display: none;
}
.Tree
{
background-color: #fff;
color: #333;
width: 300px;
overflow: auto;
}
.TreeNode, .TreeItem
{
white-space: nowrap;
margin: 2px 2px 2px 2px;
}
.TOCDiv
{
position: relative;
float: left;
width: 300px;
height: 100%;
}
.TOCSizer
{
clear: none;
float: left;
width: 10px;
height: 100%;
background-image: url("Splitter.gif");
background-position:center center;
background-repeat:no-repeat;
position: relative;
cursor: w-resize;
border-left: solid 1px #CCC;
}
.TopicContent
{
position: relative;
float: right;
background-color: white;
height: 100%;
}
.SearchOpts
{
padding: 5px 5px 10px 5px;
color: black;
width: 300px;
border-bottom: solid lightgrey 1px;
height: 110px !important;
}
.NavOpts
{
padding: 5px 5px 6px 5px;
color: black;
width: 300px;
border-bottom: solid lightgrey 1px;
}
.NavOpts img {
display:inline-block;
margin: 0px 5px 0px 5px;
}
.IndexOpts
{
padding: 5px 5px 6px 5px;
color: black;
width: 300px;
border-bottom: solid lightgrey 1px;
}
.IndexItem
{
white-space: nowrap;
margin: 2px 2px 2px 2px;
}
.IndexSubItem
{
white-space: nowrap;
margin: 2px 2px 2px 12px;
}
.PaddedText
{
margin: 10px 10px 10px 10px;
}
+172
View File
@@ -0,0 +1,172 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<!-- The configuration and platform will be used to determine which
assemblies to include from solution and project documentation
sources -->
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{cb4d85f1-7390-40ee-b41f-a724bb8fddea}</ProjectGuid>
<SHFBSchemaVersion>1.9.5.0</SHFBSchemaVersion>
<!-- AssemblyName, Name, and RootNamespace are not used by SHFB but Visual
Studio adds them anyway -->
<AssemblyName>Documentation</AssemblyName>
<RootNamespace>Documentation</RootNamespace>
<Name>Documentation</Name>
<!-- SHFB properties -->
<FrameworkVersion>.NET Framework 4.5</FrameworkVersion>
<OutputPath>.\Output\</OutputPath>
<HtmlHelpName>UmbracoClassLibrary</HtmlHelpName>
<Language>en-US</Language>
<BuildAssemblerVerbosity>OnlyErrors</BuildAssemblerVerbosity>
<BuildLogFile>csharp-api-docs.log</BuildLogFile>
<HelpFileFormat>Website</HelpFileFormat>
<IndentHtml>True</IndentHtml>
<KeepLogFile>False</KeepLogFile>
<DisableCodeBlockComponent>False</DisableCodeBlockComponent>
<CppCommentsFixup>False</CppCommentsFixup>
<CleanIntermediates>True</CleanIntermediates>
<SyntaxFilters>CSharp</SyntaxFilters>
<SdkLinkTarget>Blank</SdkLinkTarget>
<RootNamespaceContainer>False</RootNamespaceContainer>
<PresentationStyle>VS2010</PresentationStyle>
<Preliminary>False</Preliminary>
<NamingMethod>Guid</NamingMethod>
<HelpTitle>Umbraco .Net Class Library</HelpTitle>
<ContentPlacement>AboveNamespaces</ContentPlacement>
<VisibleItems>Attributes, InheritedMembers, InheritedFrameworkMembers, Protected, SealedProtected</VisibleItems>
<ComponentConfigurations />
<DocumentationSources>
<DocumentationSource sourceFile="..\..\src\Umbraco.Core\Umbraco.Core.csproj" />
<DocumentationSource sourceFile="..\..\src\Umbraco.Core\bin\Release\Umbraco.Core.xml" />
<DocumentationSource sourceFile="..\..\src\Umbraco.Web\Umbraco.Web.csproj" />
<DocumentationSource sourceFile="..\..\src\Umbraco.Web\bin\Release\umbraco.xml" /></DocumentationSources>
<WebsiteSdkLinkType>None</WebsiteSdkLinkType>
<HtmlSdkLinkType>None</HtmlSdkLinkType>
<IncludeFavorites>False</IncludeFavorites>
<BinaryTOC>True</BinaryTOC>
<MissingTags>Summary, AutoDocumentCtors, AutoDocumentDispose</MissingTags>
<TransformComponentArguments>
<Argument Key="logoFile" Value="" />
<Argument Key="logoHeight" Value="" />
<Argument Key="logoWidth" Value="" />
<Argument Key="logoAltText" Value="" />
<Argument Key="logoPlacement" Value="left" />
<Argument Key="logoAlignment" Value="left" />
</TransformComponentArguments>
<ApiFilter>
<Filter entryType="Namespace" fullName="CookComputing.Blogger" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="CookComputing.MetaWeblog" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="dashboardUtilities" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="presentation.umbraco.webservices" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco" isExposed="False" xmlns="">
<Filter entryType="Class" fullName="umbraco.content" filterName="content" isExposed="True" />
<Filter entryType="Delegate" fullName="umbraco.content.ContentCacheDatabaseLoadXmlStringEventHandler" filterName="content.ContentCacheDatabaseLoadXmlStringEventHandler" isExposed="False" />
<Filter entryType="Delegate" fullName="umbraco.content.ContentCacheLoadNodeEventHandler" filterName="content.ContentCacheLoadNodeEventHandler" isExposed="False" />
<Filter entryType="Delegate" fullName="umbraco.content.DocumentCacheEventHandler" filterName="content.DocumentCacheEventHandler" isExposed="False" />
<Filter entryType="Delegate" fullName="umbraco.content.RefreshContentEventHandler" filterName="content.RefreshContentEventHandler" isExposed="False" />
<Filter entryType="Class" fullName="umbraco.ContentExtensions" filterName="ContentExtensions" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.ContentTypeExtensions" filterName="ContentTypeExtensions" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.item" filterName="item" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.library" filterName="library" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.macro" filterName="macro" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.MacroCacheContent" filterName="MacroCacheContent" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.MacroRenderingEventArgs" filterName="MacroRenderingEventArgs" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.MediaExtensions" filterName="MediaExtensions" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.MemberExtensions" filterName="MemberExtensions" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.page" filterName="page" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.PreValueExtensions" filterName="PreValueExtensions" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.RelationTypeExtensions" filterName="RelationTypeExtensions" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.template" filterName="template" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.UmbracoObjectTypeExtensions" filterName="UmbracoObjectTypeExtensions" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.uQuery" filterName="uQuery" isExposed="True" />
<Filter entryType="Interface" fullName="umbraco.uQuery.IGetProperty" filterName="uQuery.IGetProperty" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.uQuery.Members" filterName="uQuery.Members" isExposed="True" />
<Filter entryType="Enumeration" fullName="umbraco.uQuery.UmbracoObjectType" filterName="uQuery.UmbracoObjectType" isExposed="True" />
</Filter>
<Filter entryType="Namespace" fullName="umbraco.cms.presentation" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.create.controls" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.developer" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.developer.RelationTypes" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.developer.RelationTypes.TreeMenu" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.members" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.settings" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.settings.modal" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.settings.scripts" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.settings.stylesheet" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.cms.presentation.user" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.controls" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.controls.GenericProperties" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.controls.Images" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.controls.Tree" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.developer" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.dialogs" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.js" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.layoutControls" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.NodeFactory" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.actions" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.channels" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.channels.businesslogic" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.create" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.developer.packages" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.dialogs" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.masterpages" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.members" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.nodeFactory" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.org.umbraco.update" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.plugins.tinymce3" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.preview" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.Search" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.settings" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.templateControls" isExposed="False" xmlns="">
<Filter entryType="Class" fullName="umbraco.presentation.templateControls.Item" filterName="Item" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.presentation.templateControls.ItemRenderer" filterName="ItemRenderer" isExposed="True" />
<Filter entryType="Class" fullName="umbraco.presentation.templateControls.Macro" filterName="Macro" isExposed="True" />
<Filter entryType="Enumeration" fullName="umbraco.presentation.templateControls.Macro.RenderEvents" filterName="Macro.RenderEvents" isExposed="False" />
</Filter>
<Filter entryType="Namespace" fullName="umbraco.presentation.tinymce3" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.translation" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.channels" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.controls" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.create" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.developer.Xslt" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.dialogs" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.masterpages" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.members" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.plugins.tinymce3" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.Search" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.translation" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco.webservices" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.umbraco_client.tinymce3.plugins.spellchecker" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.urlRewriter" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.Web.UI" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.presentation.webservices" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.scripting" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.settings" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="Umbraco.Web.org.umbraco.our" isExposed="False" xmlns="" />
<Filter entryType="Namespace" fullName="umbraco.webservices" isExposed="False" xmlns="" /></ApiFilter>
</PropertyGroup>
<!-- There are no properties for these groups. AnyCPU needs to appear in
order for Visual Studio to perform the build. The others are optional
common platform types that may appear. -->
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Win32' ">
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Win32' ">
</PropertyGroup>
<!-- Import the SHFB build targets -->
<Import Project="$(SHFBROOT)\SandcastleHelpFileBuilder.targets" />
</Project>
+2 -2
View File
@@ -1,6 +1,6 @@
@ECHO OFF
SET release=7.0.4
SET comment=
SET release=7.1.0
SET comment=beta
SET version=%release%
IF [%comment%] EQU [] (SET version=%release%) ELSE (SET version=%release%-%comment%)
+27
View File
@@ -0,0 +1,27 @@
##We cannot continue if sandcastle is not installed determined by env variable: SHFBROOT
if (-not (Test-Path Env:\SHFBROOT))
{
throw "The docs cannot be build, install Sandcastle help file builder"
}
$PSScriptFilePath = (Get-Item $MyInvocation.MyCommand.Path).FullName
$BuildRoot = Split-Path -Path $PSScriptFilePath -Parent
$OutputPath = Join-Path -Path $BuildRoot -ChildPath "ApiDocs\Output"
$ProjFile = Join-Path -Path $BuildRoot -ChildPath "ApiDocs\csharp-api-docs.shfbproj"
"Building docs with project file: $ProjFile"
$MSBuild = "$Env:SYSTEMROOT\Microsoft.NET\Framework\v4.0.30319\msbuild.exe"
# build it!
& $MSBuild "$ProjFile"
# remove files left over
Remove-Item $BuildRoot\* -include csharp-api-docs.shfbproj_*
# copy our custom styles in
Copy-Item $BuildRoot\ApiDocs\TOC.css $OutputPath\TOC.css
""
"Done!"
-1
View File
@@ -37,7 +37,6 @@
<file src="..\_BuildOutput\WebApp\App_Data\**" target="UmbracoFiles\App_Data" />
<file src="..\_BuildOutput\WebApp\App_Plugins\**" target="UmbracoFiles\App_Plugins" />
<file src="..\_BuildOutput\WebApp\config\splashes\**" target="UmbracoFiles\config\splashes" />
<file src="..\_BuildOutput\WebApp\install\**" target="UmbracoFiles\install" />
<file src="..\_BuildOutput\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
<file src="..\_BuildOutput\WebApp\umbraco_client\**" target="UmbracoFiles\umbraco_client" />
<file src="..\_BuildOutput\WebApp\Global.asax" target="UmbracoFiles\Global.asax" />
+7
View File
@@ -42,6 +42,13 @@ namespace SqlCE4Umbraco
{
var sqlCeEngine = new SqlCeEngine(ConnectionString);
sqlCeEngine.CreateDatabase();
// SD: Pretty sure this should be in a using clause but i don't want to cause unknown side-effects here
// since it's been like this for quite some time
//using (var sqlCeEngine = new SqlCeEngine(ConnectionString))
//{
// sqlCeEngine.CreateDatabase();
//}
}
}
+3
View File
@@ -165,6 +165,9 @@ namespace Umbraco.Core
/// </remarks>
internal string OriginalRequestUrl { get; set; }
/// <summary>
/// Checks if the version configured matches the assembly version
/// </summary>
private bool Configured
{
get
+10
View File
@@ -160,5 +160,15 @@ namespace Umbraco.Core
{
return new Attempt<T>(condition, result, null);
}
/// <summary>
/// Implicity operator to check if the attempt was successful without having to access the 'success' property
/// </summary>
/// <param name="a"></param>
/// <returns></returns>
public static implicit operator bool(Attempt<T> a)
{
return a.Success;
}
}
}
+7 -1
View File
@@ -1,3 +1,5 @@
using System;
namespace Umbraco.Core.Cache
{
@@ -9,6 +11,7 @@ namespace Umbraco.Core.Cache
public const string ApplicationTreeCacheKey = "ApplicationTreeCache";
public const string ApplicationsCacheKey = "ApplicationCache";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
public const string UserTypeCacheKey = "UserTypeCache";
public const string ContentItemCacheKey = "contentItem";
@@ -24,13 +27,16 @@ namespace Umbraco.Core.Cache
public const string MemberLibraryCacheKey = "UL_GetMember";
public const string MemberBusinessLogicCacheKey = "MemberCacheItem_";
public const string TemplateFrontEndCacheKey = "template";
public const string TemplateBusinessLogicCacheKey = "UmbracoTemplateCache";
public const string UserContextCacheKey = "UmbracoUserContext";
public const string UserContextTimeoutCacheKey = "UmbracoUserContextTimeout";
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
public const string UserCacheKey = "UmbracoUser";
public const string UserPermissionsCacheKey = "UmbracoUserPermissions";
public const string ContentTypeCacheKey = "UmbracoContentType";
+1 -1
View File
@@ -27,7 +27,7 @@ namespace Umbraco.Core
/// <summary>
/// Gets the <see cref="ICacheRefresher"/> implementations.
/// </summary>
public IEnumerable<ICacheRefresher> CacheResolvers
public IEnumerable<ICacheRefresher> CacheRefreshers
{
get
{
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Configuration
}
/// <summary>
/// Increases the version number in ClientDependency.config by 1
/// Changes the version number in ClientDependency.config to a random value to avoid stale caches
/// </summary>
internal bool IncreaseVersionNumber()
{
@@ -28,9 +28,9 @@ namespace Umbraco.Core.Configuration
var versionAttribute = clientDependencyConfigXml.Root.Attribute("version");
int oldVersion;
int.TryParse(versionAttribute.Value, out oldVersion);
var newVersion = oldVersion + 100;
//Set the new version to the hashcode of now
var oldVersion = versionAttribute.Value;
var newVersion = Math.Abs(DateTime.UtcNow.GetHashCode());
versionAttribute.SetValue(newVersion);
clientDependencyConfigXml.Save(_fileName, SaveOptions.DisableFormatting);
@@ -6,10 +6,13 @@ using System.Web;
using System.Web.Configuration;
using System.Web.Hosting;
using System.Web.Routing;
using System.Web.Security;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Security;
namespace Umbraco.Core.Configuration
{
@@ -38,7 +41,7 @@ namespace Umbraco.Core.Configuration
private static string _reservedUrls;
//ensure the built on (non-changeable) reserved paths are there at all times
private const string StaticReservedPaths = "~/app_plugins/,~/install/,";
private const string StaticReservedUrls = "~/config/splashes/booting.aspx,~/install/default.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd,";
private const string StaticReservedUrls = "~/config/splashes/booting.aspx,~/config/splashes/noNodes.aspx,~/VSEnterpriseHelper.axd,";
#endregion
@@ -259,7 +262,38 @@ namespace Umbraco.Core.Configuration
SaveSetting("umbracoConfigurationStatus", value);
}
}
/// <summary>
/// Gets or sets the Umbraco members membership providers' useLegacyEncoding state. This will return a boolean
/// </summary>
/// <value>The useLegacyEncoding status.</value>
public static bool UmbracoMembershipProviderLegacyEncoding
{
get
{
return IsConfiguredMembershipProviderUsingLegacyEncoding(Constants.Conventions.Member.UmbracoMemberProviderName);
}
set
{
SetMembershipProvidersLegacyEncoding(Constants.Conventions.Member.UmbracoMemberProviderName, value);
}
}
/// <summary>
/// Gets or sets the Umbraco users membership providers' useLegacyEncoding state. This will return a boolean
/// </summary>
/// <value>The useLegacyEncoding status.</value>
public static bool UmbracoUsersMembershipProviderLegacyEncoding
{
get
{
return IsConfiguredMembershipProviderUsingLegacyEncoding(Constants.Conventions.User.UmbracoUsersProviderName);
}
set
{
SetMembershipProvidersLegacyEncoding(Constants.Conventions.User.UmbracoUsersProviderName, value);
}
}
/// <summary>
/// Saves a setting into the configuration file.
@@ -301,7 +335,51 @@ namespace Umbraco.Core.Configuration
setting.Remove();
xml.Save(fileName, SaveOptions.DisableFormatting);
ConfigurationManager.RefreshSection("appSettings");
}
}
private static void SetMembershipProvidersLegacyEncoding(string providerName, bool useLegacyEncoding)
{
//check if this can even be configured.
var membershipProvider = Membership.Providers[providerName] as MembershipProviderBase;
if (membershipProvider == null)
{
return;
}
if (membershipProvider.GetType().Namespace == "umbraco.providers.members")
{
//its the legacy one, this cannot be changed
return;
}
var webConfigFilename = IOHelper.MapPath(string.Format("{0}/web.config", SystemDirectories.Root));
var webConfigXml = XDocument.Load(webConfigFilename, LoadOptions.PreserveWhitespace);
var membershipConfigs = webConfigXml.XPathSelectElements("configuration/system.web/membership/providers/add").ToList();
if (membershipConfigs.Any() == false)
return;
var provider = membershipConfigs.SingleOrDefault(c => c.Attribute("name") != null && c.Attribute("name").Value == providerName);
if (provider == null)
return;
provider.SetAttributeValue("useLegacyEncoding", useLegacyEncoding);
webConfigXml.Save(webConfigFilename, SaveOptions.DisableFormatting);
}
private static bool IsConfiguredMembershipProviderUsingLegacyEncoding(string providerName)
{
//check if this can even be configured.
var membershipProvider = Membership.Providers[providerName] as MembershipProviderBase;
if (membershipProvider == null)
{
return false;
}
return membershipProvider.UseLegacyEncoding;
}
/// <summary>
@@ -1,10 +1,10 @@
using System.Collections.Generic;
using System.Configuration;
using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class ContentImagingElement : ConfigurationElement
{
[ConfigurationProperty("imageFileTypes")]
internal CommaDelimitedConfigurationElement ImageFileTypes
{
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
return new OptionalInnerTextConfigurationElement<string>(
(InnerTextConfigurationElement<string>)this["DefaultBackofficeProvider"],
//set the default
"UsersMembershipProvider");
Constants.Conventions.User.UmbracoUsersProviderName);
}
}
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.0.4");
private static readonly Version Version = new Version("7.1.0");
/// <summary>
/// Gets the current version of Umbraco.
@@ -23,7 +23,7 @@ namespace Umbraco.Core.Configuration
/// Gets the version comment (like beta or RC).
/// </summary>
/// <value>The version comment.</value>
public static string CurrentComment { get { return ""; } }
public static string CurrentComment { get { return "beta"; } }
// Get the version of the umbraco.dll by looking at a class in that dll
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
+35 -21
View File
@@ -85,7 +85,7 @@ namespace Umbraco.Core
/// <summary>
/// MediaType alias for a folder.
/// </summary>
/// </summary>
public const string Folder = "Folder";
/// <summary>
@@ -94,9 +94,18 @@ namespace Umbraco.Core
public const string Image = "Image";
}
/// <summary>
/// Constants for Umbraco user
/// </summary>
public static class User
{
public static readonly string UmbracoUsersProviderName = "UsersMembershipProvider";
}
/// <summary>
/// Constants for Umbraco Member property aliases.
/// </summary>
/// </summary>
public static class Member
{
/// <summary>
@@ -111,73 +120,78 @@ namespace Umbraco.Core
/// <summary>
/// Property alias for a Members Password Question
/// </summary>
public const string PasswordQuestion = "umbracoPasswordRetrievalQuestionPropertyTypeAlias";
public const string PasswordQuestion = "umbracoMemberPasswordRetrievalQuestion";
public const string PasswordQuestionLabel = "Password Question";
/// <summary>
/// Property alias for Members Password Answer
/// </summary>
public const string PasswordAnswer = "umbracoPasswordRetrievalAnswerPropertyTypeAlias";
public const string PasswordAnswer = "umbracoMemberPasswordRetrievalAnswer";
public const string PasswordAnswerLabel = "Password Answer";
/// <summary>
/// Property alias for the Comments on a Member
/// </summary>
public const string Comments = "umbracoCommentPropertyTypeAlias";
public const string Comments = "umbracoMemberComments";
public const string CommentsLabel = "Comments";
/// <summary>
/// Property alias for the Approved boolean of a Member
/// </summary>
public const string IsApproved = "umbracoApprovePropertyTypeAlias";
public const string IsApproved = "umbracoMemberApproved";
public const string IsApprovedLabel = "Is Approved";
/// <summary>
/// Property alias for the Locked out boolean of a Member
/// </summary>
public const string IsLockedOut = "umbracoLockPropertyTypeAlias";
public const string IsLockedOut = "umbracoMemberLockedOut";
public const string IsLockedOutLabel = "Is Locked Out";
/// <summary>
/// Property alias for the last date the Member logged in
/// </summary>
public const string LastLoginDate = "umbracoLastLoginPropertyTypeAlias";
public const string LastLoginDate = "umbracoMemberLastLogin";
public const string LastLoginDateLabel = "Last Login Date";
/// <summary>
/// Property alias for the last date a Member changed its password
/// </summary>
public const string LastPasswordChangeDate = "umbracoMemberLastPasswordChange";
public const string LastPasswordChangeDate = "umbracoMemberLastPasswordChangeDate";
public const string LastPasswordChangeDateLabel = "Last Password Change Date";
/// <summary>
/// Property alias for the last date a Member was locked out
/// </summary>
public const string LastLockoutDate = "umbracoMemberLastLockout";
public const string LastLockoutDate = "umbracoMemberLastLockoutDate";
public const string LastLockoutDateLabel = "Last Lockout Date";
/// <summary>
/// Property alias for the number of failed login attemps
/// </summary>
public const string FailedPasswordAttempts = "umbracoFailedPasswordAttemptsPropertyTypeAlias";
public const string FailedPasswordAttempts = "umbracoMemberFailedPasswordAttempts";
public const string FailedPasswordAttemptsLabel = "Failed Password Attempts";
/// <summary>
/// Group name to put the membership properties on
/// </summary>
internal const string StandardPropertiesGroupName = "Membership";
internal static Dictionary<string, PropertyType> GetStandardPropertyTypeStubs()
{
return new Dictionary<string, PropertyType>
{
{
Comments,
new PropertyType(PropertyEditors.TextboxMultipleAlias, DataTypeDatabaseType.Ntext)
new PropertyType(PropertyEditors.TextboxMultipleAlias, DataTypeDatabaseType.Ntext, true)
{
Alias = Comments,
Name = CommentsLabel
@@ -185,7 +199,7 @@ namespace Umbraco.Core
},
{
FailedPasswordAttempts,
new PropertyType(PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer)
new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Integer, true)
{
Alias = FailedPasswordAttempts,
Name = FailedPasswordAttemptsLabel
@@ -193,7 +207,7 @@ namespace Umbraco.Core
},
{
IsApproved,
new PropertyType(PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer)
new PropertyType(PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer, true)
{
Alias = IsApproved,
Name = IsApprovedLabel
@@ -201,7 +215,7 @@ namespace Umbraco.Core
},
{
IsLockedOut,
new PropertyType(PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer)
new PropertyType(PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer, true)
{
Alias = IsLockedOut,
Name = IsLockedOutLabel
@@ -209,7 +223,7 @@ namespace Umbraco.Core
},
{
LastLockoutDate,
new PropertyType(PropertyEditors.DateAlias, DataTypeDatabaseType.Date)
new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, true)
{
Alias = LastLockoutDate,
Name = LastLockoutDateLabel
@@ -217,7 +231,7 @@ namespace Umbraco.Core
},
{
LastLoginDate,
new PropertyType(PropertyEditors.DateAlias, DataTypeDatabaseType.Date)
new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, true)
{
Alias = LastLoginDate,
Name = LastLoginDateLabel
@@ -225,7 +239,7 @@ namespace Umbraco.Core
},
{
LastPasswordChangeDate,
new PropertyType(PropertyEditors.DateAlias, DataTypeDatabaseType.Date)
new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date, true)
{
Alias = LastPasswordChangeDate,
Name = LastPasswordChangeDateLabel
@@ -233,7 +247,7 @@ namespace Umbraco.Core
},
{
PasswordAnswer,
new PropertyType(PropertyEditors.TextboxAlias, DataTypeDatabaseType.Nvarchar)
new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Nvarchar, true)
{
Alias = PasswordAnswer,
Name = PasswordAnswerLabel
@@ -241,7 +255,7 @@ namespace Umbraco.Core
},
{
PasswordQuestion,
new PropertyType(PropertyEditors.TextboxAlias, DataTypeDatabaseType.Nvarchar)
new PropertyType(PropertyEditors.NoEditAlias, DataTypeDatabaseType.Nvarchar, true)
{
Alias = PasswordQuestion,
Name = PasswordQuestionLabel
@@ -259,7 +273,7 @@ namespace Umbraco.Core
/// <summary>
/// MemberType alias for default member type.
/// </summary>
public const string Member = "Member";
public const string DefaultAlias = "Member";
public const string SystemDefaultProtectType = "_umbracoSystemDefaultProtectType";
}
@@ -139,7 +139,7 @@ namespace Umbraco.Core
///// <summary>
///// Alias for the Image Cropper datatype.
///// </summary>
//public const string ImageCropperAlias = "Umbraco.ImageCropper";
public const string ImageCropperAlias = "Umbraco.ImageCropper";
/// <summary>
/// Guid for the Integer datatype.
+46
View File
@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
namespace Umbraco.Core
{
internal static class ControlExtensions
{
/// <summary>
/// Recursively finds a control with the specified identifier.
/// </summary>
/// <typeparam name="T">
/// The type of control to be found.
/// </typeparam>
/// <param name="parent">
/// The parent control from which the search will start.
/// </param>
/// <param name="id">
/// The identifier of the control to be found.
/// </param>
/// <returns>
/// The control with the specified identifier, otherwise <see langword="null"/> if the control
/// is not found.
/// </returns>
public static T FindControlRecursive<T>(this Control parent, string id) where T : Control
{
if ((parent is T) && (parent.ID == id))
{
return (T)parent;
}
foreach (Control control in parent.Controls)
{
var foundControl = FindControlRecursive<T>(control, id);
if (foundControl != null)
{
return foundControl;
}
}
return default(T);
}
}
}
+1 -1
View File
@@ -287,7 +287,7 @@ namespace Umbraco.Core
() => PluginManager.Current.ResolveAssignedMapperTypes());
RepositoryResolver.Current = new RepositoryResolver(
new RepositoryFactory());
new RepositoryFactory(ApplicationCache));
SqlSyntaxProvidersResolver.Current = new SqlSyntaxProvidersResolver(
new[] { typeof(MySqlSyntaxProvider), typeof(SqlCeSyntaxProvider), typeof(SqlServerSyntaxProvider) })
+66 -19
View File
@@ -113,8 +113,8 @@ namespace Umbraco.Core
public void ConfigureEmbeddedDatabaseConnection()
{
const string providerName = "System.Data.SqlServerCe.4.0";
const string connectionString = @"Data Source=|DataDirectory|\Umbraco.sdf;Flush Interval=1;";
var connectionString = GetEmbeddedDatabaseConnectionString();
SaveConnectionString(connectionString, providerName);
var path = Path.Combine(GlobalSettings.FullpathToRoot, "App_Data", "Umbraco.sdf");
@@ -122,11 +122,23 @@ namespace Umbraco.Core
{
var engine = new SqlCeEngine(connectionString);
engine.CreateDatabase();
// SD: Pretty sure this should be in a using clause but i don't want to cause unknown side-effects here
// since it's been like this for quite some time
//using (var engine = new SqlCeEngine(connectionString))
//{
// engine.CreateDatabase();
//}
}
Initialize(providerName);
}
public string GetEmbeddedDatabaseConnectionString()
{
return @"Data Source=|DataDirectory|\Umbraco.sdf;Flush Interval=1;";
}
/// <summary>
/// Configure a ConnectionString that has been entered manually.
/// </summary>
@@ -149,27 +161,29 @@ namespace Umbraco.Core
/// <param name="password">Database Password</param>
/// <param name="databaseProvider">Type of the provider to be used (Sql, Sql Azure, Sql Ce, MySql)</param>
public void ConfigureDatabaseConnection(string server, string databaseName, string user, string password, string databaseProvider)
{
string connectionString;
string providerName = "System.Data.SqlClient";
if (databaseProvider.ToLower().Contains("mysql"))
{
providerName = "MySql.Data.MySqlClient";
connectionString = string.Format("Server={0}; Database={1};Uid={2};Pwd={3}", server, databaseName, user, password);
}
else if (databaseProvider.ToLower().Contains("azure"))
{
connectionString = BuildAzureConnectionString(server, databaseName, user, password);
}
else
{
connectionString = string.Format("server={0};database={1};user id={2};password={3}", server, databaseName, user, password);
}
{
string providerName;
var connectionString = GetDatabaseConnectionString(server, databaseName, user, password, databaseProvider, out providerName);
SaveConnectionString(connectionString, providerName);
Initialize(providerName);
}
public string GetDatabaseConnectionString(string server, string databaseName, string user, string password, string databaseProvider, out string providerName)
{
providerName = "System.Data.SqlClient";
if (databaseProvider.ToLower().Contains("mysql"))
{
providerName = "MySql.Data.MySqlClient";
return string.Format("Server={0}; Database={1};Uid={2};Pwd={3}", server, databaseName, user, password);
}
if (databaseProvider.ToLower().Contains("azure"))
{
return BuildAzureConnectionString(server, databaseName, user, password);
}
return string.Format("server={0};database={1};user id={2};password={3}", server, databaseName, user, password);
}
/// <summary>
/// Configures a ConnectionString for the Umbraco database that uses Microsoft SQL Server integrated security.
/// </summary>
@@ -178,12 +192,16 @@ namespace Umbraco.Core
public void ConfigureIntegratedSecurityDatabaseConnection(string server, string databaseName)
{
const string providerName = "System.Data.SqlClient";
string connectionString = String.Format("Server={0};Database={1};Integrated Security=true", server, databaseName);
var connectionString = GetIntegratedSecurityDatabaseConnectionString(server, databaseName);
SaveConnectionString(connectionString, providerName);
Initialize(providerName);
}
public string GetIntegratedSecurityDatabaseConnectionString(string server, string databaseName)
{
return String.Format("Server={0};Database={1};Integrated Security=true", server, databaseName);
}
internal string BuildAzureConnectionString(string server, string databaseName, string user, string password)
{
if (server.Contains(".") && ServerStartsWithTcp(server) == false)
@@ -597,5 +615,34 @@ namespace Umbraco.Core
public bool Success { get; set; }
public string Percentage { get; set; }
}
internal bool IsConnectionStringConfigured(ConnectionStringSettings databaseSettings)
{
var dbIsSqlCe = false;
if (databaseSettings != null && databaseSettings.ProviderName != null)
dbIsSqlCe = databaseSettings.ProviderName == "System.Data.SqlServerCe.4.0";
var sqlCeDatabaseExists = false;
if (dbIsSqlCe)
{
var parts = databaseSettings.ConnectionString.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
var dataSourcePart = parts.FirstOrDefault(x => x.InvariantStartsWith("Data Source="));
if (dataSourcePart != null)
{
var datasource = dataSourcePart.Replace("|DataDirectory|", AppDomain.CurrentDomain.GetData("DataDirectory").ToString());
var filePath = datasource.Replace("Data Source=", string.Empty);
sqlCeDatabaseExists = File.Exists(filePath);
}
}
// Either the connection details are not fully specified or it's a SQL CE database that doesn't exist yet
if (databaseSettings == null
|| string.IsNullOrWhiteSpace(databaseSettings.ConnectionString) || string.IsNullOrWhiteSpace(databaseSettings.ProviderName)
|| (dbIsSqlCe && sqlCeDatabaseExists == false))
{
return false;
}
return true;
}
}
}
+25
View File
@@ -18,5 +18,30 @@ namespace Umbraco.Core
return dt.ToString("yyyy-MM-dd HH:mm:ss");
}
public static DateTime TruncateTo(this DateTime dt, DateTruncate truncateTo)
{
if (truncateTo == DateTruncate.Year)
return new DateTime(dt.Year, 0, 0);
if (truncateTo == DateTruncate.Month)
return new DateTime(dt.Year, dt.Month, 0);
if (truncateTo == DateTruncate.Day)
return new DateTime(dt.Year, dt.Month, dt.Day);
if (truncateTo == DateTruncate.Hour)
return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, 0, 0);
if (truncateTo == DateTruncate.Minute)
return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, 0);
return new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second);
}
public enum DateTruncate
{
Year,
Month,
Day,
Hour,
Minute,
Second
}
}
}
+19
View File
@@ -15,6 +15,25 @@ namespace Umbraco.Core
///</summary>
internal static class DictionaryExtensions
{
/// <summary>
/// Method to Get a value by the key. If the key doesn't exist it will create a new TVal object for the key and return it.
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TVal"></typeparam>
/// <param name="dict"></param>
/// <param name="key"></param>
/// <returns></returns>
public static TVal GetOrCreate<TKey, TVal>(this IDictionary<TKey, TVal> dict, TKey key)
where TVal : class, new()
{
if (dict.ContainsKey(key) == false)
{
dict.Add(key, new TVal());
}
return dict[key];
}
/// <summary>
/// Updates an item with the specified key with the specified value
/// </summary>
+2 -4
View File
@@ -306,10 +306,8 @@ namespace Umbraco.Core.Models
/// <returns><see cref="Property"/> Value as a <see cref="TPassType"/></returns>
public virtual TPassType GetValue<TPassType>(string propertyTypeAlias)
{
if (Properties[propertyTypeAlias].Value is TPassType)
return (TPassType)Properties[propertyTypeAlias].Value;
return (TPassType)Convert.ChangeType(Properties[propertyTypeAlias].Value, typeof(TPassType));
var convertAttempt = Properties[propertyTypeAlias].Value.TryConvertTo<TPassType>();
return convertAttempt.Success ? convertAttempt.Result : default(TPassType);
}
/// <summary>
@@ -26,6 +26,20 @@ namespace Umbraco.Core.Models
{
#region IContent
/// <summary>
/// Returns true if this entity was just published as part of a recent save operation (i.e. it wasn't previously published)
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
/// <remarks>
/// This is helpful for determining if the published event will execute during the saved event for a content item.
/// </remarks>
internal static bool JustPublished(this IContent entity)
{
var dirty = (IRememberBeingDirty)entity;
return dirty.WasPropertyDirty("Published") && entity.Published;
}
/// <summary>
/// Determines if a new version should be created
/// </summary>
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
public static class EntityExtensions
{
/// <summary>
/// Returns true if this entity has just been created and persisted to the data store
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
/// <remarks>
/// This is useful when handling events to determine if an entity is a brand new entity or was
/// already existing.
/// </remarks>
public static bool IsNewEntity(this IEntity entity)
{
var dirty = (IRememberBeingDirty)entity;
return dirty.WasPropertyDirty("Id");
}
}
}
+26
View File
@@ -0,0 +1,26 @@
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a member type
/// </summary>
public interface IMemberGroup : IAggregateRoot
{
/// <summary>
/// The name of the member group
/// </summary>
string Name { get; set; }
/// <summary>
/// Profile of the user who created this Entity
/// </summary>
int CreatorId { get; set; }
/// <summary>
/// Some entities may expose additional data that other's might not, this custom data will be available in this collection
/// </summary>
IDictionary<string, object> AdditionalData { get; }
}
}
+6
View File
@@ -10,5 +10,11 @@
/// </summary>
/// <returns><see cref="RenderingEngine"/></returns>
RenderingEngine GetTypeOfRenderingEngine();
/// <summary>
/// Set the mastertemplate
/// </summary>
/// <param name="masterTemplate"></param>
void SetMasterTemplate(ITemplate masterTemplate);
}
}
+184 -51
View File
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Models
{
@@ -29,8 +31,10 @@ namespace Umbraco.Core.Models
: base(name, -1, contentType, new PropertyCollection())
{
_contentType = contentType;
IsApproved = true;
}
//TODO: Should we just get rid of this one? no reason to have a level set.
internal Member(string name, string email, string username, string password, int parentId, IMemberType contentType)
: base(name, parentId, contentType, new PropertyCollection())
{
@@ -40,6 +44,7 @@ namespace Umbraco.Core.Models
_email = email;
_username = username;
_password = password;
IsApproved = true;
}
public Member(string name, string email, string username, string password, IMemberType contentType)
@@ -51,6 +56,7 @@ namespace Umbraco.Core.Models
_email = email;
_username = username;
_password = password;
IsApproved = true;
}
//public Member(string name, string email, string username, string password, IContentBase parent, IMemberType contentType)
@@ -136,7 +142,7 @@ namespace Umbraco.Core.Models
/// Gets or sets the Password Question
/// </summary>
/// <remarks>
/// Alias: umbracoPasswordRetrievalQuestionPropertyTypeAlias
/// Alias: umbracoMemberPasswordRetrievalQuestion
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
@@ -144,12 +150,19 @@ namespace Umbraco.Core.Models
{
get
{
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.PasswordQuestion, "PasswordQuestion", default(string));
if (a.Success == false) return a.Result;
return Properties[Constants.Conventions.Member.PasswordQuestion].Value == null
? string.Empty
: Properties[Constants.Conventions.Member.PasswordQuestion].Value.ToString();
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.PasswordQuestion,
"PasswordQuestion") == false) return;
Properties[Constants.Conventions.Member.PasswordQuestion].Value = value;
}
}
@@ -158,7 +171,7 @@ namespace Umbraco.Core.Models
/// Gets or sets the Password Answer
/// </summary>
/// <remarks>
/// Alias: umbracoPasswordRetrievalAnswerPropertyTypeAlias
/// Alias: umbracoMemberPasswordRetrievalAnswer
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
@@ -166,12 +179,19 @@ namespace Umbraco.Core.Models
{
get
{
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.PasswordAnswer, "PasswordAnswer", default(string));
if (a.Success == false) return a.Result;
return Properties[Constants.Conventions.Member.PasswordAnswer].Value == null
? string.Empty
: Properties[Constants.Conventions.Member.PasswordAnswer].Value.ToString();
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.PasswordAnswer,
"PasswordAnswer") == false) return;
Properties[Constants.Conventions.Member.PasswordAnswer].Value = value;
}
}
@@ -180,7 +200,7 @@ namespace Umbraco.Core.Models
/// Gets or set the comments for the member
/// </summary>
/// <remarks>
/// Alias: umbracoCommentPropertyTypeAlias
/// Alias: umbracoMemberComments
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
@@ -188,12 +208,19 @@ namespace Umbraco.Core.Models
{
get
{
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.Comments, "Comments", default(string));
if (a.Success == false) return a.Result;
return Properties[Constants.Conventions.Member.Comments].Value == null
? string.Empty
: Properties[Constants.Conventions.Member.Comments].Value.ToString();
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.Comments,
"Comments") == false) return;
Properties[Constants.Conventions.Member.Comments].Value = value;
}
}
@@ -202,7 +229,7 @@ namespace Umbraco.Core.Models
/// Gets or sets a boolean indicating whether the Member is approved
/// </summary>
/// <remarks>
/// Alias: umbracoApprovePropertyTypeAlias
/// Alias: umbracoMemberApproved
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
@@ -210,17 +237,25 @@ namespace Umbraco.Core.Models
{
get
{
if (Properties[Constants.Conventions.Member.IsApproved].Value == null)
return default(bool);
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.IsApproved, "IsApproved",
//This is the default value if the prop is not found
true);
if (a.Success == false) return a.Result;
if (Properties[Constants.Conventions.Member.IsApproved].Value is bool)
return (bool)Properties[Constants.Conventions.Member.IsApproved].Value;
//TODO: Use TryConvertTo<T> instead
return (bool)Convert.ChangeType(Properties[Constants.Conventions.Member.IsApproved].Value, typeof(bool));
var tryConvert = Properties[Constants.Conventions.Member.IsApproved].Value.TryConvertTo<bool>();
if (tryConvert.Success)
{
return tryConvert.Result;
}
//if the property exists but it cannot be converted, we will assume true
return true;
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.IsApproved,
"IsApproved") == false) return;
Properties[Constants.Conventions.Member.IsApproved].Value = value;
}
}
@@ -229,7 +264,7 @@ namespace Umbraco.Core.Models
/// Gets or sets a boolean indicating whether the Member is locked out
/// </summary>
/// <remarks>
/// Alias: umbracoLockPropertyTypeAlias
/// Alias: umbracoMemberLockedOut
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
@@ -237,17 +272,23 @@ namespace Umbraco.Core.Models
{
get
{
if (Properties[Constants.Conventions.Member.IsLockedOut].Value == null)
return default(bool);
if (Properties[Constants.Conventions.Member.IsLockedOut].Value is bool)
return (bool)Properties[Constants.Conventions.Member.IsLockedOut].Value;
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.IsLockedOut, "IsLockedOut", false);
if (a.Success == false) return a.Result;
var tryConvert = Properties[Constants.Conventions.Member.IsLockedOut].Value.TryConvertTo<bool>();
if (tryConvert.Success)
{
return tryConvert.Result;
}
return false;
//TODO: Use TryConvertTo<T> instead
return (bool)Convert.ChangeType(Properties[Constants.Conventions.Member.IsLockedOut].Value, typeof(bool));
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.IsLockedOut,
"IsLockedOut") == false) return;
Properties[Constants.Conventions.Member.IsLockedOut].Value = value;
}
}
@@ -256,7 +297,7 @@ namespace Umbraco.Core.Models
/// Gets or sets the date for last login
/// </summary>
/// <remarks>
/// Alias: umbracoLastLoginPropertyTypeAlias
/// Alias: umbracoMemberLastLogin
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
@@ -264,17 +305,23 @@ namespace Umbraco.Core.Models
{
get
{
if (Properties[Constants.Conventions.Member.LastLoginDate].Value == null)
return default(DateTime);
if (Properties[Constants.Conventions.Member.LastLoginDate].Value is DateTime)
return (DateTime)Properties[Constants.Conventions.Member.LastLoginDate].Value;
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.LastLoginDate, "LastLoginDate", default(DateTime));
if (a.Success == false) return a.Result;
var tryConvert = Properties[Constants.Conventions.Member.LastLoginDate].Value.TryConvertTo<DateTime>();
if (tryConvert.Success)
{
return tryConvert.Result;
}
return default(DateTime);
//TODO: Use TryConvertTo<T> instead
return (DateTime)Convert.ChangeType(Properties[Constants.Conventions.Member.LastLoginDate].Value, typeof(DateTime));
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.LastLoginDate,
"LastLoginDate") == false) return;
Properties[Constants.Conventions.Member.LastLoginDate].Value = value;
}
}
@@ -283,7 +330,7 @@ namespace Umbraco.Core.Models
/// Gest or sets the date for last password change
/// </summary>
/// <remarks>
/// Alias: umbracoMemberLastPasswordChange
/// Alias: umbracoMemberLastPasswordChangeDate
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
@@ -291,17 +338,23 @@ namespace Umbraco.Core.Models
{
get
{
if (Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value == null)
return default(DateTime);
if (Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value is DateTime)
return (DateTime)Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value;
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.LastPasswordChangeDate, "LastPasswordChangeDate", default(DateTime));
if (a.Success == false) return a.Result;
var tryConvert = Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value.TryConvertTo<DateTime>();
if (tryConvert.Success)
{
return tryConvert.Result;
}
return default(DateTime);
//TODO: Use TryConvertTo<T> instead
return (DateTime)Convert.ChangeType(Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value, typeof(DateTime));
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.LastPasswordChangeDate,
"LastPasswordChangeDate") == false) return;
Properties[Constants.Conventions.Member.LastPasswordChangeDate].Value = value;
}
}
@@ -310,7 +363,7 @@ namespace Umbraco.Core.Models
/// Gets or sets the date for when Member was locked out
/// </summary>
/// <remarks>
/// Alias: umbracoMemberLastLockout
/// Alias: umbracoMemberLastLockoutDate
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
@@ -318,17 +371,23 @@ namespace Umbraco.Core.Models
{
get
{
if (Properties[Constants.Conventions.Member.LastLockoutDate].Value == null)
return default(DateTime);
if (Properties[Constants.Conventions.Member.LastLockoutDate].Value is DateTime)
return (DateTime)Properties[Constants.Conventions.Member.LastLockoutDate].Value;
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.LastLockoutDate, "LastLockoutDate", default(DateTime));
if (a.Success == false) return a.Result;
var tryConvert = Properties[Constants.Conventions.Member.LastLockoutDate].Value.TryConvertTo<DateTime>();
if (tryConvert.Success)
{
return tryConvert.Result;
}
return default(DateTime);
//TODO: Use TryConvertTo<T> instead
return (DateTime)Convert.ChangeType(Properties[Constants.Conventions.Member.LastLockoutDate].Value, typeof(DateTime));
}
set
{
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.LastLockoutDate,
"LastLockoutDate") == false) return;
Properties[Constants.Conventions.Member.LastLockoutDate].Value = value;
}
}
@@ -338,7 +397,7 @@ namespace Umbraco.Core.Models
/// This is the number of times the password was entered incorrectly upon login.
/// </summary>
/// <remarks>
/// Alias: umbracoFailedPasswordAttemptsPropertyTypeAlias
/// Alias: umbracoMemberFailedPasswordAttempts
/// Part of the standard properties collection.
/// </remarks>
[IgnoreDataMember]
@@ -346,18 +405,24 @@ namespace Umbraco.Core.Models
{
get
{
if (Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value == null)
return default(int);
if (Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value is int)
return (int)Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value;
var a = WarnIfPropertyTypeNotFoundOnGet(Constants.Conventions.Member.FailedPasswordAttempts, "FailedPasswordAttempts", 0);
if (a.Success == false) return a.Result;
var tryConvert = Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value.TryConvertTo<int>();
if (tryConvert.Success)
{
return tryConvert.Result;
}
return default(int);
//TODO: Use TryConvertTo<T> instead
return (int)Convert.ChangeType(Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value, typeof(int));
}
set
{
Properties[Constants.Conventions.Member.LastLockoutDate].Value = value;
if (WarnIfPropertyTypeNotFoundOnSet(
Constants.Conventions.Member.FailedPasswordAttempts,
"FailedPasswordAttempts") == false) return;
Properties[Constants.Conventions.Member.FailedPasswordAttempts].Value = value;
}
}
@@ -471,5 +536,73 @@ namespace Umbraco.Core.Models
internal bool BoolPropertyValue { get; set; }
internal DateTime DateTimePropertyValue { get; set; }
internal string PropertyTypeAlias { get; set; }
private Attempt<T> WarnIfPropertyTypeNotFoundOnGet<T>(string propertyAlias, string propertyName, T defaultVal)
{
Action doLog = () => LogHelper.Warn<Member>(
"Trying to access the '"
+ propertyName
+ "' property on "
+ typeof(Member)
+ " but the "
+ propertyAlias
+ " property does not exist on the member type so a default value is returned. Ensure that you have a property type with alias: "
+ propertyAlias
+ " configured on your member type in order to use the '"
+ propertyName
+ "' property on the model correctly.");
//if the property doesn't exist, then do the logging and return a failure
if (Properties.Contains(propertyAlias) == false)
{
//we'll put a warn in the log if this entity has been persisted
if (HasIdentity)
{
doLog();
}
return Attempt<T>.Fail(defaultVal);
}
//if the property doesn't have an identity but we do, then do logging and return failure
var prop = Properties.Single(x => x.Alias == propertyAlias);
if (prop.HasIdentity == false && HasIdentity)
{
doLog();
return Attempt<T>.Fail(defaultVal);
}
return Attempt<T>.Succeed();
}
private bool WarnIfPropertyTypeNotFoundOnSet(string propertyAlias, string propertyname)
{
Action doLog = () => LogHelper.Warn<Member>("An attempt was made to set a value on the property '"
+ propertyname
+ "' on type "
+ typeof(Member)
+ " but the property type "
+ propertyAlias
+ " does not exist on the member type, ensure that this property type exists so that setting this property works correctly.");
//if the property doesn't exist, then do the logging and return a failure
if (Properties.Contains(propertyAlias) == false)
{
if (HasIdentity)
{
doLog();
}
return false;
}
//if the property doesn't have an identity but we do, then do logging and return failure
var prop = Properties.Single(x => x.Alias == propertyAlias);
if (prop.HasIdentity == false && HasIdentity)
{
doLog();
return false;
}
return true;
}
}
}
+76
View File
@@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a member type
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
public class MemberGroup : Entity, IMemberGroup
{
public MemberGroup()
{
AdditionalData = new Dictionary<string, object>();
}
private string _name;
private int _creatorId;
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<MemberGroup, string>(x => x.Name);
private static readonly PropertyInfo CreatorIdSelector = ExpressionHelper.GetPropertyInfo<MemberGroup, int>(x => x.CreatorId);
[DataMember]
public string Name
{
get { return _name; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
if (_name != value)
{
//if the name has changed, add the value to the additional data,
//this is required purely for event handlers to know the previous name of the group
//so we can keep the public access up to date.
AdditionalData["previousName"] = _name;
}
_name = value;
return _name;
}, _name, NameSelector);
}
}
public int CreatorId
{
get { return _creatorId; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_creatorId = value;
return _creatorId;
}, _creatorId, CreatorIdSelector);
}
}
public IDictionary<string, object> AdditionalData { get; private set; }
/// <summary>
/// Method to call when Entity is being saved
/// </summary>
/// <remarks>Created date is set and a Unique key is assigned</remarks>
internal override void AddingEntity()
{
base.AddingEntity();
if (Key == Guid.Empty)
Key = Guid.NewGuid();
}
}
}
+10 -27
View File
@@ -14,20 +14,18 @@ namespace Umbraco.Core.Models
public class MemberType : ContentTypeCompositionBase, IMemberType
{
//Dictionary is divided into string: PropertyTypeAlias, Tuple: MemberCanEdit, VisibleOnProfile, PropertyTypeId
private IDictionary<string, Tuple<bool, bool, int>> _memberTypePropertyTypes;
private string _alias;
public MemberType(int parentId) : base(parentId)
{
_memberTypePropertyTypes = new Dictionary<string, Tuple<bool, bool, int>>();
MemberTypePropertyTypes = new Dictionary<string, MemberTypePropertyProfileAccess>();
}
public MemberType(IContentTypeComposition parent) : base(parent)
{
_memberTypePropertyTypes = new Dictionary<string, Tuple<bool, bool, int>>();
MemberTypePropertyTypes = new Dictionary<string, MemberTypePropertyProfileAccess>();
}
private static readonly PropertyInfo MemberTypePropertyTypesSelector = ExpressionHelper.GetPropertyInfo<MemberType, IDictionary<string, Tuple<bool, bool, int>>>(x => x.MemberTypePropertyTypes);
private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<MemberType, string>(x => x.Alias);
/// <summary>
@@ -53,21 +51,10 @@ namespace Umbraco.Core.Models
}
/// <summary>
/// Gets or Sets a Dictionary of Tuples (MemberCanEdit, VisibleOnProfile, PropertyTypeId) by the PropertyTypes' alias.
/// Gets or Sets a Dictionary of Tuples (MemberCanEdit, VisibleOnProfile) by the PropertyTypes' alias.
/// </summary>
[DataMember]
internal IDictionary<string, Tuple<bool, bool, int>> MemberTypePropertyTypes
{
get { return _memberTypePropertyTypes; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_memberTypePropertyTypes = value;
return _memberTypePropertyTypes;
}, _memberTypePropertyTypes, MemberTypePropertyTypesSelector);
}
}
internal IDictionary<string, MemberTypePropertyProfileAccess> MemberTypePropertyTypes { get; private set; }
/// <summary>
/// Gets a boolean indicating whether a Property is editable by the Member.
@@ -78,7 +65,7 @@ namespace Umbraco.Core.Models
{
if (MemberTypePropertyTypes.ContainsKey(propertyTypeAlias))
{
return MemberTypePropertyTypes[propertyTypeAlias].Item1;
return MemberTypePropertyTypes[propertyTypeAlias].IsEditable;
}
return false;
@@ -93,7 +80,7 @@ namespace Umbraco.Core.Models
{
if (MemberTypePropertyTypes.ContainsKey(propertyTypeAlias))
{
return MemberTypePropertyTypes[propertyTypeAlias].Item2;
return MemberTypePropertyTypes[propertyTypeAlias].IsVisible;
}
return false;
@@ -108,13 +95,11 @@ namespace Umbraco.Core.Models
{
if (MemberTypePropertyTypes.ContainsKey(propertyTypeAlias))
{
var tuple = MemberTypePropertyTypes[propertyTypeAlias];
MemberTypePropertyTypes[propertyTypeAlias] = new Tuple<bool, bool, int>(value, tuple.Item2, tuple.Item3);
MemberTypePropertyTypes[propertyTypeAlias].IsEditable = value;
}
else
{
var propertyType = PropertyTypes.First(x => x.Alias.Equals(propertyTypeAlias));
var tuple = new Tuple<bool, bool, int>(value, false, propertyType.Id);
var tuple = new MemberTypePropertyProfileAccess(false, value);
MemberTypePropertyTypes.Add(propertyTypeAlias, tuple);
}
}
@@ -128,13 +113,11 @@ namespace Umbraco.Core.Models
{
if (MemberTypePropertyTypes.ContainsKey(propertyTypeAlias))
{
var tuple = MemberTypePropertyTypes[propertyTypeAlias];
MemberTypePropertyTypes[propertyTypeAlias] = new Tuple<bool, bool, int>(tuple.Item1, value, tuple.Item3);
MemberTypePropertyTypes[propertyTypeAlias].IsVisible = value;
}
else
{
var propertyType = PropertyTypes.First(x => x.Alias.Equals(propertyTypeAlias));
var tuple = new Tuple<bool, bool, int>(false, value, propertyType.Id);
var tuple = new MemberTypePropertyProfileAccess(value, false);
MemberTypePropertyTypes.Add(propertyTypeAlias, tuple);
}
}
@@ -0,0 +1,17 @@
namespace Umbraco.Core.Models
{
/// <summary>
/// Used to track the property types that are visible/editable on member profiles
/// </summary>
internal class MemberTypePropertyProfileAccess
{
public MemberTypePropertyProfileAccess(bool isVisible, bool isEditable)
{
IsVisible = isVisible;
IsEditable = isEditable;
}
public bool IsVisible { get; set; }
public bool IsEditable { get; set; }
}
}
@@ -5,14 +5,14 @@
/// </summary>
public class EntityPermission
{
public EntityPermission(object userId, int entityId, string[] assignedPermissions)
public EntityPermission(int userId, int entityId, string[] assignedPermissions)
{
UserId = userId;
EntityId = entityId;
AssignedPermissions = assignedPermissions;
}
public object UserId { get; private set; }
public int UserId { get; private set; }
public int EntityId { get; private set; }
/// <summary>
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Models.Membership
/// This is the number of times the password was entered incorrectly upon login.
/// </summary>
/// <remarks>
/// Alias: umbracoFailedPasswordAttemptsPropertyTypeAlias
/// Alias: umbracoMemberFailedPasswordAttempts
/// Part of the standard properties collection.
/// </remarks>
int FailedPasswordAttempts { get; set; }
@@ -3,6 +3,10 @@
/// <summary>
/// Defines the the Profile interface
/// </summary>
/// <remarks>
/// This interface is pretty useless but has been exposed publicly from 6.x so we're stuck with it. It would make more sense
/// if the Id was an int but since it's not people have to cast it to int all of the time!
/// </remarks>
public interface IProfile
{
object Id { get; set; }
+11 -7
View File
@@ -7,19 +7,18 @@ namespace Umbraco.Core.Models.Membership
/// Defines the interface for a <see cref="User"/>
/// </summary>
/// <remarks>Will be left internal until a proper Membership implementation is part of the roadmap</remarks>
internal interface IUser : IMembershipUser, IProfile
public interface IUser : IMembershipUser
{
new object Id { get; set; }
string Name { get; set; }
int SessionTimeout { get; set; }
int StartContentId { get; set; }
int StartMediaId { get; set; }
string Language { get; set; }
//NOTE: I have removed this because it is obsolete in v7 and we are basically removing live editing for now
//bool DefaultToLiveEditing { get; set; }
IUserType UserType { get; }
/// <summary>
/// Gets/sets the user type for the user
/// </summary>
IUserType UserType { get; set; }
/// <summary>
/// The default permission set for the user
@@ -32,5 +31,10 @@ namespace Umbraco.Core.Models.Membership
IEnumerable<string> AllowedSections { get; }
void RemoveAllowedSection(string sectionAlias);
void AddAllowedSection(string sectionAlias);
/// <summary>
/// Exposes the basic profile data
/// </summary>
IProfile ProfileData { get; }
}
}
@@ -5,7 +5,7 @@ using Umbraco.Core.Persistence.Mappers;
namespace Umbraco.Core.Models.Membership
{
internal interface IUserType : IAggregateRoot
public interface IUserType : IAggregateRoot
{
/// <summary>
/// The user type alias
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Models.Membership
{
return MembershipScenario.NativeUmbraco;
}
var memberType = ApplicationContext.Current.Services.MemberTypeService.GetMemberType(Constants.Conventions.MemberTypes.Member);
var memberType = ApplicationContext.Current.Services.MemberTypeService.Get(Constants.Conventions.MemberTypes.DefaultAlias);
return memberType != null
? MembershipScenario.CustomProviderWithUmbracoLink
: MembershipScenario.StandaloneCustomProvider;
+89 -35
View File
@@ -5,6 +5,7 @@ using System.Collections.Specialized;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Persistence.Mappers;
@@ -19,7 +20,7 @@ namespace Umbraco.Core.Models.Membership
/// </remarks>
[Serializable]
[DataContract(IsReference = true)]
internal class User : TracksChangesEntityBase, IUser
public class User : TracksChangesEntityBase, IUser
{
public User(IUserType userType)
{
@@ -31,7 +32,12 @@ namespace Umbraco.Core.Models.Membership
_sectionCollection = new ObservableCollection<string>();
_addedSections = new List<string>();
_removedSections = new List<string>();
_language = GlobalSettings.DefaultUILanguage;
_sectionCollection.CollectionChanged += SectionCollectionChanged;
_isApproved = true;
_isLockedOut = false;
_startContentId = -1;
_startMediaId = -1;
}
public User(string name, string email, string username, string password, IUserType userType)
@@ -41,11 +47,15 @@ namespace Umbraco.Core.Models.Membership
_email = email;
_username = username;
_password = password;
_isApproved = true;
_isLockedOut = false;
_startContentId = -1;
_startMediaId = -1;
}
private readonly IUserType _userType;
private IUserType _userType;
private bool _hasIdentity;
private object _id;
private int _id;
private string _name;
private Type _userTypeKey;
private readonly List<string> _addedSections;
@@ -58,7 +68,6 @@ namespace Umbraco.Core.Models.Membership
private string _username;
private string _email;
private string _password;
private Guid _key;
private bool _isApproved;
private bool _isLockedOut;
private string _language;
@@ -81,23 +90,43 @@ namespace Umbraco.Core.Models.Membership
private static readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Language);
private static readonly PropertyInfo DefaultPermissionsSelector = ExpressionHelper.GetPropertyInfo<User, IEnumerable<string>>(x => x.DefaultPermissions);
private static readonly PropertyInfo DefaultToLiveEditingSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.DefaultToLiveEditing);
private static readonly PropertyInfo HasIdentitySelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.HasIdentity);
private static readonly PropertyInfo UserTypeSelector = ExpressionHelper.GetPropertyInfo<User, IUserType>(x => x.UserType);
#region Implementation of IEntity
[IgnoreDataMember]
public bool HasIdentity { get { return Id != null || _hasIdentity; } }
[IgnoreDataMember]
int IEntity.Id
public bool HasIdentity
{
get
{
return int.Parse(Id.ToString());
return _hasIdentity;
}
protected set
{
SetPropertyValueAndDetectChanges(o =>
{
_hasIdentity = value;
return _hasIdentity;
}, _hasIdentity, HasIdentitySelector);
}
}
[DataMember]
public int Id
{
get
{
return _id;
}
set
{
Id = value;
_hasIdentity = true;
SetPropertyValueAndDetectChanges(o =>
{
_id = value;
HasIdentity = true; //set the has Identity
return _id;
}, _id, IdSelector);
}
}
@@ -239,8 +268,8 @@ namespace Umbraco.Core.Models.Membership
public int FailedPasswordAttempts { get; set; }
#endregion
#region Implementation of IProfile
#region Implementation of IUser
[DataMember]
public string Name
@@ -249,17 +278,13 @@ namespace Umbraco.Core.Models.Membership
set
{
SetPropertyValueAndDetectChanges(o =>
{
_name = value;
return _name;
}, _name, NameSelector);
{
_name = value;
return _name;
}, _name, NameSelector);
}
}
#endregion
#region Implementation of IUser
public IEnumerable<string> AllowedSections
{
get { return _sectionCollection; }
@@ -278,6 +303,11 @@ namespace Umbraco.Core.Models.Membership
}
}
public IProfile ProfileData
{
get { return new UserProfile(this); }
}
/// <summary>
/// Used internally to check if we need to add a section in the repository to the db
/// </summary>
@@ -354,20 +384,6 @@ namespace Umbraco.Core.Models.Membership
}
}
[DataMember]
public object Id
{
get { return _id; }
set
{
SetPropertyValueAndDetectChanges(o =>
{
_id = value;
return _id;
}, _id, IdSelector);
}
}
[DataMember]
public string Language
{
@@ -414,6 +430,19 @@ namespace Umbraco.Core.Models.Membership
public IUserType UserType
{
get { return _userType; }
set
{
if (value.HasIdentity == false)
{
throw new InvalidOperationException("Cannot assign a User Type that has not been persisted");
}
SetPropertyValueAndDetectChanges(o =>
{
_userType = value;
return _userType;
}, _userType, UserTypeSelector);
}
}
#endregion
@@ -459,5 +488,30 @@ namespace Umbraco.Core.Models.Membership
_removedSections.Add(e.OldItems.Cast<string>().First());
}
}
/// <summary>
/// Internal class used to wrap the user in a profile
/// </summary>
private class UserProfile : IProfile
{
private readonly IUser _user;
public UserProfile(IUser user)
{
_user = user;
}
public object Id
{
get { return _user.Id; }
set { _user.Id = (int)value; }
}
public string Name
{
get { return _user.Name; }
set { _user.Name = value; }
}
}
}
}
+8 -3
View File
@@ -44,7 +44,7 @@ namespace Umbraco.Core.Models
private static readonly PropertyInfo ValueSelector = ExpressionHelper.GetPropertyInfo<Property, object>(x => x.Value);
private static readonly PropertyInfo VersionSelector = ExpressionHelper.GetPropertyInfo<Property, Guid>(x => x.Version);
/// <summary>
/// Returns the instance of the tag support, by default tags are not enabled
/// </summary>
@@ -68,9 +68,14 @@ namespace Umbraco.Core.Models
/// <summary>
/// Returns the DatabaseType that the underlaying DataType is using to store its values
/// </summary>
/// <remarks>Only used internally when saving the property value</remarks>
/// <remarks>
/// Only used internally when saving the property value.
/// </remarks>
[IgnoreDataMember]
internal DataTypeDatabaseType DataTypeDatabaseType { get { return _propertyType.DataTypeDatabaseType; } }
internal DataTypeDatabaseType DataTypeDatabaseType
{
get { return _propertyType.DataTypeDatabaseType; }
}
/// <summary>
/// Returns the PropertyType, which this Property is based on
+21 -4
View File
@@ -15,6 +15,7 @@ namespace Umbraco.Core.Models
[DataContract(IsReference = true)]
public class PropertyType : Entity, IEquatable<PropertyType>
{
private readonly bool _isExplicitDbType;
private string _name;
private string _alias;
private string _description;
@@ -30,16 +31,29 @@ namespace Umbraco.Core.Models
public PropertyType(IDataTypeDefinition dataTypeDefinition)
{
if(dataTypeDefinition.HasIdentity)
DataTypeDefinitionId = dataTypeDefinition.Id;
_dataTypeDefinitionId = dataTypeDefinition.Id;
PropertyEditorAlias = dataTypeDefinition.PropertyEditorAlias;
DataTypeDatabaseType = dataTypeDefinition.DatabaseType;
_propertyEditorAlias = dataTypeDefinition.PropertyEditorAlias;
_dataTypeDatabaseType = dataTypeDefinition.DatabaseType;
}
internal PropertyType(string propertyEditorAlias, DataTypeDatabaseType dataTypeDatabaseType)
: this(propertyEditorAlias, dataTypeDatabaseType, false)
{
PropertyEditorAlias = propertyEditorAlias;
DataTypeDatabaseType = dataTypeDatabaseType;
}
/// <summary>
/// Used internally to assign an explicity database type for this property type regardless of what the underlying data type/property editor is.
/// </summary>
/// <param name="propertyEditorAlias"></param>
/// <param name="dataTypeDatabaseType"></param>
/// <param name="isExplicitDbType"></param>
internal PropertyType(string propertyEditorAlias, DataTypeDatabaseType dataTypeDatabaseType, bool isExplicitDbType)
{
_isExplicitDbType = isExplicitDbType;
_propertyEditorAlias = propertyEditorAlias;
_dataTypeDatabaseType = dataTypeDatabaseType;
}
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<PropertyType, string>(x => x.Name);
@@ -165,6 +179,9 @@ namespace Umbraco.Core.Models
get { return _dataTypeDatabaseType; }
set
{
//don't allow setting this if an explicit declaration has been made in the ctor
if (_isExplicitDbType) return;
SetPropertyValueAndDetectChanges(o =>
{
_dataTypeDatabaseType = value;
+7 -1
View File
@@ -183,5 +183,11 @@ namespace Umbraco.Core.Models
if (Key == Guid.Empty)
Key = Guid.NewGuid();
}
public void SetMasterTemplate(ITemplate masterTemplate)
{
MasterTemplateId = new Lazy<int>(() => masterTemplate.Id);
}
}
}
}
+8
View File
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using Umbraco.Core.Models.EntityBase;
@@ -53,6 +54,13 @@ namespace Umbraco.Core.Models
Trashed = trashed;
}
// for MySql
public UmbracoEntity(UInt64 trashed)
{
AdditionalData = new Dictionary<string, object>();
Trashed = trashed == 1;
}
public int CreatorId
{
get { return _creatorId; }
+14 -3
View File
@@ -246,12 +246,14 @@ namespace Umbraco.Core
else if (destinationType == typeof(Double))
{
Double value;
return Double.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
var input2 = NormalizeNumberDecimalSeparator(input);
return Double.TryParse(input2, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(Single))
{
Single value;
return Single.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
var input2 = NormalizeNumberDecimalSeparator(input);
return Single.TryParse(input2, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(Char))
{
@@ -320,7 +322,8 @@ namespace Umbraco.Core
else if (destinationType == typeof(Decimal))
{
Decimal value;
return Decimal.TryParse(input, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
var input2 = NormalizeNumberDecimalSeparator(input);
return Decimal.TryParse(input2, out value) ? Attempt<object>.Succeed(value) : Attempt<object>.Fail();
}
else if (destinationType == typeof(Version))
{
@@ -332,6 +335,14 @@ namespace Umbraco.Core
return null; // we can't decide...
}
private readonly static char[] NumberDecimalSeparatorsToNormalize = new[] {'.', ','};
private static string NormalizeNumberDecimalSeparator(string s)
{
var normalized = System.Threading.Thread.CurrentThread.CurrentUICulture.NumberFormat.NumberDecimalSeparator[0];
return s.ReplaceMany(NumberDecimalSeparatorsToNormalize, normalized);
}
internal static void CheckThrowObjectDisposed(this IDisposable disposable, bool isDisposed, string objectname)
{
//TODO: Localise this exception
@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Umbraco.Core.Persistence
{
//TODO: Would be good to use this exception type anytime we cannot find an entity
/// <summary>
/// An exception used to indicate that an umbraco entity could not be found
/// </summary>
public class EntityNotFoundException : Exception
{
public object Id { get; private set; }
private readonly string _msg;
public EntityNotFoundException(object id, string msg)
{
Id = id;
_msg = msg;
}
public EntityNotFoundException(string msg)
{
_msg = msg;
}
public override string Message
{
get { return _msg; }
}
public override string ToString()
{
var result = base.ToString();
if (Id != null)
{
return "Umbraco entity (id: " + Id + ") not found. " + result;
}
return result;
}
}
}
@@ -0,0 +1,64 @@
using System;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Factories
{
internal class MemberGroupFactory : IEntityFactory<IMemberGroup, NodeDto>
{
private readonly Guid _nodeObjectTypeId;
public MemberGroupFactory()
{
_nodeObjectTypeId = new Guid(Constants.ObjectTypes.MemberGroup);
}
#region Implementation of IEntityFactory<ITemplate,TemplateDto>
public IMemberGroup BuildEntity(NodeDto dto)
{
var template = new MemberGroup
{
CreateDate = dto.CreateDate,
Id = dto.NodeId,
Key = dto.UniqueId.Value,
Name = dto.Text
};
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
template.ResetDirtyProperties(false);
return template;
}
public NodeDto BuildDto(IMemberGroup entity)
{
var dto = new NodeDto
{
CreateDate = entity.CreateDate,
NodeId = entity.Id,
Level = 0,
NodeObjectType = _nodeObjectTypeId,
ParentId = -1,
Path = "",
SortOrder = 0,
Text = entity.Name,
Trashed = false,
UniqueId = entity.Key,
UserId = entity.CreatorId
};
if (entity.HasIdentity)
{
dto.NodeId = entity.Id;
dto.Path = "-1," + entity.Id;
}
return dto;
}
#endregion
}
}
@@ -25,7 +25,7 @@ namespace Umbraco.Core.Persistence.Factories
CreateDate = dto.CreateDate,
UpdateDate = dto.UpdateDate,
Name = dto.Text,
ProviderUserKey = dto.UniqueId.Value,
ProviderUserKey = dto.NodeId,
Trashed = dto.Trashed,
Key = dto.UniqueId.Value,
CreatorId = dto.UserId.HasValue ? dto.UserId.Value : 0,
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.Repositories;
namespace Umbraco.Core.Persistence.Factories
{
@@ -10,6 +11,8 @@ namespace Umbraco.Core.Persistence.Factories
{
public IMemberType BuildEntity(MemberTypeReadOnlyDto dto)
{
var standardPropertyTypes = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
var memberType = new MemberType(dto.ParentId)
{
Alias = dto.Alias,
@@ -31,12 +34,12 @@ namespace Umbraco.Core.Persistence.Factories
AllowedContentTypes = Enumerable.Empty<ContentTypeSort>()
};
var propertyTypeGroupCollection = GetPropertyTypeGroupCollection(dto, memberType);
var propertyTypeGroupCollection = GetPropertyTypeGroupCollection(dto, memberType, standardPropertyTypes);
memberType.PropertyGroups = propertyTypeGroupCollection;
var propertyTypes = GetPropertyTypes(dto, memberType);
//By Convention we add 9 stnd PropertyTypes - This is only here to support loading of types that didn't have these conventions before.
var standardPropertyTypes = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
var propertyTypes = GetPropertyTypes(dto, memberType, standardPropertyTypes);
//By Convention we add 9 stnd PropertyTypes - This is only here to support loading of types that didn't have these conventions before.
foreach (var standardPropertyType in standardPropertyTypes)
{
if(dto.PropertyTypes.Any(x => x.Alias.Equals(standardPropertyType.Key))) continue;
@@ -46,16 +49,17 @@ namespace Umbraco.Core.Persistence.Factories
//Internal dictionary for adding "MemberCanEdit" and "VisibleOnProfile" properties to each PropertyType
memberType.MemberTypePropertyTypes.Add(standardPropertyType.Key,
new Tuple<bool, bool, int>(false, false, default(int)));
new MemberTypePropertyProfileAccess(false, false));
}
memberType.PropertyTypes = propertyTypes;
return memberType;
}
private PropertyGroupCollection GetPropertyTypeGroupCollection(MemberTypeReadOnlyDto dto, MemberType memberType)
private PropertyGroupCollection GetPropertyTypeGroupCollection(MemberTypeReadOnlyDto dto, MemberType memberType, Dictionary<string, PropertyType> standardProps)
{
var propertyGroups = new PropertyGroupCollection();
var propertyGroups = new PropertyGroupCollection();
foreach (var groupDto in dto.PropertyTypeGroups.Where(x => x.Id.HasValue))
{
var group = new PropertyGroup();
@@ -85,11 +89,23 @@ namespace Umbraco.Core.Persistence.Factories
{
//Internal dictionary for adding "MemberCanEdit" and "VisibleOnProfile" properties to each PropertyType
memberType.MemberTypePropertyTypes.Add(typeDto.Alias,
new Tuple<bool, bool, int>(typeDto.CanEdit, typeDto.ViewOnProfile, typeDto.Id.Value));
new MemberTypePropertyProfileAccess(typeDto.ViewOnProfile, typeDto.CanEdit));
var tempGroupDto = groupDto;
var propertyType = new PropertyType(typeDto.PropertyEditorAlias,
typeDto.DbType.EnumParse<DataTypeDatabaseType>(true))
//ensures that any built-in membership properties have their correct dbtype assigned no matter
//what the underlying data type is
var propDbType = MemberTypeRepository.GetDbTypeForBuiltInProperty(
typeDto.Alias,
typeDto.DbType.EnumParse<DataTypeDatabaseType>(true),
standardProps);
var propertyType = new PropertyType(
typeDto.PropertyEditorAlias,
propDbType.Result,
//This flag tells the property type that it has an explicit dbtype and that it cannot be changed
// which is what we want for the built-in properties.
propDbType.Success)
{
Alias = typeDto.Alias,
DataTypeDefinitionId = typeDto.DataTypeId,
@@ -118,32 +134,47 @@ namespace Umbraco.Core.Persistence.Factories
return propertyGroups;
}
private List<PropertyType> GetPropertyTypes(MemberTypeReadOnlyDto dto, MemberType memberType)
private List<PropertyType> GetPropertyTypes(MemberTypeReadOnlyDto dto, MemberType memberType, Dictionary<string, PropertyType> standardProps)
{
//Find PropertyTypes that does not belong to a PropertyTypeGroup
var propertyTypes = new List<PropertyType>();
foreach (var propertyType in dto.PropertyTypes.Where(x => (x.PropertyTypeGroupId.HasValue == false || x.PropertyTypeGroupId.Value == 0) && x.Id.HasValue))
foreach (var typeDto in dto.PropertyTypes.Where(x => (x.PropertyTypeGroupId.HasValue == false || x.PropertyTypeGroupId.Value == 0) && x.Id.HasValue))
{
//Internal dictionary for adding "MemberCanEdit" and "VisibleOnProfile" properties to each PropertyType
memberType.MemberTypePropertyTypes.Add(propertyType.Alias,
new Tuple<bool, bool, int>(propertyType.CanEdit, propertyType.ViewOnProfile, propertyType.Id.Value));
//PropertyType Collection
propertyTypes.Add(new PropertyType(propertyType.PropertyEditorAlias,
propertyType.DbType.EnumParse<DataTypeDatabaseType>(true))
{
Alias = propertyType.Alias,
DataTypeDefinitionId = propertyType.DataTypeId,
Description = propertyType.Description,
HelpText = propertyType.HelpText,
Id = propertyType.Id.Value,
Mandatory = propertyType.Mandatory,
Name = propertyType.Name,
SortOrder = propertyType.SortOrder,
ValidationRegExp = propertyType.ValidationRegExp,
PropertyGroupId = new Lazy<int>(() => default(int)),
CreateDate = dto.CreateDate,
UpdateDate = dto.CreateDate
});
memberType.MemberTypePropertyTypes.Add(typeDto.Alias,
new MemberTypePropertyProfileAccess(typeDto.ViewOnProfile, typeDto.CanEdit));
//ensures that any built-in membership properties have their correct dbtype assigned no matter
//what the underlying data type is
var propDbType = MemberTypeRepository.GetDbTypeForBuiltInProperty(
typeDto.Alias,
typeDto.DbType.EnumParse<DataTypeDatabaseType>(true),
standardProps);
var propertyType = new PropertyType(
typeDto.PropertyEditorAlias,
propDbType.Result,
//This flag tells the property type that it has an explicit dbtype and that it cannot be changed
// which is what we want for the built-in properties.
propDbType.Success)
{
Alias = typeDto.Alias,
DataTypeDefinitionId = typeDto.DataTypeId,
Description = typeDto.Description,
HelpText = typeDto.HelpText,
Id = typeDto.Id.Value,
Mandatory = typeDto.Mandatory,
Name = typeDto.Name,
SortOrder = typeDto.SortOrder,
ValidationRegExp = typeDto.ValidationRegExp,
PropertyGroupId = new Lazy<int>(() => default(int)),
CreateDate = dto.CreateDate,
UpdateDate = dto.CreateDate
};
propertyTypes.Add(propertyType);
}
return propertyTypes;
}
@@ -11,17 +11,21 @@ namespace Umbraco.Core.Persistence.Factories
private readonly int _id;
private readonly DateTime _createDate;
private readonly DateTime _updateDate;
//a callback to create a property type which can be injected via a contructor
private readonly Func<string, DataTypeDatabaseType, string, PropertyType> _propertyTypeCtor;
public PropertyGroupFactory(int id)
{
_id = id;
_propertyTypeCtor = (propertyEditorAlias, dbType, alias) => new PropertyType(propertyEditorAlias, dbType);
}
public PropertyGroupFactory(int id, DateTime createDate, DateTime updateDate)
public PropertyGroupFactory(int id, DateTime createDate, DateTime updateDate, Func<string, DataTypeDatabaseType, string, PropertyType> propertyTypeCtor)
{
_id = id;
_createDate = createDate;
_updateDate = updateDate;
_propertyTypeCtor = propertyTypeCtor;
}
#region Implementation of IEntityFactory<IEnumerable<PropertyGroup>,IEnumerable<TabDto>>
@@ -55,22 +59,23 @@ namespace Umbraco.Core.Persistence.Factories
foreach (var typeDto in typeDtos)
{
var tempGroupDto = groupDto;
var propertyType = new PropertyType(typeDto.DataTypeDto.PropertyEditorAlias,
typeDto.DataTypeDto.DbType.EnumParse<DataTypeDatabaseType>(true))
{
Alias = typeDto.Alias,
DataTypeDefinitionId = typeDto.DataTypeId,
Description = typeDto.Description,
Id = typeDto.Id,
Name = typeDto.Name,
HelpText = typeDto.HelpText,
Mandatory = typeDto.Mandatory,
SortOrder = typeDto.SortOrder,
ValidationRegExp = typeDto.ValidationRegExp,
PropertyGroupId = new Lazy<int>(() => tempGroupDto.Id),
CreateDate = _createDate,
UpdateDate = _updateDate
};
var propertyType = _propertyTypeCtor(typeDto.DataTypeDto.PropertyEditorAlias,
typeDto.DataTypeDto.DbType.EnumParse<DataTypeDatabaseType>(true),
typeDto.Alias);
propertyType.Alias = typeDto.Alias;
propertyType.DataTypeDefinitionId = typeDto.DataTypeId;
propertyType.Description = typeDto.Description;
propertyType.Id = typeDto.Id;
propertyType.Name = typeDto.Name;
propertyType.HelpText = typeDto.HelpText;
propertyType.Mandatory = typeDto.Mandatory;
propertyType.SortOrder = typeDto.SortOrder;
propertyType.ValidationRegExp = typeDto.ValidationRegExp;
propertyType.PropertyGroupId = new Lazy<int>(() => tempGroupDto.Id);
propertyType.CreateDate = _createDate;
propertyType.UpdateDate = _updateDate;
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
propertyType.ResetDirtyProperties(false);
@@ -0,0 +1,34 @@
using System.Collections.Concurrent;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Mappers
{
[MapperFor(typeof (IMemberGroup))]
[MapperFor(typeof (MemberGroup))]
public sealed class MemberGroupMapper : BaseMapper
{
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
// otherwise that would fail because there is no public constructor.
public MemberGroupMapper()
{
BuildMap();
}
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
{
get { return PropertyInfoCacheInstance; }
}
internal override void BuildMap()
{
CacheMap<MemberGroup, NodeDto>(src => src.Id, dto => dto.NodeId);
CacheMap<MemberGroup, NodeDto>(src => src.CreateDate, dto => dto.CreateDate);
CacheMap<MemberGroup, NodeDto>(src => src.CreatorId, dto => dto.UserId);
CacheMap<MemberGroup, NodeDto>(src => src.Name, dto => dto.Text);
CacheMap<MemberGroup, NodeDto>(src => src.Key, dto => dto.UniqueId);
}
}
}
@@ -120,7 +120,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1036, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1036", SortOrder = 2, UniqueId = new Guid("2b24165f-9782-4aa3-b459-1de4a4d21f60"), Text = "Member Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1040, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1040", SortOrder = 2, UniqueId = new Guid("21e798da-e06e-4eda-a511-ed257f78d4fa"), Text = "Related Links", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1041, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1041", SortOrder = 2, UniqueId = new Guid("b6b73142-b9c1-4bf8-a16d-e1c23320b549"), Text = "Tags", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1044, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1044", SortOrder = 0, UniqueId = new Guid("d59be02f-1df9-4228-aa1e-01917d806cda"), Text = Constants.Conventions.MemberTypes.Member, NodeObjectType = new Guid(Constants.ObjectTypes.MemberType), CreateDate = DateTime.Now });
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1044, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1044", SortOrder = 0, UniqueId = new Guid("d59be02f-1df9-4228-aa1e-01917d806cda"), Text = Constants.Conventions.MemberTypes.DefaultAlias, NodeObjectType = new Guid(Constants.ObjectTypes.MemberType), CreateDate = DateTime.Now });
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1045, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1045", SortOrder = 2, UniqueId = new Guid("7E3962CC-CE20-4FFC-B661-5897A894BA7E"), Text = "Multiple Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
//TODO: We're not creating these for 7.0
@@ -135,7 +135,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 532, NodeId = 1031, Alias = Constants.Conventions.MediaTypes.Folder, Icon = "icon-folder", Thumbnail = "folder.png", IsContainer = false, AllowAtRoot = true });
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 533, NodeId = 1032, Alias = Constants.Conventions.MediaTypes.Image, Icon = "icon-picture", Thumbnail = "mediaPhoto.png" });
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 534, NodeId = 1033, Alias = Constants.Conventions.MediaTypes.File, Icon = "icon-document", Thumbnail = "mediaFile.png" });
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 531, NodeId = 1044, Alias = Constants.Conventions.MemberTypes.Member, Icon = "icon-user", Thumbnail = "folder.png" });
_database.Insert("cmsContentType", "pk", false, new ContentTypeDto { PrimaryKey = 531, NodeId = 1044, Alias = Constants.Conventions.MemberTypes.DefaultAlias, Icon = "icon-user", Thumbnail = "folder.png" });
}
private void CreateUmbracoUserData()
@@ -79,7 +79,10 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
try
{
_database.DropTable(tableName);
if (_database.TableExist(tableName))
{
_database.DropTable(tableName);
}
}
catch (Exception ex)
{
@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.Deployment.Internal;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
using System.Xml;
using Newtonsoft.Json;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenOne
{
[Migration("7.1.0", 1, GlobalSettings.UmbracoMigrationName)]
public class UpdateToNewMemberPropertyAliases : MigrationBase
{
public override void Up()
{
Execute.Code(Update);
}
internal static string Update(Database database)
{
if (database != null)
{
var aliasMap = new Dictionary<string, string>
{
{"umbracoPasswordRetrievalQuestionPropertyTypeAlias", Constants.Conventions.Member.PasswordQuestion},
{"umbracoPasswordRetrievalAnswerPropertyTypeAlias", Constants.Conventions.Member.PasswordAnswer},
{"umbracoCommentPropertyTypeAlias", Constants.Conventions.Member.Comments},
{"umbracoApprovePropertyTypeAlias", Constants.Conventions.Member.IsApproved},
{"umbracoLockPropertyTypeAlias", Constants.Conventions.Member.IsLockedOut},
{"umbracoLastLoginPropertyTypeAlias", Constants.Conventions.Member.LastLoginDate},
{"umbracoMemberLastPasswordChange", Constants.Conventions.Member.LastPasswordChangeDate},
{"umbracoMemberLastLockout", Constants.Conventions.Member.LastLockoutDate},
{"umbracoFailedPasswordAttemptsPropertyTypeAlias", Constants.Conventions.Member.FailedPasswordAttempts}
};
const string propertyTypeUpdateSql = @"UPDATE cmsPropertyType
SET Alias = @newAlias
WHERE Alias = @oldAlias AND contentTypeId IN (
SELECT DISTINCT cmsContentType.nodeId FROM cmsPropertyType
INNER JOIN cmsContentType ON cmsPropertyType.contentTypeId = cmsContentType.nodeId
INNER JOIN umbracoNode ON cmsContentType.nodeId = umbracoNode.id
WHERE umbracoNode.nodeObjectType = @objectType)";
const string xmlSelectSql = @"SELECT cmsContentXml.* FROM cmsContentXml
INNER JOIN umbracoNode ON cmsContentXml.nodeId = umbracoNode.id
WHERE umbracoNode.nodeObjectType = @objectType";
using (var trans = database.GetTransaction())
{
try
{
//Upate all of the property type aliases
foreach (var map in aliasMap)
{
database.Execute(propertyTypeUpdateSql, new { newAlias = map.Value, oldAlias = map.Key, objectType = Constants.ObjectTypes.MemberType });
}
//Update all of the XML
var items = database.Fetch<ContentXmlDto>(xmlSelectSql, new {objectType = Constants.ObjectTypes.Member});
foreach (var item in items)
{
foreach (var map in aliasMap)
{
item.Xml = item.Xml.Replace("<" + map.Key + ">", "<" + map.Value + ">");
item.Xml = item.Xml.Replace("</" + map.Key + ">", "</" + map.Value + ">");
}
database.Update(item);
}
trans.Complete();
}
catch (Exception ex)
{
LogHelper.Error<UpdateToNewMemberPropertyAliases>("Exception was thrown when trying to upgrade old member aliases to the new ones", ex);
throw;
}
}
}
return string.Empty;
}
public override void Down()
{
throw new NotImplementedException();
}
}
}
@@ -57,11 +57,20 @@ namespace Umbraco.Core.Persistence
using (var tr = db.GetTransaction())
{
db.BulkInsertRecords(collection, tr);
db.BulkInsertRecords(collection, tr, true);
}
}
public static void BulkInsertRecords<T>(this Database db, IEnumerable<T> collection, Transaction tr)
/// <summary>
/// Performs the bulk insertion in the context of a current transaction with an optional parameter to complete the transaction
/// when finished
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="db"></param>
/// <param name="collection"></param>
/// <param name="tr"></param>
/// <param name="commitTrans"></param>
public static void BulkInsertRecords<T>(this Database db, IEnumerable<T> collection, Transaction tr, bool commitTrans = false)
{
//don't do anything if there are no records.
if (collection.Any() == false)
@@ -95,11 +104,17 @@ namespace Umbraco.Core.Persistence
}
}
tr.Complete();
if (commitTrans)
{
tr.Complete();
}
}
catch
{
tr.Dispose();
if (commitTrans)
{
tr.Dispose();
}
throw;
}
}
@@ -1,5 +1,6 @@
using System;
using System.Globalization;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Querying
{
@@ -25,7 +26,7 @@ namespace Umbraco.Core.Persistence.Querying
{
//if (TypeSerializer.CanCreateFromString(fieldType))
//{
// return "'" + EscapeParam(TypeSerializer.SerializeToString(value)) + "'";
// return "'" + escapeCallback(TypeSerializer.SerializeToString(value)) + "'";
//}
throw new NotSupportedException(
@@ -46,27 +47,24 @@ namespace Umbraco.Core.Persistence.Querying
if (fieldType == typeof(DateTime))
{
return "'" + EscapeParam(((DateTime)value).ToIsoString()) + "'";
return "'" + escapeCallback(((DateTime)value).ToIsoString()) + "'";
}
if (fieldType == typeof(bool))
return ((bool)value) ? Convert.ToString(1, CultureInfo.InvariantCulture) : Convert.ToString(0, CultureInfo.InvariantCulture);
return ShouldQuoteValue(fieldType)
? "'" + EscapeParam(value) + "'"
return shouldQuoteCallback(fieldType)
? "'" + escapeCallback(value) + "'"
: value.ToString();
}
public virtual string EscapeParam(object paramValue)
{
return paramValue.ToString().Replace("'", "''");
return paramValue == null
? string.Empty
: SqlSyntaxContext.SqlSyntaxProvider.EscapeString(paramValue.ToString());
}
public virtual string EscapeAtArgument(string exp)
{
return PetaPocoExtensions.EscapeAtSymbols(exp);
}
public virtual bool ShouldQuoteValue(Type fieldType)
{
return true;
@@ -205,13 +205,12 @@ namespace Umbraco.Core.Persistence.Querying
{
if (c.Value == null)
return "null";
else if (c.Value.GetType() == typeof(bool))
if (c.Value is bool)
{
object o = GetQuotedValue(c.Value, c.Value.GetType());
return string.Format("({0}={1})", GetQuotedTrueValue(), o);
}
else
return GetQuotedValue(c.Value, c.Value.GetType());
return GetQuotedValue(c.Value, c.Value.GetType());
}
protected virtual string VisitUnary(UnaryExpression u)
@@ -233,15 +232,15 @@ namespace Umbraco.Core.Persistence.Querying
switch (verb)
{
case "SqlWildcard":
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnWildcardComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType);
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnWildcardComparison(col, RemoveQuote(val), columnType);
case "Equals":
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEqualComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType);
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEqualComparison(col, RemoveQuote(val), columnType);
case "StartsWith":
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnStartsWithComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType);
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnStartsWithComparison(col, RemoveQuote(val), columnType);
case "EndsWith":
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEndsWithComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType);
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEndsWithComparison(col, RemoveQuote(val), columnType);
case "Contains":
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnContainsComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType);
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnContainsComparison(col, RemoveQuote(val), columnType);
case "InvariantEquals":
case "SqlEquals":
//recurse
@@ -243,6 +243,10 @@ namespace Umbraco.Core.Persistence.Querying
args.RemoveAt(0);
}
//TODO: We should probably add the same logic we've done for ModelToSqlExpressionHelper with checking for:
// InvariantStartsWith, InvariantEndsWith, SqlWildcard, etc...
// since we should be able to easily handle that with the Poco objects too.
switch (m.Method.Name)
{
case "ToUpper":
@@ -250,11 +254,11 @@ namespace Umbraco.Core.Persistence.Querying
case "ToLower":
return string.Format("lower({0})", r);
case "StartsWith":
return string.Format("upper({0}) like '{1}%'", r, EscapeAtArgument(RemoveQuote(args[0].ToString().ToUpper())));
return string.Format("upper({0}) like '{1}%'", r, RemoveQuote(args[0].ToString().ToUpper()));
case "EndsWith":
return string.Format("upper({0}) like '%{1}'", r, EscapeAtArgument(RemoveQuote(args[0].ToString()).ToUpper()));
return string.Format("upper({0}) like '%{1}'", r, RemoveQuote(args[0].ToString()).ToUpper());
case "Contains":
return string.Format("upper({0}) like '%{1}%'", r, EscapeAtArgument(RemoveQuote(args[0].ToString()).ToUpper()));
return string.Format("upper({0}) like '%{1}%'", r, RemoveQuote(args[0].ToString()).ToUpper());
case "Substring":
var startIndex = Int32.Parse(args[0].ToString()) + 1;
if (args.Count == 2)
@@ -24,8 +24,9 @@ namespace Umbraco.Core.Persistence.Repositories
private readonly IContentTypeRepository _contentTypeRepository;
private readonly ITemplateRepository _templateRepository;
private readonly ITagsRepository _tagRepository;
private readonly CacheHelper _cacheHelper;
public ContentRepository(IDatabaseUnitOfWork work, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagsRepository tagRepository)
public ContentRepository(IDatabaseUnitOfWork work, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagsRepository tagRepository, CacheHelper cacheHelper)
: base(work)
{
if (contentTypeRepository == null) throw new ArgumentNullException("contentTypeRepository");
@@ -34,11 +35,12 @@ namespace Umbraco.Core.Persistence.Repositories
_contentTypeRepository = contentTypeRepository;
_templateRepository = templateRepository;
_tagRepository = tagRepository;
_cacheHelper = cacheHelper;
EnsureUniqueNaming = true;
}
public ContentRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagsRepository tagRepository)
public ContentRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IContentTypeRepository contentTypeRepository, ITemplateRepository templateRepository, ITagsRepository tagRepository, CacheHelper cacheHelper)
: base(work, cache)
{
if (contentTypeRepository == null) throw new ArgumentNullException("contentTypeRepository");
@@ -47,6 +49,7 @@ namespace Umbraco.Core.Persistence.Repositories
_contentTypeRepository = contentTypeRepository;
_templateRepository = templateRepository;
_tagRepository = tagRepository;
_cacheHelper = cacheHelper;
EnsureUniqueNaming = true;
}
@@ -139,6 +142,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
var list = new List<string>
{
"DELETE FROM cmsTask WHERE nodeId = @Id",
"DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @Id",
"DELETE FROM umbracoUser2NodePermission WHERE nodeId = @Id",
"DELETE FROM umbracoRelation WHERE parentId = @Id",
@@ -274,7 +278,7 @@ namespace Umbraco.Core.Persistence.Repositories
//Assign the same permissions to it as the parent node
// http://issues.umbraco.org/issue/U4-2161
var permissionsRepo = new PermissionRepository<IContent>(UnitOfWork);
var permissionsRepo = new PermissionRepository<IContent>(UnitOfWork, _cacheHelper);
var parentPermissions = permissionsRepo.GetPermissionsForEntity(entity.ParentId).ToArray();
//if there are parent permissions then assign them, otherwise leave null and permissions will become the
// user's default permissions.
@@ -283,9 +287,9 @@ namespace Umbraco.Core.Persistence.Repositories
var userPermissions = (
from perm in parentPermissions
from p in perm.AssignedPermissions
select new Tuple<object, string>(perm.UserId, p)).ToList();
select new Tuple<int, string>(perm.UserId, p)).ToList();
permissionsRepo.AssignEntityPermissions(entity, userPermissions);
permissionsRepo.ReplaceEntityPermissions(entity, userPermissions);
//flag the entity's permissions changed flag so we can track those changes.
//Currently only used for the cache refreshers to detect if we should refresh all user permissions cache.
((Content) entity).PermissionsChanged = true;
@@ -555,15 +559,21 @@ namespace Umbraco.Core.Persistence.Repositories
return GetByVersion(dto.ContentVersionDto.VersionId);
}
public void AssignEntityPermissions(IContent entity, char permission, IEnumerable<object> userIds)
/// <summary>
/// Assigns a single permission to the current content item for the specified user ids
/// </summary>
/// <param name="entity"></param>
/// <param name="permission"></param>
/// <param name="userIds"></param>
public void AssignEntityPermission(IContent entity, char permission, IEnumerable<int> userIds)
{
var repo = new PermissionRepository<IContent>(UnitOfWork);
repo.AssignEntityPermissions(entity, permission, userIds);
var repo = new PermissionRepository<IContent>(UnitOfWork, _cacheHelper);
repo.AssignEntityPermission(entity, permission, userIds);
}
public IEnumerable<EntityPermission> GetPermissionsForEntity(int entityId)
{
var repo = new PermissionRepository<IContent>(UnitOfWork);
var repo = new PermissionRepository<IContent>(UnitOfWork, _cacheHelper);
return repo.GetPermissionsForEntity(entityId);
}
@@ -596,33 +606,6 @@ namespace Umbraco.Core.Persistence.Repositories
return content;
}
private PropertyCollection GetPropertyCollection(int id, Guid versionId, IContentType contentType, DateTime createDate, DateTime updateDate)
{
var sql = new Sql();
sql.Select("*")
.From<PropertyDataDto>()
.InnerJoin<PropertyTypeDto>()
.On<PropertyDataDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
.Where<PropertyDataDto>(x => x.NodeId == id)
.Where<PropertyDataDto>(x => x.VersionId == versionId);
var propertyDataDtos = Database.Fetch<PropertyDataDto, PropertyTypeDto>(sql);
var propertyFactory = new PropertyFactory(contentType, versionId, id, createDate, updateDate);
var properties = propertyFactory.BuildEntity(propertyDataDtos);
var newProperties = properties.Where(x => x.HasIdentity == false);
foreach (var property in newProperties)
{
var propertyDataDto = new PropertyDataDto{ NodeId = id, PropertyTypeId = property.PropertyTypeId, VersionId = versionId };
int primaryKey = Convert.ToInt32(Database.Insert(propertyDataDto));
property.Version = versionId;
property.Id = primaryKey;
}
return new PropertyCollection(properties);
}
private string EnsureUniqueNodeName(int parentId, string nodeName, int id = 0)
{
if (EnsureUniqueNaming == false)
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Rdbms;
@@ -54,19 +55,10 @@ namespace Umbraco.Core.Persistence.Repositories
yield return dto.ContentTypeNodeId;
}
}
/// <summary>
/// We need to override this method to ensure that any content cache is cleared
/// </summary>
/// <param name="entity"></param>
/// <remarks>
/// see: http://issues.umbraco.org/issue/U4-1963
/// </remarks>
public override void PersistUpdatedItem(IEntity entity)
protected virtual PropertyType CreatePropertyType(string propertyEditorAlias, DataTypeDatabaseType dbType, string propertyTypeAlias)
{
InMemoryCacheProvider.Current.Clear(typeof(IContent));
RuntimeCacheProvider.Current.Clear(typeof(IContent));
base.PersistUpdatedItem(entity);
return new PropertyType(propertyEditorAlias, dbType);
}
protected void PersistNewBaseContentType(ContentTypeDto dto, IContentTypeComposition entity)
@@ -158,8 +150,7 @@ namespace Umbraco.Core.Persistence.Repositories
//If the Id of the DataType is not set, we resolve it from the db by its PropertyEditorAlias
if (propertyType.DataTypeDefinitionId == 0 || propertyType.DataTypeDefinitionId == default(int))
{
var datatype = Database.FirstOrDefault<DataTypeDto>("WHERE propertyEditorAlias = @alias", new { alias = propertyType.PropertyEditorAlias });
propertyType.DataTypeDefinitionId = datatype.DataTypeId;
AssignDataTypeFromPropertyEditor(propertyType);
}
var propertyTypeDto = propertyFactory.BuildPropertyTypeDto(tabId, propertyType);
int typePrimaryKey = Convert.ToInt32(Database.Insert(propertyTypeDto));
@@ -316,9 +307,12 @@ namespace Umbraco.Core.Persistence.Repositories
//If the Id of the DataType is not set, we resolve it from the db by its PropertyEditorAlias
if (propertyType.DataTypeDefinitionId == 0 || propertyType.DataTypeDefinitionId == default(int))
{
var datatype = Database.FirstOrDefault<DataTypeDto>("WHERE propertyEditorAlias = @alias", new { alias = propertyType.PropertyEditorAlias });
propertyType.DataTypeDefinitionId = datatype.DataTypeId;
AssignDataTypeFromPropertyEditor(propertyType);
}
//validate the alias!
ValidateAlias(propertyType);
var propertyTypeDto = propertyGroupFactory.BuildPropertyTypeDto(tabId, propertyType);
int typePrimaryKey = propertyType.HasIdentity
? Database.Update(propertyTypeDto)
@@ -355,7 +349,7 @@ namespace Umbraco.Core.Persistence.Repositories
var dtos = Database.Fetch<PropertyTypeGroupDto, PropertyTypeDto, DataTypeDto, PropertyTypeGroupDto>(new GroupPropertyTypeRelator().Map, sql);
var propertyGroupFactory = new PropertyGroupFactory(id, createDate, updateDate);
var propertyGroupFactory = new PropertyGroupFactory(id, createDate, updateDate, CreatePropertyType);
var propertyGroups = propertyGroupFactory.BuildEntity(dtos);
return new PropertyGroupCollection(propertyGroups);
}
@@ -372,29 +366,88 @@ namespace Umbraco.Core.Persistence.Repositories
var dtos = Database.Fetch<PropertyTypeDto, DataTypeDto>(sql);
//TODO Move this to a PropertyTypeFactory
var list = (from dto in dtos
where (dto.PropertyTypeGroupId > 0) == false
select
new PropertyType(dto.DataTypeDto.PropertyEditorAlias,
dto.DataTypeDto.DbType.EnumParse<DataTypeDatabaseType>(true))
{
Alias = dto.Alias,
DataTypeDefinitionId = dto.DataTypeId,
Description = dto.Description,
Id = dto.Id,
Name = dto.Name,
HelpText = dto.HelpText,
Mandatory = dto.Mandatory,
SortOrder = dto.SortOrder,
ValidationRegExp = dto.ValidationRegExp,
CreateDate = createDate,
UpdateDate = updateDate
}).ToList();
var list = new List<PropertyType>();
foreach (var dto in dtos.Where(x => (x.PropertyTypeGroupId > 0) == false))
{
var propType = CreatePropertyType(dto.DataTypeDto.PropertyEditorAlias, dto.DataTypeDto.DbType.EnumParse<DataTypeDatabaseType>(true), dto.Alias);
propType.Alias = dto.Alias;
propType.DataTypeDefinitionId = dto.DataTypeId;
propType.Description = dto.Description;
propType.Id = dto.Id;
propType.Name = dto.Name;
propType.HelpText = dto.HelpText;
propType.Mandatory = dto.Mandatory;
propType.SortOrder = dto.SortOrder;
propType.ValidationRegExp = dto.ValidationRegExp;
propType.CreateDate = createDate;
propType.UpdateDate = updateDate;
list.Add(propType);
}
//Reset dirty properties
Parallel.ForEach(list, currentFile => currentFile.ResetDirtyProperties(false));
return new PropertyTypeCollection(list);
}
protected void ValidateAlias(PropertyType pt)
{
Mandate.That<InvalidOperationException>(string.IsNullOrEmpty(pt.Alias) == false,
() =>
{
var message =
string.Format(
"{0} '{1}' cannot have an empty Alias. This is most likely due to invalid characters stripped from the Alias.",
"Property Type",
pt.Name);
var exception = new InvalidOperationException(message);
LogHelper.Error<ContentTypeBaseRepository<TId, TEntity>>(message, exception);
throw exception;
});
}
protected void ValidateAlias(TEntity entity)
{
Mandate.That<InvalidOperationException>(string.IsNullOrEmpty(entity.Alias) == false,
() =>
{
var message =
string.Format(
"{0} '{1}' cannot have an empty Alias. This is most likely due to invalid characters stripped from the Alias.",
typeof(TEntity).Name,
entity.Name);
var exception = new InvalidOperationException(message);
LogHelper.Error<ContentTypeBaseRepository<TId, TEntity>>(message, exception);
throw exception;
});
}
/// <summary>
/// Try to set the data type id based on its ControlId
/// </summary>
/// <param name="propertyType"></param>
private void AssignDataTypeFromPropertyEditor(PropertyType propertyType)
{
//we cannot try to assign a data type of it's empty
if (propertyType.PropertyEditorAlias.IsNullOrWhiteSpace() == false)
{
var sql = new Sql()
.Select("*")
.From<DataTypeDto>()
.Where("propertyEditorAlias = @propertyEditorAlias", new { propertyEditorAlias = propertyType.PropertyEditorAlias })
.OrderBy<DataTypeDto>(typeDto => typeDto.DataTypeId);
var datatype = Database.FirstOrDefault<DataTypeDto>(sql);
//we cannot assign a data type if one was not found
if (datatype != null)
{
propertyType.DataTypeDefinitionId = datatype.DataTypeId;
}
else
{
LogHelper.Warn<ContentTypeBaseRepository<TId, TEntity>>("Could not assign a data type for the property type " + propertyType.Alias + " since no data type was found with a property editor " + propertyType.PropertyEditorAlias);
}
}
}
}
}
@@ -229,18 +229,7 @@ namespace Umbraco.Core.Persistence.Repositories
protected override void PersistUpdatedItem(IContentType entity)
{
Mandate.That<Exception>(string.IsNullOrEmpty(entity.Alias) == false,
() =>
{
var message =
string.Format(
"ContentType '{0}' cannot have an empty Alias. This is most likely due to invalid characters stripped from the Alias.",
entity.Name);
var exception = new Exception(message);
LogHelper.Error<ContentTypeRepository>(message, exception);
throw exception;
});
ValidateAlias(entity);
//Updates Modified date
((ContentType)entity).UpdatingEntity();
@@ -23,8 +23,19 @@ namespace Umbraco.Core.Persistence.Repositories
/// <returns>An enumerable list of <see cref="IContent"/></returns>
IEnumerable<IContent> GetByPublishedVersion(IQuery<IContent> query);
void AssignEntityPermissions(IContent entity, char permission, IEnumerable<object> userIds);
/// <summary>
/// Assigns a single permission to the current content item for the specified user ids
/// </summary>
/// <param name="entity"></param>
/// <param name="permission"></param>
/// <param name="userIds"></param>
void AssignEntityPermission(IContent entity, char permission, IEnumerable<int> userIds);
/// <summary>
/// Gets the list of permissions for the content item
/// </summary>
/// <param name="entityId"></param>
/// <returns></returns>
IEnumerable<EntityPermission> GetPermissionsForEntity(int entityId);
}
}
@@ -0,0 +1,43 @@
using System.Collections.Generic;
using Umbraco.Core.Models;
namespace Umbraco.Core.Persistence.Repositories
{
public interface IMemberGroupRepository : IRepositoryQueryable<int, IMemberGroup>
{
/// <summary>
/// Gets a member group by it's name
/// </summary>
/// <param name="name"></param>
/// <returns></returns>
IMemberGroup GetByName(string name);
/// <summary>
/// Creates the new member group if it doesn't already exist
/// </summary>
/// <param name="roleName"></param>
IMemberGroup CreateIfNotExists(string roleName);
/// <summary>
/// Returns the member groups for a given member
/// </summary>
/// <param name="memberId"></param>
/// <returns></returns>
IEnumerable<IMemberGroup> GetMemberGroupsForMember(int memberId);
/// <summary>
/// Returns the member groups for a given member
/// </summary>
/// <param name="username"></param>
/// <returns></returns>
IEnumerable<IMemberGroup> GetMemberGroupsForMember(string username);
void AssignRoles(string[] usernames, string[] roleNames);
void DissociateRoles(string[] usernames, string[] roleNames);
void AssignRoles(int[] memberIds, string[] roleNames);
void DissociateRoles(int[] memberIds, string[] roleNames);
}
}
@@ -7,8 +7,17 @@ using Umbraco.Core.Persistence.Querying;
namespace Umbraco.Core.Persistence.Repositories
{
internal interface IMemberRepository : IRepositoryVersionable<int, IMember>
public interface IMemberRepository : IRepositoryVersionable<int, IMember>
{
/// <summary>
/// Finds members in a given role
/// </summary>
/// <param name="roleName"></param>
/// <param name="usernameToMatch"></param>
/// <param name="matchType"></param>
/// <returns></returns>
IEnumerable<IMember> FindMembersInRole(string roleName, string usernameToMatch, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
/// <summary>
/// Get all members in a specific group
/// </summary>
@@ -6,7 +6,7 @@ using Umbraco.Core.Persistence.Querying;
namespace Umbraco.Core.Persistence.Repositories
{
internal interface IUserRepository : IRepositoryQueryable<int, IUser>
public interface IUserRepository : IRepositoryQueryable<int, IUser>
{
/// <summary>
/// Gets the count of items based on a complex query
@@ -38,7 +38,7 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="orderBy"></param>
/// <returns></returns>
IEnumerable<IUser> GetPagedResultsByQuery(IQuery<IUser> query, int pageIndex, int pageSize, out int totalRecords, Expression<Func<IUser, string>> orderBy);
/// <summary>
/// Gets the user permissions for the specified entities
@@ -46,7 +46,14 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="userId"></param>
/// <param name="entityIds"></param>
/// <returns></returns>
IEnumerable<EntityPermission> GetUserPermissionsForEntities(object userId, params int[] entityIds);
IEnumerable<EntityPermission> GetUserPermissionsForEntities(int userId, params int[] entityIds);
/// <summary>
/// Replaces the same permission set for a single user to any number of entities
/// </summary>
/// <param name="userId"></param>
/// <param name="permissions"></param>
/// <param name="entityIds"></param>
void ReplaceUserPermissions(int userId, IEnumerable<char> permissions, params int[] entityIds);
}
}
@@ -2,7 +2,7 @@
namespace Umbraco.Core.Persistence.Repositories
{
internal interface IUserTypeRepository : IRepositoryQueryable<int, IUserType>
public interface IUserTypeRepository : IRepositoryQueryable<int, IUserType>
{
}
@@ -131,6 +131,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
var list = new List<string>
{
"DELETE FROM cmsTask WHERE nodeId = @Id",
"DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @Id",
"DELETE FROM umbracoUser2NodePermission WHERE nodeId = @Id",
"DELETE FROM umbracoRelation WHERE parentId = @Id",
@@ -370,33 +371,6 @@ namespace Umbraco.Core.Persistence.Repositories
#endregion
private PropertyCollection GetPropertyCollection(int id, Guid versionId, IMediaType contentType, DateTime createDate, DateTime updateDate)
{
var sql = new Sql();
sql.Select("*")
.From<PropertyDataDto>()
.InnerJoin<PropertyTypeDto>()
.On<PropertyDataDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
.Where<PropertyDataDto>(x => x.NodeId == id)
.Where<PropertyDataDto>(x => x.VersionId == versionId);
var propertyDataDtos = Database.Fetch<PropertyDataDto, PropertyTypeDto>(sql);
var propertyFactory = new PropertyFactory(contentType, versionId, id, createDate, updateDate);
var properties = propertyFactory.BuildEntity(propertyDataDtos);
var newProperties = properties.Where(x => x.HasIdentity == false);
foreach (var property in newProperties)
{
var propertyDataDto = new PropertyDataDto { NodeId = id, PropertyTypeId = property.PropertyTypeId, VersionId = versionId };
int primaryKey = Convert.ToInt32(Database.Insert(propertyDataDto));
property.Version = versionId;
property.Id = primaryKey;
}
return new PropertyCollection(properties);
}
private string EnsureUniqueNodeName(int parentId, string nodeName, int id = 0)
{
if (EnsureUniqueNaming == false)
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Rdbms;
@@ -162,6 +163,8 @@ namespace Umbraco.Core.Persistence.Repositories
protected override void PersistUpdatedItem(IMediaType entity)
{
ValidateAlias(entity);
//Updates Modified date
((MediaType)entity).UpdatingEntity();
@@ -1,7 +1,383 @@
namespace Umbraco.Core.Persistence.Repositories
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.Caching;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Services;
using Umbraco.Core.Cache;
namespace Umbraco.Core.Persistence.Repositories
{
public class MemberGroupRepository
internal class MemberGroupRepository : PetaPocoRepositoryBase<int, IMemberGroup>, IMemberGroupRepository
{
private readonly CacheHelper _cacheHelper;
public MemberGroupRepository(IDatabaseUnitOfWork work, CacheHelper cacheHelper)
: base(work)
{
if (cacheHelper == null) throw new ArgumentNullException("cacheHelper");
_cacheHelper = cacheHelper;
}
public MemberGroupRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, CacheHelper cacheHelper)
: base(work, cache)
{
if (cacheHelper == null) throw new ArgumentNullException("cacheHelper");
_cacheHelper = cacheHelper;
}
private readonly MemberGroupFactory _modelFactory = new MemberGroupFactory();
protected override IMemberGroup PerformGet(int id)
{
var sql = GetBaseQuery(false);
sql.Where(GetBaseWhereClause(), new { Id = id });
var dto = Database.Fetch<NodeDto>(sql).FirstOrDefault();
return dto == null ? null : _modelFactory.BuildEntity(dto);
}
protected override IEnumerable<IMemberGroup> PerformGetAll(params int[] ids)
{
if (ids.Any())
{
var sql = new Sql()
.Select("*")
.From<NodeDto>()
.Where<NodeDto>(dto => dto.NodeObjectType == NodeObjectTypeId)
.Where("umbracoNode.id in (@ids)", new { ids = ids });
return Database.Fetch<NodeDto>(sql)
.Select(x => _modelFactory.BuildEntity(x));
}
else
{
var sql = new Sql()
.From<NodeDto>()
.Where<NodeDto>(dto => dto.NodeObjectType == NodeObjectTypeId);
return Database.Fetch<NodeDto>(sql)
.Select(x => _modelFactory.BuildEntity(x));
}
}
protected override IEnumerable<IMemberGroup> PerformGetByQuery(IQuery<IMemberGroup> query)
{
var sqlClause = GetBaseQuery(false);
var translator = new SqlTranslator<IMemberGroup>(sqlClause, query);
var sql = translator.Translate();
return Database.Fetch<NodeDto>(sql)
.Select(x => _modelFactory.BuildEntity(x));
}
protected override Sql GetBaseQuery(bool isCount)
{
var sql = new Sql();
sql.Select(isCount ? "COUNT(*)" : "*")
.From<NodeDto>()
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId);
return sql;
}
protected override string GetBaseWhereClause()
{
return "umbracoNode.id = @Id";
}
protected override IEnumerable<string> GetDeleteClauses()
{
var list = new[]
{
"DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @Id",
"DELETE FROM umbracoUser2NodePermission WHERE nodeId = @Id",
"DELETE FROM umbracoRelation WHERE parentId = @Id",
"DELETE FROM umbracoRelation WHERE childId = @Id",
"DELETE FROM cmsTagRelationship WHERE nodeId = @Id",
"DELETE FROM cmsMember2MemberGroup WHERE MemberGroup = @Id",
"DELETE FROM umbracoNode WHERE id = @Id"
};
return list;
}
protected override Guid NodeObjectTypeId
{
get { return new Guid(Constants.ObjectTypes.MemberGroup); }
}
protected override void PersistNewItem(IMemberGroup entity)
{
//Save to db
var group = (MemberGroup)entity;
group.AddingEntity();
var dto = _modelFactory.BuildDto(group);
var o = Database.IsNew(dto) ? Convert.ToInt32(Database.Insert(dto)) : Database.Update(dto);
//Update with new correct path
dto.Path = string.Concat("-1,", dto.NodeId);
Database.Update(dto);
group.ResetDirtyProperties();
}
protected override void PersistUpdatedItem(IMemberGroup entity)
{
var dto = _modelFactory.BuildDto(entity);
Database.Update(dto);
((ICanBeDirty)entity).ResetDirtyProperties();
}
public IMemberGroup GetByName(string name)
{
return _cacheHelper.RuntimeCache.GetCacheItem<IMemberGroup>(
string.Format("{0}.{1}", typeof (IMemberGroup).FullName, name),
() =>
{
var qry = new Query<IMemberGroup>().Where(group => group.Name.Equals(name));
var result = GetByQuery(qry);
return result.FirstOrDefault();
},
//cache for 5 mins since that is the default in the RuntimeCacheProvider
TimeSpan.FromMinutes(5),
//sliding is true
true);
}
public IMemberGroup CreateIfNotExists(string roleName)
{
using (var transaction = Database.GetTransaction())
{
var qry = new Query<IMemberGroup>().Where(group => group.Name.Equals(roleName));
var result = GetByQuery(qry);
if (result.Any()) return null;
var grp = new MemberGroup
{
Name = roleName
};
PersistNewItem(grp);
if (SavingMemberGroup.IsRaisedEventCancelled(new SaveEventArgs<IMemberGroup>(grp), this))
{
return null;
}
transaction.Complete();
SavedMemberGroup.RaiseEvent(new SaveEventArgs<IMemberGroup>(grp), this);
return grp;
}
}
public IEnumerable<IMemberGroup> GetMemberGroupsForMember(int memberId)
{
var sql = new Sql();
sql.Select("umbracoNode.*")
.From<NodeDto>()
.InnerJoin<Member2MemberGroupDto>()
.On<NodeDto, Member2MemberGroupDto>(dto => dto.NodeId, dto => dto.MemberGroup)
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId)
.Where<Member2MemberGroupDto>(x => x.Member == memberId);
return Database.Fetch<NodeDto>(sql)
.DistinctBy(dto => dto.NodeId)
.Select(x => _modelFactory.BuildEntity(x));
}
public IEnumerable<IMemberGroup> GetMemberGroupsForMember(string username)
{
//find the member by username
var memberSql = new Sql();
var memberObjectType = new Guid(Constants.ObjectTypes.Member);
var escapedUsername = PetaPocoExtensions.EscapeAtSymbols(username);
memberSql.Select("umbracoNode.id")
.From<NodeDto>()
.InnerJoin<MemberDto>()
.On<NodeDto, MemberDto>(dto => dto.NodeId, dto => dto.NodeId)
.Where<NodeDto>(x => x.NodeObjectType == memberObjectType)
.Where<MemberDto>(x => x.LoginName == escapedUsername);
var memberIdUsername = Database.Fetch<int?>(memberSql).FirstOrDefault();
if (memberIdUsername.HasValue == false)
{
return Enumerable.Empty<IMemberGroup>();
}
var sql = new Sql();
sql.Select("umbracoNode.*")
.From<NodeDto>()
.InnerJoin<Member2MemberGroupDto>()
.On<NodeDto, Member2MemberGroupDto>(dto => dto.NodeId, dto => dto.MemberGroup)
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId)
.Where<Member2MemberGroupDto>(x => x.Member == memberIdUsername.Value);
return Database.Fetch<NodeDto>(sql)
.DistinctBy(dto => dto.NodeId)
.Select(x => _modelFactory.BuildEntity(x));
}
public void AssignRoles(string[] usernames, string[] roleNames)
{
using (var transaction = Database.GetTransaction())
{
//first get the member ids based on the usernames
var memberSql = new Sql();
var memberObjectType = new Guid(Constants.ObjectTypes.Member);
memberSql.Select("umbracoNode.id")
.From<NodeDto>()
.InnerJoin<MemberDto>()
.On<NodeDto, MemberDto>(dto => dto.NodeId, dto => dto.NodeId)
.Where<NodeDto>(x => x.NodeObjectType == memberObjectType)
.Where("cmsMember.LoginName in (@usernames)", new { usernames = usernames });
var memberIds = Database.Fetch<int>(memberSql).ToArray();
AssignRolesInternal(memberIds, roleNames);
transaction.Complete();
}
}
public void DissociateRoles(string[] usernames, string[] roleNames)
{
using (var transaction = Database.GetTransaction())
{
//first get the member ids based on the usernames
var memberSql = new Sql();
var memberObjectType = new Guid(Constants.ObjectTypes.Member);
memberSql.Select("umbracoNode.id")
.From<NodeDto>()
.InnerJoin<MemberDto>()
.On<NodeDto, MemberDto>(dto => dto.NodeId, dto => dto.NodeId)
.Where<NodeDto>(x => x.NodeObjectType == memberObjectType)
.Where("cmsMember.LoginName in (@usernames)", new { usernames = usernames });
var memberIds = Database.Fetch<int>(memberSql).ToArray();
DissociateRolesInternal(memberIds, roleNames);
transaction.Complete();
}
}
public void AssignRoles(int[] memberIds, string[] roleNames)
{
using (var transaction = Database.GetTransaction())
{
AssignRolesInternal(memberIds, roleNames);
transaction.Complete();
}
}
public void AssignRolesInternal(int[] memberIds, string[] roleNames)
{
//create the missing roles first
var existingSql = new Sql()
.Select("*")
.From<NodeDto>()
.Where<NodeDto>(dto => dto.NodeObjectType == NodeObjectTypeId)
.Where("umbracoNode." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text") + " in (@names)", new { names = roleNames });
var existingRoles = Database.Fetch<NodeDto>(existingSql).Select(x => x.Text);
var missingRoles = roleNames.Except(existingRoles);
var missingGroups = missingRoles.Select(x => new MemberGroup {Name = x}).ToArray();
if (SavingMemberGroup.IsRaisedEventCancelled(new SaveEventArgs<IMemberGroup>(missingGroups), this))
{
return;
}
foreach (var m in missingGroups)
{
PersistNewItem(m);
}
SavedMemberGroup.RaiseEvent(new SaveEventArgs<IMemberGroup>(missingGroups), this);
//now go get all the dto's for roles with these role names
var rolesForNames = Database.Fetch<NodeDto>(existingSql).ToArray();
//get the groups that are currently assigned to any of these members
var assignedSql = new Sql();
assignedSql.Select(string.Format(
"{0},{1},{2}",
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text"),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("Member"),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("MemberGroup")))
.From<NodeDto>()
.InnerJoin<Member2MemberGroupDto>()
.On<NodeDto, Member2MemberGroupDto>(dto => dto.NodeId, dto => dto.MemberGroup)
.Where<NodeDto>(x => x.NodeObjectType == NodeObjectTypeId)
.Where("cmsMember2MemberGroup.Member in (@ids)", new { ids = memberIds });
var currentlyAssigned = Database.Fetch<AssignedRolesDto>(assignedSql).ToArray();
//assign the roles for each member id
foreach (var memberId in memberIds)
{
//find any roles for the current member that are currently assigned that
//exist in the roleNames list, then determine which ones are not currently assigned.
var mId = memberId;
var found = currentlyAssigned.Where(x => x.MemberId == mId).ToArray();
var assignedRoles = found.Where(x => roleNames.Contains(x.RoleName)).Select(x => x.RoleName);
var nonAssignedRoles = roleNames.Except(assignedRoles);
foreach (var toAssign in nonAssignedRoles)
{
var groupId = rolesForNames.First(x => x.Text == toAssign).NodeId;
Database.Insert(new Member2MemberGroupDto { Member = mId, MemberGroup = groupId });
}
}
}
public void DissociateRoles(int[] memberIds, string[] roleNames)
{
using (var transaction = Database.GetTransaction())
{
DissociateRolesInternal(memberIds, roleNames);
transaction.Complete();
}
}
private void DissociateRolesInternal(int[] memberIds, string[] roleNames)
{
var existingSql = new Sql()
.Select("*")
.From<NodeDto>()
.Where<NodeDto>(dto => dto.NodeObjectType == NodeObjectTypeId)
.Where("umbracoNode." + SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("text") + " in (@names)", new { names = roleNames });
var existingRolesIds = Database.Fetch<NodeDto>(existingSql).Select(x => x.NodeId).ToArray();
Database.Execute("DELETE FROM cmsMember2MemberGroup WHERE Member IN (@memberIds) AND MemberGroup IN (@memberGroups)",
new { memberIds = memberIds, memberGroups = existingRolesIds });
}
private class AssignedRolesDto
{
[Column("text")]
public string RoleName { get; set; }
[Column("Member")]
public int MemberId { get; set; }
[Column("MemberGroup")]
public int MemberGroupId { get; set; }
}
/// <summary>
/// Occurs before Save
/// </summary>
internal static event TypedEventHandler<IMemberGroupRepository, SaveEventArgs<IMemberGroup>> SavingMemberGroup;
/// <summary>
/// Occurs after Save
/// </summary>
internal static event TypedEventHandler<IMemberGroupRepository, SaveEventArgs<IMemberGroup>> SavedMemberGroup;
}
}
@@ -24,23 +24,26 @@ namespace Umbraco.Core.Persistence.Repositories
{
private readonly IMemberTypeRepository _memberTypeRepository;
private readonly ITagsRepository _tagRepository;
private readonly IMemberGroupRepository _memberGroupRepository;
public MemberRepository(IDatabaseUnitOfWork work, IMemberTypeRepository memberTypeRepository, ITagsRepository tagRepository)
public MemberRepository(IDatabaseUnitOfWork work, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagsRepository tagRepository)
: base(work)
{
if (memberTypeRepository == null) throw new ArgumentNullException("memberTypeRepository");
if (tagRepository == null) throw new ArgumentNullException("tagRepository");
_memberTypeRepository = memberTypeRepository;
_tagRepository = tagRepository;
_memberGroupRepository = memberGroupRepository;
}
public MemberRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IMemberTypeRepository memberTypeRepository, ITagsRepository tagRepository)
public MemberRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IMemberTypeRepository memberTypeRepository, IMemberGroupRepository memberGroupRepository, ITagsRepository tagRepository)
: base(work, cache)
{
if (memberTypeRepository == null) throw new ArgumentNullException("memberTypeRepository");
if (tagRepository == null) throw new ArgumentNullException("tagRepository");
_memberTypeRepository = memberTypeRepository;
_tagRepository = tagRepository;
_memberGroupRepository = memberGroupRepository;
}
#region Overrides of RepositoryBase<int, IMembershipUser>
@@ -169,6 +172,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
var list = new List<string>
{
"DELETE FROM cmsTask WHERE nodeId = @Id",
"DELETE FROM umbracoUser2NodeNotify WHERE nodeId = @Id",
"DELETE FROM umbracoUser2NodePermission WHERE nodeId = @Id",
"DELETE FROM umbracoRelation WHERE parentId = @Id",
@@ -242,7 +246,12 @@ namespace Umbraco.Core.Persistence.Repositories
//Create the PropertyData for this version - cmsPropertyData
var propertyFactory = new PropertyFactory(entity.ContentType, entity.Version, entity.Id);
var propertyDataDtos = propertyFactory.BuildDto(((Member)entity).Properties);
//Add Properties
// - don't try to save the property if it doesn't exist (or doesn't have an ID) on the content type
// - this can occur if the member type doesn't contain the built-in properties that the
// - member object contains.
var propsToPersist = entity.Properties.Where(x => x.PropertyType.HasIdentity).ToArray();
var propertyDataDtos = propertyFactory.BuildDto(propsToPersist);
var keyDictionary = new Dictionary<int, int>();
//Add Properties
@@ -253,7 +262,7 @@ namespace Umbraco.Core.Persistence.Repositories
}
//Update Properties with its newly set Id
foreach (var property in ((Member)entity).Properties)
foreach (var property in propsToPersist)
{
property.Id = keyDictionary[property.PropertyTypeId];
}
@@ -338,12 +347,10 @@ namespace Umbraco.Core.Persistence.Repositories
//Add Properties
// - don't try to save the property if it doesn't exist (or doesn't have an ID) on the content type
// - this can occur if the member type doesn't contain the built-in properties that the
// - member object contains.
var existingProperties = entity.Properties
.Where(property => entity.ContentType.PropertyTypes.Any(x => x.Alias == property.Alias && x.HasIdentity))
.ToList();
// - member object contains.
var propsToPersist = entity.Properties.Where(x => x.PropertyType.HasIdentity).ToArray();
var propertyDataDtos = propertyFactory.BuildDto(existingProperties);
var propertyDataDtos = propertyFactory.BuildDto(propsToPersist);
foreach (var propertyDataDto in propertyDataDtos)
{
@@ -428,6 +435,57 @@ namespace Umbraco.Core.Persistence.Repositories
#endregion
public IEnumerable<IMember> FindMembersInRole(string roleName, string usernameToMatch, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
{
//get the group id
var grpQry = new Query<IMemberGroup>().Where(group => group.Name.Equals(roleName));
var memberGroup = _memberGroupRepository.GetByQuery(grpQry).FirstOrDefault();
if (memberGroup == null) return Enumerable.Empty<IMember>();
// get the members by username
var query = new Query<IMember>();
switch (matchType)
{
case StringPropertyMatchType.Exact:
query.Where(member => member.Username.Equals(usernameToMatch));
break;
case StringPropertyMatchType.Contains:
query.Where(member => member.Username.Contains(usernameToMatch));
break;
case StringPropertyMatchType.StartsWith:
query.Where(member => member.Username.StartsWith(usernameToMatch));
break;
case StringPropertyMatchType.EndsWith:
query.Where(member => member.Username.EndsWith(usernameToMatch));
break;
case StringPropertyMatchType.Wildcard:
query.Where(member => member.Username.SqlWildcard(usernameToMatch, TextColumnType.NVarchar));
break;
default:
throw new ArgumentOutOfRangeException("matchType");
}
var matchedMembers = GetByQuery(query).ToArray();
var membersInGroup = new List<IMember>();
//then we need to filter the matched members that are in the role
//since the max sql params are 2100 on sql server, we'll reduce that to be safe for potentially other servers and run the queries in batches
var inGroups = matchedMembers.InGroupsOf(1000);
foreach (var batch in inGroups)
{
var memberIdBatch = batch.Select(x => x.Id);
var sql = new Sql().Select("*").From<Member2MemberGroupDto>()
.Where<Member2MemberGroupDto>(dto => dto.MemberGroup == memberGroup.Id)
.Where("Member IN (@memberIds)", new { memberIds = memberIdBatch });
var memberIdsInGroup = Database.Fetch<Member2MemberGroupDto>(sql)
.Select(x => x.Member).ToArray();
membersInGroup.AddRange(matchedMembers.Where(x => memberIdsInGroup.Contains(x.Id)));
}
return membersInGroup;
}
/// <summary>
/// Get all members in a specific group
/// </summary>
@@ -435,9 +493,13 @@ namespace Umbraco.Core.Persistence.Repositories
/// <returns></returns>
public IEnumerable<IMember> GetByMemberGroup(string groupName)
{
var subquery = GetSubquery().Where<NodeDto>(x => x.Text == groupName);
var grpQry = new Query<IMemberGroup>().Where(group => group.Name.Equals(groupName));
var memberGroup = _memberGroupRepository.GetByQuery(grpQry).FirstOrDefault();
if (memberGroup == null) return Enumerable.Empty<IMember>();
var subQuery = new Sql().Select("Member").From<Member2MemberGroupDto>().Where<Member2MemberGroupDto>(dto => dto.MemberGroup == memberGroup.Id);
var sql = GetBaseQuery(false)
.Append(new Sql("WHERE umbracoNode.id IN (" + subquery.SQL + ")", subquery.Arguments))
.Append(new Sql("WHERE umbracoNode.id IN (" + subQuery.SQL + ")", subQuery.Arguments))
.OrderByDescending<ContentVersionDto>(x => x.VersionDate)
.OrderBy<NodeDto>(x => x.SortOrder);
@@ -548,6 +610,8 @@ namespace Umbraco.Core.Persistence.Repositories
var factory = new MemberReadOnlyFactory(memberTypes);
var member = factory.BuildEntity(dto);
member.Properties = GetPropertyCollection(dto.NodeId, dto.VersionId, member.ContentType, dto.CreateDate, dto.UpdateDate);
return member;
}
@@ -561,8 +625,15 @@ namespace Umbraco.Core.Persistence.Repositories
var memberTypeList = _memberTypeRepository.GetAll();
memberTypeList.ForEach(x => memberTypes.Add(x.Alias, x));
var entities = new List<IMember>();
var factory = new MemberReadOnlyFactory(memberTypes);
return dtos.Select(factory.BuildEntity);
foreach (var dto in dtos)
{
var entity = factory.BuildEntity(dto);
entity.Properties = GetPropertyCollection(dto.NodeId, dto.VersionId, entity.ContentType, dto.CreateDate, dto.UpdateDate);
entities.Add(entity);
}
return entities;
}
}
}
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
@@ -17,17 +18,17 @@ namespace Umbraco.Core.Persistence.Repositories
/// </summary>
internal class MemberTypeRepository : ContentTypeBaseRepository<int, IMemberType>, IMemberTypeRepository
{
public MemberTypeRepository(IDatabaseUnitOfWork work)
public MemberTypeRepository(IDatabaseUnitOfWork work)
: base(work)
{
}
public MemberTypeRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache)
public MemberTypeRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache)
: base(work, cache)
{
}
#region Overrides of RepositoryBase<int, IMemberType>
#region Overrides of RepositoryBase<int, IMemberType>
protected override IMemberType PerformGet(int id)
{
@@ -39,13 +40,13 @@ namespace Umbraco.Core.Persistence.Repositories
Database.Fetch<MemberTypeReadOnlyDto, PropertyTypeReadOnlyDto, PropertyTypeGroupReadOnlyDto, MemberTypeReadOnlyDto>(
new PropertyTypePropertyGroupRelator().Map, sql);
if (dtos == null || dtos.Any() == false)
return null;
if (dtos == null || dtos.Any() == false)
return null;
var factory = new MemberTypeReadOnlyFactory();
var member = factory.BuildEntity(dtos.First());
var factory = new MemberTypeReadOnlyFactory();
var member = factory.BuildEntity(dtos.First());
return member;
return member;
}
protected override IEnumerable<IMemberType> PerformGetAll(params int[] ids)
@@ -98,7 +99,7 @@ namespace Umbraco.Core.Persistence.Repositories
return sql;
}
sql.Select("umbracoNode.*", "cmsContentType.*", "cmsPropertyType.id AS PropertyTypeId", "cmsPropertyType.Alias",
sql.Select("umbracoNode.*", "cmsContentType.*", "cmsPropertyType.id AS PropertyTypeId", "cmsPropertyType.Alias",
"cmsPropertyType.Name", "cmsPropertyType.Description", "cmsPropertyType.helpText", "cmsPropertyType.mandatory",
"cmsPropertyType.validationRegExp", "cmsPropertyType.dataTypeId", "cmsPropertyType.sortOrder AS PropertyTypeSortOrder",
"cmsPropertyType.propertyTypeGroupId AS PropertyTypesGroupId", "cmsMemberType.memberCanEdit", "cmsMemberType.viewOnProfile",
@@ -168,15 +169,18 @@ namespace Umbraco.Core.Persistence.Repositories
((MemberType)entity).AddingEntity();
//By Convention we add 9 stnd PropertyTypes to an Umbraco MemberType
entity.AddPropertyGroup(Constants.Conventions.Member.StandardPropertiesGroupName);
var standardPropertyTypes = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
foreach (var standardPropertyType in standardPropertyTypes)
{
entity.AddPropertyType(standardPropertyType.Value);
entity.AddPropertyType(standardPropertyType.Value, Constants.Conventions.Member.StandardPropertiesGroupName);
}
var factory = new MemberTypeFactory(NodeObjectTypeId);
var dto = factory.BuildDto(entity);
EnsureExplicitDataTypeForBuiltInProperties(entity);
PersistNewBaseContentType(dto, entity);
//Handles the MemberTypeDto (cmsMemberType table)
@@ -191,6 +195,8 @@ namespace Umbraco.Core.Persistence.Repositories
protected override void PersistUpdatedItem(IMemberType entity)
{
ValidateAlias(entity);
//Updates Modified date
((MemberType)entity).UpdatingEntity();
@@ -210,10 +216,12 @@ namespace Umbraco.Core.Persistence.Repositories
var factory = new MemberTypeFactory(NodeObjectTypeId);
var dto = factory.BuildDto(entity);
EnsureExplicitDataTypeForBuiltInProperties(entity);
PersistUpdatedBaseContentType(dto, entity);
//Remove existing entries before inserting new ones
Database.Delete<MemberTypeDto>("WHERE NodeId = @Id", new {Id = entity.Id});
Database.Delete<MemberTypeDto>("WHERE NodeId = @Id", new { Id = entity.Id });
//Handles the MemberTypeDto (cmsMemberType table)
var memberTypeDtos = factory.BuildMemberTypeDtos(entity);
@@ -227,7 +235,50 @@ namespace Umbraco.Core.Persistence.Repositories
#endregion
private IEnumerable<IMemberType> BuildFromDtos(List<MemberTypeReadOnlyDto> dtos)
/// <summary>
/// Override so we can specify explicit db type's on any property types that are built-in.
/// </summary>
/// <param name="propertyEditorAlias"></param>
/// <param name="dbType"></param>
/// <param name="propertyTypeAlias"></param>
/// <returns></returns>
protected override PropertyType CreatePropertyType(string propertyEditorAlias, DataTypeDatabaseType dbType, string propertyTypeAlias)
{
//custom property type constructor logic to set explicit dbtype's for built in properties
var stdProps = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
var propDbType = GetDbTypeForBuiltInProperty(propertyTypeAlias, dbType, stdProps);
return new PropertyType(propertyEditorAlias, propDbType.Result,
//This flag tells the property type that it has an explicit dbtype and that it cannot be changed
// which is what we want for the built-in properties.
propDbType.Success);
}
/// <summary>
/// Ensure that all the built-in membership provider properties have their correct data type
/// and property editors assigned. This occurs prior to saving so that the correct values are persisted.
/// </summary>
/// <param name="memberType"></param>
private static void EnsureExplicitDataTypeForBuiltInProperties(IContentTypeBase memberType)
{
var stdProps = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
foreach (var propertyType in memberType.PropertyTypes)
{
var dbTypeAttempt = GetDbTypeForBuiltInProperty(propertyType.Alias, propertyType.DataTypeDatabaseType, stdProps);
if (dbTypeAttempt)
{
//this reset's it's current data type reference which will be re-assigned based on the property editor assigned on the next line
propertyType.DataTypeDefinitionId = 0;
propertyType.DataTypeId = GetPropertyEditorForBuiltInProperty(propertyType.Alias, propertyType.DataTypeId, stdProps).Result;
}
}
}
/// <summary>
/// Builds a collection of entities from a collection of Dtos
/// </summary>
/// <param name="dtos"></param>
/// <returns></returns>
private static IEnumerable<IMemberType> BuildFromDtos(List<MemberTypeReadOnlyDto> dtos)
{
if (dtos == null || dtos.Any() == false)
return Enumerable.Empty<IMemberType>();
@@ -235,5 +286,58 @@ namespace Umbraco.Core.Persistence.Repositories
var factory = new MemberTypeReadOnlyFactory();
return dtos.Select(factory.BuildEntity);
}
/// <summary>
/// If this is one of our internal properties - we will manually assign the data type since they must
/// always correspond to the correct db type no matter what the backing data type is assigned.
/// </summary>
/// <param name="propAlias"></param>
/// <param name="dbType"></param>
/// <param name="standardProps"></param>
/// <returns>
/// Successful attempt if it was a built in property
/// </returns>
internal static Attempt<DataTypeDatabaseType> GetDbTypeForBuiltInProperty(
string propAlias,
DataTypeDatabaseType dbType,
Dictionary<string, PropertyType> standardProps)
{
var aliases = standardProps.Select(x => x.Key).ToArray();
//check if it is built in
if (aliases.Contains(propAlias))
{
//return the pre-determined db type for this property
return Attempt<DataTypeDatabaseType>.Succeed(standardProps.Single(x => x.Key == propAlias).Value.DataTypeDatabaseType);
}
return Attempt<DataTypeDatabaseType>.Fail(dbType);
}
/// <summary>
///
/// </summary>
/// <param name="propAlias"></param>
/// <param name="propertyEditor"></param>
/// <param name="standardProps"></param>
/// <returns>
/// Successful attempt if it was a built in property
/// </returns>
internal static Attempt<Guid> GetPropertyEditorForBuiltInProperty(
string propAlias,
Guid propertyEditor,
Dictionary<string, PropertyType> standardProps)
{
var aliases = standardProps.Select(x => x.Key).ToArray();
//check if it is built in
if (aliases.Contains(propAlias))
{
//return the pre-determined db type for this property
return Attempt<Guid>.Succeed(standardProps.Single(x => x.Key == propAlias).Value.DataTypeId);
}
return Attempt<Guid>.Fail(propertyEditor);
}
}
}
@@ -1,14 +1,20 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Web.Caching;
using Umbraco.Core.Events;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using Umbraco.Core.Services;
using CacheKeys = Umbraco.Core.Cache.CacheKeys;
using Umbraco.Core.Cache;
namespace Umbraco.Core.Persistence.Repositories
{
@@ -20,10 +26,12 @@ namespace Umbraco.Core.Persistence.Repositories
where TEntity : class, IAggregateRoot
{
private readonly IDatabaseUnitOfWork _unitOfWork;
private readonly CacheHelper _cache;
internal PermissionRepository(IDatabaseUnitOfWork unitOfWork)
internal PermissionRepository(IDatabaseUnitOfWork unitOfWork, CacheHelper cache)
{
_unitOfWork = unitOfWork;
_cache = cache;
}
/// <summary>
@@ -32,39 +40,57 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="userId"></param>
/// <param name="entityIds"></param>
/// <returns></returns>
internal IEnumerable<EntityPermission> GetUserPermissionsForEntities(object userId, params int[] entityIds)
public IEnumerable<EntityPermission> GetUserPermissionsForEntities(int userId, params int[] entityIds)
{
var entityIdKey = string.Join(",", entityIds.Select(x => x.ToString(CultureInfo.InvariantCulture)));
return _cache.RuntimeCache.GetCacheItem<IEnumerable<EntityPermission>>(
string.Format("{0}{1}{2}", CacheKeys.UserPermissionsCacheKey, userId, entityIdKey),
() =>
{
var whereBuilder = new StringBuilder();
var whereBuilder = new StringBuilder();
//where userId = @userId AND
whereBuilder.Append(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("userId"));
whereBuilder.Append("=");
whereBuilder.Append(userId);
whereBuilder.Append(" AND ");
//where userId = @userId AND
whereBuilder.Append(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("userId"));
whereBuilder.Append("=");
whereBuilder.Append(userId);
//where nodeId = @nodeId1 OR nodeId = @nodeId2, etc...
whereBuilder.Append("(");
for (var index = 0; index < entityIds.Length; index++)
{
var entityId = entityIds[index];
whereBuilder.Append(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("nodeId"));
whereBuilder.Append("=");
whereBuilder.Append(entityId);
if (index < entityIds.Length - 1)
{
whereBuilder.Append(" OR ");
}
}
whereBuilder.Append(")");
if (entityIds.Any())
{
whereBuilder.Append(" AND ");
var sql = new Sql();
sql.Select("*")
.From<User2NodePermissionDto>()
.Where(whereBuilder.ToString());
//where nodeId = @nodeId1 OR nodeId = @nodeId2, etc...
whereBuilder.Append("(");
for (var index = 0; index < entityIds.Length; index++)
{
var entityId = entityIds[index];
whereBuilder.Append(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("nodeId"));
whereBuilder.Append("=");
whereBuilder.Append(entityId);
if (index < entityIds.Length - 1)
{
whereBuilder.Append(" OR ");
}
}
whereBuilder.Append(")");
}
var sql = new Sql();
sql.Select("*")
.From<User2NodePermissionDto>()
.Where(whereBuilder.ToString());
//ToArray() to ensure it's all fetched from the db once.
var result = _unitOfWork.Database.Fetch<User2NodePermissionDto>(sql).ToArray();
return ConvertToPermissionList(result);
},
//Since this cache can be quite large (http://issues.umbraco.org/issue/U4-2161) we will only have this exist in cache for 20 minutes,
// then it will refresh from the database.
new TimeSpan(0, 20, 0),
//Since this cache can be quite large (http://issues.umbraco.org/issue/U4-2161) we will make this priority below average
priority: CacheItemPriority.BelowNormal);
//ToArray() to ensure it's all fetched from the db once.
var result = _unitOfWork.Database.Fetch<User2NodePermissionDto>(sql).ToArray();
return ConvertToPermissionList(result);
}
/// <summary>
@@ -72,7 +98,7 @@ namespace Umbraco.Core.Persistence.Repositories
/// </summary>
/// <param name="entityId"></param>
/// <returns></returns>
internal IEnumerable<EntityPermission> GetPermissionsForEntity(int entityId)
public IEnumerable<EntityPermission> GetPermissionsForEntity(int entityId)
{
var sql = new Sql();
sql.Select("*")
@@ -85,7 +111,118 @@ namespace Umbraco.Core.Persistence.Repositories
return ConvertToPermissionList(result);
}
private IEnumerable<EntityPermission> ConvertToPermissionList(IEnumerable<User2NodePermissionDto> result)
/// <summary>
/// Assigns the same permission set for a single user to any number of entities
/// </summary>
/// <param name="userId"></param>
/// <param name="permissions"></param>
/// <param name="entityIds"></param>
/// <remarks>
/// This will first clear the permissions for this user and entities and recreate them
/// </remarks>
public void ReplaceUserPermissions(int userId, IEnumerable<char> permissions, params int[] entityIds)
{
var db = _unitOfWork.Database;
using (var trans = db.GetTransaction())
{
db.Execute("DELETE FROM umbracoUser2NodePermission WHERE userId=@userId AND nodeId in (@nodeIds)",
new {userId = userId, nodeIds = entityIds});
var toInsert = new List<User2NodePermissionDto>();
foreach (var p in permissions)
{
foreach (var e in entityIds)
{
toInsert.Add(new User2NodePermissionDto
{
NodeId = e,
Permission = p.ToString(CultureInfo.InvariantCulture),
UserId = userId
});
}
}
_unitOfWork.Database.BulkInsertRecords(toInsert, trans);
trans.Complete();
//Raise the event
AssignedPermissions.RaiseEvent(
new SaveEventArgs<EntityPermission>(ConvertToPermissionList(toInsert), false), this);
}
}
/// <summary>
/// Assigns one permission to an entity for multiple users
/// </summary>
/// <param name="entity"></param>
/// <param name="permission"></param>
/// <param name="userIds"></param>
public void AssignEntityPermission(TEntity entity, char permission, IEnumerable<int> userIds)
{
var db = _unitOfWork.Database;
using (var trans = db.GetTransaction())
{
db.Execute("DELETE FROM umbracoUser2NodePermission WHERE nodeId=@nodeId AND permission=@permission AND userId in (@userIds)",
new
{
nodeId = entity.Id,
permission = permission.ToString(CultureInfo.InvariantCulture),
userIds = userIds
});
var actions = userIds.Select(id => new User2NodePermissionDto
{
NodeId = entity.Id,
Permission = permission.ToString(CultureInfo.InvariantCulture),
UserId = id
}).ToArray();
_unitOfWork.Database.BulkInsertRecords(actions, trans);
trans.Complete();
//Raise the event
AssignedPermissions.RaiseEvent(
new SaveEventArgs<EntityPermission>(ConvertToPermissionList(actions), false), this);
}
}
/// <summary>
/// Assigns permissions to an entity for multiple users/permission entries
/// </summary>
/// <param name="entity"></param>
/// <param name="userPermissions">
/// A key/value pair list containing a userId and a permission to assign
/// </param>
/// <remarks>
/// This will first clear the permissions for this entity then re-create them
/// </remarks>
public void ReplaceEntityPermissions(TEntity entity, IEnumerable<Tuple<int, string>> userPermissions)
{
var db = _unitOfWork.Database;
using (var trans = db.GetTransaction())
{
db.Execute("DELETE FROM umbracoUser2NodePermission WHERE nodeId=@nodeId", new { nodeId = entity.Id });
var actions = userPermissions.Select(p => new User2NodePermissionDto
{
NodeId = entity.Id,
Permission = p.Item2,
UserId = p.Item1
}).ToArray();
_unitOfWork.Database.BulkInsertRecords(actions, trans);
trans.Complete();
//Raise the event
AssignedPermissions.RaiseEvent(
new SaveEventArgs<EntityPermission>(ConvertToPermissionList(actions), false), this);
}
}
private static IEnumerable<EntityPermission> ConvertToPermissionList(IEnumerable<User2NodePermissionDto> result)
{
var permissions = new List<EntityPermission>();
var nodePermissions = result.GroupBy(x => x.NodeId);
@@ -99,118 +236,8 @@ namespace Umbraco.Core.Persistence.Repositories
}
}
return permissions;
}
/// <summary>
/// Assigns one permission to an entity for multiple users
/// </summary>
/// <param name="entity"></param>
/// <param name="permission"></param>
/// <param name="userIds"></param>
internal void AssignEntityPermissions(TEntity entity, char permission, IEnumerable<object> userIds)
{
var actions = userIds.Select(id => new User2NodePermissionDto
{
NodeId = entity.Id,
Permission = permission.ToString(CultureInfo.InvariantCulture),
UserId = (int)id
});
_unitOfWork.Database.BulkInsertRecords(actions);
}
/// <summary>
/// Assigns permissions to an entity for multiple users/permission entries
/// </summary>
/// <param name="entity"></param>
/// <param name="userPermissions">
/// A key/value pair list containing a userId and a permission to assign
/// </param>
internal void AssignEntityPermissions(TEntity entity, IEnumerable<Tuple<object, string>> userPermissions)
{
var actions = userPermissions.Select(p => new User2NodePermissionDto
{
NodeId = entity.Id,
Permission = p.Item2,
UserId = (int)p.Item1
});
_unitOfWork.Database.BulkInsertRecords(actions);
}
/// <summary>
/// Replace permissions for an entity for multiple users
/// </summary>
/// <param name="entity"></param>
/// <param name="permissions"></param>
/// <param name="userIds"></param>
internal void ReplaceEntityPermissions(TEntity entity, string permissions, IEnumerable<object> userIds)
{
_unitOfWork.Database.Update<User2NodePermissionDto>(
GenerateReplaceEntityPermissionsSql(entity.Id, permissions, userIds.ToArray()));
}
/// <summary>
/// An overload to replace entity permissions and all replace all descendant permissions
/// </summary>
/// <param name="entity"></param>
/// <param name="permissions"></param>
/// <param name="getDescendantIds">
/// A callback to get the descendant Ids of the current entity
/// </param>
/// <param name="userIds"></param>
internal void ReplaceEntityPermissions(TEntity entity, string permissions, Func<IEntity, IEnumerable<int>> getDescendantIds, IEnumerable<object> userIds)
{
_unitOfWork.Database.Update<User2NodePermissionDto>(
GenerateReplaceEntityPermissionsSql(
new[] { entity.Id }.Concat(getDescendantIds(entity)).ToArray(),
permissions,
userIds.ToArray()));
}
internal static string GenerateReplaceEntityPermissionsSql(int entityId, string permissions, object[] userIds)
{
return GenerateReplaceEntityPermissionsSql(new[] { entityId }, permissions, userIds);
}
internal static string GenerateReplaceEntityPermissionsSql(int[] entityIds, string permissions, object[] userIds)
{
//create the "SET" clause of the update statement
var sqlSet = string.Format("SET {0}={1}",
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName("permission"),
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedValue(permissions));
//build the nodeIds part of the where clause
var sqlNodeWhere = BuildOrClause(entityIds, "nodeId");
//build up the userIds part of the where clause
var userWhereBuilder = BuildOrClause(userIds, "userId");
var sqlWhere = new Sql();
sqlWhere.Where(string.Format("{0} AND {1}", sqlNodeWhere, userWhereBuilder));
return string.Format("{0} {1}", sqlSet, sqlWhere.SQL);
}
private static string BuildOrClause<T>(IEnumerable<T> ids, string colName)
{
var asArray = ids.ToArray();
var userWhereBuilder = new StringBuilder();
userWhereBuilder.Append("(");
for (var index = 0; index < asArray.Length; index++)
{
var userId = asArray[index];
userWhereBuilder.Append(SqlSyntaxContext.SqlSyntaxProvider.GetQuotedColumnName(colName));
userWhereBuilder.Append("=");
userWhereBuilder.Append(userId);
if (index < asArray.Length - 1)
{
userWhereBuilder.Append(" OR ");
}
}
userWhereBuilder.Append(")");
return userWhereBuilder.ToString();
}
public static event TypedEventHandler<PermissionRepository<TEntity>, SaveEventArgs<EntityPermission>> AssignedPermissions;
}
}
@@ -58,7 +58,7 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="entity"></param>
public void AddOrUpdate(TEntity entity)
{
if (!entity.HasIdentity)
if (entity.HasIdentity == false)
{
_work.RegisterAdded(entity, this);
}
@@ -104,7 +104,7 @@ namespace Umbraco.Core.Persistence.Repositories
{
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
TracksChangesEntityBase asEntity = entity as TracksChangesEntityBase;
var asEntity = entity as TracksChangesEntityBase;
if (asEntity != null)
{
asEntity.ResetDirtyProperties(false);
@@ -135,13 +135,16 @@ namespace Umbraco.Core.Persistence.Repositories
{
if (ids.Any())
{
var entities = _cache.GetByIds(typeof(TEntity), ids.Select(id => id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString())).ToList());
var entities = _cache.GetByIds(
typeof (TEntity), ids.Select(id => id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString())).ToList())
.ToArray();
if (ids.Count().Equals(entities.Count()) && entities.Any(x => x == null) == false)
return entities.Select(x => (TEntity)x);
}
else
{
var allEntities = _cache.GetAllByType(typeof(TEntity));
var allEntities = _cache.GetAllByType(typeof (TEntity)).ToArray();
if (allEntities.Any())
{
@@ -154,7 +157,10 @@ namespace Umbraco.Core.Persistence.Repositories
}
}
var entityCollection = PerformGetAll(ids);
var entityCollection = PerformGetAll(ids)
//ensure we don't include any null refs in the returned collection!
.WhereNotNull()
.ToArray();
foreach (var entity in entityCollection)
{
@@ -175,7 +181,9 @@ namespace Umbraco.Core.Persistence.Repositories
/// <returns></returns>
public IEnumerable<TEntity> GetByQuery(IQuery<TEntity> query)
{
return PerformGetByQuery(query);
return PerformGetByQuery(query)
//ensure we don't include any null refs in the returned collection!
.WhereNotNull();
}
protected abstract bool PerformExists(TId id);
@@ -22,17 +22,20 @@ namespace Umbraco.Core.Persistence.Repositories
internal class UserRepository : PetaPocoRepositoryBase<int, IUser>, IUserRepository
{
private readonly IUserTypeRepository _userTypeRepository;
private readonly CacheHelper _cacheHelper;
public UserRepository(IDatabaseUnitOfWork work, IUserTypeRepository userTypeRepository)
public UserRepository(IDatabaseUnitOfWork work, IUserTypeRepository userTypeRepository, CacheHelper cacheHelper)
: base(work)
{
_userTypeRepository = userTypeRepository;
_cacheHelper = cacheHelper;
}
public UserRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IUserTypeRepository userTypeRepository)
public UserRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IUserTypeRepository userTypeRepository, CacheHelper cacheHelper)
: base(work, cache)
{
_userTypeRepository = userTypeRepository;
_cacheHelper = cacheHelper;
}
#region Overrides of RepositoryBase<int,IUser>
@@ -128,6 +131,8 @@ namespace Umbraco.Core.Persistence.Repositories
{
var list = new List<string>
{
"DELETE FROM cmsTask WHERE userId = @Id",
"DELETE FROM cmsTask WHERE parentUserId = @Id",
"DELETE FROM umbracoUser2NodePermission WHERE userId = @Id",
"DELETE FROM umbracoUser2NodeNotify WHERE userId = @Id",
"DELETE FROM umbracoUserLogins WHERE userId = @Id",
@@ -315,12 +320,24 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="userId"></param>
/// <param name="entityIds"></param>
/// <returns></returns>
public IEnumerable<EntityPermission> GetUserPermissionsForEntities(object userId, params int[] entityIds)
public IEnumerable<EntityPermission> GetUserPermissionsForEntities(int userId, params int[] entityIds)
{
var repo = new PermissionRepository<IContent>(UnitOfWork);
var repo = new PermissionRepository<IContent>(UnitOfWork, _cacheHelper);
return repo.GetUserPermissionsForEntities(userId, entityIds);
}
/// <summary>
/// Replaces the same permission set for a single user to any number of entities
/// </summary>
/// <param name="userId"></param>
/// <param name="permissions"></param>
/// <param name="entityIds"></param>
public void ReplaceUserPermissions(int userId, IEnumerable<char> permissions, params int[] entityIds)
{
var repo = new PermissionRepository<IContent>(UnitOfWork, _cacheHelper);
repo.ReplaceUserPermissions(userId, permissions, entityIds);
}
#endregion
private IEnumerable<IUser> ConvertFromDtos(IEnumerable<UserDto> dtos)
@@ -5,6 +5,7 @@ using Umbraco.Core.Models;
using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.Caching;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Persistence.Repositories
@@ -120,5 +121,42 @@ namespace Umbraco.Core.Persistence.Repositories
}
}
}
/// <summary>
/// This is a fix for U4-1407 - when property types are added to a content type - the property of the entity are not actually created
/// and we get YSODs
/// </summary>
/// <param name="id"></param>
/// <param name="versionId"></param>
/// <param name="contentType"></param>
/// <param name="createDate"></param>
/// <param name="updateDate"></param>
/// <returns></returns>
protected PropertyCollection GetPropertyCollection(int id, Guid versionId, IContentTypeComposition contentType, DateTime createDate, DateTime updateDate)
{
var sql = new Sql();
sql.Select("*")
.From<PropertyDataDto>()
.InnerJoin<PropertyTypeDto>()
.On<PropertyDataDto, PropertyTypeDto>(left => left.PropertyTypeId, right => right.Id)
.Where<PropertyDataDto>(x => x.NodeId == id)
.Where<PropertyDataDto>(x => x.VersionId == versionId);
var propertyDataDtos = Database.Fetch<PropertyDataDto, PropertyTypeDto>(sql);
var propertyFactory = new PropertyFactory(contentType, versionId, id, createDate, updateDate);
var properties = propertyFactory.BuildEntity(propertyDataDtos).ToArray();
var newProperties = properties.Where(x => x.HasIdentity == false && x.PropertyType.HasIdentity);
foreach (var property in newProperties)
{
var propertyDataDto = new PropertyDataDto { NodeId = id, PropertyTypeId = property.PropertyTypeId, VersionId = versionId };
int primaryKey = Convert.ToInt32(Database.Insert(propertyDataDto));
property.Version = versionId;
property.Id = primaryKey;
}
return new PropertyCollection(properties);
}
}
}
@@ -1,4 +1,5 @@
using Umbraco.Core.Configuration;
using System;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Persistence.Caching;
using Umbraco.Core.Persistence.Repositories;
@@ -12,12 +13,28 @@ namespace Umbraco.Core.Persistence
public class RepositoryFactory
{
private readonly bool _disableAllCache;
private readonly CacheHelper _cacheHelper;
private readonly IUmbracoSettingsSection _settings;
#region Ctors
public RepositoryFactory()
: this(false, UmbracoConfig.For.UmbracoSettings())
{
}
public RepositoryFactory(CacheHelper cacheHelper)
: this(false, UmbracoConfig.For.UmbracoSettings())
{
if (cacheHelper == null) throw new ArgumentNullException("cacheHelper");
_disableAllCache = false;
_cacheHelper = cacheHelper;
}
public RepositoryFactory(bool disableAllCache, CacheHelper cacheHelper)
: this(disableAllCache, UmbracoConfig.For.UmbracoSettings())
{
if (cacheHelper == null) throw new ArgumentNullException("cacheHelper");
_cacheHelper = cacheHelper;
}
public RepositoryFactory(bool disableAllCache)
@@ -30,9 +47,17 @@ namespace Umbraco.Core.Persistence
{
_disableAllCache = disableAllCache;
_settings = settings;
_cacheHelper = _disableAllCache ? CacheHelper.CreateDisabledCacheHelper() : ApplicationContext.Current.ApplicationCache;
}
internal RepositoryFactory(bool disableAllCache, IUmbracoSettingsSection settings, CacheHelper cacheHelper)
{
_disableAllCache = disableAllCache;
_settings = settings;
_cacheHelper = cacheHelper;
}
#endregion
public virtual ITagsRepository CreateTagsRepository(IDatabaseUnitOfWork uow)
{
return new TagsRepository(
@@ -43,18 +68,19 @@ namespace Umbraco.Core.Persistence
public virtual IContentRepository CreateContentRepository(IDatabaseUnitOfWork uow)
{
return new ContentRepository(
uow,
uow,
_disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current,
CreateContentTypeRepository(uow),
CreateTemplateRepository(uow),
CreateTagsRepository(uow)) { EnsureUniqueNaming = _settings.Content.EnsureUniqueNaming };
CreateTagsRepository(uow),
_cacheHelper) { EnsureUniqueNaming = _settings.Content.EnsureUniqueNaming };
}
public virtual IContentTypeRepository CreateContentTypeRepository(IDatabaseUnitOfWork uow)
{
return new ContentTypeRepository(
uow,
_disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : InMemoryCacheProvider.Current,
_disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current,
new TemplateRepository(uow, NullCacheProvider.Current));
}
@@ -69,7 +95,7 @@ namespace Umbraco.Core.Persistence
{
return new DictionaryRepository(
uow,
_disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : InMemoryCacheProvider.Current,
_disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current,
CreateLanguageRepository(uow));
}
@@ -77,7 +103,7 @@ namespace Umbraco.Core.Persistence
{
return new LanguageRepository(
uow,
_disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : InMemoryCacheProvider.Current);
_disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current);
}
public virtual IMediaRepository CreateMediaRepository(IDatabaseUnitOfWork uow)
@@ -93,7 +119,7 @@ namespace Umbraco.Core.Persistence
{
return new MediaTypeRepository(
uow,
_disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : InMemoryCacheProvider.Current);
_disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current);
}
public virtual IRelationRepository CreateRelationRepository(IDatabaseUnitOfWork uow)
@@ -133,20 +159,22 @@ namespace Umbraco.Core.Persistence
NullCacheProvider.Current);
}
internal virtual IUserTypeRepository CreateUserTypeRepository(IDatabaseUnitOfWork uow)
public virtual IUserTypeRepository CreateUserTypeRepository(IDatabaseUnitOfWork uow)
{
return new UserTypeRepository(
uow,
//There's not many user types but we query on users all the time so the result needs to be cached
RuntimeCacheProvider.Current);
_disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current);
}
internal virtual IUserRepository CreateUserRepository(IDatabaseUnitOfWork uow)
{
public virtual IUserRepository CreateUserRepository(IDatabaseUnitOfWork uow)
{
return new UserRepository(
uow,
NullCacheProvider.Current,
CreateUserTypeRepository(uow));
//Need to cache users - we look up user information more than anything in the back office!
_disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current,
CreateUserTypeRepository(uow),
_cacheHelper);
}
internal virtual IMacroRepository CreateMacroRepository(IDatabaseUnitOfWork uow)
@@ -154,20 +182,27 @@ namespace Umbraco.Core.Persistence
return new MacroRepository(uow, _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current);
}
internal virtual IMemberRepository CreateMemberRepository(IDatabaseUnitOfWork uow)
public virtual IMemberRepository CreateMemberRepository(IDatabaseUnitOfWork uow)
{
return new MemberRepository(uow,
_disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current,
return new MemberRepository(
uow,
_disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current,
CreateMemberTypeRepository(uow),
CreateMemberGroupRepository(uow),
CreateTagsRepository(uow));
}
internal virtual IMemberTypeRepository CreateMemberTypeRepository(IDatabaseUnitOfWork uow)
public virtual IMemberTypeRepository CreateMemberTypeRepository(IDatabaseUnitOfWork uow)
{
return new MemberTypeRepository(uow, _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : InMemoryCacheProvider.Current);
return new MemberTypeRepository(uow, _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current);
}
internal virtual IEntityRepository CreateEntityRepository(IDatabaseUnitOfWork uow)
public virtual IMemberGroupRepository CreateMemberGroupRepository(IDatabaseUnitOfWork uow)
{
return new MemberGroupRepository(uow, _disableAllCache ? (IRepositoryCacheProvider)NullCacheProvider.Current : RuntimeCacheProvider.Current, _cacheHelper);
}
public virtual IEntityRepository CreateEntityRepository(IDatabaseUnitOfWork uow)
{
return new EntityRepository(uow);
}
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Umbraco.Core.Persistence
{
//TODO: check if any of this works and for what databse types it works for:
// ref: http://stackoverflow.com/questions/16171144/how-to-check-for-database-availability
internal static class SqlExtensions
{
public static bool IsConnectionAvailable(string connString)
{
using (var connection = new SqlConnection(connString))
{
return connection.IsAvailable();
}
}
public static bool IsAvailable(this SqlConnection connection)
{
try
{
connection.Open();
connection.Close();
}
catch (SqlException)
{
return false;
}
return true;
}
}
}
@@ -11,6 +11,8 @@ namespace Umbraco.Core.Persistence.SqlSyntax
/// </summary>
public interface ISqlSyntaxProvider
{
string EscapeString(string val);
string GetStringColumnEqualComparison(string column, string value, TextColumnType columnType);
string GetStringColumnStartsWithComparison(string column, string value, TextColumnType columnType);
string GetStringColumnEndsWithComparison(string column, string value, TextColumnType columnType);
@@ -327,5 +327,10 @@ namespace Umbraco.Core.Persistence.SqlSyntax
// add message to check with their hosting provider
return supportsCaseInsensitiveQueries;
}
public override string EscapeString(string val)
{
return PetaPocoExtensions.EscapeAtSymbols(MySql.Data.MySqlClient.MySqlHelper.EscapeString(val));
}
}
}
@@ -103,6 +103,11 @@ namespace Umbraco.Core.Persistence.SqlSyntax
DbTypeMap.Set<byte[]>(DbType.Binary, BlobColumnDefinition);
}
public virtual string EscapeString(string val)
{
return PetaPocoExtensions.EscapeAtSymbols(val.Replace("'", "''"));
}
public virtual string GetStringColumnEqualComparison(string column, string value, TextColumnType columnType)
{
//use the 'upper' method to always ensure strings are matched without case sensitivity no matter what the db setting.
+10 -8
View File
@@ -34,7 +34,7 @@ namespace Umbraco.Core
/// it will use the cached resolved plugins that it has already found which means that no assembly scanning is necessary. This leads
/// to much faster startup times.
/// </remarks>
internal class PluginManager
public class PluginManager
{
private readonly ApplicationContext _appContext;
private const string CacheKey = "umbraco-plugins.list";
@@ -107,7 +107,7 @@ namespace Umbraco.Core
/// <remarks>
/// The setter is generally only used for unit tests
/// </remarks>
internal static PluginManager Current
public static PluginManager Current
{
get
{
@@ -783,12 +783,13 @@ namespace Umbraco.Core
UpdateCachedPluginsFile<T>(typeList.GetTypes(), resolutionKind);
}
#region Public Methods
/// <summary>
/// Generic method to find the specified type and cache the result
/// </summary>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
internal IEnumerable<Type> ResolveTypes<T>(bool cacheResult = true, IEnumerable<Assembly> specificAssemblies = null)
public IEnumerable<Type> ResolveTypes<T>(bool cacheResult = true, IEnumerable<Assembly> specificAssemblies = null)
{
return ResolveTypes<T>(
() => TypeFinder.FindClassesOfType<T>(specificAssemblies ?? AssembliesToScan),
@@ -802,11 +803,11 @@ namespace Umbraco.Core
/// <typeparam name="T"></typeparam>
/// <typeparam name="TAttribute"></typeparam>
/// <returns></returns>
internal IEnumerable<Type> ResolveTypesWithAttribute<T, TAttribute>(bool cacheResult = true)
public IEnumerable<Type> ResolveTypesWithAttribute<T, TAttribute>(bool cacheResult = true, IEnumerable<Assembly> specificAssemblies = null)
where TAttribute : Attribute
{
return ResolveTypes<T>(
() => TypeFinder.FindClassesOfTypeWithAttribute<T, TAttribute>(AssembliesToScan),
() => TypeFinder.FindClassesOfTypeWithAttribute<T, TAttribute>(specificAssemblies ?? AssembliesToScan),
TypeResolutionKind.FindTypesWithAttribute,
cacheResult);
}
@@ -816,14 +817,15 @@ namespace Umbraco.Core
/// </summary>
/// <typeparam name="TAttribute"></typeparam>
/// <returns></returns>
internal IEnumerable<Type> ResolveAttributedTypes<TAttribute>(bool cacheResult = true)
public IEnumerable<Type> ResolveAttributedTypes<TAttribute>(bool cacheResult = true, IEnumerable<Assembly> specificAssemblies = null)
where TAttribute : Attribute
{
return ResolveTypes<TAttribute>(
() => TypeFinder.FindClassesWithAttribute<TAttribute>(AssembliesToScan),
() => TypeFinder.FindClassesWithAttribute<TAttribute>(specificAssemblies ?? AssembliesToScan),
TypeResolutionKind.FindAttributedTypes,
cacheResult);
}
}
#endregion
/// <summary>
/// Used for unit tests
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Xml.Linq;
using Newtonsoft.Json;
@@ -127,7 +128,7 @@ namespace Umbraco.Core.PropertyEditors
/// <returns></returns>
public DataTypeDatabaseType GetDatabaseType()
{
switch (ValueType.ToUpper())
switch (ValueType.ToUpper(CultureInfo.InvariantCulture))
{
case "INT":
case "INTEGER":
@@ -0,0 +1,10 @@
namespace Umbraco.Core.Security
{
/// <summary>
/// A marker interface used internally to identify Umbraco built-in Users membership providers
/// </summary>
internal interface IUsersMembershipProvider
{
}
}
@@ -711,11 +711,6 @@ namespace Umbraco.Core.Security
var decrypted = DecryptPassword(dbPassword);
return decrypted == password;
case MembershipPasswordFormat.Hashed:
//only triggered when we set the initial installer password
if (dbPassword == "default" && password == dbPassword)
return true;
string salt;
var storedHashedPass = StoredPassword(dbPassword, out salt);
var hashed = EncryptOrHashPassword(password, salt);
@@ -10,6 +10,16 @@ namespace Umbraco.Core.Security
{
internal static class MembershipProviderExtensions
{
/// <summary>
/// Returns true if the provider specified is a built-in Umbraco users provider
/// </summary>
/// <param name="membershipProvider"></param>
/// <returns></returns>
public static bool IsUmbracoUsersProvider(this MembershipProvider membershipProvider)
{
return (membershipProvider is IUsersMembershipProvider);
}
/// <summary>
/// Returns true if the provider specified is a built-in Umbraco membership provider
/// </summary>
@@ -20,6 +30,8 @@ namespace Umbraco.Core.Security
return (membershipProvider is UmbracoMembershipProviderBase);
}
//TODO: Add role provider checks too
public static UmbracoMembershipProviderBase AsUmbracoMembershipProvider(this MembershipProvider membershipProvider)
{
return (UmbracoMembershipProviderBase)membershipProvider;
@@ -0,0 +1,23 @@
using System.Collections.Specialized;
namespace Umbraco.Core.Security
{
/// <summary>
/// An interface for exposing the content type properties for storing membership data in when
/// a membership provider's data is backed by an Umbraco content type.
/// </summary>
public interface IUmbracoMemberTypeMembershipProvider
{
string LockPropertyTypeAlias { get; }
string LastLockedOutPropertyTypeAlias { get; }
string FailedPasswordAttemptsPropertyTypeAlias { get; }
string ApprovedPropertyTypeAlias { get; }
string CommentPropertyTypeAlias { get; }
string LastLoginPropertyTypeAlias { get; }
string LastPasswordChangedPropertyTypeAlias { get; }
string PasswordRetrievalQuestionPropertyTypeAlias { get; }
string PasswordRetrievalAnswerPropertyTypeAlias { get; }
}
}
@@ -3,7 +3,6 @@ using System.Web.Security;
namespace Umbraco.Core.Security
{
/// <summary>
/// A base membership provider class for umbraco providers
/// </summary>
+47 -7
View File
@@ -59,14 +59,32 @@ namespace Umbraco.Core.Services
_repositoryFactory = repositoryFactory;
}
//TODO: There are various ways to expose permission setting on this service, we just need to list out the different ways we'll need to
// be able to acheive this for the core, for now this is here so I can run a unit test.
internal void AssignContentPermissions(IContent entity, char permission, IEnumerable<object> userIds)
/// <summary>
/// Assigns a single permission to the current content item for the specified user ids
/// </summary>
/// <param name="entity"></param>
/// <param name="permission"></param>
/// <param name="userIds"></param>
public void AssignContentPermission(IContent entity, char permission, IEnumerable<int> userIds)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateContentRepository(uow))
{
repository.AssignEntityPermissions(entity, permission, userIds);
repository.AssignEntityPermission(entity, permission, userIds);
}
}
/// <summary>
/// Gets the list of permissions for the content item
/// </summary>
/// <param name="content"></param>
/// <returns></returns>
public IEnumerable<EntityPermission> GetPermissionsForEntity(IContent content)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateContentRepository(uow))
{
return repository.GetPermissionsForEntity(content.Id);
}
}
@@ -158,12 +176,20 @@ namespace Umbraco.Core.Services
var contentType = FindContentTypeByAlias(contentTypeAlias);
var content = new Content(name, parentId, contentType);
//NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found
// out that in these 'WithIdentity' methods, the Saving/Saved events were not fired, wtf. Anyways, they're added now.
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IContent>(content, contentTypeAlias, parentId), this))
{
content.WasCancelled = true;
return content;
}
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IContent>(content), this))
{
content.WasCancelled = true;
return content;
}
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateContentRepository(uow))
{
@@ -173,6 +199,8 @@ namespace Umbraco.Core.Services
uow.Commit();
}
Saved.RaiseEvent(new SaveEventArgs<IContent>(content, false), this);
Created.RaiseEvent(new NewEventArgs<IContent>(content, false, contentTypeAlias, parentId), this);
Audit.Add(AuditTypes.New, string.Format("Content '{0}' was created with Id {1}", name, content.Id), content.CreatorId, content.Id);
@@ -198,12 +226,20 @@ namespace Umbraco.Core.Services
var contentType = FindContentTypeByAlias(contentTypeAlias);
var content = new Content(name, parent, contentType);
//NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found
// out that in these 'WithIdentity' methods, the Saving/Saved events were not fired, wtf. Anyways, they're added now.
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IContent>(content, contentTypeAlias, parent), this))
{
content.WasCancelled = true;
return content;
}
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IContent>(content), this))
{
content.WasCancelled = true;
return content;
}
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateContentRepository(uow))
{
@@ -213,6 +249,8 @@ namespace Umbraco.Core.Services
uow.Commit();
}
Saved.RaiseEvent(new SaveEventArgs<IContent>(content, false), this);
Created.RaiseEvent(new NewEventArgs<IContent>(content, false, contentTypeAlias, parent), this);
Audit.Add(AuditTypes.New, string.Format("Content '{0}' was created with Id {1}", name, content.Id), content.CreatorId, content.Id);
@@ -628,10 +666,10 @@ namespace Umbraco.Core.Services
/// <param name="content">The <see cref="IContent"/> to publish</param>
/// <param name="userId">Optional Id of the User issueing the publishing</param>
/// <returns>True if publishing succeeded, otherwise False</returns>
[Obsolete("Use PublishWithStatus instead, that method will provide more detailed information on the outcome")]
public bool Publish(IContent content, int userId = 0)
{
var result = SaveAndPublishDo(content, userId);
LogHelper.Info<ContentService>("Call was made to ContentService.Publish, use PublishWithStatus instead since that method will provide more detailed information on the outcome");
return result.Success;
}
@@ -1220,6 +1258,7 @@ namespace Umbraco.Core.Services
}
}
/// <summary>
/// Sends an <see cref="IContent"/> to Publication, which executes handlers and events for the 'Send to Publication' action.
/// </summary>
@@ -1458,6 +1497,8 @@ namespace Umbraco.Core.Services
//bulk insert it into the database
uow.Database.BulkInsertRecords(xmlItems, tr);
tr.Complete();
}
Audit.Add(AuditTypes.Publish, "RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1);
@@ -1929,7 +1970,7 @@ namespace Umbraco.Core.Services
/// <summary>
/// Occurs before Create
/// </summary>
[Obsolete("This event should not be used, it was originally created for backwards compatibility for the legacy API. To modify a new document before it is saved use the Saving event")]
[Obsolete("Use the Created event instead, the Creating and Created events both offer the same functionality, Creating event has been deprecated.")]
public static event TypedEventHandler<IContentService, NewEventArgs<IContent>> Creating;
/// <summary>
@@ -1939,7 +1980,6 @@ namespace Umbraco.Core.Services
/// Please note that the Content object has been created, but might not have been saved
/// so it does not have an identity yet (meaning no Id has been set).
/// </remarks>
[Obsolete("This event should not be used, it was originally created for backwards compatibility for the legacy API. To modify a new document before it is saved use the Saving event")]
public static event TypedEventHandler<IContentService, NewEventArgs<IContent>> Created;
/// <summary>
+9 -9
View File
@@ -226,17 +226,17 @@ namespace Umbraco.Core.Services
{
using (var uow = _uowProvider.GetUnitOfWork())
{
var sortOrderObj =
uow.Database.ExecuteScalar<object>(
"SELECT max(sortorder) FROM cmsDataTypePreValues WHERE datatypeNodeId = @DataTypeId", new { DataTypeId = id });
int sortOrder;
if (sortOrderObj == null || int.TryParse(sortOrderObj.ToString(), out sortOrder) == false)
{
sortOrder = 1;
}
using (var transaction = uow.Database.GetTransaction())
{
var sortOrderObj =
uow.Database.ExecuteScalar<object>(
"SELECT max(sortorder) FROM cmsDataTypePreValues WHERE datatypeNodeId = @DataTypeId", new { DataTypeId = id });
int sortOrder;
if (sortOrderObj == null || int.TryParse(sortOrderObj.ToString(), out sortOrder) == false)
{
sortOrder = 1;
}
foreach (var value in values)
{
var dto = new DataTypePreValueDto { DataTypeNodeId = id, Value = value, SortOrder = sortOrder };
+14 -1
View File
@@ -11,6 +11,20 @@ namespace Umbraco.Core.Services
/// </summary>
public interface IContentService : IService
{
/// <summary>
/// Assigns a single permission to the current content item for the specified user ids
/// </summary>
/// <param name="entity"></param>
/// <param name="permission"></param>
/// <param name="userIds"></param>
void AssignContentPermission(IContent entity, char permission, IEnumerable<int> userIds);
/// <summary>
/// Gets the list of permissions for the content item
/// </summary>
/// <param name="content"></param>
/// <returns></returns>
IEnumerable<EntityPermission> GetPermissionsForEntity(IContent content);
bool SendToPublication(IContent content, int userId = 0);
@@ -249,7 +263,6 @@ namespace Umbraco.Core.Services
/// <param name="content">The <see cref="IContent"/> to publish</param>
/// <param name="userId">Optional Id of the User issueing the publishing</param>
/// <returns>True if publishing succeeded, otherwise False</returns>
[Obsolete("Use PublishWithStatus instead, that method will provide more detailed information on the outcome")]
bool Publish(IContent content, int userId = 0);
/// <summary>
@@ -0,0 +1,14 @@
using System.Collections.Generic;
using Umbraco.Core.Models;
namespace Umbraco.Core.Services
{
public interface IMemberGroupService : IService
{
IEnumerable<IMemberGroup> GetAll();
IMemberGroup GetById(int id);
IMemberGroup GetByName(string name);
void Save(IMemberGroup memberGroup, bool raiseEvents = true);
void Delete(IMemberGroup memberGroup);
}
}
+20 -9
View File
@@ -8,7 +8,7 @@ namespace Umbraco.Core.Services
/// <summary>
/// Defines the MemberService, which is an easy access to operations involving (umbraco) members.
/// </summary>
internal interface IMemberService : IMembershipMemberService
public interface IMemberService : IMembershipMemberService
{
/// <summary>
/// Checks if a member with the id exists
@@ -16,14 +16,7 @@ namespace Umbraco.Core.Services
/// <param name="id"></param>
/// <returns></returns>
bool Exists(int id);
/// <summary>
/// Get a member by its id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
IMember GetById(int id);
/// <summary>
/// Get a member by the unique key
/// </summary>
@@ -31,6 +24,13 @@ namespace Umbraco.Core.Services
/// <returns></returns>
IMember GetByKey(Guid id);
/// <summary>
/// Gets a member by it's id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
IMember GetById(int id);
/// <summary>
/// Get all members for the member type alias
/// </summary>
@@ -65,6 +65,17 @@ namespace Umbraco.Core.Services
/// <param name="memberTypeId"></param>
void DeleteMembersOfType(int memberTypeId);
/// <summary>
/// Find members based on their display name
/// </summary>
/// <param name="displayNameToMatch"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalRecords"></param>
/// <param name="matchType"></param>
/// <returns></returns>
IEnumerable<IMember> FindMembersByDisplayName(string displayNameToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
/// <summary>
/// Get members based on a property search
/// </summary>
@@ -3,28 +3,28 @@ using Umbraco.Core.Models;
namespace Umbraco.Core.Services
{
internal interface IMemberTypeService : IService
{
public interface IMemberTypeService : IService
{
/// <summary>
/// Gets a list of all available <see cref="IContentType"/> objects
/// </summary>
/// <param name="ids">Optional list of ids</param>
/// <returns>An Enumerable list of <see cref="IContentType"/> objects</returns>
IEnumerable<IMemberType> GetAllMemberTypes(params int[] ids);
IEnumerable<IMemberType> GetAll(params int[] ids);
/// <summary>
/// Gets an <see cref="IMemberType"/> object by its Id
/// </summary>
/// <param name="id">Id of the <see cref="IMediaType"/> to retrieve</param>
/// <returns><see cref="IMediaType"/></returns>
IMemberType GetMemberType(int id);
IMemberType Get(int id);
/// <summary>
/// Gets an <see cref="IMemberType"/> object by its Alias
/// </summary>
/// <param name="alias">Alias of the <see cref="IMediaType"/> to retrieve</param>
/// <returns><see cref="IMediaType"/></returns>
IMemberType GetMemberType(string alias);
IMemberType Get(string alias);
/// <summary>
/// Saves a single <see cref="IMemberType"/> object
@@ -6,16 +6,16 @@ using Umbraco.Core.Persistence.Querying;
namespace Umbraco.Core.Services
{
/// <summary>
/// Defines part of the MemberService, which is specific to methods used by the membership provider.
/// </summary>
/// <remarks>
/// Idea is to have this is an isolated interface so that it can be easily 'replaced' in the membership provider impl.
/// </remarks>
internal interface IMembershipMemberService : IMembershipMemberService<IMember>
public interface IMembershipMemberService : IMembershipMemberService<IMember>, IMembershipRoleService<IMember>
{
IMember CreateMember(string email, string username, string password, IMemberType memberType);
IMember CreateMember(string username, string email, string password, string memberType);
IMember CreateMemberWithIdentity(string username, string email, string password, IMemberType memberType);
}
/// <summary>
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Services
/// <remarks>
/// Idea is to have this is an isolated interface so that it can be easily 'replaced' in the membership provider impl.
/// </remarks>
internal interface IMembershipMemberService<T> : IService
public interface IMembershipMemberService<T> : IService
where T : class, IMembershipUser
{
/// <summary>
@@ -48,9 +48,14 @@ namespace Umbraco.Core.Services
/// <param name="password"></param>
/// <param name="memberTypeAlias"></param>
/// <returns></returns>
T CreateMember(string username, string email, string password, string memberTypeAlias);
T CreateWithIdentity(string username, string email, string password, string memberTypeAlias);
T GetById(object id);
/// <summary>
/// Gets the member by the provider key
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
T GetByProviderKey(object id);
/// <summary>
/// Get a member by email
@@ -62,20 +67,20 @@ namespace Umbraco.Core.Services
T GetByUsername(string login);
void Delete(T membershipUser);
void Save(T entity, bool raiseEvents = true);
void Save(T membershipUser, bool raiseEvents = true);
void Save(IEnumerable<T> entities, bool raiseEvents = true);
void Save(IEnumerable<T> members, bool raiseEvents = true);
IEnumerable<T> FindByEmail(string emailStringToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
IEnumerable<T> FindMembersByEmail(string emailStringToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
IEnumerable<T> FindMembersByUsername(string login, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
IEnumerable<T> FindByUsername(string login, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
/// <summary>
/// Gets the total number of members based on the count type
/// </summary>
/// <returns></returns>
int GetMemberCount(MemberCountType countType);
int GetCount(MemberCountType countType);
/// <summary>
/// Gets a list of paged member data
@@ -84,6 +89,6 @@ namespace Umbraco.Core.Services
/// <param name="pageSize"></param>
/// <param name="totalRecords"></param>
/// <returns></returns>
IEnumerable<T> GetAllMembers(int pageIndex, int pageSize, out int totalRecords);
IEnumerable<T> GetAll(int pageIndex, int pageSize, out int totalRecords);
}
}
@@ -0,0 +1,22 @@
using System.Collections.Generic;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Persistence.Querying;
namespace Umbraco.Core.Services
{
public interface IMembershipRoleService<out T>
where T : class, IMembershipUser
{
void AddRole(string roleName);
IEnumerable<string> GetAllRoles();
IEnumerable<string> GetAllRoles(int memberId);
IEnumerable<string> GetAllRoles(string username);
IEnumerable<T> GetMembersInRole(string roleName);
IEnumerable<T> FindMembersInRole(string roleName, string usernameToMatch, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
bool DeleteRole(string roleName, bool throwIfBeingUsed);
void AssignRoles(string[] usernames, string[] roleNames);
void DissociateRoles(string[] usernames, string[] roleNames);
void AssignRoles(int[] memberIds, string[] roleNames);
void DissociateRoles(int[] memberIds, string[] roleNames);
}
}
@@ -8,10 +8,10 @@ namespace Umbraco.Core.Services
/// <remarks>
/// Idea is to have this is an isolated interface so that it can be easily 'replaced' in the membership provider impl.
/// </remarks>
internal interface IMembershipUserService : IMembershipMemberService<IUser>
public interface IMembershipUserService : IMembershipMemberService<IUser>
{
IUser CreateMember(string username, string email, string password, IUserType userType);
IUser CreateUserWithIdentity(string username, string email, string password, IUserType userType);
}
}
+55 -14
View File
@@ -7,18 +7,64 @@ namespace Umbraco.Core.Services
/// <summary>
/// Defines the UserService, which is an easy access to operations involving <see cref="IProfile"/> and eventually Users.
/// </summary>
internal interface IUserService : IMembershipUserService
public interface IUserService : IMembershipUserService
{
/// <summary>
/// To permanently delete the user pass in true, otherwise they will just be disabled
/// </summary>
/// <param name="user"></param>
/// <param name="deletePermanently"></param>
void Delete(IUser user, bool deletePermanently);
/// <summary>
/// Gets an IProfile by User Id.
/// </summary>
/// <param name="id">Id of the User to retrieve</param>
/// <returns><see cref="IProfile"/></returns>
IProfile GetProfileById(int id);
/// <summary>
/// Get profile by username
/// </summary>
/// <param name="username"></param>
/// <returns></returns>
IProfile GetProfileByUserName(string username);
/// <summary>
/// Get user by Id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
IUser GetUserById(int id);
/// <summary>
/// This is useful when an entire section is removed from config
/// </summary>
/// <param name="sectionAlias"></param>
void DeleteSectionFromAllUsers(string sectionAlias);
/// <summary>
/// Get permissions set for user and specified node ids
/// </summary>
/// <param name="user"></param>
/// <param name="nodeIds">
/// Specifiying nothing will return all user permissions for all nodes
/// </param>
/// <returns></returns>
IEnumerable<EntityPermission> GetPermissions(IUser user, params int[] nodeIds);
/// <summary>
/// Replaces the same permission set for a single user to any number of entities
/// </summary>
/// <param name="userId"></param>
/// <param name="permissions"></param>
/// <param name="entityIds"></param>
void ReplaceUserPermissions(int userId, IEnumerable<char> permissions, params int[] entityIds);
#region User types
IEnumerable<IUserType> GetAllUserTypes(params int[] ids);
/// <summary>
/// Gets an IUserType by its Alias
/// </summary>
@@ -26,6 +72,13 @@ namespace Umbraco.Core.Services
/// <returns><see cref="IUserType"/></returns>
IUserType GetUserTypeByAlias(string alias);
/// <summary>
/// Gets an IUserType by its Id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
IUserType GetUserTypeById(int id);
/// <summary>
/// Gets an IUserType by its Name
/// </summary>
@@ -45,19 +98,7 @@ namespace Umbraco.Core.Services
/// </summary>
/// <param name="userType"></param>
void DeleteUserType(IUserType userType);
/// <summary>
/// This is useful when an entire section is removed from config
/// </summary>
/// <param name="sectionAlias"></param>
void DeleteSectionFromAllUsers(string sectionAlias);
/// <summary>
/// Returns a list of the sections that the user is allowed access to
/// </summary>
/// <returns></returns>
IEnumerable<string> GetUserSections(IUser user);
IEnumerable<EntityPermission> GetPermissions(IUser user, params int[] nodeIds);
#endregion
}
}
+27 -2
View File
@@ -122,12 +122,23 @@ namespace Umbraco.Core.Services
{
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
var media = new Models.Media(name, parentId, mediaType);
//NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found
// out that in these 'WithIdentity' methods, the Saving/Saved events were not fired, wtf. Anyways, they're added now.
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parentId), this))
{
media.WasCancelled = true;
return media;
}
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMedia>(media), this))
{
media.WasCancelled = true;
return media;
}
//TODO: Once we fix up the transaction logic, these write locks should be replaced with
// an outter transaction instead.
using (new WriteLock(Locker))
{
var uow = _uowProvider.GetUnitOfWork();
@@ -142,6 +153,8 @@ namespace Umbraco.Core.Services
}
}
Saved.RaiseEvent(new SaveEventArgs<IMedia>(media, false), this);
Created.RaiseEvent(new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parentId), this);
Audit.Add(AuditTypes.New, string.Format("Media '{0}' was created with Id {1}", name, media.Id), media.CreatorId, media.Id);
@@ -166,12 +179,21 @@ namespace Umbraco.Core.Services
{
var mediaType = FindMediaTypeByAlias(mediaTypeAlias);
var media = new Models.Media(name, parent, mediaType);
//NOTE: I really hate the notion of these Creating/Created events - they are so inconsistent, I've only just found
// out that in these 'WithIdentity' methods, the Saving/Saved events were not fired, wtf. Anyways, they're added now.
if (Creating.IsRaisedEventCancelled(new NewEventArgs<IMedia>(media, mediaTypeAlias, parent), this))
{
media.WasCancelled = true;
return media;
}
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMedia>(media), this))
{
media.WasCancelled = true;
return media;
}
using (new WriteLock(Locker))
{
var uow = _uowProvider.GetUnitOfWork();
@@ -186,6 +208,8 @@ namespace Umbraco.Core.Services
}
}
Saved.RaiseEvent(new SaveEventArgs<IMedia>(media, false), this);
Created.RaiseEvent(new NewEventArgs<IMedia>(media, false, mediaTypeAlias, parent), this);
Audit.Add(AuditTypes.New, string.Format("Media '{0}' was created with Id {1}", name, media.Id), media.CreatorId, media.Id);
@@ -938,6 +962,8 @@ namespace Umbraco.Core.Services
//bulk insert it into the database
uow.Database.BulkInsertRecords(xmlItems, tr);
tr.Complete();
}
Audit.Add(AuditTypes.Publish, "RebuildXmlStructures completed, the xml has been regenerated in the database", 0, -1);
@@ -1040,7 +1066,7 @@ namespace Umbraco.Core.Services
/// <summary>
/// Occurs before Create
/// </summary>
[Obsolete("This event should not be used, it was originally created for backwards compatibility for the legacy API. To modify a new document before it is saved use the Saving event")]
[Obsolete("Use the Created event instead, the Creating and Created events both offer the same functionality, Creating event has been deprecated.")]
public static event TypedEventHandler<IMediaService, NewEventArgs<IMedia>> Creating;
/// <summary>
@@ -1050,7 +1076,6 @@ namespace Umbraco.Core.Services
/// Please note that the Media object has been created, but not saved
/// so it does not have an identity yet (meaning no Id has been set).
/// </remarks>
[Obsolete("This event should not be used, it was originally created for backwards compatibility for the legacy API. To modify a new document before it is saved use the Saving event")]
public static event TypedEventHandler<IMediaService, NewEventArgs<IMedia>> Created;
/// <summary>
@@ -0,0 +1,138 @@
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Services
{
public class MemberGroupService : IMemberGroupService
{
private readonly RepositoryFactory _repositoryFactory;
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
public MemberGroupService(RepositoryFactory repositoryFactory)
: this(new PetaPocoUnitOfWorkProvider(), repositoryFactory)
{
}
public MemberGroupService(IDatabaseUnitOfWorkProvider provider)
: this(provider, new RepositoryFactory())
{
}
public MemberGroupService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory)
{
_repositoryFactory = repositoryFactory;
_uowProvider = provider;
//Proxy events!
MemberGroupRepository.SavedMemberGroup += MemberGroupRepository_SavedMemberGroup;
MemberGroupRepository.SavingMemberGroup += MemberGroupRepository_SavingMemberGroup;
}
#region Proxied event handlers
void MemberGroupRepository_SavingMemberGroup(IMemberGroupRepository sender, SaveEventArgs<IMemberGroup> e)
{
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMemberGroup>(e.SavedEntities), this))
{
e.Cancel = true;
}
}
void MemberGroupRepository_SavedMemberGroup(IMemberGroupRepository sender, SaveEventArgs<IMemberGroup> e)
{
Saved.RaiseEvent(new SaveEventArgs<IMemberGroup>(e.SavedEntities, false), this);
}
#endregion
public IEnumerable<IMemberGroup> GetAll()
{
using (var repository = _repositoryFactory.CreateMemberGroupRepository(_uowProvider.GetUnitOfWork()))
{
return repository.GetAll();
}
}
public IMemberGroup GetById(int id)
{
using (var repository = _repositoryFactory.CreateMemberGroupRepository(_uowProvider.GetUnitOfWork()))
{
return repository.Get(id);
}
}
public IMemberGroup GetByName(string name)
{
using (var repository = _repositoryFactory.CreateMemberGroupRepository(_uowProvider.GetUnitOfWork()))
{
return repository.GetByName(name);
}
}
public void Save(IMemberGroup memberGroup, bool raiseEvents = true)
{
if (raiseEvents)
{
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMemberGroup>(memberGroup), this))
{
return;
}
}
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
{
repository.AddOrUpdate(memberGroup);
uow.Commit();
}
if (raiseEvents)
Saved.RaiseEvent(new SaveEventArgs<IMemberGroup>(memberGroup, false), this);
}
public void Delete(IMemberGroup memberGroup)
{
if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs<IMemberGroup>(memberGroup), this))
return;
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
{
repository.Delete(memberGroup);
uow.Commit();
}
Deleted.RaiseEvent(new DeleteEventArgs<IMemberGroup>(memberGroup, false), this);
}
/// <summary>
/// Occurs before Delete of a member group
/// </summary>
public static event TypedEventHandler<IMemberGroupService, DeleteEventArgs<IMemberGroup>> Deleting;
/// <summary>
/// Occurs after Delete of a member group
/// </summary>
public static event TypedEventHandler<IMemberGroupService, DeleteEventArgs<IMemberGroup>> Deleted;
/// <summary>
/// Occurs before Save of a member group
/// </summary>
/// <remarks>
/// We need to proxy these events because the events need to take place at the repo level
/// </remarks>
public static event TypedEventHandler<IMemberGroupService, SaveEventArgs<IMemberGroup>> Saving;
/// <summary>
/// Occurs after Save of a member group
/// </summary>
/// <remarks>
/// We need to proxy these events because the events need to take place at the repo level
/// </remarks>
public static event TypedEventHandler<IMemberGroupService, SaveEventArgs<IMemberGroup>> Saved;
}
}
+236 -37
View File
@@ -5,12 +5,14 @@ using System.Threading;
using System.Web.Security;
using System.Xml.Linq;
using System.Xml.Linq;
using Umbraco.Core.Auditing;
using Umbraco.Core.Events;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Persistence.UnitOfWork;
using System.Linq;
@@ -20,26 +22,31 @@ namespace Umbraco.Core.Services
/// <summary>
/// Represents the MemberService.
/// </summary>
internal class MemberService : IMemberService
public class MemberService : IMemberService
{
private readonly RepositoryFactory _repositoryFactory;
private readonly IMemberGroupService _memberGroupService;
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim();
internal MemberService(RepositoryFactory repositoryFactory)
: this(new PetaPocoUnitOfWorkProvider(), repositoryFactory)
public MemberService(RepositoryFactory repositoryFactory, IMemberGroupService memberGroupService)
: this(new PetaPocoUnitOfWorkProvider(), repositoryFactory, memberGroupService)
{
}
internal MemberService(IDatabaseUnitOfWorkProvider provider)
: this(provider, new RepositoryFactory())
public MemberService(IDatabaseUnitOfWorkProvider provider, IMemberGroupService memberGroupService)
: this(provider, new RepositoryFactory(), memberGroupService)
{
}
internal MemberService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory)
public MemberService(IDatabaseUnitOfWorkProvider provider, RepositoryFactory repositoryFactory, IMemberGroupService memberGroupService)
{
if (provider == null) throw new ArgumentNullException("provider");
if (repositoryFactory == null) throw new ArgumentNullException("repositoryFactory");
if (memberGroupService == null) throw new ArgumentNullException("memberGroupService");
_repositoryFactory = repositoryFactory;
_memberGroupService = memberGroupService;
_uowProvider = provider;
}
@@ -207,6 +214,38 @@ namespace Umbraco.Core.Services
}
}
public IEnumerable<IMember> FindMembersByDisplayName(string displayNameToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberRepository(uow))
{
var query = new Query<IMember>();
switch (matchType)
{
case StringPropertyMatchType.Exact:
query.Where(member => member.Name.Equals(displayNameToMatch));
break;
case StringPropertyMatchType.Contains:
query.Where(member => member.Name.Contains(displayNameToMatch));
break;
case StringPropertyMatchType.StartsWith:
query.Where(member => member.Name.StartsWith(displayNameToMatch));
break;
case StringPropertyMatchType.EndsWith:
query.Where(member => member.Name.EndsWith(displayNameToMatch));
break;
case StringPropertyMatchType.Wildcard:
query.Where(member => member.Name.SqlWildcard(displayNameToMatch, TextColumnType.NVarchar));
break;
default:
throw new ArgumentOutOfRangeException("matchType");
}
return repository.GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, dto => dto.Name);
}
}
/// <summary>
/// Does a search for members that contain the specified string in their email address
/// </summary>
@@ -216,7 +255,7 @@ namespace Umbraco.Core.Services
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <returns></returns>
public IEnumerable<IMember> FindMembersByEmail(string emailStringToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
public IEnumerable<IMember> FindByEmail(string emailStringToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberRepository(uow))
@@ -248,7 +287,7 @@ namespace Umbraco.Core.Services
}
}
public IEnumerable<IMember> FindMembersByUsername(string login, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
public IEnumerable<IMember> FindByUsername(string login, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberRepository(uow))
@@ -489,7 +528,7 @@ namespace Umbraco.Core.Services
/// that have their last active date within the Membership.UserIsOnlineTimeWindow (which is in minutes). It isn't exact science
/// but that is how MS have made theirs so we'll follow that principal.
/// </remarks>
public int GetMemberCount(MemberCountType countType)
public int GetCount(MemberCountType countType)
{
using (var repository = _repositoryFactory.CreateMemberRepository(_uowProvider.GetUnitOfWork()))
{
@@ -529,7 +568,7 @@ namespace Umbraco.Core.Services
}
public IEnumerable<IMember> GetAllMembers(int pageIndex, int pageSize, out int totalRecords)
public IEnumerable<IMember> GetAll(int pageIndex, int pageSize, out int totalRecords)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberRepository(uow))
@@ -538,11 +577,29 @@ namespace Umbraco.Core.Services
}
}
public IMember CreateMember(string email, string username, string password, IMemberType memberType)
public IMember CreateMember(string username, string email, string password, string memberTypeAlias)
{
var memberTypeService = ApplicationContext.Current.Services.MemberTypeService;
var memberType = memberTypeService.Get(memberTypeAlias);
var member = new Member(username, email.ToLower().Trim(), username, password, -1, memberType);
Created.RaiseEvent(new NewEventArgs<IMember>(member, false, memberTypeAlias, -1), this);
return member;
}
public IMember CreateMemberWithIdentity(string username, string email, string password, IMemberType memberType)
{
if (memberType == null) throw new ArgumentNullException("memberType");
var member = new Member(email, email, username, password, -1, memberType);
var member = new Member(username, email.ToLower().Trim(), username, password, -1, memberType);
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMember>(member), this))
{
member.WasCancelled = true;
return member;
}
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberRepository(uow))
@@ -555,9 +612,12 @@ namespace Umbraco.Core.Services
CreateAndSaveMemberXml(xml, member.Id, uow.Database);
}
Saved.RaiseEvent(new SaveEventArgs<IMember>(member, false), this);
Created.RaiseEvent(new NewEventArgs<IMember>(member, false, memberType.Alias, -1), this);
return member;
}
/// <summary>
/// Creates and persists a new Member
/// </summary>
@@ -566,7 +626,7 @@ namespace Umbraco.Core.Services
/// <param name="password"></param>
/// <param name="memberTypeAlias"></param>
/// <returns></returns>
public IMember CreateMember(string email, string username, string password, string memberTypeAlias)
IMember IMembershipMemberService<IMember>.CreateWithIdentity(string username, string email, string password, string memberTypeAlias)
{
var uow = _uowProvider.GetUnitOfWork();
IMemberType memberType;
@@ -582,7 +642,7 @@ namespace Umbraco.Core.Services
throw new ArgumentException(string.Format("No MemberType matching the passed in Alias: '{0}' was found", memberTypeAlias));
}
return CreateMember(email, username, password, memberTypeAlias);
return CreateMemberWithIdentity(username, email, password, memberType);
}
/// <summary>
@@ -593,17 +653,18 @@ namespace Umbraco.Core.Services
/// </remarks>
/// <param name="id"></param>
/// <returns></returns>
public IMember GetById(object id)
public IMember GetByProviderKey(object id)
{
if (id is int)
{
return GetById((int)id);
}
if (id is Guid)
var asGuid = id.TryConvertTo<Guid>();
if (asGuid.Success)
{
return GetByKey((Guid)id);
}
var asInt = id.TryConvertTo<int>();
if (asInt.Success)
{
return GetById((int)id);
}
return null;
}
@@ -660,39 +721,42 @@ namespace Umbraco.Core.Services
Deleted.RaiseEvent(new DeleteEventArgs<IMember>(member, false), this);
}
/// <summary>
/// Saves an updated Member
/// </summary>
/// <param name="member"></param>
/// <param name="entity"></param>
/// <param name="raiseEvents"></param>
public void Save(IMember member, bool raiseEvents = true)
public void Save(IMember entity, bool raiseEvents = true)
{
if (raiseEvents)
{
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMember>(member), this))
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMember>(entity), this))
{
return;
}
}
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberRepository(uow))
{
repository.AddOrUpdate(member);
repository.AddOrUpdate(entity);
uow.Commit();
var xml = member.ToXml();
CreateAndSaveMemberXml(xml, member.Id, uow.Database);
var xml = entity.ToXml();
CreateAndSaveMemberXml(xml, entity.Id, uow.Database);
}
if (raiseEvents)
Saved.RaiseEvent(new SaveEventArgs<IMember>(member, false), this);
Saved.RaiseEvent(new SaveEventArgs<IMember>(entity, false), this);
}
public void Save(IEnumerable<IMember> members, bool raiseEvents = true)
public void Save(IEnumerable<IMember> entities, bool raiseEvents = true)
{
if (raiseEvents)
{
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMember>(members), this))
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMember>(entities), this))
return;
}
using (new WriteLock(Locker))
@@ -700,7 +764,7 @@ namespace Umbraco.Core.Services
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberRepository(uow))
{
foreach (var member in members)
foreach (var member in entities)
{
repository.AddOrUpdate(member);
}
@@ -708,19 +772,143 @@ namespace Umbraco.Core.Services
//commit the whole lot in one go
uow.Commit();
foreach (var member in members)
foreach (var member in entities)
{
CreateAndSaveMemberXml(member.ToXml(), member.Id, uow.Database);
}
}
if (raiseEvents)
Saved.RaiseEvent(new SaveEventArgs<IMember>(members, false), this);
Saved.RaiseEvent(new SaveEventArgs<IMember>(entities, false), this);
}
}
#endregion
#region IMembershipRoleService Implementation
public void AddRole(string roleName)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
{
repository.CreateIfNotExists(roleName);
}
}
public IEnumerable<string> GetAllRoles()
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
{
var result = repository.GetAll();
return result.Select(x => x.Name).Distinct();
}
}
public IEnumerable<string> GetAllRoles(int memberId)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
{
var result = repository.GetMemberGroupsForMember(memberId);
return result.Select(x => x.Name).Distinct();
}
}
public IEnumerable<string> GetAllRoles(string username)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
{
var result = repository.GetMemberGroupsForMember(username);
return result.Select(x => x.Name).Distinct();
}
}
public IEnumerable<IMember> GetMembersInRole(string roleName)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberRepository(uow))
{
return repository.GetByMemberGroup(roleName);
}
}
public IEnumerable<IMember> FindMembersInRole(string roleName, string usernameToMatch, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberRepository(uow))
{
return repository.FindMembersInRole(roleName, usernameToMatch, matchType);
}
}
public bool DeleteRole(string roleName, bool throwIfBeingUsed)
{
using (new WriteLock(Locker))
{
if (throwIfBeingUsed)
{
var inRole = GetMembersInRole(roleName);
if (inRole.Any())
{
throw new InvalidOperationException("The role " + roleName + " is currently assigned to members");
}
}
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
{
var qry = new Query<IMemberGroup>().Where(g => g.Name == roleName);
var found = repository.GetByQuery(qry).ToArray();
foreach (var memberGroup in found)
{
_memberGroupService.Delete(memberGroup);
}
return found.Any();
}
}
}
public void AssignRoles(string[] usernames, string[] roleNames)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
{
repository.AssignRoles(usernames, roleNames);
}
}
public void DissociateRoles(string[] usernames, string[] roleNames)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
{
repository.DissociateRoles(usernames, roleNames);
}
}
public void AssignRoles(int[] memberIds, string[] roleNames)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
{
repository.AssignRoles(memberIds, roleNames);
}
}
public void DissociateRoles(int[] memberIds, string[] roleNames)
{
var uow = _uowProvider.GetUnitOfWork();
using (var repository = _repositoryFactory.CreateMemberGroupRepository(uow))
{
repository.DissociateRoles(memberIds, roleNames);
}
}
#endregion
/// <summary>
/// Rebuilds all xml content in the cmsContentXml table for all media
/// </summary>
@@ -797,6 +985,8 @@ namespace Umbraco.Core.Services
//bulk insert it into the database
uow.Database.BulkInsertRecords(xmlItems, tr);
tr.Complete();
}
}
}
@@ -810,7 +1000,6 @@ namespace Umbraco.Core.Services
#region Event Handlers
/// <summary>
/// Occurs before Delete
/// </summary>
@@ -825,12 +1014,21 @@ namespace Umbraco.Core.Services
/// Occurs before Save
/// </summary>
public static event TypedEventHandler<IMemberService, SaveEventArgs<IMember>> Saving;
/// <summary>
/// Occurs after Create
/// </summary>
/// <remarks>
/// Please note that the Member object has been created, but might not have been saved
/// so it does not have an identity yet (meaning no Id has been set).
/// </remarks>
public static event TypedEventHandler<IMemberService, NewEventArgs<IMember>> Created;
/// <summary>
/// Occurs after Save
/// </summary>
public static event TypedEventHandler<IMemberService, SaveEventArgs<IMember>> Saved;
#endregion
/// <summary>
@@ -895,5 +1093,6 @@ namespace Umbraco.Core.Services
return new Member(name, email, username, password, -1, memType);
}
}
}
+16 -16
View File
@@ -11,7 +11,7 @@ using Umbraco.Core.Persistence.UnitOfWork;
namespace Umbraco.Core.Services
{
internal class MemberTypeService : ContentTypeServiceBase, IMemberTypeService
public class MemberTypeService : ContentTypeServiceBase, IMemberTypeService
{
private readonly IDatabaseUnitOfWorkProvider _uowProvider;
private readonly RepositoryFactory _repositoryFactory;
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Services
_memberService = memberService;
}
public IEnumerable<IMemberType> GetAllMemberTypes(params int[] ids)
public IEnumerable<IMemberType> GetAll(params int[] ids)
{
using (var repository = _repositoryFactory.CreateMemberTypeRepository(_uowProvider.GetUnitOfWork()))
{
@@ -49,7 +49,7 @@ namespace Umbraco.Core.Services
/// </summary>
/// <param name="id">Id of the <see cref="IMemberType"/> to retrieve</param>
/// <returns><see cref="IMemberType"/></returns>
public IMemberType GetMemberType(int id)
public IMemberType Get(int id)
{
using (var repository = _repositoryFactory.CreateMemberTypeRepository(_uowProvider.GetUnitOfWork()))
{
@@ -62,7 +62,7 @@ namespace Umbraco.Core.Services
/// </summary>
/// <param name="alias">Alias of the <see cref="IMemberType"/> to retrieve</param>
/// <returns><see cref="IMemberType"/></returns>
public IMemberType GetMemberType(string alias)
public IMemberType Get(string alias)
{
using (var repository = _repositoryFactory.CreateMemberTypeRepository(_uowProvider.GetUnitOfWork()))
{
@@ -75,7 +75,7 @@ namespace Umbraco.Core.Services
public void Save(IMemberType memberType, int userId = 0)
{
if (SavingMemberType.IsRaisedEventCancelled(new SaveEventArgs<IMemberType>(memberType), this))
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMemberType>(memberType), this))
return;
using (new WriteLock(Locker))
@@ -91,14 +91,14 @@ namespace Umbraco.Core.Services
UpdateContentXmlStructure(memberType);
}
SavedMemberType.RaiseEvent(new SaveEventArgs<IMemberType>(memberType, false), this);
Saved.RaiseEvent(new SaveEventArgs<IMemberType>(memberType, false), this);
}
public void Save(IEnumerable<IMemberType> memberTypes, int userId = 0)
{
var asArray = memberTypes.ToArray();
if (SavingMemberType.IsRaisedEventCancelled(new SaveEventArgs<IMemberType>(asArray), this))
if (Saving.IsRaisedEventCancelled(new SaveEventArgs<IMemberType>(asArray), this))
return;
using (new WriteLock(Locker))
@@ -118,12 +118,12 @@ namespace Umbraco.Core.Services
UpdateContentXmlStructure(asArray.Cast<IContentTypeBase>().ToArray());
}
SavedMemberType.RaiseEvent(new SaveEventArgs<IMemberType>(asArray, false), this);
Saved.RaiseEvent(new SaveEventArgs<IMemberType>(asArray, false), this);
}
public void Delete(IMemberType memberType, int userId = 0)
{
if (DeletingMemberType.IsRaisedEventCancelled(new DeleteEventArgs<IMemberType>(memberType), this))
if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs<IMemberType>(memberType), this))
return;
using (new WriteLock(Locker))
@@ -136,7 +136,7 @@ namespace Umbraco.Core.Services
repository.Delete(memberType);
uow.Commit();
DeletedMemberType.RaiseEvent(new DeleteEventArgs<IMemberType>(memberType, false), this);
Deleted.RaiseEvent(new DeleteEventArgs<IMemberType>(memberType, false), this);
}
}
}
@@ -145,7 +145,7 @@ namespace Umbraco.Core.Services
{
var asArray = memberTypes.ToArray();
if (DeletingMemberType.IsRaisedEventCancelled(new DeleteEventArgs<IMemberType>(asArray), this))
if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs<IMemberType>(asArray), this))
return;
using (new WriteLock(Locker))
@@ -165,7 +165,7 @@ namespace Umbraco.Core.Services
uow.Commit();
DeletedMemberType.RaiseEvent(new DeleteEventArgs<IMemberType>(asArray, false), this);
Deleted.RaiseEvent(new DeleteEventArgs<IMemberType>(asArray, false), this);
}
}
}
@@ -195,21 +195,21 @@ namespace Umbraco.Core.Services
/// <summary>
/// Occurs before Save
/// </summary>
public static event TypedEventHandler<IMemberTypeService, SaveEventArgs<IMemberType>> SavingMemberType;
public static event TypedEventHandler<IMemberTypeService, SaveEventArgs<IMemberType>> Saving;
/// <summary>
/// Occurs after Save
/// </summary>
public static event TypedEventHandler<IMemberTypeService, SaveEventArgs<IMemberType>> SavedMemberType;
public static event TypedEventHandler<IMemberTypeService, SaveEventArgs<IMemberType>> Saved;
/// <summary>
/// Occurs before Delete
/// </summary>
public static event TypedEventHandler<IMemberTypeService, DeleteEventArgs<IMemberType>> DeletingMemberType;
public static event TypedEventHandler<IMemberTypeService, DeleteEventArgs<IMemberType>> Deleting;
/// <summary>
/// Occurs after Delete
/// </summary>
public static event TypedEventHandler<IMemberTypeService, DeleteEventArgs<IMemberType>> DeletedMemberType;
public static event TypedEventHandler<IMemberTypeService, DeleteEventArgs<IMemberType>> Deleted;
}
}

Some files were not shown because too many files have changed in this diff Show More