Skip to content

Commit 6ff5bb8

Browse files
committedJan 19, 2023
[MIG] session_db to 16.0
1 parent 5cc37f9 commit 6ff5bb8

File tree

11 files changed

+236
-149
lines changed

11 files changed

+236
-149
lines changed
 

‎session_db/README.rst

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
====================
2+
Store sessions in DB
3+
====================
4+
5+
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
6+
!! This file is generated by oca-gen-addon-readme !!
7+
!! changes will be overwritten. !!
8+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
9+
10+
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
11+
:target: https://odoo-community.org/page/development-status
12+
:alt: Beta
13+
.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png
14+
:target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html
15+
:alt: License: LGPL-3
16+
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github
17+
:target: https://github.com/OCA/server-tools/tree/16.0/session_db
18+
:alt: OCA/server-tools
19+
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
20+
:target: https://translation.odoo-community.org/projects/server-tools-16-0/server-tools-16-0-session_db
21+
:alt: Translate me on Weblate
22+
.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png
23+
:target: https://runbot.odoo-community.org/runbot/149/16.0
24+
:alt: Try me on Runbot
25+
26+
|badge1| |badge2| |badge3| |badge4| |badge5|
27+
28+
Store sessions in a database instead of the filesystem.
29+
30+
**Table of contents**
31+
32+
.. contents::
33+
:local:
34+
35+
Usage
36+
=====
37+
38+
Set this module in the server wide modules.
39+
40+
Set a ``SESSION_DB_URI`` environment variable as a full postgresql connection string,
41+
like ``postgres://user:passwd@server/db`` or ``db``.
42+
43+
It is recommended to use a dedicated database for this module, and possibly a dedicated
44+
postgres user for additional security.
45+
46+
Known issues / Roadmap
47+
======================
48+
49+
This module does not work with multi-threaded workers, so it requires workers > 0.
50+
51+
Bug Tracker
52+
===========
53+
54+
Bugs are tracked on `GitHub Issues <https://github.com/OCA/server-tools/issues>`_.
55+
In case of trouble, please check there if your issue has already been reported.
56+
If you spotted it first, help us smashing it by providing a detailed and welcomed
57+
`feedback <https://github.com/OCA/server-tools/issues/new?body=module:%20session_db%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
58+
59+
Do not contact contributors directly about support or help with technical issues.
60+
61+
Credits
62+
=======
63+
64+
Authors
65+
~~~~~~~
66+
67+
* Odoo SA
68+
* ACSONE SA/NV
69+
70+
Maintainers
71+
~~~~~~~~~~~
72+
73+
This module is maintained by the OCA.
74+
75+
.. image:: https://odoo-community.org/logo.png
76+
:alt: Odoo Community Association
77+
:target: https://odoo-community.org
78+
79+
OCA, or the Odoo Community Association, is a nonprofit organization whose
80+
mission is to support the collaborative development of Odoo features and
81+
promote its widespread use.
82+
83+
This module is part of the `OCA/server-tools <https://github.com/OCA/server-tools/tree/16.0/session_db>`_ project on GitHub.
84+
85+
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

‎session_db/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
import models
1+
from . import pg_session_store

‎session_db/__manifest__.py

+5-22
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,7 @@
1-
# -*- coding: utf-8 -*-
21
{
3-
'name': "Store sessions in DB",
4-
'description': """
5-
Storing sessions in DB
6-
- workls only with workers > 0
7-
- set the session_db parameter in the odoo config file
8-
- session_db parameter value is a full postgresql connection string, like user:passwd@server/db
9-
- choose another DB than the odoo db itself, for security purpose
10-
- it also possible to use another PostgreSQL user for the same security reasons
11-
12-
Set this module in the server wide modules
13-
""",
14-
'category': '',
15-
'version': '1.0',
16-
17-
'depends': [
18-
],
19-
20-
'data': [
21-
],
22-
'demo': [
23-
],
2+
"name": "Store sessions in DB",
3+
"version": "16.0.1.0.0",
4+
"author": "Odoo SA,ACSONE SA/NV,Odoo Community Association (OCA)",
5+
"license": "LGPL-3",
6+
"website": "https://github.com/OCA/server-tools",
247
}

‎session_db/models/__init__.py

-1
This file was deleted.

‎session_db/models/session.py

-125
This file was deleted.

‎session_db/pg_session_store.py

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# Copyright (c) Odoo SA 2017
2+
# @author Nicolas Seinlet
3+
# Copyright (c) ACSONE SA 2022
4+
# @author Stéphane Bidoul
5+
import json
6+
import logging
7+
import os
8+
9+
import psycopg2
10+
11+
import odoo
12+
from odoo import http
13+
from odoo.tools._vendor import sessions
14+
from odoo.tools.func import lazy_property
15+
16+
_logger = logging.getLogger(__name__)
17+
18+
19+
def with_cursor(func):
20+
def wrapper(self, *args, **kwargs):
21+
tries = 0
22+
while True:
23+
tries += 1
24+
try:
25+
return func(self, *args, **kwargs)
26+
except psycopg2.InterfaceError as e:
27+
_logger.info("Session in DB connection Retry %s/5" % tries)
28+
if tries > 4:
29+
raise e
30+
self._open_connection()
31+
32+
return wrapper
33+
34+
35+
class PGSessionStore(sessions.SessionStore):
36+
def __init__(self, uri, session_class=None):
37+
super().__init__(session_class)
38+
self._uri = uri
39+
self._cr = None
40+
# FIXME This class is NOT thread-safe. Only use in worker mode
41+
if odoo.tools.config["workers"] == 0:
42+
raise ValueError("session_db requires multiple workers")
43+
self._open_connection()
44+
self._setup_db()
45+
46+
def __del__(self):
47+
if self._cr is not None:
48+
self._cr.close()
49+
50+
def _open_connection(self):
51+
cnx = odoo.sql_db.db_connect(self._uri, allow_uri=True)
52+
self._cr = cnx.cursor()
53+
self._cr._cnx.autocommit = True
54+
55+
@with_cursor
56+
def _setup_db(self):
57+
self._cr.execute(
58+
"""
59+
CREATE TABLE IF NOT EXISTS http_sessions (
60+
sid varchar PRIMARY KEY,
61+
write_date timestamp without time zone NOT NULL,
62+
payload text NOT NULL
63+
)
64+
"""
65+
)
66+
67+
@with_cursor
68+
def save(self, session):
69+
payload = json.dumps(dict(session))
70+
self._cr.execute(
71+
"""
72+
INSERT INTO http_sessions(sid, write_date, payload)
73+
VALUES (%(sid)s, now() at time zone 'UTC', %(payload)s)
74+
ON CONFLICT (sid)
75+
DO UPDATE SET payload = %(payload)s,
76+
write_date = now() at time zone 'UTC'
77+
""",
78+
dict(sid=session.sid, payload=payload),
79+
)
80+
81+
@with_cursor
82+
def delete(self, session):
83+
self._cr.execute("DELETE FROM http_sessions WHERE sid=%s", (session.sid,))
84+
85+
@with_cursor
86+
def get(self, sid):
87+
self._cr.execute(
88+
"UPDATE http_sessions "
89+
"SET write_date = now() at time zone 'UTC' "
90+
"WHERE sid=%s",
91+
[sid],
92+
)
93+
self._cr.execute("SELECT payload FROM http_sessions WHERE sid=%s", (sid,))
94+
try:
95+
data = json.loads(self._cr.fetchone()[0])
96+
except Exception:
97+
return self.new()
98+
99+
return self.session_class(data, sid, False)
100+
101+
# This method is not part of the Session interface but is called nevertheless,
102+
# so let's get it from FilesystemSessionStore.
103+
rotate = http.FilesystemSessionStore.rotate
104+
105+
@with_cursor
106+
def vacuum(self):
107+
self._cr.execute(
108+
"DELETE FROM http_sessions "
109+
"WHERE now() at time zone 'UTC' - write_date > '7 days'"
110+
)
111+
112+
113+
_original_session_store = http.root.__class__.session_store
114+
115+
116+
@lazy_property
117+
def session_store(self):
118+
session_db_uri = os.environ.get("SESSION_DB_URI")
119+
if session_db_uri:
120+
_logger.debug("HTTP sessions stored in: db")
121+
return PGSessionStore(session_db_uri, session_class=http.Session)
122+
return _original_session_store.__get__(self, self.__class__)
123+
124+
125+
# Monkey patch of standard methods
126+
_logger.debug("Monkey patching session store")
127+
http.root.__class__.session_store = session_store
128+
# Reset the lazy property cache
129+
vars(http.root).pop("session_store", None)

‎session_db/readme/DESCRIPTION.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Store sessions in a database instead of the filesystem.

‎session_db/readme/ROADMAP.rst

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This module does not work with multi-threaded workers, so it requires workers > 0.

‎session_db/readme/USAGE.rst

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Set this module in the server wide modules.
2+
3+
Set a ``SESSION_DB_URI`` environment variable as a full postgresql connection string,
4+
like ``postgres://user:passwd@server/db`` or ``db``.
5+
6+
It is recommended to use a dedicated database for this module, and possibly a dedicated
7+
postgres user for additional security.
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../session_db

‎setup/session_db/setup.py

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import setuptools
2+
3+
setuptools.setup(
4+
setup_requires=['setuptools-odoo'],
5+
odoo_addon=True,
6+
)

0 commit comments

Comments
 (0)
Please sign in to comment.