This commit is contained in:
Liza 2023-10-03 22:05:19 +02:00
parent d337413b82
commit a1a9c70889
Signed by: liza
GPG Key ID: 7199F8D727D55F67
19 changed files with 97 additions and 60 deletions

View File

@ -10,9 +10,6 @@ public sealed class AccountConfigurationV7 : IAccountConfiguration
{ {
private const int DefaultEntropyLength = 16; private const int DefaultEntropyLength = 16;
private static readonly ILogger _logger =
DependencyInjectionContext.LoggerProvider.CreateLogger<AccountConfigurationV7>();
[JsonConstructor] [JsonConstructor]
public AccountConfigurationV7() public AccountConfigurationV7()
{ {
@ -75,9 +72,8 @@ public sealed class AccountConfigurationV7 : IAccountConfiguration
byte[] guidBytes = ProtectedData.Unprotect(Convert.FromBase64String(EncryptedId), Entropy, DataProtectionScope.CurrentUser); byte[] guidBytes = ProtectedData.Unprotect(Convert.FromBase64String(EncryptedId), Entropy, DataProtectionScope.CurrentUser);
return new Guid(guidBytes); return new Guid(guidBytes);
} }
catch (Exception e) catch (Exception)
{ {
_logger.LogTrace(e, "Could not load account id {Id}", EncryptedId);
return null; return null;
} }
} }

View File

@ -7,15 +7,13 @@ namespace Pal.Client.Configuration;
internal static class ConfigurationData internal static class ConfigurationData
{ {
private static readonly ILogger _logger =
DependencyInjectionContext.LoggerProvider.CreateLogger(typeof(ConfigurationData));
[Obsolete("for V1 import")] [Obsolete("for V1 import")]
internal static readonly byte[] FixedV1Entropy = { 0x22, 0x4b, 0xe7, 0x21, 0x44, 0x83, 0x69, 0x55, 0x80, 0x38 }; internal static readonly byte[] FixedV1Entropy = { 0x22, 0x4b, 0xe7, 0x21, 0x44, 0x83, 0x69, 0x55, 0x80, 0x38 };
public const string ConfigFileName = "palace-pal.config.json"; public const string ConfigFileName = "palace-pal.config.json";
private static bool? _supportsDpapi; private static bool? _supportsDpapi;
public static bool SupportsDpapi public static bool SupportsDpapi
{ {
get get
@ -34,9 +32,8 @@ internal static class ConfigurationData
{ {
_supportsDpapi = false; _supportsDpapi = false;
} }
_logger.LogTrace("DPAPI support: {Supported}", _supportsDpapi);
} }
return _supportsDpapi.Value; return _supportsDpapi.Value;
} }
} }

View File

@ -34,7 +34,6 @@ namespace Pal.Client;
internal sealed class DependencyInjectionContext : IDisposable internal sealed class DependencyInjectionContext : IDisposable
{ {
public const string DatabaseFileName = "palace-pal.data.sqlite3"; public const string DatabaseFileName = "palace-pal.data.sqlite3";
public static DalamudLoggerProvider LoggerProvider { get; private set; } = null!;
/// <summary> /// <summary>
/// Initialized as temporary logger, will be overriden once context is ready with a logger that supports scopes. /// Initialized as temporary logger, will be overriden once context is ready with a logger that supports scopes.
@ -59,8 +58,8 @@ internal sealed class DependencyInjectionContext : IDisposable
IPluginLog pluginLog, IPluginLog pluginLog,
Plugin plugin) Plugin plugin)
{ {
LoggerProvider = new DalamudLoggerProvider(pluginLog); var loggerProvider = new DalamudLoggerProvider(pluginLog);
_logger = LoggerProvider.CreateLogger<DependencyInjectionContext>(); _logger = loggerProvider.CreateLogger<DependencyInjectionContext>();
_logger.LogInformation("Building dalamud service container for {Assembly}", _logger.LogInformation("Building dalamud service container for {Assembly}",
typeof(DependencyInjectionContext).Assembly.FullName); typeof(DependencyInjectionContext).Assembly.FullName);

View File

@ -447,7 +447,6 @@ internal sealed class FrameworkService : IDisposable
Position = obj.Position, Position = obj.Position,
Seen = true, Seen = true,
Source = ClientLocation.ESource.ExplodedLocally, Source = ClientLocation.ESource.ExplodedLocally,
}); });
} }
} }

