From 6df29271cbfa876f0339b8a07648747c5da9e3c3 Mon Sep 17 00:00:00 2001 From: Thach Nguyen Date: Tue, 3 Oct 2023 14:05:24 +0700 Subject: [PATCH 1/6] WIP --- .../MusicFestival.Backend.csproj | 10 +-- .../musicfestival-backend-dotnet/Startup.cs | 62 +++---------------- .../musicfestival-frontend-react/src/App.tsx | 16 +++-- .../src/components/SearchButton.tsx | 7 ++- .../src/helpers/queryCacheHelper.ts | 4 +- .../src/helpers/urlHelper.ts | 19 +++--- .../src/models/Payload.ts | 4 ++ .../src/pages/SearchPage.tsx | 2 +- 8 files changed, 39 insertions(+), 85 deletions(-) create mode 100644 samples/musicfestival-frontend-react/src/models/Payload.ts diff --git a/samples/musicfestival-backend-dotnet/MusicFestival.Backend.csproj b/samples/musicfestival-backend-dotnet/MusicFestival.Backend.csproj index e17541c..d98f7ca 100644 --- a/samples/musicfestival-backend-dotnet/MusicFestival.Backend.csproj +++ b/samples/musicfestival-backend-dotnet/MusicFestival.Backend.csproj @@ -8,12 +8,12 @@ - - - - + + + + - + diff --git a/samples/musicfestival-backend-dotnet/Startup.cs b/samples/musicfestival-backend-dotnet/Startup.cs index 99ec729..bc5d557 100644 --- a/samples/musicfestival-backend-dotnet/Startup.cs +++ b/samples/musicfestival-backend-dotnet/Startup.cs @@ -62,64 +62,13 @@ public void ConfigureServices(IServiceCollection services) .Add("narrow", "Narrow", "u-md-size1of3", string.Empty, "epi-icon__layout--one-third"); }); - // services.AddOpenIddict(); - - Console.WriteLine("Adding OpenID Connect"); - services.AddOpenIDConnect( - useDevelopmentCertificate: true, - signingCertificate: null, - encryptionCertificate: null, - createSchema: true, - options => - { - var baseUri = new Uri(_frontendUri); - options.RequireHttps = !_webHostingEnvironment.IsDevelopment(); - options.DisableTokenPruning = true; - options.DisableSlidingRefreshTokenExpiration = true; - - options.Applications.Add(new OpenIDConnectApplication - { - ClientId = "frontend", - Scopes = { "openid", "offline_access", "profile", "email", "roles", ContentDeliveryApiOptionsDefaults.Scope }, - PostLogoutRedirectUris = { baseUri }, - RedirectUris = - { - new Uri(baseUri, "/"), - new Uri(baseUri, "/login-callback"), - new Uri(baseUri, "/login-renewal"), - }, - }); - - options.Applications.Add(new OpenIDConnectApplication - { - ClientId = "cli", - ClientSecret = "cli", - Scopes = { ContentDefinitionsApiOptionsDefaults.Scope }, - }); - }); - - services.AddOpenIDConnectUI(); - - // No encrypt the token so it's easier to debug, not recommend for production. - services.AddOpenIddict() - .AddServer(options => options.DisableAccessTokenEncryption()); - - services.AddContentDefinitionsApi(OpenIDConnectOptionsDefaults.AuthenticationScheme); - - services.AddContentDeliveryApi(OpenIDConnectOptionsDefaults.AuthenticationScheme); - - services.AddContentManagementApi(OpenIDConnectOptionsDefaults.AuthenticationScheme, options => + services.AddContentDefinitionsApi(); + services.AddContentDeliveryApi(); + services.AddContentManagementApi(options => { options.DisableScopeValidation = false; options.RequiredRole = "WebAdmins"; }); - // services.AddContentManagementApi(string.Empty); - - services.AddOpenIddict() - .AddServer(options => - { - options.DisableAccessTokenEncryption(); - }); services.ConfigureForContentDeliveryClient(); @@ -133,7 +82,10 @@ public void ConfigureServices(IServiceCollection services) o.IncludeNumericContentIdentifier = true; }); - services.AddContentGraph(_configuration, OpenIDConnectOptionsDefaults.AuthenticationScheme); + services.AddContentGraph(options => + { + options.EnablePreviewTokens = true; + }); services.AddHostedService(); } diff --git a/samples/musicfestival-frontend-react/src/App.tsx b/samples/musicfestival-frontend-react/src/App.tsx index a427f57..09cca91 100644 --- a/samples/musicfestival-frontend-react/src/App.tsx +++ b/samples/musicfestival-frontend-react/src/App.tsx @@ -16,7 +16,7 @@ import { BlockPage } from './pages/BlockPage'; let previousSavedMessage: any = null; const singleKeyUrl = process.env.REACT_APP_CONTENT_GRAPH_GATEWAY_URL as string -const hmacKeyUrl = process.env.REACT_APP_CG_PROXY_URL as string +const hmacKeyUrl = process.env.REACT_APP_CG_CONTENT_URL as string const App = () => { const queryClient = useQueryClient(); @@ -36,21 +36,19 @@ const App = () => { } }); - authService.getAccessToken().then((_token) => { - _token && setToken(_token) - modeEdit && !_token && !data && authService.login() - }) + const urlParams = new URLSearchParams(window.location.search); + const previewToken = urlParams.get('preview_token') ?? ""; - variables = generateGQLQueryVars(token, window.location.pathname) + variables = generateGQLQueryVars(previewToken, window.location.pathname) if (modeEdit) { - if (token) { - headers = { 'Authorization': 'Bearer ' + token }; + if (previewToken) { + headers = { 'Authorization': 'Bearer ' + previewToken }; } url = hmacKeyUrl subcribeContentSavedEvent((message: any) => mutate(message)) } - const { data: queryData } = useStartQuery({ endpoint: url, fetchParams: { headers: headers } }, variables, { staleTime: 2000, enabled: !modeEdit || !!token }); + const { data: queryData } = useStartQuery({ endpoint: url, fetchParams: { headers: headers } }, variables, { staleTime: 2000, enabled: !modeEdit || !!previewToken }); data = queryData if (!data) { diff --git a/samples/musicfestival-frontend-react/src/components/SearchButton.tsx b/samples/musicfestival-frontend-react/src/components/SearchButton.tsx index b94b359..f5af8ca 100644 --- a/samples/musicfestival-frontend-react/src/components/SearchButton.tsx +++ b/samples/musicfestival-frontend-react/src/components/SearchButton.tsx @@ -18,10 +18,13 @@ function SearchButton({filterValue}: any): JSX.Element { const [orderBy] = useState("ASC") let modeEdit = isEditOrPreviewMode() - let variables = generateGQLSearchQueryVars(token, window.location.pathname, searchValue as string | null, orderBy, ranking); + const urlParams = new URLSearchParams(window.location.search); + const previewToken = urlParams.get('preview_token') ?? ""; + + let variables = generateGQLSearchQueryVars(previewToken, window.location.pathname, searchValue as string | null, orderBy, ranking); const autocompleteData = useArtistAutocompleteQuery({endpoint: singleKeyUrl}, variables, { staleTime: 2000, - enabled: !modeEdit || !!token + enabled: !modeEdit || !!previewToken }).data; const onSearch = (event: any) => { diff --git a/samples/musicfestival-frontend-react/src/helpers/queryCacheHelper.ts b/samples/musicfestival-frontend-react/src/helpers/queryCacheHelper.ts index 2914ef2..8249cf7 100644 --- a/samples/musicfestival-frontend-react/src/helpers/queryCacheHelper.ts +++ b/samples/musicfestival-frontend-react/src/helpers/queryCacheHelper.ts @@ -4,7 +4,7 @@ import { ContentSavedMessage } from "../models/ContentSavedMessage"; import { extractParams, isEditOrPreviewMode } from "./urlHelper"; const generateGQLQueryVars = (token: string, pathname: string): any => { - const { relativePath, locales, language, contentId, workId } = extractParams(pathname) + const { relativePath, locales, language, contentId, workId } = extractParams(token, pathname) let variables: any = { relativePath, locales: locales as Locales, language, statusEqual: "Published" }; if (isEditOrPreviewMode() && token) { variables = workId === undefined @@ -16,7 +16,7 @@ const generateGQLQueryVars = (token: string, pathname: string): any => { } const generateGQLSearchQueryVars = (token: string, pathname: string, searchParam: string | null, sortOption: string, ranking: Ranking = Ranking.Relevance): any => { - const { locales } = extractParams(pathname) + const { locales } = extractParams(token, pathname) let variables: any = { locales: locales as Locales, searchParam: searchParam, order: sortOption, ranking: ranking }; if (isEditOrPreviewMode() && token) { variables = { locales: locales as Locales, searchParam, sortOption, ranking }; diff --git a/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts b/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts index e97d6e5..2e0a20a 100644 --- a/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts +++ b/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts @@ -1,4 +1,7 @@ import {Ranking} from "../generated"; +import { Buffer } from "buffer"; +import { Payload } from "../models/Payload"; + const isEditOrPreviewMode = () => { const params = window.location.search.split(/[&?]+/); @@ -14,10 +17,11 @@ const getImageUrl = (path = "") => { return path.startsWith("http") ? path : siteUrl + path } -const extractParams = (urlPath: string) => { +const extractParams = (token: string, urlPath: string) => { + const base64String = token.substring(token.indexOf('.') + 1, token.lastIndexOf('.')); + const payload: Payload = JSON.parse(Buffer.from(base64String, 'base64').toString()); + let relativePath = (urlPath.length > 1 && urlPath != "/search") ? urlPath : '/en' - let contentId - let workId = undefined const epiContentPrefix = "/EPiServer/CMS/Content/"; if (relativePath.startsWith(epiContentPrefix)) { @@ -29,13 +33,6 @@ const extractParams = (urlPath: string) => { } if (relativePath.includes(",")) { - const [, , idString] = relativePath.split(",") - if (idString.includes("_")) { - [contentId, workId] = idString.split("_").map(x => parseInt(x)); - - } else { - contentId = parseInt(idString) - } relativePath = relativePath.substring(0, relativePath.indexOf(',')); } @@ -46,7 +43,7 @@ const extractParams = (urlPath: string) => { const urlSegments = relativePath.split('/') const language = urlSegments.length ? urlSegments.find(s => s.length === 2) : "en" - return {relativePath, locales: language, language, contentId, workId} + return { relativePath, locales: language, language, contentId: parseInt(payload.c_id.toString()) , workId: parseInt(payload.c_ver.toString()) } } const getRankingFromSearchParams = (searchParams: URLSearchParams): Ranking => { diff --git a/samples/musicfestival-frontend-react/src/models/Payload.ts b/samples/musicfestival-frontend-react/src/models/Payload.ts new file mode 100644 index 0000000..eaa6ff7 --- /dev/null +++ b/samples/musicfestival-frontend-react/src/models/Payload.ts @@ -0,0 +1,4 @@ +export interface Payload { + c_id: number; + c_ver: number; +} \ No newline at end of file diff --git a/samples/musicfestival-frontend-react/src/pages/SearchPage.tsx b/samples/musicfestival-frontend-react/src/pages/SearchPage.tsx index 04644f6..933ba80 100644 --- a/samples/musicfestival-frontend-react/src/pages/SearchPage.tsx +++ b/samples/musicfestival-frontend-react/src/pages/SearchPage.tsx @@ -21,7 +21,7 @@ import { subcribeContentSavedEvent } from "../helpers/contentSavedEvent"; let previousSavedMessage: any = null; const singleKeyUrl = process.env.REACT_APP_CONTENT_GRAPH_GATEWAY_URL as string -const hmacKeyUrl = process.env.REACT_APP_CG_PROXY_URL as string +const hmacKeyUrl = process.env.REACT_APP_CG_CONTENT_URL as string function SearchPage() { console.log("Start") From fbd87d77266eecc1251340be78807bd0f3131f92 Mon Sep 17 00:00:00 2001 From: Thach Nguyen Date: Wed, 4 Oct 2023 14:14:04 +0700 Subject: [PATCH 2/6] Fix rendering in view mode --- samples/musicfestival-frontend-react/.env | 2 +- samples/musicfestival-frontend-react/src/App.tsx | 2 +- .../src/helpers/urlHelper.ts | 16 +++++++++++++--- .../src/models/Payload.ts | 4 ++-- .../src/pages/SearchPage.tsx | 2 +- 5 files changed, 18 insertions(+), 8 deletions(-) diff --git a/samples/musicfestival-frontend-react/.env b/samples/musicfestival-frontend-react/.env index 0ea85b1..99fcc7c 100644 --- a/samples/musicfestival-frontend-react/.env +++ b/samples/musicfestival-frontend-react/.env @@ -1,4 +1,4 @@ -REACT_APP_CG_PROXY_URL=http://localhost:8082/EpiServer/ContentGraph/CGProxy/Query +REACT_APP_CG_PREVIEW_URL=https://cg.optimizely.com/content/v2 REACT_APP_CONTENT_GRAPH_GATEWAY_URL=https://cg.optimizely.com/content/v2?auth=INPUT_SINGLE_KEY_HERE REACT_APP_LOGIN_AUTHORITY=http://localhost:8082 diff --git a/samples/musicfestival-frontend-react/src/App.tsx b/samples/musicfestival-frontend-react/src/App.tsx index 09cca91..436bbc5 100644 --- a/samples/musicfestival-frontend-react/src/App.tsx +++ b/samples/musicfestival-frontend-react/src/App.tsx @@ -16,7 +16,7 @@ import { BlockPage } from './pages/BlockPage'; let previousSavedMessage: any = null; const singleKeyUrl = process.env.REACT_APP_CONTENT_GRAPH_GATEWAY_URL as string -const hmacKeyUrl = process.env.REACT_APP_CG_CONTENT_URL as string +const hmacKeyUrl = process.env.REACT_APP_CG_PREVIEW_URL as string const App = () => { const queryClient = useQueryClient(); diff --git a/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts b/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts index 2e0a20a..189bbfe 100644 --- a/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts +++ b/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts @@ -18,9 +18,16 @@ const getImageUrl = (path = "") => { } const extractParams = (token: string, urlPath: string) => { - const base64String = token.substring(token.indexOf('.') + 1, token.lastIndexOf('.')); - const payload: Payload = JSON.parse(Buffer.from(base64String, 'base64').toString()); + var payload: Payload = { + c_id: undefined, + c_ver: undefined + }; + if (token) { + const base64String = token.substring(token.indexOf('.') + 1, token.lastIndexOf('.')); + payload = JSON.parse(Buffer.from(base64String, 'base64').toString()); + } + let relativePath = (urlPath.length > 1 && urlPath != "/search") ? urlPath : '/en' const epiContentPrefix = "/EPiServer/CMS/Content/"; @@ -43,7 +50,10 @@ const extractParams = (token: string, urlPath: string) => { const urlSegments = relativePath.split('/') const language = urlSegments.length ? urlSegments.find(s => s.length === 2) : "en" - return { relativePath, locales: language, language, contentId: parseInt(payload.c_id.toString()) , workId: parseInt(payload.c_ver.toString()) } + const contentId = payload.c_id && parseInt(payload.c_id!.toString()); + const workId = payload.c_ver && parseInt(payload.c_ver!.toString()); + + return { relativePath, locales: language, language, contentId: contentId, workId: workId } } const getRankingFromSearchParams = (searchParams: URLSearchParams): Ranking => { diff --git a/samples/musicfestival-frontend-react/src/models/Payload.ts b/samples/musicfestival-frontend-react/src/models/Payload.ts index eaa6ff7..c7f2650 100644 --- a/samples/musicfestival-frontend-react/src/models/Payload.ts +++ b/samples/musicfestival-frontend-react/src/models/Payload.ts @@ -1,4 +1,4 @@ export interface Payload { - c_id: number; - c_ver: number; + c_id?: number; + c_ver?: number; } \ No newline at end of file diff --git a/samples/musicfestival-frontend-react/src/pages/SearchPage.tsx b/samples/musicfestival-frontend-react/src/pages/SearchPage.tsx index 933ba80..49af396 100644 --- a/samples/musicfestival-frontend-react/src/pages/SearchPage.tsx +++ b/samples/musicfestival-frontend-react/src/pages/SearchPage.tsx @@ -21,7 +21,7 @@ import { subcribeContentSavedEvent } from "../helpers/contentSavedEvent"; let previousSavedMessage: any = null; const singleKeyUrl = process.env.REACT_APP_CONTENT_GRAPH_GATEWAY_URL as string -const hmacKeyUrl = process.env.REACT_APP_CG_CONTENT_URL as string +const hmacKeyUrl = process.env.REACT_APP_CG_PREVIEW_URL as string function SearchPage() { console.log("Start") From bf7c7043cce85e1bc5921ee6264ee61f8cbe9f0a Mon Sep 17 00:00:00 2001 From: Thach Nguyen Date: Thu, 5 Oct 2023 13:53:21 +0700 Subject: [PATCH 3/6] Refactor code --- samples/musicfestival-backend-dotnet/Startup.cs | 3 --- samples/musicfestival-frontend-react/src/App.tsx | 5 ++--- .../src/components/SearchButton.tsx | 5 ++--- .../src/helpers/urlHelper.ts | 10 +++++++++- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/samples/musicfestival-backend-dotnet/Startup.cs b/samples/musicfestival-backend-dotnet/Startup.cs index bc5d557..d8427a4 100644 --- a/samples/musicfestival-backend-dotnet/Startup.cs +++ b/samples/musicfestival-backend-dotnet/Startup.cs @@ -1,13 +1,10 @@ using System.Runtime.InteropServices; using EPiServer.Cms.Shell; using EPiServer.Cms.UI.AspNetIdentity; -using EPiServer.ContentApi.Cms; using EPiServer.ContentApi.Core.DependencyInjection; -using EPiServer.ContentDefinitionsApi; using EPiServer.Core; using EPiServer.Data; using EPiServer.DependencyInjection; -using EPiServer.OpenIDConnect; using EPiServer.Web; using EPiServer.Web.Routing; diff --git a/samples/musicfestival-frontend-react/src/App.tsx b/samples/musicfestival-frontend-react/src/App.tsx index 436bbc5..10f5600 100644 --- a/samples/musicfestival-frontend-react/src/App.tsx +++ b/samples/musicfestival-frontend-react/src/App.tsx @@ -5,7 +5,7 @@ import ArtistContainerPage from './pages/ArtistContainerPage'; import ArtistDetailsPage from './pages/ArtistDetailsPage'; import authService from './authService'; import { useState } from 'react'; -import { isEditOrPreviewMode } from './helpers/urlHelper' +import { isEditOrPreviewMode, getPreviewTokenFromUrl } from './helpers/urlHelper' import './App.css'; import Footer from './components/Footer'; import { useMutation, useQueryClient } from '@tanstack/react-query'; @@ -36,8 +36,7 @@ const App = () => { } }); - const urlParams = new URLSearchParams(window.location.search); - const previewToken = urlParams.get('preview_token') ?? ""; + const previewToken = getPreviewTokenFromUrl(window.location.search); variables = generateGQLQueryVars(previewToken, window.location.pathname) if (modeEdit) { diff --git a/samples/musicfestival-frontend-react/src/components/SearchButton.tsx b/samples/musicfestival-frontend-react/src/components/SearchButton.tsx index f5af8ca..a9c3b45 100644 --- a/samples/musicfestival-frontend-react/src/components/SearchButton.tsx +++ b/samples/musicfestival-frontend-react/src/components/SearchButton.tsx @@ -2,7 +2,7 @@ import {useEffect, useRef, useState} from "react"; import {useSearchParams} from "react-router-dom"; import {ArtistAutocompleteQuery, Ranking, useArtistAutocompleteQuery} from "../generated"; import {generateGQLSearchQueryVars} from "../helpers/queryCacheHelper"; -import {getRankingFromSearchParams, isEditOrPreviewMode} from "../helpers/urlHelper"; +import {getRankingFromSearchParams, isEditOrPreviewMode, getPreviewTokenFromUrl } from "../helpers/urlHelper"; type CustomString = string | number | readonly string[] | undefined @@ -18,8 +18,7 @@ function SearchButton({filterValue}: any): JSX.Element { const [orderBy] = useState("ASC") let modeEdit = isEditOrPreviewMode() - const urlParams = new URLSearchParams(window.location.search); - const previewToken = urlParams.get('preview_token') ?? ""; + const previewToken = getPreviewTokenFromUrl(window.location.search); let variables = generateGQLSearchQueryVars(previewToken, window.location.pathname, searchValue as string | null, orderBy, ranking); const autocompleteData = useArtistAutocompleteQuery({endpoint: singleKeyUrl}, variables, { diff --git a/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts b/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts index 189bbfe..525ccf3 100644 --- a/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts +++ b/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts @@ -66,4 +66,12 @@ const getRankingFromSearchParams = (searchParams: URLSearchParams): Ranking => { return Ranking.Relevance; } -export {isEditOrPreviewMode, extractParams, getImageUrl, getRankingFromSearchParams} \ No newline at end of file +const getPreviewTokenFromUrl = (queryString: string) => { + const urlParams = new URLSearchParams(queryString); + const previewToken = urlParams.get('preview_token') ?? ""; + + return previewToken; +} + + +export {isEditOrPreviewMode, extractParams, getImageUrl, getRankingFromSearchParams, getPreviewTokenFromUrl} \ No newline at end of file From 136331494f83a27c04b1183c098fcfe9ae1c76a0 Mon Sep 17 00:00:00 2001 From: Thach Nguyen Date: Fri, 6 Oct 2023 09:41:24 +0700 Subject: [PATCH 4/6] Restore OIDC CG-4678 --- .../musicfestival-backend-dotnet/Startup.cs | 66 +++++++++++++++++-- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/samples/musicfestival-backend-dotnet/Startup.cs b/samples/musicfestival-backend-dotnet/Startup.cs index d8427a4..e332e55 100644 --- a/samples/musicfestival-backend-dotnet/Startup.cs +++ b/samples/musicfestival-backend-dotnet/Startup.cs @@ -1,10 +1,13 @@ using System.Runtime.InteropServices; using EPiServer.Cms.Shell; using EPiServer.Cms.UI.AspNetIdentity; +using EPiServer.ContentApi.Cms; using EPiServer.ContentApi.Core.DependencyInjection; +using EPiServer.ContentDefinitionsApi; using EPiServer.Core; using EPiServer.Data; using EPiServer.DependencyInjection; +using EPiServer.OpenIDConnect; using EPiServer.Web; using EPiServer.Web.Routing; @@ -36,7 +39,7 @@ public void ConfigureServices(IServiceCollection services) User=sa;Password=Admin123!; Trust Server Certificate=True;Connect Timeout=30"; var connectionstring = _configuration.GetConnectionString("EPiServerDB") - ?? (isMacOs? macOsConnString: localDBConnString); + ?? (isMacOs ? macOsConnString : localDBConnString); services.Configure(o => { o.SetConnectionString(connectionstring); @@ -59,13 +62,64 @@ public void ConfigureServices(IServiceCollection services) .Add("narrow", "Narrow", "u-md-size1of3", string.Empty, "epi-icon__layout--one-third"); }); - services.AddContentDefinitionsApi(); - services.AddContentDeliveryApi(); - services.AddContentManagementApi(options => + // services.AddOpenIddict(); + + Console.WriteLine("Adding OpenID Connect"); + services.AddOpenIDConnect( + useDevelopmentCertificate: true, + signingCertificate: null, + encryptionCertificate: null, + createSchema: true, + options => + { + var baseUri = new Uri(_frontendUri); + options.RequireHttps = !_webHostingEnvironment.IsDevelopment(); + options.DisableTokenPruning = true; + options.DisableSlidingRefreshTokenExpiration = true; + + options.Applications.Add(new OpenIDConnectApplication + { + ClientId = "frontend", + Scopes = { "openid", "offline_access", "profile", "email", "roles", ContentDeliveryApiOptionsDefaults.Scope }, + PostLogoutRedirectUris = { baseUri }, + RedirectUris = + { + new Uri(baseUri, "/"), + new Uri(baseUri, "/login-callback"), + new Uri(baseUri, "/login-renewal"), + }, + }); + + options.Applications.Add(new OpenIDConnectApplication + { + ClientId = "cli", + ClientSecret = "cli", + Scopes = { ContentDefinitionsApiOptionsDefaults.Scope }, + }); + }); + + services.AddOpenIDConnectUI(); + + // No encrypt the token so it's easier to debug, not recommend for production. + services.AddOpenIddict() + .AddServer(options => options.DisableAccessTokenEncryption()); + + services.AddContentDefinitionsApi(OpenIDConnectOptionsDefaults.AuthenticationScheme); + + services.AddContentDeliveryApi(OpenIDConnectOptionsDefaults.AuthenticationScheme); + + services.AddContentManagementApi(OpenIDConnectOptionsDefaults.AuthenticationScheme, options => { options.DisableScopeValidation = false; options.RequiredRole = "WebAdmins"; }); + // services.AddContentManagementApi(string.Empty); + + services.AddOpenIddict() + .AddServer(options => + { + options.DisableAccessTokenEncryption(); + }); services.ConfigureForContentDeliveryClient(); @@ -79,7 +133,7 @@ public void ConfigureServices(IServiceCollection services) o.IncludeNumericContentIdentifier = true; }); - services.AddContentGraph(options => + services.AddContentGraph(OpenIDConnectOptionsDefaults.AuthenticationScheme, options => { options.EnablePreviewTokens = true; }); @@ -96,7 +150,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) app.UseStaticFiles(); app.UseRouting(); app.UseCors(b => b - .WithOrigins(new[] { $"{_frontendUri}"}) + .WithOrigins(new[] { $"{_frontendUri}" }) .WithExposedContentDeliveryApiHeaders() .WithExposedContentDefinitionApiHeaders() .WithHeaders("Authorization") From 0b69bdef3239889e5b71d34c148b94711f32efc4 Mon Sep 17 00:00:00 2001 From: Thach Nguyen Date: Mon, 9 Oct 2023 14:19:38 +0700 Subject: [PATCH 5/6] update to use public package --- .../MusicFestival.Backend.csproj | 2 +- .../src/generated.ts | 275 +++++++++++++++++- 2 files changed, 271 insertions(+), 6 deletions(-) diff --git a/samples/musicfestival-backend-dotnet/MusicFestival.Backend.csproj b/samples/musicfestival-backend-dotnet/MusicFestival.Backend.csproj index d98f7ca..887b07c 100644 --- a/samples/musicfestival-backend-dotnet/MusicFestival.Backend.csproj +++ b/samples/musicfestival-backend-dotnet/MusicFestival.Backend.csproj @@ -14,6 +14,6 @@ - + diff --git a/samples/musicfestival-frontend-react/src/generated.ts b/samples/musicfestival-frontend-react/src/generated.ts index 279e77d..814841f 100644 --- a/samples/musicfestival-frontend-react/src/generated.ts +++ b/samples/musicfestival-frontend-react/src/generated.ts @@ -52,6 +52,7 @@ export type ArtistContainerPage = IContent & { RelativePath?: Maybe; RouteSegment?: Maybe; Saved?: Maybe; + SiteId?: Maybe; StartPublish?: Maybe; Status?: Maybe; StopPublish?: Maybe; @@ -59,10 +60,16 @@ export type ArtistContainerPage = IContent & { _children?: Maybe; _deleted?: Maybe; _fulltext?: Maybe>>; + _link?: Maybe; _modified?: Maybe; _score?: Maybe; }; + +export type ArtistContainerPage_LinkArgs = { + type?: InputMaybe; +}; + export type ArtistContainerPageAutocomplete = { __typename?: 'ArtistContainerPageAutocomplete'; Ancestors?: Maybe>>; @@ -75,6 +82,7 @@ export type ArtistContainerPageAutocomplete = { ParentLink?: Maybe; RelativePath?: Maybe>>; RouteSegment?: Maybe>>; + SiteId?: Maybe>>; Status?: Maybe>>; Url?: Maybe>>; }; @@ -104,6 +112,12 @@ export type ArtistContainerPageAutocompleteRouteSegmentArgs = { }; +export type ArtistContainerPageAutocompleteSiteIdArgs = { + limit?: Scalars['Int']; + value: Scalars['String']; +}; + + export type ArtistContainerPageAutocompleteStatusArgs = { limit?: Scalars['Int']; value: Scalars['String']; @@ -132,6 +146,7 @@ export type ArtistContainerPageFacet = { RelativePath?: Maybe>>; RouteSegment?: Maybe>>; Saved?: Maybe>>; + SiteId?: Maybe>>; StartPublish?: Maybe>>; Status?: Maybe>>; StopPublish?: Maybe>>; @@ -205,6 +220,14 @@ export type ArtistContainerPageFacetSavedArgs = { }; +export type ArtistContainerPageFacetSiteIdArgs = { + filters?: InputMaybe>; + limit?: Scalars['Int']; + orderBy?: InputMaybe; + orderType?: InputMaybe; +}; + + export type ArtistContainerPageFacetStartPublishArgs = { unit?: InputMaybe; value?: InputMaybe; @@ -248,6 +271,7 @@ export type ArtistContainerPageOrderByInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; StopPublish?: InputMaybe; @@ -285,6 +309,7 @@ export type ArtistContainerPageWhereInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; StopPublish?: InputMaybe; @@ -321,6 +346,7 @@ export type ArtistDetailsPage = IContent & { RelativePath?: Maybe; RouteSegment?: Maybe; Saved?: Maybe; + SiteId?: Maybe; StageName?: Maybe; StartPublish?: Maybe; Status?: Maybe; @@ -329,10 +355,16 @@ export type ArtistDetailsPage = IContent & { _children?: Maybe; _deleted?: Maybe; _fulltext?: Maybe>>; + _link?: Maybe; _modified?: Maybe; _score?: Maybe; }; + +export type ArtistDetailsPage_LinkArgs = { + type?: InputMaybe; +}; + export type ArtistDetailsPageAutocomplete = { __typename?: 'ArtistDetailsPageAutocomplete'; Ancestors?: Maybe>>; @@ -349,6 +381,7 @@ export type ArtistDetailsPageAutocomplete = { ParentLink?: Maybe; RelativePath?: Maybe>>; RouteSegment?: Maybe>>; + SiteId?: Maybe>>; StageName?: Maybe>>; Status?: Maybe>>; Url?: Maybe>>; @@ -403,6 +436,12 @@ export type ArtistDetailsPageAutocompleteRouteSegmentArgs = { }; +export type ArtistDetailsPageAutocompleteSiteIdArgs = { + limit?: Scalars['Int']; + value: Scalars['String']; +}; + + export type ArtistDetailsPageAutocompleteStageNameArgs = { limit?: Scalars['Int']; value: Scalars['String']; @@ -444,6 +483,7 @@ export type ArtistDetailsPageFacet = { RelativePath?: Maybe>>; RouteSegment?: Maybe>>; Saved?: Maybe>>; + SiteId?: Maybe>>; StageName?: Maybe>>; StartPublish?: Maybe>>; Status?: Maybe>>; @@ -570,6 +610,14 @@ export type ArtistDetailsPageFacetSavedArgs = { }; +export type ArtistDetailsPageFacetSiteIdArgs = { + filters?: InputMaybe>; + limit?: Scalars['Int']; + orderBy?: InputMaybe; + orderType?: InputMaybe; +}; + + export type ArtistDetailsPageFacetStageNameArgs = { filters?: InputMaybe>; limit?: Scalars['Int']; @@ -628,6 +676,7 @@ export type ArtistDetailsPageOrderByInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StageName?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; @@ -673,6 +722,7 @@ export type ArtistDetailsPageWhereInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StageName?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; @@ -771,6 +821,7 @@ export type BuyTicketBlock = IContent & { RelativePath?: Maybe; RouteSegment?: Maybe; Saved?: Maybe; + SiteId?: Maybe; StartPublish?: Maybe; Status?: Maybe; StopPublish?: Maybe; @@ -778,10 +829,16 @@ export type BuyTicketBlock = IContent & { _children?: Maybe; _deleted?: Maybe; _fulltext?: Maybe>>; + _link?: Maybe; _modified?: Maybe; _score?: Maybe; }; + +export type BuyTicketBlock_LinkArgs = { + type?: InputMaybe; +}; + export type BuyTicketBlockAutocomplete = { __typename?: 'BuyTicketBlockAutocomplete'; Ancestors?: Maybe>>; @@ -796,6 +853,7 @@ export type BuyTicketBlockAutocomplete = { ParentLink?: Maybe; RelativePath?: Maybe>>; RouteSegment?: Maybe>>; + SiteId?: Maybe>>; Status?: Maybe>>; Url?: Maybe>>; }; @@ -837,6 +895,12 @@ export type BuyTicketBlockAutocompleteRouteSegmentArgs = { }; +export type BuyTicketBlockAutocompleteSiteIdArgs = { + limit?: Scalars['Int']; + value: Scalars['String']; +}; + + export type BuyTicketBlockAutocompleteStatusArgs = { limit?: Scalars['Int']; value: Scalars['String']; @@ -867,6 +931,7 @@ export type BuyTicketBlockFacet = { RelativePath?: Maybe>>; RouteSegment?: Maybe>>; Saved?: Maybe>>; + SiteId?: Maybe>>; StartPublish?: Maybe>>; Status?: Maybe>>; StopPublish?: Maybe>>; @@ -956,6 +1021,14 @@ export type BuyTicketBlockFacetSavedArgs = { }; +export type BuyTicketBlockFacetSiteIdArgs = { + filters?: InputMaybe>; + limit?: Scalars['Int']; + orderBy?: InputMaybe; + orderType?: InputMaybe; +}; + + export type BuyTicketBlockFacetStartPublishArgs = { unit?: InputMaybe; value?: InputMaybe; @@ -1001,6 +1074,7 @@ export type BuyTicketBlockOrderByInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; StopPublish?: InputMaybe; @@ -1040,6 +1114,7 @@ export type BuyTicketBlockWhereInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; StopPublish?: InputMaybe; @@ -1132,6 +1207,7 @@ export type Content = IContent & { RelativePath?: Maybe; RouteSegment?: Maybe; Saved?: Maybe; + SiteId?: Maybe; StartPublish?: Maybe; Status?: Maybe; StopPublish?: Maybe; @@ -1139,14 +1215,21 @@ export type Content = IContent & { _children?: Maybe; _deleted?: Maybe; _fulltext?: Maybe>>; + _link?: Maybe; _modified?: Maybe; _score?: Maybe; }; + +export type Content_LinkArgs = { + type?: InputMaybe; +}; + export type ContentAreaItemModel = { __typename?: 'ContentAreaItemModel'; ContentLink?: Maybe; DisplayOption?: Maybe; + InlineBlock?: Maybe; Tag?: Maybe; }; @@ -1154,6 +1237,7 @@ export type ContentAreaItemModelAutocomplete = { __typename?: 'ContentAreaItemModelAutocomplete'; ContentLink?: Maybe; DisplayOption?: Maybe>>; + InlineBlock?: Maybe; Tag?: Maybe>>; }; @@ -1173,6 +1257,7 @@ export type ContentAreaItemModelFacet = { __typename?: 'ContentAreaItemModelFacet'; ContentLink?: Maybe; DisplayOption?: Maybe>>; + InlineBlock?: Maybe; Tag?: Maybe>>; }; @@ -1195,12 +1280,14 @@ export type ContentAreaItemModelFacetTagArgs = { export type ContentAreaItemModelOrderByInput = { ContentLink?: InputMaybe; DisplayOption?: InputMaybe; + InlineBlock?: InputMaybe; Tag?: InputMaybe; }; export type ContentAreaItemModelWhereInput = { ContentLink?: InputMaybe; DisplayOption?: InputMaybe; + InlineBlock?: InputMaybe; Tag?: InputMaybe; }; @@ -1215,6 +1302,7 @@ export type ContentAutocomplete = { ParentLink?: Maybe; RelativePath?: Maybe>>; RouteSegment?: Maybe>>; + SiteId?: Maybe>>; Status?: Maybe>>; Url?: Maybe>>; }; @@ -1244,6 +1332,12 @@ export type ContentAutocompleteRouteSegmentArgs = { }; +export type ContentAutocompleteSiteIdArgs = { + limit?: Scalars['Int']; + value: Scalars['String']; +}; + + export type ContentAutocompleteStatusArgs = { limit?: Scalars['Int']; value: Scalars['String']; @@ -1275,6 +1369,7 @@ export type ContentBlock = IContent & { RelativePath?: Maybe; RouteSegment?: Maybe; Saved?: Maybe; + SiteId?: Maybe; StartPublish?: Maybe; Status?: Maybe; StopPublish?: Maybe; @@ -1283,10 +1378,16 @@ export type ContentBlock = IContent & { _children?: Maybe; _deleted?: Maybe; _fulltext?: Maybe>>; + _link?: Maybe; _modified?: Maybe; _score?: Maybe; }; + +export type ContentBlock_LinkArgs = { + type?: InputMaybe; +}; + export type ContentBlockAutocomplete = { __typename?: 'ContentBlockAutocomplete'; Ancestors?: Maybe>>; @@ -1302,6 +1403,7 @@ export type ContentBlockAutocomplete = { ParentLink?: Maybe; RelativePath?: Maybe>>; RouteSegment?: Maybe>>; + SiteId?: Maybe>>; Status?: Maybe>>; Title?: Maybe>>; Url?: Maybe>>; @@ -1350,6 +1452,12 @@ export type ContentBlockAutocompleteRouteSegmentArgs = { }; +export type ContentBlockAutocompleteSiteIdArgs = { + limit?: Scalars['Int']; + value: Scalars['String']; +}; + + export type ContentBlockAutocompleteStatusArgs = { limit?: Scalars['Int']; value: Scalars['String']; @@ -1387,6 +1495,7 @@ export type ContentBlockFacet = { RelativePath?: Maybe>>; RouteSegment?: Maybe>>; Saved?: Maybe>>; + SiteId?: Maybe>>; StartPublish?: Maybe>>; Status?: Maybe>>; StopPublish?: Maybe>>; @@ -1485,6 +1594,14 @@ export type ContentBlockFacetSavedArgs = { }; +export type ContentBlockFacetSiteIdArgs = { + filters?: InputMaybe>; + limit?: Scalars['Int']; + orderBy?: InputMaybe; + orderType?: InputMaybe; +}; + + export type ContentBlockFacetStartPublishArgs = { unit?: InputMaybe; value?: InputMaybe; @@ -1539,6 +1656,7 @@ export type ContentBlockOrderByInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; StopPublish?: InputMaybe; @@ -1580,6 +1698,7 @@ export type ContentBlockWhereInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; StopPublish?: InputMaybe; @@ -1608,6 +1727,7 @@ export type ContentFacet = { RelativePath?: Maybe>>; RouteSegment?: Maybe>>; Saved?: Maybe>>; + SiteId?: Maybe>>; StartPublish?: Maybe>>; Status?: Maybe>>; StopPublish?: Maybe>>; @@ -1681,6 +1801,14 @@ export type ContentFacetSavedArgs = { }; +export type ContentFacetSiteIdArgs = { + filters?: InputMaybe>; + limit?: Scalars['Int']; + orderBy?: InputMaybe; + orderType?: InputMaybe; +}; + + export type ContentFacetStartPublishArgs = { unit?: InputMaybe; value?: InputMaybe; @@ -1897,6 +2025,7 @@ export type ContentOrderByInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; StopPublish?: InputMaybe; @@ -1981,6 +2110,7 @@ export type ContentWhereInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; StopPublish?: InputMaybe; @@ -2100,6 +2230,7 @@ export type IContent = { RelativePath?: Maybe; RouteSegment?: Maybe; Saved?: Maybe; + SiteId?: Maybe; StartPublish?: Maybe; Status?: Maybe; StopPublish?: Maybe; @@ -2107,10 +2238,16 @@ export type IContent = { _children?: Maybe; _deleted?: Maybe; _fulltext?: Maybe>>; + _link?: Maybe; _modified?: Maybe; _score?: Maybe; }; + +export type IContent_LinkArgs = { + type?: InputMaybe; +}; + export type ImageFile = IContent & { __typename?: 'ImageFile'; Ancestors?: Maybe>>; @@ -2130,6 +2267,7 @@ export type ImageFile = IContent & { RelativePath?: Maybe; RouteSegment?: Maybe; Saved?: Maybe; + SiteId?: Maybe; StartPublish?: Maybe; Status?: Maybe; StopPublish?: Maybe; @@ -2138,10 +2276,16 @@ export type ImageFile = IContent & { _children?: Maybe; _deleted?: Maybe; _fulltext?: Maybe>>; + _link?: Maybe; _modified?: Maybe; _score?: Maybe; }; + +export type ImageFile_LinkArgs = { + type?: InputMaybe; +}; + export type ImageFileAutocomplete = { __typename?: 'ImageFileAutocomplete'; Ancestors?: Maybe>>; @@ -2155,6 +2299,7 @@ export type ImageFileAutocomplete = { ParentLink?: Maybe; RelativePath?: Maybe>>; RouteSegment?: Maybe>>; + SiteId?: Maybe>>; Status?: Maybe>>; Thumbnail?: Maybe; Url?: Maybe>>; @@ -2191,6 +2336,12 @@ export type ImageFileAutocompleteRouteSegmentArgs = { }; +export type ImageFileAutocompleteSiteIdArgs = { + limit?: Scalars['Int']; + value: Scalars['String']; +}; + + export type ImageFileAutocompleteStatusArgs = { limit?: Scalars['Int']; value: Scalars['String']; @@ -2221,6 +2372,7 @@ export type ImageFileFacet = { RelativePath?: Maybe>>; RouteSegment?: Maybe>>; Saved?: Maybe>>; + SiteId?: Maybe>>; StartPublish?: Maybe>>; Status?: Maybe>>; StopPublish?: Maybe>>; @@ -2311,6 +2463,14 @@ export type ImageFileFacetSavedArgs = { }; +export type ImageFileFacetSiteIdArgs = { + filters?: InputMaybe>; + limit?: Scalars['Int']; + orderBy?: InputMaybe; + orderType?: InputMaybe; +}; + + export type ImageFileFacetStartPublishArgs = { unit?: InputMaybe; value?: InputMaybe; @@ -2356,6 +2516,7 @@ export type ImageFileOrderByInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; StopPublish?: InputMaybe; @@ -2396,6 +2557,7 @@ export type ImageFileWhereInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; StopPublish?: InputMaybe; @@ -2428,6 +2590,7 @@ export type ImagePage = IContent & { RelativePath?: Maybe; RouteSegment?: Maybe; Saved?: Maybe; + SiteId?: Maybe; StartPublish?: Maybe; Status?: Maybe; StopPublish?: Maybe; @@ -2436,10 +2599,16 @@ export type ImagePage = IContent & { _children?: Maybe; _deleted?: Maybe; _fulltext?: Maybe>>; + _link?: Maybe; _modified?: Maybe; _score?: Maybe; }; + +export type ImagePage_LinkArgs = { + type?: InputMaybe; +}; + export type ImagePageAutocomplete = { __typename?: 'ImagePageAutocomplete'; Ancestors?: Maybe>>; @@ -2453,6 +2622,7 @@ export type ImagePageAutocomplete = { ParentLink?: Maybe; RelativePath?: Maybe>>; RouteSegment?: Maybe>>; + SiteId?: Maybe>>; Status?: Maybe>>; Thumbnail?: Maybe; Url?: Maybe>>; @@ -2489,6 +2659,12 @@ export type ImagePageAutocompleteRouteSegmentArgs = { }; +export type ImagePageAutocompleteSiteIdArgs = { + limit?: Scalars['Int']; + value: Scalars['String']; +}; + + export type ImagePageAutocompleteStatusArgs = { limit?: Scalars['Int']; value: Scalars['String']; @@ -2520,6 +2696,7 @@ export type ImagePageFacet = { RelativePath?: Maybe>>; RouteSegment?: Maybe>>; Saved?: Maybe>>; + SiteId?: Maybe>>; StartPublish?: Maybe>>; Status?: Maybe>>; StopPublish?: Maybe>>; @@ -2618,6 +2795,14 @@ export type ImagePageFacetSavedArgs = { }; +export type ImagePageFacetSiteIdArgs = { + filters?: InputMaybe>; + limit?: Scalars['Int']; + orderBy?: InputMaybe; + orderType?: InputMaybe; +}; + + export type ImagePageFacetStartPublishArgs = { unit?: InputMaybe; value?: InputMaybe; @@ -2664,6 +2849,7 @@ export type ImagePageOrderByInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; StopPublish?: InputMaybe; @@ -2705,6 +2891,7 @@ export type ImagePageWhereInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; StopPublish?: InputMaybe; @@ -2717,6 +2904,43 @@ export type ImagePageWhereInput = { _or?: InputMaybe>>; }; +export type InlineBlockPropertyModel = { + __typename?: 'InlineBlockPropertyModel'; + ContentType?: Maybe>>; +}; + +export type InlineBlockPropertyModelAutocomplete = { + __typename?: 'InlineBlockPropertyModelAutocomplete'; + ContentType?: Maybe>>; +}; + + +export type InlineBlockPropertyModelAutocompleteContentTypeArgs = { + limit?: Scalars['Int']; + value: Scalars['String']; +}; + +export type InlineBlockPropertyModelFacet = { + __typename?: 'InlineBlockPropertyModelFacet'; + ContentType?: Maybe>>; +}; + + +export type InlineBlockPropertyModelFacetContentTypeArgs = { + filters?: InputMaybe>; + limit?: Scalars['Int']; + orderBy?: InputMaybe; + orderType?: InputMaybe; +}; + +export type InlineBlockPropertyModelOrderByInput = { + ContentType?: InputMaybe; +}; + +export type InlineBlockPropertyModelWhereInput = { + ContentType?: InputMaybe; +}; + export type IntFilterInput = { /** `boost` influences the weight of a field by boosting a match with a number (default: 1) — counts more towards the eventual relevance score which can be projected with `_score` — at query time. Note that `boost` cannot be a negative number. */ boost?: InputMaybe; @@ -2762,6 +2986,7 @@ export type LandingPage = IContent & { RelativePath?: Maybe; RouteSegment?: Maybe; Saved?: Maybe; + SiteId?: Maybe; StartPublish?: Maybe; Status?: Maybe; StopPublish?: Maybe; @@ -2771,10 +2996,16 @@ export type LandingPage = IContent & { _children?: Maybe; _deleted?: Maybe; _fulltext?: Maybe>>; + _link?: Maybe; _modified?: Maybe; _score?: Maybe; }; + +export type LandingPage_LinkArgs = { + type?: InputMaybe; +}; + export type LandingPageAutocomplete = { __typename?: 'LandingPageAutocomplete'; Ancestors?: Maybe>>; @@ -2792,6 +3023,7 @@ export type LandingPageAutocomplete = { ParentLink?: Maybe; RelativePath?: Maybe>>; RouteSegment?: Maybe>>; + SiteId?: Maybe>>; Status?: Maybe>>; Subtitle?: Maybe>>; Title?: Maybe>>; @@ -2829,6 +3061,12 @@ export type LandingPageAutocompleteRouteSegmentArgs = { }; +export type LandingPageAutocompleteSiteIdArgs = { + limit?: Scalars['Int']; + value: Scalars['String']; +}; + + export type LandingPageAutocompleteStatusArgs = { limit?: Scalars['Int']; value: Scalars['String']; @@ -2930,6 +3168,7 @@ export type LandingPageFacet = { RelativePath?: Maybe>>; RouteSegment?: Maybe>>; Saved?: Maybe>>; + SiteId?: Maybe>>; StartPublish?: Maybe>>; Status?: Maybe>>; StopPublish?: Maybe>>; @@ -3013,6 +3252,14 @@ export type LandingPageFacetSavedArgs = { }; +export type LandingPageFacetSiteIdArgs = { + filters?: InputMaybe>; + limit?: Scalars['Int']; + orderBy?: InputMaybe; + orderType?: InputMaybe; +}; + + export type LandingPageFacetStartPublishArgs = { unit?: InputMaybe; value?: InputMaybe; @@ -3077,6 +3324,7 @@ export type LandingPageOrderByInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; StopPublish?: InputMaybe; @@ -3121,6 +3369,7 @@ export type LandingPageWhereInput = { RelativePath?: InputMaybe; RouteSegment?: InputMaybe; Saved?: InputMaybe; + SiteId?: InputMaybe; StartPublish?: InputMaybe; Status?: InputMaybe; StopPublish?: InputMaybe; @@ -3134,6 +3383,10 @@ export type LandingPageWhereInput = { _or?: InputMaybe>>; }; +export enum LinkTypes { + Default = 'DEFAULT' +} + export enum Locales { All = 'ALL', Neutral = 'NEUTRAL', @@ -3390,7 +3643,7 @@ export enum Ranking { BoostOnly = 'BOOST_ONLY', Doc = 'DOC', Relevance = 'RELEVANCE', - Semantic = "SEMANTIC", + Semantic = 'SEMANTIC' } export type SearchableStringFilterInput = { @@ -3402,10 +3655,14 @@ export type SearchableStringFilterInput = { eq?: InputMaybe; /** `exist` matches results that have this field. */ exist?: InputMaybe; + /** enables supporting fuzzy matching on the query terms (keywords), which returns items that contain terms in the content similar to the keywords, as measured by a _Levenshtein edit distance_. An edit distance is the number of one-character changes needed to turn one term into another. The edit distance is based on the length of the term. */ + fuzzy?: InputMaybe; /** `in` matches with 1 or more exact values in a list. Example: `in: ["word1", "word2", "this is a phrase"]` */ in?: InputMaybe>>; /** `like` matches on substrings with wildcard support: `%` to match on 0 or more characters, `_` to match on any character. */ like?: InputMaybe; + /** `match` performs full-text search on a word or phrase where less relevant items are also returned. The `match` operator is only supported for `searchable` fields. It will improve fulltext search by making it easier to match on words. More exact matches will be ranked higher, less exact matches will be ranked lower. The `match` operator is supported with synonyms and fuzzy search. */ + match?: InputMaybe; /** `not_eq` retrieves results not matching with an exact (but case-insensitive) value. */ notEq?: InputMaybe; /** `not_in` returns results that do not match with 1 or more exact values in a list. Example: `not_in: ["word1", "word2", "this is a phrase"]` */ @@ -3430,10 +3687,16 @@ export type SiteDefinition = { _children?: Maybe; _deleted?: Maybe; _fulltext?: Maybe>>; + _link?: Maybe; _modified?: Maybe; _score?: Maybe; }; + +export type SiteDefinition_LinkArgs = { + type?: InputMaybe; +}; + export type SiteDefinitionAutocomplete = { __typename?: 'SiteDefinitionAutocomplete'; ContentLink?: Maybe; @@ -3688,6 +3951,8 @@ export type StringFilterInput = { eq?: InputMaybe; /** `exist` matches results that have this field. */ exist?: InputMaybe; + /** enables supporting fuzzy matching on the query terms (keywords), which returns items that contain terms in the content similar to the keywords, as measured by a _Levenshtein edit distance_. An edit distance is the number of one-character changes needed to turn one term into another. The edit distance is based on the length of the term. */ + fuzzy?: InputMaybe; /** `in` matches with 1 or more exact values in a list. Example: `in: ["word1", "word2", "this is a phrase"]` */ in?: InputMaybe>>; /** `like` matches on substrings with wildcard support: `%` to match on 0 or more characters, `_` to match on any character. */ @@ -3884,10 +4149,10 @@ export const useArtistAutocompleteQuery = < options ); export const ArtistSearchDocument = ` - query ArtistSearch($searchParam: String!, $locales: Locales!, $order: OrderBy, $ranking: Ranking) { + query ArtistSearch($searchParam: String!, $locales: Locales!, $order: OrderBy) { ArtistDetailsPage( locale: [$locales] - orderBy: {_ranking: $ranking, ArtistName: $order} + orderBy: {_ranking: RELEVANCE, ArtistName: $order} where: {_or: [{Name: {contains: $searchParam, boost: 10}}, {Name: {startsWith: $searchParam, boost: 10}}, {StageName: {startsWith: $searchParam}}]} ) { items { @@ -3932,10 +4197,10 @@ export const useArtistSearchQuery = < options ); export const OtherContentSearchDocument = ` - query OtherContentSearch($searchParam: String!, $locales: Locales!, $order: OrderBy, $ranking: Ranking) { + query OtherContentSearch($searchParam: String!, $locales: Locales!, $order: OrderBy) { Content( locale: [$locales] - orderBy: {_ranking: $ranking, Name: $order} + orderBy: {_ranking: RELEVANCE, Name: $order} where: {_or: [{Name: {contains: $searchParam, boost: 10}}, {Name: {startsWith: $searchParam, boost: 10}}], _and: {ContentType: {notEq: "ArtistDetailsPage"}}} ) { items { From 9630d8e8b5ba942e6553424b1858d4b0c1a7a378 Mon Sep 17 00:00:00 2001 From: Thach Nguyen Date: Tue, 10 Oct 2023 11:01:12 +0700 Subject: [PATCH 6/6] fix comments on the PR --- samples/musicfestival-frontend-react/src/App.tsx | 4 ++-- .../musicfestival-frontend-react/src/helpers/urlHelper.ts | 7 ++----- .../musicfestival-frontend-react/src/pages/SearchPage.tsx | 4 ++-- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/samples/musicfestival-frontend-react/src/App.tsx b/samples/musicfestival-frontend-react/src/App.tsx index 10f5600..67d3673 100644 --- a/samples/musicfestival-frontend-react/src/App.tsx +++ b/samples/musicfestival-frontend-react/src/App.tsx @@ -16,7 +16,7 @@ import { BlockPage } from './pages/BlockPage'; let previousSavedMessage: any = null; const singleKeyUrl = process.env.REACT_APP_CONTENT_GRAPH_GATEWAY_URL as string -const hmacKeyUrl = process.env.REACT_APP_CG_PREVIEW_URL as string +const previewUrl = process.env.REACT_APP_CG_PREVIEW_URL as string const App = () => { const queryClient = useQueryClient(); @@ -43,7 +43,7 @@ const App = () => { if (previewToken) { headers = { 'Authorization': 'Bearer ' + previewToken }; } - url = hmacKeyUrl + url = previewUrl subcribeContentSavedEvent((message: any) => mutate(message)) } diff --git a/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts b/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts index 525ccf3..5b3e81e 100644 --- a/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts +++ b/samples/musicfestival-frontend-react/src/helpers/urlHelper.ts @@ -18,13 +18,10 @@ const getImageUrl = (path = "") => { } const extractParams = (token: string, urlPath: string) => { - var payload: Payload = { - c_id: undefined, - c_ver: undefined - }; + var payload: Payload = {}; if (token) { - const base64String = token.substring(token.indexOf('.') + 1, token.lastIndexOf('.')); + const base64String = token.split('.')[1] payload = JSON.parse(Buffer.from(base64String, 'base64').toString()); } diff --git a/samples/musicfestival-frontend-react/src/pages/SearchPage.tsx b/samples/musicfestival-frontend-react/src/pages/SearchPage.tsx index 49af396..bc985a8 100644 --- a/samples/musicfestival-frontend-react/src/pages/SearchPage.tsx +++ b/samples/musicfestival-frontend-react/src/pages/SearchPage.tsx @@ -21,7 +21,7 @@ import { subcribeContentSavedEvent } from "../helpers/contentSavedEvent"; let previousSavedMessage: any = null; const singleKeyUrl = process.env.REACT_APP_CONTENT_GRAPH_GATEWAY_URL as string -const hmacKeyUrl = process.env.REACT_APP_CG_PREVIEW_URL as string +const previewUrl = process.env.REACT_APP_CG_PREVIEW_URL as string function SearchPage() { console.log("Start") @@ -80,7 +80,7 @@ function SearchPage() { if (token) { headers = { 'Authorization': 'Bearer ' + token } } - url = hmacKeyUrl + url = previewUrl subcribeContentSavedEvent((message: any) => mutate(message)) }