Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full trust Wino Server implementation. #295

Merged
merged 64 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
3b84542
Separation of messages. Introducing Wino.Messages library.
bkaankose Jul 16, 2024
ec4162e
Wino.Server and Wino.Packaging projects. Enabling full trust for UWP …
bkaankose Jul 16, 2024
7d3dbc6
Remove debug code.
bkaankose Jul 16, 2024
06d8559
Enable generating assembly info to deal with unsupported os platform …
bkaankose Jul 16, 2024
ad1c7e1
Fix server-client connection.
bkaankose Jul 16, 2024
329eae3
UIMessage communication. Single instancing for server and re-connecti…
bkaankose Jul 17, 2024
a9a9907
Removed IWinoSynchronizerFactory from UWP project.
bkaankose Jul 17, 2024
7ef045a
Removal of background task service from core.
bkaankose Jul 18, 2024
38f44a8
Delegating changes to UI and triggering new background synchronization.
bkaankose Jul 18, 2024
9bd75f7
Fix build error.
bkaankose Jul 19, 2024
31de740
Moved core lib messages to Messaging project.
bkaankose Jul 22, 2024
07af5c9
Better client-server communication. Handling of requests in the serve…
bkaankose Jul 23, 2024
a937762
WAM broker and MSAL token caching for OutlookAuthenticator. Handling …
bkaankose Jul 23, 2024
6e5c36f
WinoServerResponse basics.
bkaankose Jul 23, 2024
7acdadb
Delegating protocol activation for Gmail authenticator.
bkaankose Jul 24, 2024
7176b88
Adding margin to searchbox to match action bar width.
bkaankose Jul 25, 2024
4e62e65
Move libraries into lib folder.
bkaankose Jul 25, 2024
bd8208b
Storing base64 encoded mime on draft creation instead of MimeMessage …
bkaankose Jul 25, 2024
20440fe
Scrollbar adjustments
bkaankose Jul 26, 2024
fb65524
WınoExpander for thread expander layout ıssue.
bkaankose Jul 26, 2024
fc27bde
Handling synchronizer state changes.
bkaankose Jul 26, 2024
d674552
Double init on background activation.
bkaankose Jul 26, 2024
1a2b580
FIxing packaging issues and new Wino Mail launcher protocol for activ…
bkaankose Jul 27, 2024
cf0521e
Remove debug deserialization.
bkaankose Jul 27, 2024
a46e17a
Remove debug code.
bkaankose Jul 27, 2024
2d6feab
Making sure the server connection is established when the app is laun…
bkaankose Jul 27, 2024
0f40d06
Thrust -> Trust string replacement...
bkaankose Jul 27, 2024
936cd08
Merged main
bkaankose Jul 27, 2024
94cace5
Rename package to Wino Mail
bkaankose Jul 27, 2024
b9bf0f3
Enable translated values in the server.
bkaankose Jul 27, 2024
d215fe2
Fixed an issue where toast activation can't find the clicked mail aft…
bkaankose Jul 27, 2024
b3f4760
Revert debug code.
bkaankose Jul 27, 2024
a693a78
Change server background sync to every 3 minute and Inbox only synchr…
bkaankose Jul 27, 2024
1a0a4b7
Revert google auth changes.
bkaankose Jul 27, 2024
c717746
App preferences page.
bkaankose Jul 27, 2024
50421a5
Changing tray icon visibility on preference change.
bkaankose Jul 28, 2024
902d91e
Start the server with invisible tray icon if set to invisible.
bkaankose Jul 28, 2024
bedfc60
Reconnect button on the title bar.
bkaankose Jul 28, 2024
11f97d6
Handling of toast actions.
bkaankose Jul 28, 2024
6a82523
Enable x86 build for server during packaging.
bkaankose Jul 28, 2024
1df621a
Get rid of old background tasks and v180 migration.
bkaankose Jul 28, 2024
784f952
Terminate client when Exit clicked in server.
bkaankose Jul 28, 2024
64e360c
Introducing SynchronizationSource to prevent notifying UI after serve…
bkaankose Jul 28, 2024
be49a33
Remove confirmAppClose restricted capability and unused debug code in…
bkaankose Jul 28, 2024
5c7f1b1
Closing the reconnect info popup when reconnect is clicked.
bkaankose Jul 28, 2024
996ecfe
Custom RetryHandler for OutlookSynchronizer and separating client/ser…
bkaankose Jul 30, 2024
eeaeead
Running server on Windows startup.
bkaankose Aug 1, 2024
f580d1b
Fix startup exe.
bkaankose Aug 2, 2024
623b38a
Fix for expander list view item paddings.
bkaankose Aug 2, 2024
0857ba7
Force full sync on app launch instead of Inbox.
bkaankose Aug 2, 2024
85e2ba0
Fix draft creation.
bkaankose Aug 2, 2024
108fda7
Fix an issue with custom folder sync logic.
bkaankose Aug 2, 2024
3cecbfd
Reporting back account sync progress from server.
bkaankose Aug 2, 2024
0acdfc5
Fix sending drafts and missing notifications for imap.
bkaankose Aug 2, 2024
b371924
Changing imap folder sync requirements.
bkaankose Aug 2, 2024
ccd24b3
Retain file count is set to 3.
bkaankose Aug 3, 2024
2176b92
Disabled swipe gestures temporarily due to native crash
bkaankose Aug 3, 2024
b198792
Save all attachments implementation.
bkaankose Aug 3, 2024
0f1f676
Localization for save all attachments button.
bkaankose Aug 3, 2024
b4ddcf5
Fix logging dates for logs.
bkaankose Aug 3, 2024
b42b1a7
Fixing ARM64 build.
bkaankose Aug 4, 2024
1b4d677
Add ARM64 build config to packaging project.
bkaankose Aug 4, 2024
b5e7ec1
Comment out OutOfProcPDB for ARM64.
bkaankose Aug 4, 2024
a9aca13
Hnadling GONE response for Outlook folder synchronization.
bkaankose Aug 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 4 additions & 33 deletions Wino.BackgroundTasks/SessionConnectedTask.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Background;
using Windows.Storage;
using Wino.Core;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Services;
using Wino.Core.UWP;
using Wino.Services;