View File

@ -23,7 +23,8 @@ internal sealed class ObjectTableDebug : IDisposable
private readonly IGameGui _gameGui; private readonly IGameGui _gameGui;
private readonly IClientState _clientState; private readonly IClientState _clientState;
public ObjectTableDebug(DalamudPluginInterface pluginInterface, IObjectTable objectTable, IGameGui gameGui, IClientState clientState) public ObjectTableDebug(DalamudPluginInterface pluginInterface, IObjectTable objectTable, IGameGui gameGui,
IClientState clientState)
{ {
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
_objectTable = objectTable; _objectTable = objectTable;

View File

@ -24,14 +24,20 @@ internal abstract class DbTask<T>
{ {
using var scope = _serviceScopeFactory.CreateScope(); using var scope = _serviceScopeFactory.CreateScope();
ILogger<T> logger = scope.ServiceProvider.GetRequiredService<ILogger<T>>(); ILogger<T> logger = scope.ServiceProvider.GetRequiredService<ILogger<T>>();
using var dbContext = scope.ServiceProvider.GetRequiredService<PalClientContext>(); try
{
using var dbContext = scope.ServiceProvider.GetRequiredService<PalClientContext>();
Run(dbContext, logger); Run(dbContext, logger);
}
catch (Exception e)
{
logger.LogError(e, "Failed to run DbTask");
}
} }
catch (Exception e) catch (Exception)
{ {
DependencyInjectionContext.LoggerProvider.CreateLogger<DbTask<T>>() // nothing we can do here but catch it, if we don't we crash the game
.LogError(e, "Failed to run DbTask");
} }
}); });
} }

View File

@ -24,7 +24,8 @@ internal sealed class MarkLocalSeen : DbTask<MarkLocalSeen>
{ {
lock (_territory.LockObj) lock (_territory.LockObj)
{ {
logger.LogInformation("Marking {Count} locations as seen locally in territory {Territory}", _locations.Count, logger.LogInformation("Marking {Count} locations as seen locally in territory {Territory}",
_locations.Count,
_territory.TerritoryType); _territory.TerritoryType);
List<int> localIds = _locations.Select(l => l.LocalId).Where(x => x != null).Cast<int>().ToList(); List<int> localIds = _locations.Select(l => l.LocalId).Where(x => x != null).Cast<int>().ToList();
dbContext.Locations dbContext.Locations

View File

@ -23,7 +23,6 @@ public sealed class TerritoryState
_clientState.IsLoggedIn _clientState.IsLoggedIn
&& _condition[ConditionFlag.InDeepDungeon] && _condition[ConditionFlag.InDeepDungeon]
&& typeof(ETerritoryType).IsEnumDefined(_clientState.TerritoryType); && typeof(ETerritoryType).IsEnumDefined(_clientState.TerritoryType);
} }
public enum PomanderState public enum PomanderState

View File

@ -40,7 +40,8 @@ internal sealed class JwtClaims
payload += "="; payload += "=";
string content = Encoding.UTF8.GetString(Convert.FromBase64String(payload)); string content = Encoding.UTF8.GetString(Convert.FromBase64String(payload));
return JsonSerializer.Deserialize<JwtClaims>(content) ?? throw new InvalidOperationException("token deserialization returned null"); return JsonSerializer.Deserialize<JwtClaims>(content) ??
throw new InvalidOperationException("token deserialization returned null");
} }
} }
@ -73,5 +74,6 @@ internal sealed class JwtRoleConverter : JsonConverter<List<string>>
throw new JsonException("bad token type"); throw new JsonException("bad token type");
} }
public override void Write(Utf8JsonWriter writer, List<string> value, JsonSerializerOptions options) => throw new NotImplementedException(); public override void Write(Utf8JsonWriter writer, List<string> value, JsonSerializerOptions options) =>
throw new NotImplementedException();
} }

