Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# generated from manifests external_dependencies
altcha
127 changes: 127 additions & 0 deletions website_altcha/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
========================
Privacy Friendly Captcha
========================

..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:72f381043be58f2d2154c68ba7152e620c995760d9ce8280c5d49e161adbf924
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fwebsite-lightgray.png?logo=github
:target: https://github.com/OCA/website/tree/17.0/website_altcha
:alt: OCA/website
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/website-17-0/website-17-0-website_altcha
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/builds?repo=OCA/website&target_branch=17.0
:alt: Try me on Runboat

|badge1| |badge2| |badge3| |badge4| |badge5|

This module allows to use a Captcha System completly handled by Odoo.

It relies on Altcha (https://altcha.org), an OpenSource captcha
alternative.

**Table of contents**

.. contents::
:local:

Use Cases / Context
===================

Currently, Odoo provides 2 options:

- Google Recaptcha relies on tracking of the user. It implies cookies
- Cloudfare Turnstile relies on signals of the browser so it is less
GDPR problematic. However, it relies on a third party infrastructure.
The decision is made from a probabilistic perspective (likely a human)

With this new module, everything relies on our own system with no
cookies, no tracking and no network calls.

The way to solve it is to add a deterministic puzzle to solve. Bots need
to spend more CPU, making it costly at scale.

Configuration
=============

Go to Configuration/Website, check "Enable Altcha" under "Privacy". Some
extra parameters will appear with all the ALTCHA information. This
parameters are website dependent.

- ``altcha_key``: This key is made to create the challenge and review it
later

Also, the system adds the option to use some extra parameters:

- ``altcha_secret_key``: Key used to use deterministic mode. Using it
will make it faster from a server perspective.
- ``altcha_algorithm``: Algorithm used, by default ``PBKDF2/SHA-512``,
however, we can use:

- Fast ones only for testing purposes: ``SHA-256``, ``SHA-384``,
``SHA-512``
- Good by default: ``PBKDF2/SHA-256``, ``PBKDF2/SHA-384``,
``PBKDF2/SHA-512``
- Memory Hard: ``SCRYPT``. To be implemented
- Memory Hard (it required argon2-cffi): ``ARGON2ID``. To be
implemented

- ``altcha_timeout``: Number of minutes that we will trust the key, by
default 5
- ``altcha_cost``: Cost of the challenge. By default, 5000

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/OCA/website/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/OCA/website/issues/new?body=module:%20website_altcha%0Aversion:%2017.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
-------

* Dixmit

Contributors
------------

- `Dixmit <https://www.dixmit.com>`__

- Enric Tobella
- Luís David Rodríguez

Maintainers
-----------

This module is maintained by the OCA.

.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org

OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.

This module is part of the `OCA/website <https://github.com/OCA/website/tree/17.0/website_altcha>`_ project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
2 changes: 2 additions & 0 deletions website_altcha/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import controllers
from . import models
34 changes: 34 additions & 0 deletions website_altcha/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Copyright 2025 Dixmit
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

{
"name": "Privacy Friendly Captcha",
"summary": """Use self hosted privacy friendly captcha for
verifying website users are not bots""",
"version": "17.0.1.0.0",
"license": "AGPL-3",
"author": "Dixmit,Odoo Community Association (OCA)",
"website": "https://github.com/OCA/website",
"depends": [
"website",
],
"assets": {
"web.assets_frontend": [
"website_altcha/static/src/**/*.esm.js",
"website_altcha/static/src/**/*.xml",
"website_altcha/static/src/**/*.scss",
],
"web.altcha_libs": [
"website_altcha/static/lib/altcha.js",
"website_altcha/static/lib/altcha-l10n.js",
"website_altcha/static/lib/altcha.css",
],
},
"external_dependencies": {
"python": ["altcha"],
},
"data": [
"security/ir.model.access.csv",
"views/res_config_settings_views.xml",
],
}
1 change: 1 addition & 0 deletions website_altcha/controllers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import altcha
39 changes: 39 additions & 0 deletions website_altcha/controllers/altcha.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import json
import secrets
from datetime import timedelta

import altcha.v2 as altcha

from odoo import fields, http
from odoo.http import request


class AltchaController(http.Controller):
@http.route("/altcha", type="http", auth="public", website=True)
def generate_altcha_challenge(self):
timeout = int(request.website.sudo().altcha_timeout or 5)
cost = int(request.website.sudo().altcha_cost or 1_000)
algorithm = request.website.sudo().altcha_algorithm or "PBKDF2/SHA-512"
expires = fields.Datetime.now() + timedelta(minutes=timeout)
key = request.website.sudo().altcha_key
secret_key = request.website.sudo().altcha_private_key
parameters = {
"algorithm": algorithm,
"cost": cost,
"hmac_secret": key,
"expires_at": expires,
}
if secret_key:
parameters["hmac_key_secret"] = secret_key
parameters["counter"] = secrets.randbelow(cost) + cost
challenge = altcha.create_challenge(**parameters)
request.env["altcha.key"].sudo().create(
{
"key": request.env["ir.http"]._get_altcha_key(challenge.signature),
"expires_at": expires,
}
)
return request.make_response(
json.dumps(challenge.to_dict()),
headers=[("Content-Type", "application/json")],
)
178 changes: 178 additions & 0 deletions website_altcha/i18n/it.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * website_altcha
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 18.0\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-06-03 09:46+0000\n"
"Last-Translator: mymage <stefano.consolaro@mymage.it>\n"
"Language-Team: none\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=n != 1;\n"
"X-Generator: Weblate 5.15.2\n"

#. module: website_altcha
#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form
msgid "Add Altcha functionality"
msgstr "Aggiungi funzionalità Altcha"

#. module: website_altcha
#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form
msgid "Algorithm"
msgstr "Algoritmo"

#. module: website_altcha
#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_algorithm
#: model:ir.model.fields,field_description:website_altcha.field_website__altcha_algorithm
msgid "Altcha Algorithm"
msgstr "Algoritmo Altcha"

#. module: website_altcha
#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_cost
#: model:ir.model.fields,field_description:website_altcha.field_website__altcha_cost
msgid "Altcha Cost"
msgstr "Costo Altcha"

#. module: website_altcha
#: model:ir.model,name:website_altcha.model_altcha_key
#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_key
#: model:ir.model.fields,field_description:website_altcha.field_website__altcha_key
msgid "Altcha Key"
msgstr "Chiave Altcha"

#. module: website_altcha
#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_private_key
#: model:ir.model.fields,field_description:website_altcha.field_website__altcha_private_key
msgid "Altcha Private Key"
msgstr "Chiave privata Altcha"

#. module: website_altcha
#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_timeout
#: model:ir.model.fields,field_description:website_altcha.field_website__altcha_timeout
msgid "Altcha Timeout"
msgstr "Timeout Altcha"

#. module: website_altcha
#: model:ir.model,name:website_altcha.model_res_config_settings
msgid "Config Settings"
msgstr "Impostazioni configurazione"

#. module: website_altcha
#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form
msgid "Cost"
msgstr "Costo"

#. module: website_altcha
#: model:ir.model.fields,help:website_altcha.field_res_config_settings__altcha_cost
#: model:ir.model.fields,help:website_altcha.field_website__altcha_cost
msgid ""
"Cost factor for the hashing algorithm.\n"
" For PBKDF2, this is the number of iterations.\n"
" Default is 5000 for PBKDF2/SHA-512."
msgstr ""
"Fattore di costo per l'algoritmo di hashing.\n"
" Per PBKDF2, questo rappresenta il numero di iterazioni.\n"
" Il valore predefinito è 5000 per PBKDF2/SHA-512."

#. module: website_altcha
#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__create_uid
msgid "Created by"
msgstr "Creato da"

#. module: website_altcha
#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__create_date
msgid "Created on"
msgstr "Creato il"

#. module: website_altcha
#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__display_name
msgid "Display Name"
msgstr "Nome visualizzato"

#. module: website_altcha
#: model:ir.model.fields,field_description:website_altcha.field_res_config_settings__altcha_enabled
msgid "Enable Altcha"
msgstr "Abilita Altcha"

#. module: website_altcha
#: model:ir.model.fields,help:website_altcha.field_res_config_settings__altcha_enabled
msgid "Enable Altcha functionality on the website."
msgstr "Abilita la funzionalità Altcha sul sito web."

#. module: website_altcha
#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__expires_at
msgid "Expires At"
msgstr "Scade alle"

#. module: website_altcha
#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form
msgid "HMAC key secret"
msgstr "Segreto chiave HMAC"

#. module: website_altcha
#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form
msgid "HMAC secret"
msgstr "Segreto HMAC"

#. module: website_altcha
#: model:ir.model,name:website_altcha.model_ir_http
msgid "HTTP Routing"
msgstr "Instradamento HTTP"

#. module: website_altcha
#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__id
msgid "ID"
msgstr "ID"

#. module: website_altcha
#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__key
msgid "Key"
msgstr "Chiave"

#. module: website_altcha
#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__write_uid
msgid "Last Updated by"
msgstr "Ultimo aggiornamento di"

#. module: website_altcha
#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__write_date
msgid "Last Updated on"
msgstr "Ultimo aggiornamento il"

#. module: website_altcha
#. odoo-python
#: code:addons/website_altcha/models/ir_http.py:0
msgid "Suspicious activity detected by Altcha"
msgstr "Attività sospetta rilevata da Altcha"

#. module: website_altcha
#: model:ir.model.constraint,message:website_altcha.constraint_altcha_key_key_uniq
msgid "The Altcha key must be unique."
msgstr "La chiave Altcha deve essere univoca."

#. module: website_altcha
#: model:ir.model.fields,help:website_altcha.field_res_config_settings__altcha_timeout
#: model:ir.model.fields,help:website_altcha.field_website__altcha_timeout
msgid "Time in minutes before a captcha expires. Default is 5 minutes."
msgstr ""
"Tempo in minuti prima della scadenza di un captcha. Predefinito 5 minuti."

#. module: website_altcha
#: model_terms:ir.ui.view,arch_db:website_altcha.res_config_settings_view_form
msgid "Timeout"
msgstr "Timeout"

#. module: website_altcha
#: model:ir.model.fields,field_description:website_altcha.field_altcha_key__used
msgid "Used"
msgstr "Usata"

#. module: website_altcha
#: model:ir.model,name:website_altcha.model_website
msgid "Website"
msgstr "Sito web"
Loading
Loading