Files
shcool/odoosh_connector
2026-09-10 19:36:08 +08:00
..
2026-09-10 19:36:08 +08:00
2026-09-10 19:36:08 +08:00
2026-09-10 19:36:08 +08:00
2026-09-10 19:36:08 +08:00
2026-09-10 19:36:08 +08:00
2026-09-10 19:36:08 +08:00
2026-09-10 19:36:08 +08:00
2026-09-10 19:36:08 +08:00
2026-09-10 19:36:08 +08:00
2026-09-10 19:36:08 +08:00

OdooshCN Lab Environments

Syncs the users of this Odoo instance to an OdooshCN platform and gives every user a one-click entry to their own lab environment.

Install

  1. Add the parent folder to addons_path:

    addons_path = ...,D:\odoo_project\odoo18-2\odoo\custom_project\school-python
    
  2. Restart Odoo, update the app list and install OdooshCN Lab Environments.

Configure

1. Create an access token on OdooshCN

Sign in as a super administrator, open the user menu in the top right corner and choose Access tokens, then create one:

Field Suggested value
Name Odoo course system
Source school (synced users are recorded under this source)
Organisation where the users should land
Scopes tick all four
Maximum grantable role Organisation manager, if any user needs that role
Instances per user 1
Allow deleting users on, if deleting a user here should delete the platform account
Allow other organisations / platform administrator off

The token is shown once, so copy it immediately. Scopes can be edited later without changing the token value.

2. Fill it in here

Settings > General Settings > OdooshCN Lab Environments:

  1. Turn on Enable sync.
  2. Enter the platform URL and the token, then press Test connection. It validates the URL and token only, reports the organisation, the scopes and the limits, and warns when a scope is missing. For local testing use http://127.0.0.1:port rather than localhost: on Windows localhost resolves to IPv6 first while WSL2 and Docker only forward IPv4, and every request would wait out a 20 second timeout. The module rewrites localhost anyway, but an explicit address is safer.
  3. Adjust the environment defaults if needed and save.

That is all. There is nothing to configure per user.

Daily use

New users are synced automatically. Everything the platform knows about a user sits on the Lab Environment tab of the user form:

Field Meaning Default
Sync to lab platform Master switch for this user On
Platform username override Empty derives it from the login Empty
Organisation Platform organisation slug Empty (default)
Platform role Regular user or platform administrator Regular user
Role in organisation Tester / Developer / Organisation manager Developer
Web Shell, Enterprise edition, Auto-provision Switches On / Off / On
Instance limit, Extra database limit 0 means unlimited 1 / 2
Platform menus Overview / Git / AI / Backups Off / Off / On / Off

Select several users in the list and use the Actions menu to sync, enable or disable them in bulk.

Users open their environment from the Lab Environment menu. The platform console - the instance list and the instance detail page - is embedded in a frame on that same page, so nobody leaves the course system, with an Open in a new tab button for a full window. The instance's own Odoo always opens in a new tab: nesting a whole Odoo inside another one stacks three navigation bars and two sidebars.

For the frame to work the platform has to allow being embedded by this Odoo. Its console answers X-Frame-Options: SAMEORIGIN by default and the frame stays blank; the platform administrator drops a file console-frame-odoo.inc into <data dir>/nginx/ naming this server, then reloads the platform's web container:

add_header Content-Security-Policy "frame-ancestors 'self' http://school.example.com:8069" always;

The value has to match what users actually have in the address bar, scheme and port included: http://localhost:8069 does not cover http://the-machine-name:8069.

What happens when

In Odoo On the platform
Create a user Account created, sync switch turned on, environment provisioned
Update a user Pushed when the switch is on, ignored when it is off
Archive a user Account deactivated, instances stopped, nothing deleted
Restore an archived user Account activated again
Delete a user Account deleted; the instances move to the platform recycle bin, where the data stays recoverable for the retention period

Deleting requires the access token to allow it. Without that permission the platform refuses and the queue row shows delete_not_allowed; the account is then only deactivated.

Portal users and built-in Odoo accounts (OdooBot, the public user, the portal template and the new-user default template) are never synced.

How syncing works

The hooks only write a row into odoosh.sync.log; no HTTP happens inside a user request. A dedicated thread pushes right after the transaction commits, using its own database connection, so a failure there can never affect what was already saved.

Three paths back each other up:

Path Trigger Purpose
Background thread Right after commit The user barely notices a delay
Queue cron Every minute Takes over when the thread was killed with the worker, and drives the retry back-off
User scan Inside that same cron, every 30 minutes Walks users changed since the last scan and compares fingerprints

The scan has no cron of its own: it is cheap, but Odoo's cron pool is shared by the whole database (max_cron_threads, 2 by default), so a slot costs more than the scan does. Set the system parameter odoosh.scan_interval_minutes to change the interval, or to 0 to turn the scan off and rely on the hooks alone.

Cost control: only login, name, active, the sync switch and the platform permission fields trigger a push, so changing an avatar or a preference does not; the scan reads at most 200 users per round through an index; identical content is never pushed twice.

A daily reconciliation sends the full list of users so the platform can deactivate accounts that disappeared. An empty local list is skipped, and the platform refuses a list that would deactivate an implausible share of the accounts.

Security

  • The token is stored in a system parameter, readable by system administrators only, and the settings page shows only a mask plus the last four characters.
  • The identity sent to the platform always comes from the current session, never from a request parameter. Otherwise a user could edit a URL and land in somebody else's environment.
  • Entry URLs are short lived and single use: they are redirected to immediately, never stored and never logged.

Adjusting the code

Everything a user gets is a field, so day-to-day changes need no code. If the mapping itself has to change, it lives in models/res_users.py:

  • _odoosh_payload() builds the user payload from the fields.
  • _odoosh_env_spec() builds the environment specification.