View File

@ -16,5 +16,6 @@ public sealed class JwtDateConverter : JsonConverter<DateTimeOffset>
return Zero.AddSeconds(reader.GetInt64()); return Zero.AddSeconds(reader.GetInt64());
} }
public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) => throw new NotImplementedException(); public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) =>
throw new NotImplementedException();
} }

View File

@ -11,11 +11,13 @@ using Microsoft.Extensions.Logging;
using Pal.Client.Configuration; using Pal.Client.Configuration;
using Pal.Client.Extensions; using Pal.Client.Extensions;
using Pal.Client.Properties; using Pal.Client.Properties;
using Version = System.Version;
namespace Pal.Client.Net; namespace Pal.Client.Net;
internal partial class RemoteApi internal partial class RemoteApi
{ {
private static readonly Version PluginVersion = typeof(Plugin).Assembly.GetName().Version!;
private readonly SemaphoreSlim _connectLock = new(1, 1); private readonly SemaphoreSlim _connectLock = new(1, 1);
private async Task<(bool Success, string Error)> TryConnect(CancellationToken cancellationToken, private async Task<(bool Success, string Error)> TryConnect(CancellationToken cancellationToken,
@ -73,7 +75,14 @@ internal partial class RemoteApi
if (configuredAccount == null) if (configuredAccount == null)
{ {
_logger.LogInformation("No account information saved for {Url}, creating new account", RemoteUrl); _logger.LogInformation("No account information saved for {Url}, creating new account", RemoteUrl);
var createAccountReply = await accountClient.CreateAccountAsync(new CreateAccountRequest(), var createAccountReply = await accountClient.CreateAccountAsync(new CreateAccountRequest
{
Version = new()
{
Major = PluginVersion.Major,
Minor = PluginVersion.Minor,
},
},
headers: UnauthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10), headers: UnauthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10),
cancellationToken: cancellationToken); cancellationToken: cancellationToken);
if (createAccountReply.Success) if (createAccountReply.Success)
@ -115,7 +124,15 @@ internal partial class RemoteApi
_logger.LogInformation("Logging in with account id {AccountId}", _logger.LogInformation("Logging in with account id {AccountId}",
configuredAccount.AccountId.ToPartialId()); configuredAccount.AccountId.ToPartialId());
LoginReply loginReply = await accountClient.LoginAsync( LoginReply loginReply = await accountClient.LoginAsync(
new LoginRequest { AccountId = configuredAccount.AccountId.ToString() }, new LoginRequest
{
AccountId = configuredAccount.AccountId.ToString(),
Version = new()
{
Major = PluginVersion.Major,
Minor = PluginVersion.Minor,
},
},
headers: UnauthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10), headers: UnauthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10),
cancellationToken: cancellationToken); cancellationToken: cancellationToken);

View File

@ -14,9 +14,10 @@ internal partial class RemoteApi
var exportClient = new ExportService.ExportServiceClient(_channel); var exportClient = new ExportService.ExportServiceClient(_channel);
var exportReply = await exportClient.ExportAsync(new ExportRequest var exportReply = await exportClient.ExportAsync(new ExportRequest
{ {
ServerUrl = RemoteUrl, ServerUrl = RemoteUrl,
}, headers: AuthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(120), cancellationToken: cancellationToken); }, headers: AuthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(120),
cancellationToken: cancellationToken);
return (exportReply.Success, exportReply.Data); return (exportReply.Success, exportReply.Data);
} }
} }

View File

