Compare commits

...

287 Commits

Author SHA1 Message Date
Rasmus John Pedersen 87716c7ed8 Only add "Move" action once 2018-10-11 19:46:43 +02:00
Kenn Jacobsen afa3e9b5eb Improve image cropper UX (#3149) 2018-10-09 22:54:51 +02:00
Jan Skovgaard 3aece09e09 3223 - Minor tweaks and code alignment for the checkbox and color picker styling (#3224)
* Make the focus effect on the toggle use the same box-shadow as is already being used in the color picker instead of doing it differently

* Use the color variables instead of hard coded color and also make use of LESS' fade function outputting an rgba() color
2018-10-09 22:25:42 +02:00
Dave Woestenborghs fd1a9bb365 #3214 - umbracoUrlAlias with uppercase characters (#3220) 2018-10-09 21:51:04 +02:00
Kenn Jacobsen 4d1b361f8f Style Public access dialog (#3194) 2018-10-09 21:32:54 +02:00
Sebastiaan Janssen ee4a252b07 Revert "Fixed udi's rendered in rte content (#2531)"
This reverts commit b0374695b1.
2018-10-09 21:19:55 +02:00
Jan Skovgaard d1b1a1cf6d #3178 - Make the Checkbox/TrueFalse property editor configurable (#3179) 2018-10-09 14:23:09 +02:00
Poornima Nayar 7e16cf360a Issue with the bottom border looking out of place on the select editor screen fixed 2018-10-09 12:36:28 +02:00
Poornima Nayar 9986c10cec Cleaned up the view by removing inline styles and style tags on the view itself.
Removed inline styles in the code behind files
Moved all styles into the modals.less stylesheet
2018-10-09 12:35:32 +02:00
Anders Bjerner 9b4f879b6d Added XML documentation to the DatabaseSchemaHelper class (#3205) 2018-10-09 12:28:43 +02:00
Kenn Jacobsen 62d65f0e3a Style the sort result so it looks like e.g. the copy dialog result 2018-10-09 12:09:12 +02:00
Jan Skovgaard 8d35dac9b6 #3187 - Small UI fixes for the toggle directive (#3188) 2018-10-09 12:00:29 +02:00
Kenn Jacobsen b8890aee25 Safe(r) handling of invalid images in the image cropper 2018-10-09 11:12:47 +02:00
Paul Seal bb23e8e200 - fix styling of Learn Umbraco help list (#3184) 2018-10-09 10:56:54 +02:00
Paul Seal cbc3ca0768 Updated copyright year 2018-10-09 10:56:18 +02:00
Søren Kottal e76d7cf060 removes selector 2018-10-09 10:45:03 +02:00
Jan Skovgaard 471e47e11b #3163 - Don't overwrite the label name even though labels are disabled in the color picker (#3164) 2018-10-09 10:41:31 +02:00
Sebastiaan Janssen 747edaa6ce #3141 fixed broken Do something else button (#3154) 2018-10-09 10:20:46 +02:00
Nathan Woulfe 08818c6358 removes ng-show from iframe, make loader background a solid color to hide iframe while it loads 2018-10-09 10:08:51 +02:00
Dave Woestenborghs 94922ccbd2 #3141 fixed the problem differently after input from @markadrake 2018-10-09 08:51:02 +02:00
Poornima Nayar 3977d24eb2 Button styling on inactive user profile & clean up user view (#3170) 2018-10-08 15:29:09 +02:00
Kenn Jacobsen 2e135d2006 Register an audit on the parent node when sorting child nodes. 2018-10-08 15:11:51 +02:00
Kenn Jacobsen b820baf643 Whe moving an item, make sure the current user is registered in Audit instead of the default user (#3150) 2018-10-08 14:27:18 +02:00
Kim Holzmann a3cf1d7d58 #3138 - Can add a null item to the grid
Don't perform submit function if selectedItem is undefined
2018-10-08 14:22:04 +02:00
KimHolzmann 4d7a36e017 #3001 Styles cannot be saved - Not sure if oldName is legacy (#3123) 2018-10-08 14:04:52 +02:00
Sebastiaan Janssen a9756e065c Don't show toggles to create templates when that feature is disabled.
Also default the toggle to false when the feature is disabled.
2018-10-08 13:07:54 +02:00
Robert 59962c7afe Merge pull request #3136 from umbraco/temp-3063-xmlPublishedContent-lock
Lock XmlPublishedContent initialization for thread-safety
2018-10-08 09:58:58 +02:00
Jan Skovgaard 0f3da1ae14 #3159 - Add border around the colors from the approved color picker (#3161) 2018-10-08 08:38:24 +02:00
Poornima Nayar 774f1d706c Fixed issue with actions dropdown menu being partially visible. 2018-10-08 08:17:48 +02:00
Sebastiaan Janssen 6b55c11321 Merge pull request #3156 from jannikanker/patch-1
Lecoati CSS reference removed (issue #3147)
2018-10-08 08:13:04 +02:00
Sebastiaan Janssen 2737085161 Merge pull request #3167 from rahulkumaran/licsene-patch
Update LICENSE.md
2018-10-08 08:10:21 +02:00
Rahul Arulkumaran e7d7de6273 Update LICENSE.md 2018-10-05 11:43:41 +05:30
Jannik Anker b6c3297884 Lecoati CSS reference removed (issue #3147)
ApprovedColorPickerController had a reference for no apparent reason.
2018-10-04 17:16:57 +02:00
Dave Woestenborghs 9d36ee6bd8 #3141 fixed broken Do something else button 2018-10-04 15:49:32 +02:00
Bjarne Fyrstenborg 7355ba4b23 Add option to rename colorpicker labels (#3121) 2018-10-04 08:36:21 +02:00
Jan Skovgaard deca5d7bdb Refactor error handling to serve different error messages depending on the context. If we know that the id being moved is the same as the id we want to move it to then show a specific error message hinting the editor what's wrong and otherwise show the usual generic error message. 2018-10-04 08:19:51 +02:00
Anders Bjerner bc081db9e6 Sentences should end with a period (#3144) 2018-10-04 08:16:11 +02:00
Sebastiaan Janssen b6966055b4 Merge pull request #3140 from StrikerRUS/domain
updated domain in links to Umbraco community
2018-10-03 18:29:11 +02:00
Sebastiaan Janssen 2389901ba9 Merge pull request #3139 from ThomasAdams2/twitter-settings-typo
Fix typo in twitter settings section of EmbeddedMedia configs
2018-10-03 18:23:09 +02:00
Claus 9579b97dde fixes #3124 - logging in BaseDataCreation. 2018-10-03 18:17:46 +02:00
Claus c27b9d76db fixes #3126 - If no property data is found for a specific version - a null exception is thrown.
- Throwing an exception with a description instead of hitting a null exception.
2018-10-03 18:16:56 +02:00
KimHolzmann a8df8f484f #3022 media uploader in rte doesn't select uploaded image (#3117) 2018-10-03 18:13:35 +02:00
Jan Skovgaard 0a245dda43 Add an outer check to make sure the scope.includeSubFolders property is not undefined, which makes the media render in the view again 2018-10-03 17:38:44 +02:00
BatJan 125bbdd5bd #3102 - Make styling for media search dialogue prettier (#3103) 2018-10-03 17:20:04 +02:00
Dave Woestenborghs 321460c395 #3099 Added docs for tour directives (#3100) 2018-10-03 17:05:25 +02:00
Sebastiaan Janssen 6bd31636f0 Merge pull request #3086 from kjac/fix-nc-dragging-discards-changes
Avoid data loss when dragging an unsaved Nested Content item
2018-10-03 17:03:49 +02:00
Sebastiaan Janssen e80c450e42 Merge pull request #3085 from kjac/fix-nc-config-duplicate-doctypes
Don't let the same doctype be selectable twice in the Nested Content configuration
2018-10-03 16:52:58 +02:00
Sebastiaan Janssen 262f7aff7c Merge pull request #3084 from kjac/fix-nc-rte-loading-v2
Fix loading issue for RTE's in Nested Content
2018-10-03 16:33:28 +02:00
StrikerRUS 62a82c17c2 updated domain in links to Umbraco community 2018-10-03 17:33:11 +03:00
Thomas Adams 833137772d Fix typo in twitter settings section of EmbeddedMedia configs 2018-10-03 15:04:33 +01:00
Sebastiaan Janssen 69528704ca Merge pull request #3106 from umbraco/abjerner-patch-3
Hide the "Links" box when there are no links
2018-10-03 15:36:16 +02:00
Sebastiaan Janssen be140bd06c Merge pull request #3104 from umbraco/abjerner-patch-2
Hide "Created Date" field when the media hasn't yet been created
2018-10-03 15:35:35 +02:00
Sebastiaan Janssen 2bda1a211d Merge pull request #3107 from umbraco/abjerner-patch-4
Should be "JavaScript" instead of "javascript"
2018-10-03 15:34:40 +02:00
Stephan f42bb663ff Lock XmlPublishedContent initialization for thread-safety 2018-10-03 15:17:32 +02:00
Sebastiaan Janssen ff0b95b337 Merge pull request #3083 from kjac/fix-nc-dragging-offset
Fix Nested Content "second time dragging" issue
2018-10-03 11:46:35 +02:00
Sebastiaan Janssen 7c28e8979a Merge pull request #3082 from kjac/fix-nc-icon-colors
Ensure the correct color for items in the Nested Content item picker
2018-10-03 11:17:27 +02:00
Sebastiaan Janssen 93ae55c919 Removes the DatabaseSchemaValidationHealthCheck for now until we can improve it
Fixes #3132
2018-10-03 10:27:07 +02:00
Claus 985e1cc1b7 fixing annoying typo... 2018-10-03 07:49:36 +02:00
Sebastiaan Janssen c90e7735f9 Fix initial upload for svg and correct the way the cropper elements are hidden when cropping is not possible 2018-10-02 15:24:51 +02:00
Anders Bjerner 3dffb59f72 Should be "JavaScript" instead of "javascript" 2018-10-01 21:55:13 +02:00
Anders Bjerner 38bd53978b Should be "JavaScript" instead of "javascript" 2018-10-01 21:53:53 +02:00
Anders Bjerner 9c04abc5ad Hide the "Links" box when there are no links 2018-10-01 21:40:24 +02:00
Anders Bjerner 66221364ca Hide "Created Date" field when the media hasn't yet been created 2018-10-01 21:21:17 +02:00
Stephan eda6e084a7 Fix casing issue in member group service/repo 2018-10-01 14:37:40 +02:00
Sebastiaan Janssen 328b4b1556 Merge pull request #3077 from umbraco/abjerner-patch-1
Removed "debugger" statement from linkpicker overlay controller
2018-09-30 22:19:05 +02:00
Anders Bjerner fabab44342 Removed "debugger" statement from linkpicker overlay 2018-09-30 19:31:40 +02:00
Kenn Jacobsen 2c9256c672 Don't let the same doctype be selectable twice in the Nested Content configuration 2018-09-30 18:50:33 +02:00
agrath 63a2a155d1 User invite flow review (#3000) 2018-09-30 15:03:52 +02:00
KimHolzmann 8fad718347 #2916 Media picker searches entire media archive (#3061) 2018-09-30 14:08:01 +02:00
Sebastiaan Janssen 3879b81ed3 Merge pull request #3062 from markadrake/temp-3058
If TinyMCE has not loaded yet, return the initialized value.
2018-09-30 13:44:11 +02:00
Mark Drake c5de33dcae Added an active css class for Umbraco Tree items (#3056) 2018-09-30 13:38:19 +02:00
Sebastiaan Janssen f36139619a Merge pull request #3060 from markadrake/temp-3051
Minimal changes to class `nav-tabs` styling
2018-09-30 13:29:01 +02:00
Sebastiaan Janssen 093182c56d Allow svg uploads 2018-09-30 13:12:11 +02:00
imranhaidercogworks 5f1fb144e0 Uploading SVG's Causes Error (Depending on imageFileTypes Setting) (#3072) 2018-09-30 13:09:44 +02:00
Sebastiaan Janssen 6b398a2d16 Merge pull request #3074 from arknu/tags-internal
Make TagSupport and related types public
2018-09-30 11:02:52 +02:00
Sebastiaan Janssen 3c73f6a764 Rename name property so title gets set for the doctype icon picker - relates to PR #2864 2018-09-30 10:59:20 +02:00
Bjarne Fyrstenborg 865cdc09c6 U4-11588 - Adjustments of color picker (#2864) 2018-09-30 10:50:05 +02:00
Asbjørn 7f107a8559 Make TagSupport and related types public #2988 2018-09-29 17:42:45 +02:00
Kenn Jacobsen 0dbbb585ad Fix loading issue for RTE's in Nested Content 2018-09-29 17:06:04 +02:00
Kenn Jacobsen a7573ce31f Avoid data loss when dragging an unsaved Nested Content item (#3014) 2018-09-29 07:35:16 +02:00
Kenn Jacobsen c6e2ced971 Fix Nested Content "second time dragging" issue 2018-09-29 07:30:27 +02:00
Kenn Jacobsen 45f574ed3a Ensure the correct color for items in the Nested Content item picker 2018-09-29 07:27:39 +02:00
Mark Drake 12a9466cd7 if tinymce has not loaded yet, return the initialized value only 2018-09-27 17:03:24 -04:00
Mark Drake fce0dd98f9 minimal changes to class nav-tabs styling 2018-09-27 13:34:20 -04:00
Sebastiaan Janssen 25aa74b4cd Merge pull request #2937 from umbraco/temp-view-compilation
Changes compilation batch mode to true uses Roslyn compiler for views
2018-09-27 12:01:00 +02:00
Sebastiaan Janssen 976d329292 Merge pull request #3005 from dalyUSN/temp-U4-9967
Preview update: smartphone sizes
2018-09-27 11:55:05 +02:00
Sebastiaan Janssen b079593efd Merge pull request #2083 from Eyescream/#U4-5139
U4-5139 Error uploading a file when filename contains comma
2018-09-27 11:17:27 +02:00
Sebastiaan Janssen 883da4eaf1 Merge pull request #2408 from abjerner/patch-35
"Select editor" items shouldn't have a max height
2018-09-26 23:28:12 +02:00
Marc Goodson c021cc50ce U4-10669 7.8. Show 301 url redirects on info tab too (#2452) 2018-09-26 23:16:54 +02:00
Sebastiaan Janssen 85291b562e Merge pull request #2533 from ronaldbarendse/U4-10586
Added property editor alias to PreValueDisplayResolver warning
2018-09-26 23:03:57 +02:00
Sebastiaan Janssen ca8c6248c1 Merge pull request #2561 from umbraco/temp-U4-10816
fixes U4-10816 Umbraco V7.7.1 - Media - File upload taking full path
2018-09-26 22:53:41 +02:00
Sebastiaan Janssen 6843fa72aa Merge pull request #3016 from readingdancer/patch-1
Updated the URL for the issue tracker.
2018-09-26 22:02:35 +02:00
Sebastiaan Janssen 258baad127 Removed uneccessary properties 2018-09-26 22:01:09 +02:00
Chris Houston 0e6376f4e5 Updated the URL for the issue tracker.
Also updated the version number to reflect the current version.
2018-09-26 21:58:05 +02:00
Dave Woestenborghs b0374695b1 Fixed udi's rendered in rte content (#2531) 2018-09-26 21:51:20 +02:00
Dave Woestenborghs 471bc7f116 U4-11458 - Fix multiple issues for angular logResource (#2719) 2018-09-26 20:48:54 +02:00
Sebastiaan Janssen 9c0aa5e099 Merge pull request #2072 from Adolfi/U4-6961
U4-6961 Prevent from deleting default used datatypes (e.g. Label)
2018-09-26 18:04:13 +02:00
Sebastiaan Janssen 3940176f23 Just a bit of code cleanup 2018-09-26 18:01:50 +02:00
Dennis Adolfi 5832387484 Added the DefaultLabelDataTypeIdas a non-deletable datatype. 2018-09-26 17:55:28 +02:00
Sebastiaan Janssen a1224da5e1 Fixes #3036
Removes WebClient completely except for in an old legacy class that is not used for anything
any more (umbraco.cms.businesslogic.packager.Installer.Fetch).
2018-09-26 13:27:16 +02:00
Sebastiaan Janssen 540e4f17d6 Fixes #3042
Code comes from v8, commit: 9bfe9e6bbf
2018-09-26 09:48:24 +02:00
Sebastiaan Janssen 2e92172ed4 Merge pull request #2984 from bjarnef/dev-v7-momentjs-locales
Load specific locales for moment.js
2018-09-25 23:28:00 +02:00
Sebastiaan Janssen f0fbc808f2 Merge pull request #3025 from WebCentrum/temp-#3024
#3024: Removed unnecessary queries in MultiNodeTreePickerPropertyConv…
2018-09-25 23:05:09 +02:00
Sebastiaan Janssen c44a22d205 Merge pull request #3023 from UEDevs/temp-U4-11302
Fixes content getting deleted when saving an RTE before it's fully loaded
2018-09-25 20:55:48 +02:00
Sebastiaan Janssen 0f6ce1eeba Merge pull request #2965 from poornimanayar/2964
Removed the anchor tag around notification
2018-09-25 17:44:53 +02:00
Sebastiaan Janssen cbeb0de748 Merge pull request #2947 from readingdancer/Issue-#2910
Fixing issue #2910 -  List view shows dimmed link for saved item
2018-09-25 17:37:25 +02:00
Sebastiaan Janssen e06fef2b6d Merge pull request #2901 from umbraco/abjerner-patch-1
Hide "Created Date" field when the content hasn't yet been created
2018-09-25 17:33:21 +02:00
Sebastiaan Janssen 524f53d03f Merge pull request #2899 from villian/temp-U4-8143
U4-8143 - MNTP (content picker) does not set $dirty
2018-09-25 17:19:12 +02:00
Sebastiaan Janssen d2d77d2732 Merge pull request #2895 from marcemarc/temp-u4-11561
Make the file extension visible when picking a file using the media picker
2018-09-25 17:07:48 +02:00
Sebastiaan Janssen 31bdc9d9a6 Merge pull request #2894 from KimHolzmann/dev-v7
U4-8824 Selection in media grid doesn't match when filter has value
2018-09-25 16:58:32 +02:00
Sebastiaan Janssen 8c8e23f981 Merge pull request #2861 from raduorleanu/temp2-U4-11570
Found additional usages for (var web = new HttpClient()) and replaced…
2018-09-25 16:17:26 +02:00
Sebastiaan Janssen 35ec07f970 Some tiny code style updates 2018-09-25 16:15:37 +02:00
Sebastiaan Janssen 917269a260 Merge branch 'temp2-U4-11570' of https://github.com/raduorleanu/Umbraco-CMS into raduorleanu-temp2-U4-11570 2018-09-25 16:09:58 +02:00
Sebastiaan Janssen 00fc1b7c26 Merge branch 'dev-v7' into temp-view-compilation 2018-09-25 15:13:22 +02:00
Sebastiaan Janssen 53c218428f Merge pull request #3029 from kedde/dev-v7
fix #3020 - casing errors
2018-09-25 14:41:35 +02:00
Sebastiaan Janssen b9f5ddab06 Merge pull request #2866 from umbraco/temp-U4-11458-2
Fixes SQL generation for paged results for both UserRepository and AuditRepository
2018-09-25 14:27:27 +02:00
Umbraco HQ f9973f602c Fixes the belle build (requires newer node version) 2018-09-25 14:03:21 +02:00
kedde 3d0d8d7430 fix mysql casing 2018-09-24 20:00:08 +02:00
Pavel Budik 70a851dbf9 #3024: Removed unnecessary queries in MultiNodeTreePickerPropertyConverter 2018-09-24 14:23:00 +02:00
Jim Osborn 3f79067e26 Fixes content getting deleted when saving an RTE before it's fully loaded. 2018-09-24 12:38:04 +01:00
Paul Daly 1050e9d0a1 Preview update: smartphone sizes
The current most used screen size on a smarthphone is 360x640 according to Globalstats Statcounter. With this in mind I have adjusted the sizes of the preview frames for both portrait and landscape. Minor change but something that has been on my mind for a while.
2018-09-20 13:15:22 +01:00
Sebastiaan Janssen 8bf8e0a741 Updates CDF 2018-09-20 08:48:46 +02:00
Sebastiaan Janssen fd0e2f5a9c Merge pull request #2992 from dampee/patch-3
old issue tracker reference
2018-09-17 21:30:10 +02:00
Damiaan 6ee235b640 old issue tracker reference
Since the github issue tracker is used, we should at least mention that.
2018-09-17 20:42:22 +02:00
Sebastiaan Janssen 2921413476 Merge pull request #2941 from AliSheikhTaheri/temp-2939
temp-2939 - Removed hardcoded number of rows from textarea with the d…
2018-09-17 20:18:17 +02:00
Poornima Nayar 7f4280c67f added checks for whitespace 2018-09-14 10:06:32 +01:00
Bjarne Fyrstenborg e9f8fb8d1f Remove console.log 2018-09-14 01:10:17 +02:00
Bjarne Fyrstenborg 28ae25c166 Move logic to load moment.js locales to public function in userservice 2018-09-14 00:57:19 +02:00
Ali.Taheri 1acc61ede8 temp-2939 - corrected the data type from boolean to int for rich text editor. 2018-09-13 16:24:50 +01:00
Sebastiaan Janssen 31ed4e0574 Merge pull request #2973 from prjseal/patch-1
update the release notes url
2018-09-13 12:01:01 +02:00
Poornima Nayar a0ae39a147 Reworked the notifications banner to use ng-switch to show the anchor tag when there is a notification url. 2018-09-13 10:27:48 +01:00
Paul Seal 9e3cf00cc0 update the release notes url 2018-09-12 13:32:10 +01:00
Poornima Nayar fbbc89b477 Removed the anchor tag around notification 2018-09-11 16:29:21 +01:00
Shannon 2f74720c38 updates wording 2018-09-10 11:12:46 +10:00
Sebastiaan Janssen 91ebc649d4 Re-apply missing changes from #2446 2018-09-09 16:35:48 +02:00
Chris Houston b2133aace1 Fixing issue #2910 2018-09-08 23:28:44 -04:00
Sebastiaan Janssen 32591eec36 Merge branch 'shoecake-U4-5572' into dev-v7 2018-09-07 15:20:36 +02:00
Sebastiaan Janssen e05a55c532 Fixes incorrectly named method and removes extraneous spaces 2018-09-07 15:20:29 +02:00
Sebastiaan Janssen f3d96ad45e Merge branch 'U4-5572' of https://github.com/shoecake/Umbraco-CMS into shoecake-U4-5572 2018-09-07 15:15:52 +02:00
Poornima Nayar 010a2e012e Clean up multiple textstring(repeatable textstring) view - (#2934)
* Clean up multiple textstring(repeatable textstring) view - Introduced some styling rules to make the view look cleaner

* Removes unnecessary additional included files from csproj
2018-09-07 14:54:20 +02:00
Ali.Taheri da88cc2d04 temp-2939 - Removed hardcoded number of rows from textarea with the default value of 10. 2018-09-07 11:04:35 +01:00
Shannon 8ff671a7c6 Changes compilation batch mode to true uses Roslyn compiler for views 2018-09-07 13:10:55 +10:00
Sebastiaan Janssen 5986899b5e Fixes #U4-10383 Feature request - Ignore casing when getting member email and username from IPublishedContent 2018-09-06 11:07:04 +02:00
Anders Bjerner c8664a886a ID property is now hidden as well when creating new content 2018-09-04 14:27:58 +02:00
Sebastiaan Janssen 5dd04d9a3e Merge pull request #2902 from umbraco/abjerner-patch-2
The name field is not automatically in focus when creating a new data type folder
2018-09-04 09:38:15 +02:00
Anders Bjerner 6ff2f1eabb The name field is not automatically in focus when creating a new data type folder 2018-09-03 18:06:15 +02:00
Anders Bjerner cbdfb6f25f Hide "Created Date" field when content hasn't yet been created 2018-09-03 17:32:39 +02:00
villian 1437af62b3 fix U4-8143 2018-09-03 17:39:17 +03:00
Sebastiaan Janssen ac9c6305e7 Update CONTRIBUTING_DETAILED.md 2018-09-03 12:12:27 +02:00
Sebastiaan Janssen b2b9b53af1 Whoops, fixes previous commit for #2896 2018-09-02 10:03:51 +02:00
Sebastiaan Janssen 2dd5010d2c Seems there is no need to hide the .small class, fixes #2896 2018-09-02 09:57:45 +02:00
Marc Goodson c6a31b30f1 position relative to stack the item above to avoid opacity issue 2018-09-01 19:27:55 +01:00
Kim Holzmann ef3abea005 U4-8824
Selection in media grid doesn't match when filter has value.
2018-09-01 12:57:32 +02:00
Marc Goodson c95cc14703 Make the file extension for files visible when picking a file using the media picker 2018-09-01 11:57:05 +01:00
Sebastiaan Janssen bfd12b3a7b Merge pull request #2888 from mvanhelmont/#2886
Media Picker should not show deleted items #2886
2018-08-31 20:43:47 +02:00
Sebastiaan Janssen 396b499e81 Merge pull request #2885 from adhaliwal34/comment-change
Fix comment regarding the length of the salt bytes array
2018-08-31 20:27:32 +02:00
Sebastiaan Janssen 61ce1bcdca Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2018-08-31 20:21:58 +02:00
Sebastiaan Janssen ec1d2a6433 Merge branch 'mvanhelmont-U4-11589' into dev-v7 2018-08-31 20:21:05 +02:00
Sebastiaan Janssen 9ea9c5d6b7 Don't repeat the code to check for and create a template 2018-08-31 20:20:37 +02:00
Sebastiaan Janssen fee9bce110 Merge branch 'U4-11589' of https://github.com/mvanhelmont/Umbraco-CMS into mvanhelmont-U4-11589 2018-08-31 20:11:50 +02:00
Sebastiaan Janssen 222720aea4 Merge pull request #2884 from AliSheikhTaheri/temp-u4-8310
Temp u4 8310 - Fixed can't rename of a document type alias by changing its casing
2018-08-31 20:06:07 +02:00
Sebastiaan Janssen 9e3213147f Merge pull request #2883 from mvanhelmont/U4-11145
U4-11145 Email validation is too strict on password reset screen
2018-08-31 19:50:54 +02:00
Marcel van Helmont c29357b845 inside ensureWithinStartNode also check if node is trashed otherwise go to startnode. 2018-08-30 21:06:29 +02:00
AJ_Dhaliwal cc680f2cfb Fix comment regarding the length of the salt bytes array 2018-08-30 18:03:44 +08:00
Sebastiaan Janssen 58dab23d04 Fix links 2018-08-30 10:00:29 +02:00
Sebastiaan Janssen 90a47cd042 Move from docs to github folder 2018-08-30 09:58:29 +02:00
Sebastiaan Janssen fb6079d4e2 Add issue templates and updated PR template 2018-08-30 09:57:17 +02:00
Shannon f359648215 fixes U4-11463 MembershipHelper is not working with basic auth on the initial request 2018-08-30 09:57:16 +02:00
Marcel van Helmont 74ca315197 added val-email to corrrectly validate emails supporting new TLD 2018-08-29 15:38:12 +02:00
Ali.Taheri 541e546f7b u4-8310 - Added error message to the xml file. 2018-08-29 14:35:20 +01:00
Ali.Taheri 26a8d680d4 u4-8310 - Fixed rename content type with the same alias but with different casing. 2018-08-29 14:28:33 +01:00
RaduOrleanu 412069414b U4-11570 - performed instantiation locally in classes where WebClient or HttpClient is used only in 1 method and added null check 2018-08-29 12:39:06 +02:00
Marcel van Helmont ec1a3f0fe8 make sure alias is camelCase format 2018-08-28 22:44:53 +02:00
Marcel van Helmont 8ce200bd16 added toggles to allow creating templates for collection and collection item 2018-08-28 21:32:18 +02:00
Sebastiaan Janssen 26e2bc6afa Merge pull request #2879 from umbraco/temp-u4-11599
U4-11599 - do not abort inst processing on error
2018-08-27 08:45:04 +02:00
Sebastiaan Janssen 546458bcfd Merge pull request #2322 from umbraco/validate-using-schema
Updates sql to include current schema in queries
2018-08-27 08:16:57 +02:00
Stephan f2090e9fc7 U4-11599 - do not abort inst processing on error 2018-08-27 08:10:39 +02:00
Sebastiaan Janssen 46b0063921 Fixes U4-11598 Scheduling the content does not reload the page at the same time 2018-08-27 06:56:05 +02:00
Sebastiaan Janssen 7fd1617759 Merge branch 'dev-v7' into validate-using-schema 2018-08-26 23:13:08 +02:00
Sebastiaan Janssen 5e7c9f2341 Merge pull request #2876 from RNHornets/temp-u4-9030
U4-9030 Moving a RTE between grid cells causes rendering issues for other RTEs
2018-08-26 22:57:17 +02:00
Sebastiaan Janssen bec8aabede Merge pull request #2442 from madsoulswe/temp-U4-10962
U4-10962 - Disable stickyheader when nested, fix margins when disabled
2018-08-26 22:17:44 +02:00
Sebastiaan Janssen c07780caff Merge pull request #2481 from SaDa1337/dev-v7.9
fix x alignment in colorpicker transparent option in umbraco skin
2018-08-26 22:08:24 +02:00
Sebastiaan Janssen 0c3d3ca545 Merge pull request #2506 from PeteDuncanson/temp-U4-11074
Added web.config to fonts folder to allow for caching out of the box
2018-08-26 21:26:45 +02:00
Sebastiaan Janssen 35a0d4451f Merge pull request #2483 from kccsf/U4-4441
U4-4441 Fix: TinyMCE overlay was showing in front of login overlay
2018-08-26 21:01:58 +02:00
Sebastiaan Janssen 03fdba6a3b Merge pull request #2512 from NathalieLarsson/dev-v7
Quick fix for U4-11085 and added filtering to list view in MNTP
2018-08-26 20:51:53 +02:00
Sebastiaan Janssen 550c383598 Also make sure there's a value for dialogOptions.filterTypes if it doesn't start with "!"
Else you get errors on `dialogOptions.filterTypes.toLowerCase()`
2018-08-26 20:47:26 +02:00
Sebastiaan Janssen 9d3d718e16 Merge branch 'dev-v7' into dev-v7 2018-08-26 20:33:00 +02:00
Ben Palmer b09bf518c6 U4-9237 Validate application parameter when getting application trees (#2315) 2018-08-26 18:12:07 +02:00
Sebastiaan Janssen 8666b222ac Merge pull request #2841 from leekelleher/U4-11556
U4-11556 - Removed metablogConfig.config
2018-08-26 18:04:50 +02:00
Sebastiaan Janssen 9e564d70ef Merge branch 'drpeck-U4-8550' into dev-v7 2018-08-26 17:57:00 +02:00
Sebastiaan Janssen 276810be6c Bump to v7.13.0 2018-08-26 17:56:13 +02:00
Sebastiaan Janssen 49df6e7c9d Merge branch 'U4-8550' of https://github.com/drpeck/Umbraco-CMS into drpeck-U4-8550
# Conflicts:
#	src/Umbraco.Web.UI/config/umbracoSettings.config
#	src/Umbraco.Web/PublishedContentExtensions.cs
2018-08-26 17:45:34 +02:00
Sebastiaan Janssen 16155ea416 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into dev-v7 2018-08-26 17:25:18 +02:00
Sebastiaan Janssen f183e27cae Merge branch 'jamescoxhead-U4-11166' into dev-v7 2018-08-26 17:24:18 +02:00
Sebastiaan Janssen a411c9c300 Make sure inactive users get the correct state attached to them 2018-08-26 17:23:52 +02:00
Sebastiaan Janssen 342ac7b1b2 Merge branch 'U4-11166' of https://github.com/jamescoxhead/Umbraco-CMS into jamescoxhead-U4-11166 2018-08-26 16:52:58 +02:00
Sebastiaan Janssen f5ac5f20a8 Merge pull request #2869 from Bazmech/temp-U4-11594
U4-11594 HasFocalPoint in ImageCropDataSet does not return correct value
2018-08-26 16:44:19 +02:00
Chris Houston 56de9ff4ae Fix for issue: U4 11409 - "Create content" tour is failing when doing the tour with the starter kit installed (#2851) 2018-08-26 14:52:14 +02:00
Arbie Sarkissian e4d8fcf019 U4-11506 - Fix Gregorian DateTime.MinValue is out of range for some calendars (like PersianCalendar) (#2821) 2018-08-24 11:15:53 +02:00
Sebastiaan Janssen e1f7e835ea Fixes U4-11584 RelatedLinks2 throws exception with null value in Link field 2018-08-24 11:08:27 +02:00
Sebastiaan Janssen d83bb6aa49 Whoops, committed the wrong file! Revert "Fixes U4-11584 RelatedLinks2 throws exception with null value in Link field"
This reverts commit 612138f0e1.
2018-08-24 11:07:55 +02:00
Robert Johnston 06e55c8c4e Use offsetParent to get the grid cell for the moved item since parents() always returns 0 results 2018-08-24 09:50:24 +01:00
Sebastiaan Janssen 612138f0e1 Fixes U4-11584 RelatedLinks2 throws exception with null value in Link field 2018-08-24 10:49:39 +02:00
Sebastiaan Janssen bfc627857d Merge pull request #2840 from WebCentrum/temp-U4-11527
U4-11527 Fix concurrency issue
2018-08-24 00:02:30 +02:00
BatJan 7d439566cd U4-11526 - Member Group Picker doesn't remove group after unselecting it during selection. (#2835) 2018-08-23 23:56:32 +02:00
Sebastiaan Janssen d224a93ce1 Merge branch 'BatJan-feature/temp-U4-11577' into dev-v7 2018-08-23 23:44:23 +02:00
Sebastiaan Janssen 3454db6ee8 No need to do an extra userService request, if the contentType is null we can't access the settings section, that's a good enough test
Also fixed the bug where editors would see the node name instead of the content type name
2018-08-23 23:36:50 +02:00
Sebastiaan Janssen b67c06a85a Remove console.log that was left behind 2018-08-23 22:23:41 +02:00
Sebastiaan Janssen 44bd3dec9a Merge branch 'dev-v7' into feature/temp-U4-11577 2018-08-23 22:22:57 +02:00
Thomas Nielsen 68ac84aa1d Sort the Umbraco.UserPicker list alphabetically by name (#2872) 2018-08-23 22:15:28 +02:00
Sebastiaan Janssen c1bf8259ef Merge branch 'rasmusjp-fix/linkpicker-url-empty' into dev-v7 2018-08-23 21:34:06 +02:00
Sebastiaan Janssen 1b1df84863 Populates the anchor when found
Also fixes one of the JS files where .model was seemingly used randomly, but the view doesn't want a .model in there
2018-08-23 21:31:31 +02:00
Sebastiaan Janssen 05fdfc6b34 Merge branch 'fix/linkpicker-url-empty' of https://github.com/rasmusjp/Umbraco-CMS into rasmusjp-fix/linkpicker-url-empty 2018-08-23 20:52:14 +02:00
Sebastiaan Janssen 18b690f11a Bump the version to 7.12.2 2018-08-23 20:45:49 +02:00
Sebastiaan Janssen d3b577fe37 Merge pull request #2867 from BatJan/features/temp-U4-11587
U4-11587 Media link does not update when the file is swapped
2018-08-23 20:37:45 +02:00
Sebastiaan Janssen 720409ef54 Merge pull request #2871 from leekelleher/U4-11595
umb-node-preview directive - corrected the title of the "Edit" button
2018-08-23 19:21:30 +02:00
Sebastiaan Janssen 919a63d0ea Merge pull request #2848 from readingdancer/U4-11569
Small tweaks to the Getting Started tour text.
2018-08-23 18:53:40 +02:00
Mads Rasmussen ef6822e15b Merge pull request #2873 from kjac/media-picker-update
Media picker: Minor style update + add help text.
2018-08-23 09:29:05 +02:00
Jan Skovgaard 015e89b927 Make sure the "open" action is only visible when logged in as an administrator 2018-08-22 11:31:07 +02:00
Jan Skovgaard 05e48376c7 Use the node object to get the name and icon so it's also displayed for non-admin users 2018-08-22 11:30:39 +02:00
Jan Skovgaard a2cc0ec411 Shorten comments 2018-08-22 11:30:07 +02:00
Jan Skovgaard d4fff97814 Move the setModePublishStatus function above the scope.previewOpenUrl...not sure why but this makes the status be visible when logged in as something other than an administrator. When logged in as an admin it worked fine before. Can't quite make sense of this. But now it works. 2018-08-22 11:23:51 +02:00
Lee Kelleher 06e99c3b33 Corrected the title of the "Edit" button
umb-node-preview directive - corrected the title of the "Edit" button
2018-08-22 09:13:43 +01:00
Jan Skovgaard ad3d27be76 Reference the node object instead of the documentType object, which returns null if the user is not logged in as an admin. 2018-08-22 10:00:54 +02:00
Jan Skovgaard 2e2fc6ad84 Make sure to check whether the open anchor for the template should be displayed or not 2018-08-22 09:31:44 +02:00
Jan Skovgaard 9f396e4b15 By default set the "allowOpen" to be false and only set it to true if the current user is an admin. This ensures that the "Open" anchors are never displayed for other than admin users. 2018-08-22 09:13:46 +02:00
Barry Bell f42862c42a Update ImageCropDataSet.cs
If only one of the Left or Right values changed the HasFocalPoint function would return false but this should now return true if only one is altered
2018-08-21 21:07:54 +01:00
Mads Rasmussen f7201a70bd add colored border 2018-08-21 21:20:38 +02:00
Mads Rasmussen ec67ab83af Merge branch 'patch-1' of git://github.com/jannikanker/Umbraco-CMS into jannikanker-patch-1 2018-08-21 21:10:01 +02:00
Rasmus John Pedersen a725ddae5a Only remove ? or # if it's part of the url 2018-08-21 17:10:46 +02:00
Jan Skovgaard 8f2c253138 Refactort the scope.nodeUrl to be updated whenever save is hit in the existing update watcher 2018-08-21 14:52:00 +02:00
Shannon efbcce5261 Fixes SQL generation for paged results for both UserRepository and AuditRepository 2018-08-21 10:41:50 +10:00
Sebastiaan Janssen e6597d47e3 Fixes U4-11574 - return an empty string if the datatype is in "single" mode and nothing is selected 2018-08-20 16:12:23 +02:00
Nathan Woulfe 89f69bd2a8 U4 4732 - fix regressions in 7.12 (#2862) 2018-08-20 16:10:36 +02:00
Sebastiaan Janssen 8087fc4c9a Merge pull request #2858 from umbraco/temp-U4-11579
U4-11579 Take startNodeId into account before picking the current nod…
2018-08-20 12:06:45 +02:00
RaduOrleanu 07e5161988 U4-11570 - changed WebClient() from created inside of using to check if null and then creating it 2018-08-18 20:21:24 +02:00
RaduOrleanu 03e642fced Found additional usages for (var web = new HttpClient()) and replaced with private static readonly HttpClient HttpClient = new HttpClient(); 2018-08-17 15:21:33 +02:00
RaduOrleanu 051b595f82 Found additional usages for (var web = new HttpClient()) and replaced with private static readonly HttpClient HttpClient = new HttpClient(); 2018-08-17 15:18:08 +02:00
RaduOrleanu 0cd3bb38ed Found additional usages for (var web = new HttpClient()) and replaced with private static readonly HttpClient HttpClient = new HttpClient(); 2018-08-17 15:07:57 +02:00
Radu Orleanu f665f8af89 fixing U4-11570 (#2860) 2018-08-17 14:04:35 +02:00
Kenn Jacobsen de8a24c691 Add "info" style to upload button + add help text when the dropzone is hidden. 2018-08-17 12:22:54 +02:00
Sebastiaan Janssen c4163e94c0 Merge pull request #2856 from dawoe/remove-deleted-scripts-from-solution
Removed files from solution that are not longer present in repo
2018-08-17 08:25:50 +02:00
Sebastiaan Janssen 62855d021f Merge pull request #2857 from umbraco/temp-U4-11581
U4-11581 In rare cases the umbracoLanguage table has a constraint ins…
2018-08-17 08:24:43 +02:00
Shannon 49430ca0a5 fixes logic order of dropping indexes 2018-08-17 16:07:53 +10:00
Shannon 9d75e36eb4 Ensures that checking for constraints/indexes is done within the transaction before dropping anything instead of before the transaction. 2018-08-17 15:20:12 +10:00
Shannon 5068b8ae9f Fixes DB schema validation 2018-08-17 11:16:10 +10:00
Shannon cdf3581721 code simplification 2018-08-17 10:53:45 +10:00
Shannon 0c6cca44d8 Fixes SQL providers for returning the correct results for constraints 2018-08-17 10:53:21 +10:00
Sebastiaan Janssen f18b0aa774 U4-11579 Take startNodeId into account before picking the current node to sync to 2018-08-16 13:53:42 +02:00
Sebastiaan Janssen b9e8dd8b86 Removes unused import statement 2018-08-16 13:47:20 +02:00
Sebastiaan Janssen 45d8d302c9 U4-11581 In rare cases the umbracoLanguage table has a constraint instead of an index, making the migration fail 2018-08-16 12:10:21 +02:00
Dave Woestenborghs e0ce9f1a77 Removed files from solution that are not longer present in repo 2018-08-16 10:35:08 +02:00
Sebastiaan Janssen d7a0886097 Fixes problem where we try to query a table that hasn't been updated with the new column yet, so we can't use the DTO 2018-08-16 10:32:10 +02:00
Sebastiaan Janssen 39e8a9fa67 Bump version to 7.12.1 2018-08-15 15:47:21 +02:00
Warren Buckley 1dbf509020 Merge pull request #2855 from umbraco/temp7-156
fixes: 156: Update nested content css/markup so it doesn't collide with the old package
2018-08-15 14:03:47 +01:00
Mads Rasmussen 8ce93055ef update colors to use variables and match the new color scheme 2018-08-15 13:00:40 +02:00
Mads Rasmussen ee4b2adbd4 prefix all nested content css classes with "umb" 2018-08-15 11:59:06 +02:00
Jannik Anker de73080e14 U4-11572
Add border to selected icon in document type icon picker dialog
2018-08-14 13:37:54 +02:00
Mads Rasmussen 6c0d14e0f4 add type="button" to toggle so it doesn't auto-submits a form 2018-08-14 13:14:49 +02:00
Chris Houston ba682d95dc Small tweaks to the Getting Started tour text. 2018-08-12 01:16:57 -04:00
Sebastiaan Janssen fd888cab4b Fixes U4-9095 - the textService.Localize always returns some string, either the translation or [alias] - so we need to make sure it actually translated something 2018-08-09 14:36:08 +02:00
leekelleher 92273f263b U4-11556 V8 - Removed metablogConfig.config
http://issues.umbraco.org/issue/U4-11556

For v7, I've marked the `SystemFiles.MetablogConfig` strings as deprecated.
2018-08-08 10:23:14 +01:00
Pavel Budik 3efbb47aed U4-11527 Fix concurrency issue 2018-08-08 10:38:53 +02:00
James Coxhead 9a774c8f9e Added inactive state for users who haven't logged in 2018-08-02 22:01:45 +01:00
James Coxhead f81dc16210 Specify which user states we want to include when getting all users 2018-08-02 21:55:04 +01:00
James Coxhead c4a787331f Reverted previous commit to show disabled users in the status filter 2018-08-02 21:54:00 +01:00
James Coxhead 3078be93b6 Remove disabled users option from users list view filter 2018-07-05 21:07:12 +01:00
James Coxhead 0a2fd277a6 U4-11166 Hide disabled users from the users list view 2018-06-28 20:19:02 +01:00
Morten Christensen f5b017ed67 Updates sql to include current schema in queries 2018-06-08 10:44:11 +02:00
Claus 08bf48b8b7 adding the fix for content controller - to support when uploads are done via content. 2018-04-05 11:04:56 +02:00
Claus 8ddda5868e fixes U4-10816 Umbraco V7.7.1 - Media - File upload taking full path 2018-04-05 10:41:08 +02:00
Ronald Barendse 477761a81a Added property editor alias to PreValueDisplayResolver warning and updated key lookup 2018-03-22 10:41:14 +01:00
Nathalie Festin 4512cf0145 Filtering items 'Allow items of type' in mini list view in MNTP 2018-03-11 20:49:43 +01:00
Nathalie Festin 38e9a3d2ee Bug in exclude - Dialogoption.filter 2018-03-11 20:41:51 +01:00
Peter Duncanson 13f42773d7 Added web.config to fonts folder to allow for caching out of the box 2018-03-06 17:02:16 +00:00
Steve Fawcett 71d3c1112e Fix: TinyMCE overlay was showing in front of login overlay 2018-02-27 17:48:53 +00:00
Maciej Sadowski 5bfac6c5b4 fix x alignment in colorpicker in umbraco skin 2018-02-27 09:23:35 +01:00
Dennis Öhman ebae69d00c U4-10962 - Disable stickyheader when nested, fix margins when disabled 2018-02-11 16:58:46 +01:00
Anders Bjerner a8ea535bb2 "Select editor" items shouldn't have a max height 2018-01-22 18:52:54 +01:00
Eyescream 3b231f5138 Update fileupload.controller.js
Uploading a file with a comma in it resulted in an error (because server side there was a split on the comma character). The comma later was replaced with a dash, so it's safe to replace it before sending it to the server.
2017-07-28 15:49:07 +02:00
David Peck 1ece576825 Merge branch 'dev-v7' of https://github.com/umbraco/Umbraco-CMS into U4-8550
Conflicts:
	src/Umbraco.Web.UI/config/umbracoSettings.config
2017-05-30 23:13:33 +01:00
David Peck a2611ce35f Changed the name of IsTemplateAllowed to IsAllowedTemplate to reflect the usage elsewhere and changed the overload of IsAllowedTemplate with the alias parameter to use the template id version to be more DRY 2017-05-30 22:39:26 +01:00
David Peck 7a89580db2 Merge branch 'dev-v7' into U4-8550 2016-11-08 21:06:39 +00:00
David Peck a031551fb2 Rationalised changes in whitespace, to reduce the differences in the PR 2016-11-08 17:59:30 +00:00
David Peck 69728fb5c4 Changed Allowed Templates setting to be validate templates which checks url only 2016-11-08 08:27:18 +00:00
David Peck afd91f8adb Added ability to only allow templates what are allowed by the document type 2016-11-03 16:25:45 +00:00
Patrick Scott d99d5a0b36 Issue U4-5572 convert file name to friendly media item name 2016-11-03 14:30:57 +00:00
286 changed files with 5680 additions and 4045 deletions
View File
@@ -17,7 +17,7 @@ Assume positive intent and try to understand before being understood.
Treat others as you would like to be treated.
This also goes for treating the HQ with respect. For example: dont promote products on [our.umbraco.org](https://our.umbraco.org) that directly compete with our commercial offerings which enables us to work for a sustainable Umbraco.
This also goes for treating the HQ with respect. For example: dont promote products on [our.umbraco.com](https://our.umbraco.com) that directly compete with our commercial offerings which enables us to work for a sustainable Umbraco.
## Open
@@ -82,7 +82,7 @@ These wonderful volunteers will provide you with a first reply to your PR, revie
You can get in touch with [the PR team](#the-pr-team) in multiple ways, we love open conversations and we are a friendly bunch. No question you have is stupid. Any questions you have usually helps out multiple people with the same question. Ask away:
- If there's an existing issue on the issue tracker then that's a good place to leave questions and discuss how to start or move forward
- Unsure where to start? Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.org/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely
- Unsure where to start? Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.com/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely
- We're also [active in the Gitter chatroom](https://gitter.im/umbraco/Umbraco-CMS)
## Code of Conduct
@@ -31,7 +31,7 @@ Before creating bug reports, please check [this list](#before-submitting-a-bug-r
##### Before Submitting A Bug Report
* Most importantly, check **if you can reproduce the problem** in the [latest version of Umbraco](https://our.umbraco.org/download/). We might have already fixed your particular problem.
* Most importantly, check **if you can reproduce the problem** in the [latest version of Umbraco](https://our.umbraco.com/download/). We might have already fixed your particular problem.
* It also helps tremendously to check if the issue you're experiencing is present in **a clean install** of the Umbraco version you're currently using. Custom code can have side-effects that don't occur in a clean install.
* **Use the Google**. Whatever you're experiencing, Google it plus "Umbraco" - usually you can get some pretty good hints from the search results, including open issues and further troubleshooting hints.
* If you do find and existing issue has **and the issue is still open**, add a comment to the existing issue if you have additional information. If you have the same problem and no new info to add, just "star" the issue.
@@ -65,7 +65,7 @@ Most of the suggestions in the [reporting bugs](#reporting-bugs) section also co
Some additional hints that may be helpful:
* **Include screenshots and animated GIFs** which help you demonstrate the steps or point out the part of Umbraco which the suggestion is related to.
* **Explain why this enhancement would be useful to most Umbraco users** and isn't something that can or should be implemented as a [community package](https://our.umbraco.org/projects/).
* **Explain why this enhancement would be useful to most Umbraco users** and isn't something that can or should be implemented as a [community package](https://our.umbraco.com/projects/).
### Your First Code Contribution
@@ -80,7 +80,7 @@ The most successful pull requests usually look a like this:
* Fill in the required template
* Include screenshots and animated GIFs in your pull request whenever possible.
* Unit tests, while optional are awesome, thank you!
* New code is commented with documentation from which [the reference documentation](https://our.umbraco.org/documentation/Reference/) is generated
* New code is commented with documentation from which [the reference documentation](https://our.umbraco.com/documentation/Reference/) is generated
Again, these are guidelines, not strict requirements.
@@ -116,8 +116,8 @@ There's two big areas that you should know about:
To find the general areas of something you're looking to fix or improve, have a look at the following two parts of the API documentation.
* [The AngularJS based backoffice files](https://our.umbraco.org/apidocs/ui/#/api) (to be found in `src\Umbraco.Web.UI.Client\src`)
* [The rest](https://our.umbraco.org/apidocs/csharp/)
* [The AngularJS based backoffice files](https://our.umbraco.com/apidocs/ui/#/api) (to be found in `src\Umbraco.Web.UI.Client\src`)
* [The rest](https://our.umbraco.com/apidocs/csharp/)
### What branch should I target for my contributions?
@@ -129,7 +129,7 @@ We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-fl
The easiest way to get started is to run `build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `gulp dev` in `src\Umbraco.Web.UI.Client`. See [this page](BUILD.md) for more details.
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 ([the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 (version 15.3 or higher, [the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
![Gulp build in Visual Studio](img/gulpbuild.png)
@@ -156,4 +156,4 @@ git rebase upstream/dev-v7
In this command we're syncing with the `dev-v7` branch, but you can of course choose another one if needed.
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
+66
View File
@@ -0,0 +1,66 @@
---
name: 🐛 Bug Report
about: File a bug report, if you've discovered a problem in Umbraco.
---
A brief description of the issue goes here.
<!--
If you haven't yet done so, please read the "contributing guidelines"
thoroughly. Then, proceed by filling out the rest of the details in the issue
template below. The more details you can give us, the easier it will be for us
to determine the cause of a problem.
See: https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/.github/CONTRIBUTING.md
-->
Reproduction
------------
If you're filing a bug, please describe how to reproduce it. Include as much
relevant information as possible, such as:
### Bug summary
<!--
* Write a short summary of the bug
* Try to pinpoint it as much as possible
* Try to state the _actual problem_, and not just what you _think_ the
solution might be.
-->
### Specifics
<!--
* Mention the URL where this bug occurs, if applicable
* What version of Umbraco are you using (down to the very last digit!)
* What browser and version you are using
* Please mention if you've checked it in other browsers as well
* Please include *full error messages* and *screenshots* if possible
-->
### Steps to reproduce
<!--
* Clearly mention the steps to reproduce the bug
-->
### Expected result
<!--
* What did you _expect_ that would happen on your Umbraco site?
* Describe the intended/desired outcome after you did the steps mentioned.
-->
### Actual result
<!--
* What is the actual result of the above steps?
* Describe the behaviour of the bug
* Please, please include **error messages** and screenshots. They might mean
nothing to you, but they are _very_ helpful to us.
-->
@@ -0,0 +1,31 @@
---
name: 📮 Feature Request
about: Open a feature request, if you want to propose a new feature.
---
A brief description of your feature request goes here.
<!--
If you want to discuss the feature you're imagining, please make sure to keep
those discussions on the forum at https://our.umbraco.com/ (choose the
category "Contributing to Umbraco", Umbraco HQ follows all new topics there).
Once you've come to a conclusion in the discussion, feel free to propose the
new feature here.
-->
How can you help?
-------------------------------
<!--
The resources (read: available time and effort) of Umbraco's core team are
limited.
If we can not work on your suggestion, please don't take it personally. Most
likely, it's either:
- We think your idea is valid, but we can't find the time to work on it.
- Your idea might be better suited as a package, if it's not suitable for
the majority of users.
-->
@@ -0,0 +1,9 @@
---
name: ⁉️ Support Question
about: Having trouble with Umbraco? -> https://our.umbraco.com
---
This issue tracker is NOT meant for support questions. If you have a question,
please join us on the forum at https://our.umbraco.com.
Thanks!
@@ -0,0 +1,9 @@
---
name: 📖 Documentation Issue
about: See https://github.com/umbraco/UmbracoDocs/issues for documentation issues
---
The Umbraco documentation has its own dedicated repository. Please open your
documentation-related issue at https://github.com/umbraco/UmbracoDocs/issues
Thanks!
@@ -0,0 +1,31 @@
---
name: 🔐 Security Issue
about: Discovered a Security Issue in Umbraco?
---
⚠️ PLEASE DON'T DISCLOSE SECURITY-RELATED ISSUES PUBLICLY, SEE BELOW.
If you have found a security issue in Umbraco, please send the details to
security@umbraco.com and don't disclose it publicly until we can provide a fix for
it. If you wish, we'll credit you for finding verified issues, when we release
the patched version.
❗ Please read more about how to report security issues on https://umbraco.com/security
A note on "Self XSS"
--------------------
Umbraco is a CMS, that allows users to edit content on a website. As such,
all _authenticated users_ can:
- Edit content, and (depending on the field types) insert HTML and CSS in that
content, with a variety of allowed attributes.
- Depending on the user level: Edit template files, and insert C#, HTML, CSS and
javascript in so on.
- Upload files to the site, which will become publicly available.
We see these functionalities as _features_, and not as security issues. Please
report the mentioned items only if they can be performed by non-authorized
users, or other exploitable vulnerabilities.
Thanks!
+11
View File
@@ -0,0 +1,11 @@
### Prerequisites
- [ ] I have [created an issue](https://github.com/umbraco/Umbraco-CMS/issues) for the proposed changes in this PR, the link is:
- [ ] I have added steps to test this contribution in the description below
### Description
<!-- A description of the changes proposed in the pull-request -->
<!-- Make sure to link to the related issue number so we can easily find it in the issue tracker -->
<!-- Thanks for contributing to Umbraco CMS! -->
+3 -2
View File
@@ -44,6 +44,7 @@ Umbraco is contribution focused and community driven. If you want to contribute
## Found a bug?
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/docs/CONTRIBUTING.md).
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/.github/CONTRIBUTING.md).
To view existing issues, please visit [http://issues.umbraco.org](http://issues.umbraco.org).
You can comment and report issues on the [github issue tracker](https://github.com/umbraco/Umbraco-CMS/issues).
Since [September 2018](https://umbraco.com/blog/a-second-take-on-umbraco-issue-tracker-hello-github-issues/) the old issue tracker is in read only mode, but can still be found at [http://issues.umbraco.org](http://issues.umbraco.org).

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
# The MIT License (MIT) #
Copyright (c) 2013 Umbraco
Copyright (c) 2013-present Umbraco
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
@@ -8,7 +8,7 @@
<meta name="title" content="{{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}}">
<meta name="generator" content="docfx {{_docfxVersion}}">
{{#_description}}<meta name="description" content="{{_description}}">{{/_description}}
<link rel="icon" type="image/png" href="https://our.umbraco.org/assets/images/app-icons/favicon.png">
<link rel="icon" type="image/png" href="https://our.umbraco.com/assets/images/app-icons/favicon.png">
<link rel="stylesheet" href="{{_rel}}styles/docfx.vendor.css">
<link rel="stylesheet" href="{{_rel}}styles/docfx.css">
<link rel="stylesheet" href="{{_rel}}styles/main.css">
+1 -1
View File
@@ -63,7 +63,7 @@ a:focus {
}
.navbar-header .navbar-brand {
background: url(https://our.umbraco.org/assets/images/logo.svg) left center no-repeat;
background: url(https://our.umbraco.com/assets/images/logo.svg) left center no-repeat;
background-size: 40px auto;
width:50px;
}
@@ -94,14 +94,14 @@ function Get-UmbracoBuildEnv
}
# ensure we have node
$node = "$path\node-v6.9.1-win-x86"
$source = "http://nodejs.org/dist/v6.9.1/node-v6.9.1-win-x86.7z"
$node = "$path\node-v8.12.0-win-x86"
$source = "http://nodejs.org/dist/v8.12.0/node-v8.12.0-win-x86.7z "
if (-not (test-path $node))
{
Write-Host "Download Node..."
Invoke-WebRequest $source -OutFile "$path\node-v6.9.1-win-x86.7z"
&$sevenZip x "$path\node-v6.9.1-win-x86.7z" -o"$path" -aos > $nul
Remove-File "$path\node-v6.9.1-win-x86.7z"
Invoke-WebRequest $source -OutFile "$path\node-v8.12.0-win-x86.7z"
&$sevenZip x "$path\node-v8.12.0-win-x86.7z" -o"$path" -aos > $nul
Remove-File "$path\node-v8.12.0-win-x86.7z"
}
# note: why? node already brings everything we need!
+1 -1
View File
@@ -28,7 +28,7 @@
<dependency id="HtmlAgilityPack" version="[1.4.9.5, 2.0.0)" />
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
<dependency id="MySql.Data" version="[6.9.9, 7.0.0)" />
<dependency id="ClientDependency" version="[1.9.6, 2.0.0)" />
<dependency id="ClientDependency" version="[1.9.7, 2.0.0)" />
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
+1
View File
@@ -20,6 +20,7 @@
<dependency id="Umbraco.ModelsBuilder" version="[3.0.10, 4.0.0)" />
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
<dependency id="ImageProcessor.Web.Config" version="[2.3.1, 3.0.0)" />
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[2.0.0, 3.0.0)" />
</dependencies>
</metadata>
<files>
+2 -2
View File
@@ -21,6 +21,6 @@ The following items will now be automatically included when creating a deploy pa
system: umbraco, umbraco_client, config\splashes and global.asax.
Please read the release notes on our.umbraco.com:
http://our.umbraco.com/contribute/releases
https://our.umbraco.com/download/releases
- Umbraco
- Umbraco
-11
View File
@@ -1,11 +0,0 @@
### Prerequisites
- [ ] I have written a descriptive pull-request title
- [ ] I have linked this PR to an issue on the tracker at http://issues.umbraco.org
### Description
<!-- A description of the changes proposed in the pull-request -->
<!-- Thanks for contributing to Umbraco CMS! -->
+3 -3
View File
@@ -2,7 +2,7 @@
using System.Resources;
[assembly: AssemblyCompany("Umbraco")]
[assembly: AssemblyCopyright("Copyright © Umbraco 2017")]
[assembly: AssemblyCopyright("Copyright © Umbraco 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.12.0")]
[assembly: AssemblyInformationalVersion("7.12.0")]
[assembly: AssemblyFileVersion("7.13.0")]
[assembly: AssemblyInformationalVersion("7.13.0")]
+10 -10
View File
@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using Semver;
using System;
using System.Collections.Concurrent;
using System.Configuration;
using System.Threading;
using Semver;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;
@@ -13,7 +13,7 @@ using Umbraco.Core.Sync;
namespace Umbraco.Core
{
/// <summary>
/// <summary>
/// the Umbraco Application context
/// </summary>
/// <remarks>
@@ -270,7 +270,7 @@ namespace Umbraco.Core
return _umbracoApplicationUrl;
}
}
/// <summary>
/// Resets the url.
/// </summary>
@@ -280,10 +280,10 @@ namespace Umbraco.Core
}
// ReSharper disable once InconsistentNaming
internal string _umbracoApplicationUrl;
internal List<string> _umbracoApplicationDomains = new List<string>();
internal string _umbracoApplicationUrl;
internal ConcurrentDictionary<string, string> _umbracoApplicationDomains = new ConcurrentDictionary<string, string>();
internal string _umbracoApplicationDeploymentId;
private Lazy<bool> _configured;
@@ -399,7 +399,7 @@ namespace Umbraco.Core
}
return version;
}
}
private void AssertIsNotReady()
{
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
IEnumerable<string> ImageTagAllowedAttributes { get; }
IEnumerable<IImagingAutoFillUploadField> ImageAutoFillProperties { get; }
string ScriptFolderPath { get; }
IEnumerable<string> ScriptFileTypes { get; }
@@ -8,6 +8,8 @@
bool DisableAlternativeTemplates { get; }
bool ValidateAlternativeTemplates { get; }
bool DisableFindContentByIdPath { get; }
bool DisableRedirectUrlTracking { get; }
@@ -1,4 +1,5 @@
using System.Configuration;
using System;
using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
@@ -21,6 +22,13 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{
get { return (bool) base["disableAlternativeTemplates"]; }
}
[ConfigurationProperty("validateAlternativeTemplates", DefaultValue = "false")]
public bool ValidateAlternativeTemplates
{
get { return (bool)base["validateAlternativeTemplates"]; }
}
[ConfigurationProperty("disableFindContentByIdPath", DefaultValue = "false")]
public bool DisableFindContentByIdPath
{
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.12.0");
private static readonly Version Version = new Version("7.13.0");
/// <summary>
/// Gets the current version of Umbraco.
+6 -1
View File
@@ -110,6 +110,11 @@ namespace Umbraco.Core
/// Property alias for the Media's file extension.
/// </summary>
public const string Extension = "umbracoExtension";
/// <summary>
/// The default height/width of an image file if the size can't be determined from the metadata
/// </summary>
public const int DefaultSize = 200;
}
/// <summary>
@@ -354,4 +359,4 @@ namespace Umbraco.Core
}
}
}
}
}
+1
View File
@@ -61,6 +61,7 @@
public const int DefaultContentListViewDataTypeId = -95;
public const int DefaultMediaListViewDataTypeId = -96;
public const int DefaultMembersListViewDataTypeId = -97;
public const int DefaultLabelDataTypeId = -92;
public const string UmbracoConnectionName = "umbracoDbDSN";
public const string UmbracoMigrationName = "Umbraco";
+29 -28
View File
@@ -17,15 +17,15 @@ using Umbraco.Core.Models;
namespace Umbraco.Core.IO
{
/// <summary>
/// A custom file system provider for media
/// </summary>
[FileSystemProvider("media")]
public class MediaFileSystem : FileSystemWrapper
{
private readonly IContentSection _contentConfig;
/// <summary>
/// A custom file system provider for media
/// </summary>
[FileSystemProvider("media")]
public class MediaFileSystem : FileSystemWrapper
{
private readonly IContentSection _contentConfig;
private readonly UploadAutoFillProperties _uploadAutoFillProperties;
private readonly ILogger _logger;
private readonly ILogger _logger;
private readonly object _folderCounterLock = new object();
private long _folderCounter;
@@ -39,8 +39,8 @@ namespace Umbraco.Core.IO
};
public MediaFileSystem(IFileSystem wrapped)
: this(wrapped, UmbracoConfig.For.UmbracoSettings().Content, ApplicationContext.Current.ProfilingLogger.Logger)
{ }
: this(wrapped, UmbracoConfig.For.UmbracoSettings().Content, ApplicationContext.Current.ProfilingLogger.Logger)
{ }
public MediaFileSystem(IFileSystem wrapped, IContentSection contentConfig, ILogger logger)
: base(wrapped)
@@ -60,13 +60,13 @@ namespace Umbraco.Core.IO
[Obsolete("This low-level method should NOT exist.")]
public string GetRelativePath(int propertyId, string fileName)
{
{
var sep = _contentConfig.UploadAllowDirectories
? Path.DirectorySeparatorChar
: '-';
? Path.DirectorySeparatorChar
: '-';
return propertyId.ToString(CultureInfo.InvariantCulture) + sep + fileName;
}
return propertyId.ToString(CultureInfo.InvariantCulture) + sep + fileName;
}
[Obsolete("This low-level method should NOT exist.", false)]
public string GetRelativePath(string subfolder, string fileName)
@@ -264,7 +264,7 @@ namespace Umbraco.Core.IO
var filename = Path.GetFileName(sourcepath);
var filepath = GetMediaPath(filename, content.Key, propertyType.Key);
this.CopyFile(sourcepath, filepath);
return filepath;
}
@@ -321,7 +321,7 @@ namespace Umbraco.Core.IO
/// <param name="filepath"></param>
/// <param name="filestream"></param>
private void SetUploadFile(IContentBase content, Property property, string filepath, Stream filestream)
{
{
// will use filepath for extension, and filestream for length
_uploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream);
}
@@ -368,19 +368,20 @@ namespace Umbraco.Core.IO
return new Size(width, height);
}
}
//we have no choice but to try to read in via GDI
using (var image = Image.FromStream(stream))
{
var fileWidth = image.Width;
var fileHeight = image.Height;
return new Size(fileWidth, fileHeight);
}
}
catch (Exception)
{
//We will just swallow, just means we can't read exif data, we don't want to log an error either
}
//we have no choice but to try to read in via GDI
using (var image = Image.FromStream(stream))
{
var fileWidth = image.Width;
var fileHeight = image.Height;
return new Size(fileWidth, fileHeight);
return new Size(Constants.Conventions.Media.DefaultSize, Constants.Conventions.Media.DefaultSize);
}
}
@@ -430,8 +431,8 @@ namespace Umbraco.Core.IO
}
}
public void DeleteMediaFiles(IEnumerable<string> files)
{
public void DeleteMediaFiles(IEnumerable<string> files)
{
files = files.Distinct();
Parallel.ForEach(files, file =>
+1
View File
@@ -37,6 +37,7 @@ namespace Umbraco.Core.IO
}
}
[Obsolete("This file is no longer used and should not be accessed!")]
public static string MetablogConfig
{
get
+20 -16
View File
@@ -2,6 +2,7 @@
using System.Drawing;
using System.IO;
using System.Text;
using Umbraco.Core.Media.TypeDetector;
namespace Umbraco.Core.Media.Exif
{
@@ -118,22 +119,25 @@ namespace Umbraco.Core.Media.Exif
/// <returns>The <see cref="ImageFile"/> created from the file.</returns>
public static ImageFile FromStream(Stream stream, Encoding encoding)
{
stream.Seek (0, SeekOrigin.Begin);
byte[] header = new byte[8];
stream.Seek (0, SeekOrigin.Begin);
if (stream.Read (header, 0, header.Length) != header.Length)
throw new NotValidImageFileException ();
// JPEG
if (header[0] == 0xFF && header[1] == 0xD8)
return new JPEGFile (stream, encoding);
// TIFF
string tiffHeader = Encoding.ASCII.GetString (header, 0, 4);
if (tiffHeader == "MM\x00\x2a" || tiffHeader == "II\x2a\x00")
return new TIFFFile (stream, encoding);
throw new NotValidImageFileException ();
// JPEG
if(JPEGDetector.IsOfType(stream))
{
return new JPEGFile(stream, encoding);
}
// TIFF
if (TIFFDetector.IsOfType(stream))
{
return new TIFFFile(stream, encoding);
}
// SVG
if (SVGDetector.IsOfType(stream))
{
return new SVGFile(stream);
}
throw new NotValidImageFileException ();
}
#endregion
}
@@ -17,5 +17,9 @@
/// The file is a TIFF File.
/// </summary>
TIFF,
/// <summary>
/// The file is a SVG File.
/// </summary>
SVG,
}
}
+37
View File
@@ -0,0 +1,37 @@
using System;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Xml.Linq;
namespace Umbraco.Core.Media.Exif
{
internal class SVGFile : ImageFile
{
public SVGFile(Stream fileStream)
{
fileStream.Position = 0;
var document = XDocument.Load(fileStream); //if it throws an exception the ugly try catch in MediaFileSystem will catch it
var width = document.Root?.Attributes().Where(x => x.Name == "width").Select(x => x.Value).FirstOrDefault();
var height = document.Root?.Attributes().Where(x => x.Name == "height").Select(x => x.Value).FirstOrDefault();
Properties.Add(new ExifSInt(ExifTag.PixelYDimension,
height == null ? Constants.Conventions.Media.DefaultSize : int.Parse(height)));
Properties.Add(new ExifSInt(ExifTag.PixelXDimension,
width == null ? Constants.Conventions.Media.DefaultSize : int.Parse(width)));
Format = ImageFileFormat.SVG;
}
public override void Save(Stream stream)
{
}
public override Image ToImage()
{
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,14 @@
using System.IO;
namespace Umbraco.Core.Media.TypeDetector
{
public class JPEGDetector : RasterizedTypeDetector
{
public static bool IsOfType(Stream fileStream)
{
var header = GetFileHeader(fileStream);
return header[0] == 0xff && header[1] == 0xD8;
}
}
}
@@ -0,0 +1,16 @@
using System.IO;
namespace Umbraco.Core.Media.TypeDetector
{
public abstract class RasterizedTypeDetector
{
public static byte[] GetFileHeader(Stream fileStream)
{
fileStream.Seek(0, SeekOrigin.Begin);
byte[] header = new byte[8];
fileStream.Seek(0, SeekOrigin.Begin);
return header;
}
}
}
@@ -0,0 +1,24 @@
using System.IO;
using System.Xml.Linq;
namespace Umbraco.Core.Media.TypeDetector
{
public class SVGDetector
{
public static bool IsOfType(Stream fileStream)
{
var document = new XDocument();
try
{
document = XDocument.Load(fileStream);
}
catch (System.Exception ex)
{
return false;
}
return document.Root?.Name.LocalName == "svg";
}
}
}
@@ -0,0 +1,24 @@
using System.IO;
using System.Text;
namespace Umbraco.Core.Media.TypeDetector
{
public class TIFFDetector
{
public static bool IsOfType(Stream fileStream)
{
string tiffHeader = GetFileHeader(fileStream);
return tiffHeader == "MM\x00\x2a" || tiffHeader == "II\x2a\x00";
}
public static string GetFileHeader(Stream fileStream)
{
var header = RasterizedTypeDetector.GetFileHeader(fileStream);
string tiffHeader = Encoding.ASCII.GetString(header, 0, 4);
return tiffHeader;
}
}
}
+22
View File
@@ -102,6 +102,28 @@ namespace Umbraco.Core.Models
}
}
/// <summary>
/// Determines if AllowedTemplates contains templateId
/// </summary>
/// <param name="templateId">The template id to check</param>
/// <returns>True if AllowedTemplates contains the templateId else False</returns>
public bool IsAllowedTemplate(int templateId)
{
var allowedTemplates = AllowedTemplates ?? new ITemplate[0];
return allowedTemplates.Any(t => t.Id == templateId);
}
/// <summary>
/// Determines if AllowedTemplates contains templateId
/// </summary>
/// <param name="templateAlias">The template alias to check</param>
/// <returns>True if AllowedTemplates contains the templateAlias else False</returns>
public bool IsAllowedTemplate(string templateAlias)
{
var allowedTemplates = AllowedTemplates ?? new ITemplate[0];
return allowedTemplates.Any(t => t.Alias.Equals(templateAlias, StringComparison.InvariantCultureIgnoreCase));
}
/// <summary>
/// Sets the default template for the ContentType
/// </summary>
+14
View File
@@ -17,6 +17,20 @@ namespace Umbraco.Core.Models
/// </summary>
IEnumerable<ITemplate> AllowedTemplates { get; set; }
/// <summary>
/// Determines if AllowedTemplates contains templateId
/// </summary>
/// <param name="templateId">The template id to check</param>
/// <returns>True if AllowedTemplates contains the templateId else False</returns>
bool IsAllowedTemplate(int templateId);
/// <summary>
/// Determines if AllowedTemplates contains templateId
/// </summary>
/// <param name="templateAlias">The template alias to check</param>
/// <returns>True if AllowedTemplates contains the templateAlias else False</returns>
bool IsAllowedTemplate(string templateAlias);
/// <summary>
/// Sets the default template for the ContentType
/// </summary>
+6 -2
View File
@@ -259,7 +259,7 @@ namespace Umbraco.Core.Models.Membership
{
get
{
if (LastLoginDate == default(DateTime) && IsApproved == false && InvitedDate != null)
if (LastLoginDate == default && IsApproved == false && InvitedDate != null)
return UserState.Invited;
if (IsLockedOut)
@@ -267,7 +267,11 @@ namespace Umbraco.Core.Models.Membership
if (IsApproved == false)
return UserState.Disabled;
return UserState.Active;
// User is not disabled or locked and has never logged in before
if (LastLoginDate == default && IsApproved && IsLockedOut == false)
return UserState.Inactive;
return UserState.Active;
}
}
@@ -9,6 +9,7 @@
Active = 0,
Disabled = 1,
LockedOut = 2,
Invited = 3
Invited = 3,
Inactive = 4
}
}
}
+2 -2
View File
@@ -83,7 +83,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// Returns the instance of the tag support, by default tags are not enabled
/// </summary>
internal PropertyTags TagSupport
public PropertyTags TagSupport
{
get { return _tagSupport; }
}
@@ -242,4 +242,4 @@ namespace Umbraco.Core.Models
return clone;
}
}
}
}
@@ -1,9 +1,9 @@
namespace Umbraco.Core.Models
{
internal enum PropertyTagBehavior
public enum PropertyTagBehavior
{
Replace,
Remove,
Merge
}
}
}
+2 -2
View File
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Models
/// <summary>
/// A property extension class that allows us to enable tags for any given property
/// </summary>
internal class PropertyTags
public class PropertyTags
{
public PropertyTags()
{
@@ -33,4 +33,4 @@ namespace Umbraco.Core.Models
public IEnumerable<Tuple<string, string>> Tags { get; set; }
}
}
}
@@ -6,17 +6,17 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
{
public ConstraintDefinition(ConstraintType type)
{
constraintType = type;
_constraintType = type;
}
private ConstraintType constraintType;
public bool IsPrimaryKeyConstraint { get { return ConstraintType.PrimaryKey == constraintType; } }
public bool IsUniqueConstraint { get { return ConstraintType.Unique == constraintType; } }
public bool IsNonUniqueConstraint { get { return ConstraintType.NonUnique == constraintType; } }
private readonly ConstraintType _constraintType;
public bool IsPrimaryKeyConstraint => ConstraintType.PrimaryKey == _constraintType;
public bool IsUniqueConstraint => ConstraintType.Unique == _constraintType;
public bool IsNonUniqueConstraint => ConstraintType.NonUnique == _constraintType;
public string SchemaName { get; set; }
public string ConstraintName { get; set; }
public string TableName { get; set; }
public ICollection<string> Columns = new HashSet<string>();
}
}
}
@@ -1,3 +1,5 @@
using System;
namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
{
/// <summary>
@@ -5,9 +7,17 @@ namespace Umbraco.Core.Persistence.DatabaseModelDefinitions
/// </summary>
internal class DbIndexDefinition
{
public virtual string IndexName { get; set; }
public virtual string TableName { get; set; }
public virtual string ColumnName { get; set; }
public virtual bool IsUnique { get; set; }
public DbIndexDefinition(Tuple<string, string, string, bool> data)
{
TableName = data.Item1;
IndexName = data.Item2;
ColumnName = data.Item3;
IsUnique = data.Item4;
}
public string IndexName { get; }
public string TableName { get; }
public string ColumnName { get; }
public bool IsUnique { get; }
}
}
}
@@ -1,6 +1,5 @@
using System;
using System.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
@@ -11,6 +10,9 @@ using Umbraco.Core.Services;
namespace Umbraco.Core.Persistence
{
/// <summary>
/// Helper class for working with databases and schemas.
/// </summary>
public class DatabaseSchemaHelper
{
private readonly Database _db;
@@ -18,6 +20,22 @@ namespace Umbraco.Core.Persistence
private readonly ISqlSyntaxProvider _syntaxProvider;
private readonly BaseDataCreation _baseDataCreation;
/// <summary>
/// Intializes a new helper instance.
/// </summary>
/// <param name="db">The database to be used.</param>
/// <param name="logger">The logger.</param>
/// <param name="syntaxProvider">The syntax provider.</param>
/// <example>
/// A new instance could be initialized like:
/// <code>
/// var schemaHelper = new DatabaseSchemaHelper(
/// ApplicationContext.Current.DatabaseContext.Database,
/// ApplicationContext.Current.ProfilingLogger.Logger,
/// ApplicationContext.Current.DatabaseContext.SqlSyntax
/// );
/// </code>
/// </example>
public DatabaseSchemaHelper(Database db, ILogger logger, ISqlSyntaxProvider syntaxProvider)
{
_db = db;
@@ -26,11 +44,41 @@ namespace Umbraco.Core.Persistence
_baseDataCreation = new BaseDataCreation(db, logger);
}
/// <summary>
/// Returns whether a table with the specified <paramref name="tableName"/> exists in the database.
/// </summary>
/// <param name="tableName">The name of the table.</param>
/// <returns><c>true</c> if the table exists; otherwise <c>false</c>.</returns>
/// <example>
/// <code>
/// if (schemaHelper.TableExist("MyTable"))
/// {
/// // do something when the table exists
/// }
/// </code>
/// </example>
public bool TableExist(string tableName)
{
return _syntaxProvider.DoesTableExist(_db, tableName);
}
/// <summary>
/// Returns whether the table for the specified <typeparamref name="T"/> exists in the database.
///
/// If <typeparamref name="T"/> has been decorated with an <see cref="TableNameAttribute"/>, the name from that
/// attribute will be used for the table name. If the attribute is not present, the name
/// <typeparamref name="T"/> will be used instead.
/// </summary>
/// <typeparam name="T">The type representing the DTO/table.</typeparam>
/// <returns><c>true</c> if the table exists; otherwise <c>false</c>.</returns>
/// <example>
/// <code>
/// if (schemaHelper.TableExist&lt;MyDto&gt;)
/// {
/// // do something when the table exists
/// }
/// </code>
/// </example>
public bool TableExist<T>()
{
var poco = Database.PocoData.ForType(typeof(T));
@@ -90,6 +138,17 @@ namespace Umbraco.Core.Persistence
_logger.Info<Database>("Finalized database schema creation");
}
/// Creates a new table in the database based on the type of <typeparamref name="T"/>.
///
/// If <typeparamref name="T"/> has been decorated with an <see cref="TableNameAttribute"/>, the name from that
/// attribute will be used for the table name. If the attribute is not present, the name
/// <typeparamref name="T"/> will be used instead.
///
/// If a table with the same name already exists, the <paramref name="overwrite"/> parameter will determine
/// whether the table is overwritten. If <c>true</c>, the table will be overwritten, whereas this method will
/// not do anything if the parameter is <c>false</c>.
/// <typeparam name="T">The type representing the DTO/table.</typeparam>
/// <param name="overwrite">Whether the table should be overwritten if it already exists.</param>
public void CreateTable<T>(bool overwrite)
where T : new()
{
@@ -97,6 +156,16 @@ namespace Umbraco.Core.Persistence
CreateTable(overwrite, tableType);
}
/// <summary>
/// Creates a new table in the database based on the type of <typeparamref name="T"/>.
///
/// If <typeparamref name="T"/> has been decorated with an <see cref="TableNameAttribute"/>, the name from that
/// attribute will be used for the table name. If the attribute is not present, the name
/// <typeparamref name="T"/> will be used instead.
///
/// If a table with the same name already exists, this method will not do anything.
/// </summary>
/// <typeparam name="T">The type representing the DTO/table.</typeparam>
public void CreateTable<T>()
where T : new()
{
@@ -104,6 +173,19 @@ namespace Umbraco.Core.Persistence
CreateTable(false, tableType);
}
/// <summary>
/// Creates a new table in the database for the specified <paramref name="modelType"/>.
///
/// If <paramref name="modelType"/> has been decorated with an <see cref="TableNameAttribute"/>, the name from
/// that attribute will be used for the table name. If the attribute is not present, the name
/// <paramref name="modelType"/> will be used instead.
///
/// If a table with the same name already exists, the <paramref name="overwrite"/> parameter will determine
/// whether the table is overwritten. If <c>true</c>, the table will be overwritten, whereas this method will
/// not do anything if the parameter is <c>false</c>.
/// </summary>
/// <param name="overwrite">Whether the table should be overwritten if it already exists.</param>
/// <param name="modelType">The the representing the table.</param>
public void CreateTable(bool overwrite, Type modelType)
{
var tableDefinition = DefinitionFactory.GetTableDefinition(_syntaxProvider, modelType);
@@ -117,6 +199,8 @@ namespace Umbraco.Core.Persistence
var tableExist = TableExist(tableName);
if (overwrite && tableExist)
{
_logger.Info<Database>(string.Format("Table '{0}' already exists, but will be recreated", tableName));
DropTable(tableName);
tableExist = false;
}
@@ -169,15 +253,37 @@ namespace Umbraco.Core.Persistence
_logger.Info<Database>(string.Format("Create Foreign Key sql {0}:\n {1}", createdFk, sql));
}
transaction.Complete();
if (overwrite)
{
_logger.Info<Database>(string.Format("Table '{0}' was recreated", tableName));
}
else
{
_logger.Info<Database>(string.Format("New table '{0}' was created", tableName));
}
}
}
_logger.Info<Database>(string.Format("New table '{0}' was created", tableName));
else
{
// The table exists and was not recreated/overwritten.
_logger.Info<Database>(string.Format("Table '{0}' already exists - no changes were made", tableName));
}
}
/// <summary>
/// Drops the table for the specified <typeparamref name="T"/>.
///
/// If <typeparamref name="T"/> has been decorated with an <see cref="TableNameAttribute"/>, the name from that
/// attribute will be used for the table name. If the attribute is not present, the name
/// <typeparamref name="T"/> will be used instead.
/// </summary>
/// <typeparam name="T">The type representing the DTO/table.</typeparam>
/// <example>
/// <code>
/// schemaHelper.DropTable&lt;MyDto&gt;);
/// </code>
/// </example>
public void DropTable<T>()
where T : new()
{
@@ -193,6 +299,15 @@ namespace Umbraco.Core.Persistence
DropTable(tableName);
}
/// <summary>
/// Drops the table with the specified <paramref name="tableName"/>.
/// </summary>
/// <param name="tableName">The name of the table.</param>
/// <example>
/// <code>
/// schemaHelper.DropTable("MyTable");
/// </code>
/// </example>
public void DropTable(string tableName)
{
var sql = new Sql(string.Format(
@@ -30,7 +30,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
if(tableName.Equals("umbracoNode"))
{
CreateUmbracNodeData();
CreateUmbracoNodeData();
}
if (tableName.Equals("umbracoLock"))
@@ -111,7 +111,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
_logger.Info<BaseDataCreation>(string.Format("Done creating data in table {0}", tableName));
}
private void CreateUmbracNodeData()
private void CreateUmbracoNodeData()
{
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -1, Trashed = false, ParentId = -1, UserId = 0, Level = 0, Path = "-1", SortOrder = 0, UniqueId = new Guid("916724a5-173d-4619-b97e-b9de133dd6f5"), Text = "SYSTEM DATA: umbraco master root", NodeObjectType = new Guid(Constants.ObjectTypes.SystemRoot), CreateDate = DateTime.Now });
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = -20, Trashed = false, ParentId = -1, UserId = 0, Level = 0, Path = "-1,-20", SortOrder = 0, UniqueId = new Guid("0F582A79-1E41-4CF0-BFA0-76340651891A"), Text = "Recycle Bin", NodeObjectType = new Guid(Constants.ObjectTypes.ContentRecycleBin), CreateDate = DateTime.Now });
@@ -159,13 +159,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
//get the db index defs
result.DbIndexDefinitions = _sqlSyntaxProvider.GetDefinedIndexes(_database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
foreach (var item in OrderedTables.OrderBy(x => x.Key))
{
@@ -184,6 +178,14 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
return result;
}
/// <summary>
/// This validates the Primary/Foreign keys in the database
/// </summary>
/// <param name="result"></param>
/// <remarks>
/// This does not validate any database constraints that are not PKs or FKs because Umbraco does not create a database with non PK/FK contraints.
/// Any unique "constraints" in the database are done with unique indexes.
/// </remarks>
private void ValidateDbConstraints(DatabaseSchemaResult result)
{
//MySql doesn't conform to the "normal" naming of constraints, so there is currently no point in doing these checks.
@@ -196,8 +198,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
var constraintsInDatabase = _sqlSyntaxProvider.GetConstraintsPerColumn(_database).DistinctBy(x => x.Item3).ToList();
var foreignKeysInDatabase = constraintsInDatabase.Where(x => x.Item3.InvariantStartsWith("FK_")).Select(x => x.Item3).ToList();
var primaryKeysInDatabase = constraintsInDatabase.Where(x => x.Item3.InvariantStartsWith("PK_")).Select(x => x.Item3).ToList();
var indexesInDatabase = constraintsInDatabase.Where(x => x.Item3.InvariantStartsWith("IX_")).Select(x => x.Item3).ToList();
var indexesInSchema = result.TableDefinitions.SelectMany(x => x.Indexes.Select(y => y.Name)).ToList();
var unknownConstraintsInDatabase =
constraintsInDatabase.Where(
x =>
@@ -212,7 +213,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
// In theory you could have: FK_ or fk_ ...or really any standard that your development department (or developer) chooses to use.
foreach (var unknown in unknownConstraintsInDatabase)
{
if (foreignKeysInSchema.InvariantContains(unknown) || primaryKeysInSchema.InvariantContains(unknown) || indexesInSchema.InvariantContains(unknown))
if (foreignKeysInSchema.InvariantContains(unknown) || primaryKeysInSchema.InvariantContains(unknown))
{
result.ValidConstraints.Add(unknown);
}
@@ -254,23 +255,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
result.Errors.Add(new Tuple<string, string>("Constraint", primaryKey));
}
//Constaints:
//NOTE: SD: The colIndex checks above should really take care of this but I need to keep this here because it was here before
// and some schema validation checks might rely on this data remaining here!
//Add valid and invalid index differences to the result object
var validIndexDifferences = indexesInDatabase.Intersect(indexesInSchema, StringComparer.InvariantCultureIgnoreCase);
foreach (var index in validIndexDifferences)
{
result.ValidConstraints.Add(index);
}
var invalidIndexDifferences =
indexesInDatabase.Except(indexesInSchema, StringComparer.InvariantCultureIgnoreCase)
.Union(indexesInSchema.Except(indexesInDatabase, StringComparer.InvariantCultureIgnoreCase));
foreach (var index in invalidIndexDifferences)
{
result.Errors.Add(new Tuple<string, string>("Constraint", index));
}
}
private void ValidateDbColumns(DatabaseSchemaResult result)
@@ -28,13 +28,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
public override void Up()
{
var dbIndexes = _skipIndexCheck ? new DbIndexDefinition[]{} : SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMacroProperty_Alias")) == false)
@@ -54,4 +48,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
Delete.Index("IX_cmsMacroProperty_Alias").OnTable("cmsMacroProperty");
}
}
}
}
@@ -30,13 +30,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
public override void Up()
{
var dbIndexes = _forTesting ? new DbIndexDefinition[] { } : SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMacro_Alias")) == false)
@@ -75,4 +69,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
Delete.Index("IX_cmsMacro_Alias").OnTable("cmsMacro");
}
}
}
}
@@ -18,13 +18,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
public override void Up()
{
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
//add a foreign key to the parent id column too!
@@ -54,4 +48,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
throw new DataLossException("Cannot downgrade from a version 7 database to a prior version, the database schema has already been modified");
}
}
}
}
@@ -26,13 +26,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
// it is absolutely required to exist in order to have it as a foreign key reference, so we'll need to check it's existence
// this came to light from this issue: http://issues.umbraco.org/issue/U4-4133
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsContent")) == false)
{
Create.Index("IX_cmsContent").OnTable("cmsContent").OnColumn("nodeId").Ascending().WithOptions().Unique();
@@ -95,4 +89,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
//don't do anything, these keys should have always existed!
}
}
}
}
@@ -15,7 +15,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenEightZe
{
Execute.Code(database =>
{
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database);
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(database);
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsPropertyTypeAlias")) == false)
@@ -62,13 +62,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
}
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsDictionary_id")) == false)
@@ -104,4 +98,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
throw new NotImplementedException();
}
}
}
}
@@ -120,13 +120,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
//in some databases there's an index (IX_Master) on the master column which needs to be dropped first
var foundIndex = dbIndexes.FirstOrDefault(x => x.TableName.InvariantEquals("cmsTemplate") && x.ColumnName.InvariantEquals("master"));
@@ -167,4 +161,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
return path;
}
}
}
}
@@ -15,13 +15,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
public override void Up()
{
var indexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
// drop the index if it exists
if (indexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoNodeUniqueID")))
@@ -38,4 +32,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenThreeZe
public override void Down()
{ }
}
}
}
@@ -1,7 +1,4 @@
using System;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwelveZero
@@ -16,20 +13,22 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwelveZ
public override void Up()
{
var exists = Context.Database.FirstOrDefault<RelationTypeDto>("WHERE alias=@alias", new { alias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias });
if (exists == null)
var relationTypeCount = Context.Database.ExecuteScalar<int>("SELECT COUNT(*) FROM umbracoRelationType WHERE alias=@alias",
new { alias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias });
if (relationTypeCount > 0)
return;
var uniqueId = (Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias + "____" + Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName).ToGuid();
Insert.IntoTable("umbracoRelationType").Row(new
{
var uniqueId = (Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias + "____" + Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName).ToGuid();
Insert.IntoTable("umbracoRelationType").Row(new
{
typeUniqueId = uniqueId,
alias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias,
name = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName,
childObjectType = Constants.ObjectTypes.MediaType,
parentObjectType = Constants.ObjectTypes.MediaType,
dual = false
});
}
typeUniqueId = uniqueId,
alias = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteAlias,
name = Constants.Conventions.RelationTypes.RelateParentMediaFolderOnDeleteName,
childObjectType = Constants.ObjectTypes.MediaType,
parentObjectType = Constants.ObjectTypes.MediaType,
dual = false
});
}
public override void Down()
@@ -15,21 +15,35 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwelveZ
public override void Up()
{
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
//Ensure the index exists before dropping it
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoLanguage_languageISOCode")))
Execute.Code(database =>
{
Delete.Index("IX_umbracoLanguage_languageISOCode").OnTable("umbracoLanguage");
}
var localContext = new LocalMigrationContext(Context.CurrentDatabaseProvider, database, SqlSyntax, Logger);
// Some people seem to have a constraint in their DB instead of an index, we'd need to drop that one
// See: https://our.umbraco.com/forum/using-umbraco-and-getting-started/93282-upgrade-from-711-to-712-fails
var constraints = SqlSyntax.GetConstraintsPerTable(database).Distinct().ToArray();
if (constraints.Any(x => x.Item2.InvariantEquals("IX_umbracoLanguage_languageISOCode")))
{
localContext.Delete.UniqueConstraint("IX_umbracoLanguage_languageISOCode").FromTable("umbracoLanguage");
return localContext.GetSql();
}
return null;
});
Execute.Code(database =>
{
var localContext = new LocalMigrationContext(Context.CurrentDatabaseProvider, database, SqlSyntax, Logger);
//Now check for indexes of that name and drop that if it exists
var dbIndexes = SqlSyntax.GetDefinedIndexes(database)
.Select(x => new DbIndexDefinition(x)).ToArray();
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoLanguage_languageISOCode")))
{
localContext.Delete.Index("IX_umbracoLanguage_languageISOCode").OnTable("umbracoLanguage");
return localContext.GetSql();
}
return null;
});
Alter.Table("umbracoLanguage")
.AlterColumn("languageISOCode")
.AsString(14)
@@ -38,6 +52,8 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwelveZ
Create.Index("IX_umbracoLanguage_languageISOCode")
.OnTable("umbracoLanguage")
.OnColumn("languageISOCode")
.Ascending()
.WithOptions()
.Unique();
}
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwelveZ
// We need to get all datatypes with an alias of "umbraco.tags" so we can loop over them and set the missing values if needed
var datatypes = Context.Database.Fetch<DataTypeDto>("SELECT * FROM cmsDataType");
var tagsDataTypes = datatypes.Where(x => string.Equals(x.PropertyEditorAlias, Constants.PropertyEditors.TagsAlias, StringComparison.InvariantCultureIgnoreCase));
var dataTypePreValues = Context.Database.Fetch<DataTypePreValueDto>("SELECT * FROM cmsDataTypePrevalues");
var dataTypePreValues = Context.Database.Fetch<DataTypePreValueDto>("SELECT * FROM cmsDataTypePreValues");
foreach (var datatype in tagsDataTypes)
{
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwelveZ
// if the "storageType" has not been set we do so by adding a new row in the table for the nodid and set it
if (result == null)
{
Insert.IntoTable("CmsDataTypePrevalues").Row(new
Insert.IntoTable("cmsDataTypePreValues").Row(new
{
datatypeNodeId = datatype.DataTypeId,
value = "Csv",
@@ -48,14 +48,8 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero
//Some very old schemas don't have an index on the cmsContentType.nodeId column, I'm not actually sure when it was added but
// it is absolutely required to exist in order to add other foreign keys and much better for perf, so we'll need to check it's existence
// this came to light from this issue: http://issues.umbraco.org/issue/U4-4133
var dbIndexes = SqlSyntaxContext.SqlSyntaxProvider.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition(x)).ToArray();
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsContentType")) == false)
{
Create.Index("IX_cmsContentType").OnTable("cmsContentType").OnColumn("nodeId").Ascending().WithOptions().Unique();
@@ -82,4 +76,4 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenTwoZero
throw new DataLossException("Cannot downgrade from a version 7.2 database to a prior version, the database schema has already been modified");
}
}
}
}
@@ -20,13 +20,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSixTwoZero
{
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
//do not create any indexes if they already exist in the database
@@ -118,4 +112,4 @@ DROP TABLE ""umbracoUserLogins_temp""");
}
}
}
}
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
@@ -47,43 +48,33 @@ namespace Umbraco.Core.Persistence.Repositories
var sql = GetBaseQuery(false);
if (query == null) query = new Query<IAuditItem>();
var queryHasWhereClause = query.GetWhereClauses().Any();
var translatorIds = new SqlTranslator<IAuditItem>(sql, query);
var translatedQuery = translatorIds.Translate();
var customFilterWheres = customFilter != null ? customFilter.GetWhereClauses().ToArray() : null;
var customFilterWheres = customFilter?.GetWhereClauses().ToArray();
var hasCustomFilter = customFilterWheres != null && customFilterWheres.Length > 0;
if (hasCustomFilter)
{
var filterSql = new Sql();
var first = true;
foreach (var filterClaus in customFilterWheres)
{
if (first == false)
{
filterSql.Append(" AND ");
}
filterSql.Append(string.Format("({0})", filterClaus.Item1), filterClaus.Item2);
first = false;
foreach (var filterClause in customFilterWheres)
{
filterSql.Append($"AND ({filterClause.Item1})", filterClause.Item2);
}
translatedQuery = GetFilteredSqlForPagedResults(translatedQuery, filterSql);
translatedQuery = GetFilteredSqlForPagedResults(translatedQuery, filterSql, queryHasWhereClause);
}
if (auditTypeFilter.Length > 0)
{
var filterSql = new Sql();
var first = true;
foreach (var filterClaus in auditTypeFilter)
{
if (first == false || hasCustomFilter)
{
filterSql.Append(" AND ");
}
filterSql.Append("(logHeader = @logHeader)", new {logHeader = filterClaus.ToString() });
first = false;
foreach (var filterClause in auditTypeFilter)
{
filterSql.Append("AND (logHeader = @logHeader)", new { logHeader = filterClause.ToString() });
}
translatedQuery = GetFilteredSqlForPagedResults(translatedQuery, filterSql);
translatedQuery = GetFilteredSqlForPagedResults(translatedQuery, filterSql, queryHasWhereClause || hasCustomFilter);
}
if (orderDirection == Direction.Descending)
@@ -99,7 +90,7 @@ namespace Umbraco.Core.Persistence.Repositories
dto => new AuditItem(dto.Id, dto.Comment, Enum<AuditType>.ParseOrNull(dto.Header) ?? AuditType.Custom, dto.UserId)).ToArray();
//Mapping the DateStamp
for (int i = 0; i < pages.Length; i++)
for (var i = 0; i < pages.Length; i++)
{
pages[i].CreateDate = pagedResult.Items[i].Datestamp;
}
@@ -169,14 +160,17 @@ namespace Umbraco.Core.Persistence.Repositories
}
#endregion
private Sql GetFilteredSqlForPagedResults(Sql sql, Sql filterSql)
private Sql GetFilteredSqlForPagedResults(Sql sql, Sql filterSql, bool hasWhereClause)
{
Sql filteredSql;
// Apply filter
if (filterSql != null)
{
var sqlFilter = " WHERE " + filterSql.SQL.TrimStart("AND ");
//ensure we don't append a WHERE if there is already one
var sqlFilter = hasWhereClause
? filterSql.SQL
: " WHERE " + filterSql.SQL.TrimStart("AND ");
//NOTE: this is certainly strange - NPoco handles this much better but we need to re-create the sql
// instance a couple of times to get the parameter order correct, for some reason the first
@@ -134,7 +134,7 @@ namespace Umbraco.Core.Persistence.Repositories
.InnerJoin<ContentDto>(SqlSyntax)
.On<ContentVersionDto, ContentDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
.InnerJoin<NodeDto>(SqlSyntax)
.On<ContentDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
.On<ContentDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
.InnerJoin<ContentTypeDto>()
.On<ContentTypeDto, ContentDto>(left => left.NodeId, right => right.ContentTypeId);
//TODO: IF we want to enable querying on content type information this will need to be joined
@@ -836,19 +836,19 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
}
public int CountPublished(string contentTypeAlias = null)
{
if (contentTypeAlias.IsNullOrWhiteSpace())
{
{
if (contentTypeAlias.IsNullOrWhiteSpace())
{
var sql = GetBaseQuery(true).Where<NodeDto>(x => x.Trashed == false)
.Where<DocumentDto>(x => x.Published == true);
return Database.ExecuteScalar<int>(sql);
.Where<DocumentDto>(x => x.Published == true);
return Database.ExecuteScalar<int>(sql);
}
else
{
else
{
var sql = GetBaseQuery(true).Where<NodeDto>(x => x.Trashed == false)
.Where<DocumentDto>(x => x.Published == true)
.Where<ContentTypeDto>(x => x.Alias == contentTypeAlias);
return Database.ExecuteScalar<int>(sql);
.Where<DocumentDto>(x => x.Published == true)
.Where<ContentTypeDto>(x => x.Alias == contentTypeAlias);
return Database.ExecuteScalar<int>(sql);
}
}
@@ -1220,7 +1220,14 @@ ORDER BY cmsContentVersion.id DESC
if (def.DocumentDto.TemplateId.HasValue)
templates.TryGetValue(def.DocumentDto.TemplateId.Value, out template); // else null
cc.Template = template;
cc.Properties = propertyData[cc.Version];
if (propertyData.ContainsKey(cc.Version))
{
cc.Properties = propertyData[cc.Version];
}
else
{
throw new InvalidOperationException($"No property data found for version: '{cc.Version}'.");
}
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
@@ -1307,4 +1314,4 @@ ORDER BY cmsContentVersion.id DESC
}
}
}
}
}
@@ -284,7 +284,7 @@ namespace Umbraco.Core.Persistence.Repositories
var nonAssignedRoles = roleNames.Except(assignedRoles, StringComparer.CurrentCultureIgnoreCase);
foreach (var toAssign in nonAssignedRoles)
{
var groupId = rolesForNames.First(x => x.Text == toAssign).NodeId;
var groupId = rolesForNames.First(x => x.Text.InvariantEquals(toAssign)).NodeId;
Database.Insert(new Member2MemberGroupDto { Member = mId, MemberGroup = groupId });
}
}
@@ -4,6 +4,7 @@ using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.Security;
using Newtonsoft.Json;
using Umbraco.Core.Configuration;
@@ -186,6 +187,8 @@ UNION
SELECT '4CountOfLockedOut' AS colName, COUNT(id) AS num FROM umbracoUser WHERE userNoConsole = 1
UNION
SELECT '5CountOfInvited' AS colName, COUNT(id) AS num FROM umbracoUser WHERE lastLoginDate IS NULL AND userDisabled = 1 AND invitedDate IS NOT NULL
UNION
SELECT '6CountOfDisabled' AS colName, COUNT(id) AS num FROM umbracoUser WHERE userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NULL
ORDER BY colName";
var result = Database.Fetch<dynamic>(sql);
@@ -196,7 +199,8 @@ ORDER BY colName";
{UserState.Active, (int)result[1].num},
{UserState.Disabled, (int)result[2].num},
{UserState.LockedOut, (int)result[3].num},
{UserState.Invited, (int)result[4].num}
{UserState.Invited, (int)result[4].num},
{UserState.Inactive, (int) result[5].num}
};
}
@@ -707,10 +711,10 @@ ORDER BY colName";
private IEnumerable<IUser> GetPagedResultsByQuery(IQuery<IUser> query, long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection,
string[] includeUserGroups = null,
string[] excludeUserGroups = null,
UserState[] userState = null,
private IEnumerable<IUser> GetPagedResultsByQuery(IQuery<IUser> query, long pageIndex, int pageSize, out long totalRecords, string orderBy, Direction orderDirection,
string[] includeUserGroups = null,
string[] excludeUserGroups = null,
UserState[] userState = null,
IQuery<IUser> customFilter = null)
{
if (string.IsNullOrWhiteSpace(orderBy)) throw new ArgumentException("Value cannot be null or whitespace.", "orderBy");
@@ -718,23 +722,23 @@ ORDER BY colName";
Sql filterSql = null;
var customFilterWheres = customFilter != null ? customFilter.GetWhereClauses().ToArray() : null;
var hasCustomFilter = customFilterWheres != null && customFilterWheres.Length > 0;
var hasCustomFilter = customFilterWheres != null && customFilterWheres.Length > 0;
if (hasCustomFilter
|| (includeUserGroups != null && includeUserGroups.Length > 0) || (excludeUserGroups != null && excludeUserGroups.Length > 0)
|| (userState != null && userState.Length > 0 && userState.Contains(UserState.All) == false))
filterSql = new Sql();
|| (includeUserGroups != null && includeUserGroups.Length > 0) || (excludeUserGroups != null && excludeUserGroups.Length > 0)
|| (userState != null && userState.Length > 0 && userState.Contains(UserState.All) == false))
filterSql = new Sql();
if (hasCustomFilter)
{
foreach (var filterClause in customFilterWheres)
{
filterSql.Append(string.Format("AND ({0})", filterClause.Item1), filterClause.Item2);
filterSql.Append($"AND ({filterClause.Item1})", filterClause.Item2);
}
}
}
if (includeUserGroups != null && includeUserGroups.Length > 0)
{
var subQuery = @"AND (umbracoUser.id IN (SELECT DISTINCT umbracoUser.id
const string subQuery = @"AND (umbracoUser.id IN (SELECT DISTINCT umbracoUser.id
FROM umbracoUser
INNER JOIN umbracoUser2UserGroup ON umbracoUser2UserGroup.userId = umbracoUser.id
INNER JOIN umbracoUserGroup ON umbracoUserGroup.id = umbracoUser2UserGroup.userGroupId
@@ -744,27 +748,33 @@ ORDER BY colName";
if (excludeUserGroups != null && excludeUserGroups.Length > 0)
{
var subQuery = @"AND (umbracoUser.id NOT IN (SELECT DISTINCT umbracoUser.id
const string subQuery = @"AND (umbracoUser.id NOT IN (SELECT DISTINCT umbracoUser.id
FROM umbracoUser
INNER JOIN umbracoUser2UserGroup ON umbracoUser2UserGroup.userId = umbracoUser.id
INNER JOIN umbracoUserGroup ON umbracoUserGroup.id = umbracoUser2UserGroup.userGroupId
WHERE umbracoUserGroup.userGroupAlias IN (@userGroups)))";
filterSql.Append(subQuery, new { userGroups = excludeUserGroups });
}
}
if (userState != null && userState.Length > 0)
{
{
//the "ALL" state doesn't require any filtering so we ignore that, if it exists in the list we don't do any filtering
if (userState.Contains(UserState.All) == false)
{
var sb = new StringBuilder("(");
var appended = false;
var appended = false;
if (userState.Contains(UserState.Active))
{
sb.Append("(userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NOT NULL)");
appended = true;
}
if (userState.Contains(UserState.Inactive))
{
if (appended) sb.Append(" OR ");
sb.Append("(userDisabled = 0 AND userNoConsole = 0 AND lastLoginDate IS NULL)");
appended = true;
}
if (userState.Contains(UserState.Disabled))
{
if (appended) sb.Append(" OR ");
@@ -788,67 +798,81 @@ ORDER BY colName";
filterSql.Append("AND " + sb);
}
}
// Get base query for returning IDs
var sqlBaseIds = GetBaseQuery("id");
}
// Get base query for returning IDs
var sqlBaseIds = GetBaseQuery("id");
if (query == null) query = new Query<IUser>();
var queryHasWhereClause = query.GetWhereClauses().Any();
var translatorIds = new SqlTranslator<IUser>(sqlBaseIds, query);
var sqlQueryIds = translatorIds.Translate();
//get sorted and filtered sql
var sqlQueryIds = translatorIds.Translate();
var sqlBaseFull = GetBaseQuery("umbracoUser.*, umbracoUserGroup.*, umbracoUserGroup2App.*, umbracoUserStartNode.*");
var translatorFull = new SqlTranslator<IUser>(sqlBaseFull, query);
//get sorted and filtered sql
var sqlNodeIdsWithSort = GetSortedSqlForPagedResults(
GetFilteredSqlForPagedResults(sqlQueryIds, filterSql),
GetFilteredSqlForPagedResults(sqlQueryIds, filterSql, queryHasWhereClause),
orderDirection, orderBy);
// Get page of results and total count
var pagedResult = Database.Page<UserDto>(pageIndex + 1, pageSize, sqlNodeIdsWithSort);
totalRecords = Convert.ToInt32(pagedResult.TotalItems);
//NOTE: We need to check the actual items returned, not the 'totalRecords', that is because if you request a page number
// that doesn't actually have any data on it, the totalRecords will still indicate there are records but there are none in
// the pageResult.
totalRecords = Convert.ToInt32(pagedResult.TotalItems);
//NOTE: We need to check the actual items returned, not the 'totalRecords', that is because if you request a page number
// that doesn't actually have any data on it, the totalRecords will still indicate there are records but there are none in
// the pageResult.
if (pagedResult.Items.Any())
{
//Create the inner paged query that was used above to get the paged result, we'll use that as the inner sub query
var args = sqlNodeIdsWithSort.Arguments;
string sqlStringCount, sqlStringPage;
Database.BuildPageQueries<UserDto>(pageIndex * pageSize, pageSize, sqlNodeIdsWithSort.SQL, ref args, out sqlStringCount, out sqlStringPage);
var sqlQueryFull = translatorFull.Translate();
var sqlQueryFull = GetBaseQuery("umbracoUser.*, umbracoUserGroup.*, umbracoUserGroup2App.*, umbracoUserStartNode.*");
var fullQueryWithPagedInnerJoin = sqlQueryFull
.Append("INNER JOIN (")
//join the paged query with the paged query arguments
//We need to make this FULL query an inner join on the paged ID query
var splitQuery = sqlQueryFull.SQL.Split(new[] { "WHERE " }, StringSplitOptions.None);
var fullQueryWithPagedInnerJoin = new Sql(splitQuery[0])
.Append("INNER JOIN (")
//join the paged query with the paged query arguments
.Append(sqlStringPage, args)
.Append(") temp ")
.Append("ON umbracoUser.id = temp.id");
AddGroupLeftJoin(fullQueryWithPagedInnerJoin);
if (splitQuery.Length > 1)
{
//add the original where clause back with the original arguments
fullQueryWithPagedInnerJoin.Where(splitQuery[1], sqlQueryIds.Arguments);
}
//get sorted and filtered sql
var fullQuery = GetSortedSqlForPagedResults(
GetFilteredSqlForPagedResults(fullQueryWithPagedInnerJoin, filterSql),
GetFilteredSqlForPagedResults(fullQueryWithPagedInnerJoin, filterSql, queryHasWhereClause),
orderDirection, orderBy);
var users = ConvertFromDtos(Database.Fetch<UserDto, UserGroupDto, UserGroup2AppDto, UserStartNodeDto, UserDto>(new UserGroupRelator().Map, fullQuery))
.ToArray(); // important so we don't iterate twice, if we don't do this we can end up with null values in cache if we were caching.
return users;
}
}
return Enumerable.Empty<IUser>();
}
private Sql GetFilteredSqlForPagedResults(Sql sql, Sql filterSql)
private Sql GetFilteredSqlForPagedResults(Sql sql, Sql filterSql, bool hasWhereClause)
{
Sql filteredSql;
// Apply filter
if (filterSql != null)
{
var sqlFilter = " WHERE " + filterSql.SQL.TrimStart("AND ");
//ensure we don't append a WHERE if there is already one
var sqlFilter = hasWhereClause
? filterSql.SQL
: " WHERE " + filterSql.SQL.TrimStart("AND ");
//NOTE: this is certainly strange - NPoco handles this much better but we need to re-create the sql
// instance a couple of times to get the parameter order correct, for some reason the first
@@ -915,4 +939,4 @@ ORDER BY colName";
}
}
}
}
@@ -290,6 +290,9 @@ namespace Umbraco.Core.Persistence.Repositories
// Apply filter
if (defaultFilter != null)
{
//NOTE: It is assumed here that the `sql` already contains a WHERE clause, see UserRepository.GetFilteredSqlForPagedResults
// for an example of when it's not assumed there's already a WHERE clause
var filterResult = defaultFilter();
//NOTE: this is certainly strange - NPoco handles this much better but we need to re-create the sql
@@ -993,4 +996,4 @@ ORDER BY contentNodeId, versionId, propertytypeid
}
}
}
}
}
@@ -53,6 +53,8 @@ namespace Umbraco.Core.Persistence.SqlSyntax
string TruncateTable { get; }
string CreateConstraint { get; }
string DeleteConstraint { get; }
[Obsolete("This is never used, use the Format(ForeignKeyDefinition) instead")]
string CreateForeignKeyConstraint { get; }
string DeleteDefaultConstraint { get; }
string FormatDateTime(DateTime date, bool includeTime = true);
@@ -78,9 +80,32 @@ namespace Umbraco.Core.Persistence.SqlSyntax
IEnumerable<string> GetTablesInSchema(Database db);
IEnumerable<ColumnInfo> GetColumnsInSchema(Database db);
/// <summary>
/// Returns all constraints defined in the database (Primary keys, foreign keys, unique constraints...) (does not include indexes)
/// </summary>
/// <param name="db"></param>
/// <returns>
/// A Tuple containing: TableName, ConstraintName
/// </returns>
IEnumerable<Tuple<string, string>> GetConstraintsPerTable(Database db);
/// <summary>
/// Returns all constraints defined in the database (Primary keys, foreign keys, unique constraints...) (does not include indexes)
/// </summary>
/// <param name="db"></param>
/// <returns>
/// A Tuple containing: TableName, ColumnName, ConstraintName
/// </returns>
IEnumerable<Tuple<string, string, string>> GetConstraintsPerColumn(Database db);
/// <summary>
/// Returns all defined Indexes in the database excluding primary keys
/// </summary>
/// <param name="db"></param>
/// <returns>
/// A Tuple containing: TableName, IndexName, ColumnName, IsUnique
/// </returns>
IEnumerable<Tuple<string, string, string, bool>> GetDefinedIndexes(Database db);
}
}
}
@@ -78,6 +78,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
return list;
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string>> GetConstraintsPerTable(Database db)
{
List<Tuple<string, string>> list;
@@ -100,6 +101,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
return list;
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string, string>> GetConstraintsPerColumn(Database db)
{
List<Tuple<string, string, string>> list;
@@ -126,6 +128,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
return list;
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string, string, bool>> GetDefinedIndexes(Database db)
{
List<Tuple<string, string, string, bool>> list;
@@ -401,4 +404,4 @@ ORDER BY TABLE_NAME, INDEX_NAME",
return PetaPocoExtensions.EscapeAtSymbols(MySql.Data.MySqlClient.MySqlHelper.EscapeString(val));
}
}
}
}
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
/// <summary>
/// Represents an SqlSyntaxProvider for Sql Ce
/// </summary>
[SqlSyntaxProviderAttribute(Constants.DatabaseProviders.SqlCe)]
[SqlSyntaxProvider(Constants.DatabaseProviders.SqlCe)]
public class SqlCeSyntaxProvider : MicrosoftSqlSyntaxProviderBase<SqlCeSyntaxProvider>
{
public SqlCeSyntaxProvider()
@@ -123,40 +123,27 @@ namespace Umbraco.Core.Persistence.SqlSyntax
item.IS_NULLABLE, item.DATA_TYPE)).ToList();
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string>> GetConstraintsPerTable(Database db)
{
var items = db.Fetch<dynamic>("SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS");
var indexItems = db.Fetch<dynamic>("SELECT TABLE_NAME, INDEX_NAME FROM INFORMATION_SCHEMA.INDEXES");
return
items.Select(item => new Tuple<string, string>(item.TABLE_NAME, item.CONSTRAINT_NAME))
.Union(
indexItems.Select(
indexItem => new Tuple<string, string>(indexItem.TABLE_NAME, indexItem.INDEX_NAME)))
.ToList();
return items.Select(item => new Tuple<string, string>(item.TABLE_NAME, item.CONSTRAINT_NAME)).ToList();
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string, string>> GetConstraintsPerColumn(Database db)
{
var items =
db.Fetch<dynamic>(
"SELECT CONSTRAINT_NAME, TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE");
var indexItems = db.Fetch<dynamic>("SELECT INDEX_NAME, TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.INDEXES");
return
items.Select(
item => new Tuple<string, string, string>(item.TABLE_NAME, item.COLUMN_NAME, item.CONSTRAINT_NAME))
.Union(
indexItems.Select(
indexItem =>
new Tuple<string, string, string>(indexItem.TABLE_NAME, indexItem.COLUMN_NAME,
indexItem.INDEX_NAME))).ToList();
var items = db.Fetch<dynamic>("SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE");
return items.Select(item => new Tuple<string, string, string>(item.TABLE_NAME, item.COLUMN_NAME, item.CONSTRAINT_NAME)).ToList();
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string, string, bool>> GetDefinedIndexes(Database db)
{
var items =
db.Fetch<dynamic>(
@"SELECT TABLE_NAME, INDEX_NAME, COLUMN_NAME, [UNIQUE] FROM INFORMATION_SCHEMA.INDEXES
WHERE INDEX_NAME NOT LIKE 'PK_%'
WHERE PRIMARY_KEY=0
ORDER BY TABLE_NAME, INDEX_NAME");
return
items.Select(
@@ -215,4 +202,4 @@ ORDER BY TABLE_NAME, INDEX_NAME");
public override string DropIndex { get { return "DROP INDEX {1}.{0}"; } }
}
}
}
@@ -1,186 +1,188 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Persistence.SqlSyntax
{
/// <summary>
/// Represents an SqlSyntaxProvider for Sql Server.
/// </summary>
[SqlSyntaxProvider(Constants.DatabaseProviders.SqlServer)]
public class SqlServerSyntaxProvider : MicrosoftSqlSyntaxProviderBase<SqlServerSyntaxProvider>
{
/// <summary>
/// Gets/sets the version of the current SQL server instance
/// </summary>
internal SqlServerVersionName GetVersionName(Database database)
{
if (_versionName.HasValue)
return _versionName.Value;
try
{
var version = database.ExecuteScalar<string>("SELECT SERVERPROPERTY('productversion')");
var firstPart = version.Split('.')[0];
switch (firstPart)
{
case "13":
_versionName = SqlServerVersionName.V2016;
break;
case "12":
_versionName = SqlServerVersionName.V2014;
break;
case "11":
_versionName = SqlServerVersionName.V2012;
break;
case "10":
_versionName = SqlServerVersionName.V2008;
break;
case "9":
_versionName = SqlServerVersionName.V2005;
break;
case "8":
_versionName = SqlServerVersionName.V2000;
break;
case "7":
_versionName = SqlServerVersionName.V7;
break;
default:
_versionName = SqlServerVersionName.Other;
break;
}
}
catch (Exception)
{
_versionName = SqlServerVersionName.Invalid;
}
return _versionName.Value;
}
private SqlServerVersionName? _versionName;
/// <summary>
/// SQL Server stores default values assigned to columns as constraints, it also stores them with named values, this is the only
/// server type that does this, therefore this method doesn't exist on any other syntax provider
/// </summary>
/// <returns></returns>
public IEnumerable<Tuple<string, string, string, string>> GetDefaultConstraintsPerColumn(Database db)
{
var items = db.Fetch<dynamic>("SELECT TableName = t.Name,ColumnName = c.Name,dc.Name,dc.[Definition] FROM sys.tables t INNER JOIN sys.default_constraints dc ON t.object_id = dc.parent_object_id INNER JOIN sys.columns c ON dc.parent_object_id = c.object_id AND c.column_id = dc.parent_column_id");
return items.Select(x => new Tuple<string, string, string, string>(x.TableName, x.ColumnName, x.Name, x.Definition));
}
public override IEnumerable<string> GetTablesInSchema(Database db)
{
var items = db.Fetch<dynamic>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES");
return items.Select(x => x.TABLE_NAME).Cast<string>().ToList();
}
public override IEnumerable<ColumnInfo> GetColumnsInSchema(Database db)
{
var items = db.Fetch<dynamic>("SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS");
return
items.Select(
item =>
new ColumnInfo(item.TABLE_NAME, item.COLUMN_NAME, item.ORDINAL_POSITION, item.COLUMN_DEFAULT,
item.IS_NULLABLE, item.DATA_TYPE)).ToList();
}
public override IEnumerable<Tuple<string, string>> GetConstraintsPerTable(Database db)
{
var items =
db.Fetch<dynamic>(
"SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE");
return items.Select(item => new Tuple<string, string>(item.TABLE_NAME, item.CONSTRAINT_NAME)).ToList();
}
public override IEnumerable<Tuple<string, string, string>> GetConstraintsPerColumn(Database db)
{
var items =
db.Fetch<dynamic>(
"SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE");
return items.Select(item => new Tuple<string, string, string>(item.TABLE_NAME, item.COLUMN_NAME, item.CONSTRAINT_NAME)).ToList();
}
public override IEnumerable<Tuple<string, string, string, bool>> GetDefinedIndexes(Database db)
{
var items =
db.Fetch<dynamic>(
@"select T.name as TABLE_NAME, I.name as INDEX_NAME, AC.Name as COLUMN_NAME,
CASE WHEN I.is_unique_constraint = 1 OR I.is_unique = 1 THEN 1 ELSE 0 END AS [UNIQUE]
from sys.tables as T inner join sys.indexes as I on T.[object_id] = I.[object_id]
inner join sys.index_columns as IC on IC.[object_id] = I.[object_id] and IC.[index_id] = I.[index_id]
inner join sys.all_columns as AC on IC.[object_id] = AC.[object_id] and IC.[column_id] = AC.[column_id]
WHERE I.name NOT LIKE 'PK_%'
order by T.name, I.name");
return items.Select(item => new Tuple<string, string, string, bool>(item.TABLE_NAME, item.INDEX_NAME, item.COLUMN_NAME,
item.UNIQUE == 1)).ToList();
}
public override bool DoesTableExist(Database db, string tableName)
{
var result =
db.ExecuteScalar<long>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @TableName",
new { TableName = tableName });
return result > 0;
}
public override string FormatColumnRename(string tableName, string oldName, string newName)
{
return string.Format(RenameColumn, tableName, oldName, newName);
}
public override string FormatTableRename(string oldName, string newName)
{
return string.Format(RenameTable, oldName, newName);
}
protected override string FormatIdentity(ColumnDefinition column)
{
return column.IsIdentity ? GetIdentityString(column) : string.Empty;
}
public override Sql SelectTop(Sql sql, int top)
{
return new Sql(sql.SQL.Insert(sql.SQL.IndexOf(' '), " TOP " + top), sql.Arguments);
}
private static string GetIdentityString(ColumnDefinition column)
{
return "IDENTITY(1,1)";
}
protected override string FormatSystemMethods(SystemMethods systemMethod)
{
switch (systemMethod)
{
case SystemMethods.NewGuid:
return "NEWID()";
case SystemMethods.CurrentDateTime:
return "GETDATE()";
//case SystemMethods.NewSequentialId:
// return "NEWSEQUENTIALID()";
//case SystemMethods.CurrentUTCDateTime:
// return "GETUTCDATE()";
}
return null;
}
public override string DeleteDefaultConstraint
{
get { return "ALTER TABLE [{0}] DROP CONSTRAINT [DF_{0}_{1}]"; }
}
public override string DropIndex { get { return "DROP INDEX {0} ON {1}"; } }
public override string RenameColumn { get { return "sp_rename '{0}.{1}', '{2}', 'COLUMN'"; } }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Persistence.SqlSyntax
{
/// <summary>
/// Represents an SqlSyntaxProvider for Sql Server.
/// </summary>
[SqlSyntaxProvider(Constants.DatabaseProviders.SqlServer)]
public class SqlServerSyntaxProvider : MicrosoftSqlSyntaxProviderBase<SqlServerSyntaxProvider>
{
/// <summary>
/// Gets/sets the version of the current SQL server instance
/// </summary>
internal SqlServerVersionName GetVersionName(Database database)
{
if (_versionName.HasValue)
return _versionName.Value;
try
{
var version = database.ExecuteScalar<string>("SELECT SERVERPROPERTY('productversion')");
var firstPart = version.Split('.')[0];
switch (firstPart)
{
case "13":
_versionName = SqlServerVersionName.V2016;
break;
case "12":
_versionName = SqlServerVersionName.V2014;
break;
case "11":
_versionName = SqlServerVersionName.V2012;
break;
case "10":
_versionName = SqlServerVersionName.V2008;
break;
case "9":
_versionName = SqlServerVersionName.V2005;
break;
case "8":
_versionName = SqlServerVersionName.V2000;
break;
case "7":
_versionName = SqlServerVersionName.V7;
break;
default:
_versionName = SqlServerVersionName.Other;
break;
}
}
catch (Exception)
{
_versionName = SqlServerVersionName.Invalid;
}
return _versionName.Value;
}
private SqlServerVersionName? _versionName;
/// <summary>
/// SQL Server stores default values assigned to columns as constraints, it also stores them with named values, this is the only
/// server type that does this, therefore this method doesn't exist on any other syntax provider
/// </summary>
/// <returns></returns>
public IEnumerable<Tuple<string, string, string, string>> GetDefaultConstraintsPerColumn(Database db)
{
var items = db.Fetch<dynamic>("SELECT TableName = t.Name, ColumnName = c.Name, dc.Name, dc.[Definition] FROM sys.tables t INNER JOIN sys.default_constraints dc ON t.object_id = dc.parent_object_id INNER JOIN sys.columns c ON dc.parent_object_id = c.object_id AND c.column_id = dc.parent_column_id INNER JOIN sys.schemas as s on t.[schema_id] = s.[schema_id] WHERE s.name = (SELECT SCHEMA_NAME())");
return items.Select(x => new Tuple<string, string, string, string>(x.TableName, x.ColumnName, x.Name, x.Definition));
}
public override IEnumerable<string> GetTablesInSchema(Database db)
{
var items = db.Fetch<dynamic>("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
return items.Select(x => x.TABLE_NAME).Cast<string>().ToList();
}
public override IEnumerable<ColumnInfo> GetColumnsInSchema(Database db)
{
var items = db.Fetch<dynamic>("SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
return
items.Select(
item =>
new ColumnInfo(item.TABLE_NAME, item.COLUMN_NAME, item.ORDINAL_POSITION, item.COLUMN_DEFAULT,
item.IS_NULLABLE, item.DATA_TYPE)).ToList();
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string>> GetConstraintsPerTable(Database db)
{
var items =
db.Fetch<dynamic>(
"SELECT TABLE_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_TABLE_USAGE WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
return items.Select(item => new Tuple<string, string>(item.TABLE_NAME, item.CONSTRAINT_NAME)).ToList();
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string, string>> GetConstraintsPerColumn(Database db)
{
var items =
db.Fetch<dynamic>(
"SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE WHERE TABLE_SCHEMA = (SELECT SCHEMA_NAME())");
return items.Select(item => new Tuple<string, string, string>(item.TABLE_NAME, item.COLUMN_NAME, item.CONSTRAINT_NAME)).ToList();
}
/// <inheritdoc />
public override IEnumerable<Tuple<string, string, string, bool>> GetDefinedIndexes(Database db)
{
var items =
db.Fetch<dynamic>(
@"select T.name as TABLE_NAME, I.name as INDEX_NAME, AC.Name as COLUMN_NAME,
CASE WHEN I.is_unique_constraint = 1 OR I.is_unique = 1 THEN 1 ELSE 0 END AS [UNIQUE]
from sys.tables as T inner join sys.indexes as I on T.[object_id] = I.[object_id]
inner join sys.index_columns as IC on IC.[object_id] = I.[object_id] and IC.[index_id] = I.[index_id]
inner join sys.all_columns as AC on IC.[object_id] = AC.[object_id] and IC.[column_id] = AC.[column_id]
inner join sys.schemas as S on T.[schema_id] = S.[schema_id]
WHERE S.name = (SELECT SCHEMA_NAME()) AND I.is_primary_key = 0
order by T.name, I.name");
return items.Select(item => new Tuple<string, string, string, bool>(item.TABLE_NAME, item.INDEX_NAME, item.COLUMN_NAME,
item.UNIQUE == 1)).ToList();
}
public override bool DoesTableExist(Database db, string tableName)
{
var result =
db.ExecuteScalar<long>("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = @TableName AND TABLE_SCHEMA = (SELECT SCHEMA_NAME())",
new { TableName = tableName });
return result > 0;
}
public override string FormatColumnRename(string tableName, string oldName, string newName)
{
return string.Format(RenameColumn, tableName, oldName, newName);
}
public override string FormatTableRename(string oldName, string newName)
{
return string.Format(RenameTable, oldName, newName);
}
protected override string FormatIdentity(ColumnDefinition column)
{
return column.IsIdentity ? GetIdentityString(column) : string.Empty;
}
public override Sql SelectTop(Sql sql, int top)
{
return new Sql(sql.SQL.Insert(sql.SQL.IndexOf(' '), " TOP " + top), sql.Arguments);
}
private static string GetIdentityString(ColumnDefinition column)
{
return "IDENTITY(1,1)";
}
protected override string FormatSystemMethods(SystemMethods systemMethod)
{
switch (systemMethod)
{
case SystemMethods.NewGuid:
return "NEWID()";
case SystemMethods.CurrentDateTime:
return "GETDATE()";
//case SystemMethods.NewSequentialId:
// return "NEWSEQUENTIALID()";
//case SystemMethods.CurrentUTCDateTime:
// return "GETUTCDATE()";
}
return null;
}
public override string DeleteDefaultConstraint
{
get { return "ALTER TABLE [{0}] DROP CONSTRAINT [DF_{0}_{1}]"; }
}
public override string DropIndex { get { return "DROP INDEX {0} ON {1}"; } }
public override string RenameColumn { get { return "sp_rename '{0}.{1}', '{2}', 'COLUMN'"; } }
}
}
@@ -537,10 +537,11 @@ namespace Umbraco.Core.Persistence.SqlSyntax
public virtual string CreateConstraint { get { return "ALTER TABLE {0} ADD CONSTRAINT {1} {2} ({3})"; } }
public virtual string DeleteConstraint { get { return "ALTER TABLE {0} DROP CONSTRAINT {1}"; } }
public virtual string CreateForeignKeyConstraint { get { return "ALTER TABLE {0} ADD CONSTRAINT {1} FOREIGN KEY ({2}) REFERENCES {3} ({4}){5}{6}"; } }
public virtual string ConvertIntegerToOrderableString { get { return "REPLACE(STR({0}, 8), SPACE(1), '0')"; } }
public virtual string ConvertDateToOrderableString { get { return "CONVERT(nvarchar, {0}, 102)"; } }
public virtual string ConvertDecimalToOrderableString { get { return "REPLACE(STR({0}, 20, 9), SPACE(1), '0')"; } }
}
}
}
@@ -9,13 +9,7 @@ namespace Umbraco.Core.Persistence.SqlSyntax
public static IEnumerable<DbIndexDefinition> GetDefinedIndexesDefinitions(this ISqlSyntaxProvider sql, Database db)
{
return sql.GetDefinedIndexes(db)
.Select(x => new DbIndexDefinition()
{
TableName = x.Item1,
IndexName = x.Item2,
ColumnName = x.Item3,
IsUnique = x.Item4
}).ToArray();
.Select(x => new DbIndexDefinition(x)).ToArray();
}
/// <summary>
@@ -57,4 +51,4 @@ namespace Umbraco.Core.Persistence.SqlSyntax
In,
NotIn
}
}
}
@@ -42,18 +42,19 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
return null;
}
var isMultipleDataType = IsMultipleDataType(propertyType.DataTypeId, propertyType.PropertyEditorAlias);
var selectedValues = (string[]) source;
if (selectedValues.Any())
{
if (IsMultipleDataType(propertyType.DataTypeId, propertyType.PropertyEditorAlias))
{
if (isMultipleDataType)
return selectedValues;
}
return selectedValues.First();
}
return source;
return isMultipleDataType ? source : string.Empty;
}
public Type GetPropertyValueType(PublishedPropertyType propertyType)
@@ -1,8 +1,10 @@
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
@@ -458,5 +460,23 @@ namespace Umbraco.Core.Security
return ticket;
}
/// <summary>
/// Ensures that the thread culture is set based on the back office user's culture
/// </summary>
/// <param name="identity"></param>
internal static void EnsureCulture(this IIdentity identity)
{
if (identity is UmbracoBackOfficeIdentity umbIdentity && umbIdentity.IsAuthenticated)
{
Thread.CurrentThread.CurrentUICulture =
Thread.CurrentThread.CurrentCulture =
UserCultures.GetOrAdd(umbIdentity.Culture, s => new CultureInfo(s));
}
}
/// <summary>
/// Used so that we aren't creating a new CultureInfo object for every single request
/// </summary>
private static readonly ConcurrentDictionary<string, CultureInfo> UserCultures = new ConcurrentDictionary<string, CultureInfo>();
}
}
}
@@ -102,7 +102,8 @@ namespace Umbraco.Core.Security
/// <returns/>
public override async Task ValidateIdentity(CookieValidateIdentityContext context)
{
EnsureCulture(context);
//ensure the thread culture is set
context?.Identity?.EnsureCulture();
await EnsureValidSessionId(context);
@@ -120,21 +121,5 @@ namespace Umbraco.Core.Security
if (_appCtx.IsConfigured && _appCtx.IsUpgrading == false)
await SessionIdValidator.ValidateSessionAsync(TimeSpan.FromMinutes(1), context);
}
private void EnsureCulture(CookieValidateIdentityContext context)
{
var umbIdentity = context.Identity as UmbracoBackOfficeIdentity;
if (umbIdentity != null && umbIdentity.IsAuthenticated)
{
Thread.CurrentThread.CurrentCulture =
Thread.CurrentThread.CurrentUICulture =
UserCultures.GetOrAdd(umbIdentity.Culture, s => new CultureInfo(s));
}
}
/// <summary>
/// Used so that we aren't creating a new CultureInfo object for every single request
/// </summary>
private static readonly ConcurrentDictionary<string, CultureInfo> UserCultures = new ConcurrentDictionary<string, CultureInfo>();
}
}
}
@@ -236,7 +236,10 @@ namespace Umbraco.Core.Security
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<T, int>(dataProtectionProvider.Create("ASP.NET Identity"));
manager.UserTokenProvider = new DataProtectorTokenProvider<T, int>(dataProtectionProvider.Create("ASP.NET Identity"))
{
TokenLifespan = TimeSpan.FromDays(3)
};
}
manager.UserLockoutEnabledByDefault = true;
@@ -748,6 +751,7 @@ namespace Umbraco.Core.Security
var httpContext = HttpContext.Current == null ? (HttpContextBase)null : new HttpContextWrapper(HttpContext.Current);
return httpContext.GetCurrentRequestIpAddress();
}
}
}
@@ -630,7 +630,9 @@ namespace Umbraco.Core.Security
|| identityUser.LastLoginDateUtc.HasValue && user.LastLoginDate.ToUniversalTime() != identityUser.LastLoginDateUtc.Value)
{
anythingChanged = true;
user.LastLoginDate = identityUser.LastLoginDateUtc.Value.ToLocalTime();
//if the LastLoginDate is being set to MinValue, don't convert it ToLocalTime
var dt = identityUser.LastLoginDateUtc == DateTime.MinValue ? DateTime.MinValue : identityUser.LastLoginDateUtc.Value.ToLocalTime();
user.LastLoginDate = dt;
}
if (identityUser.IsPropertyDirty("LastPasswordChangeDateUtc")
|| (user.LastPasswordChangeDate != default(DateTime) && identityUser.LastPasswordChangeDateUtc.HasValue == false)
@@ -720,7 +720,7 @@ namespace Umbraco.Core.Security
}
else
{
//if the salt bytes is too long for the required key length for the algorithm, extend it
//if the salt bytes is too short for the required key length for the algorithm, extend it
var numArray2 = new byte[keyedHashAlgorithm.Key.Length];
var dstOffset = 0;
while (dstOffset < numArray2.Length)
@@ -963,4 +963,4 @@ namespace Umbraco.Core.Security
}
}
}
}
+8 -5
View File
@@ -2060,12 +2060,15 @@ namespace Umbraco.Core.Services
using (new WriteLock(Locker))
{
var allContent = GetByIds(ids).ToDictionary(x => x.Id, x => x);
var items = ids.Select(x => allContent[x]);
if (allContent.Any() == false)
{
return false;
}
var items = ids.Select(x => allContent[x]).ToArray();
using (var uow = UowProvider.GetUnitOfWork())
{
var asArray = items.ToArray();
var saveEventArgs = new SaveEventArgs<IContent>(asArray);
var saveEventArgs = new SaveEventArgs<IContent>(items);
if (raiseEvents && uow.Events.DispatchCancelable(Saving, this, saveEventArgs, "Saving"))
{
uow.Commit();
@@ -2075,7 +2078,7 @@ namespace Umbraco.Core.Services
var repository = RepositoryFactory.CreateContentRepository(uow);
var i = 0;
foreach (var content in asArray)
foreach (var content in items)
{
//If the current sort order equals that of the content
//we don't need to update it, so just increment the sort order
@@ -2122,7 +2125,7 @@ namespace Umbraco.Core.Services
_publishingStrategy.PublishingFinalized(uow, shouldBePublished, false);
}
Audit(uow, AuditType.Sort, "Sorting content performed by user", userId, 0);
Audit(uow, AuditType.Sort, "Sort child items performed by user", userId, items.First().ParentId);
uow.Commit();
}
}
@@ -49,7 +49,7 @@ namespace Umbraco.Core.Services
private Dictionary<string, IContentType> _importedContentTypes;
private IPackageInstallation _packageInstallation;
private readonly IUserService _userService;
private static HttpClient _httpClient;
public PackagingService(
ILogger logger,
@@ -89,7 +89,6 @@ namespace Umbraco.Core.Services
/// <returns></returns>
public string FetchPackageFile(Guid packageId, Version umbracoVersion, int userId)
{
using (var httpClient = new HttpClient())
using (var uow = _uowProvider.GetUnitOfWork())
{
//includeHidden = true because we don't care if it's hidden we want to get the file regardless
@@ -97,7 +96,11 @@ namespace Umbraco.Core.Services
byte[] bytes;
try
{
bytes = httpClient.GetByteArrayAsync(url).GetAwaiter().GetResult();
if (_httpClient == null)
{
_httpClient = new HttpClient();
}
bytes = _httpClient.GetByteArrayAsync(url).GetAwaiter().GetResult();
}
catch (HttpRequestException ex)
{
@@ -1746,7 +1749,7 @@ namespace Umbraco.Core.Services
internal InstallationSummary InstallPackage(string packageFilePath, int userId = 0, bool raiseEvents = false)
{
var metaData = GetPackageMetaData(packageFilePath);
var metaData = GetPackageMetaData(packageFilePath);
if (raiseEvents)
{
@@ -77,7 +77,7 @@ namespace Umbraco.Core.Services
regs = xr.Repository.GetAll().ToArray();
// default role is single server, but if registrations contain more
// than one active server, then role is master or slave
// than one active server, then role is master or replica
_currentServerRole = regs.Count(x => x.IsActive) > 1
? (server.IsMaster ? ServerRole.Master : ServerRole.Slave)
: ServerRole.Single;
@@ -175,4 +175,4 @@ namespace Umbraco.Core.Services
return _currentServerRole;
}
}
}
}
+1 -1
View File
@@ -699,7 +699,7 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
{
var repository = RepositoryFactory.CreateUserRepository(uow);
return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, member => member.Username);
return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, member => member.Name);
}
}
+24
View File
@@ -1574,5 +1574,29 @@ namespace Umbraco.Core
guid[left] = guid[right];
guid[right] = temp;
}
/// <summary>
/// Converts a file name to a friendly name for a content item
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public static string ToFriendlyName(this string fileName)
{
// strip the file extension
fileName = fileName.StripFileExtension();
// underscores and dashes to spaces
fileName = fileName.ReplaceMany(new[] { '_', '-' }, ' ');
// any other conversions ?
// Pascalcase (to be done last)
fileName = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(fileName);
// Replace multiple consecutive spaces with a single space
fileName = string.Join(" ", fileName.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries));
return fileName;
}
}
}
@@ -51,10 +51,9 @@ namespace Umbraco.Core.Sync
if (request != null)
{
var applicationUrl = GetApplicationUrlFromRequest(request);
newApplicationUrl = !appContext._umbracoApplicationDomains.Contains(applicationUrl);
newApplicationUrl = appContext._umbracoApplicationDomains.TryAdd(applicationUrl, applicationUrl);
if (newApplicationUrl)
{
appContext._umbracoApplicationDomains.Add(applicationUrl);
LogHelper.Info(typeof(ApplicationUrlHelper), string.Format("New ApplicationUrl detected: {0}", applicationUrl));
}
}
+2 -2
View File
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Sync
Single = 1,
/// <summary>
/// In a multi-servers environment, the server is a slave server.
/// In a multi-servers environment, the server is a replica server.
/// </summary>
Slave = 2,
@@ -25,4 +25,4 @@ namespace Umbraco.Core.Sync
/// </summary>
Master = 3
}
}
}
+12 -7
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -45,8 +45,8 @@
<Reference Include="AutoMapper.Net4, Version=3.3.1.0, Culture=neutral, PublicKeyToken=be96cd2c38ef1005, processorArchitecture=MSIL">
<HintPath>..\packages\AutoMapper.3.3.1\lib\net40\AutoMapper.Net4.dll</HintPath>
</Reference>
<Reference Include="ClientDependency.Core, Version=1.9.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.6\lib\net45\ClientDependency.Core.dll</HintPath>
<Reference Include="ClientDependency.Core, Version=1.9.7.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.7\lib\net45\ClientDependency.Core.dll</HintPath>
</Reference>
<Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, PublicKeyToken=bd319b19eaf3b43a, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
@@ -365,6 +365,11 @@
<Compile Include="IEmailSender.cs" />
<Compile Include="IHttpContextAccessor.cs" />
<Compile Include="Logging\RollingFileCleanupAppender.cs" />
<Compile Include="Media\Exif\SVGFile.cs" />
<Compile Include="Media\TypeDetector\JPEGDetector.cs" />
<Compile Include="Media\TypeDetector\RasterizedTypeDetector.cs" />
<Compile Include="Media\TypeDetector\SVGDetector.cs" />
<Compile Include="Media\TypeDetector\TIFFDetector.cs" />
<Compile Include="Models\AuditEntry.cs" />
<Compile Include="Models\Consent.cs" />
<Compile Include="Models\ConsentExtensions.cs" />
@@ -567,8 +572,8 @@
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenEightZero\AddInstructionCountColumn.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenEightZero\AddCmsMediaTable.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenEightZero\AddUserLoginTable.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwelveZero\RenameTrueFalseField.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwelveZero\SetDefaultTagsStorageType.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwelveZero\RenameTrueFalseField.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwelveZero\SetDefaultTagsStorageType.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenNineZero\AddUmbracoAuditTable.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenNineZero\AddUmbracoConsentTable.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenNineZero\AddIsSensitiveMemberTypeColumn.cs" />
@@ -638,7 +643,7 @@
<Compile Include="Media\Exif\TIFFStrip.cs" />
<Compile Include="Media\Exif\Utility.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenThreeOne\UpdateUserLanguagesToIsoCode.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwelveZero\IncreaseLanguageIsoCodeColumnLength.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwelveZero\IncreaseLanguageIsoCodeColumnLength.cs" />
<Compile Include="Persistence\Migrations\Upgrades\TargetVersionSevenTwelveZero\UpdateUmbracoConsent.cs" />
<Compile Include="Persistence\PocoDataDataReader.cs" />
<Compile Include="Persistence\Querying\CachedExpression.cs" />
@@ -1688,4 +1693,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>
+1 -1
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="ClientDependency" version="1.9.6" targetFramework="net45" />
<package id="ClientDependency" version="1.9.7" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
<package id="ImageProcessor" version="2.5.6" targetFramework="net45" />
<package id="log4net" version="2.0.8" targetFramework="net45" />
@@ -129,7 +129,7 @@ namespace Umbraco.Tests
public void SetApplicationUrlFromDcSettingsSsl2()
{
// set from distributed call settings
// other servers are slave servers
// other servers are replica servers
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Enabled == true && callSection.Servers == new IServer[]
@@ -224,7 +224,7 @@ namespace Umbraco.Tests
[Test]
public void ServerRoleUnknown2()
{
// distributed call enabled, cannot find server, assume it's an undeclared slave
// distributed call enabled, cannot find server, assume it's an undeclared replica
var settings = Mock.Of<IUmbracoSettingsSection>(section =>
section.DistributedCall == Mock.Of<IDistributedCallSection>(callSection => callSection.Enabled == true && callSection.Servers == new IServer[]
@@ -301,4 +301,4 @@ namespace Umbraco.Tests
Assert.AreEqual("httpx://whatever.com/umbraco", appCtx._umbracoApplicationUrl);
}
}
}
}
@@ -23,6 +23,12 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings
Assert.IsTrue(SettingsSection.WebRouting.DisableAlternativeTemplates == false);
}
[Test]
public void ValidateAlternativeTemplates()
{
Assert.IsTrue(SettingsSection.WebRouting.ValidateAlternativeTemplates == false);
}
[Test]
public void DisableFindContentByIdPath()
{
@@ -66,6 +66,46 @@ namespace Umbraco.Tests.Persistence.Repositories
}
}
[Test]
public void Get_Paged_Items_By_User_Id_With_Query_And_Filter()
{
var provider = new PetaPocoUnitOfWorkProvider(Logger);
var unitOfWork = provider.GetUnitOfWork();
using (var repo = new AuditRepository(unitOfWork, CacheHelper, Logger, SqlSyntax))
{
for (int i = 0; i < 100; i++)
{
repo.AddOrUpdate(new AuditItem(i, string.Format("Content {0} created", i), AuditType.New, 0));
repo.AddOrUpdate(new AuditItem(i, string.Format("Content {0} published", i), AuditType.Publish, 0));
}
unitOfWork.Commit();
}
using (var repo = new AuditRepository(unitOfWork, CacheHelper, Logger, SqlSyntax))
{
var query = Query<IAuditItem>.Builder.Where(x => x.UserId == 0);
try
{
DatabaseContext.Database.EnableSqlTrace = true;
DatabaseContext.Database.EnableSqlCount();
var page = repo.GetPagedResultsByQuery(query, 0, 10, out var total, Direction.Descending,
new[] { AuditType.Publish },
Query<IAuditItem>.Builder.Where(x => x.UserId > -1));
Assert.AreEqual(10, page.Count());
Assert.AreEqual(100, total);
}
finally
{
DatabaseContext.Database.EnableSqlTrace = false;
DatabaseContext.Database.DisableSqlCount();
}
}
}
[Test]
public void Get_Paged_Items_With_AuditType_Filter()
{
@@ -83,14 +123,24 @@ namespace Umbraco.Tests.Persistence.Repositories
using (var repo = new AuditRepository(unitOfWork, CacheHelper, Logger, SqlSyntax))
{
long total;
var page = repo.GetPagedResultsByQuery(Query<IAuditItem>.Builder, 0, 9, out total, Direction.Descending,
new[] {AuditType.Publish}, null)
.ToArray();
try
{
DatabaseContext.Database.EnableSqlTrace = true;
DatabaseContext.Database.EnableSqlCount();
Assert.AreEqual(9, page.Length);
Assert.IsTrue(page.All(x => x.AuditType == AuditType.Publish));
Assert.AreEqual(100, total);
var page = repo.GetPagedResultsByQuery(Query<IAuditItem>.Builder, 0, 9, out var total, Direction.Descending,
new[] { AuditType.Publish }, null)
.ToArray();
Assert.AreEqual(9, page.Length);
Assert.IsTrue(page.All(x => x.AuditType == AuditType.Publish));
Assert.AreEqual(100, total);
}
finally
{
DatabaseContext.Database.EnableSqlTrace = false;
DatabaseContext.Database.DisableSqlCount();
}
}
}
@@ -111,15 +161,25 @@ namespace Umbraco.Tests.Persistence.Repositories
using (var repo = new AuditRepository(unitOfWork, CacheHelper, Logger, SqlSyntax))
{
long total;
var page = repo.GetPagedResultsByQuery(Query<IAuditItem>.Builder, 0, 8, out total, Direction.Descending,
null, Query<IAuditItem>.Builder.Where(item => item.Comment == "Content created"))
.ToArray();
try
{
DatabaseContext.Database.EnableSqlTrace = true;
DatabaseContext.Database.EnableSqlCount();
Assert.AreEqual(8, page.Length);
Assert.IsTrue(page.All(x => x.Comment == "Content created"));
Assert.AreEqual(100, total);
var page = repo.GetPagedResultsByQuery(Query<IAuditItem>.Builder, 0, 8, out var total, Direction.Descending,
null, Query<IAuditItem>.Builder.Where(item => item.Comment == "Content created"))
.ToArray();
Assert.AreEqual(8, page.Length);
Assert.IsTrue(page.All(x => x.Comment == "Content created"));
Assert.AreEqual(100, total);
}
finally
{
DatabaseContext.Database.EnableSqlTrace = false;
DatabaseContext.Database.DisableSqlCount();
}
}
}
}
}
}
@@ -6,6 +6,7 @@ using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.UnitOfWork;
@@ -392,7 +393,71 @@ namespace Umbraco.Tests.Persistence.Repositories
var result = repository.Count(query);
// Assert
Assert.That(result, Is.GreaterThanOrEqualTo(2));
Assert.AreEqual(2, result);
}
}
[Test]
public void Can_Get_Paged_Results_By_Query_And_Filter_And_Groups()
{
// Arrange
var provider = new PetaPocoUnitOfWorkProvider(Logger);
var unitOfWork = provider.GetUnitOfWork();
using (var repository = CreateRepository(unitOfWork))
{
var users = CreateAndCommitMultipleUsers(repository, unitOfWork);
var query = Query<IUser>.Builder.Where(x => x.Username == "TestUser1" || x.Username == "TestUser2");
try
{
DatabaseContext.Database.EnableSqlTrace = true;
DatabaseContext.Database.EnableSqlCount();
// Act
var result = repository.GetPagedResultsByQuery(query, 0, 10, out var totalRecs, user => user.Id, Direction.Ascending,
excludeUserGroups: new[] { Constants.Security.TranslatorGroupAlias },
filter: Query<IUser>.Builder.Where(x => x.Id > -1));
// Assert
Assert.AreEqual(2, totalRecs);
}
finally
{
DatabaseContext.Database.EnableSqlTrace = false;
DatabaseContext.Database.DisableSqlCount();
}
}
}
[Test]
public void Can_Get_Paged_Results_With_Filter_And_Groups()
{
// Arrange
var provider = new PetaPocoUnitOfWorkProvider(Logger);
var unitOfWork = provider.GetUnitOfWork();
using (var repository = CreateRepository(unitOfWork))
{
var users = CreateAndCommitMultipleUsers(repository, unitOfWork);
try
{
DatabaseContext.Database.EnableSqlTrace = true;
DatabaseContext.Database.EnableSqlCount();
// Act
var result = repository.GetPagedResultsByQuery(null, 0, 10, out var totalRecs, user => user.Id, Direction.Ascending,
includeUserGroups: new[] { Constants.Security.AdminGroupAlias, Constants.Security.SensitiveDataGroupAlias },
excludeUserGroups: new[] { Constants.Security.TranslatorGroupAlias },
filter: Query<IUser>.Builder.Where(x => x.Id == 0));
// Assert
Assert.AreEqual(1, totalRecs);
}
finally
{
DatabaseContext.Database.EnableSqlTrace = false;
DatabaseContext.Database.DisableSqlCount();
}
}
}
@@ -439,4 +504,4 @@ namespace Umbraco.Tests.Persistence.Repositories
return new IUser[] { user1, user2, user3 };
}
}
}
}
@@ -288,6 +288,29 @@ namespace Umbraco.Tests.Services
Assert.AreEqual(2, membersInRole.Count());
}
[Test]
public void Associate_Members_To_Roles_With_Member_Id_Casing()
{
ServiceContext.MemberService.AddRole("MyTestRole1");
IMemberType memberType = MockedContentTypes.CreateSimpleMemberType();
ServiceContext.MemberTypeService.Save(memberType);
var member1 = MockedMember.CreateSimpleMember(memberType, "test1", "test1@test.com", "pass", "test1");
ServiceContext.MemberService.Save(member1);
var member2 = MockedMember.CreateSimpleMember(memberType, "test2", "test2@test.com", "pass", "test2");
ServiceContext.MemberService.Save(member2);
// temp make sure they exist
Assert.IsNotNull(ServiceContext.MemberService.GetById(member1.Id));
Assert.IsNotNull(ServiceContext.MemberService.GetById(member2.Id));
ServiceContext.MemberService.AssignRoles(new[] { member1.Id, member2.Id }, new[] { "mytestrole1" });
var membersInRole = ServiceContext.MemberService.GetMembersInRole("MyTestRole1");
Assert.AreEqual(2, membersInRole.Count());
}
[Test]
public void Associate_Members_To_Roles_With_Member_Username()
{
@@ -1179,4 +1202,4 @@ namespace Umbraco.Tests.Services
}
}
}
}

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