Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@
<PackageVersion Include="MiniProfiler.AspNetCore.Mvc" Version="4.5.4" />
<PackageVersion Include="MiniProfiler.Shared" Version="4.5.4" />
<PackageVersion Include="ncrontab" Version="3.3.3" />
<PackageVersion Include="NPoco" Version="5.7.1" />
<PackageVersion Include="NPoco.SqlServer" Version="5.7.1" />
<PackageVersion Include="NPoco" Version="6.1.0" />
<PackageVersion Include="NPoco.SqlServer" Version="6.1.0" />
<PackageVersion Include="OpenIddict.Abstractions" Version="6.2.1" />
<PackageVersion Include="OpenIddict.AspNetCore" Version="6.2.1" />
<PackageVersion Include="OpenIddict.EntityFrameworkCore" Version="6.2.1" />
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "10.0.100-preview.7.25380.108",
"version": "10.0.100-rc.1.25451.107",
"rollForward": "latestFeature",
"allowPrerelease": false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,14 @@ private static bool EndpointSupportsApiVersion(Endpoint endpoint, ApiVersion? re
{
ApiVersion[]? supportedApiVersions = endpoint.Metadata.GetMetadata<MapToApiVersionAttribute>()?.Versions.ToArray();

// if the endpoint is versioned, the requested API version must be among the API versions supported by the endpoint.
// if the endpoint is NOT versioned, it cannot be used with a requested API version
return supportedApiVersions?.Contains(requestedApiVersion) ?? requestedApiVersion is null;
// If the endpoint is versioned, the requested API version must be among the API versions supported by the endpoint.
// If the endpoint is NOT versioned, it cannot be used with a requested API version.
if (supportedApiVersions is not null && requestedApiVersion is not null)
{
return supportedApiVersions.Contains(requestedApiVersion);
}

return requestedApiVersion is null;
}

private static bool IsByIdsController(ControllerActionDescriptor? controllerActionDescriptor)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,12 @@ public IEnumerable<UserAccessEntity> ChildUserAccessEntities(
return ChildUserAccessEntities(children, userStartNodePaths);
}

int[] allowedChildIds = GetAllowedIds(userStartNodePaths, parentId);
// Need to use a List here because the expression tree cannot convert an array when used in Contains.
// See ExpressionTests.Sql_In().
List<int> allowedChildIds = GetAllowedIds(userStartNodePaths, parentId);

totalItems = allowedChildIds.Length;
if (allowedChildIds.Length == 0)
totalItems = allowedChildIds.Count;
if (allowedChildIds.Count == 0)
{
// The requested parent is outside the scope of any user start nodes.
return [];
Expand All @@ -102,7 +104,7 @@ public IEnumerable<UserAccessEntity> ChildUserAccessEntities(
return ChildUserAccessEntities(children, userStartNodePaths);
}

private static int[] GetAllowedIds(string[] userStartNodePaths, int parentId)
private static List<int> GetAllowedIds(string[] userStartNodePaths, int parentId)
{
// If one or more of the user start nodes are descendants of the requested parent, find the "next child IDs" in those user start node paths
// that are the final entries in the path.
Expand All @@ -112,7 +114,7 @@ private static int[] GetAllowedIds(string[] userStartNodePaths, int parentId)
.Where(ids => ids.Contains(parentId))
.Select(ids => ids[ids.IndexOf(parentId) + 1]) // Given the previous checks, the parent ID can never be the last in the user start node path, so this is safe
.Distinct()
.ToArray();
.ToList();
}

/// <inheritdoc />
Expand Down Expand Up @@ -185,9 +187,9 @@ out long totalAfter
return ChildUserAccessEntities(siblings, userStartNodePaths);
}

int[] allowedSiblingIds = GetAllowedIds(userStartNodePaths, targetParent.Id);
List<int> allowedSiblingIds = GetAllowedIds(userStartNodePaths, targetParent.Id);

if (allowedSiblingIds.Length == 0)
if (allowedSiblingIds.Count == 0)
{
// The requested target is outside the scope of any user start nodes.
totalBefore = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ private void ObtainReadLock()
throw new PanicException("Could not find a database");
}

if (!db.InTransaction)
if (db.InTransaction is false || db.Transaction is null)
{
throw new InvalidOperationException(
"SqlServerDistributedLockingMechanism requires a transaction to function.");
Expand Down Expand Up @@ -167,7 +167,7 @@ private void ObtainWriteLock()
throw new PanicException("Could not find a database");
}

if (!db.InTransaction)
if (db.InTransaction is false || db.Transaction is null)
{
throw new InvalidOperationException(
"SqlServerDistributedLockingMechanism requires a transaction to function.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,12 @@ public override IEnumerable<Tuple<string, string, string, bool>> GetDefinedIndex
/// <inheritdoc />
public override bool TryGetDefaultConstraint(IDatabase db, string? tableName, string columnName, [MaybeNullWhen(false)] out string constraintName)
{
if (string.IsNullOrWhiteSpace(tableName))
{
constraintName = null;
return false;
}

constraintName = db.Fetch<string>(
@"select con.[name] as [constraintName]
from sys.default_constraints con
Expand Down
4 changes: 2 additions & 2 deletions src/Umbraco.Core/Models/Notification.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace Umbraco.Cms.Core.Models;

public class Notification
{
public Notification(int entityId, int userId, string action, Guid? entityType)
public Notification(int entityId, int userId, string action, Guid entityType)
{
EntityId = entityId;
UserId = userId;
Expand All @@ -16,5 +16,5 @@ public Notification(int entityId, int userId, string action, Guid? entityType)

public string Action { get; }

public Guid? EntityType { get; }
public Guid EntityType { get; }
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Entities;
using Umbraco.Cms.Core.Models.Membership;
Expand All @@ -6,19 +7,19 @@ namespace Umbraco.Cms.Core.Persistence.Repositories;

public interface INotificationsRepository : IRepository
{
Notification CreateNotification(IUser user, IEntity entity, string action);
bool TryCreateNotification(IUser user, IEntity entity, string action, [NotNullWhen(true)] out Notification? notification);

int DeleteNotifications(IUser user);

int DeleteNotifications(IEntity entity);

int DeleteNotifications(IUser user, IEntity entity);

IEnumerable<Notification>? GetEntityNotifications(IEntity entity);
IEnumerable<Notification> GetEntityNotifications(IEntity entity);

IEnumerable<Notification>? GetUserNotifications(IUser user);
IEnumerable<Notification> GetUserNotifications(IUser user);

IEnumerable<Notification>? GetUsersNotifications(IEnumerable<int> userIds, string? action, IEnumerable<int> nodeIds, Guid objectType);
IEnumerable<Notification> GetUsersNotifications(IEnumerable<int> userIds, string? action, IEnumerable<int> nodeIds, Guid objectType);

IEnumerable<Notification> SetNotifications(IUser user, IEntity entity, string[] actions);
}
20 changes: 15 additions & 5 deletions src/Umbraco.Core/Services/ContentService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Collections.Immutable;

Check notice on line 1 in src/Umbraco.Core/Services/ContentService.cs

View check run for this annotation

CodeScene Delta Analysis / CodeScene Cloud Delta Analysis (v17/dev)

✅ Getting better: Code Duplication

reduced similar code in: GetPagedOfTypes. Avoid duplicated, aka copy-pasted, code inside the module. More duplication lowers the code health.
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -695,9 +695,13 @@

using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
{
// Need to use a List here because the expression tree cannot convert the array when used in Contains.
// See ExpressionTests.Sql_In().
List<int> contentTypeIdsAsList = [.. contentTypeIds];

scope.ReadLock(Constants.Locks.ContentTree);
return _documentRepository.GetPage(
Query<IContent>()?.Where(x => contentTypeIds.Contains(x.ContentTypeId)),
Query<IContent>()?.Where(x => contentTypeIdsAsList.Contains(x.ContentTypeId)),
pageIndex,
pageSize,
out totalRecords,
Expand Down Expand Up @@ -3759,7 +3763,10 @@
IQuery<IContent> query = Query<IContent>();
if (contentTypeId.Length > 0)
{
query.Where(x => contentTypeId.Contains(x.ContentTypeId));
// Need to use a List here because the expression tree cannot convert the array when used in Contains.
// See ExpressionTests.Sql_In().
List<int> contentTypeIdsAsList = [.. contentTypeId];
query.Where(x => contentTypeIdsAsList.Contains(x.ContentTypeId));
}

return _documentBlueprintRepository.Get(query).Select(x =>
Expand All @@ -3778,11 +3785,14 @@
{
scope.WriteLock(Constants.Locks.ContentTree);

var contentTypeIdsA = contentTypeIds.ToArray();
// Need to use a List here because the expression tree cannot convert an array when used in Contains.
// See ExpressionTests.Sql_In().
var contentTypeIdsAsList = contentTypeIds.ToList();

IQuery<IContent> query = Query<IContent>();
if (contentTypeIdsA.Length > 0)
if (contentTypeIdsAsList.Count > 0)
{
query.Where(x => contentTypeIdsA.Contains(x.ContentTypeId));
query.Where(x => contentTypeIdsAsList.Contains(x.ContentTypeId));
}

IContent[]? blueprints = _documentBlueprintRepository.Get(query)?.Select(x =>
Expand Down
12 changes: 10 additions & 2 deletions src/Umbraco.Core/Services/DataTypeService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,10 @@ public Task<IEnumerable<IDataType>> GetAllAsync(params Guid[] keys)
IQuery<IDataType> query = Query<IDataType>();
if (keys.Length > 0)
{
query = query.Where(x => keys.Contains(x.Key));
// Need to use a List here because the expression tree cannot convert the array when used in Contains.
// See ExpressionTests.Sql_In().
List<Guid> keysAsList = [.. keys];
query = query.Where(x => keysAsList.Contains(x.Key));
}

IDataType[] dataTypes = _dataTypeRepository.Get(query).ToArray();
Expand Down Expand Up @@ -398,7 +401,12 @@ public Task<IEnumerable<IDataType>> GetByEditorAliasAsync(string propertyEditorA
public Task<IEnumerable<IDataType>> GetByEditorAliasAsync(string[] propertyEditorAlias)
{
using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true);
IQuery<IDataType> query = Query<IDataType>().Where(x => propertyEditorAlias.Contains(x.EditorAlias));

// Need to use a List here because the expression tree cannot convert the array when used in Contains.
// See ExpressionTests.Sql_In().
List<string> propertyEditorAliasesAsList = [.. propertyEditorAlias];
IQuery<IDataType> query = Query<IDataType>().Where(x => propertyEditorAliasesAsList.Contains(x.EditorAlias));

IEnumerable<IDataType> dataTypes = _dataTypeRepository.Get(query).ToArray();
return Task.FromResult(dataTypes);
}
Expand Down
12 changes: 7 additions & 5 deletions src/Umbraco.Core/Services/INotificationService.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.Entities;
using Umbraco.Cms.Core.Models.Membership;
Expand Down Expand Up @@ -82,11 +83,12 @@ void SendNotifications(
IEnumerable<Notification>? SetNotifications(IUser? user, IEntity entity, string[] actions);

/// <summary>
/// Creates a new notification
/// Tries to create a new notification.
/// </summary>
/// <param name="user"></param>
/// <param name="entity"></param>
/// <param name="user">The user.</param>
/// <param name="entity">The entity.</param>
/// <param name="action">The action letter - note: this is a string for future compatibility</param>
/// <returns></returns>
Notification CreateNotification(IUser user, IEntity entity, string action);
/// <param name="notification">The created notification.</param>
/// <inheritdoc/>
bool TryCreateNotification(IUser user, IEntity entity, string action, [NotNullWhen(true)] out Notification? notification);
}
7 changes: 6 additions & 1 deletion src/Umbraco.Core/Services/MediaService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -498,10 +498,15 @@ public IEnumerable<IMedia> GetPagedOfTypes(int[] contentTypeIds, long pageIndex,
ordering = Ordering.By("sortOrder");
}

// Need to use a List here because the expression tree cannot convert the array when used in Contains.
// See ExpressionTests.Sql_In().
List<int> contentTypeIdsAsList = [.. contentTypeIds];

using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true);
scope.ReadLock(Constants.Locks.MediaTree);

return _mediaRepository.GetPage(
Query<IMedia>()?.Where(x => contentTypeIds.Contains(x.ContentTypeId)), pageIndex, pageSize, out totalRecords, filter, ordering);
Query<IMedia>()?.Where(x => contentTypeIdsAsList.Contains(x.ContentTypeId)), pageIndex, pageSize, out totalRecords, filter, ordering);
}

/// <summary>
Expand Down
15 changes: 5 additions & 10 deletions src/Umbraco.Core/Services/NotificationService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Concurrent;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -241,20 +242,14 @@ public void DeleteNotifications(IUser user, IEntity entity)
}
}

/// <summary>
/// Creates a new notification
/// </summary>
/// <param name="user"></param>
/// <param name="entity"></param>
/// <param name="action">The action letter - note: this is a string for future compatibility</param>
/// <returns></returns>
public Notification CreateNotification(IUser user, IEntity entity, string action)
/// <inheritdoc/>
public bool TryCreateNotification(IUser user, IEntity entity, string action, [NotNullWhen(true)] out Notification? notification)
{
using (ICoreScope scope = _uowProvider.CreateCoreScope())
{
Notification notification = _notificationsRepository.CreateNotification(user, entity, action);
var result = _notificationsRepository.TryCreateNotification(user, entity, action, out notification);
scope.Complete();
return notification;
return result;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ protected AsyncMigrationBase(IMigrationContext context)
/// <summary>
/// Gets the database type.
/// </summary>
protected DatabaseType DatabaseType => Context.Database.DatabaseType;
protected DatabaseType DatabaseType => (DatabaseType)Context.Database.DatabaseType;

/// <summary>
/// Builds a Create expression.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public void Do()
{
throw new NotSupportedException($"SQLite does not support ALTER TABLE operations. Instead you will have to:{Environment.NewLine}1. Create a temp table.{Environment.NewLine}2. Copy data from existing table into the temp table.{Environment.NewLine}3. Delete the existing table.{Environment.NewLine}4. Create a new table with the name of the table you're trying to alter, but with a new signature{Environment.NewLine}5. Copy data from the temp table into the new table.{Environment.NewLine}6. Delete the temp table.");
}

Expression.Execute();
}

Expand Down
11 changes: 8 additions & 3 deletions src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,20 +102,25 @@ public bool CanConnect(string? connectionString, string providerName)

public bool HasSomeNonDefaultUser()
{
if (_scopeAccessor.AmbientScope is null)
{
throw new InvalidOperationException("Cannot execute without a valid AmbientScope.");
}

using (ICoreScope scope = _scopeProvider.CreateCoreScope())
{
// look for the super user with default password
NPoco.Sql<ISqlContext>? sql = _scopeAccessor.AmbientScope?.Database.SqlContext.Sql()
NPoco.Sql<ISqlContext> sql = _scopeAccessor.AmbientScope.Database.SqlContext.Sql()
.SelectCount()
.From<UserDto>()
.Where<UserDto>(x => x.Id == Constants.Security.SuperUserId && x.Password == "default");
var result = _scopeAccessor.AmbientScope?.Database.ExecuteScalar<int>(sql);
var result = _scopeAccessor.AmbientScope.Database.ExecuteScalar<int>(sql);
var has = result != 1;
if (has == false)
{
// found only 1 user == the default user with default password
// however this always exists on uCloud, also need to check if there are other users too
result = _scopeAccessor.AmbientScope?.Database.ExecuteScalar<int>("SELECT COUNT(*) FROM umbracoUser");
result = _scopeAccessor.AmbientScope.Database.ExecuteScalar<int>("SELECT COUNT(*) FROM umbracoUser");
has = result != 1;
}
scope.Complete();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public abstract class MigrationExpressionBase : IMigrationExpression
protected MigrationExpressionBase(IMigrationContext context) =>
Context = context ?? throw new ArgumentNullException(nameof(context));

public DatabaseType DatabaseType => Context.Database.DatabaseType;
public IDatabaseType DatabaseType => Context.Database.DatabaseType;

protected IMigrationContext Context { get; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@ namespace Umbraco.Cms.Infrastructure.Persistence.Dtos;

[ResultColumn]
[Reference(ReferenceType.Many, ColumnName = "UniqueId", ReferenceMemberName = "UniqueId")]
public List<LanguageTextDto>? LanguageTextDtos { get; set; }
public List<LanguageTextDto> LanguageTextDtos { get; set; } = [];
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,5 @@ internal sealed class PropertyTypeGroupDto

[ResultColumn]
[Reference(ReferenceType.Many, ReferenceMemberName = "PropertyTypeGroupId")]
public List<PropertyTypeDto>? PropertyTypeDtos { get; set; }
public List<PropertyTypeDto> PropertyTypeDtos { get; set; } = [];
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ internal static PropertyTypeGroupDto BuildGroupDto(PropertyGroup propertyGroup,
}

dto.PropertyTypeDtos = propertyGroup.PropertyTypes
?.Select(propertyType => BuildPropertyTypeDto(propertyGroup.Id, propertyType, contentTypeId)).ToList();
?.Select(propertyType => BuildPropertyTypeDto(propertyGroup.Id, propertyType, contentTypeId)).ToList()
?? [];

return dto;
}
Expand Down
1 change: 1 addition & 0 deletions src/Umbraco.Infrastructure/Persistence/ISqlContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Umbraco.Cms.Core.Persistence.Querying;
using Umbraco.Cms.Infrastructure.Persistence.Mappers;
using Umbraco.Cms.Infrastructure.Persistence.SqlSyntax;
using IMapperCollection = Umbraco.Cms.Infrastructure.Persistence.Mappers.IMapperCollection;

namespace Umbraco.Cms.Infrastructure.Persistence;

Expand Down
Loading