using Socialize.Api.Modules.Identity.Contracts; namespace Socialize.Api.Modules.Approvals.Services; public static class ApprovalModes { public const string None = "None"; public const string Optional = "Optional"; public const string Required = "Required"; public const string MultiLevel = "Multi-level"; } public static class ApprovalWorkflowRules { public static bool BlocksManualApprovedOrScheduledStatus(string approvalMode) { return approvalMode is ApprovalModes.Required or ApprovalModes.MultiLevel; } public static bool IsApprovalCompletionStatus(string status) { return status is "Approved" or "Scheduled"; } public static string GetFinalApprovalStatus(bool schedulePostsAutomaticallyOnApproval, DateTimeOffset? plannedPublishDate) { return schedulePostsAutomaticallyOnApproval && plannedPublishDate.HasValue ? "Scheduled" : "Approved"; } public static bool HasRequiredStepApprovals(int approvedDecisionCount, int requiredApproverCount) { return approvedDecisionCount >= Math.Max(1, requiredApproverCount); } public static bool CanApproveWorkflowStep( bool isAdministrator, bool hasWorkspaceAccess, IReadOnlyCollection userRoles, Guid userId, string? targetType, string? targetValue) { if (isAdministrator) { return true; } if (!hasWorkspaceAccess || string.IsNullOrWhiteSpace(targetType) || string.IsNullOrWhiteSpace(targetValue)) { return false; } return targetType switch { ApprovalStepTargetTypes.Role => userRoles.Contains(targetValue), ApprovalStepTargetTypes.Membership => MatchesMembershipTarget(userRoles, targetValue), ApprovalStepTargetTypes.Member => ParseMemberTargetIds(targetValue).Contains(userId), _ => false, }; } public static IReadOnlyCollection ParseMemberTargetIds(string? targetValue) { if (string.IsNullOrWhiteSpace(targetValue)) { return []; } return targetValue .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) .Select(value => Guid.TryParse(value, out Guid memberUserId) ? memberUserId : Guid.Empty) .Where(memberUserId => memberUserId != Guid.Empty) .Distinct() .ToArray(); } public static string FormatMemberTargetValue(IEnumerable memberUserIds) { return string.Join(",", memberUserIds.Distinct().OrderBy(memberUserId => memberUserId)); } private static bool MatchesMembershipTarget( IReadOnlyCollection userRoles, string targetValue) { return targetValue switch { ApprovalMembershipTargets.Client => userRoles.Contains(KnownRoles.Client), ApprovalMembershipTargets.Team => !userRoles.Contains(KnownRoles.Client), _ => false, }; } }