dolittle/DotNET.SDK

View on GitHub
Source/Security/Claims.cs

Summary

Maintainability
A
1 hr
Test Coverage
C
76%
// Copyright (c) Dolittle. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Dolittle.SDK.Concepts;

namespace Dolittle.SDK.Security;

/// <summary>
/// Represents a set of <see cref="Claim">Claims</see>.
/// </summary>
public class Claims : IEnumerable<Claim>, IEquatable<Claims>
{
    /// <summary>
    /// Gets the empty representation of <see cref="Claims"/>.
    /// </summary>
    public static readonly Claims Empty = new(Array.Empty<Claim>());

    readonly List<Claim> _claims = new();

    /// <summary>
    /// Initializes a new instance of the <see cref="Claims"/> class.
    /// </summary>
    /// <param name="claims">The claims to populate.</param>
    public Claims(IEnumerable<Claim> claims)
    {
        _claims.AddRange(claims ?? Enumerable.Empty<Claim>());
    }

    /// <summary>
    /// Uses the same equality as the Equals method.
    /// </summary>
    /// <param name="leftHandSide">Left hand side <see cref="Claim"/>.</param>
    /// <param name="rightHandSide">Right hand side <see cref="Claim"/>.</param>
    /// <returns>True if equals, false otherwise.</returns>
    public static bool operator ==(Claims leftHandSide, Claims rightHandSide)
    {
        if (Equals(leftHandSide, null) && Equals(rightHandSide, null))
        {
            return true;
        }

        return !Equals(leftHandSide, null) && leftHandSide.Equals(rightHandSide);
    }

    /// <summary>
    /// Uses the same equality as the Equals method.
    /// </summary>
    /// <param name="leftHandSide">Left hand side <see cref="Claim"/>.</param>
    /// <param name="rightHandSide">Right hand side <see cref="Claim"/>.</param>
    /// <returns>true if not equals, false otherwise.</returns>
    public static bool operator !=(Claims leftHandSide, Claims rightHandSide)
    {
        return !(leftHandSide == rightHandSide);
    }

    /// <inheritdoc/>
    public bool Equals(Claims other)
    {
        if (other == null || other.Count() != this.Count())
        {
            return false;
        }

        var thisClaims = _claims.OrderBy(_ => _.Name).ThenBy(_ => _.ValueType).ThenBy(_ => _.Value).ToArray();
        var otherClaims = other.OrderBy(_ => _.Name).ThenBy(_ => _.ValueType).ThenBy(_ => _.Value).ToArray();

        for (var i = 0; i < thisClaims.Length; i++)
        {
            if (!Equals(thisClaims[i], otherClaims[i]))
            {
                return false;
            }
        }

        return true;
    }

    /// <inheritdoc/>
    public override bool Equals(object other)
    {
        return Equals(other as Claims);
    }

    /// <inheritdoc/>
    public override int GetHashCode()
    {
        var array = _claims.OrderBy(_ => _.Name).ThenBy(_ => _.ValueType).ThenBy(_ => _.Value).ToArray();
        return HashCodeHelper.GetHashCode(array);
    }

    /// <summary>
    /// Gets an enumerator to iterate over the claims.
    /// </summary>
    /// <returns><see cref="IEnumerator{T}"/> of <see cref="Claim"/>.</returns>
    public IEnumerator<Claim> GetEnumerator()
    {
        return _claims.GetEnumerator();
    }

    /// <summary>
    /// Gets an enumerator to iterate over the claims.
    /// </summary>
    /// <returns><see cref="IEnumerator"/> of <see cref="Claim"/>.</returns>
    IEnumerator IEnumerable.GetEnumerator()
    {
        return _claims.GetEnumerator();
    }
}