From 22f05c00c11a8c7b6364ce1aeee1d3e300dbb845 Mon Sep 17 00:00:00 2001 From: Dennis Brentjes Date: Sun, 30 Apr 2023 20:51:42 +0200 Subject: [PATCH] Added a client (From generator) and a basic login page to test it. --- .../FrontendPlatformUno.Mobile.csproj | 2 - .../FrontendPlatformUno.Skia.Gtk.csproj | 2 - .../FrontendPlatformUno.Wasm.csproj | 2 - .../FrontendPlatformUno.Windows.csproj | 2 - .../FrontendPlatformUno/App.cs | 17 +- .../FrontendPlatformUno/AppResources.xaml | 1 + .../FrontendPlatformUno.csproj | 27 +- .../FrontendPlatformUno.csproj.user | 6 + .../FrontendPlatformUno/GlobalUsings.cs | 3 - .../FrontendPlatformUno/Services/.gitignore | 1 + .../Services/Caching/IWeatherCache.cs | 10 - .../Services/Caching/WeatherCache.cs | 80 ------ .../Services/Endpoints/IApiClient.cs | 12 - .../Services/Gamenight.yaml | 249 ++++++++++++++++++ .../Styles/GamenightStyles.xaml | 13 + .../ViewModels/LoginViewModel.cs | 30 ++- .../Views/GamenightsPage.xaml | 13 +- .../FrontendPlatformUno/Views/LoginPage.xaml | 27 +- .../Views/LoginPage.xaml.cs | 11 + .../Views/NavBarUserControl.xaml | 27 ++ .../Views/NavBarUserControl.xaml.cs | 27 ++ backend-actix/src/request/responses.rs | 9 - backend-actix/src/request/user_handlers.rs | 19 +- 23 files changed, 415 insertions(+), 175 deletions(-) create mode 100644 FrontendPlatformUno/FrontendPlatformUno/Services/.gitignore delete mode 100644 FrontendPlatformUno/FrontendPlatformUno/Services/Caching/IWeatherCache.cs delete mode 100644 FrontendPlatformUno/FrontendPlatformUno/Services/Caching/WeatherCache.cs delete mode 100644 FrontendPlatformUno/FrontendPlatformUno/Services/Endpoints/IApiClient.cs create mode 100644 FrontendPlatformUno/FrontendPlatformUno/Services/Gamenight.yaml create mode 100644 FrontendPlatformUno/FrontendPlatformUno/Styles/GamenightStyles.xaml create mode 100644 FrontendPlatformUno/FrontendPlatformUno/Views/NavBarUserControl.xaml create mode 100644 FrontendPlatformUno/FrontendPlatformUno/Views/NavBarUserControl.xaml.cs diff --git a/FrontendPlatformUno/FrontendPlatformUno.Mobile/FrontendPlatformUno.Mobile.csproj b/FrontendPlatformUno/FrontendPlatformUno.Mobile/FrontendPlatformUno.Mobile.csproj index ece10a2..5b89230 100644 --- a/FrontendPlatformUno/FrontendPlatformUno.Mobile/FrontendPlatformUno.Mobile.csproj +++ b/FrontendPlatformUno/FrontendPlatformUno.Mobile/FrontendPlatformUno.Mobile.csproj @@ -27,10 +27,8 @@ - - diff --git a/FrontendPlatformUno/FrontendPlatformUno.Skia.Gtk/FrontendPlatformUno.Skia.Gtk.csproj b/FrontendPlatformUno/FrontendPlatformUno.Skia.Gtk/FrontendPlatformUno.Skia.Gtk.csproj index d9d43dc..b871876 100644 --- a/FrontendPlatformUno/FrontendPlatformUno.Skia.Gtk/FrontendPlatformUno.Skia.Gtk.csproj +++ b/FrontendPlatformUno/FrontendPlatformUno.Skia.Gtk/FrontendPlatformUno.Skia.Gtk.csproj @@ -14,10 +14,8 @@ - - diff --git a/FrontendPlatformUno/FrontendPlatformUno.Wasm/FrontendPlatformUno.Wasm.csproj b/FrontendPlatformUno/FrontendPlatformUno.Wasm/FrontendPlatformUno.Wasm.csproj index c3c8ca6..e363182 100644 --- a/FrontendPlatformUno/FrontendPlatformUno.Wasm/FrontendPlatformUno.Wasm.csproj +++ b/FrontendPlatformUno/FrontendPlatformUno.Wasm/FrontendPlatformUno.Wasm.csproj @@ -64,11 +64,9 @@ - - diff --git a/FrontendPlatformUno/FrontendPlatformUno.Windows/FrontendPlatformUno.Windows.csproj b/FrontendPlatformUno/FrontendPlatformUno.Windows/FrontendPlatformUno.Windows.csproj index 18b266e..08f37f4 100644 --- a/FrontendPlatformUno/FrontendPlatformUno.Windows/FrontendPlatformUno.Windows.csproj +++ b/FrontendPlatformUno/FrontendPlatformUno.Windows/FrontendPlatformUno.Windows.csproj @@ -30,10 +30,8 @@ - - diff --git a/FrontendPlatformUno/FrontendPlatformUno/App.cs b/FrontendPlatformUno/FrontendPlatformUno/App.cs index fd18c8b..feb25bb 100644 --- a/FrontendPlatformUno/FrontendPlatformUno/App.cs +++ b/FrontendPlatformUno/FrontendPlatformUno/App.cs @@ -1,5 +1,6 @@ using FrontendPlatformUno.Views; using FrontendPlatformUno.ViewModels; +using FrontendPlatformUno.Services.Api; namespace FrontendPlatformUno { @@ -34,23 +35,11 @@ namespace FrontendPlatformUno ) // Enable localization (see appsettings.json for supported languages) .UseLocalization() - // Register Json serializers (ISerializer and ISerializer) - .UseSerialization((context, services) => services - .AddContentSerializer(context) - .AddJsonTypeInfo(WeatherForecastContext.Default.IImmutableListWeatherForecast)) - .UseHttp((context, services) => services - // Register HttpClient -#if DEBUG - // DelegatingHandler will be automatically injected into Refit Client - .AddTransient() -#endif - .AddSingleton() - .AddRefitClient(context)) .ConfigureServices((context, services) => { // TODO: Register your services //services.AddSingleton(); - //services.AddSingleton(); + services.AddSingleton(_ => new DefaultApi("http://localhost:8080")); }) .UseNavigation(RegisterRoutes) ); @@ -68,8 +57,6 @@ namespace FrontendPlatformUno { views.Register( new ViewMap(ViewModel: typeof(ShellViewModel)), - //new ViewMap(), - //new DataViewMap(), new ViewMap(), new ViewMap() ); diff --git a/FrontendPlatformUno/FrontendPlatformUno/AppResources.xaml b/FrontendPlatformUno/FrontendPlatformUno/AppResources.xaml index 3fb1bc2..463668f 100644 --- a/FrontendPlatformUno/FrontendPlatformUno/AppResources.xaml +++ b/FrontendPlatformUno/FrontendPlatformUno/AppResources.xaml @@ -8,6 +8,7 @@ ColorOverrideSource="ms-appx:///FrontendPlatformUno/Styles/ColorPaletteOverride.xaml" FontOverrideSource="ms-appx:///FrontendPlatformUno/Styles/MaterialFontsOverride.xaml" /> + diff --git a/FrontendPlatformUno/FrontendPlatformUno/FrontendPlatformUno.csproj b/FrontendPlatformUno/FrontendPlatformUno/FrontendPlatformUno.csproj index c325657..5fd5d36 100644 --- a/FrontendPlatformUno/FrontendPlatformUno/FrontendPlatformUno.csproj +++ b/FrontendPlatformUno/FrontendPlatformUno/FrontendPlatformUno.csproj @@ -1,4 +1,4 @@ - + $(TargetFrameworks);net7.0-windows10.0.19041 $(TargetFrameworks);net7.0;net7.0-ios;net7.0-android;net7.0-maccatalyst @@ -8,16 +8,18 @@ + + + + - - @@ -77,8 +79,10 @@ + + @@ -86,7 +90,24 @@ + + + + + + + True + True + Gamenight.yaml + + + + + + OpenApiCodeGenerator + Gamenight.cs + diff --git a/FrontendPlatformUno/FrontendPlatformUno/FrontendPlatformUno.csproj.user b/FrontendPlatformUno/FrontendPlatformUno/FrontendPlatformUno.csproj.user index b532320..f6e0d89 100644 --- a/FrontendPlatformUno/FrontendPlatformUno/FrontendPlatformUno.csproj.user +++ b/FrontendPlatformUno/FrontendPlatformUno/FrontendPlatformUno.csproj.user @@ -2,11 +2,17 @@ + + Designer + Designer Designer + + Designer + \ No newline at end of file diff --git a/FrontendPlatformUno/FrontendPlatformUno/GlobalUsings.cs b/FrontendPlatformUno/FrontendPlatformUno/GlobalUsings.cs index 0c66040..fe5ab46 100644 --- a/FrontendPlatformUno/FrontendPlatformUno/GlobalUsings.cs +++ b/FrontendPlatformUno/FrontendPlatformUno/GlobalUsings.cs @@ -2,8 +2,6 @@ global using FrontendPlatformUno.DataContracts; global using FrontendPlatformUno.DataContracts.Serialization; global using FrontendPlatformUno.Infrastructure; -global using FrontendPlatformUno.Services.Caching; -global using FrontendPlatformUno.Services.Endpoints; global using Microsoft.Extensions.DependencyInjection; global using Microsoft.Extensions.Hosting; global using Microsoft.Extensions.Localization; @@ -13,7 +11,6 @@ global using Microsoft.UI.Xaml; global using Microsoft.UI.Xaml.Controls; global using Microsoft.UI.Xaml.Media; global using Microsoft.UI.Xaml.Navigation; -global using Refit; global using System; global using System.Collections.Generic; global using System.Collections.Immutable; diff --git a/FrontendPlatformUno/FrontendPlatformUno/Services/.gitignore b/FrontendPlatformUno/FrontendPlatformUno/Services/.gitignore new file mode 100644 index 0000000..6a23d61 --- /dev/null +++ b/FrontendPlatformUno/FrontendPlatformUno/Services/.gitignore @@ -0,0 +1 @@ +Gamenight.cs diff --git a/FrontendPlatformUno/FrontendPlatformUno/Services/Caching/IWeatherCache.cs b/FrontendPlatformUno/FrontendPlatformUno/Services/Caching/IWeatherCache.cs deleted file mode 100644 index 87f04fb..0000000 --- a/FrontendPlatformUno/FrontendPlatformUno/Services/Caching/IWeatherCache.cs +++ /dev/null @@ -1,10 +0,0 @@ -using FrontendPlatformUno.DataContracts; -using System.Collections.Immutable; - -namespace FrontendPlatformUno.Services.Caching -{ - public interface IWeatherCache - { - ValueTask> GetForecast(CancellationToken token); - } -} \ No newline at end of file diff --git a/FrontendPlatformUno/FrontendPlatformUno/Services/Caching/WeatherCache.cs b/FrontendPlatformUno/FrontendPlatformUno/Services/Caching/WeatherCache.cs deleted file mode 100644 index db5896c..0000000 --- a/FrontendPlatformUno/FrontendPlatformUno/Services/Caching/WeatherCache.cs +++ /dev/null @@ -1,80 +0,0 @@ -using Uno.Extensions.Serialization; -using Windows.Networking.Connectivity; -using Windows.Storage; - -namespace FrontendPlatformUno.Services.Caching -{ - public sealed class WeatherCache : IWeatherCache - { - private readonly IApiClient _api; - private readonly ISerializer _serializer; - private readonly ILogger _logger; - - public WeatherCache(IApiClient api, ISerializer serializer, ILogger logger) - { - _api = api; - _serializer = serializer; - _logger = logger; - } - - private bool IsConnected => NetworkInformation.GetInternetConnectionProfile().GetNetworkConnectivityLevel() == NetworkConnectivityLevel.InternetAccess; - - public async ValueTask> GetForecast(CancellationToken token) - { - var weatherText = await GetCachedWeather(); - if (!string.IsNullOrWhiteSpace(weatherText)) - { - return _serializer.FromString>(weatherText); - } - - if (!IsConnected) - { - _logger.LogWarning("App is offline and cannot connect to the API."); - throw new Exception("No internet connection"); - } - - var response = await _api.GetWeather(token); - - if (response.IsSuccessStatusCode && response.Content is not null) - { - var weather = response.Content; - await Save(weather, token); - return weather; - } - else if (response.Error is not null) - { - _logger.LogError(response.Error, "An error occurred while retrieving the latest Forecast."); - throw response.Error; - } - else - { - return ImmutableArray.Empty; - } - } - - private async ValueTask GetFile(CreationCollisionOption option) => - await ApplicationData.Current.TemporaryFolder.CreateFileAsync("weather.json", option); - - private async ValueTask GetCachedWeather() - { - var file = await GetFile(CreationCollisionOption.OpenIfExists); - var properties = await file.GetBasicPropertiesAsync(); - - // Reuse latest cache file if offline - // or if the file is less than 5 minutes old - if (IsConnected || DateTimeOffset.Now.AddMinutes(-5) > properties.DateModified) - { - return null; - } - - return await File.ReadAllTextAsync(file.Path); - } - - private async ValueTask Save(IImmutableList weather, CancellationToken token) - { - var weatherText = _serializer.ToString(weather); - var file = await GetFile(CreationCollisionOption.ReplaceExisting); - await File.WriteAllTextAsync(file.Path, weatherText); - } - } -} \ No newline at end of file diff --git a/FrontendPlatformUno/FrontendPlatformUno/Services/Endpoints/IApiClient.cs b/FrontendPlatformUno/FrontendPlatformUno/Services/Endpoints/IApiClient.cs deleted file mode 100644 index 7680b02..0000000 --- a/FrontendPlatformUno/FrontendPlatformUno/Services/Endpoints/IApiClient.cs +++ /dev/null @@ -1,12 +0,0 @@ -using FrontendPlatformUno.DataContracts; -using System.Collections.Immutable; - -namespace FrontendPlatformUno.Services.Endpoints -{ - [Headers("Content-Type: application/json")] - public interface IApiClient - { - [Get("/api/weatherforecast")] - Task>> GetWeather(CancellationToken cancellationToken = default); - } -} \ No newline at end of file diff --git a/FrontendPlatformUno/FrontendPlatformUno/Services/Gamenight.yaml b/FrontendPlatformUno/FrontendPlatformUno/Services/Gamenight.yaml new file mode 100644 index 0000000..1fa1696 --- /dev/null +++ b/FrontendPlatformUno/FrontendPlatformUno/Services/Gamenight.yaml @@ -0,0 +1,249 @@ +openapi: 3.0.0 +x-stoplight: + id: w776sltk0h1bo +info: + title: Gamenight + version: '1.0' + contact: + name: Dennis Brentjes + email: dennis@brentj.es + url: 'https://brentj.es' + description: Api specifaction for a Gamenight server + license: + name: MIT +servers: + - url: 'http://localhost:8080' + description: Gamenight +paths: + /token: + get: + summary: '' + operationId: get-token + responses: + '200': + $ref: '#/components/responses/TokenResponse' + '401': + $ref: '#/components/responses/FailureResponse' + requestBody: + $ref: '#/components/requestBodies/Login' + description: Submit your credentials to get a JWT-token to use with the rest of the api. + /user: + post: + summary: '' + operationId: post-register + requestBody: + $ref: '#/components/requestBodies/Register' + responses: + '200': + description: '' + '422': + $ref: '#/components/responses/FailureResponse' + description: 'Create a new user given a registration token and user information, username and email must be unique, and password and password_repeat must match.' + parameters: [] + /gamenights: + get: + summary: Your GET endpoint + responses: + '200': + $ref: '#/components/responses/GamenightsResponse' + '400': + $ref: '#/components/responses/FailureResponse' + '401': + $ref: '#/components/responses/FailureResponse' + operationId: get-gamenights + security: + - JWT-Auth: [] + description: Retrieve the list of gamenights on this gamenight server. Requires authorization. + /gamenight: + post: + summary: '' + operationId: post-gamenight + responses: + '200': + description: OK + '401': + $ref: '#/components/responses/FailureResponse' + '422': + $ref: '#/components/responses/FailureResponse' + security: + - JWT-Auth: [] + requestBody: + $ref: '#/components/requestBodies/AddGamenight' + description: 'Add a gamenight by providing a name and a date, only available when providing an JWT token.' + get: + summary: '' + operationId: get-gamenight + responses: + '200': + $ref: '#/components/responses/GamenightResponse' + '401': + $ref: '#/components/responses/FailureResponse' + '422': + $ref: '#/components/responses/FailureResponse' + requestBody: + $ref: '#/components/requestBodies/GetGamenight' + security: + - JWT-Auth: [] +components: + schemas: + Gamenight: + title: Gamenight + x-stoplight: + id: 0nmru75ph5wh3 + type: object + properties: + id: + type: string + x-stoplight: + id: 3bd6bux9juutk + name: + type: string + x-stoplight: + id: hp3ulebe5l5k2 + datetime: + type: string + x-stoplight: + id: qrae8k13mit85 + owner_id: + type: string + x-stoplight: + id: q8g2pnzqx4byh + required: + - id + - name + - datetime + - owner_id + requestBodies: + Login: + content: + application/json: + schema: + type: object + properties: + username: + type: string + x-stoplight: + id: hvemn3s02e6h2 + password: + type: string + x-stoplight: + id: yx02fdolrp9rj + required: + - username + - password + Register: + content: + application/json: + schema: + type: object + properties: + username: + type: string + x-stoplight: + id: el8e6kdc6xgmw + email: + type: string + x-stoplight: + id: ipexmxasalhym + password: + type: string + x-stoplight: + id: 5fztmf9jhd7dt + password_repeat: + type: string + x-stoplight: + id: xw1skr0mjujuq + registration_token: + type: string + x-stoplight: + id: kvq6rzg1fcn7s + required: + - username + - email + - password + - password_repeat + - registration_token + AddGamenight: + content: + application/json: + schema: + type: object + properties: + name: + type: string + x-stoplight: + id: ak4fkyj5haj8k + datetime: + type: string + x-stoplight: + id: 3dylqwf2yuyku + GetGamenight: + content: + application/json: + schema: + type: object + properties: + id: + type: string + x-stoplight: + id: qykfde4zkqfgx + responses: + TokenResponse: + description: Example response + content: + application/json: + schema: + type: object + properties: + jwt_token: + type: string + x-stoplight: + id: qyp2q6rqsk1ql + required: + - jwt_token + FailureResponse: + description: Example response + content: + application/json: + schema: + type: object + properties: + message: + type: string + x-stoplight: + id: g1la0pt0erd0b + application/xml: + schema: + type: object + properties: + message: + type: string + x-stoplight: + id: ir85ew0w88sv7 + required: + - message + GamenightsResponse: + description: Example response + content: + application/json: + schema: + type: object + properties: + gamenights: + x-stoplight: + id: t1i2zjid122y2 + type: array + items: + $ref: '#/components/schemas/Gamenight' + GamenightResponse: + description: Example response + content: + application/json: + schema: + $ref: '#/components/schemas/Gamenight' + securitySchemes: + JWT-Auth: + type: http + scheme: bearer + bearerFormat: JWT + description: '' diff --git a/FrontendPlatformUno/FrontendPlatformUno/Styles/GamenightStyles.xaml b/FrontendPlatformUno/FrontendPlatformUno/Styles/GamenightStyles.xaml new file mode 100644 index 0000000..b1cf484 --- /dev/null +++ b/FrontendPlatformUno/FrontendPlatformUno/Styles/GamenightStyles.xaml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/FrontendPlatformUno/FrontendPlatformUno/ViewModels/LoginViewModel.cs b/FrontendPlatformUno/FrontendPlatformUno/ViewModels/LoginViewModel.cs index cf1c9fc..b152720 100644 --- a/FrontendPlatformUno/FrontendPlatformUno/ViewModels/LoginViewModel.cs +++ b/FrontendPlatformUno/FrontendPlatformUno/ViewModels/LoginViewModel.cs @@ -1,5 +1,8 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; +using FrontendPlatformUno.Services.Api; +using FrontendPlatformUno.Services.Client; +using FrontendPlatformUno.Services.Model; using FrontendPlatformUno.Views; using System; using System.Collections.Generic; @@ -16,16 +19,41 @@ namespace FrontendPlatformUno.ViewModels public string? Title { get; } public ICommand GoToLogin { get; } - public LoginViewModel(INavigator navigator, IStringLocalizer stringLocalizer) + public string? Username { get; set; } + + public string? Password { get; set; } + public ICommand LoginCommand { get; internal set; } + + private IDefaultApi GamenightApi { get; } + + public LoginViewModel(INavigator navigator, IStringLocalizer stringLocalizer, IDefaultApi gamenightApi) { Navigator = navigator; + GamenightApi = gamenightApi; Title = $"{stringLocalizer["ApplicationName"]} - Login"; GoToLogin = new AsyncRelayCommand(GoToLoginView); + LoginCommand = new AsyncRelayCommand(Login); } private async Task GoToLoginView() { await Navigator.NavigateViewModelAsync(this); } + + private async Task Login() + { + var req = new GetTokenRequest(Username, Password); + GetToken200Response tokenResponse; + try + { + tokenResponse = await GamenightApi.GetTokenAsync(req); + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + return; + } + ((Configuration)GamenightApi.Configuration).AccessToken = tokenResponse.JwtToken; + } } } diff --git a/FrontendPlatformUno/FrontendPlatformUno/Views/GamenightsPage.xaml b/FrontendPlatformUno/FrontendPlatformUno/Views/GamenightsPage.xaml index ad85a47..76f42d1 100644 --- a/FrontendPlatformUno/FrontendPlatformUno/Views/GamenightsPage.xaml +++ b/FrontendPlatformUno/FrontendPlatformUno/Views/GamenightsPage.xaml @@ -17,18 +17,7 @@ - - - - - - - - - - - - + diff --git a/FrontendPlatformUno/FrontendPlatformUno/Views/LoginPage.xaml b/FrontendPlatformUno/FrontendPlatformUno/Views/LoginPage.xaml index 7130b7d..1ee6a83 100644 --- a/FrontendPlatformUno/FrontendPlatformUno/Views/LoginPage.xaml +++ b/FrontendPlatformUno/FrontendPlatformUno/Views/LoginPage.xaml @@ -17,18 +17,21 @@ - - - - - - - - - - - - + + + + + + + + + + + + +