namespace Wino.BackgroundTasks
{
Expand All @@ -17,32 +10,10 @@ public async void Run(IBackgroundTaskInstance taskInstance)
{
var def = taskInstance.GetDeferral();

try
{
var services = new ServiceCollection();
// Run server on session connected by launching the Full Thrust process.
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();

services.RegisterCoreServices();
services.RegisterCoreUWPServices();

var providere = services.BuildServiceProvider();

var backgroundTaskService = providere.GetService<IBackgroundSynchronizer>();
var dbService = providere.GetService<IDatabaseService>();
var logInitializer = providere.GetService<ILogInitializer>();

logInitializer.SetupLogger(ApplicationData.Current.LocalFolder.Path);

await dbService.InitializeAsync();
await backgroundTaskService.RunBackgroundSynchronizationAsync(Core.Domain.Enums.BackgroundSynchronizationReason.SessionConnected);
}
catch (Exception ex)
{
Log.Error(ex, "Background synchronization failed from background task.");
}
finally
{
def.Complete();
}
def.Complete();
}
}
}
19 changes: 0 additions & 19 deletions Wino.BackgroundTasks/Wino.BackgroundTasks.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,6 @@
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<AllowCrossPlatformRetargeting>false</AllowCrossPlatformRetargeting>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
Expand Down
6 changes: 4 additions & 2 deletions Wino.Core.Domain/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ public static class Constants
public const string WinoLocalDraftHeader = "X-Wino-Draft-Id";
public const string LocalDraftStartPrefix = "localDraft_";

public const string ToastMailItemIdKey = nameof(ToastMailItemIdKey);
public const string ToastMailItemRemoteFolderIdKey = nameof(ToastMailItemRemoteFolderIdKey);
public const string ToastMailUniqueIdKey = nameof(ToastMailUniqueIdKey);
public const string ToastActionKey = nameof(ToastActionKey);

public const string ClientLogFile = "Client_.log";
public const string ServerLogFile = "Server_.log";
}
}
4 changes: 4 additions & 0 deletions Wino.Core.Domain/Entities/TokenInformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ public class TokenInformation : TokenInformationBase

public Guid AccountId { get; set; }

/// <summary>
/// Unique object storage for authenticators if needed.
/// </summary>
public string UniqueId { get; set; }
public string Address { get; set; }

