mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 23:25:45 +03:00
optional params
This commit is contained in:
parent
98291caf76
commit
4b3bae5797
4 changed files with 265 additions and 6 deletions
|
@ -53,12 +53,12 @@ namespace Bit.App.Services
|
||||||
Thread.CurrentThread.CurrentUICulture = Culture;
|
Thread.CurrentThread.CurrentUICulture = Culture;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string T(string id, string p1, string p2, string p3)
|
public string T(string id, string p1 = null, string p2 = null, string p3 = null)
|
||||||
{
|
{
|
||||||
return Translate(id, p1, p2, p3);
|
return Translate(id, p1, p2, p3);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Translate(string id, string p1, string p2, string p3)
|
public string Translate(string id, string p1 = null, string p2 = null, string p3 = null)
|
||||||
{
|
{
|
||||||
if(string.IsNullOrWhiteSpace(id))
|
if(string.IsNullOrWhiteSpace(id))
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Bit.Core.Abstractions
|
||||||
{
|
{
|
||||||
CultureInfo Culture { get; set; }
|
CultureInfo Culture { get; set; }
|
||||||
StringComparer StringComparer { get; }
|
StringComparer StringComparer { get; }
|
||||||
string T(string id, string p1, string p2, string p3);
|
string T(string id, string p1 = null, string p2 = null, string p3 = null);
|
||||||
string Translate(string id, string p1, string p2, string p3);
|
string Translate(string id, string p1 = null, string p2 = null, string p3 = null);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -24,9 +24,9 @@ namespace Bit.Core.Models.Domain
|
||||||
public CipherString Name { get; set; }
|
public CipherString Name { get; set; }
|
||||||
public DateTime RevisionDate { get; set; }
|
public DateTime RevisionDate { get; set; }
|
||||||
|
|
||||||
public Task<FolderView> DecryptAsync(string orgId)
|
public Task<FolderView> DecryptAsync()
|
||||||
{
|
{
|
||||||
return DecryptObjAsync(new FolderView(this), this, new HashSet<string> { "Name" }, orgId);
|
return DecryptObjAsync(new FolderView(this), this, new HashSet<string> { "Name" }, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
259
src/Core/Services/FolderService.cs
Normal file
259
src/Core/Services/FolderService.cs
Normal file
|
@ -0,0 +1,259 @@
|
||||||
|
using Bit.Core.Abstractions;
|
||||||
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Exceptions;
|
||||||
|
using Bit.Core.Models.Data;
|
||||||
|
using Bit.Core.Models.Domain;
|
||||||
|
using Bit.Core.Models.Request;
|
||||||
|
using Bit.Core.Models.Response;
|
||||||
|
using Bit.Core.Models.View;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Bit.Core.Services
|
||||||
|
{
|
||||||
|
public class FolderService
|
||||||
|
{
|
||||||
|
private const string Keys_CiphersFormat = "ciphers_{0}";
|
||||||
|
private const string Keys_FoldersFormat = "folders_{0}";
|
||||||
|
private const string NestingDelimiter = "/";
|
||||||
|
|
||||||
|
private List<FolderView> _decryptedFolderCache;
|
||||||
|
private readonly ICryptoService _cryptoService;
|
||||||
|
private readonly IUserService _userService;
|
||||||
|
private readonly IApiService _apiService;
|
||||||
|
private readonly IStorageService _storageService;
|
||||||
|
private readonly II18nService _i18nService;
|
||||||
|
private readonly ICipherService _cipherService;
|
||||||
|
|
||||||
|
public FolderService(
|
||||||
|
ICryptoService cryptoService,
|
||||||
|
IUserService userService,
|
||||||
|
IApiService apiService,
|
||||||
|
IStorageService storageService,
|
||||||
|
II18nService i18nService,
|
||||||
|
ICipherService cipherService)
|
||||||
|
{
|
||||||
|
_cryptoService = cryptoService;
|
||||||
|
_userService = userService;
|
||||||
|
_apiService = apiService;
|
||||||
|
_storageService = storageService;
|
||||||
|
_i18nService = i18nService;
|
||||||
|
_cipherService = cipherService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearCache()
|
||||||
|
{
|
||||||
|
_decryptedFolderCache = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Folder> EncryptAsync(FolderView model, SymmetricCryptoKey key = null)
|
||||||
|
{
|
||||||
|
var folder = new Folder
|
||||||
|
{
|
||||||
|
Id = model.Id,
|
||||||
|
Name = await _cryptoService.EncryptAsync(model.Name, key)
|
||||||
|
};
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Folder> GetAsync(string id)
|
||||||
|
{
|
||||||
|
var userId = await _userService.GetUserIdAsync();
|
||||||
|
var folders = await _storageService.GetAsync<Dictionary<string, FolderData>>(
|
||||||
|
string.Format(Keys_FoldersFormat, userId));
|
||||||
|
if(!folders?.ContainsKey(id) ?? true)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new Folder(folders[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<List<Folder>> GetAllAsync()
|
||||||
|
{
|
||||||
|
var userId = await _userService.GetUserIdAsync();
|
||||||
|
var folders = await _storageService.GetAsync<Dictionary<string, FolderData>>(
|
||||||
|
string.Format(Keys_CiphersFormat, userId));
|
||||||
|
var response = folders.Select(f => new Folder(f.Value));
|
||||||
|
return response.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: sequentialize?
|
||||||
|
public async Task<List<FolderView>> GetAllDecryptedAsync()
|
||||||
|
{
|
||||||
|
if(_decryptedFolderCache != null)
|
||||||
|
{
|
||||||
|
return _decryptedFolderCache;
|
||||||
|
}
|
||||||
|
var hashKey = await _cryptoService.HasKeyAsync();
|
||||||
|
if(!hashKey)
|
||||||
|
{
|
||||||
|
throw new Exception("No key.");
|
||||||
|
}
|
||||||
|
var decFolders = new List<FolderView>();
|
||||||
|
var tasks = new List<Task>();
|
||||||
|
var folders = await GetAllAsync();
|
||||||
|
foreach(var folder in folders)
|
||||||
|
{
|
||||||
|
tasks.Add(folder.DecryptAsync().ContinueWith(async f => decFolders.Add(await f)));
|
||||||
|
}
|
||||||
|
await Task.WhenAll(tasks);
|
||||||
|
decFolders = decFolders.OrderBy(f => f, new FolderLocaleComparer(_i18nService)).ToList();
|
||||||
|
|
||||||
|
var noneFolder = new FolderView
|
||||||
|
{
|
||||||
|
Name = _i18nService.T("noneFolder")
|
||||||
|
};
|
||||||
|
decFolders.Add(noneFolder);
|
||||||
|
|
||||||
|
_decryptedFolderCache = decFolders;
|
||||||
|
return _decryptedFolderCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: nested stuff
|
||||||
|
|
||||||
|
public async Task SaveWithServerAsync(Folder folder)
|
||||||
|
{
|
||||||
|
var request = new FolderRequest(folder);
|
||||||
|
FolderResponse response;
|
||||||
|
if(folder.Id == null)
|
||||||
|
{
|
||||||
|
response = await _apiService.PostFolderAsync(request);
|
||||||
|
folder.Id = response.Id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response = await _apiService.PutFolderAsync(folder.Id, request);
|
||||||
|
}
|
||||||
|
var userId = await _userService.GetUserIdAsync();
|
||||||
|
var data = new FolderData(response, userId);
|
||||||
|
await UpsertAsync(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpsertAsync(FolderData folder)
|
||||||
|
{
|
||||||
|
var userId = await _userService.GetUserIdAsync();
|
||||||
|
var storageKey = string.Format(Keys_FoldersFormat, userId);
|
||||||
|
var folders = await _storageService.GetAsync<Dictionary<string, FolderData>>(storageKey);
|
||||||
|
if(folders == null)
|
||||||
|
{
|
||||||
|
folders = new Dictionary<string, FolderData>();
|
||||||
|
}
|
||||||
|
if(!folders.ContainsKey(folder.Id))
|
||||||
|
{
|
||||||
|
folders.Add(folder.Id, null);
|
||||||
|
}
|
||||||
|
folders[folder.Id] = folder;
|
||||||
|
await _storageService.SaveAsync(storageKey, folders);
|
||||||
|
_decryptedFolderCache = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task UpsertAsync(List<FolderData> folder)
|
||||||
|
{
|
||||||
|
var userId = await _userService.GetUserIdAsync();
|
||||||
|
var storageKey = string.Format(Keys_FoldersFormat, userId);
|
||||||
|
var folders = await _storageService.GetAsync<Dictionary<string, FolderData>>(storageKey);
|
||||||
|
if(folders == null)
|
||||||
|
{
|
||||||
|
folders = new Dictionary<string, FolderData>();
|
||||||
|
}
|
||||||
|
foreach(var f in folder)
|
||||||
|
{
|
||||||
|
if(!folders.ContainsKey(f.Id))
|
||||||
|
{
|
||||||
|
folders.Add(f.Id, null);
|
||||||
|
}
|
||||||
|
folders[f.Id] = f;
|
||||||
|
}
|
||||||
|
await _storageService.SaveAsync(storageKey, folders);
|
||||||
|
_decryptedFolderCache = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ReplaceAsync(Dictionary<string, FolderData> folders)
|
||||||
|
{
|
||||||
|
var userId = await _userService.GetUserIdAsync();
|
||||||
|
await _storageService.SaveAsync(string.Format(Keys_FoldersFormat, userId), folders);
|
||||||
|
_decryptedFolderCache = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task ClearAsync(string userId)
|
||||||
|
{
|
||||||
|
await _storageService.RemoveAsync(string.Format(Keys_FoldersFormat, userId));
|
||||||
|
_decryptedFolderCache = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteAsync(string id)
|
||||||
|
{
|
||||||
|
var userId = await _userService.GetUserIdAsync();
|
||||||
|
var folderKey = string.Format(Keys_FoldersFormat, userId);
|
||||||
|
var folders = await _storageService.GetAsync<Dictionary<string, FolderData>>(folderKey);
|
||||||
|
if(folders == null || !folders.ContainsKey(id))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
folders.Remove(id);
|
||||||
|
await _storageService.SaveAsync(folderKey, folders);
|
||||||
|
_decryptedFolderCache = null;
|
||||||
|
|
||||||
|
// Items in a deleted folder are re-assigned to "No Folder"
|
||||||
|
var ciphers = await _storageService.GetAsync<Dictionary<string, CipherData>>(
|
||||||
|
string.Format(Keys_CiphersFormat, userId));
|
||||||
|
if(ciphers != null)
|
||||||
|
{
|
||||||
|
var updates = new List<CipherData>();
|
||||||
|
foreach(var c in ciphers)
|
||||||
|
{
|
||||||
|
if(c.Value.FolderId == id)
|
||||||
|
{
|
||||||
|
c.Value.FolderId = null;
|
||||||
|
updates.Add(c.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(updates.Any())
|
||||||
|
{
|
||||||
|
await _cipherService.UpsertAsync(updates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task DeleteWithServerAsync(string id)
|
||||||
|
{
|
||||||
|
await _apiService.DeleteFolderAsync(id);
|
||||||
|
await DeleteAsync(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FolderLocaleComparer : IComparer<FolderView>
|
||||||
|
{
|
||||||
|
private readonly II18nService _i18nService;
|
||||||
|
|
||||||
|
public FolderLocaleComparer(II18nService i18nService)
|
||||||
|
{
|
||||||
|
_i18nService = i18nService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(FolderView a, FolderView b)
|
||||||
|
{
|
||||||
|
var aName = a.Name;
|
||||||
|
var bName = b.Name;
|
||||||
|
if(aName == null && bName != null)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(aName != null && bName == null)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if(aName == null && bName == null)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return _i18nService.StringComparer.Compare(aName, bName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue