Compare commits

..

7 Commits

Author SHA1 Message Date
Sebastiaan Jansssen 858156bab2 Merge branch 'dev-v7' into master-v7 2018-02-23 22:23:43 +01:00
Sebastiaan Jansssen 2ae96f3810 Merge branch 'dev-v7' into master-v7 2018-02-23 14:23:49 +01:00
Sebastiaan Jansssen a5f689385a Merge branch 'dev-v7' into master-v7 2018-02-19 17:13:35 +01:00
Sebastiaan Jansssen 1607e51270 Merge branch 'dev-v7' into master-v7 2018-02-19 14:21:16 +01:00
Sebastiaan Jansssen 044b43f6e1 Merge branch 'dev-v7' into master-v7 2018-02-19 14:10:09 +01:00
Sebastiaan Jansssen c59a226d56 Merge remote-tracking branch 'origin/dev-v7' into master-v7 2018-02-09 09:51:39 +01:00
Sebastiaan Jansssen 0c25c36af0 Bump version to 7.7.11 2018-02-09 09:46:05 +01:00
471 changed files with 4436 additions and 15332 deletions
+1 -2
View File
@@ -139,5 +139,4 @@ src/PrecompiledWeb/*
build.out/
build.tmp/
build/Modules/*/temp/
/src/.idea/*
build/Modules/*/temp/
@@ -44,7 +44,7 @@ function Build-UmbracoDocs
# change baseUrl
$baseUrl = "https://our.umbraco.org/apidocs/ui/"
$indexPath = "$src/Umbraco.Web.UI.Client/docs/api/index.html"
(Get-Content $indexPath).Replace("origin + location.href.substr(origin.length).replace(rUrl, indexFile)", "'$baseUrl'") `
(Get-Content $indexPath).Replace("location.href.replace(rUrl, indexFile)", "'$baseUrl'") `
| Set-Content $indexPath
# restore
@@ -100,9 +100,8 @@ function Get-DocFx($uenv, $buildTemp)
$docFx = "$buildTemp\docfx"
if (-not (test-path $docFx))
{
Write-Host "Download DocFx..."
$source = "https://github.com/dotnet/docfx/releases/download/v2.19.2/docfx.zip"
Write-Host "Download DocFx from $source"
Invoke-WebRequest $source -OutFile "$buildTemp\docfx.zip"
&$uenv.Zip x "$buildTemp\docfx.zip" -o"$buildTemp\docfx" -aos > $nul
+1
View File
@@ -27,6 +27,7 @@
<dependency id="MiniProfiler" version="[2.1.0, 3.0.0)" />
<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="SharpZipLib" version="[0.86.0, 1.0.0)" />
<dependency id="MySql.Data" version="[6.9.9, 7.0.0)" />
<dependency id="ClientDependency" version="[1.9.6, 2.0.0)" />
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
-1
View File
@@ -32,7 +32,6 @@
<file src="$BuildTmp$\WebApp\bin\amd64\**" target="UmbracoFiles\bin\amd64" />
<file src="$BuildTmp$\WebApp\bin\x86\**" target="UmbracoFiles\bin\x86" />
<file src="$BuildTmp$\WebApp\config\splashes\**" target="UmbracoFiles\Config\splashes" />
<file src="$BuildTmp$\WebApp\config\BackOfficeTours\**" target="Content\Config\BackOfficeTours" />
<file src="$BuildTmp$\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
<file src="$BuildTmp$\WebApp\umbraco_client\**" target="UmbracoFiles\umbraco_client" />
<file src="$BuildTmp$\WebApp\Media\Web.config" target="Content\Media\Web.config" />
-41
View File
@@ -98,51 +98,10 @@ if ($project) {
$umbracoUIXMLDestination = Join-Path $projectPath "Umbraco\Config\Create\UI.xml"
Copy-Item $umbracoUIXMLSource $umbracoUIXMLDestination -Force
} else {
# This part only runs for upgrades
$upgradeViewSource = Join-Path $umbracoFolderSource "Views\install\*"
$upgradeView = Join-Path $umbracoFolder "Views\install\"
Write-Host "Copying2 ${upgradeViewSource} to ${upgradeView}"
Copy-Item $upgradeViewSource $upgradeView -Force
Try
{
# Disable tours for upgrades, presumably Umbraco experience is already available
$umbracoSettingsConfigPath = Join-Path $configFolder "umbracoSettings.config"
$content = (Get-Content $umbracoSettingsConfigPath).Replace('<tours enable="true">','<tours enable="false">')
# Saves with UTF-8 encoding without BOM which makes sure Umbraco can still read it
# Reference: https://stackoverflow.com/a/32951824/5018
[IO.File]::WriteAllLines($umbracoSettingsConfigPath, $content)
}
Catch
{
# Not a big problem if this fails, let it go
}
Try
{
$uiXmlConfigPath = Join-Path $umbracoFolder -ChildPath "Config" | Join-Path -ChildPath "create" | Join-Path -ChildPath "UI.xml"
$uiXmlFile = Join-Path $umbracoFolder -ChildPath "Config" | Join-Path -ChildPath "create" | Join-Path -ChildPath "UI.xml"
$uiXml = New-Object System.Xml.XmlDocument
$uiXml.PreserveWhitespace = $true
$uiXml.Load($uiXmlFile)
$createExists = $uiXml.SelectNodes("//nodeType[@alias='macros']/tasks/create")
if($createExists.Count -eq 0)
{
$macrosTasksNode = $uiXml.SelectNodes("//nodeType[@alias='macros']/tasks")
#Creating: <create assembly="umbraco" type="macroTasks" />
$createNode = $uiXml.CreateElement("create")
$createNode.SetAttribute("assembly", "umbraco")
$createNode.SetAttribute("type", "macroTasks")
$macrosTasksNode.AppendChild($createNode)
$uiXml.Save($uiXmlFile)
}
}
Catch { }
}
$installFolder = Join-Path $projectPath "Install"
+3 -3
View File
@@ -79,14 +79,14 @@
<add sortOrder="1" alias="dataTypes" application="developer"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes(sortOrder)" />
<add initialize="true" sortOrder="2" alias="macros" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MacroTreeController, umbraco"
<add application="developer" alias="macros" title="Macros" type="umbraco.loadMacros, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="2"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add application="developer" alias="relationTypes" title="Relation Types" type="umbraco.loadRelationTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
<add initialize="true" sortOrder="5" alias="xslt" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.XsltTreeController, umbraco"
<add application="developer" alias="xslt" title="XSLT Files" type="umbraco.loadXslt, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="5"
xdt:Locator="Match(application,alias)"
xdt:Transform="SetAttributes()" />
+1 -1
View File
@@ -2,6 +2,6 @@
<configuration>
<packageSources>
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
<add key="umbracocore" value="https://www.myget.org/F/umbracocore/api/v3/index.json" />
<add key="umbracocore" value="http://www.myget.org/f/umbracocore/" />
</packageSources>
</configuration>
+2 -2
View File
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("7.9.0")]
[assembly: AssemblyInformationalVersion("7.9.0")]
[assembly: AssemblyFileVersion("7.7.13")]
[assembly: AssemblyInformationalVersion("7.7.13")]
-47
View File
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Configuration;
using System.Threading;
using Semver;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.ObjectResolution;
@@ -355,52 +354,6 @@ namespace Umbraco.Core
}
}
/// <summary>
/// Gets the Current Version of the Umbraco Site before an upgrade
/// by using the last/most recent Umbraco Migration that has been run
/// </summary>
/// <returns>A SemVersion of the latest Umbraco DB Migration run</returns>
/// <remarks>
/// NOTE: This existed in the InstallHelper previously but should really be here so it can be re-used if necessary
/// </remarks>
internal SemVersion CurrentVersion()
{
//Set a default version of 0.0.0
var version = new SemVersion(0);
//If we have a db context available, if we don't then we are not installed anyways
if (DatabaseContext.IsDatabaseConfigured && DatabaseContext.CanConnect)
version = DatabaseContext.ValidateDatabaseSchema().DetermineInstalledVersionByMigrations(Services.MigrationEntryService);
if (version != new SemVersion(0))
return version;
// If we aren't able to get a result from the umbracoMigrations table then use the version in web.config, if it's available
if (string.IsNullOrWhiteSpace(GlobalSettings.ConfigurationStatus))
return version;
var configuredVersion = GlobalSettings.ConfigurationStatus;
string currentComment = null;
var current = configuredVersion.Split('-');
if (current.Length > 1)
currentComment = current[1];
Version currentVersion;
if (Version.TryParse(current[0], out currentVersion))
{
version = new SemVersion(
currentVersion.Major,
currentVersion.Minor,
currentVersion.Build,
string.IsNullOrWhiteSpace(currentComment) ? null : currentComment,
currentVersion.Revision > 0 ? currentVersion.Revision.ToString() : null);
}
return version;
}
private void AssertIsNotReady()
{
if (this.IsReady)
@@ -1,351 +0,0 @@
using System;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
namespace Umbraco.Core.Auditing
{
public sealed class AuditEventHandler : ApplicationEventHandler
{
private IAuditService _auditServiceInstance;
private IUserService _userServiceInstance;
private IEntityService _entityServiceInstance;
private IUser CurrentPerformingUser
{
get
{
var identity = Thread.CurrentPrincipal?.GetUmbracoIdentity();
return identity == null
? new User { Id = 0, Name = "SYSTEM", Email = "" }
: _userServiceInstance.GetUserById(Convert.ToInt32(identity.Id));
}
}
private IUser GetPerformingUser(int userId)
{
var found = userId >= 0 ? _userServiceInstance.GetUserById(userId) : null;
return found ?? new User {Id = 0, Name = "SYSTEM", Email = ""};
}
private string PerformingIp
{
get
{
var httpContext = HttpContext.Current == null ? (HttpContextBase) null : new HttpContextWrapper(HttpContext.Current);
var ip = httpContext.GetCurrentRequestIpAddress();
if (ip.ToLowerInvariant().StartsWith("unknown")) ip = "";
return ip;
}
}
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
_auditServiceInstance = applicationContext.Services.AuditService;
_userServiceInstance = applicationContext.Services.UserService;
_entityServiceInstance = applicationContext.Services.EntityService;
//BackOfficeUserManager.AccountLocked += ;
//BackOfficeUserManager.AccountUnlocked += ;
BackOfficeUserManager.ForgotPasswordRequested += OnForgotPasswordRequest;
BackOfficeUserManager.ForgotPasswordChangedSuccess += OnForgotPasswordChange;
BackOfficeUserManager.LoginFailed += OnLoginFailed;
//BackOfficeUserManager.LoginRequiresVerification += ;
BackOfficeUserManager.LoginSuccess += OnLoginSuccess;
BackOfficeUserManager.LogoutSuccess += OnLogoutSuccess;
BackOfficeUserManager.PasswordChanged += OnPasswordChanged;
BackOfficeUserManager.PasswordReset += OnPasswordReset;
//BackOfficeUserManager.ResetAccessFailedCount += ;
UserService.SavedUserGroup2 += OnSavedUserGroupWithUsers;
UserService.SavedUser += OnSavedUser;
UserService.DeletedUser += OnDeletedUser;
UserService.UserGroupPermissionsAssigned += UserGroupPermissionAssigned;
MemberService.Saved += OnSavedMember;
MemberService.Deleted += OnDeletedMember;
MemberService.AssignedRoles += OnAssignedRoles;
MemberService.RemovedRoles += OnRemovedRoles;
MemberService.Exported += OnMemberExported;
}
private string FormatEmail(IMember member)
{
return member == null ? string.Empty : member.Email.IsNullOrWhiteSpace() ? "" : $"<{member.Email}>";
}
private string FormatEmail(IUser user)
{
return user == null ? string.Empty : user.Email.IsNullOrWhiteSpace() ? "" : $"<{user.Email}>";
}
private void OnRemovedRoles(IMemberService sender, RolesEventArgs args)
{
var performingUser = CurrentPerformingUser;
var roles = string.Join(", ", args.Roles);
var members = sender.GetAllMembers(args.MemberIds).ToDictionary(x => x.Id, x => x);
foreach (var id in args.MemberIds)
{
members.TryGetValue(id, out var member);
_auditServiceInstance.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
-1, $"Member {id} \"{member?.Name ?? "(unknown)"}\" {FormatEmail(member)}",
"umbraco/member/roles/removed", $"roles modified, removed {roles}");
}
}
private void OnAssignedRoles(IMemberService sender, RolesEventArgs args)
{
var performingUser = CurrentPerformingUser;
var roles = string.Join(", ", args.Roles);
var members = sender.GetAllMembers(args.MemberIds).ToDictionary(x => x.Id, x => x);
foreach (var id in args.MemberIds)
{
members.TryGetValue(id, out var member);
_auditServiceInstance.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
-1, $"Member {id} \"{member?.Name ?? "(unknown)"}\" {FormatEmail(member)}",
"umbraco/member/roles/assigned", $"roles modified, assigned {roles}");
}
}
private void OnMemberExported(IMemberService sender, ExportedMemberEventArgs exportedMemberEventArgs)
{
var performingUser = CurrentPerformingUser;
var member = exportedMemberEventArgs.Member;
_auditServiceInstance.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
-1, $"Member {member.Id} \"{member.Name}\" {FormatEmail(member)}",
"umbraco/member/exported", "exported member data");
}
private void OnSavedUserGroupWithUsers(IUserService sender, SaveEventArgs<UserGroupWithUsers> saveEventArgs)
{
var performingUser = CurrentPerformingUser;
foreach (var groupWithUser in saveEventArgs.SavedEntities)
{
var group = groupWithUser.UserGroup;
var dp = string.Join(", ", ((UserGroup)group).GetPreviouslyDirtyProperties());
var sections = ((UserGroup)group).WasPropertyDirty("AllowedSections")
? string.Join(", ", group.AllowedSections)
: null;
var perms = ((UserGroup)group).WasPropertyDirty("Permissions")
? string.Join(", ", group.Permissions)
: null;
var sb = new StringBuilder();
sb.Append($"updating {(string.IsNullOrWhiteSpace(dp) ? "(nothing)" : dp)};");
if (sections != null)
sb.Append($", assigned sections: {sections}");
if (perms != null)
{
if (sections != null)
sb.Append(", ");
sb.Append($"default perms: {perms}");
}
_auditServiceInstance.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
-1, $"User Group {group.Id} \"{group.Name}\" ({group.Alias})",
"umbraco/user-group/save", $"{sb}");
// now audit the users that have changed
foreach (var user in groupWithUser.RemovedUsers)
{
_auditServiceInstance.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
user.Id, $"User \"{user.Name}\" {FormatEmail(user)}",
"umbraco/user-group/save", $"Removed user \"{user.Name}\" {FormatEmail(user)} from group {group.Id} \"{group.Name}\" ({group.Alias})");
}
foreach (var user in groupWithUser.AddedUsers)
{
_auditServiceInstance.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
user.Id, $"User \"{user.Name}\" {FormatEmail(user)}",
"umbraco/user-group/save", $"Added user \"{user.Name}\" {FormatEmail(user)} to group {group.Id} \"{group.Name}\" ({group.Alias})");
}
}
}
private void UserGroupPermissionAssigned(IUserService sender, SaveEventArgs<EntityPermission> saveEventArgs)
{
var performingUser = CurrentPerformingUser;
var perms = saveEventArgs.SavedEntities;
foreach (var perm in perms)
{
var group = sender.GetUserGroupById(perm.UserGroupId);
var assigned = string.Join(", ", perm.AssignedPermissions);
var entity = _entityServiceInstance.Get(perm.EntityId);
_auditServiceInstance.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
-1, $"User Group {group.Id} \"{group.Name}\" ({group.Alias})",
"umbraco/user-group/permissions-change", $"assigning {(string.IsNullOrWhiteSpace(assigned) ? "(nothing)" : assigned)} on id:{perm.EntityId} \"{entity.Name}\"");
}
}
private void OnSavedMember(IMemberService sender, SaveEventArgs<IMember> saveEventArgs)
{
var performingUser = CurrentPerformingUser;
var members = saveEventArgs.SavedEntities;
foreach (var member in members)
{
var dp = string.Join(", ", ((Member) member).GetPreviouslyDirtyProperties());
_auditServiceInstance.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
-1, $"Member {member.Id} \"{member.Name}\" {FormatEmail(member)}",
"umbraco/member/save", $"updating {(string.IsNullOrWhiteSpace(dp) ? "(nothing)" : dp)}");
}
}
private void OnDeletedMember(IMemberService sender, DeleteEventArgs<IMember> deleteEventArgs)
{
var performingUser = CurrentPerformingUser;
var members = deleteEventArgs.DeletedEntities;
foreach (var member in members)
{
_auditServiceInstance.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
-1, $"Member {member.Id} \"{member.Name}\" {FormatEmail(member)}",
"umbraco/member/delete", $"delete member id:{member.Id} \"{member.Name}\" {FormatEmail(member)}");
}
}
private void OnSavedUser(IUserService sender, SaveEventArgs<IUser> saveEventArgs)
{
var performingUser = CurrentPerformingUser;
var affectedUsers = saveEventArgs.SavedEntities;
foreach (var affectedUser in affectedUsers)
{
var groups = affectedUser.WasPropertyDirty("Groups")
? string.Join(", ", affectedUser.Groups.Select(x => x.Alias))
: null;
var dp = string.Join(", ", ((User)affectedUser).GetPreviouslyDirtyProperties());
_auditServiceInstance.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
affectedUser.Id, $"User \"{affectedUser.Name}\" {FormatEmail(affectedUser)}",
"umbraco/user/save", $"updating {(string.IsNullOrWhiteSpace(dp) ? "(nothing)" : dp)}{(groups == null ? "" : "; groups assigned: " + groups)}");
}
}
private void OnDeletedUser(IUserService sender, DeleteEventArgs<IUser> deleteEventArgs)
{
var performingUser = CurrentPerformingUser;
var affectedUsers = deleteEventArgs.DeletedEntities;
foreach (var affectedUser in affectedUsers)
_auditServiceInstance.Write(performingUser.Id, $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}", PerformingIp,
DateTime.UtcNow,
affectedUser.Id, $"User \"{affectedUser.Name}\" {FormatEmail(affectedUser)}",
"umbraco/user/delete", "delete user");
}
private void OnLoginSuccess(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs)
{
var performingUser = GetPerformingUser(identityArgs.PerformingUser);
WriteAudit(performingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/sign-in/login", "login success");
}
}
private void OnLogoutSuccess(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs)
{
var performingUser = GetPerformingUser(identityArgs.PerformingUser);
WriteAudit(performingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/sign-in/logout", "logout success");
}
}
private void OnPasswordReset(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
{
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/reset", "password reset");
}
}
private void OnPasswordChanged(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
{
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/change", "password change");
}
}
private void OnLoginFailed(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
{
WriteAudit(identityArgs.PerformingUser, 0, identityArgs.IpAddress, "umbraco/user/sign-in/failed", "login failed", affectedDetails: "");
}
}
private void OnForgotPasswordChange(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
{
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/forgot/change", "password forgot/change");
}
}
private void OnForgotPasswordRequest(object sender, EventArgs args)
{
if (args is IdentityAuditEventArgs identityArgs && identityArgs.PerformingUser >= 0)
{
WriteAudit(identityArgs.PerformingUser, identityArgs.AffectedUser, identityArgs.IpAddress, "umbraco/user/password/forgot/request", "password forgot/request");
}
}
private void WriteAudit(int performingId, int affectedId, string ipAddress, string eventType, string eventDetails, string affectedDetails = null)
{
var performingUser = _userServiceInstance.GetUserById(performingId);
var performingDetails = performingUser == null
? $"User UNKNOWN:{performingId}"
: $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}";
WriteAudit(performingId, performingDetails, affectedId, ipAddress, eventType, eventDetails, affectedDetails);
}
private void WriteAudit(IUser performingUser, int affectedId, string ipAddress, string eventType, string eventDetails)
{
var performingDetails = performingUser == null
? $"User UNKNOWN"
: $"User \"{performingUser.Name}\" {FormatEmail(performingUser)}";
WriteAudit(performingUser?.Id ?? 0, performingDetails, affectedId, ipAddress, eventType, eventDetails);
}
private void WriteAudit(int performingId, string performingDetails, int affectedId, string ipAddress, string eventType, string eventDetails, string affectedDetails = null)
{
if (affectedDetails == null)
{
var affectedUser = _userServiceInstance.GetUserById(affectedId);
affectedDetails = affectedUser == null
? $"User UNKNOWN:{affectedId}"
: $"User \"{affectedUser.Name}\" {FormatEmail(affectedUser)}";
}
_auditServiceInstance.Write(performingId, performingDetails,
ipAddress,
DateTime.UtcNow,
affectedId, affectedDetails,
eventType, eventDetails);
}
}
}
@@ -1,5 +1,4 @@
using System;
using System.ComponentModel;
using System.Threading;
using System.Web;
using Umbraco.Core.Security;
@@ -46,8 +45,12 @@ namespace Umbraco.Core.Auditing
/// </summary>
public string Username { get; private set; }
[Obsolete("Use the method that has the affectedUser parameter instead")]
[EditorBrowsable(EditorBrowsableState.Never)]
/// <summary>
/// Sets the properties on the event being raised, all parameters are optional except for the action being performed
/// </summary>
/// <param name="action">An action based on the AuditEvent enum</param>
/// <param name="ipAddress">The client's IP address. This is usually automatically set but could be overridden if necessary</param>
/// <param name="performingUser">The Id of the user performing the action (if different from the user affected by the action)</param>
public IdentityAuditEventArgs(AuditEvent action, string ipAddress, int performingUser = -1)
{
DateTimeUtc = DateTime.UtcNow;
@@ -60,35 +63,6 @@ namespace Umbraco.Core.Auditing
: performingUser;
}
/// <summary>
/// Default constructor
/// </summary>
/// <param name="action"></param>
/// <param name="ipAddress"></param>
/// <param name="comment"></param>
/// <param name="performingUser"></param>
/// <param name="affectedUser"></param>
public IdentityAuditEventArgs(AuditEvent action, string ipAddress, string comment = null, int performingUser = -1, int affectedUser = -1)
{
DateTimeUtc = DateTime.UtcNow;
Action = action;
IpAddress = ipAddress;
Comment = comment;
AffectedUser = affectedUser;
PerformingUser = performingUser == -1
? GetCurrentRequestBackofficeUserId()
: performingUser;
}
/// <summary>
/// Creates an instance without a performing or affected user (the id will be set to -1)
/// </summary>
/// <param name="action"></param>
/// <param name="ipAddress"></param>
/// <param name="username"></param>
/// <param name="comment"></param>
public IdentityAuditEventArgs(AuditEvent action, string ipAddress, string username, string comment)
{
DateTimeUtc = DateTime.UtcNow;
@@ -97,22 +71,6 @@ namespace Umbraco.Core.Auditing
IpAddress = ipAddress;
Username = username;
Comment = comment;
PerformingUser = -1;
}
public IdentityAuditEventArgs(AuditEvent action, string ipAddress, string username, string comment, int performingUser)
{
DateTimeUtc = DateTime.UtcNow;
Action = action;
IpAddress = ipAddress;
Username = username;
Comment = comment;
PerformingUser = performingUser == -1
? GetCurrentRequestBackofficeUserId()
: performingUser;
}
/// <summary>
@@ -146,7 +146,7 @@ namespace Umbraco.Core.Cache
#region Insert
#endregion
private class NoopLocker : DisposableObjectSlim
private class NoopLocker : DisposableObject
{
protected override void DisposeResources()
{ }
-33
View File
@@ -1,33 +0,0 @@
using System;
using System.Collections.Generic;
namespace Umbraco.Core.Collections
{
/// <summary>
/// Represents a list of types.
/// </summary>
/// <remarks>Types in the list are, or derive from, or implement, the base type.</remarks>
/// <typeparam name="TBase">The base type.</typeparam>
internal class TypeList<TBase>
{
private readonly List<Type> _list = new List<Type>();
/// <summary>
/// Adds a type to the list.
/// </summary>
/// <typeparam name="T">The type to add.</typeparam>
public void Add<T>()
where T : TBase
{
_list.Add(typeof(T));
}
/// <summary>
/// Determines whether a type is in the list.
/// </summary>
public bool Contains(Type type)
{
return _list.Contains(type);
}
}
}
@@ -1,18 +0,0 @@
using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class BackOfficeElement : UmbracoConfigurationElement, IBackOfficeSection
{
[ConfigurationProperty("tours")]
internal TourConfigElement Tours
{
get { return (TourConfigElement)this["tours"]; }
}
ITourSection IBackOfficeSection.Tours
{
get { return Tours; }
}
}
}
@@ -1,7 +0,0 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public interface IBackOfficeSection
{
ITourSection Tours { get; }
}
}
@@ -1,7 +0,0 @@
namespace Umbraco.Core.Configuration.UmbracoSettings
{
public interface ITourSection
{
bool EnableTours { get; }
}
}
@@ -5,8 +5,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
{
public interface IUmbracoSettingsSection : IUmbracoConfigurationSection
{
IBackOfficeSection BackOffice { get; }
IContentSection Content { get; }
ISecuritySection Security { get; }
@@ -1,17 +0,0 @@
using System.Configuration;
namespace Umbraco.Core.Configuration.UmbracoSettings
{
internal class TourConfigElement : UmbracoConfigurationElement, ITourSection
{
//disabled by default so that upgraders don't get it enabled by default
//TODO: we probably just want to disable the initial one from automatically loading ?
[ConfigurationProperty("enable", DefaultValue = false)]
public bool EnableTours
{
get { return (bool)this["enable"]; }
}
//TODO: We could have additional filters, etc... defined here
}
}
@@ -8,12 +8,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
public class UmbracoSettingsSection : ConfigurationSection, IUmbracoSettingsSection
{
[ConfigurationProperty("backOffice")]
internal BackOfficeElement BackOffice
{
get { return (BackOfficeElement)this["backOffice"]; }
}
[ConfigurationProperty("content")]
internal ContentElement Content
{
@@ -155,11 +149,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
get { return Templates; }
}
IBackOfficeSection IUmbracoSettingsSection.BackOffice
{
get { return BackOffice; }
}
IDeveloperSection IUmbracoSettingsSection.Developer
{
get { return Developer; }
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
private static readonly Version Version = new Version("7.9.0");
private static readonly Version Version = new Version("7.7.13");
/// <summary>
/// Gets the current version of Umbraco.
@@ -73,11 +73,6 @@
/// </summary>
public const string Media = "media";
/// <summary>
/// alias for the macro tree.
/// </summary>
public const string Macros = "macros";
/// <summary>
/// alias for the datatype tree.
/// </summary>
+1 -2
View File
@@ -9,7 +9,6 @@ namespace Umbraco.Core
{
public const string AdminGroupAlias = "admin";
public const string SensitiveDataGroupAlias = "sensitiveData";
public const string TranslatorGroupAlias = "translator";
public const string BackOfficeAuthenticationType = "UmbracoBackOffice";
@@ -37,4 +36,4 @@ namespace Umbraco.Core
}
}
}
}
+1 -37
View File
@@ -11,53 +11,17 @@
/// The integer identifier for global system root node.
/// </summary>
public const int Root = -1;
/// <summary>
/// The string identifier for global system root node.
/// </summary>
/// <remarks>Use this instead of re-creating the string everywhere.</remarks>
public const string RootString = "-1";
/// <summary>
/// The integer identifier for content's recycle bin.
/// </summary>
public const int RecycleBinContent = -20;
/// <summary>
/// The string identifier for content's recycle bin.
/// </summary>
/// <remarks>Use this instead of re-creating the string everywhere.</remarks>
public const string RecycleBinContentString = "-20";
/// <summary>
/// The string path prefix of the content's recycle bin.
/// </summary>
/// <remarks>
/// <para>Everything that is in the content recycle bin, has a path that starts with the prefix.</para>
/// <para>Use this instead of re-creating the string everywhere.</para>
/// </remarks>
public const string RecycleBinContentPathPrefix = "-1,-20,";
/// <summary>
/// The integer identifier for media's recycle bin.
/// </summary>
public const int RecycleBinMedia = -21;
/// <summary>
/// The string identifier for media's recycle bin.
/// </summary>
/// <remarks>Use this instead of re-creating the string everywhere.</remarks>
public const string RecycleBinMediaString = "-21";
/// <summary>
/// The string path prefix of the media's recycle bin.
/// </summary>
/// <remarks>
/// <para>Everything that is in the media recycle bin, has a path that starts with the prefix.</para>
/// <para>Use this instead of re-creating the string everywhere.</para>
/// </remarks>
public const string RecycleBinMediaPathPrefix = "-1,-21,";
public const int DefaultContentListViewDataTypeId = -95;
public const int DefaultMediaListViewDataTypeId = -96;
public const int DefaultMembersListViewDataTypeId = -97;
@@ -65,6 +29,6 @@
public const string UmbracoConnectionName = "umbracoDbDSN";
public const string UmbracoMigrationName = "Umbraco";
}
}
}
+43 -43
View File
@@ -2,60 +2,60 @@ using System;
using System.Threading;
namespace Umbraco.Core
{
/// <summary>
/// Abstract implementation of IDisposable.
/// </summary>
/// <remarks>
/// Can also be used as a pattern for when inheriting is not possible.
///
{
/// <summary>
/// Abstract implementation of IDisposable.
/// </summary>
/// <remarks>
/// Can also be used as a pattern for when inheriting is not possible.
///
/// See also: https://msdn.microsoft.com/en-us/library/b1yfkh5e%28v=vs.110%29.aspx
/// See also: https://lostechies.com/chrispatterson/2012/11/29/idisposable-done-right/
///
/// Note: if an object's ctor throws, it will never be disposed, and so if that ctor
/// has allocated disposable objects, it should take care of disposing them.
/// </remarks>
public abstract class DisposableObject : IDisposable
{
private bool _disposed;
private readonly object _locko = new object();
// gets a value indicating whether this instance is disposed.
/// </remarks>
public abstract class DisposableObject : IDisposable
{
private bool _disposed;
private readonly object _locko = new object();
// gets a value indicating whether this instance is disposed.
// for internal tests only (not thread safe)
//TODO make this internal + rename "Disposed" when we can break compatibility
public bool IsDisposed { get { return _disposed; } }
// implements IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// finalizer
~DisposableObject()
{
Dispose(false);
}
public bool IsDisposed { get { return _disposed; } }
// implements IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// finalizer
~DisposableObject()
{
Dispose(false);
}
//TODO make this private, non-virtual when we can break compatibility
protected virtual void Dispose(bool disposing)
{
lock (_locko)
{
if (_disposed) return;
_disposed = true;
}
protected virtual void Dispose(bool disposing)
{
lock (_locko)
{
if (_disposed) return;
_disposed = true;
}
DisposeUnmanagedResources();
if (disposing)
DisposeResources();
}
protected abstract void DisposeResources();
protected virtual void DisposeUnmanagedResources()
{ }
}
DisposeResources();
}
protected abstract void DisposeResources();
protected virtual void DisposeUnmanagedResources()
{ }
}
}
-38
View File
@@ -1,38 +0,0 @@
using System;
namespace Umbraco.Core
{
/// <summary>
/// This should not be use if there are ubmanaged resources to be disposed, use DisposableObject instead
/// </summary>
public abstract class DisposableObjectSlim : IDisposable
{
private bool _disposed;
private readonly object _locko = new object();
// gets a value indicating whether this instance is disposed.
// for internal tests only (not thread safe)
internal bool Disposed { get { return _disposed; } }
// implements IDisposable
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
lock (_locko)
{
if (_disposed) return;
_disposed = true;
}
if (disposing)
DisposeResources();
}
protected abstract void DisposeResources();
}
}
+8 -8
View File
@@ -11,8 +11,8 @@ namespace Umbraco.Core
/// <summary>
/// Starts the timer and invokes a callback upon disposal. Provides a simple way of timing an operation by wrapping it in a <code>using</code> (C#) statement.
/// </summary>
public class DisposableTimer : DisposableObjectSlim
{
public class DisposableTimer : DisposableObject
{
private readonly ILogger _logger;
private readonly LogType? _logType;
private readonly IProfiler _profiler;
@@ -209,13 +209,13 @@ namespace Umbraco.Core
loggerType,
startMessage(),
completeMessage());
}
}
#endregion
/// <summary>
/// Handles the disposal of resources. Derived from abstract class <see cref="DisposableObjectSlim"/> which handles common required locking logic.
/// </summary>
protected override void DisposeResources()
/// <summary>
/// Handles the disposal of resources. Derived from abstract class <see cref="DisposableObject"/> which handles common required locking logic.
/// </summary>
protected override void DisposeResources()
{
if (_profiler != null)
{
+1 -1
View File
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Events
/// <summary>
/// Event messages collection
/// </summary>
public sealed class EventMessages : DisposableObjectSlim
public sealed class EventMessages : DisposableObject
{
private readonly List<EventMessage> _msgs = new List<EventMessage>();
@@ -1,18 +0,0 @@
using System;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
namespace Umbraco.Core.Events
{
internal class ExportedMemberEventArgs : EventArgs
{
public IMember Member { get; }
public MemberExportModel Exported { get; }
public ExportedMemberEventArgs(IMember member, MemberExportModel exported)
{
Member = member;
Exported = exported;
}
}
}
-16
View File
@@ -1,16 +0,0 @@
using System;
namespace Umbraco.Core.Events
{
public class RolesEventArgs : EventArgs
{
public RolesEventArgs(int[] memberIds, string[] roles)
{
MemberIds = memberIds;
Roles = roles;
}
public int[] MemberIds { get; set; }
public string[] Roles { get; set; }
}
}
@@ -1,19 +0,0 @@
using System;
using Umbraco.Core.Models.Membership;
namespace Umbraco.Core.Events
{
internal class UserGroupWithUsers
{
public UserGroupWithUsers(IUserGroup userGroup, IUser[] addedUsers, IUser[] removedUsers)
{
UserGroup = userGroup;
AddedUsers = addedUsers;
RemovedUsers = removedUsers;
}
public IUserGroup UserGroup { get; }
public IUser[] AddedUsers { get; }
public IUser[] RemovedUsers { get; }
}
}
+1 -1
View File
@@ -14,7 +14,7 @@ namespace Umbraco.Core
/// This will use the crypto libs to generate the hash and will try to ensure that
/// strings, etc... are not re-allocated so it's not consuming much memory.
/// </remarks>
internal class HashGenerator : DisposableObjectSlim
internal class HashGenerator : DisposableObject
{
public HashGenerator()
{
+2 -2
View File
@@ -26,13 +26,13 @@ namespace Umbraco.Core
var ipAddress = httpContext.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (string.IsNullOrEmpty(ipAddress))
return httpContext.Request.UserHostAddress;
return httpContext.Request.ServerVariables["REMOTE_ADDR"];
var addresses = ipAddress.Split(',');
if (addresses.Length != 0)
return addresses[0];
return httpContext.Request.UserHostAddress;
return httpContext.Request.ServerVariables["REMOTE_ADDR"];
}
catch (System.Exception ex)
{
+6 -36
View File
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using Umbraco.Core.Logging;
namespace Umbraco.Core.IO
@@ -108,7 +107,7 @@ namespace Umbraco.Core.IO
try
{
WithRetry(() => Directory.Delete(fullPath, recursive));
Directory.Delete(fullPath, recursive);
}
catch (DirectoryNotFoundException ex)
{
@@ -226,8 +225,8 @@ namespace Umbraco.Core.IO
return;
try
{
WithRetry(() => File.Delete(fullPath));
{
File.Delete(fullPath);
}
catch (FileNotFoundException ex)
{
@@ -379,7 +378,7 @@ namespace Umbraco.Core.IO
{
if (overrideIfExists == false)
throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", path));
WithRetry(() => File.Delete(fullPath));
File.Delete(fullPath);
}
var directory = Path.GetDirectoryName(fullPath);
@@ -387,9 +386,9 @@ namespace Umbraco.Core.IO
Directory.CreateDirectory(directory); // ensure it exists
if (copy)
WithRetry(() => File.Copy(physicalPath, fullPath));
File.Copy(physicalPath, fullPath);
else
WithRetry(() => File.Move(physicalPath, fullPath));
File.Move(physicalPath, fullPath);
}
#region Helper Methods
@@ -418,35 +417,6 @@ namespace Umbraco.Core.IO
return path;
}
protected void WithRetry(Action action)
{
// 10 times 100ms is 1s
const int count = 10;
const int pausems = 100;
for (var i = 0;; i++)
{
try
{
action();
break; // done
}
catch (IOException e)
{
// if it's not *exactly* IOException then it could be
// some inherited exception such as FileNotFoundException,
// and then we don't want to retry
if (e.GetType() != typeof(IOException)) throw;
// if we have tried enough, throw, else swallow
// the exception and retry after a pause
if (i == count) throw;
}
Thread.Sleep(pausems);
}
}
#endregion
}
}
+1 -1
View File
@@ -6,7 +6,7 @@ using Umbraco.Core.Logging;
namespace Umbraco.Core.Manifest
{
internal class ManifestWatcher : DisposableObjectSlim
internal class ManifestWatcher : DisposableObject
{
private readonly ILogger _logger;
private readonly List<FileSystemWatcher> _fws = new List<FileSystemWatcher>();
-94
View File
@@ -1,94 +0,0 @@
using System;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents an audited event.
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
internal class AuditEntry : Entity, IAuditEntry
{
private static PropertySelectors _selectors;
private int _performingUserId;
private string _performingDetails;
private string _performingIp;
private int _affectedUserId;
private string _affectedDetails;
private string _eventType;
private string _eventDetails;
private static PropertySelectors Selectors => _selectors ?? (_selectors = new PropertySelectors());
private class PropertySelectors
{
public readonly PropertyInfo PerformingUserId = ExpressionHelper.GetPropertyInfo<AuditEntry, int>(x => x.PerformingUserId);
public readonly PropertyInfo PerformingDetails = ExpressionHelper.GetPropertyInfo<AuditEntry, string>(x => x.PerformingDetails);
public readonly PropertyInfo PerformingIp = ExpressionHelper.GetPropertyInfo<AuditEntry, string>(x => x.PerformingIp);
public readonly PropertyInfo AffectedUserId = ExpressionHelper.GetPropertyInfo<AuditEntry, int>(x => x.AffectedUserId);
public readonly PropertyInfo AffectedDetails = ExpressionHelper.GetPropertyInfo<AuditEntry, string>(x => x.AffectedDetails);
public readonly PropertyInfo EventType = ExpressionHelper.GetPropertyInfo<AuditEntry, string>(x => x.EventType);
public readonly PropertyInfo EventDetails = ExpressionHelper.GetPropertyInfo<AuditEntry, string>(x => x.EventDetails);
}
/// <inheritdoc />
public int PerformingUserId
{
get => _performingUserId;
set => SetPropertyValueAndDetectChanges(value, ref _performingUserId, Selectors.PerformingUserId);
}
/// <inheritdoc />
public string PerformingDetails
{
get => _performingDetails;
set => SetPropertyValueAndDetectChanges(value, ref _performingDetails, Selectors.PerformingDetails);
}
/// <inheritdoc />
public string PerformingIp
{
get => _performingIp;
set => SetPropertyValueAndDetectChanges(value, ref _performingIp, Selectors.PerformingIp);
}
/// <inheritdoc />
public DateTime EventDateUtc
{
get => CreateDate;
set => CreateDate = value;
}
/// <inheritdoc />
public int AffectedUserId
{
get => _affectedUserId;
set => SetPropertyValueAndDetectChanges(value, ref _affectedUserId, Selectors.AffectedUserId);
}
/// <inheritdoc />
public string AffectedDetails
{
get => _affectedDetails;
set => SetPropertyValueAndDetectChanges(value, ref _affectedDetails, Selectors.AffectedDetails);
}
/// <inheritdoc />
public string EventType
{
get => _eventType;
set => SetPropertyValueAndDetectChanges(value, ref _eventType, Selectors.EventType);
}
/// <inheritdoc />
public string EventDetails
{
get => _eventDetails;
set => SetPropertyValueAndDetectChanges(value, ref _eventDetails, Selectors.EventDetails);
}
}
}
+1 -13
View File
@@ -2,30 +2,18 @@
namespace Umbraco.Core.Models
{
public sealed class AuditItem : Entity, IAuditItem
public sealed class AuditItem : Entity, IAggregateRoot
{
/// <summary>
/// Constructor for creating an item to be created
/// </summary>
/// <param name="objectId"></param>
/// <param name="comment"></param>
/// <param name="type"></param>
/// <param name="userId"></param>
public AuditItem(int objectId, string comment, AuditType type, int userId)
{
DisableChangeTracking();
Id = objectId;
Comment = comment;
AuditType = type;
UserId = userId;
EnableChangeTracking();
}
public string Comment { get; private set; }
public AuditType AuditType { get; private set; }
public int UserId { get; private set; }
}
}
-102
View File
@@ -1,102 +0,0 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a consent.
/// </summary>
[Serializable]
[DataContract(IsReference = true)]
internal class Consent : Entity, IConsent
{
private static PropertySelectors _selector;
private bool _current;
private string _source;
private string _context;
private string _action;
private ConsentState _state;
private string _comment;
// ReSharper disable once ClassNeverInstantiated.Local
private class PropertySelectors
{
public readonly PropertyInfo Current = ExpressionHelper.GetPropertyInfo<Consent, bool>(x => x.Current);
public readonly PropertyInfo Source = ExpressionHelper.GetPropertyInfo<Consent, string>(x => x.Source);
public readonly PropertyInfo Context = ExpressionHelper.GetPropertyInfo<Consent, string>(x => x.Context);
public readonly PropertyInfo Action = ExpressionHelper.GetPropertyInfo<Consent, string>(x => x.Action);
public readonly PropertyInfo State = ExpressionHelper.GetPropertyInfo<Consent, ConsentState>(x => x.State);
public readonly PropertyInfo Comment = ExpressionHelper.GetPropertyInfo<Consent, string>(x => x.Comment);
}
private static PropertySelectors Selectors => _selector ?? (_selector = new PropertySelectors());
/// <inheritdoc />
public bool Current
{
get => _current;
set => SetPropertyValueAndDetectChanges(value, ref _current, Selectors.Current);
}
/// <inheritdoc />
public string Source
{
get => _source;
set
{
if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException(nameof(value));
SetPropertyValueAndDetectChanges(value, ref _source, Selectors.Source);
}
}
/// <inheritdoc />
public string Context
{
get => _context;
set
{
if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException(nameof(value));
SetPropertyValueAndDetectChanges(value, ref _context, Selectors.Context);
}
}
/// <inheritdoc />
public string Action
{
get => _action;
set
{
if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException(nameof(value));
SetPropertyValueAndDetectChanges(value, ref _action, Selectors.Action);
}
}
/// <inheritdoc />
public ConsentState State
{
get => _state;
// note: we probably should validate the state here, but since the
// enum is [Flags] with many combinations, this could be expensive
set => SetPropertyValueAndDetectChanges(value, ref _state, Selectors.State);
}
/// <inheritdoc />
public string Comment
{
get => _comment;
set => SetPropertyValueAndDetectChanges(value, ref _comment, Selectors.Comment);
}
/// <inheritdoc />
public IEnumerable<IConsent> History => HistoryInternal;
/// <summary>
/// Gets the previous states of this consent.
/// </summary>
internal List<IConsent> HistoryInternal { get; set; }
}
}
@@ -1,18 +0,0 @@
namespace Umbraco.Core.Models
{
/// <summary>
/// Provides extension methods for the <see cref="IConsent"/> interface.
/// </summary>
public static class ConsentExtensions
{
/// <summary>
/// Determines whether the consent is granted.
/// </summary>
public static bool IsGranted(this IConsent consent) => (consent.State & ConsentState.Granted) > 0;
/// <summary>
/// Determines whether the consent is revoked.
/// </summary>
public static bool IsRevoked(this IConsent consent) => (consent.State & ConsentState.Revoked) > 0;
}
}
-38
View File
@@ -1,38 +0,0 @@
using System;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents the state of a consent.
/// </summary>
[Flags]
public enum ConsentState // : int
{
// note - this is a [Flags] enumeration
// on can create detailed flags such as:
//GrantedOptIn = Granted | 0x0001
//GrandedByForce = Granted | 0x0002
//
// 16 situations for each Pending/Granted/Revoked should be ok
/// <summary>
/// There is no consent.
/// </summary>
None = 0,
/// <summary>
/// Consent is pending and has not been granted yet.
/// </summary>
Pending = 0x10000,
/// <summary>
/// Consent has been granted.
/// </summary>
Granted = 0x20000,
/// <summary>
/// Consent has been revoked.
/// </summary>
Revoked = 0x40000
}
}
+1 -23
View File
@@ -544,28 +544,6 @@ namespace Umbraco.Core.Models
return false;
}
/// <summary>
/// Returns both instance dirty properties and property type properties
/// </summary>
/// <returns></returns>
public override IEnumerable<string> GetDirtyProperties()
{
var instanceProperties = base.GetDirtyProperties();
var propertyTypes = Properties.Where(x => x.IsDirty()).Select(x => x.Alias);
return instanceProperties.Concat(propertyTypes);
}
/// <summary>
/// Returns both instance dirty properties and property type properties
/// </summary>
/// <returns></returns>
internal override IEnumerable<string> GetPreviouslyDirtyProperties()
{
var instanceProperties = base.GetPreviouslyDirtyProperties();
var propertyTypes = Properties.Where(x => x.WasDirty()).Select(x => x.Alias);
return instanceProperties.Concat(propertyTypes);
}
#endregion
}
}
}
@@ -23,13 +23,6 @@ namespace Umbraco.Core.Models.EntityBase
: _propertyChangedInfo.Where(x => x.Value).Select(x => x.Key);
}
internal virtual IEnumerable<string> GetPreviouslyDirtyProperties()
{
return _lastPropertyChangedInfo == null
? Enumerable.Empty<string>()
: _lastPropertyChangedInfo.Where(x => x.Value).Select(x => x.Key);
}
private bool _changeTrackingEnabled = true;
/// <summary>
@@ -228,4 +221,4 @@ namespace Umbraco.Core.Models.EntityBase
}
}
}
}
}
-60
View File
@@ -1,60 +0,0 @@
using System;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents an audited event.
/// </summary>
/// <remarks>
/// <para>The free-form details properties can be used to capture relevant infos (for example,
/// a user email and identifier) at the time of the audited event, even though they may change
/// later on - but we want to keep a track of their value at that time.</para>
/// <para>Depending on audit loggers, these properties can be purely free-form text, or
/// contain json serialized objects.</para>
/// </remarks>
public interface IAuditEntry : IAggregateRoot, IRememberBeingDirty
{
/// <summary>
/// Gets or sets the identifier of the user triggering the audited event.
/// </summary>
int PerformingUserId { get; set; }
/// <summary>
/// Gets or sets free-form details about the user triggering the audited event.
/// </summary>
string PerformingDetails { get; set; }
/// <summary>
/// Gets or sets the IP address or the request triggering the audited event.
/// </summary>
string PerformingIp { get; set; }
/// <summary>
/// Gets or sets the date and time of the audited event.
/// </summary>
DateTime EventDateUtc { get; set; }
/// <summary>
/// Gets or sets the identifier of the user affected by the audited event.
/// </summary>
/// <remarks>Not used when no single user is affected by the event.</remarks>
int AffectedUserId { get; set; }
/// <summary>
/// Gets or sets free-form details about the entity affected by the audited event.
/// </summary>
/// <remarks>The entity affected by the event can be another user, a member...</remarks>
string AffectedDetails { get; set; }
/// <summary>
/// Gets or sets the type of the audited event.
/// </summary>
string EventType { get; set; }
/// <summary>
/// Gets or sets free-form details about the audited event.
/// </summary>
string EventDetails { get; set; }
}
}
-12
View File
@@ -1,12 +0,0 @@
using System;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
public interface IAuditItem : IAggregateRoot
{
string Comment { get; }
AuditType AuditType { get; }
int UserId { get; }
}
}
-55
View File
@@ -1,55 +0,0 @@
using System.Collections.Generic;
using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models
{
/// <summary>
/// Represents a consent state.
/// </summary>
/// <remarks>
/// <para>A consent is fully identified by a source (whoever is consenting), a context (for
/// example, an application), and an action (whatever is consented).</para>
/// <para>A consent state registers the state of the consent (granted, revoked...).</para>
/// </remarks>
public interface IConsent : IAggregateRoot, IRememberBeingDirty
{
/// <summary>
/// Determines whether the consent entity represents the current state.
/// </summary>
bool Current { get; }
/// <summary>
/// Gets the unique identifier of whoever is consenting.
/// </summary>
string Source { get; }
/// <summary>
/// Gets the unique identifier of the context of the consent.
/// </summary>
/// <remarks>
/// <para>Represents the domain, application, scope... of the action.</para>
/// <para>When the action is a Udi, this should be the Udi type.</para>
/// </remarks>
string Context { get; }
/// <summary>
/// Gets the unique identifier of the consented action.
/// </summary>
string Action { get; }
/// <summary>
/// Gets the state of the consent.
/// </summary>
ConsentState State { get; }
/// <summary>
/// Gets some additional free text.
/// </summary>
string Comment { get; }
/// <summary>
/// Gets the previous states of this consent.
/// </summary>
IEnumerable<IConsent> History { get; }
}
}
+1 -15
View File
@@ -19,13 +19,6 @@
/// <returns></returns>
bool MemberCanViewProperty(string propertyTypeAlias);
/// <summary>
/// Gets a boolean indicating whether a Property is marked as storing sensitive values on the Members profile.
/// </summary>
/// <param name="propertyTypeAlias">PropertyType Alias of the Property to check</param>
/// <returns></returns>
bool IsSensitiveProperty(string propertyTypeAlias);
/// <summary>
/// Sets a boolean indicating whether a Property is editable by the Member.
/// </summary>
@@ -39,12 +32,5 @@
/// <param name="propertyTypeAlias">PropertyType Alias of the Property to set</param>
/// <param name="value">Boolean value, true or false</param>
void SetMemberCanViewProperty(string propertyTypeAlias, bool value);
/// <summary>
/// Sets a boolean indicating whether a Property is a sensitive value on the Members profile.
/// </summary>
/// <param name="propertyTypeAlias">PropertyType Alias of the Property to set</param>
/// <param name="value">Boolean value, true or false</param>
void SetIsSensitiveProperty(string propertyTypeAlias, bool value);
}
}
}
@@ -49,6 +49,19 @@ namespace Umbraco.Core.Models.Identity
identityUser.EnableChangeTracking();
});
config.CreateMap<BackOfficeIdentityUser, UserData>()
.ConstructUsing((BackOfficeIdentityUser user) => new UserData(Guid.NewGuid().ToString("N"))) //this is the 'session id'
.ForMember(detail => detail.Id, opt => opt.MapFrom(user => user.Id))
.ForMember(detail => detail.AllowedApplications, opt => opt.MapFrom(user => user.AllowedSections))
.ForMember(detail => detail.Roles, opt => opt.MapFrom(user => user.Roles.Select(x => x.RoleId).ToArray()))
.ForMember(detail => detail.RealName, opt => opt.MapFrom(user => user.Name))
//When mapping to UserData which is used in the authcookie we want ALL start nodes including ones defined on the groups
.ForMember(detail => detail.StartContentNodes, opt => opt.MapFrom(user => user.CalculatedContentStartNodeIds))
//When mapping to UserData which is used in the authcookie we want ALL start nodes including ones defined on the groups
.ForMember(detail => detail.StartMediaNodes, opt => opt.MapFrom(user => user.CalculatedMediaStartNodeIds))
.ForMember(detail => detail.Username, opt => opt.MapFrom(user => user.UserName))
.ForMember(detail => detail.Culture, opt => opt.MapFrom(user => user.Culture))
.ForMember(detail => detail.SessionId, opt => opt.MapFrom(user => user.SecurityStamp.IsNullOrWhiteSpace() ? Guid.NewGuid().ToString("N") : user.SecurityStamp));
}
private string GetPasswordHash(string storedPass)
+2 -14
View File
@@ -170,19 +170,7 @@ namespace Umbraco.Core.Models
public string RawPasswordValue
{
get { return _rawPasswordValue; }
set
{
if (value == null)
{
//special case, this is used to ensure that the password is not updated when persisting, in this case
//we don't want to track changes either
_rawPasswordValue = null;
}
else
{
SetPropertyValueAndDetectChanges(value, ref _rawPasswordValue, Ps.Value.PasswordSelector);
}
}
set { SetPropertyValueAndDetectChanges(value, ref _rawPasswordValue, Ps.Value.PasswordSelector); }
}
/// <summary>
@@ -640,4 +628,4 @@ namespace Umbraco.Core.Models
}
}
}
}
+13 -49
View File
@@ -64,7 +64,7 @@ namespace Umbraco.Core.Models
}
/// <summary>
/// Gets or Sets a Dictionary of Tuples (MemberCanEdit, VisibleOnProfile, IsSensitive) by the PropertyTypes' alias.
/// Gets or Sets a Dictionary of Tuples (MemberCanEdit, VisibleOnProfile) by the PropertyTypes' alias.
/// </summary>
[DataMember]
internal IDictionary<string, MemberTypePropertyProfileAccess> MemberTypePropertyTypes { get; private set; }
@@ -76,11 +76,11 @@ namespace Umbraco.Core.Models
/// <returns></returns>
public bool MemberCanEditProperty(string propertyTypeAlias)
{
MemberTypePropertyProfileAccess propertyProfile;
if (MemberTypePropertyTypes.TryGetValue(propertyTypeAlias, out propertyProfile))
if (MemberTypePropertyTypes.ContainsKey(propertyTypeAlias))
{
return propertyProfile.IsEditable;
return MemberTypePropertyTypes[propertyTypeAlias].IsEditable;
}
return false;
}
@@ -91,26 +91,11 @@ namespace Umbraco.Core.Models
/// <returns></returns>
public bool MemberCanViewProperty(string propertyTypeAlias)
{
MemberTypePropertyProfileAccess propertyProfile;
if (MemberTypePropertyTypes.TryGetValue(propertyTypeAlias, out propertyProfile))
if (MemberTypePropertyTypes.ContainsKey(propertyTypeAlias))
{
return propertyProfile.IsVisible;
return MemberTypePropertyTypes[propertyTypeAlias].IsVisible;
}
return false;
}
/// <summary>
/// Gets a boolean indicating whether a Property is marked as storing sensitive values on the Members profile.
/// </summary>
/// <param name="propertyTypeAlias">PropertyType Alias of the Property to check</param>
/// <returns></returns>
public bool IsSensitiveProperty(string propertyTypeAlias)
{
MemberTypePropertyProfileAccess propertyProfile;
if (MemberTypePropertyTypes.TryGetValue(propertyTypeAlias, out propertyProfile))
{
return propertyProfile.IsSensitive;
}
return false;
}
@@ -121,14 +106,13 @@ namespace Umbraco.Core.Models
/// <param name="value">Boolean value, true or false</param>
public void SetMemberCanEditProperty(string propertyTypeAlias, bool value)
{
MemberTypePropertyProfileAccess propertyProfile;
if (MemberTypePropertyTypes.TryGetValue(propertyTypeAlias, out propertyProfile))
if (MemberTypePropertyTypes.ContainsKey(propertyTypeAlias))
{
propertyProfile.IsEditable = value;
MemberTypePropertyTypes[propertyTypeAlias].IsEditable = value;
}
else
{
var tuple = new MemberTypePropertyProfileAccess(false, value, false);
var tuple = new MemberTypePropertyProfileAccess(false, value);
MemberTypePropertyTypes.Add(propertyTypeAlias, tuple);
}
}
@@ -140,35 +124,15 @@ namespace Umbraco.Core.Models
/// <param name="value">Boolean value, true or false</param>
public void SetMemberCanViewProperty(string propertyTypeAlias, bool value)
{
MemberTypePropertyProfileAccess propertyProfile;
if (MemberTypePropertyTypes.TryGetValue(propertyTypeAlias, out propertyProfile))
if (MemberTypePropertyTypes.ContainsKey(propertyTypeAlias))
{
propertyProfile.IsVisible = value;
MemberTypePropertyTypes[propertyTypeAlias].IsVisible = value;
}
else
{
var tuple = new MemberTypePropertyProfileAccess(value, false, false);
MemberTypePropertyTypes.Add(propertyTypeAlias, tuple);
}
}
/// <summary>
/// Sets a boolean indicating whether a Property is a sensitive value on the Members profile.
/// </summary>
/// <param name="propertyTypeAlias">PropertyType Alias of the Property to set</param>
/// <param name="value">Boolean value, true or false</param>
public void SetIsSensitiveProperty(string propertyTypeAlias, bool value)
{
MemberTypePropertyProfileAccess propertyProfile;
if (MemberTypePropertyTypes.TryGetValue(propertyTypeAlias, out propertyProfile))
{
propertyProfile.IsSensitive = value;
}
else
{
var tuple = new MemberTypePropertyProfileAccess(false, false, true);
var tuple = new MemberTypePropertyProfileAccess(value, false);
MemberTypePropertyTypes.Add(propertyTypeAlias, tuple);
}
}
}
}
}
@@ -5,15 +5,13 @@ namespace Umbraco.Core.Models
/// </summary>
internal class MemberTypePropertyProfileAccess
{
public MemberTypePropertyProfileAccess(bool isVisible, bool isEditable, bool isSenstive)
public MemberTypePropertyProfileAccess(bool isVisible, bool isEditable)
{
IsVisible = isVisible;
IsEditable = isEditable;
IsSensitive = isSenstive;
}
public bool IsVisible { get; set; }
public bool IsEditable { get; set; }
public bool IsSensitive { get; set; }
}
}
}
@@ -63,4 +63,4 @@ namespace Umbraco.Core.Models.Membership
}
}
}
}
+1 -6
View File
@@ -69,11 +69,6 @@ namespace Umbraco.Core.Models.Membership
/// <summary>
/// Will hold the media file system relative path of the users custom avatar if they uploaded one
/// </summary>
string Avatar { get; set; }
/// <summary>
/// A Json blob stored for recording tour data for a user
/// </summary>
string TourData { get; set; }
string Avatar { get; set; }
}
}
@@ -3,7 +3,7 @@ using Umbraco.Core.Models.EntityBase;
namespace Umbraco.Core.Models.Membership
{
public interface IUserGroup : IAggregateRoot, IRememberBeingDirty, ICanBeDirty
public interface IUserGroup : IAggregateRoot
{
string Alias { get; set; }
@@ -41,4 +41,4 @@ namespace Umbraco.Core.Models.Membership
/// </summary>
int UserCount { get; }
}
}
}
@@ -1,22 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Umbraco.Core.Models.Membership
{
internal class MemberExportModel
{
public int Id { get; set; }
public Guid Key { get; set; }
public string Name { get; set; }
public string Username { get; set; }
public string Email { get; set; }
public List<string> Groups { get; set; }
public string ContentTypeAlias { get; set; }
public DateTime CreateDate { get; set; }
public DateTime UpdateDate { get; set; }
public List<MemberExportProperty> Properties { get; set; }
}
}
@@ -1,14 +0,0 @@
using System;
namespace Umbraco.Core.Models.Membership
{
internal class MemberExportProperty
{
public int Id { get; set; }
public string Alias { get; set; }
public string Name { get; set; }
public object Value { get; set; }
public DateTime? CreateDate { get; set; }
public DateTime? UpdateDate { get; set; }
}
}
+2 -15
View File
@@ -99,7 +99,6 @@ namespace Umbraco.Core.Models.Membership
private string _name;
private string _securityStamp;
private string _avatar;
private string _tourData;
private int _sessionTimeout;
private int[] _startContentIds;
private int[] _startMediaIds;
@@ -133,7 +132,6 @@ namespace Umbraco.Core.Models.Membership
public readonly PropertyInfo SecurityStampSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.SecurityStamp);
public readonly PropertyInfo AvatarSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Avatar);
public readonly PropertyInfo TourDataSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.TourData);
public readonly PropertyInfo SessionTimeoutSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.SessionTimeout);
public readonly PropertyInfo StartContentIdSelector = ExpressionHelper.GetPropertyInfo<User, int[]>(x => x.StartContentIds);
public readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo<User, int[]>(x => x.StartMediaIds);
@@ -466,18 +464,8 @@ namespace Umbraco.Core.Models.Membership
{
get { return _avatar; }
set { SetPropertyValueAndDetectChanges(value, ref _avatar, Ps.Value.AvatarSelector); }
}
}
/// <summary>
/// A Json blob stored for recording tour data for a user
/// </summary>
[DataMember]
public string TourData
{
get { return _tourData; }
set { SetPropertyValueAndDetectChanges(value, ref _tourData, Ps.Value.TourDataSelector); }
}
/// <summary>
/// Gets or sets the session timeout.
/// </summary>
@@ -706,6 +694,5 @@ namespace Umbraco.Core.Models.Membership
return _user.GetHashCode();
}
}
}
}
}
@@ -152,4 +152,4 @@ namespace Umbraco.Core.Models.Membership
public int UserCount { get; private set; }
}
}
}
+2 -1
View File
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
@@ -435,4 +436,4 @@ namespace Umbraco.Core.Models
return clone;
}
}
}
}
@@ -1,60 +0,0 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
[TableName(TableName)]
[PrimaryKey("id")]
[ExplicitColumns]
internal class AuditEntryDto
{
public const string TableName = "umbracoAudit";
public const int IpLength = 64;
public const int EventTypeLength = 256;
public const int DetailsLength = 1024;
[Column("id")]
[PrimaryKeyColumn]
public int Id { get; set; }
// there is NO foreign key to the users table here, neither for performing user nor for
// affected user, so we can delete users and NOT delete the associated audit trails, and
// users can still be identified via the details free-form text fields.
[Column("performingUserId")]
public int PerformingUserId { get; set; }
[Column("performingDetails")]
[NullSetting(NullSetting = NullSettings.Null)]
[Length(DetailsLength)]
public string PerformingDetails { get; set; }
[Column("performingIp")]
[NullSetting(NullSetting = NullSettings.Null)]
[Length(IpLength)]
public string PerformingIp { get; set; }
[Column("eventDateUtc")]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime EventDateUtc { get; set; }
[Column("affectedUserId")]
public int AffectedUserId { get; set; }
[Column("affectedDetails")]
[NullSetting(NullSetting = NullSettings.Null)]
[Length(DetailsLength)]
public string AffectedDetails { get; set; }
[Column("eventType")]
[Length(EventTypeLength)]
public string EventType { get; set; }
[Column("eventDetails")]
[NullSetting(NullSetting = NullSettings.Null)]
[Length(DetailsLength)]
public string EventDetails { get; set; }
}
}
@@ -27,10 +27,5 @@ namespace Umbraco.Core.Models.Rdbms
[NullSetting(NullSetting = NullSettings.NotNull)]
[Length(500)]
public string OriginIdentity { get; set; }
[Column("instructionCount")]
[NullSetting(NullSetting = NullSettings.NotNull)]
[Constraint(Default = 1)]
public int InstructionCount { get; set; }
}
}
@@ -1,44 +0,0 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
namespace Umbraco.Core.Models.Rdbms
{
[TableName(TableName)]
[PrimaryKey("id")]
[ExplicitColumns]
public class ConsentDto
{
internal const string TableName = "umbracoConsent";
[Column("id")]
[PrimaryKeyColumn]
public int Id { get; set; }
[Column("current")]
public bool Current { get; set; }
[Column("source")]
[Length(512)]
public string Source { get; set; }
[Column("context")]
[Length(128)]
public string Context { get; set; }
[Column("action")]
[Length(512)]
public string Action { get; set; }
[Column("createDate")]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime CreateDate { get; set; }
[Column("state")]
public int State { get; set; }
[Column("comment")]
public string Comment { get; set; }
}
}
@@ -24,5 +24,4 @@ namespace Umbraco.Core.Models.Rdbms
[ResultColumn]
public NodeDto NodeDto { get; set; }
}
}
+1 -1
View File
@@ -32,6 +32,6 @@ namespace Umbraco.Core.Models.Rdbms
[Column("logComment")]
[NullSetting(NullSetting = NullSettings.Null)]
[Length(4000)]
public string Comment { get; set; }
public string Comment { get; set; }
}
}
-29
View File
@@ -1,29 +0,0 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace Umbraco.Core.Models.Rdbms
{
[TableName("cmsMedia")]
[PrimaryKey("versionId", autoIncrement = false)]
[ExplicitColumns]
internal class MediaDto
{
[Column("nodeId")]
[ForeignKey(typeof(ContentDto), Column = "nodeId")]
[ForeignKey(typeof(NodeDto))]
[Index(IndexTypes.UniqueNonClustered, Name = "IX_cmsMedia", ForColumns = "nodeId, versionId, mediaPath")]
public int NodeId { get; set; }
[Column("versionId")]
[PrimaryKeyColumn(AutoIncrement = false)]
public Guid VersionId { get; set; }
[Column("mediaPath")]
[NullSetting(NullSetting = NullSettings.Null)]
public string MediaPath { get; set; }
[ResultColumn]
public ContentVersionDto ContentVersionDto { get; set; }
}
}
@@ -27,9 +27,5 @@ namespace Umbraco.Core.Models.Rdbms
[Column("viewOnProfile")]
[Constraint(Default = "0")]
public bool ViewOnProfile { get; set; }
[Column("isSensitive")]
[Constraint(Default = "0")]
public bool IsSensitive { get; set; }
}
}
}
@@ -27,7 +27,6 @@ namespace Umbraco.Core.Models.Rdbms
[ForeignKey(typeof(PropertyTypeGroupDto))]
public int? PropertyTypeGroupId { get; set; }
[Index(IndexTypes.NonClustered, Name = "IX_cmsPropertyTypeAlias")]
[Column("Alias")]
public string Alias { get; set; }
@@ -45,9 +45,6 @@ namespace Umbraco.Core.Models.Rdbms
[Column("viewOnProfile")]
public bool ViewOnProfile { get; set; }
[Column("isSensitive")]
public bool IsSensitive { get; set; }
/* cmsDataType */
[Column("propertyEditorAlias")]
public string PropertyEditorAlias { get; set; }
@@ -55,8 +52,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("dbType")]
public string DbType { get; set; }
[Column("UniqueID")]
[Column("UniqueID")]
public Guid UniqueId { get; set; }
}
}
}
+3 -11
View File
@@ -15,7 +15,7 @@ namespace Umbraco.Core.Models.Rdbms
{
UserGroupDtos = new List<UserGroupDto>();
UserStartNodeDtos = new HashSet<UserStartNodeDto>();
}
}
[Column("id")]
[PrimaryKeyColumn(Name = "PK_user")]
@@ -40,7 +40,7 @@ namespace Umbraco.Core.Models.Rdbms
[Column("userPassword")]
[Length(500)]
public string Password { get; set; }
/// <summary>
/// This will represent a JSON structure of how the password has been created (i.e hash algorithm, iterations)
/// </summary>
@@ -95,7 +95,7 @@ namespace Umbraco.Core.Models.Rdbms
[NullSetting(NullSetting = NullSettings.NotNull)]
[Constraint(Default = SystemMethods.CurrentDateTime)]
public DateTime UpdateDate { get; set; }
/// <summary>
/// Will hold the media file system relative path of the users custom avatar if they uploaded one
/// </summary>
@@ -103,14 +103,6 @@ namespace Umbraco.Core.Models.Rdbms
[NullSetting(NullSetting = NullSettings.Null)]
[Length(500)]
public string Avatar { get; set; }
/// <summary>
/// A Json blob stored for recording tour data for a user
/// </summary>
[Column("tourData")]
[NullSetting(NullSetting = NullSettings.Null)]
[SpecialDbType(SpecialDbTypes.NTEXT)]
public string TourData { get; set; }
[ResultColumn]
public List<UserGroupDto> UserGroupDtos { get; set; }
@@ -17,7 +17,7 @@ namespace Umbraco.Core.Models.Rdbms
}
[Column("id")]
[PrimaryKeyColumn(IdentitySeed = 6)]
[PrimaryKeyColumn(IdentitySeed = 5)]
public int Id { get; set; }
[Column("userGroupAlias")]
@@ -68,4 +68,4 @@ namespace Umbraco.Core.Models.Rdbms
[ResultColumn]
public int UserCount { get; set; }
}
}
}
@@ -1,52 +0,0 @@
using System;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace Umbraco.Core.Models.Rdbms
{
[TableName("umbracoUserLogin")]
[PrimaryKey("sessionId", autoIncrement = false)]
[ExplicitColumns]
internal class UserLoginDto
{
[Column("sessionId")]
[PrimaryKeyColumn(AutoIncrement = false)]
public Guid SessionId { get; set; }
[Column("userId")]
[ForeignKey(typeof(UserDto), Name = "FK_umbracoUserLogin_umbracoUser_id")]
public int UserId { get; set; }
/// <summary>
/// Tracks when the session is created
/// </summary>
[Column("loggedInUtc")]
[NullSetting(NullSetting = NullSettings.NotNull)]
public DateTime LoggedInUtc { get; set; }
/// <summary>
/// Updated every time a user's session is validated
/// </summary>
/// <remarks>
/// This allows us to guess if a session is timed out if a user doesn't actively log out
/// and also allows us to trim the data in the table
/// </remarks>
[Column("lastValidatedUtc")]
[NullSetting(NullSetting = NullSettings.NotNull)]
public DateTime LastValidatedUtc { get; set; }
/// <summary>
/// Tracks when the session is removed when the user's account is logged out
/// </summary>
[Column("loggedOutUtc")]
[NullSetting(NullSetting = NullSettings.Null)]
public DateTime? LoggedOutUtc { get; set; }
/// <summary>
/// Logs the IP address of the session if available
/// </summary>
[Column("ipAddress")]
[NullSetting(NullSetting = NullSettings.Null)]
public string IpAddress { get; set; }
}
}
+1 -1
View File
@@ -4,7 +4,7 @@ using Umbraco.Core.Persistence.DatabaseAnnotations;
namespace Umbraco.Core.Models.Rdbms
{
[Obsolete("Table no longer exists as of 7.7 - retained only to support migrations from previous versions")]
[Obsolete("Table no longer exists as of 7.6 - retained only to support migrations from previous versions")]
[TableName("umbracoUserType")]
[PrimaryKey("id")]
[ExplicitColumns]
@@ -192,7 +192,7 @@ namespace Umbraco.Core.Models
/// </summary>
[UmbracoObjectType(Constants.ObjectTypes.DocumentBlueprint, typeof(IContent))]
[FriendlyName("DocumentBlueprint")]
[UmbracoUdiType(Constants.UdiEntityType.DocumentBlueprint)]
[UmbracoUdiType(Constants.UdiEntityType.DocumentBluePrint)]
DocumentBlueprint,
/// <summary>
+3 -12
View File
@@ -30,11 +30,12 @@ namespace Umbraco.Core.Models
/// Tries to lookup the user's gravatar to see if the endpoint can be reached, if so it returns the valid URL
/// </summary>
/// <param name="user"></param>
/// <param name="userService"></param>
/// <param name="staticCache"></param>
/// <returns>
/// A list of 5 different sized avatar URLs
/// </returns>
internal static string[] GetUserAvatarUrls(this IUser user, ICacheProvider staticCache)
internal static string[] GetCurrentUserAvatarUrls(this IUser user, IUserService userService, ICacheProvider staticCache)
{
//check if the user has explicitly removed all avatars including a gravatar, this will be possible and the value will be "none"
if (user.Avatar == "none")
@@ -261,16 +262,6 @@ namespace Umbraco.Core.Models
return user.Groups != null && user.Groups.Any(x => x.Alias == Constants.Security.AdminGroupAlias);
}
/// <summary>
/// Determines whether this user has access to view sensitive data
/// </summary>
/// <param name="user"></param>
public static bool HasAccessToSensitiveData(this IUser user)
{
if (user == null) throw new ArgumentNullException("user");
return user.Groups != null && user.Groups.Any(x => x.Alias == Constants.Security.SensitiveDataGroupAlias);
}
// calc. start nodes, combining groups' and user's, and excluding what's in the bin
public static int[] CalculateContentStartNodeIds(this IUser user, IEntityService entityService)
{
@@ -423,4 +414,4 @@ namespace Umbraco.Core.Models
return lsn.ToArray();
}
}
}
}
@@ -394,7 +394,7 @@ namespace Umbraco.Core.ObjectResolution
/// WARNING! Do not use this unless you know what you are doing, clear all types registered and instances
/// created. Typically only used if a resolver is no longer used in an application and memory is to be GC'd
/// </summary>
internal virtual void ResetCollections()
internal void ResetCollections()
{
using (new WriteLock(_lock))
{
+38 -28
View File
@@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.IO.Compression;
using ICSharpCode.SharpZipLib.Zip;
namespace Umbraco.Core.Packaging
{
@@ -14,17 +14,17 @@ namespace Umbraco.Core.Packaging
bool fileFound = false;
string foundDir = null;
ReadZipfileEntries(packageFilePath, entry =>
ReadZipfileEntries(packageFilePath, (entry, stream) =>
{
string fileName = Path.GetFileName(entry.Name);
if (string.IsNullOrEmpty(fileName) == false && fileName.Equals(fileToRead, StringComparison.CurrentCultureIgnoreCase))
if (string.IsNullOrEmpty(fileName) == false &&
fileName.Equals(fileToRead, StringComparison.CurrentCultureIgnoreCase))
{
foundDir = entry.Name.Substring(0, entry.Name.Length - fileName.Length);
fileFound = true;
using (var entryStream = entry.Open())
using (var reader = new StreamReader(entryStream))
using (var reader = new StreamReader(stream))
{
retVal = reader.ReadToEnd();
return false;
@@ -77,7 +77,7 @@ namespace Umbraco.Core.Packaging
var d = sourceDestination.ToDictionary(k => k.Key.ToLower(), v => v.Value);
ReadZipfileEntries(packageFilePath, entry =>
ReadZipfileEntries(packageFilePath, (entry, stream) =>
{
string fileName = (Path.GetFileName(entry.Name) ?? string.Empty).ToLower();
if (fileName == string.Empty) { return true; }
@@ -86,9 +86,8 @@ namespace Umbraco.Core.Packaging
if (string.IsNullOrEmpty(fileName) == false && d.TryGetValue(fileName, out destination))
{
using (var streamWriter = File.Open(destination, FileMode.Create))
using (var entryStream = entry.Open())
{
entryStream.CopyTo(streamWriter);
stream.CopyTo(streamWriter);
}
d.Remove(fileName);
@@ -107,7 +106,7 @@ namespace Umbraco.Core.Packaging
{
var retVal = expectedFiles.ToList();
ReadZipfileEntries(packageFilePath, zipEntry =>
ReadZipfileEntries(packageFilePath, (zipEntry, stream) =>
{
string fileName = Path.GetFileName(zipEntry.Name);
@@ -126,7 +125,7 @@ namespace Umbraco.Core.Packaging
var dictionary = new Dictionary<string, List<string>>();
ReadZipfileEntries(packageFilePath, entry =>
ReadZipfileEntries(packageFilePath, (entry, stream) =>
{
string fileName = (Path.GetFileName(entry.Name) ?? string.Empty).ToLower();
@@ -149,42 +148,53 @@ namespace Umbraco.Core.Packaging
{
CheckPackageExists(packageFilePath);
var files = new HashSet<string>(filesToGet.Select(f => f.ToLowerInvariant()));
var files = new HashSet<string>(filesToGet.Select(f => f.ToLower()));
using (var fs = File.OpenRead(packageFilePath))
using (var zipArchive = new ZipArchive(fs))
using (var fs = File.OpenRead(packageFilePath))
{
foreach (var zipEntry in zipArchive.Entries)
using (var zipInputStream = new ZipInputStream(fs))
{
if (zipEntry.Name.IsNullOrWhiteSpace() && zipEntry.FullName.EndsWith("/")) continue;
if (files.Contains(zipEntry.Name.ToLowerInvariant()))
ZipEntry zipEntry;
while ((zipEntry = zipInputStream.GetNextEntry()) != null)
{
using (var memStream = new MemoryStream())
using (var entryStream = zipEntry.Open())
if (zipEntry.IsDirectory) continue;
if (files.Contains(zipEntry.Name))
{
entryStream.CopyTo(memStream);
memStream.Close();
yield return memStream.ToArray();
using (var memStream = new MemoryStream())
{
zipInputStream.CopyTo(memStream);
yield return memStream.ToArray();
memStream.Close();
}
}
}
zipInputStream.Close();
}
fs.Close();
}
}
private void ReadZipfileEntries(string packageFilePath, Func<ZipArchiveEntry, bool> entryFunc, bool skipsDirectories = true)
private void ReadZipfileEntries(string packageFilePath, Func<ZipEntry, ZipInputStream, bool> entryFunc, bool skipsDirectories = true)
{
CheckPackageExists(packageFilePath);
using (var fs = File.OpenRead(packageFilePath))
using (var zipArchive = new ZipArchive(fs))
{
foreach (var zipEntry in zipArchive.Entries)
using (var zipInputStream = new ZipInputStream(fs))
{
if (zipEntry.Name.IsNullOrWhiteSpace() && zipEntry.FullName.EndsWith("/") && skipsDirectories)
continue;
if (entryFunc(zipEntry) == false) break;
ZipEntry zipEntry;
while ((zipEntry = zipInputStream.GetNextEntry()) != null)
{
if (zipEntry.IsDirectory && skipsDirectories) continue;
if (entryFunc(zipEntry, zipInputStream) == false) break;
}
zipInputStream.Close();
}
fs.Close();
}
}
}
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Persistence
/// it will create one per context, otherwise it will be a global singleton object which is NOT thread safe
/// since we need (at least) a new instance of the database object per thread.
/// </remarks>
internal class DefaultDatabaseFactory : DisposableObjectSlim, IDatabaseFactory2
internal class DefaultDatabaseFactory : DisposableObject, IDatabaseFactory2
{
private readonly string _connectionStringName;
private readonly ILogger _logger;
@@ -1,52 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Factories
{
internal static class AuditEntryFactory
{
public static IEnumerable<IAuditEntry> BuildEntities(IEnumerable<AuditEntryDto> dtos)
{
return dtos.Select(BuildEntity).ToList();
}
public static IAuditEntry BuildEntity(AuditEntryDto dto)
{
var entity = new AuditEntry
{
Id = dto.Id,
PerformingUserId = dto.PerformingUserId,
PerformingDetails = dto.PerformingDetails,
PerformingIp = dto.PerformingIp,
EventDateUtc = dto.EventDateUtc,
AffectedUserId = dto.AffectedUserId,
AffectedDetails = dto.AffectedDetails,
EventType = dto.EventType,
EventDetails = dto.EventDetails
};
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
entity.ResetDirtyProperties(false);
return entity;
}
public static AuditEntryDto BuildDto(IAuditEntry entity)
{
return new AuditEntryDto
{
Id = entity.Id,
PerformingUserId = entity.PerformingUserId,
PerformingDetails = entity.PerformingDetails,
PerformingIp = entity.PerformingIp,
EventDateUtc = entity.EventDateUtc,
AffectedUserId = entity.AffectedUserId,
AffectedDetails = entity.AffectedDetails,
EventType = entity.EventType,
EventDetails = entity.EventDetails
};
}
}
}
@@ -1,65 +0,0 @@
using System.Collections.Generic;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Factories
{
internal static class ConsentFactory
{
public static IEnumerable<IConsent> BuildEntities(IEnumerable<ConsentDto> dtos)
{
var ix = new Dictionary<string, Consent>();
var output = new List<Consent>();
foreach (var dto in dtos)
{
var k = dto.Source + "::" + dto.Context + "::" + dto.Action;
var consent = new Consent
{
Id = dto.Id,
Current = dto.Current,
CreateDate = dto.CreateDate,
Source = dto.Source,
Context = dto.Context,
Action = dto.Action,
State = (ConsentState) dto.State, // assume value is valid
Comment = dto.Comment
};
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
consent.ResetDirtyProperties(false);
if (ix.TryGetValue(k, out var current))
{
if (current.HistoryInternal == null)
current.HistoryInternal = new List<IConsent>();
current.HistoryInternal.Add(consent);
}
else
{
ix[k] = consent;
output.Add(consent);
}
}
return output;
}
public static ConsentDto BuildDto(IConsent entity)
{
return new ConsentDto
{
Id = entity.Id,
Current = entity.Current,
CreateDate = entity.CreateDate,
Source = entity.Source,
Context = entity.Context,
Action = entity.Action,
State = (int) entity.State,
Comment = entity.Comment
};
}
}
}
@@ -98,18 +98,18 @@ namespace Umbraco.Core.Persistence.Factories
{
//NOTE Currently doesn't add Alias (legacy that eventually will go away)
var documentDto = new DocumentDto
{
Newest = true,
NodeId = entity.Id,
Published = entity.Published,
Text = entity.Name,
UpdateDate = entity.UpdateDate,
WriterUserId = entity.WriterId,
VersionId = entity.Version,
ExpiresDate = null,
ReleaseDate = null,
ContentVersionDto = BuildContentVersionDto(entity)
};
{
Newest = true,
NodeId = entity.Id,
Published = entity.Published,
Text = entity.Name,
UpdateDate = entity.UpdateDate,
WriterUserId = entity.WriterId,
VersionId = entity.Version,
ExpiresDate = null,
ReleaseDate = null,
ContentVersionDto = BuildContentVersionDto(entity)
};
if (entity.Template != null && entity.Template.Id > 0)
documentDto.TemplateId = entity.Template.Id;
@@ -84,8 +84,7 @@ namespace Umbraco.Core.Persistence.Factories
NodeId = entity.Id,
PropertyTypeId = x.Id,
CanEdit = memberType.MemberCanEditProperty(x.Alias),
ViewOnProfile = memberType.MemberCanViewProperty(x.Alias),
IsSensitive = memberType.IsSensitiveProperty(x.Alias)
ViewOnProfile = memberType.MemberCanViewProperty(x.Alias)
}).ToList();
return dtos;
}
@@ -160,4 +159,4 @@ namespace Umbraco.Core.Persistence.Factories
#endregion
}
}
}
@@ -5,7 +5,6 @@ using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Factories
{
internal class MacroFactory
{
public IMacro BuildEntity(MacroDto dto)
@@ -1,6 +1,5 @@
using System;
using System.Globalization;
using System.Text.RegularExpressions;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
@@ -10,17 +9,20 @@ namespace Umbraco.Core.Persistence.Factories
{
private readonly IMediaType _contentType;
private readonly Guid _nodeObjectTypeId;
private readonly int _id;
private int _primaryKey;
public MediaFactory(IMediaType contentType, Guid nodeObjectTypeId)
public MediaFactory(IMediaType contentType, Guid nodeObjectTypeId, int id)
{
_contentType = contentType;
_nodeObjectTypeId = nodeObjectTypeId;
_id = id;
}
public MediaFactory(Guid nodeObjectTypeId)
public MediaFactory(Guid nodeObjectTypeId, int id)
{
_nodeObjectTypeId = nodeObjectTypeId;
_id = id;
}
#region Implementation of IEntityFactory<IMedia,ContentVersionDto>
@@ -62,27 +64,15 @@ namespace Umbraco.Core.Persistence.Factories
return BuildEntity(dto, _contentType);
}
public MediaDto BuildDto(IMedia entity)
public ContentVersionDto BuildDto(IMedia entity)
{
var versionDto = new ContentVersionDto
{
NodeId = entity.Id,
VersionDate = entity.UpdateDate,
VersionId = entity.Version,
ContentDto = BuildContentDto(entity)
};
//Extract the media path for storage
string mediaPath;
TryMatch(entity.GetValue<string>("umbracoFile"), out mediaPath);
var dto = new MediaDto()
{
NodeId = entity.Id,
ContentVersionDto = versionDto,
MediaPath = mediaPath,
VersionId = entity.Version
};
var dto = new ContentVersionDto
{
NodeId = entity.Id,
VersionDate = entity.UpdateDate,
VersionId = entity.Version,
ContentDto = BuildContentDto(entity)
};
return dto;
}
@@ -129,30 +119,5 @@ namespace Umbraco.Core.Persistence.Factories
return nodeDto;
}
private static readonly Regex MediaPathPattern = new Regex(@"(/media/.+?)(?:['""]|$)", RegexOptions.Compiled);
/// <summary>
/// Try getting a media path out of the string being stored for media
/// </summary>
/// <param name="text"></param>
/// <param name="mediaPath"></param>
/// <returns></returns>
internal static bool TryMatch(string text, out string mediaPath)
{
mediaPath = null;
if (string.IsNullOrWhiteSpace(text))
return false;
var match = MediaPathPattern.Match(text);
if (match.Success == false || match.Groups.Count != 2)
return false;
var url = match.Groups[1].Value;
mediaPath = url;
return true;
}
}
}
@@ -56,10 +56,10 @@ namespace Umbraco.Core.Persistence.Factories
//Add the standard PropertyType to the current list
propertyTypes.Add(standardPropertyType.Value);
//Internal dictionary for adding "MemberCanEdit", "VisibleOnProfile", "IsSensitive" properties to each PropertyType
//Internal dictionary for adding "MemberCanEdit" and "VisibleOnProfile" properties to each PropertyType
memberType.MemberTypePropertyTypes.Add(standardPropertyType.Key,
new MemberTypePropertyProfileAccess(false, false, false));
new MemberTypePropertyProfileAccess(false, false));
}
memberType.NoGroupPropertyTypes = propertyTypes;
@@ -102,7 +102,7 @@ namespace Umbraco.Core.Persistence.Factories
{
//Internal dictionary for adding "MemberCanEdit" and "VisibleOnProfile" properties to each PropertyType
memberType.MemberTypePropertyTypes.Add(typeDto.Alias,
new MemberTypePropertyProfileAccess(typeDto.ViewOnProfile, typeDto.CanEdit, typeDto.IsSensitive));
new MemberTypePropertyProfileAccess(typeDto.ViewOnProfile, typeDto.CanEdit));
var tempGroupDto = groupDto;
@@ -157,7 +157,7 @@ namespace Umbraco.Core.Persistence.Factories
{
//Internal dictionary for adding "MemberCanEdit" and "VisibleOnProfile" properties to each PropertyType
memberType.MemberTypePropertyTypes.Add(typeDto.Alias,
new MemberTypePropertyProfileAccess(typeDto.ViewOnProfile, typeDto.CanEdit, typeDto.IsSensitive));
new MemberTypePropertyProfileAccess(typeDto.ViewOnProfile, typeDto.CanEdit));
//ensures that any built-in membership properties have their correct dbtype assigned no matter
//what the underlying data type is
@@ -198,4 +198,4 @@ namespace Umbraco.Core.Persistence.Factories
}
}
}
}
@@ -36,7 +36,6 @@ namespace Umbraco.Core.Persistence.Factories
user.Avatar = dto.Avatar;
user.EmailConfirmedDate = dto.EmailConfirmedDate;
user.InvitedDate = dto.InvitedDate;
user.TourData = dto.TourData;
//on initial construction we don't want to have dirty properties tracked
// http://issues.umbraco.org/issue/U4-1946
@@ -70,8 +69,7 @@ namespace Umbraco.Core.Persistence.Factories
UpdateDate = entity.UpdateDate,
Avatar = entity.Avatar,
EmailConfirmedDate = entity.EmailConfirmedDate,
InvitedDate = entity.InvitedDate,
TourData = entity.TourData
InvitedDate = entity.InvitedDate
};
foreach (var startNodeId in entity.StartContentIds)
@@ -1,41 +0,0 @@
using System.Collections.Concurrent;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Mappers
{
/// <summary>
/// Represents a mapper for audit entry entities.
/// </summary>
[MapperFor(typeof(IAuditEntry))]
[MapperFor(typeof(AuditEntry))]
public sealed class AuditEntryMapper : BaseMapper
{
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance
= new ConcurrentDictionary<string, DtoMapModel>();
/// <summary>
/// Initializes a new instance of the <see cref="AuditEntryMapper"/> class.
/// </summary>
public AuditEntryMapper()
{
// note: why the base ctor does not invoke BuildMap is a mystery to me
BuildMap();
}
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache => PropertyInfoCacheInstance;
internal override void BuildMap()
{
CacheMap<AuditEntry, AuditEntryDto>(entity => entity.Id, dto => dto.Id);
CacheMap<AuditEntry, AuditEntryDto>(entity => entity.PerformingUserId, dto => dto.PerformingUserId);
CacheMap<AuditEntry, AuditEntryDto>(entity => entity.PerformingDetails, dto => dto.PerformingDetails);
CacheMap<AuditEntry, AuditEntryDto>(entity => entity.PerformingIp, dto => dto.PerformingIp);
CacheMap<AuditEntry, AuditEntryDto>(entity => entity.EventDateUtc, dto => dto.EventDateUtc);
CacheMap<AuditEntry, AuditEntryDto>(entity => entity.AffectedUserId, dto => dto.AffectedUserId);
CacheMap<AuditEntry, AuditEntryDto>(entity => entity.AffectedDetails, dto => dto.AffectedDetails);
CacheMap<AuditEntry, AuditEntryDto>(entity => entity.EventType, dto => dto.EventType);
CacheMap<AuditEntry, AuditEntryDto>(entity => entity.EventDetails, dto => dto.EventDetails);
}
}
}
@@ -1,47 +0,0 @@
using System.Collections.Concurrent;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Mappers
{
[MapperFor(typeof(AuditItem))]
[MapperFor(typeof(IAuditItem))]
public sealed class AuditMapper : BaseMapper
{
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance = new ConcurrentDictionary<string, DtoMapModel>();
public AuditMapper(ISqlSyntaxProvider sqlSyntax) : base(sqlSyntax)
{
}
//NOTE: its an internal class but the ctor must be public since we're using Activator.CreateInstance to create it
// otherwise that would fail because there is no public constructor.
public AuditMapper()
{
BuildMap();
}
#region Overrides of BaseMapper
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache
{
get { return PropertyInfoCacheInstance; }
}
internal override void BuildMap()
{
if (PropertyInfoCache.IsEmpty)
{
CacheMap<AuditItem, LogDto>(src => src.Id, dto => dto.NodeId);
CacheMap<AuditItem, LogDto>(src => src.CreateDate, dto => dto.Datestamp);
CacheMap<AuditItem, LogDto>(src => src.UserId, dto => dto.UserId);
CacheMap<AuditItem, LogDto>(src => src.AuditType, dto => dto.Header);
CacheMap<AuditItem, LogDto>(src => src.Comment, dto => dto.Comment);
}
}
#endregion
}
}
@@ -1,40 +0,0 @@
using System.Collections.Concurrent;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Rdbms;
namespace Umbraco.Core.Persistence.Mappers
{
/// <summary>
/// Represents a mapper for consent entities.
/// </summary>
[MapperFor(typeof(IConsent))]
[MapperFor(typeof(Consent))]
public sealed class ConsentMapper : BaseMapper
{
private static readonly ConcurrentDictionary<string, DtoMapModel> PropertyInfoCacheInstance
= new ConcurrentDictionary<string, DtoMapModel>();
/// <summary>
/// Initializes a new instance of the <see cref="ConsentMapper"/> class.
/// </summary>
public ConsentMapper()
{
// note: why the base ctor does not invoke BuildMap is a mystery to me
BuildMap();
}
internal override ConcurrentDictionary<string, DtoMapModel> PropertyInfoCache => PropertyInfoCacheInstance;
internal override void BuildMap()
{
CacheMap<Consent, ConsentDto>(entity => entity.Id, dto => dto.Id);
CacheMap<Consent, ConsentDto>(entity => entity.Current, dto => dto.Current);
CacheMap<Consent, ConsentDto>(entity => entity.CreateDate, dto => dto.CreateDate);
CacheMap<Consent, ConsentDto>(entity => entity.Source, dto => dto.Source);
CacheMap<Consent, ConsentDto>(entity => entity.Context, dto => dto.Context);
CacheMap<Consent, ConsentDto>(entity => entity.Action, dto => dto.Action);
CacheMap<Consent, ConsentDto>(entity => entity.State, dto => dto.State);
CacheMap<Consent, ConsentDto>(entity => entity.Comment, dto => dto.Comment);
}
}
}
@@ -178,13 +178,11 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 2, StartMediaId = -1, StartContentId = -1, Alias = "writer", Name = "Writers", DefaultPermissions = "CAH:F", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-edit" });
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 3, StartMediaId = -1, StartContentId = -1, Alias = "editor", Name = "Editors", DefaultPermissions = "CADMOSKTPUZ:5Fï", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-tools" });
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 4, StartMediaId = -1, StartContentId = -1, Alias = Constants.Security.TranslatorGroupAlias, Name = "Translators", DefaultPermissions = "AF", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-globe" });
_database.Insert("umbracoUserGroup", "id", false, new UserGroupDto { Id = 5, StartMediaId = -1, StartContentId = -1, Alias = Constants.Security.SensitiveDataGroupAlias, Name = "Sensitive data", DefaultPermissions = "", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-lock" });
}
private void CreateUmbracoUser2UserGroupData()
{
_database.Insert(new User2UserGroupDto { UserGroupId = 1, UserId = 0 }); //add admin to admins
_database.Insert(new User2UserGroupDto { UserGroupId = 5, UserId = 0 }); //add admin to sensitive data
_database.Insert(new User2UserGroupDto { UserGroupId = 1, UserId = 0 });
}
private void CreateUmbracoUserGroup2AppData()
@@ -339,4 +337,4 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
_database.Insert("umbracoMigration", "pk", false, dto);
}
}
}
}
@@ -43,28 +43,27 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
{3, typeof (ContentDto)},
{4, typeof (ContentVersionDto)},
{5, typeof (DocumentDto)},
{6, typeof (MediaDto)},
{7, typeof (ContentTypeTemplateDto)},
{8, typeof (DataTypeDto)},
{9, typeof (DataTypePreValueDto)},
{10, typeof (DictionaryDto)},
{11, typeof (LanguageDto)},
{12, typeof (LanguageTextDto)},
{13, typeof (DomainDto)},
{14, typeof (LogDto)},
{15, typeof (MacroDto)},
{16, typeof (MacroPropertyDto)},
{17, typeof (MemberTypeDto)},
{18, typeof (MemberDto)},
{19, typeof (Member2MemberGroupDto)},
{20, typeof (ContentXmlDto)},
{21, typeof (PreviewXmlDto)},
{22, typeof (PropertyTypeGroupDto)},
{23, typeof (PropertyTypeDto)},
{24, typeof (PropertyDataDto)},
{25, typeof (RelationTypeDto)},
{26, typeof (RelationDto)},
{6, typeof (ContentTypeTemplateDto)},
{7, typeof (DataTypeDto)},
{8, typeof (DataTypePreValueDto)},
{9, typeof (DictionaryDto)},
{10, typeof (LanguageDto)},
{11, typeof (LanguageTextDto)},
{12, typeof (DomainDto)},
{13, typeof (LogDto)},
{14, typeof (MacroDto)},
{15, typeof (MacroPropertyDto)},
{16, typeof (MemberTypeDto)},
{17, typeof (MemberDto)},
{18, typeof (Member2MemberGroupDto)},
{19, typeof (ContentXmlDto)},
{20, typeof (PreviewXmlDto)},
{21, typeof (PropertyTypeGroupDto)},
{22, typeof (PropertyTypeDto)},
{23, typeof (PropertyDataDto)},
{24, typeof (RelationTypeDto)},
{25, typeof (RelationDto)},
{28, typeof (TagDto)},
{29, typeof (TagRelationshipDto)},
@@ -92,9 +91,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
{52, typeof (UserGroup2NodePermissionDto) },
{53, typeof (UserGroup2AppDto) },
{54, typeof (UserStartNodeDto) },
{55, typeof (UserLoginDto)},
{56, typeof (ConsentDto)},
{57, typeof (AuditEntryDto)}
};
#endregion
@@ -380,4 +376,4 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
#endregion
}
}
}
@@ -148,18 +148,6 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
return new Version(7, 6, 0);
}
//if the error is for cmsMedia it must be the previous version to 7.8 since that is when it is added
if (Errors.Any(x => x.Item1.Equals("Table") && (x.Item2.InvariantEquals("cmsMedia"))))
{
return new Version(7, 7, 0);
}
//if the error is for isSensitive column it must be the previous version to 7.9 since that is when it is added
if (Errors.Any(x => x.Item1.Equals("Column") && (x.Item2.InvariantEquals("cmsMemberType,isSensitive"))))
{
return new Version(7, 8, 0);
}
return UmbracoVersion.Current;
}
@@ -220,4 +208,4 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
return sb.ToString();
}
}
}
}
@@ -1,101 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.Factories;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenEightZero
{
[Migration("7.8.0", 1, Constants.System.UmbracoMigrationName)]
public class AddCmsMediaTable : MigrationBase
{
public AddCmsMediaTable(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger)
{
}
public override void Up()
{
var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray();
if (tables.InvariantContains("cmsMedia") == false)
{
Create.Table<MediaDto>();
MigrateMediaPaths();
}
}
private void MigrateMediaPaths()
{
Execute.Code(database =>
{
//Due to how much data there can be and that this query will result in executing an Index Scan on the cmsPropertyData PK
//which will literally iterate over every row in there (assume there's 1,000,000 and you can see why this will perform
//horribly) ultimately we need to fix this: http://issues.umbraco.org/issue/U4-10286
//so in the meantime I've found an ugly query to work around this Index Scan issue which is to use a sub-query of Ids.
//Doing this results in the same Index Scan taking place but it only visits the explicit rows that are provided, not every row
//in the cmsPropertyData table. This results in a tremendously faster query when there is tons of data.
//The will return any media property in nvarchar or ntext that is an umbracoFile that is not null.
//This will give us the least amount of data returned to work with.
var sql = @"SELECT cmsPropertyData.dataNvarchar, cmsPropertyData.dataNtext, umbracoNode.id, cmsContentVersion.VersionId
FROM cmsPropertyData
INNER JOIN cmsPropertyType ON cmsPropertyType.id = cmsPropertyData.propertytypeid
INNER JOIN umbracoNode ON umbracoNode.id = cmsPropertyData.contentNodeId
INNER JOIN cmsContentVersion ON cmsContentVersion.ContentId = umbracoNode.id
WHERE cmsPropertyType.Alias = (@alias)
AND umbracoNode.id IN (SELECT umbracoNode.id
FROM umbracoNode
INNER JOIN cmsContent ON cmsContent.nodeId = umbracoNode.id
INNER JOIN cmsContentType ON cmsContentType.nodeId = cmsContent.contentType
INNER JOIN cmsPropertyType ON cmsPropertyType.contentTypeId = cmsContentType.nodeId
WHERE cmsPropertyType.Alias = (@alias) AND umbracoNode.nodeObjectType = (@nodeObjectType))
AND (cmsPropertyData.dataNvarchar IS NOT NULL OR cmsPropertyData.dataNtext IS NOT NULL)";
var paths = new List<MediaDto>();
//using QUERY = a db cursor, we won't load this all into memory first, just row by row
foreach (var row in database.Query<dynamic>(sql, new {alias = "umbracoFile", nodeObjectType = Constants.ObjectTypes.Media}))
{
var id = (int) row.id;
var versionId = (Guid)row.VersionId;
string mediaPath = null;
//if there's values in dataNvarchar then ensure there's a media path match and extract it
if (row.dataNvarchar != null && MediaFactory.TryMatch((string) row.dataNvarchar, out mediaPath))
{
paths.Add(new MediaDto
{
MediaPath = mediaPath,
NodeId = id,
VersionId = versionId
});
}
//if there's values in dataNtext then ensure there's a media path match and extract it
else if (row.dataNtext != null && MediaFactory.TryMatch((string) row.dataNtext, out mediaPath))
{
paths.Add(new MediaDto
{
MediaPath = mediaPath,
NodeId = id,
VersionId = versionId
});
}
}
//now we need to insert paths for each item
database.BulkInsertRecords(paths, SqlSyntax);
return null;
});
}
public override void Down()
{
}
}
}
@@ -1,48 +0,0 @@
using System.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenEightZero
{
[Migration("7.8.0", 0, Constants.System.UmbracoMigrationName)]
public class AddIndexToPropertyTypeAliasColumn : MigrationBase
{
public AddIndexToPropertyTypeAliasColumn(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{ }
public override void Up()
{
Execute.Code(database =>
{
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database);
//make sure it doesn't already exist
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsPropertyTypeAlias")) == false)
{
var localContext = new LocalMigrationContext(Context.CurrentDatabaseProvider, database, SqlSyntax, Logger);
//we can apply the index
localContext.Create.Index("IX_cmsPropertyTypeAlias").OnTable("cmsPropertyType")
.OnColumn("Alias")
.Ascending()
.WithOptions()
.NonClustered();
return localContext.GetSql();
}
return null;
});
}
public override void Down()
{
Delete.Index("IX_cmsPropertyTypeAlias").OnTable("cmsPropertyType");
}
}
}
@@ -1,32 +0,0 @@
using System.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenEightZero
{
[Migration("7.8.0", 2, Constants.System.UmbracoMigrationName)]
public class AddInstructionCountColumn : MigrationBase
{
public AddInstructionCountColumn(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{
}
public override void Up()
{
//Don't exeucte if the column is already there
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray();
if (columns.Any(x => x.TableName.InvariantEquals("umbracoCacheInstruction") && x.ColumnName.InvariantEquals("instructionCount")) == false)
Create.Column("instructionCount")
.OnTable("umbracoCacheInstruction")
.AsInt32()
.WithDefaultValue(1)
.NotNullable();
}
public override void Down()
{
}
}
}
@@ -1,38 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenEightZero
{
[Migration("7.8.0", 1, Constants.System.UmbracoMigrationName)]
public class AddTourDataUserColumn : MigrationBase
{
public AddTourDataUserColumn(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{
}
public override void Up()
{
//Don't exeucte if the column is already there
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray();
if (columns.Any(x => x.TableName.InvariantEquals("umbracoUser") && x.ColumnName.InvariantEquals("tourData")) == false)
{
var textType = SqlSyntax.GetSpecialDbType(SpecialDbTypes.NTEXT);
Create.Column("tourData").OnTable("umbracoUser").AsCustom(textType).Nullable();
}
}
public override void Down()
{
}
}
}
@@ -1,29 +0,0 @@
using System.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenEightZero
{
[Migration("7.8.0", 4, Constants.System.UmbracoMigrationName)]
public class AddUserLoginTable : MigrationBase
{
public AddUserLoginTable(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger)
{
}
public override void Up()
{
var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray();
if (tables.InvariantContains("umbracoUserLogin") == false)
{
Create.Table<UserLoginDto>();
}
}
public override void Down()
{
}
}
}
@@ -1,35 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.DatabaseAnnotations;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenEightZero
{
[Migration("7.9.0", 1, Constants.System.UmbracoMigrationName)]
public class AddIsSensitiveMemberTypeColumn : MigrationBase
{
public AddIsSensitiveMemberTypeColumn(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{
}
public override void Up()
{
//Don't exeucte if the column is already there
var columns = SqlSyntax.GetColumnsInSchema(Context.Database).ToArray();
if (columns.Any(x => x.TableName.InvariantEquals("cmsMemberType") && x.ColumnName.InvariantEquals("isSensitive")) == false)
{
Create.Column("isSensitive").OnTable("cmsMemberType").AsBoolean().WithDefaultValue(0).NotNullable();
}
}
public override void Down()
{
}
}
}
@@ -1,29 +0,0 @@
using System;
using System.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenNineZero
{
[Migration("7.9.0", 1, Constants.System.UmbracoMigrationName)]
public class AddUmbracoAuditTable : MigrationBase
{
public AddUmbracoAuditTable(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{ }
public override void Up()
{
var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray();
if (tables.InvariantContains(AuditEntryDto.TableName))
return;
Create.Table<AuditEntryDto>();
}
public override void Down()
{
throw new NotSupportedException();
}
}
}
@@ -1,29 +0,0 @@
using System.Linq;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenNineZero
{
[Migration("7.9.0", 1, Constants.System.UmbracoMigrationName)]
public class AddUmbracoConsentTable : MigrationBase
{
public AddUmbracoConsentTable(ISqlSyntaxProvider sqlSyntax, ILogger logger) : base(sqlSyntax, logger)
{
}
public override void Up()
{
var tables = SqlSyntax.GetTablesInSchema(Context.Database).ToArray();
if (tables.InvariantContains(ConsentDto.TableName))
return;
Create.Table<ConsentDto>();
}
public override void Down()
{
}
}
}
@@ -1,37 +0,0 @@
using System;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenNineZero
{
[Migration("7.9.0", 2, Constants.System.UmbracoMigrationName)]
public class CreateSensitiveDataUserGroup : MigrationBase
{
public CreateSensitiveDataUserGroup(ISqlSyntaxProvider sqlSyntax, ILogger logger)
: base(sqlSyntax, logger)
{
}
public override void Up()
{
Execute.Code(database =>
{
//Don't exeucte if the group is already there
var exists = database.ExecuteScalar<int>("SELECT COUNT(*) FROM umbracoUserGroup WHERE userGroupAlias = @userGroupAlias",
new {userGroupAlias = Constants.Security.SensitiveDataGroupAlias });
if (exists == 0)
{
var resultId = database.Insert("umbracoUserGroup", "id", new UserGroupDto { StartMediaId = -1, StartContentId = -1, Alias = Constants.Security.SensitiveDataGroupAlias, Name = "Sensitive data", DefaultPermissions = "", CreateDate = DateTime.Now, UpdateDate = DateTime.Now, Icon = "icon-lock" });
database.Insert(new User2UserGroupDto { UserGroupId = Convert.ToInt32(resultId), UserId = 0 }); //add admin to sensitive data
}
return string.Empty;
});
}
public override void Down()
{
}
}
}
@@ -1,5 +1,6 @@
using System;
using System.Data;
using System.Data.SqlClient;
using Umbraco.Core.Persistence.FaultHandling;
namespace Umbraco.Core.Persistence
@@ -1,12 +1,16 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Data.SqlServerCe;
using System.Linq;
using System.Text.RegularExpressions;
using MySql.Data.MySqlClient;
using StackExchange.Profiling.Data;
using Umbraco.Core.Logging;
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
using Umbraco.Core.Persistence.Querying;
using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Persistence

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