@ -12,17 +12,21 @@ namespace Pal.Client.Net;
internal partial class RemoteApi internal partial class RemoteApi
{ {
public async Task<(bool, List<PersistentLocation>)> DownloadRemoteMarkers(ushort territoryId, CancellationToken cancellationToken = default) public async Task<(bool, List<PersistentLocation>)> DownloadRemoteMarkers(ushort territoryId,
CancellationToken cancellationToken = default)
{ {
if (!await Connect(cancellationToken)) if (!await Connect(cancellationToken))
return (false, new()); return (false, new());
var palaceClient = new PalaceService.PalaceServiceClient(_channel); var palaceClient = new PalaceService.PalaceServiceClient(_channel);
var downloadReply = await palaceClient.DownloadFloorsAsync(new DownloadFloorsRequest { TerritoryType = territoryId }, headers: AuthorizedHeaders(), cancellationToken: cancellationToken); var downloadReply = await palaceClient.DownloadFloorsAsync(
new DownloadFloorsRequest { TerritoryType = territoryId }, headers: AuthorizedHeaders(),
cancellationToken: cancellationToken);
return (downloadReply.Success, downloadReply.Objects.Select(CreateLocationFromNetworkObject).ToList()); return (downloadReply.Success, downloadReply.Objects.Select(CreateLocationFromNetworkObject).ToList());
} }
public async Task<(bool, List<PersistentLocation>)> UploadLocations(ushort territoryType, IReadOnlyList<PersistentLocation> locations, CancellationToken cancellationToken = default) public async Task<(bool, List<PersistentLocation>)> UploadLocations(ushort territoryType,
IReadOnlyList<PersistentLocation> locations, CancellationToken cancellationToken = default)
{ {
if (locations.Count == 0) if (locations.Count == 0)
return (true, new()); return (true, new());
@ -42,11 +46,13 @@ internal partial class RemoteApi
Y = m.Position.Y, Y = m.Position.Y,
Z = m.Position.Z Z = m.Position.Z
})); }));
var uploadReply = await palaceClient.UploadFloorsAsync(uploadRequest, headers: AuthorizedHeaders(), cancellationToken: cancellationToken); var uploadReply = await palaceClient.UploadFloorsAsync(uploadRequest, headers: AuthorizedHeaders(),
cancellationToken: cancellationToken);
return (uploadReply.Success, uploadReply.Objects.Select(CreateLocationFromNetworkObject).ToList()); return (uploadReply.Success, uploadReply.Objects.Select(CreateLocationFromNetworkObject).ToList());
} }
public async Task<bool> MarkAsSeen(ushort territoryType, IReadOnlyList<PersistentLocation> locations, CancellationToken cancellationToken = default) public async Task<bool> MarkAsSeen(ushort territoryType, IReadOnlyList<PersistentLocation> locations,
CancellationToken cancellationToken = default)
{ {
if (locations.Count == 0) if (locations.Count == 0)
return true; return true;
@ -59,7 +65,8 @@ internal partial class RemoteApi
foreach (var marker in locations) foreach (var marker in locations)
seenRequest.NetworkIds.Add(marker.NetworkId.ToString()); seenRequest.NetworkIds.Add(marker.NetworkId.ToString());
var seenReply = await palaceClient.MarkObjectsSeenAsync(seenRequest, headers: AuthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(10), cancellationToken: cancellationToken); var seenReply = await palaceClient.MarkObjectsSeenAsync(seenRequest, headers: AuthorizedHeaders(),
deadline: DateTime.UtcNow.AddSeconds(10), cancellationToken: cancellationToken);
return seenReply.Success; return seenReply.Success;
} }
@ -80,7 +87,9 @@ internal partial class RemoteApi
return new(false, new List<FloorStatistics>()); return new(false, new List<FloorStatistics>());
var palaceClient = new PalaceService.PalaceServiceClient(_channel); var palaceClient = new PalaceService.PalaceServiceClient(_channel);
var statisticsReply = await palaceClient.FetchStatisticsAsync(new StatisticsRequest(), headers: AuthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(30), cancellationToken: cancellationToken); var statisticsReply = await palaceClient.FetchStatisticsAsync(new StatisticsRequest(),
headers: AuthorizedHeaders(), deadline: DateTime.UtcNow.AddSeconds(30),
cancellationToken: cancellationToken);
return (statisticsReply.Success, statisticsReply.FloorStatistics.ToList()); return (statisticsReply.Success, statisticsReply.FloorStatistics.ToList());
} }
} }

