Skip to content

Commit fffa5e1

Browse files
[ADD] auth_session_scheduled_logout
1 parent 28e8371 commit fffa5e1

15 files changed

Lines changed: 791 additions & 0 deletions

File tree

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
========================
2+
Scheduled Session Logout
3+
========================
4+
5+
..
6+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
7+
!! This file is generated by oca-gen-addon-readme !!
8+
!! changes will be overwritten. !!
9+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
10+
!! source digest: sha256:e95d136b9f41fab8af17e33dc5863aa6ee89f13c45cc001d4617cbbc86c88359
11+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
12+
13+
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
14+
:target: https://odoo-community.org/page/development-status
15+
:alt: Beta
16+
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
17+
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
18+
:alt: License: AGPL-3
19+
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--auth-lightgray.png?logo=github
20+
:target: https://github.com/OCA/server-auth/tree/18.0/auth_session_scheduled_logout
21+
:alt: OCA/server-auth
22+
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
23+
:target: https://translation.odoo-community.org/projects/server-auth-18-0/server-auth-18-0-auth_session_scheduled_logout
24+
:alt: Translate me on Weblate
25+
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
26+
:target: https://runboat.odoo-community.org/builds?repo=OCA/server-auth&target_branch=18.0
27+
:alt: Try me on Runboat
28+
29+
|badge1| |badge2| |badge3| |badge4| |badge5|
30+
31+
This module forces logout of all active user sessions on a schedule
32+
(defaults to every Sunday at 23:00), regardless of user activity. It's
33+
not an inactivity timeout: even users actively working are logged out at
34+
scheduled time. At the scheduled time every targeted browser session
35+
becomes invalid. On next request the user is redirected to the login
36+
page.
37+
38+
Installing or upgrading the module logs nobody out: the timestamp is
39+
empty for existing users, and leaves the token untouched while it is
40+
empty, so current sessions keep working until the scheduled job runs.
41+
Users can be excluded from the logout by adding them to the security
42+
group *Exempt from Scheduled Session Logout*.
43+
44+
**Table of contents**
45+
46+
.. contents::
47+
:local:
48+
49+
Configuration
50+
=============
51+
52+
**Schedule**
53+
54+
Go to *Settings > Technical > Automation > Scheduled Actions* and open
55+
*Scheduled Session Logout: revoke all sessions*.
56+
57+
- By default it runs **every Sunday at 23:00 UTC**.
58+
- Adjust *Next Execution Date* and the interval to fit your needs.
59+
- Deactivate the scheduled action to disable the feature entirely.
60+
61+
**Excluding users**
62+
63+
To keep some users logged in when the job runs, add them to the security
64+
group *Exempt from Scheduled Session Logout*. The group appears as a
65+
checkbox in the *Other* section of the user form (*Settings > Users*).
66+
67+
Bug Tracker
68+
===========
69+
70+
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-auth/issues>`_.
71+
In case of trouble, please check there if your issue has already been reported.
72+
If you spotted it first, help us to smash it by providing a detailed and welcomed
73+
`feedback <https://github.com/OCA/server-auth/issues/new?body=module:%20auth_session_scheduled_logout%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
74+
75+
Do not contact contributors directly about support or help with technical issues.
76+
77+
Credits
78+
=======
79+
80+
Authors
81+
-------
82+
83+
* ForgeFlow
84+
85+
Contributors
86+
------------
87+
88+
- ForgeFlow S.L. <contact@forgeflow.com>
89+
90+
- Laura Cazorla <laura.cazorla@forgeflow.com>
91+
92+
Maintainers
93+
-----------
94+
95+
This module is maintained by the OCA.
96+
97+
.. image:: https://odoo-community.org/logo.png
98+
:alt: Odoo Community Association
99+
:target: https://odoo-community.org
100+
101+
OCA, or the Odoo Community Association, is a nonprofit organization whose
102+
mission is to support the collaborative development of Odoo features and
103+
promote its widespread use.
104+
105+
This module is part of the `OCA/server-auth <https://github.com/OCA/server-auth/tree/18.0/auth_session_scheduled_logout>`_ project on GitHub.
106+
107+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from . import models
2+
from .hooks import post_init_hook
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright 2026 ForgeFlow S.L.
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
3+
4+
{
5+
"name": "Scheduled Session Logout",
6+
"summary": "Force logout of all active user sessions on a schedule",
7+
"version": "18.0.1.0.0",
8+
"category": "Tools",
9+
"author": "ForgeFlow, Odoo Community Association (OCA)",
10+
"website": "https://github.com/OCA/server-auth",
11+
"license": "AGPL-3",
12+
"depends": ["base"],
13+
"data": [
14+
"security/auth_session_scheduled_logout_groups.xml",
15+
"data/ir_cron_data.xml",
16+
],
17+
"post_init_hook": "post_init_hook",
18+
"installable": True,
19+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<!-- Copyright 2026 ForgeFlow S.L.
3+
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html). -->
4+
<odoo noupdate="1">
5+
<record id="cron_revoke_all_sessions" model="ir.cron">
6+
<field name="name">Scheduled Session Logout: revoke all sessions</field>
7+
<field name="model_id" ref="base.model_res_users" />
8+
<field name="state">code</field>
9+
<field name="code">model._cron_revoke_all_sessions()</field>
10+
<field name="interval_number">1</field>
11+
<field name="interval_type">weeks</field>
12+
<field name="nextcall">2099-01-04 23:00:00</field>
13+
<field name="active" eval="True" />
14+
</record>
15+
</odoo>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright 2026 ForgeFlow S.L.
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
3+
4+
import logging
5+
from datetime import datetime, time, timedelta
6+
7+
from odoo import fields
8+
9+
_logger = logging.getLogger(__name__)
10+
11+
12+
def post_init_hook(env):
13+
# Schedule the first run at the next Sunday 23:00 (UTC)
14+
cron = env.ref("auth_session_scheduled_logout.cron_revoke_all_sessions")
15+
if not cron:
16+
return
17+
now = fields.Datetime.now()
18+
ahead = (6 - now.weekday()) % 7
19+
next_call = datetime.combine(now.date() + timedelta(days=ahead), time(23, 0))
20+
if next_call <= now:
21+
next_call += timedelta(days=7)
22+
cron.nextcall = next_call
23+
_logger.info("Scheduled first session logout for %s UTC.", next_call)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import res_users
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Copyright 2026 ForgeFlow S.L.
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
3+
4+
import hmac
5+
import logging
6+
from hashlib import sha256
7+
8+
from odoo import api, fields, models
9+
10+
_logger = logging.getLogger(__name__)
11+
12+
13+
class ResUsers(models.Model):
14+
_inherit = "res.users"
15+
16+
auth_session_valid_from = fields.Datetime(
17+
string="Sessions Valid From",
18+
copy=False,
19+
readonly=True,
20+
help="Any browser session opened before this datetime is invalid: the "
21+
"user is redirected to the login page on their next request. The value "
22+
"is bumped by scheduled logout job and folded into the session token.",
23+
)
24+
25+
def _compute_session_token(self, sid):
26+
token = super()._compute_session_token(sid)
27+
valid_from = self.sudo().auth_session_valid_from
28+
if token and valid_from:
29+
token_encoded = token.encode("utf-8")
30+
valid_from_encoded = valid_from.isoformat().encode("utf-8")
31+
encoded = hmac.new(token_encoded, valid_from_encoded, sha256)
32+
token = encoded.hexdigest()
33+
return token
34+
35+
@api.model
36+
def _get_scheduled_logout_exempt_group(self):
37+
group_id = "auth_session_scheduled_logout.group_auth_session_no_sched_logout"
38+
group = self.env.ref(group_id, raise_if_not_found=False)
39+
return group or self.env["res.groups"]
40+
41+
@api.model
42+
def _get_users_to_logout(self):
43+
domain = []
44+
exempt_group = self._get_scheduled_logout_exempt_group()
45+
if exempt_group:
46+
domain.append(("groups_id", "not in", exempt_group.ids))
47+
users = self.search(domain)
48+
tech_users = self.browse()
49+
for xmlid in ("base.public_user", "base.default_user"):
50+
if self.env.ref(xmlid, raise_if_not_found=False):
51+
tech_users |= self.env.ref(xmlid, raise_if_not_found=False)
52+
return users - tech_users
53+
54+
@api.model
55+
def _cron_revoke_all_sessions(self):
56+
users = self._get_users_to_logout()
57+
if not users:
58+
return
59+
users.write({"auth_session_valid_from": fields.Datetime.now()})
60+
_logger.info("Scheduled logout: revoked sessions for %d user(s).", len(users))
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[build-system]
2+
requires = ["whool"]
3+
build-backend = "whool.buildapi"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
**Schedule**
2+
3+
Go to *Settings > Technical > Automation > Scheduled Actions* and open
4+
*Scheduled Session Logout: revoke all sessions*.
5+
6+
- By default it runs **every Sunday at 23:00 UTC**.
7+
- Adjust *Next Execution Date* and the interval to fit your needs.
8+
- Deactivate the scheduled action to disable the feature entirely.
9+
10+
**Excluding users**
11+
12+
To keep some users logged in when the job runs, add them to the security group
13+
*Exempt from Scheduled Session Logout*. The group appears as a checkbox in the
14+
*Other* section of the user form (*Settings > Users*).
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- ForgeFlow S.L. \<<contact@forgeflow.com>\>
2+
- Laura Cazorla \<<laura.cazorla@forgeflow.com>\>

0 commit comments

Comments
 (0)