Skip to content

Commit

Permalink
merge hotfix
Browse files Browse the repository at this point in the history
  • Loading branch information
tmm360 committed Jun 2, 2023
2 parents 9daedc2 + 909828d commit 48fddcb
Show file tree
Hide file tree
Showing 72 changed files with 3,550 additions and 2,898 deletions.
7 changes: 0 additions & 7 deletions EthernaSSO.sln
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
README.md = README.md
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{61C8B690-EEA5-440E-B5B5-7C8D5098503C}"
ProjectSection(SolutionItems) = preProject
.github\workflows\stable-release.yml = .github\workflows\stable-release.yml
.github\workflows\unstable-release.yml = .github\workflows\unstable-release.yml
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EthernaSSO.Persistence.Tests", "test\EthernaSSO.Persistence.Tests\EthernaSSO.Persistence.Tests.csproj", "{7928405E-1942-4B8A-AEFB-447EEEA092B7}"
EndProject
Global
Expand Down Expand Up @@ -76,7 +70,6 @@ Global
{5AE428C2-CD56-4E51-A229-3F4C137D9D83} = {A0B68B53-E0DF-4EC9-AFAA-7476C8A26256}
{AF83D80A-77BE-48C8-ABE3-D1373F20F2B0} = {5AE428C2-CD56-4E51-A229-3F4C137D9D83}
{8EE2E2BE-2FB6-4E96-8F34-08F9CDACFCFE} = {BB9B2543-8741-4D95-AC15-35923C422E60}
{61C8B690-EEA5-440E-B5B5-7C8D5098503C} = {1C01CDAC-366E-4F9B-8A52-25F7770FE92A}
{7928405E-1942-4B8A-AEFB-447EEEA092B7} = {10DAD3ED-08F6-48B9-A298-60D0ABF3B2E2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
Expand Down
8 changes: 4 additions & 4 deletions src/EthernaSSO.Domain/EthernaSSO.Domain.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Etherna.Authentication.AspNetCore" Version="0.3.1" />
<PackageReference Include="Etherna.DomainEvents" Version="1.4.0" />
<PackageReference Include="EthernaACR" Version="0.3.8" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.Etherna" Version="0.3.0-alpha.7" />
<PackageReference Include="MongODM.Core" Version="0.24.0-alpha.80" />
<PackageReference Include="Nethereum.Accounts" Version="4.13.0" />
<PackageReference Include="EthernaACR" Version="0.3.9" />
<PackageReference Include="MongODM.Core" Version="0.24.0-alpha.93" />
<PackageReference Include="Nethereum.Accounts" Version="4.14.0" />
</ItemGroup>

</Project>
1 change: 1 addition & 0 deletions src/EthernaSSO.Domain/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@
using System.Diagnostics.CodeAnalysis;

[assembly: SuppressMessage("Usage", "CA2214:Do not call overridable methods in constructors", Justification = "Overridability is needed for permit to use proxy models. Setting methods for data validation", Scope = "namespaceanddescendants", Target = "~N:Etherna.SSOServer.Domain.Models")]
[assembly: SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "Domain models can", Scope = "namespaceanddescendants", Target = "~N:Etherna.SSOServer.Domain.Models")]
1 change: 1 addition & 0 deletions src/EthernaSSO.Domain/ISsoDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ namespace Etherna.SSOServer.Domain
public interface ISsoDbContext : IDbContext
{
IRepository<AlphaPassRequest, string> AlphaPassRequests { get; }
IRepository<ApiKey, string> ApiKeys { get; }
IRepository<DailyStats, string> DailyStats { get; }
IRepository<Invitation, string> Invitations { get; }
IRepository<Role, string> Roles { get; }
Expand Down
85 changes: 85 additions & 0 deletions src/EthernaSSO.Domain/Models/ApiKey.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2021-present Etherna Sagl
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System;
using System.Security.Cryptography;
using System.Text;

namespace Etherna.SSOServer.Domain.Models
{
public class ApiKey : EntityModelBase<string>
{
// Consts.
public const int KeyLength = 64;
public const string KeyValidChars = "0123456789" + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public const int LabelMaxLength = 25;
public const int MaxKeysPerUser = 10;

// Static fields.
private static readonly SHA256 sha256Encoder = SHA256.Create();

// Constructors.
public ApiKey(
string plainKey,
string label,
DateTime? endOfLife,
UserBase owner)
{
if (string.IsNullOrEmpty(plainKey))
throw new ArgumentException($"'{nameof(plainKey)}' cannot be null or empty.", nameof(plainKey));
if (string.IsNullOrWhiteSpace(label))
throw new ArgumentException($"'{nameof(label)}' cannot be null or whitespace.", nameof(label));
if (label.Length > LabelMaxLength)
throw new ArgumentException($"'{nameof(label)}' cannot be longer than {LabelMaxLength}.", nameof(label));

EndOfLife = endOfLife;
KeyHash = HashKey(plainKey);
Label = label;
Owner = owner ?? throw new ArgumentNullException(nameof(owner));
}
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
protected ApiKey() { }
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.

// Properties.
public virtual DateTime? EndOfLife { get; protected set; }
public virtual bool IsAlive => EndOfLife is null || DateTime.UtcNow <= EndOfLife;
public virtual byte[] KeyHash { get; protected set; }
public virtual string Label { get; protected set; }
public virtual UserBase Owner { get; protected set; }

// Helpers.
public static string GetPrettyPrintedPlainKey(string plainKey, UserBase owner)
{
if (plainKey is null)
throw new ArgumentNullException(nameof(plainKey));
if (owner is null)
throw new ArgumentNullException(nameof(owner));

return $"{owner.Id}:{plainKey}";
}

public static string GetRandomPlainKey()
{
var codeBuilder = new StringBuilder();
for (int i = 0; i < KeyLength; i++)
codeBuilder.Append(KeyValidChars[RandomNumberGenerator.GetInt32(KeyValidChars.Length)]);

return codeBuilder.ToString();
}

public static byte[] HashKey(string plainKey) =>
sha256Encoder.ComputeHash(Encoding.UTF8.GetBytes(plainKey));
}
}
53 changes: 0 additions & 53 deletions src/EthernaSSO.Domain/Models/UserAgg/UserLoginInfo.cs

This file was deleted.

20 changes: 10 additions & 10 deletions src/EthernaSSO.Domain/Models/UserBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ public abstract class UserBase : EntityModelBase<string>
// Consts.
public static readonly IEnumerable<string> DomainManagedClaimNames = new[]
{
ClaimTypes.EtherAddress,
ClaimTypes.EtherPreviousAddresses,
ClaimTypes.IsWeb3Account,
ClaimTypes.Role,
ClaimTypes.Username
EthernaClaimTypes.EtherAddress,
EthernaClaimTypes.EtherPreviousAddresses,
EthernaClaimTypes.IsWeb3Account,
EthernaClaimTypes.Role,
EthernaClaimTypes.Username
};

// Fields.
Expand Down Expand Up @@ -76,14 +76,14 @@ public virtual IEnumerable<UserClaim> DefaultClaims
{
var claims = new List<UserClaim>
{
new UserClaim(ClaimTypes.EtherAddress, EtherAddress),
new UserClaim(ClaimTypes.EtherPreviousAddresses, JsonSerializer.Serialize(_etherPreviousAddresses)),
new UserClaim(ClaimTypes.IsWeb3Account, (this is UserWeb3).ToString()),
new UserClaim(ClaimTypes.Username, Username)
new UserClaim(EthernaClaimTypes.EtherAddress, EtherAddress),
new UserClaim(EthernaClaimTypes.EtherPreviousAddresses, JsonSerializer.Serialize(_etherPreviousAddresses)),
new UserClaim(EthernaClaimTypes.IsWeb3Account, (this is UserWeb3).ToString()),
new UserClaim(EthernaClaimTypes.Username, Username)
};

foreach (var role in _roles)
claims.Add(new UserClaim(ClaimTypes.Role, role.NormalizedName));
claims.Add(new UserClaim(EthernaClaimTypes.Role, role.NormalizedName));

return claims;
}
Expand Down
43 changes: 1 addition & 42 deletions src/EthernaSSO.Domain/Models/UserWeb2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,13 @@
using Nethereum.Web3.Accounts;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Etherna.SSOServer.Domain.Models
{
public class UserWeb2 : UserBase
{
// Fields.
private Account? _etherManagedAccount;
private List<UserAgg.UserLoginInfo> _logins = new();
private List<string> _twoFactorRecoveryCode = new();

// Constructors.
Expand All @@ -36,19 +34,14 @@ public UserWeb2(
UserBase? invitedBy,
bool invitedByAdmin,
string etherManagedPrivateKey,
UserSharedInfo sharedInfo,
UserAgg.UserLoginInfo? loginInfo = default)
UserSharedInfo sharedInfo)
: base(username, invitedBy, invitedByAdmin, sharedInfo)
{
// Verify that private key generates correct ether address.
var account = new Account(etherManagedPrivateKey);
if (account.Address != sharedInfo.EtherAddress)
throw new ArgumentException("Ethereum managed private key doesn't generate same address of shared info");

// Initialize.
if (loginInfo is not null)
AddLogin(loginInfo);

EtherManagedPrivateKey = etherManagedPrivateKey;
}
protected UserWeb2() { }
Expand All @@ -58,19 +51,11 @@ protected UserWeb2() { }
public virtual string? AuthenticatorKey { get; set; }
public virtual bool CanLoginWithEmail => NormalizedEmail != null && PasswordHash != null;
public virtual bool CanLoginWithEtherAddress => EtherLoginAddress != null;
public virtual bool CanLoginWithExternalProvider => Logins.Any();
public virtual bool CanLoginWithUsername => NormalizedUsername != null && PasswordHash != null;
public virtual bool CanRemoveEtherLoginAddress =>
CanLoginWithEtherAddress &&
(CanLoginWithEmail ||
CanLoginWithExternalProvider ||
CanLoginWithUsername);
public virtual bool CanRemoveExternalLogin =>
CanLoginWithExternalProvider &&
(CanLoginWithEmail ||
CanLoginWithEtherAddress ||
CanLoginWithUsername ||
Logins.Count() >= 2);
public override string EtherAddress
{
get => EtherManagedAccount.Address;
Expand All @@ -81,12 +66,6 @@ public override string EtherAddress
[PersonalData]
public virtual string? EtherLoginAddress { get; protected set; }
public virtual bool HasPassword => !string.IsNullOrEmpty(PasswordHash);
[PersonalData]
public virtual IEnumerable<UserAgg.UserLoginInfo> Logins
{
get => _logins;
protected set => _logins = new List<UserAgg.UserLoginInfo>(value ?? Array.Empty<UserAgg.UserLoginInfo>());
}
public virtual string? PasswordHash { get; set; }
public virtual bool TwoFactorEnabled { get; set; }
public virtual IEnumerable<string> TwoFactorRecoveryCodes
Expand All @@ -96,17 +75,6 @@ public virtual IEnumerable<string> TwoFactorRecoveryCodes
}

// Methods.
[PropertyAlterer(nameof(Logins))]
public virtual bool AddLogin(UserAgg.UserLoginInfo userLoginInfo)
{
//avoid multiaccounting with same provider
if (Logins.Any(login => login.LoginProvider == userLoginInfo.ProviderKey))
return false;

_logins.Add(userLoginInfo);
return true;
}

[PropertyAlterer(nameof(AccessFailedCount))]
public virtual void IncrementAccessFailedCount() => AccessFailedCount++;

Expand Down Expand Up @@ -135,15 +103,6 @@ public virtual bool RemoveEtherLoginAddress()
return true;
}

[PropertyAlterer(nameof(Logins))]
public virtual bool RemoveExternalLogin(string loginProvider, string providerKey)
{
if (!CanRemoveExternalLogin)
throw new InvalidOperationException();

return _logins.RemoveAll(l => l.LoginProvider == loginProvider && l.ProviderKey == providerKey) > 0;
}

[PropertyAlterer(nameof(AccessFailedCount))]
public virtual void ResetAccessFailedCount() => AccessFailedCount = 0;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,23 @@
// limitations under the License.

using Etherna.MongODM.Core;
using Etherna.MongODM.Core.Extensions;
using Etherna.MongODM.Core.Serialization;
using Etherna.SSOServer.Domain.Models.UserAgg;
using Etherna.SSOServer.Domain.Models;

namespace Etherna.SSOServer.Persistence.ModelMaps.Sso
{
internal sealed class UserLoginInfoMap : IModelMapsCollector
internal sealed class ApiKeyMap : IModelMapsCollector
{
public void Register(IDbContext dbContext)
{
dbContext.MapRegistry.AddModelMap<UserLoginInfo>("6cec179b-807a-4ff9-977b-9314a60725a7");
dbContext.MapRegistry.AddModelMap<ApiKey>("4c9f5ecd-37b7-425e-8cc4-96ec97ef443b", mm =>
{
mm.AutoMap();

// Set members with custom serializers.
mm.SetMemberSerializer(k => k.Owner, UserMap.ReferenceSerializer(dbContext));
});
}
}
}
1 change: 0 additions & 1 deletion src/EthernaSSO.Persistence/ModelMaps/Sso/UserMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ public void Register(IDbContext dbContext)
// Set members to ignore if null.
mm.GetMemberMap(u => u.EtherLoginAddress).SetIgnoreIfNull(true);
mm.GetMemberMap(u => u.EtherManagedPrivateKey).SetIgnoreIfNull(true);
mm.GetMemberMap(u => u.Logins).SetIgnoreIfNull(true);
mm.GetMemberMap(u => u.PasswordHash).SetIgnoreIfNull(true);
});
dbContext.MapRegistry.AddModelMap<UserWeb3>("7d8804ab-217c-476a-a47f-977fe693fce3");
Expand Down
6 changes: 3 additions & 3 deletions src/EthernaSSO.Persistence/Repositories/DomainRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,16 @@ public override async Task DeleteAsync(TModel model, CancellationToken cancellat
if (model is null)
throw new ArgumentNullException(nameof(model));

// Delete entity.
await base.DeleteAsync(model, cancellationToken);

// Dispatch custom events.
if (EventDispatcher != null)
{
await EventDispatcher.DispatchAsync(model.Events);
model.ClearEvents();
}

// Delete entity.
await base.DeleteAsync(model, cancellationToken);

// Dispatch deleted event.
if (EventDispatcher != null)
await EventDispatcher.DispatchAsync(
Expand Down
Loading

0 comments on commit 48fddcb

Please sign in to comment.