diff --git a/src/components/rooms/RoomExternalToolCard.vue b/src/components/rooms/RoomExternalToolCard.vue index b73ed359e6..ff973dabee 100644 --- a/src/components/rooms/RoomExternalToolCard.vue +++ b/src/components/rooms/RoomExternalToolCard.vue @@ -1,6 +1,7 @@ diff --git a/src/pages/course-rooms/tools/RoomExternalToolsSection.vue b/src/pages/course-rooms/tools/RoomExternalToolsSection.vue index 04c26d979f..353ce3d945 100644 --- a/src/pages/course-rooms/tools/RoomExternalToolsSection.vue +++ b/src/pages/course-rooms/tools/RoomExternalToolsSection.vue @@ -10,6 +10,7 @@ @delete="onOpenDeleteDialog" @edit="onEditTool" @error="onError" + @refresh="$emit('refresh')" :data-testid="`external-tool-card-${index}`" /> @@ -77,6 +78,7 @@ const props = defineProps({ const emit = defineEmits<{ (e: "delete", value: ExternalToolDisplayData): void; + (e: "refresh"): void; }>(); const authModule: AuthModule = injectStrict(AUTH_MODULE_KEY); diff --git a/src/serverApi/v3/api.ts b/src/serverApi/v3/api.ts index 4fe75fa025..f05cbabad7 100644 --- a/src/serverApi/v3/api.ts +++ b/src/serverApi/v3/api.ts @@ -2014,12 +2014,6 @@ export interface ContextExternalToolResponse { * @memberof ContextExternalToolResponse */ parameters: Array; - /** - * - * @type {string} - * @memberof ContextExternalToolResponse - */ - logoUrl?: string; } /** @@ -4102,6 +4096,18 @@ export enum LanguageType { Uk = 'uk' } +/** + * + * @export + * @enum {string} + */ +export enum LaunchType { + Basic = 'basic', + Oauth2 = 'oauth2', + Lti11BasicLaunch = 'lti11BasicLaunch', + Lti11ContentItemSelection = 'lti11ContentItemSelection' +} + /** * * @export @@ -4625,6 +4631,171 @@ export interface LoginResponse { */ accessToken: string; } +/** + * + * @export + * @interface Lti11DeepLinkContentItemListParams + */ +export interface Lti11DeepLinkContentItemListParams { + /** + * + * @type {string} + * @memberof Lti11DeepLinkContentItemListParams + */ + context: string; + /** + * + * @type {Array} + * @memberof Lti11DeepLinkContentItemListParams + */ + graph: Array; +} +/** + * + * @export + * @interface Lti11DeepLinkParams + */ +export interface Lti11DeepLinkParams { + /** + * + * @type {string} + * @memberof Lti11DeepLinkParams + */ + lti_message_type: string; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParams + */ + lti_version: string; + /** + * + * @type {Lti11DeepLinkContentItemListParams} + * @memberof Lti11DeepLinkParams + */ + content_items?: Lti11DeepLinkContentItemListParams; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParams + */ + data: string; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParams + */ + oauth_version: string; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParams + */ + oauth_nonce: string; + /** + * + * @type {number} + * @memberof Lti11DeepLinkParams + */ + oauth_timestamp: number; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParams + */ + oauth_signature_method: string; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParams + */ + oauth_consumer_key: string; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParams + */ + oauth_signature: string; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParams + */ + oauth_callback?: string; +} +/** + * + * @export + * @interface Lti11DeepLinkParamsRaw + */ +export interface Lti11DeepLinkParamsRaw { + /** + * + * @type {string} + * @memberof Lti11DeepLinkParamsRaw + */ + lti_message_type: string; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParamsRaw + */ + lti_version: string; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParamsRaw + */ + content_items?: string; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParamsRaw + */ + data: string; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParamsRaw + */ + oauth_version: string; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParamsRaw + */ + oauth_nonce: string; + /** + * + * @type {number} + * @memberof Lti11DeepLinkParamsRaw + */ + oauth_timestamp: number; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParamsRaw + */ + oauth_signature_method: string; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParamsRaw + */ + oauth_consumer_key: string; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParamsRaw + */ + oauth_signature: string; + /** + * + * @type {string} + * @memberof Lti11DeepLinkParamsRaw + */ + oauth_callback?: string; +} /** * * @export @@ -4723,6 +4894,55 @@ export interface Lti11ToolConfigUpdateParams { */ launch_presentation_locale: string; } +/** + * + * @export + * @interface LtiDeepLinkResponse + */ +export interface LtiDeepLinkResponse { + /** + * + * @type {string} + * @memberof LtiDeepLinkResponse + */ + mediaType: string; + /** + * + * @type {string} + * @memberof LtiDeepLinkResponse + */ + title?: string; + /** + * + * @type {string} + * @memberof LtiDeepLinkResponse + */ + text?: string; + /** + * + * @type {string} + * @memberof LtiDeepLinkResponse + */ + availableFrom?: string; + /** + * + * @type {string} + * @memberof LtiDeepLinkResponse + */ + availableUntil?: string; + /** + * + * @type {string} + * @memberof LtiDeepLinkResponse + */ + submissionFrom?: string; + /** + * + * @type {string} + * @memberof LtiDeepLinkResponse + */ + submissionUntil?: string; +} /** * * @export @@ -6384,6 +6604,19 @@ export interface OidcContextResponse { */ ui_locales: Array; } +/** + * + * @export + * @interface OidcLogoutBodyParams + */ +export interface OidcLogoutBodyParams { + /** + * + * @type {string} + * @memberof OidcLogoutBodyParams + */ + logout_token: string; +} /** * * @export @@ -8753,11 +8986,11 @@ export interface ToolLaunchRequestResponse { */ openNewTab?: boolean; /** - * Specifies whether the request is an LTI Deep linking content item selection request - * @type {boolean} + * + * @type {LaunchType} * @memberof ToolLaunchRequestResponse */ - isDeepLink: boolean; + launchType: LaunchType; } /** @@ -8830,6 +9063,18 @@ export interface ToolReferenceResponse { * @memberof ToolReferenceResponse */ status: ContextExternalToolConfigurationStatusResponse; + /** + * Whether the tool is a lti deep linking tool + * @type {boolean} + * @memberof ToolReferenceResponse + */ + isLtiDeepLinkingTool: boolean; + /** + * + * @type {LtiDeepLinkResponse} + * @memberof ToolReferenceResponse + */ + ltiDeepLink?: LtiDeepLinkResponse; } /** * @@ -10970,6 +11215,42 @@ export const AuthenticationApiAxiosParamCreator = function (configuration?: Conf let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @summary Logs out a user for a given logout token from an external oidc system. + * @param {OidcLogoutBodyParams} oidcLogoutBodyParams + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + logoutControllerLogoutOidc: async (oidcLogoutBodyParams: OidcLogoutBodyParams, options: any = {}): Promise => { + // verify required parameter 'oidcLogoutBodyParams' is not null or undefined + assertParamExists('logoutControllerLogoutOidc', 'oidcLogoutBodyParams', oidcLogoutBodyParams) + const localVarPath = `/logout/oidc`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter, options.query); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(oidcLogoutBodyParams, localVarRequestOptions, configuration) + return { url: toPathString(localVarUrlObj), options: localVarRequestOptions, @@ -11038,6 +11319,17 @@ export const AuthenticationApiFp = function(configuration?: Configuration) { const localVarAxiosArgs = await localVarAxiosParamCreator.logoutControllerLogout(options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, + /** + * + * @summary Logs out a user for a given logout token from an external oidc system. + * @param {OidcLogoutBodyParams} oidcLogoutBodyParams + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async logoutControllerLogoutOidc(oidcLogoutBodyParams: OidcLogoutBodyParams, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.logoutControllerLogoutOidc(oidcLogoutBodyParams, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, } }; @@ -11096,6 +11388,16 @@ export const AuthenticationApiFactory = function (configuration?: Configuration, logoutControllerLogout(options?: any): AxiosPromise { return localVarFp.logoutControllerLogout(options).then((request) => request(axios, basePath)); }, + /** + * + * @summary Logs out a user for a given logout token from an external oidc system. + * @param {OidcLogoutBodyParams} oidcLogoutBodyParams + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + logoutControllerLogoutOidc(oidcLogoutBodyParams: OidcLogoutBodyParams, options?: any): AxiosPromise { + return localVarFp.logoutControllerLogoutOidc(oidcLogoutBodyParams, options).then((request) => request(axios, basePath)); + }, }; }; @@ -11153,6 +11455,16 @@ export interface AuthenticationApiInterface { */ logoutControllerLogout(options?: any): AxiosPromise; + /** + * + * @summary Logs out a user for a given logout token from an external oidc system. + * @param {OidcLogoutBodyParams} oidcLogoutBodyParams + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AuthenticationApiInterface + */ + logoutControllerLogoutOidc(oidcLogoutBodyParams: OidcLogoutBodyParams, options?: any): AxiosPromise; + } /** @@ -11219,6 +11531,18 @@ export class AuthenticationApi extends BaseAPI implements AuthenticationApiInter public logoutControllerLogout(options?: any) { return AuthenticationApiFp(this.configuration).logoutControllerLogout(options).then((request) => request(this.axios, this.basePath)); } + + /** + * + * @summary Logs out a user for a given logout token from an external oidc system. + * @param {OidcLogoutBodyParams} oidcLogoutBodyParams + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof AuthenticationApi + */ + public logoutControllerLogoutOidc(oidcLogoutBodyParams: OidcLogoutBodyParams, options?: any) { + return AuthenticationApiFp(this.configuration).logoutControllerLogoutOidc(oidcLogoutBodyParams, options).then((request) => request(this.axios, this.basePath)); + } } @@ -24294,6 +24618,45 @@ export const ToolApiAxiosParamCreator = function (configuration?: Configuration) options: localVarRequestOptions, }; }, + /** + * + * @param {string} contextExternalToolId + * @param {Lti11DeepLinkParamsRaw} lti11DeepLinkParamsRaw + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + toolDeepLinkControllerDeepLink: async (contextExternalToolId: string, lti11DeepLinkParamsRaw: Lti11DeepLinkParamsRaw, options: any = {}): Promise => { + // verify required parameter 'contextExternalToolId' is not null or undefined + assertParamExists('toolDeepLinkControllerDeepLink', 'contextExternalToolId', contextExternalToolId) + // verify required parameter 'lti11DeepLinkParamsRaw' is not null or undefined + assertParamExists('toolDeepLinkControllerDeepLink', 'lti11DeepLinkParamsRaw', lti11DeepLinkParamsRaw) + const localVarPath = `/tools/context-external-tools/{contextExternalToolId}/lti11-deep-link-callback` + .replace(`{${"contextExternalToolId"}}`, encodeURIComponent(String(contextExternalToolId))); + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + + const localVarRequestOptions = { method: 'POST', ...baseOptions, ...options}; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + + + localVarHeaderParameter['Content-Type'] = 'application/json'; + + setSearchParams(localVarUrlObj, localVarQueryParameter, options.query); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers}; + localVarRequestOptions.data = serializeDataIfNeeded(lti11DeepLinkParamsRaw, localVarRequestOptions, configuration) + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, /** * * @summary Get tool launch request for a context external tool id @@ -24933,6 +25296,17 @@ export const ToolApiFp = function(configuration?: Configuration) { const localVarAxiosArgs = await localVarAxiosParamCreator.toolControllerUpdateExternalTool(externalToolId, externalToolUpdateParams, options); return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); }, + /** + * + * @param {string} contextExternalToolId + * @param {Lti11DeepLinkParamsRaw} lti11DeepLinkParamsRaw + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async toolDeepLinkControllerDeepLink(contextExternalToolId: string, lti11DeepLinkParamsRaw: Lti11DeepLinkParamsRaw, options?: any): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await localVarAxiosParamCreator.toolDeepLinkControllerDeepLink(contextExternalToolId, lti11DeepLinkParamsRaw, options); + return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration); + }, /** * * @summary Get tool launch request for a context external tool id @@ -25264,6 +25638,16 @@ export const ToolApiFactory = function (configuration?: Configuration, basePath? toolControllerUpdateExternalTool(externalToolId: string, externalToolUpdateParams: ExternalToolUpdateParams, options?: any): AxiosPromise { return localVarFp.toolControllerUpdateExternalTool(externalToolId, externalToolUpdateParams, options).then((request) => request(axios, basePath)); }, + /** + * + * @param {string} contextExternalToolId + * @param {Lti11DeepLinkParamsRaw} lti11DeepLinkParamsRaw + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + toolDeepLinkControllerDeepLink(contextExternalToolId: string, lti11DeepLinkParamsRaw: Lti11DeepLinkParamsRaw, options?: any): AxiosPromise { + return localVarFp.toolDeepLinkControllerDeepLink(contextExternalToolId, lti11DeepLinkParamsRaw, options).then((request) => request(axios, basePath)); + }, /** * * @summary Get tool launch request for a context external tool id @@ -25584,6 +25968,16 @@ export interface ToolApiInterface { */ toolControllerUpdateExternalTool(externalToolId: string, externalToolUpdateParams: ExternalToolUpdateParams, options?: any): AxiosPromise; + /** + * + * @param {string} contextExternalToolId + * @param {Lti11DeepLinkParamsRaw} lti11DeepLinkParamsRaw + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ToolApiInterface + */ + toolDeepLinkControllerDeepLink(contextExternalToolId: string, lti11DeepLinkParamsRaw: Lti11DeepLinkParamsRaw, options?: any): AxiosPromise; + /** * * @summary Get tool launch request for a context external tool id @@ -25944,6 +26338,18 @@ export class ToolApi extends BaseAPI implements ToolApiInterface { return ToolApiFp(this.configuration).toolControllerUpdateExternalTool(externalToolId, externalToolUpdateParams, options).then((request) => request(this.axios, this.basePath)); } + /** + * + * @param {string} contextExternalToolId + * @param {Lti11DeepLinkParamsRaw} lti11DeepLinkParamsRaw + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ToolApi + */ + public toolDeepLinkControllerDeepLink(contextExternalToolId: string, lti11DeepLinkParamsRaw: Lti11DeepLinkParamsRaw, options?: any) { + return ToolApiFp(this.configuration).toolDeepLinkControllerDeepLink(contextExternalToolId, lti11DeepLinkParamsRaw, options).then((request) => request(this.axios, this.basePath)); + } + /** * * @summary Get tool launch request for a context external tool id diff --git a/src/store/external-tool/mapper/external-tool.mapper.ts b/src/store/external-tool/mapper/external-tool.mapper.ts index 88b80e81a0..771cc0620a 100644 --- a/src/store/external-tool/mapper/external-tool.mapper.ts +++ b/src/store/external-tool/mapper/external-tool.mapper.ts @@ -58,6 +58,8 @@ export class ExternalToolMapper { logoUrl: response.logoUrl, thumbnailUrl: response.thumbnailUrl, openInNewTab: response.openInNewTab, + isLtiDeepLinkingTool: response.isLtiDeepLinkingTool, + ltiDeepLink: response.ltiDeepLink, }; return mapped; @@ -71,7 +73,7 @@ export class ExternalToolMapper { url: response.url, payload: response.payload, openNewTab: response.openNewTab, - isDeepLink: response.isDeepLink, + launchType: response.launchType, }; return mapped; diff --git a/src/store/external-tool/tool-launch-request.ts b/src/store/external-tool/tool-launch-request.ts index b5deddb91c..f0f3d5d1d7 100644 --- a/src/store/external-tool/tool-launch-request.ts +++ b/src/store/external-tool/tool-launch-request.ts @@ -1,3 +1,4 @@ +import { LaunchType } from "@/serverApi/v3"; import { ToolLaunchRequestMethodEnum } from "@/store/external-tool/tool-launch-request-method.enum"; export type ToolLaunchRequest = { @@ -5,5 +6,5 @@ export type ToolLaunchRequest = { url: string; payload?: string; openNewTab?: boolean; - isDeepLink: boolean; + launchType: LaunchType; }; diff --git a/tests/test-utils/factory/externalToolDisplayDataFactory.ts b/tests/test-utils/factory/externalToolDisplayDataFactory.ts index e1abd328d8..7f6a3c2c59 100644 --- a/tests/test-utils/factory/externalToolDisplayDataFactory.ts +++ b/tests/test-utils/factory/externalToolDisplayDataFactory.ts @@ -10,4 +10,5 @@ export const externalToolDisplayDataFactory = openInNewTab: false, status: contextExternalToolConfigurationStatusFactory.build(), logoUrl: "https://example.com/logo.png", + isLtiDeepLinkingTool: false, })); diff --git a/tests/test-utils/factory/index.ts b/tests/test-utils/factory/index.ts index 1817284e48..8230f77e4e 100644 --- a/tests/test-utils/factory/index.ts +++ b/tests/test-utils/factory/index.ts @@ -64,6 +64,7 @@ export * from "./videoConferenceJoinResponseFactory"; export * from "./envsFactory"; export * from "./media-board"; export * from "./contextExternalToolResponseFactory"; +export * from "./ltiDeepLinkResponseFactory"; export * from "./courseInfoDataResponseFactory"; export * from "./deletedElementResponseFactory"; export * from "./room"; diff --git a/tests/test-utils/factory/ltiDeepLinkResponseFactory.ts b/tests/test-utils/factory/ltiDeepLinkResponseFactory.ts new file mode 100644 index 0000000000..4ea0cf1883 --- /dev/null +++ b/tests/test-utils/factory/ltiDeepLinkResponseFactory.ts @@ -0,0 +1,8 @@ +import { Factory } from "fishery"; +import { LtiDeepLinkResponse } from "@/serverApi/v3"; + +export const ltiDeepLinkResponseFactory = Factory.define( + () => ({ + mediaType: "mediaType", + }) +); diff --git a/tests/test-utils/factory/toolLaunchRequestFactory.ts b/tests/test-utils/factory/toolLaunchRequestFactory.ts index f6cced0a4c..c9d1217ed8 100644 --- a/tests/test-utils/factory/toolLaunchRequestFactory.ts +++ b/tests/test-utils/factory/toolLaunchRequestFactory.ts @@ -1,3 +1,4 @@ +import { LaunchType } from "@/serverApi/v3"; import { ToolLaunchRequest, ToolLaunchRequestMethodEnum, @@ -9,6 +10,6 @@ export const toolLaunchRequestFactory = Factory.define( method: ToolLaunchRequestMethodEnum.Get, payload: '{ "key": "value" }', url: "https://example.com/tool-launch", - isDeepLink: false, + launchType: LaunchType.Basic, }) ); diff --git a/tests/test-utils/factory/toolLaunchRequestResponseFactory.ts b/tests/test-utils/factory/toolLaunchRequestResponseFactory.ts index 72ee1b30fb..0e4f195642 100644 --- a/tests/test-utils/factory/toolLaunchRequestResponseFactory.ts +++ b/tests/test-utils/factory/toolLaunchRequestResponseFactory.ts @@ -1,5 +1,6 @@ import { Factory } from "fishery"; import { + LaunchType, ToolLaunchRequestResponse, ToolLaunchRequestResponseMethodEnum, } from "@/serverApi/v3"; @@ -9,5 +10,5 @@ export const toolLaunchRequestResponseFactory = method: ToolLaunchRequestResponseMethodEnum.Get, payload: '{ "key": "value" }', url: "https://example.com/tool-launch", - isDeepLink: false, + launchType: LaunchType.Basic, })); diff --git a/tests/test-utils/factory/toolReferenceResponseFactory.ts b/tests/test-utils/factory/toolReferenceResponseFactory.ts index bd5aef3092..742cbbcfa5 100644 --- a/tests/test-utils/factory/toolReferenceResponseFactory.ts +++ b/tests/test-utils/factory/toolReferenceResponseFactory.ts @@ -8,4 +8,5 @@ export const toolReferenceResponseFactory = status: contextExternalToolConfigurationStatusFactory.build(), openInNewTab: true, displayName: `Tool ${sequence}`, + isLtiDeepLinkingTool: false, }));