Czy warto opakowywać Identity w interfejs?

1

Mam projekt, w którym korzystam z Identity (Core). Czy lepiej bezpośrednio korzystać z UserManagera i innych, czy może lepiej napisać jakiś IAuthService + implementację i to ich używać?

1

Wszystko zależy od tego jaka jest skala projektu, czy użyta technologia może się zmienić, czy użycie nie-wyabstrachowanej autentykacji utrudni testowanie itp. Moim zdaniem zazwyczaj nie ma takiej potrzeby.

0

Czy zdarzyło się komuś wymieniać Idenitity na inną bibliotekę? Czy istnieje w ogóle jakaś alternatywa dla Identity?

1

Nawet jeśli nie ma obecnie alternatywy, to nic nie stoi chyba na przeszkodzie, żeby taką sobie samemu w swoim projekcie wdrożyć.

Nie piszę w Core, ale nawet jeśli Identity jest świetne i ma wbudowane wszystko, co może być potrzebne, to trzeba by je referencjonować we wszystkich warstwach aplikacji. A to może nie być ładne, dlatego ja bym prawdopodobnie opakował.

0

Powiedzmy, że opakowuję UserManager<User> w IUserManager (wydaje mi się, że AuthService to lepsza nazwa dla usługi logującej, rejestrującej itd. operującej bezpośrednio na viewmodelach). Czy wtedy interfejs + implementacja mogą wyglądać np. tak:

public interface IUserManager
    {
        int? GetUserId(ClaimsPrincipal user);

        string GetUserName(ClaimsPrincipal user);

        Task<Result> CreateAsync(User user, string password);
    }
public class UserManager : IUserManager
    {
        // UserManager from Identity
        private readonly UserManager<User> _userManager;

        public UserManager(UserManager<User> userManager)
        {
            _userManager = userManager;
        }

        public int? GetUserId(ClaimsPrincipal user)
        {
            var isLoggedIn = int.TryParse(_userManager.GetUserId(user), out int userId);

            return isLoggedIn ? userId : (int?) null;
        }

        public string GetUserName(ClaimsPrincipal user)
        {
            return _userManager.GetUserName(user);
        }

        public async Task<Result> CreateAsync(User user, string password)
        {
            var result = await _userManager.CreateAsync(user, password);
            
            if (!result.Succeeded)
            {
                // TODO log errors
                
                return new Result(new Error(ErrorName.NotKnown));
            }

            return new Result(null);
        }
    }
0

Jakby nie rozumiem po co metody przyjmują ClaimsPrincipal. Jak dla mnie taki wrapper powinien ukrywać wszystkie szczegóły implementacyjne.

0

Yyy, nie rozumiem. Skoro metoda CreateAsync w UserManager<User> przyjmuje ClaimsPrincipal, to co powinienem przekazać do wrappera?

EDIT:
Chodzi o to, żeby użyć ClaimsPrincipal.Current?

1

No najlepiej to chyba nic. Ja bym widział taki interfejs:

ISecurityContext
{
    int GetCurrentUserId();
    string GetCurrentUserName();
    int GetCurrentUserUnitId();
}

I tak dalej dla wszystkich claimsów mających biznesowe znaczenie, i żadnego Create tutaj (bo to nie jest coś, co jest potrzebne w całej aplikacji).

Bo jeśli robić taki wrapper, który tylko opakowuje metody z UserManager, to ja nie wiem jaki jest z tego zysk.

0

OK, teraz widzę.

  1. Właściwie to implementacje tych metod mogę zrobić bez korzystania z UserManagera z Identity (patrzyłem na implementacje w Identity, są dość krótkie). Warto? Nie trzeba by było wtedy przy każdym żądaniu tworzyć UserManagera.
  2. Czyli w AuthService powinienem korzystać bezpośrednio z UserManagera z Identity? AuthService potrzebuje dość specjalistycznych metod UserManagera, które raczej nigdzie indziej nie zostaną użyte.
  3. Co, jeśli korzystałbym z małej biblioteki, której wszystkie metody są mi potrzebne i wszystkie są dość dobrze dostosowane do całej aplikacji? Skoro pisanie wrappera, który tylko opakowuje, nie ma sensu, a biblioteka może się zmienić, to co należy zrobić?

1 użytkowników online, w tym zalogowanych: 0, gości: 1