View File

@ -29,18 +29,18 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup Condition="'$(Configuration)' == 'Release' And Exists('Certificate.pfx')"> <ItemGroup Condition="'$(Configuration)' == 'Release' And Exists('Certificate.pfx')">
<None Remove="Certificate.pfx" /> <None Remove="Certificate.pfx"/>
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(Configuration)' == 'Release' And Exists('Certificate.pfx')"> <ItemGroup Condition="'$(Configuration)' == 'Release' And Exists('Certificate.pfx')">
<EmbeddedResource Include="Certificate.pfx" /> <EmbeddedResource Include="Certificate.pfx"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="DalamudPackager" Version="2.1.12" /> <PackageReference Include="DalamudPackager" Version="2.1.12"/>
<PackageReference Include="Dalamud.Extensions.MicrosoftLogging" Version="2.0.0" /> <PackageReference Include="Dalamud.Extensions.MicrosoftLogging" Version="2.0.0"/>
<PackageReference Include="Google.Protobuf" Version="3.24.3" /> <PackageReference Include="Google.Protobuf" Version="3.24.3"/>
<PackageReference Include="Grpc.Net.Client" Version="2.57.0" /> <PackageReference Include="Grpc.Net.Client" Version="2.57.0"/>
<PackageReference Include="GitInfo" Version="2.3.0"> <PackageReference Include="GitInfo" Version="2.3.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>
@ -48,24 +48,24 @@
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.11" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.11"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.11"> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.11">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0"/>
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="7.0.1" /> <PackageReference Include="System.Security.Cryptography.ProtectedData" Version="7.0.1"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Pal.Common\Pal.Common.csproj" /> <ProjectReference Include="..\Pal.Common\Pal.Common.csproj"/>
<ProjectReference Include="..\vendor\ECommons\ECommons\ECommons.csproj" /> <ProjectReference Include="..\vendor\ECommons\ECommons\ECommons.csproj"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Protobuf Include="..\Pal.Common\Protos\account.proto" Link="Protos\account.proto" GrpcServices="Client" Access="Internal" /> <Protobuf Include="..\Pal.Common\Protos\account.proto" Link="Protos\account.proto" GrpcServices="Client" Access="Internal"/>
<Protobuf Include="..\Pal.Common\Protos\palace.proto" Link="Protos\palace.proto" GrpcServices="Client" Access="Internal" /> <Protobuf Include="..\Pal.Common\Protos\palace.proto" Link="Protos\palace.proto" GrpcServices="Client" Access="Internal"/>
<Protobuf Include="..\Pal.Common\Protos\export.proto" Link="Protos\export.proto" GrpcServices="Client" Access="Internal" /> <Protobuf Include="..\Pal.Common\Protos\export.proto" Link="Protos\export.proto" GrpcServices="Client" Access="Internal"/>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -124,10 +124,10 @@
</Target> </Target>
<Target Name="RenameLatestZip" AfterTargets="PackagePlugin" Condition="'$(Configuration)' == 'Release'"> <Target Name="RenameLatestZip" AfterTargets="PackagePlugin" Condition="'$(Configuration)' == 'Release'">
<Exec Command="rename &quot;$(OutDir)$(AssemblyName)\latest.zip&quot; &quot;$(AssemblyName)-$(Version).zip&quot;" /> <Exec Command="rename &quot;$(OutDir)$(AssemblyName)\latest.zip&quot; &quot;$(AssemblyName)-$(Version).zip&quot;"/>
</Target> </Target>
<Target Name="Clean"> <Target Name="Clean">
<RemoveDir Directories="dist" /> <RemoveDir Directories="dist"/>
</Target> </Target>
</Project> </Project>