public void RefreshTokens(TokenInformationBase tokenInformationBase)
Expand Down
12 changes: 12 additions & 0 deletions Wino.Core.Domain/Enums/ServerBackgroundMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Wino.Core.Domain.Enums
{
/// <summary>
/// What should happen to server app when the client is terminated.
/// </summary>
public enum ServerBackgroundMode
{
MinimizedTray, // Still runs, tray icon is visible.
Invisible, // Still runs, tray icon is invisible.
Terminate // Server is terminated as Wino terminates.
}
}
11 changes: 11 additions & 0 deletions Wino.Core.Domain/Enums/StartupBehaviorResult.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Wino.Core.Domain.Enums
{
public enum StartupBehaviorResult
{
Enabled,
Disabled,
DisabledByUser,
DisabledByPolicy,
Fatal
}
}
12 changes: 12 additions & 0 deletions Wino.Core.Domain/Enums/SynchronizationSource.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Wino.Core.Domain.Enums
{
/// <summary>
/// Enumeration for the source of synchronization.
/// Right now it can either be from the client or the server.
/// </summary>
public enum SynchronizationSource
{
Client,
Server
}
}
1 change: 1 addition & 0 deletions Wino.Core.Domain/Enums/WinoPage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public enum WinoPage
MailListPage,
ReadComposePanePage,
LanguageTimePage,
AppPreferencesPage,
SettingOptionsPage,
}
}
11 changes: 11 additions & 0 deletions Wino.Core.Domain/Enums/WinoServerConnectionStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Wino.Core.Domain.Enums
{
public enum WinoServerConnectionStatus
{
None,
Connecting,
Connected,
Disconnected,
Failed
}
}

This file was deleted.

12 changes: 12 additions & 0 deletions Wino.Core.Domain/Exceptions/WinoServerException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;

namespace Wino.Core.Domain.Exceptions
{
/// <summary>
/// All server crash types. Wino Server ideally should not throw anything else than this Exception type.
/// </summary>
public class WinoServerException : Exception
{
public WinoServerException(string message) : base(message) { }
}
}
20 changes: 20 additions & 0 deletions Wino.Core.Domain/Extensions/MimeExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace Wino.Core.Domain.Extensions
{
public static class MimeExtensions
{
public static string GetBase64MimeMessage(this MimeKit.MimeMessage message)
{
using System.IO.MemoryStream memoryStream = new();
message.WriteTo(MimeKit.FormatOptions.Default, memoryStream);
byte[] buffer = memoryStream.GetBuffer();
int count = (int)memoryStream.Length;

return Convert.ToBase64String(buffer);
}

public static MimeKit.MimeMessage GetMimeMessageFromBase64(this string base64)
=> MimeKit.MimeMessage.Load(new System.IO.MemoryStream(Convert.FromBase64String(base64)));
}
}
12 changes: 0 additions & 12 deletions Wino.Core.Domain/Interfaces/IAppInitializerService.cs

This file was deleted.

21 changes: 21 additions & 0 deletions Wino.Core.Domain/Interfaces/IApplicationConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace Wino.Core.Domain.Interfaces
{
/// <summary>
/// Singleton object that holds the application data folder path and the publisher shared folder path.
/// Load the values before calling any service.
/// App data folder is used for storing files.
/// Pubhlisher cache folder is only used for database file so other apps can access it in the same package by same publisher.
/// </summary>
public interface IApplicationConfiguration
{
/// <summary>
/// Application data folder.
/// </summary>
string ApplicationDataFolderPath { get; set; }

/// <summary>
/// Publisher shared folder path.
/// </summary>
string PublisherSharedFolderPath { get; set; }
}
}
21 changes: 2 additions & 19 deletions Wino.Core.Domain/Interfaces/IAuthenticator.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Threading.Tasks;
using System.Threading.Tasks;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Enums;

Expand All @@ -23,28 +22,12 @@ public interface IAuthenticator

/// <summary>
/// Initial creation of token. Requires user interaction.
/// This will save token into database, but still returns for account creation
/// This will cache the token but still returns for account creation
/// since account address is required.
/// </summary>
/// <param name="expectedAccountAddress">Token cache might ask for regeneration of token for specific
/// account address. If one is provided and re-generation native token doesn't belong to this address
/// token saving to database won't happen.</param>
/// <returns>Freshly created TokenInformation..</returns>
Task<TokenInformation> GenerateTokenAsync(MailAccount account, bool saveToken);

/// <summary>
/// Required for external authorization on launched browser to continue.
/// Used for Gmail.
/// </summary>
/// <param name="authorizationResponseUri">Response's redirect uri.</param>
void ContinueAuthorization(Uri authorizationResponseUri);

/// <summary>
/// For external browser required authentications.
/// Canceling Gmail authentication dialog etc.
/// </summary>
void CancelAuthorization();

/// <summary>
/// ClientId in case of needed for authorization/authentication.
/// </summary>
Expand Down
6 changes: 6 additions & 0 deletions Wino.Core.Domain/Interfaces/IAuthenticatorTypes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace Wino.Core.Domain.Interfaces
{
public interface IOutlookAuthenticator : IAuthenticator { }
public interface IGmailAuthenticator : IAuthenticator { }
public interface IImapAuthenticator : IAuthenticator { }
}
54 changes: 54 additions & 0 deletions Wino.Core.Domain/Interfaces/IBaseSynchronizer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using System.Threading;
using System.Threading.Tasks;
using MailKit;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Synchronization;

