Initial commit: Security packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:51 +02:00
commit bb469e4763
1399 changed files with 278378 additions and 0 deletions

View file

@ -0,0 +1,61 @@
odoo.define('google_recaptcha.ReCaptchaV3', function (require) {
"use strict";
const Class = require('web.Class');
const core = require('web.core');
const { session } = require('@web/session');
const { loadJS } = require('@web/core/assets');
const _t = core._t;
const ReCaptcha = Class.extend({
/**
* @override
*/
init: function () {
this._publicKey = session.recaptcha_public_key;
},
/**
* Loads the recaptcha libraries.
*
* @returns {Promise|boolean} promise if libs are loading else false if the reCaptcha key is empty.
*/
loadLibs: function () {
if (this._publicKey) {
this._recaptchaReady = loadJS(`https://www.recaptcha.net/recaptcha/api.js?render=${encodeURIComponent(this._publicKey)}`)
.then(() => new Promise(resolve => window.grecaptcha.ready(() => resolve())));
return this._recaptchaReady.then(() => !!document.querySelector('.grecaptcha-badge'));
}
return false;
},
/**
* Returns an object with the token if reCaptcha call succeeds
* If no key is set an object with a message is returned
* If an error occurred an object with the error message is returned
*
* @param {string} action
* @returns {Promise|Object}
*/
getToken: async function (action) {
if (!this._publicKey) {
return {
message: _t("No recaptcha site key set."),
};
}
await this._recaptchaReady;
try {
return {
token: await window.grecaptcha.execute(this._publicKey, {action: action})
};
} catch (_e) {
return {
error: _t("The recaptcha site key is invalid."),
};
}
},
});
return {
ReCaptcha: ReCaptcha,
};
});

View file

@ -0,0 +1,45 @@
odoo.define('google_recaptcha.signup', function (require) {
'use strict';
const publicWidget = require('web.public.widget');
const { ReCaptcha } = require('google_recaptcha.ReCaptchaV3');
const CaptchaFunctionality = {
events: {
submit: "_onSubmit",
},
init() {
this._super(...arguments);
this._recaptcha = new ReCaptcha();
},
async willStart() {
return this._recaptcha.loadLibs();
},
_onSubmit(ev) {
if (this._recaptcha._publicKey && !this.$el.find("input[name='recaptcha_token_response']").length) {
ev.preventDefault();
this._recaptcha.getToken(this.tokenName).then((tokenCaptcha) => {
this.$el.append(
`<input name="recaptcha_token_response" type="hidden" value="${tokenCaptcha.token}"/>`,
);
this.$el.submit();
});
}
},
};
publicWidget.registry.SignupCaptcha = publicWidget.Widget.extend({
...CaptchaFunctionality,
selector: ".oe_signup_form",
tokenName: "signup",
});
publicWidget.registry.ResetPasswordCaptcha = publicWidget.Widget.extend({
...CaptchaFunctionality,
selector: ".oe_reset_password_form",
tokenName: "password_reset",
});
});

View file

@ -0,0 +1,5 @@
// Hide google recaptcha V3 don't forget to add legal
// https://developers.google.com/recaptcha/docs/faq#id-like-to-hide-the-recaptcha-badge.-what-is-allowed
.grecaptcha-badge {
visibility: hidden;
}

View file

@ -0,0 +1,13 @@
// TODO adapt in master: Allow disabling reCAPTCHA without uninstalling the
// modules, instead of hiding the toggle.
.o_settings_container {
.o_setting_box {
[name="module_google_recaptcha"] {
pointer-events: none;
display: none;
}
label[for="module_google_recaptcha"] {
pointer-events: none;
}
}
}

View file

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<t t-name="google_recaptcha.recaptcha_legal_terms">
<small class="o_recaptcha_legal_terms">
Protected by reCAPTCHA,
<a href="https://policies.google.com/privacy" target="_blank">Privacy Policy</a>
&amp;
<a href="https://policies.google.com/terms" target="_blank">Terms of Service</a>
apply.
</small>
</t>
</odoo>