View File

@ -5,6 +5,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Dalamud.Extensions.MicrosoftLogging;
using Dalamud.Game.Command; using Dalamud.Game.Command;
using Dalamud.Interface.Windowing; using Dalamud.Interface.Windowing;
using Dalamud.Plugin; using Dalamud.Plugin;
@ -40,7 +41,7 @@ internal sealed class Plugin : IDalamudPlugin
private ELoadState _loadState = ELoadState.Initializing; private ELoadState _loadState = ELoadState.Initializing;
private DependencyInjectionContext? _dependencyInjectionContext; private DependencyInjectionContext? _dependencyInjectionContext;
private ILogger _logger = DependencyInjectionContext.LoggerProvider.CreateLogger<Plugin>(); private ILogger _logger;
private WindowSystem? _windowSystem; private WindowSystem? _windowSystem;
private IServiceScope? _rootScope; private IServiceScope? _rootScope;
private Action? _loginAction; private Action? _loginAction;
@ -50,13 +51,15 @@ internal sealed class Plugin : IDalamudPlugin
ICommandManager commandManager, ICommandManager commandManager,
IClientState clientState, IClientState clientState,
IChatGui chatGui, IChatGui chatGui,
IFramework framework) IFramework framework,
IPluginLog pluginLog)
{ {
_pluginInterface = pluginInterface; _pluginInterface = pluginInterface;
_commandManager = commandManager; _commandManager = commandManager;
_clientState = clientState; _clientState = clientState;
_chatGui = chatGui; _chatGui = chatGui;
_framework = framework; _framework = framework;
_logger = new DalamudLoggerProvider(pluginLog).CreateLogger<Plugin>();
// set up the current UI language before creating anything // set up the current UI language before creating anything
Localization.Culture = new CultureInfo(_pluginInterface.UiLanguage); Localization.Culture = new CultureInfo(_pluginInterface.UiLanguage);
@ -73,8 +76,6 @@ internal sealed class Plugin : IDalamudPlugin
Task.Run(async () => await CreateDependencyContext()); Task.Run(async () => await CreateDependencyContext());
} }
public string Name => Localization.Palace_Pal;
private async Task CreateDependencyContext() private async Task CreateDependencyContext()
{ {
try try

View File

@ -15,6 +15,7 @@ dotnet ef migrations add MigrationName --configuration EF
``` ```
To rebuild the compiled model: To rebuild the compiled model:
```shell ```shell
dotnet ef dbcontext optimize --output-dir Database/Compiled --namespace Pal.Client.Database.Compiled --configuration EF dotnet ef dbcontext optimize --output-dir Database/Compiled --namespace Pal.Client.Database.Compiled --configuration EF
``` ```

View File

@ -18,6 +18,7 @@ service AccountService {
} }
message CreateAccountRequest { message CreateAccountRequest {
Version version = 1;
} }
message CreateAccountReply { message CreateAccountReply {
@ -35,6 +36,7 @@ enum CreateAccountError {
message LoginRequest { message LoginRequest {
string accountId = 1; string accountId = 1;
Version version = 2;
} }
message LoginReply { message LoginReply {
@ -55,4 +57,9 @@ message VerifyRequest {
} }
message VerifyReply { message VerifyReply {
} }
message Version {
int32 major = 1;
int32 minor = 2;
}

@ -1 +1 @@
Subproject commit 43268725eb4fc0ccef31af61a1a917832f83d3fd Subproject commit 4f629ceb6965a20fad98bd9da8b8ed4f02b7f3ed

@ -1 +1 @@
Subproject commit d67d342f395da8447131e389143d9683c0bdfbae Subproject commit 9dff2ca46b46339565ef144e6b4b365eb516daaf