{"version":3,"file":"captcha.obs.js","sources":["../../../Framework/Controls/captcha.obs"],"sourcesContent":["<!-- Copyright by the Spark Development Network; Licensed under the Rock Community License -->\r\n<template>\r\n    <RockFormField v-bind=\"fieldProps\" :rules=\"computedRules\" name=\"captchaContent\" :modelValue=\"internalValue\">\r\n        <div class=\"control-wrapper\">\r\n            <div :id=\"turnstileBoxId\"></div>\r\n        </div>\r\n    </RockFormField>\r\n</template>\r\n\r\n<script setup lang=\"ts\">\r\n    import { PropType, computed, onMounted, onUnmounted, ref, } from \"vue\";\r\n    import RockFormField from \"@Obsidian/Controls/rockFormField.obs\";\r\n    import { useHttp } from \"@Obsidian/Utility/http\";\r\n    import { ValidationResult, containsRequiredRule, normalizeRules } from \"@Obsidian/ValidationRules\";\r\n    import { standardRockFormFieldProps, useStandardRockFormFieldProps } from \"@Obsidian/Utility/component\";\r\n    import { CaptchaControlConfigurationBag } from \"@Obsidian/ViewModels/Rest/Controls/captchaControlConfigurationBag\";\r\n    import { CaptchaControlTokenValidateTokenResultBag } from \"@Obsidian/ViewModels/Rest/Controls/captchaControlTokenValidateTokenResultBag\";\r\n    import { CaptchaControlValidateTokenOptionsBag } from \"@Obsidian/ViewModels/Rest/Controls/captchaControlValidateTokenOptionsBag\";\r\n    import { loadJavaScriptAsync } from \"@Obsidian/Utility/page\";\r\n    import { newGuid } from \"@Obsidian/Utility/guid\";\r\n    import { PromiseCompletionSource } from \"@Obsidian/Utility/promiseUtils\";\r\n\r\n    interface ITurnstile {\r\n        render(elementQuery: string, options: unknown): string;\r\n        reset(widgetId: string): void;\r\n        remove(widgetId: string): void;\r\n    }\r\n\r\n    const props = defineProps({\r\n        /**\r\n         * If enabled, then validation with the server will be performed. This\r\n         * only validates the token, it does not provide a secure way to submit\r\n         * data and know it is not from a bot. When the validation has completed\r\n         * the `tokenValidated` event will be emitted.\r\n         */\r\n        performValidation: {\r\n            type: Boolean as PropType<boolean>,\r\n            default: false\r\n        },\r\n\r\n        ...standardRockFormFieldProps\r\n    });\r\n\r\n    const emit = defineEmits<{\r\n        (e: \"tokenValidated\", isValid: boolean): void\r\n    }>();\r\n\r\n    defineExpose({\r\n        getToken,\r\n        refreshToken\r\n    });\r\n\r\n    // #region Values\r\n\r\n    const fieldProps = useStandardRockFormFieldProps(props);\r\n    const internalValue = ref(\"\");\r\n    const http = useHttp();\r\n    const widgetId = ref(\"\");\r\n    const turnstileBoxId = `turnstile-box-${newGuid()}`;\r\n    let turnstile: ITurnstile | undefined;\r\n\r\n    let captchaPromiseSource = new PromiseCompletionSource<string | undefined>();\r\n\r\n    // #endregion\r\n\r\n    // #region Computed\r\n\r\n    const computedRules = computed(() => {\r\n        const rules = normalizeRules(props.rules);\r\n\r\n        if (containsRequiredRule(rules)) {\r\n            rules.push(requiredValidator);\r\n        }\r\n\r\n        return rules;\r\n    });\r\n\r\n    // #endregion\r\n\r\n    // #region Functions\r\n\r\n    /**\r\n     * Get the control configuration from the server.\r\n     */\r\n    async function getConfiguration(): Promise<CaptchaControlConfigurationBag | undefined> {\r\n        try {\r\n            const result = await http.post<CaptchaControlConfigurationBag>(\"/api/v2/Controls/CaptchaControlGetConfiguration\");\r\n\r\n            if (result.isSuccess && result.data) {\r\n                return result.data;\r\n            }\r\n            else {\r\n                console.error(result.errorMessage ?? \"Unknown error while loading captcha configuration.\");\r\n            }\r\n        }\r\n        catch (error) {\r\n            console.error(\"Unknown error while loading captcha configuration.\");\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Get validate the token with the server. This function is not currently\r\n     * used but is being left behind for later use by the captcha field type.\r\n     */\r\n    async function validateToken(token: string): Promise<CaptchaControlTokenValidateTokenResultBag | undefined> {\r\n        const options: CaptchaControlValidateTokenOptionsBag = {\r\n            token: token\r\n        };\r\n\r\n        try {\r\n            const result = await http.post<CaptchaControlTokenValidateTokenResultBag>(\"/api/v2/Controls/CaptchaControlValidateToken\", undefined, options);\r\n\r\n            if (result.isSuccess && result.data) {\r\n                return result.data;\r\n            }\r\n            else {\r\n                console.error(result.errorMessage ?? \"Unknown error while validating token.\");\r\n            }\r\n        }\r\n        catch (error) {\r\n            console.error(\"Unknown error while validating token.\");\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Gets a promise that will be resolved once the token becomes available.\r\n     * The returned token can only be used once, so if you need to make another\r\n     * call to validate the token you should call `refreshToken()` after calling\r\n     * this method.\r\n     */\r\n    function getToken(): Promise<string | undefined> {\r\n        return captchaPromiseSource.promise;\r\n    }\r\n\r\n    /**\r\n     * Begins refreshing the token so it can be used again.\r\n     */\r\n    function refreshToken(): void {\r\n        if (widgetId.value && turnstile) {\r\n            captchaPromiseSource.resolve(undefined);\r\n            captchaPromiseSource = new PromiseCompletionSource<string | undefined>();\r\n            internalValue.value = \"\";\r\n            turnstile.reset(widgetId.value);\r\n        }\r\n    }\r\n\r\n    /**\r\n    * Renders the captcha control in the selected element after the turnstile script has been injected.\r\n    */\r\n    function renderCaptchaControl(siteKey: string): void {\r\n        if (turnstile) {\r\n            widgetId.value = turnstile.render(`#${turnstileBoxId}`, {\r\n                sitekey: siteKey,\r\n                \"callback\": callback,\r\n                \"error-callback\": errorCallback,\r\n                \"expired-callback\": expiredCallback\r\n            });\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Callback function invoked upon success of the challenge. The callback is passed a token that can be validated.\r\n     */\r\n    async function callback(response: string): Promise<void> {\r\n        if (props.performValidation) {\r\n            const result = await validateToken(response);\r\n\r\n            emit(\"tokenValidated\", result?.isTokenValid ?? false);\r\n            internalValue.value = result?.isTokenValid ? response : \"\";\r\n        }\r\n        else {\r\n            captchaPromiseSource.resolve(response);\r\n            internalValue.value = response;\r\n        }\r\n    }\r\n\r\n    /**\r\n     * Callback function invoked when there is an error (e.g. network error or the challenge failed).\r\n     * The callback is passed a error code detailing the nature of the error https://developers.cloudflare.com/turnstile/reference/client-side-errors/\r\n     */\r\n    function errorCallback(error: string): void {\r\n        console.error(\"Captcha challenge failed.\", error);\r\n        internalValue.value = \"\";\r\n        captchaPromiseSource.reject(\"Captcha challenge failed.\");\r\n    }\r\n\r\n    /**\r\n    * Callback function invoked when the token expires and does not reset the widget.\r\n    */\r\n    function expiredCallback(): void {\r\n        refreshToken();\r\n    }\r\n\r\n    /**\r\n     * Ensures that the Captcha was solved and verified successfully.\r\n     */\r\n    function requiredValidator(value: unknown): ValidationResult {\r\n        const invalidMessage = \"is required\";\r\n\r\n        if (!value) {\r\n            return invalidMessage;\r\n        }\r\n\r\n        return true;\r\n    }\r\n\r\n    // #endregion\r\n\r\n    onMounted(async () => {\r\n        const config = await getConfiguration();\r\n        if (config?.siteKey) {\r\n            await loadJavaScriptAsync(\"https://challenges.cloudflare.com/turnstile/v0/api.js\", () => !!window[\"turnstile\"]);\r\n            turnstile = window[\"turnstile\"];\r\n            renderCaptchaControl(config.siteKey);\r\n        }\r\n        else {\r\n            // If captcha is not enabled globally then resolve to an empty string.\r\n            captchaPromiseSource.resolve(\"\");\r\n        }\r\n    });\r\n\r\n    onUnmounted(() => {\r\n        if (widgetId.value && turnstile) {\r\n            turnstile.remove(widgetId.value);\r\n        }\r\n    });\r\n</script>\r\n"],"names":["expose","getToken","refreshToken","fieldProps","useStandardRockFormFieldProps","props","internalValue","ref","http","useHttp","widgetId","turnstileBoxId","concat","newGuid","turnstile","captchaPromiseSource","PromiseCompletionSource","computedRules","computed","rules","normalizeRules","containsRequiredRule","push","requiredValidator","getConfiguration","_getConfiguration","apply","arguments","_asyncToGenerator","result","post","isSuccess","data","_result$errorMessage","console","error","errorMessage","validateToken","_x","_validateToken","token","options","undefined","_result$errorMessage2","promise","value","resolve","reset","renderCaptchaControl","siteKey","render","sitekey","callback","errorCallback","expiredCallback","_x2","_callback","response","performValidation","_result$isTokenValid","emit","isTokenValid","reject","invalidMessage","onMounted","config","loadJavaScriptAsync","window","onUnmounted","remove"],"mappings":"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"}