mirror of
https://github.com/bitwarden/mobile
synced 2026-01-08 03:23:23 +00:00
refactoring code for login => cipher support
This commit is contained in:
@@ -18,7 +18,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
private const string AddedLoginAlertKey = "addedSiteAlert";
|
||||
|
||||
private readonly ILoginService _loginService;
|
||||
private readonly ICipherService _cipherService;
|
||||
private readonly IFolderService _folderService;
|
||||
private readonly IUserDialogs _userDialogs;
|
||||
private readonly IConnectivity _connectivity;
|
||||
@@ -37,7 +37,7 @@ namespace Bit.App.Pages
|
||||
_defaultName = defaultName;
|
||||
_fromAutofill = fromAutofill;
|
||||
|
||||
_loginService = Resolver.Resolve<ILoginService>();
|
||||
_cipherService = Resolver.Resolve<ICipherService>();
|
||||
_folderService = Resolver.Resolve<IFolderService>();
|
||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||
_connectivity = Resolver.Resolve<IConnectivity>();
|
||||
@@ -177,24 +177,31 @@ namespace Bit.App.Pages
|
||||
return;
|
||||
}
|
||||
|
||||
var login = new Login
|
||||
var cipher = new Cipher
|
||||
{
|
||||
Name = NameCell.Entry.Text.Encrypt(),
|
||||
Uri = string.IsNullOrWhiteSpace(UriCell.Entry.Text) ? null : UriCell.Entry.Text.Encrypt(),
|
||||
Username = string.IsNullOrWhiteSpace(UsernameCell.Entry.Text) ? null : UsernameCell.Entry.Text.Encrypt(),
|
||||
Password = string.IsNullOrWhiteSpace(PasswordCell.Entry.Text) ? null : PasswordCell.Entry.Text.Encrypt(),
|
||||
Notes = string.IsNullOrWhiteSpace(NotesCell.Editor.Text) ? null : NotesCell.Editor.Text.Encrypt(),
|
||||
Totp = string.IsNullOrWhiteSpace(TotpCell.Entry.Text) ? null : TotpCell.Entry.Text.Encrypt(),
|
||||
Favorite = favoriteCell.On
|
||||
Favorite = favoriteCell.On,
|
||||
Login = new Login
|
||||
{
|
||||
Uri = string.IsNullOrWhiteSpace(UriCell.Entry.Text) ? null :
|
||||
UriCell.Entry.Text.Encrypt(),
|
||||
Username = string.IsNullOrWhiteSpace(UsernameCell.Entry.Text) ? null :
|
||||
UsernameCell.Entry.Text.Encrypt(),
|
||||
Password = string.IsNullOrWhiteSpace(PasswordCell.Entry.Text) ? null :
|
||||
PasswordCell.Entry.Text.Encrypt(),
|
||||
Totp = string.IsNullOrWhiteSpace(TotpCell.Entry.Text) ? null :
|
||||
TotpCell.Entry.Text.Encrypt(),
|
||||
}
|
||||
};
|
||||
|
||||
if(FolderCell.Picker.SelectedIndex > 0)
|
||||
{
|
||||
login.FolderId = folders.ElementAt(FolderCell.Picker.SelectedIndex - 1).Id;
|
||||
cipher.FolderId = folders.ElementAt(FolderCell.Picker.SelectedIndex - 1).Id;
|
||||
}
|
||||
|
||||
_userDialogs.ShowLoading(AppResources.Saving, MaskType.Black);
|
||||
var saveTask = await _loginService.SaveAsync(login);
|
||||
var saveTask = await _cipherService.SaveAsync(cipher);
|
||||
_userDialogs.HideLoading();
|
||||
|
||||
if(saveTask.Succeeded)
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
public class VaultAttachmentsPage : ExtendedContentPage
|
||||
{
|
||||
private readonly ILoginService _loginService;
|
||||
private readonly ICipherService _cipherService;
|
||||
private readonly IUserDialogs _userDialogs;
|
||||
private readonly IConnectivity _connectivity;
|
||||
private readonly IDeviceActionService _deviceActiveService;
|
||||
@@ -25,7 +25,7 @@ namespace Bit.App.Pages
|
||||
private readonly ITokenService _tokenService;
|
||||
private readonly ICryptoService _cryptoService;
|
||||
private readonly string _loginId;
|
||||
private Login _login;
|
||||
private Cipher _login;
|
||||
private byte[] _fileBytes;
|
||||
private DateTime? _lastAction;
|
||||
private bool _canUseAttachments = true;
|
||||
@@ -34,7 +34,7 @@ namespace Bit.App.Pages
|
||||
: base(true)
|
||||
{
|
||||
_loginId = loginId;
|
||||
_loginService = Resolver.Resolve<ILoginService>();
|
||||
_cipherService = Resolver.Resolve<ICipherService>();
|
||||
_connectivity = Resolver.Resolve<IConnectivity>();
|
||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||
_deviceActiveService = Resolver.Resolve<IDeviceActionService>();
|
||||
@@ -162,7 +162,7 @@ namespace Bit.App.Pages
|
||||
}
|
||||
|
||||
_userDialogs.ShowLoading(AppResources.Saving, MaskType.Black);
|
||||
var saveTask = await _loginService.EncryptAndSaveAttachmentAsync(_login, _fileBytes, FileLabel.Text);
|
||||
var saveTask = await _cipherService.EncryptAndSaveAttachmentAsync(_login, _fileBytes, FileLabel.Text);
|
||||
|
||||
_userDialogs.HideLoading();
|
||||
|
||||
@@ -223,7 +223,7 @@ namespace Bit.App.Pages
|
||||
|
||||
private async Task LoadAttachmentsAsync()
|
||||
{
|
||||
_login = await _loginService.GetByIdAsync(_loginId);
|
||||
_login = await _cipherService.GetByIdAsync(_loginId);
|
||||
if(_login == null)
|
||||
{
|
||||
await Navigation.PopForDeviceAsync();
|
||||
@@ -268,7 +268,7 @@ namespace Bit.App.Pages
|
||||
}
|
||||
|
||||
_userDialogs.ShowLoading(AppResources.Deleting, MaskType.Black);
|
||||
var saveTask = await _loginService.DeleteAttachmentAsync(_login, attachment.Id);
|
||||
var saveTask = await _cipherService.DeleteAttachmentAsync(_login, attachment.Id);
|
||||
_userDialogs.HideLoading();
|
||||
|
||||
if(saveTask.Succeeded)
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
public class VaultAutofillListLoginsPage : ExtendedContentPage
|
||||
{
|
||||
private readonly ILoginService _loginService;
|
||||
private readonly ICipherService _cipherService;
|
||||
private readonly IDeviceInfoService _deviceInfoService;
|
||||
private readonly IDeviceActionService _clipboardService;
|
||||
private readonly ISettingsService _settingsService;
|
||||
@@ -40,7 +40,7 @@ namespace Bit.App.Pages
|
||||
_name = "--";
|
||||
}
|
||||
|
||||
_loginService = Resolver.Resolve<ILoginService>();
|
||||
_cipherService = Resolver.Resolve<ICipherService>();
|
||||
_deviceInfoService = Resolver.Resolve<IDeviceInfoService>();
|
||||
_clipboardService = Resolver.Resolve<IDeviceActionService>();
|
||||
_settingsService = Resolver.Resolve<ISettingsService>();
|
||||
@@ -162,7 +162,7 @@ namespace Bit.App.Pages
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var autofillGroupings = new List<VaultListPageModel.AutofillGrouping>();
|
||||
var logins = await _loginService.GetAllAsync(Uri);
|
||||
var logins = await _cipherService.GetAllAsync(Uri);
|
||||
|
||||
var normalLogins = logins?.Item1.Select(l => new VaultListPageModel.AutofillLogin(l, false))
|
||||
.OrderBy(s => s.Name)
|
||||
|
||||
@@ -16,19 +16,19 @@ namespace Bit.App.Pages
|
||||
{
|
||||
public class VaultCustomFieldsPage : ExtendedContentPage
|
||||
{
|
||||
private readonly ILoginService _loginService;
|
||||
private readonly ICipherService _cipherService;
|
||||
private readonly IUserDialogs _userDialogs;
|
||||
private readonly IConnectivity _connectivity;
|
||||
private readonly IGoogleAnalyticsService _googleAnalyticsService;
|
||||
private readonly string _loginId;
|
||||
private Login _login;
|
||||
private Cipher _login;
|
||||
private DateTime? _lastAction;
|
||||
|
||||
public VaultCustomFieldsPage(string loginId)
|
||||
: base(true)
|
||||
{
|
||||
_loginId = loginId;
|
||||
_loginService = Resolver.Resolve<ILoginService>();
|
||||
_cipherService = Resolver.Resolve<ICipherService>();
|
||||
_connectivity = Resolver.Resolve<IConnectivity>();
|
||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||
_googleAnalyticsService = Resolver.Resolve<IGoogleAnalyticsService>();
|
||||
@@ -114,7 +114,7 @@ namespace Bit.App.Pages
|
||||
}
|
||||
|
||||
_userDialogs.ShowLoading(AppResources.Saving, MaskType.Black);
|
||||
var saveTask = await _loginService.SaveAsync(_login);
|
||||
var saveTask = await _cipherService.SaveAsync(_login);
|
||||
|
||||
_userDialogs.HideLoading();
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
base.OnAppearing();
|
||||
|
||||
_login = await _loginService.GetByIdAsync(_loginId);
|
||||
_login = await _cipherService.GetByIdAsync(_loginId);
|
||||
if(_login == null)
|
||||
{
|
||||
await Navigation.PopForDeviceAsync();
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Bit.App.Pages
|
||||
public class VaultEditLoginPage : ExtendedContentPage
|
||||
{
|
||||
private readonly string _loginId;
|
||||
private readonly ILoginService _loginService;
|
||||
private readonly ICipherService _cipherService;
|
||||
private readonly IFolderService _folderService;
|
||||
private readonly IUserDialogs _userDialogs;
|
||||
private readonly IConnectivity _connectivity;
|
||||
@@ -26,7 +26,7 @@ namespace Bit.App.Pages
|
||||
public VaultEditLoginPage(string loginId)
|
||||
{
|
||||
_loginId = loginId;
|
||||
_loginService = Resolver.Resolve<ILoginService>();
|
||||
_cipherService = Resolver.Resolve<ICipherService>();
|
||||
_folderService = Resolver.Resolve<IFolderService>();
|
||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||
_connectivity = Resolver.Resolve<IConnectivity>();
|
||||
@@ -50,8 +50,8 @@ namespace Bit.App.Pages
|
||||
|
||||
private void Init()
|
||||
{
|
||||
var login = _loginService.GetByIdAsync(_loginId).GetAwaiter().GetResult();
|
||||
if(login == null)
|
||||
var cipher = _cipherService.GetByIdAsync(_loginId).GetAwaiter().GetResult();
|
||||
if(cipher == null)
|
||||
{
|
||||
// TODO: handle error. navigate back? should never happen...
|
||||
return;
|
||||
@@ -59,7 +59,7 @@ namespace Bit.App.Pages
|
||||
|
||||
NotesCell = new FormEditorCell(height: 300);
|
||||
NotesCell.Editor.Keyboard = Keyboard.Text;
|
||||
NotesCell.Editor.Text = login.Notes?.Decrypt(login.OrganizationId);
|
||||
NotesCell.Editor.Text = cipher.Notes?.Decrypt(cipher.OrganizationId);
|
||||
|
||||
TotpCell = new FormEntryCell(AppResources.AuthenticatorKey, nextElement: NotesCell.Editor,
|
||||
useButton: _deviceInfo.HasCamera);
|
||||
@@ -67,28 +67,28 @@ namespace Bit.App.Pages
|
||||
{
|
||||
TotpCell.Button.Image = "camera";
|
||||
}
|
||||
TotpCell.Entry.Text = login.Totp?.Decrypt(login.OrganizationId);
|
||||
TotpCell.Entry.Text = cipher.Login?.Totp?.Decrypt(cipher.OrganizationId);
|
||||
TotpCell.Entry.DisableAutocapitalize = true;
|
||||
TotpCell.Entry.Autocorrect = false;
|
||||
TotpCell.Entry.FontFamily = Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", WinPhone: "Courier");
|
||||
|
||||
PasswordCell = new FormEntryCell(AppResources.Password, isPassword: true, nextElement: TotpCell.Entry,
|
||||
useButton: true);
|
||||
PasswordCell.Entry.Text = login.Password?.Decrypt(login.OrganizationId);
|
||||
PasswordCell.Entry.Text = cipher.Login?.Password?.Decrypt(cipher.OrganizationId);
|
||||
PasswordCell.Button.Image = "eye";
|
||||
PasswordCell.Entry.DisableAutocapitalize = true;
|
||||
PasswordCell.Entry.Autocorrect = false;
|
||||
PasswordCell.Entry.FontFamily = Helpers.OnPlatform(iOS: "Menlo-Regular", Android: "monospace", WinPhone: "Courier");
|
||||
|
||||
UsernameCell = new FormEntryCell(AppResources.Username, nextElement: PasswordCell.Entry);
|
||||
UsernameCell.Entry.Text = login.Username?.Decrypt(login.OrganizationId);
|
||||
UsernameCell.Entry.Text = cipher.Login?.Username?.Decrypt(cipher.OrganizationId);
|
||||
UsernameCell.Entry.DisableAutocapitalize = true;
|
||||
UsernameCell.Entry.Autocorrect = false;
|
||||
|
||||
UriCell = new FormEntryCell(AppResources.URI, Keyboard.Url, nextElement: UsernameCell.Entry);
|
||||
UriCell.Entry.Text = login.Uri?.Decrypt(login.OrganizationId);
|
||||
UriCell.Entry.Text = cipher.Login?.Uri?.Decrypt(cipher.OrganizationId);
|
||||
NameCell = new FormEntryCell(AppResources.Name, nextElement: UriCell.Entry);
|
||||
NameCell.Entry.Text = login.Name?.Decrypt(login.OrganizationId);
|
||||
NameCell.Entry.Text = cipher.Name?.Decrypt(cipher.OrganizationId);
|
||||
|
||||
GenerateCell = new ExtendedTextCell
|
||||
{
|
||||
@@ -104,7 +104,7 @@ namespace Bit.App.Pages
|
||||
foreach(var folder in folders)
|
||||
{
|
||||
i++;
|
||||
if(folder.Id == login.FolderId)
|
||||
if(folder.Id == cipher.FolderId)
|
||||
{
|
||||
selectedIndex = i;
|
||||
}
|
||||
@@ -117,7 +117,7 @@ namespace Bit.App.Pages
|
||||
var favoriteCell = new ExtendedSwitchCell
|
||||
{
|
||||
Text = AppResources.Favorite,
|
||||
On = login.Favorite
|
||||
On = cipher.Favorite
|
||||
};
|
||||
|
||||
AttachmentsCell = new ExtendedTextCell
|
||||
@@ -204,30 +204,34 @@ namespace Bit.App.Pages
|
||||
return;
|
||||
}
|
||||
|
||||
login.Name = NameCell.Entry.Text.Encrypt(login.OrganizationId);
|
||||
login.Uri = string.IsNullOrWhiteSpace(UriCell.Entry.Text) ? null :
|
||||
UriCell.Entry.Text.Encrypt(login.OrganizationId);
|
||||
login.Username = string.IsNullOrWhiteSpace(UsernameCell.Entry.Text) ? null :
|
||||
UsernameCell.Entry.Text.Encrypt(login.OrganizationId);
|
||||
login.Password = string.IsNullOrWhiteSpace(PasswordCell.Entry.Text) ? null :
|
||||
PasswordCell.Entry.Text.Encrypt(login.OrganizationId);
|
||||
login.Notes = string.IsNullOrWhiteSpace(NotesCell.Editor.Text) ? null :
|
||||
NotesCell.Editor.Text.Encrypt(login.OrganizationId);
|
||||
login.Totp = string.IsNullOrWhiteSpace(TotpCell.Entry.Text) ? null :
|
||||
TotpCell.Entry.Text.Encrypt(login.OrganizationId);
|
||||
login.Favorite = favoriteCell.On;
|
||||
cipher.Name = NameCell.Entry.Text.Encrypt(cipher.OrganizationId);
|
||||
cipher.Notes = string.IsNullOrWhiteSpace(NotesCell.Editor.Text) ? null :
|
||||
NotesCell.Editor.Text.Encrypt(cipher.OrganizationId);
|
||||
cipher.Favorite = favoriteCell.On;
|
||||
|
||||
cipher.Login = new Models.Login
|
||||
{
|
||||
Uri = string.IsNullOrWhiteSpace(UriCell.Entry.Text) ? null :
|
||||
UriCell.Entry.Text.Encrypt(cipher.OrganizationId),
|
||||
Username = string.IsNullOrWhiteSpace(UsernameCell.Entry.Text) ? null :
|
||||
UsernameCell.Entry.Text.Encrypt(cipher.OrganizationId),
|
||||
Password = string.IsNullOrWhiteSpace(PasswordCell.Entry.Text) ? null :
|
||||
PasswordCell.Entry.Text.Encrypt(cipher.OrganizationId),
|
||||
Totp = string.IsNullOrWhiteSpace(TotpCell.Entry.Text) ? null :
|
||||
TotpCell.Entry.Text.Encrypt(cipher.OrganizationId)
|
||||
};
|
||||
|
||||
if(FolderCell.Picker.SelectedIndex > 0)
|
||||
{
|
||||
login.FolderId = folders.ElementAt(FolderCell.Picker.SelectedIndex - 1).Id;
|
||||
cipher.FolderId = folders.ElementAt(FolderCell.Picker.SelectedIndex - 1).Id;
|
||||
}
|
||||
else
|
||||
{
|
||||
login.FolderId = null;
|
||||
cipher.FolderId = null;
|
||||
}
|
||||
|
||||
_userDialogs.ShowLoading(AppResources.Saving, MaskType.Black);
|
||||
var saveTask = await _loginService.SaveAsync(login);
|
||||
var saveTask = await _cipherService.SaveAsync(cipher);
|
||||
|
||||
_userDialogs.HideLoading();
|
||||
|
||||
@@ -405,7 +409,7 @@ namespace Bit.App.Pages
|
||||
}
|
||||
|
||||
_userDialogs.ShowLoading(AppResources.Deleting, MaskType.Black);
|
||||
var deleteTask = await _loginService.DeleteAsync(_loginId);
|
||||
var deleteTask = await _cipherService.DeleteAsync(_loginId);
|
||||
_userDialogs.HideLoading();
|
||||
|
||||
if(deleteTask.Succeeded)
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Bit.App.Pages
|
||||
public class VaultListLoginsPage : ExtendedContentPage
|
||||
{
|
||||
private readonly IFolderService _folderService;
|
||||
private readonly ILoginService _loginService;
|
||||
private readonly ICipherService _cipherService;
|
||||
private readonly IUserDialogs _userDialogs;
|
||||
private readonly IConnectivity _connectivity;
|
||||
private readonly IDeviceActionService _clipboardService;
|
||||
@@ -37,7 +37,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
_favorites = favorites;
|
||||
_folderService = Resolver.Resolve<IFolderService>();
|
||||
_loginService = Resolver.Resolve<ILoginService>();
|
||||
_cipherService = Resolver.Resolve<ICipherService>();
|
||||
_connectivity = Resolver.Resolve<IConnectivity>();
|
||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||
_clipboardService = Resolver.Resolve<IDeviceActionService>();
|
||||
@@ -310,7 +310,7 @@ namespace Bit.App.Pages
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var foldersTask = _folderService.GetAllAsync();
|
||||
var loginsTask = _favorites ? _loginService.GetAllAsync(true) : _loginService.GetAllAsync();
|
||||
var loginsTask = _favorites ? _cipherService.GetAllAsync(true) : _cipherService.GetAllAsync();
|
||||
await Task.WhenAll(foldersTask, loginsTask);
|
||||
|
||||
var folders = await foldersTask;
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Bit.App.Pages
|
||||
public class VaultViewLoginPage : ExtendedContentPage
|
||||
{
|
||||
private readonly string _loginId;
|
||||
private readonly ILoginService _loginService;
|
||||
private readonly ICipherService _cipherService;
|
||||
private readonly IUserDialogs _userDialogs;
|
||||
private readonly IDeviceActionService _deviceActionService;
|
||||
private readonly ITokenService _tokenService;
|
||||
@@ -27,7 +27,7 @@ namespace Bit.App.Pages
|
||||
public VaultViewLoginPage(string loginId)
|
||||
{
|
||||
_loginId = loginId;
|
||||
_loginService = Resolver.Resolve<ILoginService>();
|
||||
_cipherService = Resolver.Resolve<ICipherService>();
|
||||
_userDialogs = Resolver.Resolve<IUserDialogs>();
|
||||
_deviceActionService = Resolver.Resolve<IDeviceActionService>();
|
||||
_tokenService = Resolver.Resolve<ITokenService>();
|
||||
@@ -161,14 +161,14 @@ namespace Bit.App.Pages
|
||||
NotesCell.Tapped += NotesCell_Tapped;
|
||||
EditItem.InitEvents();
|
||||
|
||||
var login = await _loginService.GetByIdAsync(_loginId);
|
||||
if(login == null)
|
||||
var cipher = await _cipherService.GetByIdAsync(_loginId);
|
||||
if(cipher == null)
|
||||
{
|
||||
await Navigation.PopForDeviceAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
Model.Update(login);
|
||||
Model.Update(cipher);
|
||||
|
||||
if(LoginInformationSection.Contains(UriCell))
|
||||
{
|
||||
@@ -211,9 +211,9 @@ namespace Bit.App.Pages
|
||||
{
|
||||
LoginInformationSection.Remove(TotpCodeCell);
|
||||
}
|
||||
if(login.Totp != null && (_tokenService.TokenPremium || login.OrganizationUseTotp))
|
||||
if(cipher.Login?.Totp != null && (_tokenService.TokenPremium || cipher.OrganizationUseTotp))
|
||||
{
|
||||
var totpKey = login.Totp.Decrypt(login.OrganizationId);
|
||||
var totpKey = cipher.Login?.Totp.Decrypt(cipher.OrganizationId);
|
||||
if(!string.IsNullOrWhiteSpace(totpKey))
|
||||
{
|
||||
Model.TotpCode = Crypto.Totp(totpKey);
|
||||
@@ -249,7 +249,7 @@ namespace Bit.App.Pages
|
||||
{
|
||||
var attachmentCell = new AttachmentViewCell(attachment, async () =>
|
||||
{
|
||||
await OpenAttachmentAsync(login, attachment);
|
||||
await OpenAttachmentAsync(cipher, attachment);
|
||||
});
|
||||
AttachmentCells.Add(attachmentCell);
|
||||
AttachmentsSection.Add(attachmentCell);
|
||||
@@ -309,7 +309,7 @@ namespace Bit.App.Pages
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OpenAttachmentAsync(Login login, VaultViewLoginPageModel.Attachment attachment)
|
||||
private async Task OpenAttachmentAsync(Cipher login, VaultViewLoginPageModel.Attachment attachment)
|
||||
{
|
||||
if(!_tokenService.TokenPremium && !login.OrganizationUseTotp)
|
||||
{
|
||||
@@ -332,7 +332,7 @@ namespace Bit.App.Pages
|
||||
}
|
||||
|
||||
_userDialogs.ShowLoading(AppResources.Downloading, MaskType.Black);
|
||||
var data = await _loginService.DownloadAndDecryptAttachmentAsync(attachment.Url, login.OrganizationId);
|
||||
var data = await _cipherService.DownloadAndDecryptAttachmentAsync(attachment.Url, login.OrganizationId);
|
||||
_userDialogs.HideLoading();
|
||||
if(data == null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user