namespace Wino.Core.Domain.Interfaces
{
public interface IBaseSynchronizer
{
/// <summary>
/// Account that is assigned for this synchronizer.
/// </summary>
MailAccount Account { get; }

/// <summary>
/// Synchronizer state.
/// </summary>
AccountSynchronizerState State { get; }

/// <summary>
/// Queues a single request to be executed in the next synchronization.
/// </summary>
/// <param name="request">Request to queue.</param>
void QueueRequest(IRequestBase request);

/// <summary>
/// TODO
/// </summary>
/// <returns>Whether active synchronization is stopped or not.</returns>
bool CancelActiveSynchronization();

/// <summary>
/// Performs a full synchronization with the server with given options.
/// This will also prepares batch requests for execution.
/// Requests are executed in the order they are queued and happens before the synchronization.
/// Result of the execution queue is processed during the synchronization.
/// </summary>
/// <param name="options">Options for synchronization.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>Result summary of synchronization.</returns>
Task<SynchronizationResult> SynchronizeAsync(SynchronizationOptions options, CancellationToken cancellationToken = default);

/// <summary>
/// Downloads a single MIME message from the server and saves it to disk.
/// </summary>
/// <param name="mailItem">Mail item to download from server.</param>
/// <param name="transferProgress">Optional progress reporting for download operation.</param>
/// <param name="cancellationToken">Cancellation token.</param>
Task DownloadMissingMimeMessageAsync(IMailItem mailItem, ITransferProgress transferProgress, CancellationToken cancellationToken = default);
}
}
8 changes: 8 additions & 0 deletions Wino.Core.Domain/Interfaces/IClientMessage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Wino.Core.Domain.Interfaces
{
/// <summary>
/// All messages that Client sends to Server and awaits a response in return.
/// For example; triggering a new synchronization request.
/// </summary>
public interface IClientMessage;
}
2 changes: 1 addition & 1 deletion Wino.Core.Domain/Interfaces/ILogInitializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{
public interface ILogInitializer
{
void SetupLogger(string logFolderPath);
void SetupLogger(string fullLogFilePath);

void RefreshLoggingLevel();
}
Expand Down
22 changes: 20 additions & 2 deletions Wino.Core.Domain/Interfaces/IMailService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public interface IMailService
{
Task<MailCopy> GetSingleMailItemAsync(string mailCopyId, string remoteFolderId);
Task<MailCopy> GetSingleMailItemAsync(Guid uniqueMailId);
Task<MailCopy> CreateDraftAsync(MailAccount composerAccount, MimeMessage generatedReplyMime, MimeMessage replyingMimeMessage = null, IMailItem replyingMailItem = null);
Task<MailCopy> CreateDraftAsync(MailAccount composerAccount, string generatedReplyMimeMessageBase64, MimeMessage replyingMimeMessage = null, IMailItem replyingMailItem = null);
Task<List<IMailItem>> FetchMailsAsync(MailListInitializationOptions options);

/// <summary>
Expand Down Expand Up @@ -51,7 +51,16 @@ public interface IMailService
/// <param name="newThreadId"></param>
Task MapLocalDraftAsync(string newMailCopyId, string newDraftId, string newThreadId);

Task<MimeMessage> CreateDraftMimeMessageAsync(Guid accountId, DraftCreationOptions options);
/// <summary>
/// Creates a draft message with the given options.
/// </summary>
/// <param name="accountId">Account to create draft for.</param>
/// <param name="options">Draft creation options.</param>
/// <returns>
/// Base64 encoded string of MimeMessage object.
/// This is mainly for serialization purposes.
/// </returns>
Task<string> CreateDraftMimeBase64Async(Guid accountId, DraftCreationOptions options);
Task UpdateMailAsync(MailCopy mailCopy);

/// <summary>
Expand Down Expand Up @@ -92,5 +101,14 @@ public interface IMailService
/// </summary>
/// <param name="folderId">Folder id to get unread mails for.</param>
Task<List<MailCopy>> GetUnreadMailsByFolderIdAsync(Guid folderId);

/// <summary>
/// Checks whether the mail exists in the folder.
/// When deciding Create or Update existing mail, we need to check if the mail exists in the folder.
/// </summary>
/// <param name="messageId">Message id</param>
/// <param name="folderId">Folder's local id.</param>
/// <returns>Whether mail exists in the folder or not.</returns>
Task<bool> IsMailExistsAsync(string mailCopyId, Guid folderId);
}
}
Loading