mirror of
https://github.com/bitwarden/android.git
synced 2024-12-24 18:08:26 +03:00
user service
This commit is contained in:
parent
929727ba41
commit
13a2206735
4 changed files with 316 additions and 0 deletions
26
src/Core/Abstractions/IUserService.cs
Normal file
26
src/Core/Abstractions/IUserService.cs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models.Data;
|
||||||
|
using Bit.Core.Models.Domain;
|
||||||
|
|
||||||
|
namespace Bit.Core.Abstractions
|
||||||
|
{
|
||||||
|
public interface IUserService
|
||||||
|
{
|
||||||
|
Task<bool> CanAccessPremiumAsync();
|
||||||
|
Task ClearAsync();
|
||||||
|
Task ClearOrganizationsAsync(string userId);
|
||||||
|
Task<List<Organization>> GetAllOrganizationAsync();
|
||||||
|
Task<string> GetEmailAsync();
|
||||||
|
Task<KdfType?> GetKdfAsync();
|
||||||
|
Task<int?> GetKdfIterationsAsync();
|
||||||
|
Task<Organization> GetOrganizationAsync(string id);
|
||||||
|
Task<string> GetSecurityStampAsync();
|
||||||
|
Task<string> GetUserIdAsync();
|
||||||
|
Task<bool> IsAuthenticatedAsync();
|
||||||
|
Task ReplaceOrganizationsAsync(Dictionary<string, OrganizationData> organizations);
|
||||||
|
Task SetInformationAsync(string userId, string email, KdfType kdf, int kdfIterations);
|
||||||
|
Task SetSecurityStampAsync(string stamp);
|
||||||
|
}
|
||||||
|
}
|
45
src/Core/Models/Data/OrganizationData.cs
Normal file
45
src/Core/Models/Data/OrganizationData.cs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models.Response;
|
||||||
|
|
||||||
|
namespace Bit.Core.Models.Data
|
||||||
|
{
|
||||||
|
public class OrganizationData
|
||||||
|
{
|
||||||
|
public OrganizationData(ProfileOrganizationResponse response)
|
||||||
|
{
|
||||||
|
Id = response.Id;
|
||||||
|
Name = response.Name;
|
||||||
|
Status = response.Status;
|
||||||
|
Type = response.Type;
|
||||||
|
Enabled = response.Enabled;
|
||||||
|
UseGroups = response.UseGroups;
|
||||||
|
UseDirectory = response.UseDirectory;
|
||||||
|
UseEvents = response.UseEvents;
|
||||||
|
UseTotp = response.UseTotp;
|
||||||
|
Use2fa = response.Use2fa;
|
||||||
|
UseApi = response.UseApi;
|
||||||
|
SelfHost = response.SelfHost;
|
||||||
|
UsersGetPremium = response.UsersGetPremium;
|
||||||
|
Seats = response.Seats;
|
||||||
|
MaxCollections = response.MaxCollections;
|
||||||
|
MaxStorageGb = response.MaxStorageGb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public OrganizationUserStatusType Status { get; set; }
|
||||||
|
public OrganizationUserType Type { get; set; }
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
public bool UseGroups { get; set; }
|
||||||
|
public bool UseDirectory { get; set; }
|
||||||
|
public bool UseEvents { get; set; }
|
||||||
|
public bool UseTotp { get; set; }
|
||||||
|
public bool Use2fa { get; set; }
|
||||||
|
public bool UseApi { get; set; }
|
||||||
|
public bool SelfHost { get; set; }
|
||||||
|
public bool UsersGetPremium { get; set; }
|
||||||
|
public int Seats { get; set; }
|
||||||
|
public int MaxCollections { get; set; }
|
||||||
|
public short? MaxStorageGb { get; set; }
|
||||||
|
}
|
||||||
|
}
|
78
src/Core/Models/Domain/Organization.cs
Normal file
78
src/Core/Models/Domain/Organization.cs
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models.Data;
|
||||||
|
|
||||||
|
namespace Bit.Core.Models.Domain
|
||||||
|
{
|
||||||
|
public class Organization
|
||||||
|
{
|
||||||
|
public Organization() { }
|
||||||
|
|
||||||
|
public Organization(OrganizationData obj)
|
||||||
|
{
|
||||||
|
Id = obj.Id;
|
||||||
|
Name = obj.Name;
|
||||||
|
Status = obj.Status;
|
||||||
|
Type = obj.Type;
|
||||||
|
Enabled = obj.Enabled;
|
||||||
|
UseGroups = obj.UseGroups;
|
||||||
|
UseDirectory = obj.UseDirectory;
|
||||||
|
UseEvents = obj.UseEvents;
|
||||||
|
UseTotp = obj.UseTotp;
|
||||||
|
Use2fa = obj.Use2fa;
|
||||||
|
UseApi = obj.UseApi;
|
||||||
|
SelfHost = obj.SelfHost;
|
||||||
|
UsersGetPremium = obj.UsersGetPremium;
|
||||||
|
Seats = obj.Seats;
|
||||||
|
MaxCollections = obj.MaxCollections;
|
||||||
|
MaxStorageGb = obj.MaxStorageGb;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public OrganizationUserStatusType Status { get; set; }
|
||||||
|
public OrganizationUserType Type { get; set; }
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
public bool UseGroups { get; set; }
|
||||||
|
public bool UseDirectory { get; set; }
|
||||||
|
public bool UseEvents { get; set; }
|
||||||
|
public bool UseTotp { get; set; }
|
||||||
|
public bool Use2fa { get; set; }
|
||||||
|
public bool UseApi { get; set; }
|
||||||
|
public bool SelfHost { get; set; }
|
||||||
|
public bool UsersGetPremium { get; set; }
|
||||||
|
public int Seats { get; set; }
|
||||||
|
public int MaxCollections { get; set; }
|
||||||
|
public short? MaxStorageGb { get; set; }
|
||||||
|
|
||||||
|
public bool CanAccess
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if(Type == OrganizationUserType.Owner)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return Enabled && Status == OrganizationUserStatusType.Confirmed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsManager
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
switch(Type)
|
||||||
|
{
|
||||||
|
case OrganizationUserType.Owner:
|
||||||
|
case OrganizationUserType.Admin:
|
||||||
|
case OrganizationUserType.Manager:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsAdmin => Type == OrganizationUserType.Owner || Type == OrganizationUserType.Admin;
|
||||||
|
public bool IsOwner => Type == OrganizationUserType.Owner;
|
||||||
|
}
|
||||||
|
}
|
167
src/Core/Services/UserService.cs
Normal file
167
src/Core/Services/UserService.cs
Normal file
|
@ -0,0 +1,167 @@
|
||||||
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models.Data;
|
||||||
|
using Bit.Core.Models.Domain;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Bit.Core.Services
|
||||||
|
{
|
||||||
|
public class UserService : IUserService
|
||||||
|
{
|
||||||
|
private string _userId;
|
||||||
|
private string _email;
|
||||||
|
private string _stamp;
|
||||||
|
private KdfType? _kdf;
|
||||||
|
private int? _kdfIterations;
|
||||||
|
|
||||||
|
private const string Keys_UserId = "userId";
|
||||||
|
private const string Keys_UserEmail = "userEmail";
|
||||||
|
private const string Keys_Stamp = "securityStamp";
|
||||||
|
private const string Keys_Kdf = "kdf";
|
||||||
|
private const string Keys_KdfIterations = "kdfIterations";
|
||||||
|
private const string Keys_OrganizationsFormat = "organizations_{0}";
|
||||||
|
|
||||||
|
private readonly IStorageService _storageService;
|
||||||
|
private readonly ITokenService _tokenService;
|
||||||
|
|
||||||
|
public UserService(IStorageService storageService, ITokenService tokenService)
|
||||||
|
{
|
||||||
|
_storageService = storageService;
|
||||||
|
_tokenService = tokenService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SetInformationAsync(string userId, string email, KdfType kdf, int kdfIterations)
|
||||||
|
{
|
||||||
|
_email = email;
|
||||||
|
_userId = userId;
|
||||||
|
_kdf = kdf;
|
||||||
|
_kdfIterations = kdfIterations;
|
||||||
|
await Task.WhenAll(
|
||||||
|
_storageService.SaveAsync(Keys_UserEmail, email),
|
||||||
|
_storageService.SaveAsync(Keys_UserId, userId),
|
||||||
|
_storageService.SaveAsync(Keys_Kdf, (int)kdf),
|
||||||
|
_storageService.SaveAsync(Keys_KdfIterations, kdfIterations));
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SetSecurityStampAsync(string stamp)
|
||||||
|
{
|
||||||
|
_stamp = stamp;
|
||||||
|
await _storageService.SaveAsync(Keys_Stamp, stamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetUserIdAsync()
|
||||||
|
{
|
||||||
|
if(_userId == null)
|
||||||
|
{
|
||||||
|
_userId = await _storageService.GetAsync<string>(Keys_UserId);
|
||||||
|
}
|
||||||
|
return _userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetEmailAsync()
|
||||||
|
{
|
||||||
|
if(_email == null)
|
||||||
|
{
|
||||||
|
_email = await _storageService.GetAsync<string>(Keys_UserEmail);
|
||||||
|
}
|
||||||
|
return _email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetSecurityStampAsync()
|
||||||
|
{
|
||||||
|
if(_stamp == null)
|
||||||
|
{
|
||||||
|
_stamp = await _storageService.GetAsync<string>(Keys_Stamp);
|
||||||
|
}
|
||||||
|
return _stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<KdfType?> GetKdfAsync()
|
||||||
|
{
|
||||||
|
if(_kdf == null)
|
||||||
|
{
|
||||||
|
_kdf = (KdfType?)(await _storageService.GetAsync<int?>(Keys_Kdf));
|
||||||
|
}
|
||||||
|
return _kdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<int?> GetKdfIterationsAsync()
|
||||||
|
{
|
||||||
|
if(_kdfIterations == null)
|
||||||
|
{
|
||||||
|
_kdfIterations = await _storageService.GetAsync<int?>(Keys_KdfIterations);
|
||||||
|
}
|
||||||
|
return _kdfIterations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ClearAsync()
|
||||||
|
{
|
||||||
|
var userId = await GetUserIdAsync();
|
||||||
|
await Task.WhenAll(
|
||||||
|
_storageService.RemoveAsync(Keys_UserId),
|
||||||
|
_storageService.RemoveAsync(Keys_UserEmail),
|
||||||
|
_storageService.RemoveAsync(Keys_Stamp),
|
||||||
|
_storageService.RemoveAsync(Keys_Kdf),
|
||||||
|
_storageService.RemoveAsync(Keys_KdfIterations),
|
||||||
|
ClearOrganizationsAsync(userId));
|
||||||
|
_userId = _email = _stamp = null;
|
||||||
|
_kdf = null;
|
||||||
|
_kdfIterations = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> IsAuthenticatedAsync()
|
||||||
|
{
|
||||||
|
var token = await _tokenService.GetTokenAsync();
|
||||||
|
if(token == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var userId = await GetUserIdAsync();
|
||||||
|
return userId != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> CanAccessPremiumAsync()
|
||||||
|
{
|
||||||
|
var tokenPremium = _tokenService.GetPremium();
|
||||||
|
if(tokenPremium)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var orgs = await GetAllOrganizationAsync();
|
||||||
|
return orgs?.Any(o => o.UsersGetPremium && o.Enabled) ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Organization> GetOrganizationAsync(string id)
|
||||||
|
{
|
||||||
|
var userId = await GetUserIdAsync();
|
||||||
|
var organizations = await _storageService.GetAsync<Dictionary<string, OrganizationData>>(
|
||||||
|
string.Format(Keys_OrganizationsFormat, userId));
|
||||||
|
if(organizations == null || !organizations.ContainsKey(id))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new Organization(organizations[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<Organization>> GetAllOrganizationAsync()
|
||||||
|
{
|
||||||
|
var userId = await GetUserIdAsync();
|
||||||
|
var organizations = await _storageService.GetAsync<Dictionary<string, OrganizationData>>(
|
||||||
|
string.Format(Keys_OrganizationsFormat, userId));
|
||||||
|
return organizations?.Select(o => new Organization(o.Value)).ToList() ?? new List<Organization>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ReplaceOrganizationsAsync(Dictionary<string, OrganizationData> organizations)
|
||||||
|
{
|
||||||
|
var userId = await GetUserIdAsync();
|
||||||
|
await _storageService.SaveAsync(string.Format(Keys_OrganizationsFormat, userId), organizations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ClearOrganizationsAsync(string userId)
|
||||||
|
{
|
||||||
|
await _storageService.RemoveAsync(string.Format(Keys_OrganizationsFormat, userId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue