diff --git a/console/package.json b/console/package.json index 77b70ba352..c96d3cfafa 100644 --- a/console/package.json +++ b/console/package.json @@ -71,6 +71,7 @@ "@uppy/xhr-upload": "^3.6.0", "@vueuse/components": "^10.3.0", "@vueuse/core": "^10.3.0", + "@vueuse/integrations": "^10.5.0", "@vueuse/router": "^10.3.0", "@vueuse/shared": "^10.3.0", "axios": "^0.27.2", @@ -89,6 +90,7 @@ "path-browserify": "^1.0.1", "pinia": "^2.1.6", "pretty-bytes": "^6.0.0", + "qrcode": "^1.5.3", "qs": "^6.11.1", "short-unique-id": "^5.0.2", "transliteration": "^2.3.5", diff --git a/console/packages/api-client/src/.openapi-generator/FILES b/console/packages/api-client/src/.openapi-generator/FILES index b1676ea613..ced5501674 100644 --- a/console/packages/api-client/src/.openapi-generator/FILES +++ b/console/packages/api-client/src/.openapi-generator/FILES @@ -29,6 +29,7 @@ api/api-notification-halo-run-v1alpha1-notification-api.ts api/api-notification-halo-run-v1alpha1-notifier-api.ts api/api-notification-halo-run-v1alpha1-subscription-api.ts api/api-plugin-halo-run-v1alpha1-plugin-api.ts +api/api-security-halo-run-v1alpha1-authentication-two-factor-api.ts api/api-security-halo-run-v1alpha1-personal-access-token-api.ts api/auth-halo-run-v1alpha1-auth-provider-api.ts api/auth-halo-run-v1alpha1-user-connection-api.ts @@ -186,6 +187,7 @@ models/notifier-descriptor.ts models/notifier-info.ts models/notifier-setting-ref.ts models/owner-info.ts +models/password-request.ts models/password-reset-email-request.ts models/pat-spec.ts models/personal-access-token-list.ts @@ -283,6 +285,9 @@ models/theme-list.ts models/theme-spec.ts models/theme-status.ts models/theme.ts +models/totp-auth-link-response.ts +models/totp-request.ts +models/two-factor-auth-settings.ts models/upgrade-from-uri-request.ts models/user-connection-list.ts models/user-connection-spec.ts diff --git a/console/packages/api-client/src/api.ts b/console/packages/api-client/src/api.ts index fcdd3ce669..cd7dcb3335 100644 --- a/console/packages/api-client/src/api.ts +++ b/console/packages/api-client/src/api.ts @@ -40,6 +40,7 @@ export * from "./api/api-notification-halo-run-v1alpha1-notification-api"; export * from "./api/api-notification-halo-run-v1alpha1-notifier-api"; export * from "./api/api-notification-halo-run-v1alpha1-subscription-api"; export * from "./api/api-plugin-halo-run-v1alpha1-plugin-api"; +export * from "./api/api-security-halo-run-v1alpha1-authentication-two-factor-api"; export * from "./api/api-security-halo-run-v1alpha1-personal-access-token-api"; export * from "./api/auth-halo-run-v1alpha1-auth-provider-api"; export * from "./api/auth-halo-run-v1alpha1-user-connection-api"; diff --git a/console/packages/api-client/src/api/api-security-halo-run-v1alpha1-authentication-two-factor-api.ts b/console/packages/api-client/src/api/api-security-halo-run-v1alpha1-authentication-two-factor-api.ts new file mode 100644 index 0000000000..24cacfd949 --- /dev/null +++ b/console/packages/api-client/src/api/api-security-halo-run-v1alpha1-authentication-two-factor-api.ts @@ -0,0 +1,795 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Halo Next API + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 2.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import type { Configuration } from "../configuration"; +import type { AxiosPromise, AxiosInstance, AxiosRequestConfig } from "axios"; +import globalAxios from "axios"; +// Some imports not used depending on template conditions +// @ts-ignore +import { + DUMMY_BASE_URL, + assertParamExists, + setApiKeyToObject, + setBasicAuthToObject, + setBearerAuthToObject, + setOAuthToObject, + setSearchParams, + serializeDataIfNeeded, + toPathString, + createRequestFunction, +} from "../common"; +// @ts-ignore +import { + BASE_PATH, + COLLECTION_FORMATS, + RequestArgs, + BaseAPI, + RequiredError, +} from "../base"; +// @ts-ignore +import { PasswordRequest } from "../models"; +// @ts-ignore +import { TotpAuthLinkResponse } from "../models"; +// @ts-ignore +import { TotpRequest } from "../models"; +// @ts-ignore +import { TwoFactorAuthSettings } from "../models"; +/** + * ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi - axios parameter creator + * @export + */ +export const ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiAxiosParamCreator = + function (configuration?: Configuration) { + return { + /** + * Configure a TOTP + * @param {TotpRequest} [totpRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + configurerTotp: async ( + totpRequest?: TotpRequest, + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/apis/api.security.halo.run/v1alpha1/authentications/two-factor/totp`; + // 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; + + // authentication BasicAuth required + // http basic authentication required + setBasicAuthToObject(localVarRequestOptions, configuration); + + // authentication BearerAuth required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); + + localVarHeaderParameter["Content-Type"] = "application/json"; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + totpRequest, + localVarRequestOptions, + configuration + ); + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * + * @param {PasswordRequest} [passwordRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + deleteTotp: async ( + passwordRequest?: PasswordRequest, + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/apis/api.security.halo.run/v1alpha1/authentications/two-factor/totp/-`; + // 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: "DELETE", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication BasicAuth required + // http basic authentication required + setBasicAuthToObject(localVarRequestOptions, configuration); + + // authentication BearerAuth required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); + + localVarHeaderParameter["Content-Type"] = "application/json"; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + passwordRequest, + localVarRequestOptions, + configuration + ); + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Disable Two-factor authentication + * @param {PasswordRequest} [passwordRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + disableTwoFactor: async ( + passwordRequest?: PasswordRequest, + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/apis/api.security.halo.run/v1alpha1/authentications/two-factor/settings/disabled`; + // 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: "PUT", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication BasicAuth required + // http basic authentication required + setBasicAuthToObject(localVarRequestOptions, configuration); + + // authentication BearerAuth required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); + + localVarHeaderParameter["Content-Type"] = "application/json"; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + passwordRequest, + localVarRequestOptions, + configuration + ); + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Enable Two-factor authentication + * @param {PasswordRequest} [passwordRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + enableTwoFactor: async ( + passwordRequest?: PasswordRequest, + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/apis/api.security.halo.run/v1alpha1/authentications/two-factor/settings/enabled`; + // 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: "PUT", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication BasicAuth required + // http basic authentication required + setBasicAuthToObject(localVarRequestOptions, configuration); + + // authentication BearerAuth required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); + + localVarHeaderParameter["Content-Type"] = "application/json"; + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + localVarRequestOptions.data = serializeDataIfNeeded( + passwordRequest, + localVarRequestOptions, + configuration + ); + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Get TOTP auth link, including secret + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getTotpAuthLink: async ( + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/apis/api.security.halo.run/v1alpha1/authentications/two-factor/totp/auth-link`; + // 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: "GET", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication BasicAuth required + // http basic authentication required + setBasicAuthToObject(localVarRequestOptions, configuration); + + // authentication BearerAuth required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + /** + * Get Two-factor authentication settings. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getTwoFactorAuthenticationSettings: async ( + options: AxiosRequestConfig = {} + ): Promise => { + const localVarPath = `/apis/api.security.halo.run/v1alpha1/authentications/two-factor/settings`; + // 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: "GET", + ...baseOptions, + ...options, + }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + // authentication BasicAuth required + // http basic authentication required + setBasicAuthToObject(localVarRequestOptions, configuration); + + // authentication BearerAuth required + // http bearer authentication required + await setBearerAuthToObject(localVarHeaderParameter, configuration); + + setSearchParams(localVarUrlObj, localVarQueryParameter); + let headersFromBaseOptions = + baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + + return { + url: toPathString(localVarUrlObj), + options: localVarRequestOptions, + }; + }, + }; + }; + +/** + * ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi - functional programming interface + * @export + */ +export const ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiFp = function ( + configuration?: Configuration +) { + const localVarAxiosParamCreator = + ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiAxiosParamCreator( + configuration + ); + return { + /** + * Configure a TOTP + * @param {TotpRequest} [totpRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async configurerTotp( + totpRequest?: TotpRequest, + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.configurerTotp( + totpRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * + * @param {PasswordRequest} [passwordRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async deleteTotp( + passwordRequest?: PasswordRequest, + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.deleteTotp( + passwordRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * Disable Two-factor authentication + * @param {PasswordRequest} [passwordRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async disableTwoFactor( + passwordRequest?: PasswordRequest, + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.disableTwoFactor( + passwordRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * Enable Two-factor authentication + * @param {PasswordRequest} [passwordRequest] + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async enableTwoFactor( + passwordRequest?: PasswordRequest, + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.enableTwoFactor( + passwordRequest, + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * Get TOTP auth link, including secret + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getTotpAuthLink( + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = await localVarAxiosParamCreator.getTotpAuthLink( + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + /** + * Get Two-factor authentication settings. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getTwoFactorAuthenticationSettings( + options?: AxiosRequestConfig + ): Promise< + ( + axios?: AxiosInstance, + basePath?: string + ) => AxiosPromise + > { + const localVarAxiosArgs = + await localVarAxiosParamCreator.getTwoFactorAuthenticationSettings( + options + ); + return createRequestFunction( + localVarAxiosArgs, + globalAxios, + BASE_PATH, + configuration + ); + }, + }; +}; + +/** + * ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi - factory interface + * @export + */ +export const ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiFactory = + function ( + configuration?: Configuration, + basePath?: string, + axios?: AxiosInstance + ) { + const localVarFp = + ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiFp(configuration); + return { + /** + * Configure a TOTP + * @param {ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiConfigurerTotpRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + configurerTotp( + requestParameters: ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiConfigurerTotpRequest = {}, + options?: AxiosRequestConfig + ): AxiosPromise { + return localVarFp + .configurerTotp(requestParameters.totpRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * + * @param {ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiDeleteTotpRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + deleteTotp( + requestParameters: ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiDeleteTotpRequest = {}, + options?: AxiosRequestConfig + ): AxiosPromise { + return localVarFp + .deleteTotp(requestParameters.passwordRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * Disable Two-factor authentication + * @param {ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiDisableTwoFactorRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + disableTwoFactor( + requestParameters: ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiDisableTwoFactorRequest = {}, + options?: AxiosRequestConfig + ): AxiosPromise { + return localVarFp + .disableTwoFactor(requestParameters.passwordRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * Enable Two-factor authentication + * @param {ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiEnableTwoFactorRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + enableTwoFactor( + requestParameters: ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiEnableTwoFactorRequest = {}, + options?: AxiosRequestConfig + ): AxiosPromise { + return localVarFp + .enableTwoFactor(requestParameters.passwordRequest, options) + .then((request) => request(axios, basePath)); + }, + /** + * Get TOTP auth link, including secret + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getTotpAuthLink( + options?: AxiosRequestConfig + ): AxiosPromise { + return localVarFp + .getTotpAuthLink(options) + .then((request) => request(axios, basePath)); + }, + /** + * Get Two-factor authentication settings. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getTwoFactorAuthenticationSettings( + options?: AxiosRequestConfig + ): AxiosPromise { + return localVarFp + .getTwoFactorAuthenticationSettings(options) + .then((request) => request(axios, basePath)); + }, + }; + }; + +/** + * Request parameters for configurerTotp operation in ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi. + * @export + * @interface ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiConfigurerTotpRequest + */ +export interface ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiConfigurerTotpRequest { + /** + * + * @type {TotpRequest} + * @memberof ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiConfigurerTotp + */ + readonly totpRequest?: TotpRequest; +} + +/** + * Request parameters for deleteTotp operation in ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi. + * @export + * @interface ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiDeleteTotpRequest + */ +export interface ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiDeleteTotpRequest { + /** + * + * @type {PasswordRequest} + * @memberof ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiDeleteTotp + */ + readonly passwordRequest?: PasswordRequest; +} + +/** + * Request parameters for disableTwoFactor operation in ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi. + * @export + * @interface ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiDisableTwoFactorRequest + */ +export interface ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiDisableTwoFactorRequest { + /** + * + * @type {PasswordRequest} + * @memberof ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiDisableTwoFactor + */ + readonly passwordRequest?: PasswordRequest; +} + +/** + * Request parameters for enableTwoFactor operation in ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi. + * @export + * @interface ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiEnableTwoFactorRequest + */ +export interface ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiEnableTwoFactorRequest { + /** + * + * @type {PasswordRequest} + * @memberof ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiEnableTwoFactor + */ + readonly passwordRequest?: PasswordRequest; +} + +/** + * ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi - object-oriented interface + * @export + * @class ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi + * @extends {BaseAPI} + */ +export class ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi extends BaseAPI { + /** + * Configure a TOTP + * @param {ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiConfigurerTotpRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi + */ + public configurerTotp( + requestParameters: ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiConfigurerTotpRequest = {}, + options?: AxiosRequestConfig + ) { + return ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiFp( + this.configuration + ) + .configurerTotp(requestParameters.totpRequest, options) + .then((request) => request(this.axios, this.basePath)); + } + + /** + * + * @param {ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiDeleteTotpRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi + */ + public deleteTotp( + requestParameters: ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiDeleteTotpRequest = {}, + options?: AxiosRequestConfig + ) { + return ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiFp( + this.configuration + ) + .deleteTotp(requestParameters.passwordRequest, options) + .then((request) => request(this.axios, this.basePath)); + } + + /** + * Disable Two-factor authentication + * @param {ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiDisableTwoFactorRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi + */ + public disableTwoFactor( + requestParameters: ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiDisableTwoFactorRequest = {}, + options?: AxiosRequestConfig + ) { + return ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiFp( + this.configuration + ) + .disableTwoFactor(requestParameters.passwordRequest, options) + .then((request) => request(this.axios, this.basePath)); + } + + /** + * Enable Two-factor authentication + * @param {ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiEnableTwoFactorRequest} requestParameters Request parameters. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi + */ + public enableTwoFactor( + requestParameters: ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiEnableTwoFactorRequest = {}, + options?: AxiosRequestConfig + ) { + return ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiFp( + this.configuration + ) + .enableTwoFactor(requestParameters.passwordRequest, options) + .then((request) => request(this.axios, this.basePath)); + } + + /** + * Get TOTP auth link, including secret + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi + */ + public getTotpAuthLink(options?: AxiosRequestConfig) { + return ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiFp( + this.configuration + ) + .getTotpAuthLink(options) + .then((request) => request(this.axios, this.basePath)); + } + + /** + * Get Two-factor authentication settings. + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi + */ + public getTwoFactorAuthenticationSettings(options?: AxiosRequestConfig) { + return ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApiFp( + this.configuration + ) + .getTwoFactorAuthenticationSettings(options) + .then((request) => request(this.axios, this.basePath)); + } +} diff --git a/console/packages/api-client/src/models/index.ts b/console/packages/api-client/src/models/index.ts index f1bc6a1300..d0c5700934 100644 --- a/console/packages/api-client/src/models/index.ts +++ b/console/packages/api-client/src/models/index.ts @@ -106,6 +106,7 @@ export * from "./notifier-descriptor-spec"; export * from "./notifier-info"; export * from "./notifier-setting-ref"; export * from "./owner-info"; +export * from "./password-request"; export * from "./password-reset-email-request"; export * from "./pat-spec"; export * from "./personal-access-token"; @@ -203,6 +204,9 @@ export * from "./theme"; export * from "./theme-list"; export * from "./theme-spec"; export * from "./theme-status"; +export * from "./totp-auth-link-response"; +export * from "./totp-request"; +export * from "./two-factor-auth-settings"; export * from "./upgrade-from-uri-request"; export * from "./user"; export * from "./user-connection"; diff --git a/console/packages/api-client/src/models/password-request.ts b/console/packages/api-client/src/models/password-request.ts new file mode 100644 index 0000000000..04247c71dc --- /dev/null +++ b/console/packages/api-client/src/models/password-request.ts @@ -0,0 +1,27 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Halo Next API + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 2.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/** + * + * @export + * @interface PasswordRequest + */ +export interface PasswordRequest { + /** + * + * @type {string} + * @memberof PasswordRequest + */ + password: string; +} diff --git a/console/packages/api-client/src/models/totp-auth-link-response.ts b/console/packages/api-client/src/models/totp-auth-link-response.ts new file mode 100644 index 0000000000..094ec0c5e0 --- /dev/null +++ b/console/packages/api-client/src/models/totp-auth-link-response.ts @@ -0,0 +1,33 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Halo Next API + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 2.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/** + * + * @export + * @interface TotpAuthLinkResponse + */ +export interface TotpAuthLinkResponse { + /** + * + * @type {string} + * @memberof TotpAuthLinkResponse + */ + authLink?: string; + /** + * + * @type {string} + * @memberof TotpAuthLinkResponse + */ + rawSecret?: string; +} diff --git a/console/packages/api-client/src/models/totp-request.ts b/console/packages/api-client/src/models/totp-request.ts new file mode 100644 index 0000000000..51cf3f6ac8 --- /dev/null +++ b/console/packages/api-client/src/models/totp-request.ts @@ -0,0 +1,39 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Halo Next API + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 2.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/** + * + * @export + * @interface TotpRequest + */ +export interface TotpRequest { + /** + * + * @type {string} + * @memberof TotpRequest + */ + code: string; + /** + * + * @type {string} + * @memberof TotpRequest + */ + password: string; + /** + * + * @type {string} + * @memberof TotpRequest + */ + secret: string; +} diff --git a/console/packages/api-client/src/models/two-factor-auth-settings.ts b/console/packages/api-client/src/models/two-factor-auth-settings.ts new file mode 100644 index 0000000000..7c5269f55a --- /dev/null +++ b/console/packages/api-client/src/models/two-factor-auth-settings.ts @@ -0,0 +1,45 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Halo Next API + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * The version of the OpenAPI document: 2.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +/** + * + * @export + * @interface TwoFactorAuthSettings + */ +export interface TwoFactorAuthSettings { + /** + * + * @type {boolean} + * @memberof TwoFactorAuthSettings + */ + available?: boolean; + /** + * + * @type {boolean} + * @memberof TwoFactorAuthSettings + */ + emailVerified?: boolean; + /** + * + * @type {boolean} + * @memberof TwoFactorAuthSettings + */ + enabled?: boolean; + /** + * + * @type {boolean} + * @memberof TwoFactorAuthSettings + */ + totpConfigured?: boolean; +} diff --git a/console/packages/api-client/src/models/user-spec.ts b/console/packages/api-client/src/models/user-spec.ts index c2c2d1efb9..8a55b40b5d 100644 --- a/console/packages/api-client/src/models/user-spec.ts +++ b/console/packages/api-client/src/models/user-spec.ts @@ -78,6 +78,12 @@ export interface UserSpec { * @memberof UserSpec */ registeredAt?: string; + /** + * + * @type {string} + * @memberof UserSpec + */ + totpEncryptedSecret?: string; /** * * @type {boolean} diff --git a/console/pnpm-lock.yaml b/console/pnpm-lock.yaml index f5195a7618..9881ade70d 100644 --- a/console/pnpm-lock.yaml +++ b/console/pnpm-lock.yaml @@ -110,6 +110,9 @@ importers: '@vueuse/core': specifier: ^10.3.0 version: 10.3.0(vue@3.3.4) + '@vueuse/integrations': + specifier: ^10.5.0 + version: 10.7.1(axios@0.27.2)(fuse.js@6.6.2)(qrcode@1.5.3)(vue@3.3.4) '@vueuse/router': specifier: ^10.3.0 version: 10.3.0(vue-router@4.2.4)(vue@3.3.4) @@ -164,6 +167,9 @@ importers: pretty-bytes: specifier: ^6.0.0 version: 6.0.0 + qrcode: + specifier: ^1.5.3 + version: 1.5.3 qs: specifier: ^6.11.1 version: 6.11.1 @@ -6519,6 +6525,10 @@ packages: resolution: {integrity: sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA==} dev: false + /@types/web-bluetooth@0.0.20: + resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} + dev: false + /@types/yargs-parser@21.0.3: resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} dev: true @@ -7199,10 +7209,78 @@ packages: - vue dev: false + /@vueuse/core@10.7.1(vue@3.3.4): + resolution: {integrity: sha512-74mWHlaesJSWGp1ihg76vAnfVq9NTv1YT0SYhAQ6zwFNdBkkP+CKKJmVOEHcdSnLXCXYiL5e7MaewblfiYLP7g==} + dependencies: + '@types/web-bluetooth': 0.0.20 + '@vueuse/metadata': 10.7.1 + '@vueuse/shared': 10.7.1(vue@3.3.4) + vue-demi: 0.14.6(vue@3.3.4) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: false + + /@vueuse/integrations@10.7.1(axios@0.27.2)(fuse.js@6.6.2)(qrcode@1.5.3)(vue@3.3.4): + resolution: {integrity: sha512-cKo5LEeKVHdBRBtMTOrDPdR0YNtrmN9IBfdcnY2P3m5LHVrsD0xiHUtAH1WKjHQRIErZG6rJUa6GA4tWZt89Og==} + peerDependencies: + async-validator: '*' + axios: '*' + change-case: '*' + drauu: '*' + focus-trap: '*' + fuse.js: '*' + idb-keyval: '*' + jwt-decode: '*' + nprogress: '*' + qrcode: '*' + sortablejs: '*' + universal-cookie: '*' + peerDependenciesMeta: + async-validator: + optional: true + axios: + optional: true + change-case: + optional: true + drauu: + optional: true + focus-trap: + optional: true + fuse.js: + optional: true + idb-keyval: + optional: true + jwt-decode: + optional: true + nprogress: + optional: true + qrcode: + optional: true + sortablejs: + optional: true + universal-cookie: + optional: true + dependencies: + '@vueuse/core': 10.7.1(vue@3.3.4) + '@vueuse/shared': 10.7.1(vue@3.3.4) + axios: 0.27.2 + fuse.js: 6.6.2 + qrcode: 1.5.3 + vue-demi: 0.14.6(vue@3.3.4) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: false + /@vueuse/metadata@10.3.0: resolution: {integrity: sha512-Ema3YhNOa4swDsV0V7CEY5JXvK19JI/o1szFO1iWxdFg3vhdFtCtSTP26PCvbUpnUtNHBY2wx5y3WDXND5Pvnw==} dev: false + /@vueuse/metadata@10.7.1: + resolution: {integrity: sha512-jX8MbX5UX067DYVsbtrmKn6eG6KMcXxLRLlurGkZku5ZYT3vxgBjui2zajvUZ18QLIjrgBkFRsu7CqTAg18QFw==} + dev: false + /@vueuse/router@10.3.0(vue-router@4.2.4)(vue@3.3.4): resolution: {integrity: sha512-WCx/BAxO0eInuOcyNRBxDLS16tnNqzdaR6/babg6AUgAIL0TCfmHBh46wJa6hhg+NMGjd6HzCaktxBasp+0c0A==} peerDependencies: @@ -7225,6 +7303,15 @@ packages: - vue dev: false + /@vueuse/shared@10.7.1(vue@3.3.4): + resolution: {integrity: sha512-v0jbRR31LSgRY/C5i5X279A/WQjD6/JsMzGa+eqt658oJ75IvQXAeONmwvEMrvJQKnRElq/frzBR7fhmWY5uLw==} + dependencies: + vue-demi: 0.14.6(vue@3.3.4) + transitivePeerDependencies: + - '@vue/composition-api' + - vue + dev: false + /@webassemblyjs/ast@1.11.6: resolution: {integrity: sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==} dependencies: @@ -8181,7 +8268,6 @@ packages: /camelcase@5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} engines: {node: '>=6'} - dev: true /camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} @@ -8400,7 +8486,6 @@ packages: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 6.2.0 - dev: true /cliui@7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} @@ -8978,7 +9063,6 @@ packages: /decamelize@1.2.0: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} - dev: true /decimal.js@10.4.2: resolution: {integrity: sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==} @@ -9192,6 +9276,10 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dev: true + /dijkstrajs@1.0.3: + resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} + dev: false + /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -9367,6 +9455,10 @@ packages: engines: {node: '>= 4'} dev: true + /encode-utf8@1.0.3: + resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} + dev: false + /encodeurl@1.0.2: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} @@ -10608,7 +10700,6 @@ packages: dependencies: locate-path: 5.0.0 path-exists: 4.0.0 - dev: true /find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} @@ -12579,7 +12670,6 @@ packages: engines: {node: '>=8'} dependencies: p-locate: 4.1.0 - dev: true /locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} @@ -13581,7 +13671,6 @@ packages: engines: {node: '>=6'} dependencies: p-try: 2.2.0 - dev: true /p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} @@ -13609,7 +13698,6 @@ packages: engines: {node: '>=8'} dependencies: p-limit: 2.3.0 - dev: true /p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} @@ -13655,7 +13743,6 @@ packages: /p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} - dev: true /pac-proxy-agent@7.0.1: resolution: {integrity: sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==} @@ -13773,7 +13860,6 @@ packages: /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - dev: true /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} @@ -13958,6 +14044,11 @@ packages: pathe: 1.1.1 dev: true + /pngjs@5.0.0: + resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} + engines: {node: '>=10.13.0'} + dev: false + /polished@4.2.2: resolution: {integrity: sha512-Sz2Lkdxz6F2Pgnpi9U5Ng/WdWAUZxmHrNPoVlm3aAemxoy2Qy7LGjQg4uf8qKelDAUW94F4np3iH2YPf2qefcQ==} engines: {node: '>=10'} @@ -14583,6 +14674,17 @@ packages: - utf-8-validate dev: true + /qrcode@1.5.3: + resolution: {integrity: sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==} + engines: {node: '>=10.13.0'} + hasBin: true + dependencies: + dijkstrajs: 1.0.3 + encode-utf8: 1.0.3 + pngjs: 5.0.0 + yargs: 15.4.1 + dev: false + /qs@6.11.0: resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} engines: {node: '>=0.6'} @@ -14996,7 +15098,6 @@ packages: /require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} - dev: true /requireindex@1.2.0: resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==} @@ -15427,7 +15528,6 @@ packages: /set-blocking@2.0.0: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - dev: true /set-function-length@1.1.1: resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} @@ -17288,6 +17388,21 @@ packages: vue: 3.3.4 dev: false + /vue-demi@0.14.6(vue@3.3.4): + resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + dependencies: + vue: 3.3.4 + dev: false + /vue-docgen-api@4.75.1(vue@3.3.4): resolution: {integrity: sha512-MECZ3uExz+ssmhD/2XrFoQQs93y17IVO1KDYTp8nr6i9GNrk67AAto6QAtilW1H/pTDPMkQxJ7w/25ZIqVtfAA==} peerDependencies: @@ -17612,7 +17727,6 @@ packages: /which-module@2.0.0: resolution: {integrity: sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==} - dev: true /which-pm@2.0.0: resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} @@ -17851,7 +17965,6 @@ packages: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: true /wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} @@ -17946,7 +18059,6 @@ packages: /y18n@4.0.3: resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} - dev: true /y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} @@ -17988,7 +18100,6 @@ packages: dependencies: camelcase: 5.3.1 decamelize: 1.2.0 - dev: true /yargs-parser@20.2.9: resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} @@ -18014,7 +18125,6 @@ packages: which-module: 2.0.0 y18n: 4.0.3 yargs-parser: 18.1.3 - dev: true /yargs@16.2.0: resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} diff --git a/console/src/components/login/LoginForm.vue b/console/src/components/login/LoginForm.vue index 4435b45251..9a25b52a20 100644 --- a/console/src/components/login/LoginForm.vue +++ b/console/src/components/login/LoginForm.vue @@ -11,6 +11,8 @@ import { submitForm } from "@formkit/core"; import { JSEncrypt } from "jsencrypt"; import { apiClient } from "@/utils/api-client"; import { useI18n } from "vue-i18n"; +import { ERROR_MFA_REQUIRED_TYPE } from "@/constants/error-types"; +import MfaForm from "./MfaForm.vue"; const { t } = useI18n(); @@ -68,6 +70,7 @@ const handleLogin = async () => { withCredentials: true, headers: { "Content-Type": "application/x-www-form-urlencoded", + "X-Requested-With": "XMLHttpRequest", }, } ); @@ -92,7 +95,16 @@ const handleLogin = async () => { return; } - const { title: errorTitle, detail: errorDetail } = e.response?.data || {}; + const { + title: errorTitle, + detail: errorDetail, + type: errorType, + } = e.response?.data || {}; + + if (errorType === ERROR_MFA_REQUIRED_TYPE) { + mfaRequired.value = true; + return; + } if (errorTitle || errorDetail) { Toast.error(errorDetail || errorTitle); @@ -117,51 +129,57 @@ onMounted(() => { const inputClasses = { outer: "!py-3 first:!pt-0 last:!pb-0", }; + +// mfa +const mfaRequired = ref(false); diff --git a/console/src/components/login/MfaForm.vue b/console/src/components/login/MfaForm.vue new file mode 100644 index 0000000000..9a82c95d2b --- /dev/null +++ b/console/src/components/login/MfaForm.vue @@ -0,0 +1,72 @@ + + + diff --git a/console/src/constants/error-types.ts b/console/src/constants/error-types.ts new file mode 100644 index 0000000000..447fe61bbc --- /dev/null +++ b/console/src/constants/error-types.ts @@ -0,0 +1 @@ +export const ERROR_MFA_REQUIRED_TYPE = "https://halo.run/probs/2fa-required"; diff --git a/console/src/utils/api-client.ts b/console/src/utils/api-client.ts index a0871441a7..217defaab5 100644 --- a/console/src/utils/api-client.ts +++ b/console/src/utils/api-client.ts @@ -45,6 +45,7 @@ import { NotificationHaloRunV1alpha1NotifierDescriptorApi, ApiSecurityHaloRunV1alpha1PersonalAccessTokenApi, SecurityHaloRunV1alpha1PersonalAccessTokenApi, + ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi, UcApiContentHaloRunV1alpha1AttachmentApi, UcApiContentHaloRunV1alpha1PostApi, UcApiContentHaloRunV1alpha1SnapshotApi, @@ -247,6 +248,11 @@ function setupApiClient(axios: AxiosInstance) { baseURL, axios ), + twoFactor: new ApiSecurityHaloRunV1alpha1AuthenticationTwoFactorApi( + undefined, + baseURL, + axios + ), uc: { post: new UcApiContentHaloRunV1alpha1PostApi(undefined, baseURL, axios), attachment: new UcApiContentHaloRunV1alpha1AttachmentApi( diff --git a/console/uc-src/modules/profile/Profile.vue b/console/uc-src/modules/profile/Profile.vue index 0ed9097b99..2eb11e5f27 100644 --- a/console/uc-src/modules/profile/Profile.vue +++ b/console/uc-src/modules/profile/Profile.vue @@ -22,6 +22,7 @@ import DetailTab from "./tabs/Detail.vue"; import PersonalAccessTokensTab from "./tabs/PersonalAccessTokens.vue"; import { useRouteQuery } from "@vueuse/router"; import NotificationPreferences from "./tabs/NotificationPreferences.vue"; +import TwoFactor from "./tabs/TwoFactor.vue"; const { t } = useI18n(); @@ -79,6 +80,12 @@ const tabs: UserTab[] = [ component: markRaw(PersonalAccessTokensTab), priority: 30, }, + { + id: "2fa", + label: "两步验证", + component: markRaw(TwoFactor), + priority: 40, + }, ]; const tabbarItems = computed(() => { diff --git a/console/uc-src/modules/profile/tabs/TwoFactor.vue b/console/uc-src/modules/profile/tabs/TwoFactor.vue new file mode 100644 index 0000000000..699dbcf270 --- /dev/null +++ b/console/uc-src/modules/profile/tabs/TwoFactor.vue @@ -0,0 +1,128 @@ + + + diff --git a/console/uc-src/modules/profile/tabs/components/PasswordValidationForm.vue b/console/uc-src/modules/profile/tabs/components/PasswordValidationForm.vue new file mode 100644 index 0000000000..115033063f --- /dev/null +++ b/console/uc-src/modules/profile/tabs/components/PasswordValidationForm.vue @@ -0,0 +1,27 @@ + + + diff --git a/console/uc-src/modules/profile/tabs/components/TotpConfigureModal.vue b/console/uc-src/modules/profile/tabs/components/TotpConfigureModal.vue new file mode 100644 index 0000000000..ca02cb544c --- /dev/null +++ b/console/uc-src/modules/profile/tabs/components/TotpConfigureModal.vue @@ -0,0 +1,113 @@ + + + diff --git a/console/uc-src/modules/profile/tabs/components/TotpDeletionModal.vue b/console/uc-src/modules/profile/tabs/components/TotpDeletionModal.vue new file mode 100644 index 0000000000..5c013e54fb --- /dev/null +++ b/console/uc-src/modules/profile/tabs/components/TotpDeletionModal.vue @@ -0,0 +1,59 @@ + + + diff --git a/console/uc-src/modules/profile/tabs/components/TwoFactorDisableModal.vue b/console/uc-src/modules/profile/tabs/components/TwoFactorDisableModal.vue new file mode 100644 index 0000000000..f6070aaf7c --- /dev/null +++ b/console/uc-src/modules/profile/tabs/components/TwoFactorDisableModal.vue @@ -0,0 +1,59 @@ + + + diff --git a/console/uc-src/modules/profile/tabs/components/TwoFactorEnableModal.vue b/console/uc-src/modules/profile/tabs/components/TwoFactorEnableModal.vue new file mode 100644 index 0000000000..6220409543 --- /dev/null +++ b/console/uc-src/modules/profile/tabs/components/TwoFactorEnableModal.vue @@ -0,0 +1,59 @@ + + +