Compare commits

..

13 Commits

Author SHA1 Message Date
Sebastiaan Janssen 0f7de97558 Whoops, fixes previous commit for #2896
(cherry picked from commit b2b9b53af1)
2018-09-02 10:06:24 +02:00
Sebastiaan Janssen 588493e811 Seems there is no need to hide the .small class, fixes #2896
(cherry picked from commit 2dd5010d2c)
2018-09-02 09:58:34 +02:00
Ali.Taheri 87af9b2089 u4-8310 - Added error message to the xml file.
(cherry picked from commit 541e546f7b)
2018-08-31 20:07:10 +02:00
Ali.Taheri ba3cf056fb u4-8310 - Fixed rename content type with the same alias but with different casing.
(cherry picked from commit 26a8d680d4)
2018-08-31 20:07:05 +02:00
Marcel van Helmont 619acb552b added val-email to corrrectly validate emails supporting new TLD
(cherry picked from commit 74ca315197)
2018-08-31 19:53:52 +02:00
Sebastiaan Janssen 50b636e1c6 Add issue templates and updated PR template 2018-08-30 09:55:03 +02:00
Stephan cedf433bb0 U4-11599 - do not abort inst processing on error
(cherry picked from commit f2090e9fc7)
2018-08-27 08:47:11 +02:00
Sebastiaan Janssen 00c19e3830 Fixes U4-11598 Scheduling the content does not reload the page at the same time
(cherry picked from commit 46b0063921)
2018-08-27 06:56:50 +02:00
Steve Fawcett a5742dcd9a Fix: TinyMCE overlay was showing in front of login overlay
(cherry picked from commit 71d3c1112e)
2018-08-26 21:09:54 +02:00
Sebastiaan Janssen 63ee3c72c3 Merge branch 'dev-v7' into patch-v7 2018-08-26 17:53:13 +02:00
Simon Dingley fd2550cfe9 U4-11312 Provides a fallback AuditType value of AuditType.Custom for any legacy logHeader column values that cannot be parsed 2018-06-26 13:31:22 +02:00
Shannon 78c01801f8 fixes U4-11463 MembershipHelper is not working with basic auth on the initial request 2018-06-26 10:52:42 +10:00
Anders Bjerner ad99d164c9 U4-11477 Here we go again
https://github.com/umbraco/Umbraco-CMS/pull/2720#issuecomment-400106496
2018-06-25 23:58:25 +02:00
191 changed files with 3112 additions and 4169 deletions
@@ -94,14 +94,14 @@ function Get-UmbracoBuildEnv
}
# ensure we have node
$node = "$path\node-v8.12.0-win-x86"
$source = "http://nodejs.org/dist/v8.12.0/node-v8.12.0-win-x86.7z "
$node = "$path\node-v6.9.1-win-x86"
$source = "http://nodejs.org/dist/v6.9.1/node-v6.9.1-win-x86.7z"
if (-not (test-path $node))
{
Write-Host "Download Node..."
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"
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"
}
# 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.7, 2.0.0)" />
<dependency id="ClientDependency" version="[1.9.6, 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,7 +20,6 @@
<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:
https://our.umbraco.com/download/releases
http://our.umbraco.com/contribute/releases
- Umbraco
- Umbraco
View File
@@ -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 (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.
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.
![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))
@@ -12,7 +12,7 @@ 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
See: https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/docs/CONTRIBUTING.md
-->
+2 -3
View File
@@ -44,7 +44,6 @@ 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/.github/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/docs/CONTRIBUTING.md).
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).
To view existing issues, please visit [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

+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.13.0")]
[assembly: AssemblyInformationalVersion("7.13.0")]
[assembly: AssemblyFileVersion("7.12.2")]
[assembly: AssemblyInformationalVersion("7.12.2")]
@@ -202,4 +202,4 @@ namespace Umbraco.Core.Configuration
//TODO: Add other configurations here !
}
}
}
@@ -139,8 +139,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
internal CommaDelimitedConfigurationElement DisallowedUploadFiles
{
get { return GetOptionalDelimitedElement("disallowedUploadFiles", new[] {"ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd"}); }
}
}
[ConfigurationProperty("allowedUploadFiles")]
internal CommaDelimitedConfigurationElement AllowedUploadFiles
{
@@ -195,12 +195,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
get { return GetOptionalTextElement("loginBackgroundImage", string.Empty); }
}
[ConfigurationProperty("StripUdiAttributes")]
internal InnerTextConfigurationElement<bool> StripUdiAttributes
{
get { return GetOptionalTextElement("StripUdiAttributes", true); }
}
string IContentSection.NotificationEmailAddress
{
get { return Notifications.NotificationEmailAddress; }
@@ -319,8 +313,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
IEnumerable<string> IContentSection.DisallowedUploadFiles
{
get { return DisallowedUploadFiles; }
}
}
IEnumerable<string> IContentSection.AllowedUploadFiles
{
get { return AllowedUploadFiles; }
@@ -363,11 +357,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
string IContentSection.LoginBackgroundImage
{
get { return LoginBackgroundImage; }
}
bool IContentSection.StripUdiAttributes
{
get { return StripUdiAttributes; }
}
}
}
}
@@ -13,7 +13,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
IEnumerable<string> ImageTagAllowedAttributes { get; }
IEnumerable<IImagingAutoFillUploadField> ImageAutoFillProperties { get; }
string ScriptFolderPath { get; }
IEnumerable<string> ScriptFileTypes { get; }
@@ -75,8 +75,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
bool EnablePropertyValueConverters { get; }
string LoginBackgroundImage { get; }
bool StripUdiAttributes { get; }
}
}
}
@@ -8,8 +8,6 @@
bool DisableAlternativeTemplates { get; }
bool ValidateAlternativeTemplates { get; }
bool DisableFindContentByIdPath { get; }
bool DisableRedirectUrlTracking { get; }
@@ -1,5 +1,4 @@
using System;
using System.Configuration;
using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
@@ -22,13 +21,6 @@ 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.13.0");
private static readonly Version Version = new Version("7.12.2");
/// <summary>
/// Gets the current version of Umbraco.
+1 -6
View File
@@ -110,11 +110,6 @@ 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>
@@ -359,4 +354,4 @@ namespace Umbraco.Core
}
}
}
}
}
-1
View File
@@ -61,7 +61,6 @@
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";
+28 -29
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,20 +368,19 @@ 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
return new Size(Constants.Conventions.Media.DefaultSize, Constants.Conventions.Media.DefaultSize);
}
//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);
}
}
@@ -431,8 +430,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,7 +37,6 @@ namespace Umbraco.Core.IO
}
}
[Obsolete("This file is no longer used and should not be accessed!")]
public static string MetablogConfig
{
get
+16 -20
View File
@@ -2,7 +2,6 @@
using System.Drawing;
using System.IO;
using System.Text;
using Umbraco.Core.Media.TypeDetector;
namespace Umbraco.Core.Media.Exif
{
@@ -119,25 +118,22 @@ namespace Umbraco.Core.Media.Exif
/// <returns>The <see cref="ImageFile"/> created from the file.</returns>
public static ImageFile FromStream(Stream stream, Encoding encoding)
{
// 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 ();
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 ();
}
#endregion
}
@@ -17,9 +17,5 @@
/// The file is a TIFF File.
/// </summary>
TIFF,
/// <summary>
/// The file is a SVG File.
/// </summary>
SVG,
}
}
-37
View File
@@ -1,37 +0,0 @@
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();
}
}
}
@@ -1,14 +0,0 @@
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;
}
}
}
@@ -1,16 +0,0 @@
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;
}
}
}
@@ -1,24 +0,0 @@
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";
}
}
}
@@ -1,24 +0,0 @@
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,28 +102,6 @@ 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,20 +17,6 @@ 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>
+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>
public PropertyTags TagSupport
internal PropertyTags TagSupport
{
get { return _tagSupport; }
}
@@ -242,4 +242,4 @@ namespace Umbraco.Core.Models
return clone;
}
}
}
}
@@ -1,9 +1,9 @@
namespace Umbraco.Core.Models
{
public enum PropertyTagBehavior
internal 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>
public class PropertyTags
internal class PropertyTags
{
public PropertyTags()
{
@@ -33,4 +33,4 @@ namespace Umbraco.Core.Models
public IEnumerable<Tuple<string, string>> Tags { get; set; }
}
}
}
@@ -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",
@@ -1,7 +1,6 @@
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;
@@ -48,33 +47,43 @@ 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?.GetWhereClauses().ToArray();
var customFilterWheres = customFilter != null ? customFilter.GetWhereClauses().ToArray() : null;
var hasCustomFilter = customFilterWheres != null && customFilterWheres.Length > 0;
if (hasCustomFilter)
{
var filterSql = new Sql();
foreach (var filterClause in customFilterWheres)
{
filterSql.Append($"AND ({filterClause.Item1})", filterClause.Item2);
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;
}
translatedQuery = GetFilteredSqlForPagedResults(translatedQuery, filterSql, queryHasWhereClause);
translatedQuery = GetFilteredSqlForPagedResults(translatedQuery, filterSql);
}
if (auditTypeFilter.Length > 0)
{
var filterSql = new Sql();
foreach (var filterClause in auditTypeFilter)
{
filterSql.Append("AND (logHeader = @logHeader)", new { logHeader = filterClause.ToString() });
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;
}
translatedQuery = GetFilteredSqlForPagedResults(translatedQuery, filterSql, queryHasWhereClause || hasCustomFilter);
translatedQuery = GetFilteredSqlForPagedResults(translatedQuery, filterSql);
}
if (orderDirection == Direction.Descending)
@@ -90,7 +99,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 (var i = 0; i < pages.Length; i++)
for (int i = 0; i < pages.Length; i++)
{
pages[i].CreateDate = pagedResult.Items[i].Datestamp;
}
@@ -160,17 +169,14 @@ namespace Umbraco.Core.Persistence.Repositories
}
#endregion
private Sql GetFilteredSqlForPagedResults(Sql sql, Sql filterSql, bool hasWhereClause)
private Sql GetFilteredSqlForPagedResults(Sql sql, Sql filterSql)
{
Sql filteredSql;
// Apply filter
if (filterSql != null)
{
//ensure we don't append a WHERE if there is already one
var sqlFilter = hasWhereClause
? filterSql.SQL
: " WHERE " + filterSql.SQL.TrimStart("AND ");
var sqlFilter = " 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
@@ -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.InvariantEquals(toAssign)).NodeId;
var groupId = rolesForNames.First(x => x.Text == toAssign).NodeId;
Database.Insert(new Member2MemberGroupDto { Member = mId, MemberGroup = groupId });
}
}
@@ -4,7 +4,6 @@ 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;
@@ -711,10 +710,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");
@@ -722,23 +721,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($"AND ({filterClause.Item1})", filterClause.Item2);
filterSql.Append(string.Format("AND ({0})", filterClause.Item1), filterClause.Item2);
}
}
}
if (includeUserGroups != null && includeUserGroups.Length > 0)
{
const string subQuery = @"AND (umbracoUser.id IN (SELECT DISTINCT umbracoUser.id
var 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
@@ -748,21 +747,21 @@ ORDER BY colName";
if (excludeUserGroups != null && excludeUserGroups.Length > 0)
{
const string subQuery = @"AND (umbracoUser.id NOT IN (SELECT DISTINCT umbracoUser.id
var 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))
{
@@ -798,81 +797,67 @@ 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();
var sqlBaseFull = GetBaseQuery("umbracoUser.*, umbracoUserGroup.*, umbracoUserGroup2App.*, umbracoUserStartNode.*");
var translatorFull = new SqlTranslator<IUser>(sqlBaseFull, query);
//get sorted and filtered sql
var sqlQueryIds = translatorIds.Translate();
//get sorted and filtered sql
var sqlNodeIdsWithSort = GetSortedSqlForPagedResults(
GetFilteredSqlForPagedResults(sqlQueryIds, filterSql, queryHasWhereClause),
GetFilteredSqlForPagedResults(sqlQueryIds, filterSql),
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();
//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
var sqlQueryFull = GetBaseQuery("umbracoUser.*, umbracoUserGroup.*, umbracoUserGroup2App.*, umbracoUserStartNode.*");
var fullQueryWithPagedInnerJoin = sqlQueryFull
.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, queryHasWhereClause),
GetFilteredSqlForPagedResults(fullQueryWithPagedInnerJoin, filterSql),
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, bool hasWhereClause)
private Sql GetFilteredSqlForPagedResults(Sql sql, Sql filterSql)
{
Sql filteredSql;
// Apply filter
if (filterSql != null)
{
//ensure we don't append a WHERE if there is already one
var sqlFilter = hasWhereClause
? filterSql.SQL
: " WHERE " + filterSql.SQL.TrimStart("AND ");
var sqlFilter = " 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
@@ -290,9 +290,6 @@ 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
@@ -996,4 +993,4 @@ ORDER BY contentNodeId, versionId, propertytypeid
}
}
}
}
}
@@ -1,188 +1,189 @@
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'"; } }
}
}
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();
}
/// <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");
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");
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]
WHERE 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",
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'"; } }
}
}
@@ -1,10 +1,8 @@
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;
@@ -460,23 +458,5 @@ 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,8 +102,7 @@ namespace Umbraco.Core.Security
/// <returns/>
public override async Task ValidateIdentity(CookieValidateIdentityContext context)
{
//ensure the thread culture is set
context?.Identity?.EnsureCulture();
EnsureCulture(context);
await EnsureValidSessionId(context);
@@ -121,5 +120,21 @@ 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,10 +236,7 @@ namespace Umbraco.Core.Security
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<T, int>(dataProtectionProvider.Create("ASP.NET Identity"))
{
TokenLifespan = TimeSpan.FromDays(3)
};
manager.UserTokenProvider = new DataProtectorTokenProvider<T, int>(dataProtectionProvider.Create("ASP.NET Identity"));
}
manager.UserLockoutEnabledByDefault = true;
@@ -751,7 +748,6 @@ namespace Umbraco.Core.Security
var httpContext = HttpContext.Current == null ? (HttpContextBase)null : new HttpContextWrapper(HttpContext.Current);
return httpContext.GetCurrentRequestIpAddress();
}
}
}
@@ -630,9 +630,7 @@ namespace Umbraco.Core.Security
|| identityUser.LastLoginDateUtc.HasValue && user.LastLoginDate.ToUniversalTime() != identityUser.LastLoginDateUtc.Value)
{
anythingChanged = true;
//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;
user.LastLoginDate = identityUser.LastLoginDateUtc.Value.ToLocalTime();
}
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 short for the required key length for the algorithm, extend it
//if the salt bytes is too long 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
}
}
}
}
@@ -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,6 +89,7 @@ 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
@@ -96,11 +97,7 @@ namespace Umbraco.Core.Services
byte[] bytes;
try
{
if (_httpClient == null)
{
_httpClient = new HttpClient();
}
bytes = _httpClient.GetByteArrayAsync(url).GetAwaiter().GetResult();
bytes = httpClient.GetByteArrayAsync(url).GetAwaiter().GetResult();
}
catch (HttpRequestException ex)
{
@@ -1749,7 +1746,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 replica
// than one active server, then role is master or slave
_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;
}
}
}
}
-24
View File
@@ -1574,29 +1574,5 @@ 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;
}
}
}
+2 -2
View File
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Sync
Single = 1,
/// <summary>
/// In a multi-servers environment, the server is a replica server.
/// In a multi-servers environment, the server is a slave server.
/// </summary>
Slave = 2,
@@ -25,4 +25,4 @@ namespace Umbraco.Core.Sync
/// </summary>
Master = 3
}
}
}
+7 -12
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.7.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\ClientDependency.1.9.7\lib\net45\ClientDependency.Core.dll</HintPath>
<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>
<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,11 +365,6 @@
<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" />
@@ -572,8 +567,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" />
@@ -643,7 +638,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" />
@@ -1693,4 +1688,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.7" targetFramework="net45" />
<package id="ClientDependency" version="1.9.6" 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 replica servers
// other servers are slave 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 replica
// distributed call enabled, cannot find server, assume it's an undeclared slave
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,12 +23,6 @@ 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,46 +66,6 @@ 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()
{
@@ -123,24 +83,14 @@ namespace Umbraco.Tests.Persistence.Repositories
using (var repo = new AuditRepository(unitOfWork, CacheHelper, Logger, SqlSyntax))
{
try
{
DatabaseContext.Database.EnableSqlTrace = true;
DatabaseContext.Database.EnableSqlCount();
long total;
var page = repo.GetPagedResultsByQuery(Query<IAuditItem>.Builder, 0, 9, out total, Direction.Descending,
new[] {AuditType.Publish}, null)
.ToArray();
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();
}
Assert.AreEqual(9, page.Length);
Assert.IsTrue(page.All(x => x.AuditType == AuditType.Publish));
Assert.AreEqual(100, total);
}
}
@@ -161,25 +111,15 @@ namespace Umbraco.Tests.Persistence.Repositories
using (var repo = new AuditRepository(unitOfWork, CacheHelper, Logger, SqlSyntax))
{
try
{
DatabaseContext.Database.EnableSqlTrace = true;
DatabaseContext.Database.EnableSqlCount();
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();
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();
}
Assert.AreEqual(8, page.Length);
Assert.IsTrue(page.All(x => x.Comment == "Content created"));
Assert.AreEqual(100, total);
}
}
}
}
}
@@ -6,7 +6,6 @@ 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;
@@ -393,71 +392,7 @@ namespace Umbraco.Tests.Persistence.Repositories
var result = repository.Count(query);
// Assert
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();
}
Assert.That(result, Is.GreaterThanOrEqualTo(2));
}
}
@@ -504,4 +439,4 @@ namespace Umbraco.Tests.Persistence.Repositories
return new IUser[] { user1, user2, user3 };
}
}
}
}
@@ -288,29 +288,6 @@ 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()
{
@@ -1202,4 +1179,4 @@ namespace Umbraco.Tests.Services
}
}
}
}
-3
View File
@@ -65,9 +65,6 @@
<Reference Include="Examine, Version=0.1.89.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Examine.0.1.89\lib\net45\Examine.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>
</Reference>
<Reference Include="ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
@@ -1,6 +1,6 @@
using System;
using System.Linq;
using System.Web;
using HtmlAgilityPack;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
@@ -10,6 +10,7 @@ using Umbraco.Core.Models;
using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Profiling;
using Umbraco.Core.Scoping;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
using Umbraco.Web;
using Umbraco.Web.Routing;
@@ -33,14 +34,6 @@ namespace Umbraco.Tests.Web
[TestCase("hello href=\"{localLink:umb://document-type/9931BDE0AAC34BABB838909A7B47570E}\" world ", "hello href=\"/my-test-url\" world ")]
//this one has an invalid char so won't match
[TestCase("hello href=\"{localLink:umb^://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ", "hello href=\"{localLink:umb^://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\" world ")]
// with a-tag with data-udi attribute, that needs to be stripped
[TestCase("hello <a data-udi=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" href=\"{localLink:umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\"> world</a> ", "hello <a href=\"/my-test-url\"> world</a> ")]
// with a-tag with data-udi attribute spelled wrong, so don't need stripping
[TestCase("hello <a data-uid=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" href=\"{localLink:umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570E}\"> world</a> ", "hello <a data-uid=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" href=\"/my-test-url\"> world</a> ")]
// with a img-tag with data-udi id, that needs to be strippde
[TestCase("hello <img data-udi=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" src=\"imageofcats.jpg\"> world ", "hello <img src=\"imageofcats.jpg\"> world ")]
// with a img-tag with data-udi id spelled wrong, so don't need stripping
[TestCase("hello <img data-uid=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" src=\"imageofcats.jpg\"> world ", "hello <img data-uid=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" src=\"imageofcats.jpg\"> world ")]
public void ParseLocalLinks(string input, string result)
{
var serviceCtxMock = MockHelper.GetMockedServiceContext();
@@ -70,7 +63,7 @@ namespace Umbraco.Tests.Web
//setup a quick mock of the WebRouting section
Mock.Of<IUmbracoSettingsSection>(section => section.WebRouting == Mock.Of<IWebRoutingSection>(routingSection => routingSection.UrlProviderMode == "AutoLegacy")),
//pass in the custom url provider
new[] { testUrlProvider.Object },
new[]{ testUrlProvider.Object },
true))
{
var output = TemplateUtilities.ParseInternalLinks(input, umbCtx.UrlProvider);
@@ -78,27 +71,5 @@ namespace Umbraco.Tests.Web
Assert.AreEqual(result, output);
}
}
[Test]
public void StripDataUdiAttributesUsingSrtringOnLinks()
{
var input = "hello <a data-udi=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" href=\"/my-test-url\"> world</a> ";
var expected = "hello <a href=\"/my-test-url\"> world</a> ";
var result = TemplateUtilities.StripUdiDataAttributes(input);
Assert.AreEqual(expected, result);
}
[Test]
public void StripDataUdiAttributesUsingStringOnImages()
{
var input = "hello <img data-udi=\"umb://document-type/9931BDE0-AAC3-4BAB-B838-909A7B47570\" src=\"imageofcats.jpg\"> world ";
var expected = "hello <img src=\"imageofcats.jpg\"> world ";
var result = TemplateUtilities.StripUdiDataAttributes(input);
Assert.AreEqual(expected, result);
}
}
}
}
-1
View File
@@ -3,7 +3,6 @@
<package id="AutoMapper" version="3.3.1" targetFramework="net45" />
<package id="Castle.Core" version="4.0.0" targetFramework="net45" />
<package id="Examine" version="0.1.89" targetFramework="net45" />
<package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net45" />
<package id="log4net" version="2.0.8" targetFramework="net45" />
<package id="Log4Net.Async" version="2.0.4" targetFramework="net45" />
<package id="Lucene.Net" version="2.9.4.1" targetFramework="net45" />
File diff suppressed because one or more lines are too long
+15
View File
@@ -1,4 +1,19 @@
{
"author": "Umbraco HQ",
"name": "umbraco",
"homepage": "https://github.com/umbraco/umbraco-cms/",
"version": "7.1.2",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/umbraco/Umbraco-CMS.git"
},
"bugs": {
"url": "https://issues.umbraco.org"
},
"engines": {
"node": ">= 0.8.4"
},
"scripts": {
"install": "bower-installer",
"test": "karma start test/config/karma.conf.js --singlerun",
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="7.00:00:00" />
</staticContent>
</system.webServer>
</configuration>
@@ -1,7 +1,7 @@
(function () {
'use strict';
function ContentNodeInfoDirective($timeout, $location, logResource, eventsService, userService, localizationService, dateHelper, redirectUrlsResource) {
function ContentNodeInfoDirective($timeout, $location, logResource, eventsService, userService, localizationService, dateHelper) {
function link(scope, element, attrs, ctrl) {
@@ -46,9 +46,6 @@
// Make sure to set the node status
setNodePublishStatus(scope.node);
//default setting for redirect url management
scope.urlTrackerDisabled = false;
// Declare a fallback URL for the <umb-node-preview/> directive
if (scope.documentType !== null) {
scope.previewOpenUrl = '#/settings/documenttypes/edit/' + scope.documentType.id;
@@ -102,7 +99,7 @@
// get current backoffice user and format dates
userService.getCurrentUser().then(function (currentUser) {
angular.forEach(data.items, function (item) {
angular.forEach(data.items, function(item) {
item.timestampFormatted = dateHelper.getLocalDate(item.timestamp, currentUser.locale, 'LLL');
});
});
@@ -119,25 +116,6 @@
});
}
function loadRedirectUrls() {
scope.loadingRedirectUrls = true;
//check if Redirect Url Management is enabled
redirectUrlsResource.getEnableState().then(function (response) {
scope.urlTrackerDisabled = response.enabled !== true;
if (scope.urlTrackerDisabled === false) {
redirectUrlsResource.getRedirectsForContentItem(scope.node.udi)
.then(function (data) {
scope.redirectUrls = data.searchResults;
scope.hasRedirects = (typeof data.searchResults !== 'undefined' && data.searchResults.length > 0);
scope.loadingRedirectUrls = false;
});
}
else {
scope.loadingRedirectUrls = false;
}
});
}
function setAuditTrailLogTypeColor(auditTrail) {
angular.forEach(auditTrail, function (item) {
@@ -158,27 +136,27 @@
function setNodePublishStatus(node) {
// deleted node
if (node.trashed === true) {
if(node.trashed === true) {
scope.publishStatus.label = localizationService.localize("general_deleted");
scope.publishStatus.color = "danger";
}
// unpublished node
if (node.published === false && node.trashed === false) {
if(node.published === false && node.trashed === false) {
scope.publishStatus.label = localizationService.localize("content_unpublished");
scope.publishStatus.color = "gray";
}
// published node
if (node.hasPublishedVersion === true && node.publishDate && node.published === true) {
if(node.hasPublishedVersion === true && node.publishDate && node.published === true) {
scope.publishStatus.label = localizationService.localize("content_published");
scope.publishStatus.color = "success";
}
// published node with pending changes
if (node.hasPublishedVersion === true && node.publishDate && node.published === false) {
if(node.hasPublishedVersion === true && node.publishDate && node.published === false) {
scope.publishStatus.label = localizationService.localize("content_publishedPendingChanges");
scope.publishStatus.color = "success";
scope.publishStatus.color = "success"
}
}
@@ -274,13 +252,12 @@
});
}
// load audit trail and redirects when on the info tab
// load audit trail when on the info tab
evts.push(eventsService.on("app.tabChange", function (event, args) {
$timeout(function () {
$timeout(function(){
if (args.id === -1) {
isInfoTab = true;
loadAuditTrail();
loadRedirectUrls();
} else {
isInfoTab = false;
}
@@ -288,14 +265,13 @@
}));
// watch for content updates - reload content when node is saved, published etc.
scope.$watch('node.updateDate', function (newValue, oldValue) {
scope.$watch('node.updateDate', function(newValue, oldValue){
if (!newValue) { return; }
if (newValue === oldValue) { return; }
if(!newValue) { return; }
if(newValue === oldValue) { return; }
if(isInfoTab) {
loadAuditTrail();
loadRedirectUrls();
formatDatesToLocal();
setNodePublishStatus(scope.node);
}
@@ -11,36 +11,32 @@ function hexBgColor() {
restrict: "A",
link: function (scope, element, attr, formCtrl) {
// Only add inline hex background color if defined and not "true".
if (attr.hexBgInline === undefined || (attr.hexBgInline !== undefined && attr.hexBgInline === "true")) {
var origColor = null;
if (attr.hexBgOrig) {
// Set the orig based on the attribute if there is one.
origColor = attr.hexBgOrig;
}
attr.$observe("hexBgColor", function (newVal) {
if (newVal) {
if (!origColor) {
// Get the orig color before changing it.
origColor = element.css("border-color");
}
// Validate it - test with and without the leading hash.
if (/^([0-9a-f]{3}|[0-9a-f]{6})$/i.test(newVal)) {
element.css("background-color", "#" + newVal);
return;
}
if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(newVal)) {
element.css("background-color", newVal);
return;
}
}
element.css("background-color", origColor);
});
var origColor = null;
if (attr.hexBgOrig) {
//set the orig based on the attribute if there is one
origColor = attr.hexBgOrig;
}
attr.$observe("hexBgColor", function (newVal) {
if (newVal) {
if (!origColor) {
//get the orig color before changing it
origColor = element.css("border-color");
}
//validate it - test with and without the leading hash.
if (/^([0-9a-f]{3}|[0-9a-f]{6})$/i.test(newVal)) {
element.css("background-color", "#" + newVal);
return;
}
if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(newVal)) {
element.css("background-color", newVal);
return;
}
}
element.css("background-color", origColor);
});
}
};
}
angular.module('umbraco.directives').directive("hexBgColor", hexBgColor);
angular.module('umbraco.directives').directive("hexBgColor", hexBgColor);
@@ -14,7 +14,7 @@ angular.module("umbraco.directives")
scope: {
src: '=',
center: "=",
onImageLoaded: "&"
onImageLoaded: "="
},
link: function(scope, element, attrs) {
@@ -31,10 +31,10 @@ angular.module("umbraco.directives")
//elements
var $viewport = element.find(".viewport");
var $image = element.find("img");
var $overlay = element.find(".overlay");
var $overlay = element.find(".overlay");
scope.style = function () {
if (scope.dimensions.width <= 0) {
scope.style = function () {
if(scope.dimensions.width <= 0){
setDimensions();
}
@@ -45,28 +45,28 @@ angular.module("umbraco.directives")
};
scope.setFocalPoint = function(event) {
scope.$emit("imageFocalPointStart");
var offsetX = event.offsetX - 10;
var offsetY = event.offsetY - 10;
scope.$emit("imageFocalPointStart");
calculateGravity(offsetX, offsetY);
var offsetX = event.offsetX - 10;
var offsetY = event.offsetY - 10;
calculateGravity(offsetX, offsetY);
lazyEndEvent();
lazyEndEvent();
};
var setDimensions = function () {
if (scope.isCroppable) {
scope.dimensions.width = $image.width();
scope.dimensions.height = $image.height();
if(scope.center){
scope.dimensions.left = scope.center.left * scope.dimensions.width -10;
scope.dimensions.top = scope.center.top * scope.dimensions.height -10;
}else{
scope.center = { left: 0.5, top: 0.5 };
}
}
var setDimensions = function(){
scope.dimensions.width = $image.width();
scope.dimensions.height = $image.height();
if(scope.center){
scope.dimensions.left = scope.center.left * scope.dimensions.width -10;
scope.dimensions.top = scope.center.top * scope.dimensions.height -10;
}else{
scope.center = { left: 0.5, top: 0.5 };
}
};
var calculateGravity = function(offsetX, offsetY){
@@ -107,32 +107,10 @@ angular.module("umbraco.directives")
//// INIT /////
$image.load(function() {
$timeout(function() {
scope.isCroppable = true;
scope.hasDimensions = true;
if (scope.src !== "undefined") {
if (scope.src.endsWith(".svg")) {
scope.isCroppable = false;
scope.hasDimensions = false;
} else {
// From: https://stackoverflow.com/a/51789597/5018
var type = scope.src.substring(scope.src.indexOf("/") + 1, scope.src.indexOf(";base64"));
if (type.startsWith("svg")) {
scope.isCroppable = false;
scope.hasDimensions = false;
}
}
}
setDimensions();
scope.loaded = true;
if (angular.isFunction(scope.onImageLoaded)) {
scope.onImageLoaded(
{
"isCroppable": scope.isCroppable,
"hasDimensions": scope.hasDimensions
}
);
scope.onImageLoaded();
}
});
});
@@ -18,7 +18,7 @@
</example>
*/
angular.module("umbraco.directives")
.directive('umbTreeItem', function ($compile, $http, $templateCache, $interpolate, $log, $location, $rootScope, $window, treeService, $timeout, localizationService, appState) {
.directive('umbTreeItem', function ($compile, $http, $templateCache, $interpolate, $log, $location, $rootScope, $window, treeService, $timeout, localizationService) {
return {
restrict: 'E',
replace: true,
@@ -132,15 +132,7 @@ angular.module("umbraco.directives")
}
if (node.selected) {
css.push("umb-tree-node-checked");
}
//is this the current action node (this is not the same as the current selected node!)
var actionNode = appState.getMenuState("currentNode");
if(actionNode) {
if(actionNode.id === node.id) {
css.push("active");
}
}
}
return css.join(" ");
};
@@ -1,4 +1,5 @@
/**
/**
@ngdoc directive
@name umbraco.directives.directive:umbColorSwatches
@restrict E
@@ -14,10 +15,9 @@ Use this directive to generate color swatches to pick from.
</umb-color-swatches>
</pre>
@param {array} colors (<code>attribute</code>): The array of colors.
@param {string} colors (<code>attribute</code>): The array of colors.
@param {string} selectedColor (<code>attribute</code>): The selected color.
@param {string} size (<code>attribute</code>): The size (s, m).
@param {string} useLabel (<code>attribute</code>): Specify if labels should be used.
@param {string} useColorClass (<code>attribute</code>): Specify if color values are css classes.
@param {function} onSelect (<code>expression</code>): Callback function when the item is selected.
**/
@@ -28,11 +28,6 @@ Use this directive to generate color swatches to pick from.
function link(scope, el, attr, ctrl) {
// Set default to true if not defined
if (angular.isUndefined(scope.useColorClass)) {
scope.useColorClass = false;
}
scope.setColor = function (color) {
//scope.selectedColor({color: color });
scope.selectedColor = color;
@@ -52,9 +47,7 @@ Use this directive to generate color swatches to pick from.
colors: '=?',
size: '@',
selectedColor: '=',
onSelect: '&',
useLabel: '=',
useColorClass: '=?'
onSelect: '&'
},
link: link
};
@@ -125,14 +125,6 @@ Use this directive to generate a thumbnail grid of media items.
i--;
}
if (scope.includeSubFolders !== 'true') {
if (item.parentId !== parseInt(scope.currentFolderId)) {
scope.items.splice(i, 1);
i--;
}
}
}
if (scope.items.length > 0) {
@@ -315,9 +307,7 @@ Use this directive to generate a thumbnail grid of media items.
itemMaxHeight: "@",
itemMinWidth: "@",
itemMinHeight: "@",
onlyImages: "@",
includeSubFolders: "@",
currentFolderId: "@"
onlyImages: "@"
},
link: link
};
@@ -8,7 +8,7 @@
scope.search = "";
scope.miniListViews = [];
scope.breadcrumb = [];
var miniListViewsHistory = [];
var goingForward = true;
var skipAnimation = true;
@@ -60,13 +60,9 @@
entityResource.getPagedChildren(miniListView.node.id, scope.entityType, miniListView.pagination)
.then(function (data) {
// update children
miniListView.children = data.items;
_.each(miniListView.children, function(c) {
// child allowed by default
c.allowed = true;
// convert legacy icon for node
if(c.icon) {
c.icon = iconHelper.convertFromLegacyIcon(c.icon);
@@ -78,17 +74,6 @@
c.published = c.metaData.IsPublished;
}
}
// filter items if there is a filter and it's not advanced
// ** ignores advanced filter at the moment
if (scope.entityTypeFilter && !scope.entityTypeFilter.filterAdvanced) {
var a = scope.entityTypeFilter.filter.toLowerCase().replace(/\s/g, '').split(',');
var found = a.indexOf(c.metaData.ContentTypeAlias.toLowerCase()) >= 0;
if (!scope.entityTypeFilter.filterExclude && !found || scope.entityTypeFilter.filterExclude && found) {
c.allowed = false;
}
}
});
// update pagination
miniListView.pagination.totalItems = data.totalItems;
@@ -104,7 +89,7 @@
};
scope.selectNode = function(node) {
if (scope.onSelect && node.allowed) {
if(scope.onSelect) {
scope.onSelect({'node': node});
}
};
@@ -217,8 +202,7 @@
entityType: "@",
startNodeId: "=",
onSelect: "&",
onClose: "&",
entityTypeFilter: "="
onClose: "&"
},
link: link
};
@@ -50,11 +50,6 @@ Use this directive make an element sticky and follow the page when scrolling.
function activate() {
if (bar.parents(".umb-property").length > 1) {
bar.addClass("nested");
return;
}
if (attr.scrollableContainer) {
scrollableContainer = $(attr.scrollableContainer);
} else {
@@ -298,10 +298,10 @@ function contentTypeResource($q, $http, umbRequestHelper, umbDataFormatter) {
},
createCollection: function (parentId, collectionName, collectionCreateTemplate, collectionItemName, collectionItemCreateTemplate, collectionIcon, collectionItemIcon) {
createCollection: function (parentId, collectionName, collectionItemName, collectionIcon, collectionItemIcon) {
return umbRequestHelper.resourcePromise(
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostCreateCollection", { parentId: parentId, collectionName: collectionName, collectionCreateTemplate: collectionCreateTemplate, collectionItemName: collectionItemName, collectionItemCreateTemplate: collectionItemCreateTemplate, collectionIcon: collectionIcon, collectionItemIcon: collectionItemIcon})),
$http.post(umbRequestHelper.getApiUrl("contentTypeApiBaseUrl", "PostCreateCollection", { parentId: parentId, collectionName: collectionName, collectionItemName: collectionItemName, collectionIcon: collectionIcon, collectionItemIcon: collectionItemIcon})),
'Failed to create collection under ' + parentId);
},
@@ -7,60 +7,10 @@
**/
function logResource($q, $http, umbRequestHelper) {
function isValidDate(input) {
if (input) {
if (Object.prototype.toString.call(input) === "[object Date]" && !isNaN(input.getTime())) {
return true;
}
}
return false;
};
function dateToValidIsoString(input) {
if (isValidDate(input)) {
return input.toISOString();
}
return '';
};
//the factory object returned
return {
/**
* @ngdoc method
* @name umbraco.resources.logResource#getPagedEntityLog
* @methodOf umbraco.resources.logResource
*
* @description
* Gets a paginated log history for a entity
*
* ##usage
* <pre>
* var options = {
* id : 1234
* pageSize : 10,
* pageNumber : 1,
* orderDirection : "Descending",
* sinceDate : new Date(2018,0,1)
* };
* logResource.getPagedEntityLog(options)
* .then(function(log) {
* alert('its here!');
* });
* </pre>
*
* @param {Object} options options object
* @param {Int} options.id the id of the entity
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 10, set to 0 to disable paging
* @param {Int} options.pageNumber if paging data, current page index, default = 1
* @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Descending`
* @param {Date} options.sinceDate if provided this will only get log entries going back to this date
* @returns {Promise} resourcePromise object containing the log.
*
*/
getPagedEntityLog: function(options) {
getPagedEntityLog: function (options) {
var defaults = {
pageSize: 10,
@@ -74,21 +24,17 @@ function logResource($q, $http, umbRequestHelper) {
angular.extend(defaults, options);
//now copy back to the options we will use
options = defaults;
if (options.hasOwnProperty('sinceDate')) {
options.sinceDate = dateToValidIsoString(options.sinceDate);
}
//change asc/desct
if (options.orderDirection === "asc") {
options.orderDirection = "Ascending";
} else if (options.orderDirection === "desc") {
}
else if (options.orderDirection === "desc") {
options.orderDirection = "Descending";
}
if (options.id === undefined || options.id === null) {
throw "options.id is required";
}
}
return umbRequestHelper.resourcePromise(
$http.get(
@@ -99,37 +45,7 @@ function logResource($q, $http, umbRequestHelper) {
'Failed to retrieve log data for id');
},
/**
* @ngdoc method
* @name umbraco.resources.logResource#getPagedUserLog
* @methodOf umbraco.resources.logResource
*
* @description
* Gets a paginated log history for the current user
*
* ##usage
* <pre>
* var options = {
* pageSize : 10,
* pageNumber : 1,
* orderDirection : "Descending",
* sinceDate : new Date(2018,0,1)
* };
* logResource.getPagedUserLog(options)
* .then(function(log) {
* alert('its here!');
* });
* </pre>
*
* @param {Object} options options object
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 10, set to 0 to disable paging
* @param {Int} options.pageNumber if paging data, current page index, default = 1
* @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Descending`
* @param {Date} options.sinceDate if provided this will only get log entries going back to this date
* @returns {Promise} resourcePromise object containing the log.
*
*/
getPagedUserLog: function(options) {
getPagedUserLog: function (options) {
var defaults = {
pageSize: 10,
@@ -143,15 +59,11 @@ function logResource($q, $http, umbRequestHelper) {
angular.extend(defaults, options);
//now copy back to the options we will use
options = defaults;
if (options.hasOwnProperty('sinceDate')) {
options.sinceDate = dateToValidIsoString(options.sinceDate);
}
//change asc/desct
if (options.orderDirection === "asc") {
options.orderDirection = "Ascending";
} else if (options.orderDirection === "desc") {
}
else if (options.orderDirection === "desc") {
options.orderDirection = "Descending";
}
@@ -159,10 +71,10 @@ function logResource($q, $http, umbRequestHelper) {
$http.get(
umbRequestHelper.getApiUrl(
"logApiBaseUrl",
"GetPagedCurrentUserLog",
"GetPagedEntityLog",
options)),
'Failed to retrieve log data for id');
},
},
/**
* @ngdoc method
@@ -170,7 +82,6 @@ function logResource($q, $http, umbRequestHelper) {
* @methodOf umbraco.resources.logResource
*
* @description
* <strong>[OBSOLETE] use getPagedEntityLog instead</strong><br />
* Gets the log history for a give entity id
*
* ##usage
@@ -185,24 +96,23 @@ function logResource($q, $http, umbRequestHelper) {
* @returns {Promise} resourcePromise object containing the log.
*
*/
getEntityLog: function(id) {
getEntityLog: function (id) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"logApiBaseUrl",
"GetEntityLog",
[{ id: id }])),
'Failed to retrieve user data for id ' + id);
$http.get(
umbRequestHelper.getApiUrl(
"logApiBaseUrl",
"GetEntityLog",
[{ id: id }])),
'Failed to retrieve user data for id ' + id);
},
/**
* @ngdoc method
* @name umbraco.resources.logResource#getUserLog
* @methodOf umbraco.resources.logResource
*
* @description
* <strong>[OBSOLETE] use getPagedUserLog instead</strong><br />
* Gets the current user's log history for a given type of log entry
* Gets the current users' log history for a given type of log entry
*
* ##usage
* <pre>
@@ -217,14 +127,14 @@ function logResource($q, $http, umbRequestHelper) {
* @returns {Promise} resourcePromise object containing the log.
*
*/
getUserLog: function(type, since) {
getUserLog: function (type, since) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"logApiBaseUrl",
"GetCurrentUserLog",
[{ logtype: type }, { sinceDate: dateToValidIsoString(since) }])),
'Failed to retrieve log data for current user of type ' + type + ' since ' + since);
$http.get(
umbRequestHelper.getApiUrl(
"logApiBaseUrl",
"GetCurrentUserLog",
[{ logtype: type}, {sinceDate: since }])),
'Failed to retrieve log data for current user of type ' + type + ' since ' + since);
},
/**
@@ -248,16 +158,16 @@ function logResource($q, $http, umbRequestHelper) {
* @returns {Promise} resourcePromise object containing the log.
*
*/
getLog: function(type, since) {
getLog: function (type, since) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"logApiBaseUrl",
"GetLog",
[{ logtype: type }, { sinceDate: dateToValidIsoString(since) }])),
'Failed to retrieve log data of type ' + type + ' since ' + since);
}
};
$http.get(
umbRequestHelper.getApiUrl(
"logApiBaseUrl",
"GetLog",
[{ logtype: type}, {sinceDate: since }])),
'Failed to retrieve log data of type ' + type + ' since ' + since);
}
};
}
angular.module('umbraco.resources').factory('logResource', logResource);
@@ -40,32 +40,6 @@
{ searchTerm: searchTerm, page: pageIndex, pageSize: pageSize })),
'Failed to retrieve data for searching redirect urls');
}
/**
* @ngdoc function
* @name umbraco.resources.redirectUrlResource#getRedirectsForContentItem
* @methodOf umbraco.resources.redirectUrlResource
* @function
*
* @description
* Used to retrieve RedirectUrls for a specific item of content for Information tab
* ##usage
* <pre>
* redirectUrlsResource.getRedirectsForContentItem("udi:123456")
* .then(function(response) {
*
* });
* </pre>
* @param {String} contentUdi identifier for the content item to retrieve redirects for
*/
function getRedirectsForContentItem(contentUdi) {
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"redirectUrlManagementApiBaseUrl",
"RedirectUrlsForContentItem",
{ contentUdi: contentUdi })),
'Failed to retrieve redirects for content: ' + contentUdi);
}
function getEnableState() {
@@ -76,7 +50,7 @@
"GetEnableState")),
'Failed to retrieve data to check if the 301 redirect is enabled');
}
/**
* @ngdoc function
* @name umbraco.resources.redirectUrlResource#deleteRedirectUrl
@@ -133,8 +107,7 @@
searchRedirectUrls: searchRedirectUrls,
deleteRedirectUrl: deleteRedirectUrl,
toggleUrlTracker: toggleUrlTracker,
getEnableState: getEnableState,
getRedirectsForContentItem: getRedirectsForContentItem
getEnableState: getEnableState
};
return resource;
@@ -73,7 +73,6 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
appState.setSectionState("showSearchResults", false);
appState.setGlobalState("stickyNavigation", false);
appState.setGlobalState("showTray", false);
appState.setMenuState("currentNode", null);
if (appState.getGlobalState("isTablet") === true) {
appState.setGlobalState("showNavigation", false);
@@ -348,8 +347,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
if (appState.getGlobalState("isTablet") === true && !appState.getGlobalState("stickyNavigation")) {
//reset it to whatever is in the url
appState.setSectionState("currentSection", $routeParams.section);
appState.setSectionState("currentSection", $routeParams.section);
setMode("default-hidesectiontree");
}
@@ -143,6 +143,7 @@ angular.module('umbraco.services')
/** Called to update the current user's timeout */
function setUserTimeoutInternal(newTimeout) {
var asNumber = parseFloat(newTimeout);
if (!isNaN(asNumber) && currentUser && angular.isNumber(asNumber)) {
currentUser.remainingAuthSeconds = newTimeout;
@@ -150,29 +151,6 @@ angular.module('umbraco.services')
}
}
function getMomentLocales(locales, supportedLocales) {
var localeUrls = [];
var locales = locales.split(',');
for (var i = 0; i < locales.length; i++) {
var locale = locales[i].toString().toLowerCase();
if (locale !== 'en-us') {
if (supportedLocales.indexOf(locale + '.js') > -1) {
localeUrls.push('lib/moment/' + locale + '.js');
}
if (locale.indexOf('-') > -1) {
var majorLocale = locale.split('-')[0] + '.js';
if (supportedLocales.indexOf(majorLocale) > -1) {
localeUrls.push('lib/moment/' + majorLocale);
}
}
}
}
return localeUrls;
}
/** resets all user data, broadcasts the notAuthenticated event and shows the login dialog */
function userAuthExpired(isLogout) {
//store the last user id and clear the user
@@ -200,7 +178,7 @@ angular.module('umbraco.services')
}
});
var services = {
return {
/** Internal method to display the login dialog */
_showLoginDialog: function () {
@@ -301,32 +279,41 @@ angular.module('umbraco.services')
/** Loads the Moment.js Locale for the current user. */
loadMomentLocaleForCurrentUser: function () {
function loadLocales(currentUser, supportedLocales) {
var locale = currentUser.locale.toLowerCase();
if (locale !== 'en-us') {
var localeUrls = [];
if (supportedLocales.indexOf(locale + '.js') > -1) {
localeUrls.push('lib/moment/' + locale + '.js');
}
if (locale.indexOf('-') > -1) {
var majorLocale = locale.split('-')[0] + '.js';
if (supportedLocales.indexOf(majorLocale) > -1) {
localeUrls.push('lib/moment/' + majorLocale);
}
}
return assetsService.load(localeUrls, $rootScope);
}
else {
//return a noop promise
var deferred = $q.defer();
var promise = deferred.promise;
deferred.resolve(true);
return promise;
}
}
var promises = {
currentUser: this.getCurrentUser(),
supportedLocales: javascriptLibraryService.getSupportedLocalesForMoment()
}
return $q.all(promises).then(function (values) {
return services.loadLocales(values.currentUser.locale, values.supportedLocales);
return loadLocales(values.currentUser, values.supportedLocales);
});
},
/** Loads specific Moment.js Locales. */
loadLocales: function (locales, supportedLocales) {
var localeUrls = getMomentLocales(locales, supportedLocales);
if (localeUrls.length >= 1) {
return assetsService.load(localeUrls, $rootScope);
}
else {
//return a noop promise
var deferred = $q.defer();
var promise = deferred.promise;
deferred.resolve(true);
return promise;
}
},
/** Called whenever a server request is made that contains a x-umb-user-seconds response header for which we can update the user's remaining timeout seconds */
@@ -335,5 +322,4 @@ angular.module('umbraco.services')
}
};
return services;
});
@@ -126,7 +126,6 @@
@import "components/umb-querybuilder.less";
@import "components/umb-pagination.less";
@import "components/umb-mini-list-view.less";
@import "components/umb-multiple-textbox.less";
@import "components/umb-badge.less";
@import "components/umb-nested-content.less";
@import "components/umb-checkmark.less";
@@ -790,13 +790,13 @@ h4.panel-title {
}
.smartphone-portrait {
width: 360px;
height: 640px;
width: 320px;
height: 504px;
}
.smartphone-landscape {
width: 640px;
height: 360px;
width: 480px;
height: 256px;
}
.border {
@@ -97,6 +97,7 @@
text-align: center;
width: 100px;
height: 105px;
box-sizing: border-box;
}
@@ -114,7 +115,6 @@
width: 100%;
height: 100%;
border-radius: 3px;
padding-bottom: 5px;
}
@@ -1,18 +1,12 @@
.umb-editor-sub-header {
padding: 15px 0;
margin-bottom: 30px;
background: @white;
display: flex;
justify-content: space-between;
margin-top: -30px;
position: relative;
top: 0;
&.nested {
margin-top: 0;
margin-bottom: 0;
background: @gray-10;
}
padding: 15px 0;
margin-bottom: 30px;
background: @white;
display: flex;
justify-content: space-between;
margin-top: -30px;
position: relative;
top: 0;
}
.umb-editor-sub-header.-umb-sticky-bar {
@@ -10,7 +10,6 @@
.umb-prevalues-multivalues__left {
display: flex;
flex: 1 1 auto;
overflow: hidden;
}
.umb-prevalues-multivalues__right {
@@ -1,22 +1,18 @@
.umb-color-swatches {
display: flex;
flex-flow: row wrap;
.umb-color-box {
border: none;
color: white;
cursor: pointer;
padding: 1px;
padding: 5px;
text-align: center;
text-decoration: none;
display: inline-block;
margin: 5px;
border-radius: 3px;
width: 30px;
height: 30px;
transition: box-shadow .3s;
display: flex;
align-items: center;
justify-content: center;
&:hover, &:focus {
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
@@ -38,55 +34,4 @@
}
}
}
&.with-labels {
.umb-color-box {
width: 120px;
height: 100%;
display: flex;
flex-flow: row wrap;
.umb-color-box-inner {
display: flex;
flex-flow: column wrap;
flex: 0 0 100%;
max-width: 100%;
min-height: 80px;
padding-top: 10px;
.umb-color-box__label {
background: #fff;
font-size: 14px;
display: flex;
flex-flow: column wrap;
flex: 0 0 100%;
padding: 1px 5px;
max-width: 100%;
margin-top: auto;
margin-bottom: -3px;
margin-left: -1px;
margin-right: -1px;
text-indent: 0;
text-align: left;
border: 1px solid @gray-8;
border-bottom-left-radius: 3px;
border-bottom-right-radius: 3px;
overflow: hidden;
.umb-color-box__name {
color: @black;
font-weight: bold;
margin-top: 3px;
}
.umb-color-box__description {
font-size: 12px;
line-height: 1.5em;
color: @gray-3;
}
}
}
}
}
}
@@ -33,18 +33,6 @@
background-color: @gray-10;
}
.umb-media-grid__item-file-icon > span {
color: @white;
background: @gray-4;
padding: 1px 3px;
font-size: 10px;
line-height: 130%;
display: block;
margin-top: -30px;
margin-left: -10px;
position: relative;
}
.umb-media-grid__item.-selected {
box-shadow: 0 2px 8px 0 rgba(0,0,0,.35);
}
@@ -1,34 +0,0 @@
.umb-multiple-textbox .textbox-wrapper {
align-items: center;
margin-bottom: 15px;
}
.umb-multiple-textbox .textbox-wrapper .umb-editor {
margin-bottom: 0;
}
.umb-multiple-textbox .textbox-wrapper i {
margin-right: 5px;
}
.umb-multiple-textbox .textbox-wrapper i.handle {
margin-left: 5px;
}
.umb-multiple-textbox .textbox-wrapper a.remove {
margin-left: 5px;
text-decoration: none;
}
.umb-multiple-textbox .add-link {
&:extend(.umb-node-preview-add);
}
.umb-editor-wrapper .umb-multiple-textbox .add-link {
&:extend(.umb-editor-wrapper .umb-node-preview);
}
.umb-modal .umb-multiple-textbox .textbox-wrapper .umb-editor {
flex: 1 1 auto;
width: auto;
}
@@ -165,7 +165,7 @@ input.umb-table__input {
}
.-content :not(.with-unpublished-version).-unpublished {
.-content .-unpublished {
.umb-table__name > * {
opacity: .4;
}
@@ -157,10 +157,6 @@
/* TEMP */
.umb-minilistview {
.umb-table-row.not-allowed { opacity: 0.6; cursor: not-allowed; }
}
.umb-listview .table-striped tbody td {
position: relative
}
+9 -2
View File
@@ -119,8 +119,13 @@
// TABS
// ----
// Give the tabs something to sit on
.nav-tabs {
border-bottom: 1px solid @purple-l3;
}
// Make the list-items overlay the bottom border
.nav-tabs > li {
margin-bottom: -1px;
&.dropdown {
margin-bottom: -3px;
@@ -132,13 +137,11 @@
}
// Actual tabs (as links)
.nav-tabs > li > a {
position: relative;
color: @gray-3;
padding-top: 5px;
padding-bottom: 4px;
line-height: @baseLineHeight;
border: 1px solid transparent;
transform: translateY(1px);
&:hover {
color: @black;
@@ -180,6 +183,10 @@
.show-validation .nav-tabs > li.active.error > a:focus {
}
.umb-nav-tabs {
margin: -8px 0 0 0;
}
// PILLS
// -----
@@ -358,7 +358,6 @@
flex-direction: column;
height: 99px;
padding: 0 20px;
overflow-y: hidden;
}
.umb-panel-header-content {
@@ -437,8 +436,7 @@
}
.umb-panel-header .umb-nav-tabs {
bottom: 0;
margin: 0;
bottom: -1px;
}
input.umb-panel-header-name-input {
@@ -133,6 +133,33 @@ div.umb-codeeditor .umb-btn-toolbar {
//
// Color picker
// --------------------------------------------------
ul.color-picker li {
padding: 2px;
margin: 3px;
border: 2px solid transparent;
width: 60px;
&.active {
.check_circle {
opacity: 1;
}
}
.thumbnail{
min-width: auto;
width: inherit;
padding: 0;
}
a {
height: 50px;
display:flex;
align-items: center;
justify-content: center;
cursor:pointer;
margin: 0 0 5px;
}
}
/* pre-value editor */
.control-group.color-picker-preval {
@@ -153,7 +180,7 @@ div.umb-codeeditor .umb-btn-toolbar {
div.color-picker-prediv {
display: inline-flex;
align-items: center;
max-width: 85%;
max-width: 80%;
pre {
display: inline-flex;
@@ -336,30 +363,13 @@ div.umb-codeeditor .umb-btn-toolbar {
text-align: center;
}
.umb-sortable-thumbnails .umb-icon-holder .icon {
.umb-sortable-thumbnails .umb-icon-holder .icon{
font-size: 40px;
line-height: 50px;
color: @gray-3;
display: block;
}
.umb-sortable-thumbnails .umb-icon-holder .file-icon > span {
color: @white;
background: @gray-4;
padding: 1px 3px;
font-size: 10px;
line-height: 130%;
display: block;
margin-top: -30px;
width: 2em;
}
.umb-sortable-thumbnails .umb-icon-holder .file-icon + small {
display: block;
margin-top: 1em;
}
.umb-sortable-thumbnails .umb-sortable-thumbnails__wrapper {
width: 124px;
height: 124px;

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