From 1c07bef3cf8a5b7d55470633e9549d222dc8150e Mon Sep 17 00:00:00 2001 From: Robert Date: Fri, 14 Jul 2023 09:21:09 +0200 Subject: [PATCH] Use real backend --- .../CurrentUser/CurrentUserViewModel.cs | 3 +- .../.graphqlrc.json | 2 +- .../Artemis.WebClient.Workshop.csproj | 1 + .../DryIoc/ContainerExtensions.cs | 4 +- .../Services/IAuthenticationService.cs | 38 ++++++++----------- .../WorkshopConstants.cs | 7 ++++ .../graphql.config.yml | 2 +- src/Artemis.WebClient.Workshop/schema.graphql | 16 +++++++- 8 files changed, 43 insertions(+), 30 deletions(-) create mode 100644 src/Artemis.WebClient.Workshop/WorkshopConstants.cs diff --git a/src/Artemis.UI/Screens/Workshop/CurrentUser/CurrentUserViewModel.cs b/src/Artemis.UI/Screens/Workshop/CurrentUser/CurrentUserViewModel.cs index 3d0121043..7df2e3150 100644 --- a/src/Artemis.UI/Screens/Workshop/CurrentUser/CurrentUserViewModel.cs +++ b/src/Artemis.UI/Screens/Workshop/CurrentUser/CurrentUserViewModel.cs @@ -5,6 +5,7 @@ using System.Reactive.Disposables; using System.Threading; using System.Threading.Tasks; using Artemis.UI.Shared; +using Artemis.WebClient.Workshop; using Artemis.WebClient.Workshop.Services; using Avalonia.Media.Imaging; using Flurl.Http; @@ -94,7 +95,7 @@ public class CurrentUserViewModel : ActivatableViewModelBase { try { - Avatar = new Bitmap(await $"{IAuthenticationService.AUTHORITY}/user/avatar/{userId}".GetStreamAsync()); + Avatar = new Bitmap(await $"{WorkshopConstants.AUTHORITY_URL}/user/avatar/{userId}".GetStreamAsync()); } catch (Exception) { diff --git a/src/Artemis.WebClient.Workshop/.graphqlrc.json b/src/Artemis.WebClient.Workshop/.graphqlrc.json index 24fb39de3..3cd18817b 100644 --- a/src/Artemis.WebClient.Workshop/.graphqlrc.json +++ b/src/Artemis.WebClient.Workshop/.graphqlrc.json @@ -5,7 +5,7 @@ "strawberryShake": { "name": "WorkshopClient", "namespace": "Artemis.WebClient.Workshop", - "url": "https://localhost:7281/graphql/", + "url": "https://workshop.artemis-rgb.com/graphql/", "emitGeneratedCode": false, "records": { "inputs": false, diff --git a/src/Artemis.WebClient.Workshop/Artemis.WebClient.Workshop.csproj b/src/Artemis.WebClient.Workshop/Artemis.WebClient.Workshop.csproj index 09befbe14..653d780a8 100644 --- a/src/Artemis.WebClient.Workshop/Artemis.WebClient.Workshop.csproj +++ b/src/Artemis.WebClient.Workshop/Artemis.WebClient.Workshop.csproj @@ -13,6 +13,7 @@ + diff --git a/src/Artemis.WebClient.Workshop/DryIoc/ContainerExtensions.cs b/src/Artemis.WebClient.Workshop/DryIoc/ContainerExtensions.cs index 1988fa300..bdcdbede6 100644 --- a/src/Artemis.WebClient.Workshop/DryIoc/ContainerExtensions.cs +++ b/src/Artemis.WebClient.Workshop/DryIoc/ContainerExtensions.cs @@ -22,12 +22,12 @@ public static class ContainerExtensions serviceCollection .AddHttpClient() .AddWorkshopClient() - .ConfigureHttpClient(client => client.BaseAddress = new Uri("https://localhost:7281/graphql")); + .ConfigureHttpClient(client => client.BaseAddress = new Uri(WorkshopConstants.WORKSHOP_URL + "/graphql")); serviceCollection.AddSingleton(r => { IHttpClientFactory factory = r.GetRequiredService(); - return new DiscoveryCache(IAuthenticationService.AUTHORITY, () => factory.CreateClient()); + return new DiscoveryCache(WorkshopConstants.AUTHORITY_URL, () => factory.CreateClient()); }); container.WithDependencyInjectionAdapter(serviceCollection); diff --git a/src/Artemis.WebClient.Workshop/Services/IAuthenticationService.cs b/src/Artemis.WebClient.Workshop/Services/IAuthenticationService.cs index c3c112451..eed47ecff 100644 --- a/src/Artemis.WebClient.Workshop/Services/IAuthenticationService.cs +++ b/src/Artemis.WebClient.Workshop/Services/IAuthenticationService.cs @@ -1,5 +1,6 @@ using System.Collections.ObjectModel; using System.Diagnostics; +using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using Artemis.Core; using Artemis.Core.Services; @@ -11,8 +12,6 @@ namespace Artemis.WebClient.Workshop.Services; public interface IAuthenticationService : IProtectedArtemisService { - public const string AUTHORITY = "https://localhost:5001"; - bool IsLoggedIn { get; } string? UserCode { get; } ReadOnlyObservableCollection Claims { get; } @@ -25,7 +24,7 @@ public interface IAuthenticationService : IProtectedArtemisService internal class AuthenticationService : CorePropertyChanged, IAuthenticationService { - internal const string CLIENT_ID = "artemis.desktop"; + private const string CLIENT_ID = "artemis.desktop"; private readonly IDiscoveryCache _discoveryCache; private readonly IAuthenticationRepository _authenticationRepository; @@ -109,7 +108,8 @@ internal class AuthenticationService : CorePropertyChanged, IAuthenticationServi DeviceAuthorizationResponse response = await client.RequestDeviceAuthorizationAsync(new DeviceAuthorizationRequest { Address = disco.DeviceAuthorizationEndpoint, - ClientId = CLIENT_ID + ClientId = CLIENT_ID, + Scope = "openid profile email offline_access api" }); if (response.IsError) throw new ArtemisWebClientException("Failed to request device authorization: " + response.Error); @@ -168,33 +168,25 @@ internal class AuthenticationService : CorePropertyChanged, IAuthenticationServi throw new ArtemisWebClientException("Failed to request device token: " + response.Error); } - await SetCurrentUser(client, response); + SetCurrentUser(response); return true; } - private async Task SetCurrentUser(HttpClient client, TokenResponse response) + private void SetCurrentUser(TokenResponse response) { _token = new AuthenticationToken(response); _authenticationRepository.SetRefreshToken(_token.RefreshToken); - - await GetUserInfo(client, _token.AccessToken); - IsLoggedIn = true; - } - - private async Task GetUserInfo(HttpClient client, string accessToken) - { - DiscoveryDocumentResponse disco = await GetDiscovery(); - UserInfoResponse response = await client.GetUserInfoAsync(new UserInfoRequest() - { - Address = disco.UserInfoEndpoint, - Token = accessToken - }); - if (response.IsError) - throw new ArtemisWebClientException("Failed to retrieve user info: " + response.Error); + + JwtSecurityTokenHandler handler = new(); + JwtSecurityToken? token = handler.ReadJwtToken(response.IdentityToken); + if (token == null) + throw new ArtemisWebClientException("Failed to read JWT token"); _claims.Clear(); - foreach (Claim responseClaim in response.Claims) + foreach (Claim responseClaim in token.Claims) _claims.Add(responseClaim); + + IsLoggedIn = true; } private async Task UseRefreshToken(string refreshToken) @@ -216,7 +208,7 @@ internal class AuthenticationService : CorePropertyChanged, IAuthenticationServi throw new ArtemisWebClientException("Failed to request refresh token: " + response.Error); } - await SetCurrentUser(client, response); + SetCurrentUser(response); return false; } } \ No newline at end of file diff --git a/src/Artemis.WebClient.Workshop/WorkshopConstants.cs b/src/Artemis.WebClient.Workshop/WorkshopConstants.cs new file mode 100644 index 000000000..b514ae862 --- /dev/null +++ b/src/Artemis.WebClient.Workshop/WorkshopConstants.cs @@ -0,0 +1,7 @@ +namespace Artemis.WebClient.Workshop; + +public static class WorkshopConstants +{ + public const string AUTHORITY_URL = "https://identity.artemis-rgb.com"; + public const string WORKSHOP_URL = "https://workshop.artemis-rgb.com"; +} \ No newline at end of file diff --git a/src/Artemis.WebClient.Workshop/graphql.config.yml b/src/Artemis.WebClient.Workshop/graphql.config.yml index a8ba99703..9662a514f 100644 --- a/src/Artemis.WebClient.Workshop/graphql.config.yml +++ b/src/Artemis.WebClient.Workshop/graphql.config.yml @@ -2,7 +2,7 @@ schema: schema.graphql extensions: endpoints: Default GraphQL Endpoint: - url: https://localhost:7281/graphql + url: https://workshop.artemis-rgb.com/graphql headers: user-agent: JS GraphQL introspect: true diff --git a/src/Artemis.WebClient.Workshop/schema.graphql b/src/Artemis.WebClient.Workshop/schema.graphql index 93e31079c..c41fd39ba 100644 --- a/src/Artemis.WebClient.Workshop/schema.graphql +++ b/src/Artemis.WebClient.Workshop/schema.graphql @@ -32,7 +32,8 @@ type EntriesEdge { } type Entry { - author: UUID! + author: String! + authorId: UUID! categories: [Category!]! createdAt: DateTime! description: String! @@ -83,6 +84,7 @@ type Query { where: EntryFilterInput ): EntriesConnection entry(id: UUID!): Entry + searchEntries(input: String!, order: [EntrySortInput!], type: EntryType, where: EntryFilterInput): [Entry!]! } type Release { @@ -90,6 +92,7 @@ type Release { downloadSize: Long! downloads: Long! entry: Entry! + entryId: UUID! id: UUID! md5Hash: String version: String! @@ -100,6 +103,12 @@ type Tag { name: String! } +enum ApplyPolicy { + AFTER_RESOLVER + BEFORE_RESOLVER + VALIDATION +} + enum EntryType { LAYOUT PLUGIN @@ -150,7 +159,8 @@ input DateTimeOperationFilterInput { input EntryFilterInput { and: [EntryFilterInput!] - author: UuidOperationFilterInput + author: StringOperationFilterInput + authorId: UuidOperationFilterInput categories: ListFilterInputTypeOfCategoryFilterInput createdAt: DateTimeOperationFilterInput description: StringOperationFilterInput @@ -175,6 +185,7 @@ input EntryInput { input EntrySortInput { author: SortEnumType + authorId: SortEnumType createdAt: SortEnumType description: SortEnumType downloads: SortEnumType @@ -268,6 +279,7 @@ input ReleaseFilterInput { downloadSize: LongOperationFilterInput downloads: LongOperationFilterInput entry: EntryFilterInput + entryId: UuidOperationFilterInput id: UuidOperationFilterInput md5Hash: StringOperationFilterInput or: [ReleaseFilterInput!]