Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MIG] base_dav: Migration to 17.0 #269

Open
wants to merge 60 commits into
base: 17.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
7844e6e
[MIG] base_dav: Migration to 17.0
jaydeep32 Feb 14, 2024
5e3179e
[IMP] base_dav: Some test cases fixes,odoo tools safe_eval fixes.
jaydeep32 Feb 14, 2024
a244bd5
[IMP] base_dav: pre-commit auto fixes
jaydeep32 Feb 14, 2024
10d533d
[UPD] base_dav: python package version
jaydeep32 Feb 14, 2024
804cce3
[UPD] base_dav: Module external_dependencies with version.
jaydeep32 Feb 14, 2024
a14edea
Translated using Weblate (Spanish)
Ivorra78 Feb 14, 2024
2efc7ea
Translated using Weblate (Italian)
mymage Feb 15, 2024
a6546d7
[ADD] base_user_role_company: add per company user roles
Chandresh-OSI May 3, 2021
e063507
[UPD] Update base_user_role_company.pot
oca-travis May 19, 2021
0fba526
[UPD] README.rst
OCA-git-bot May 19, 2021
5a15310
[ADD] icon.png
OCA-git-bot May 19, 2021
2976844
[FIX] base_user_role_company: wrong xpath
kos94ok-3D Nov 3, 2021
9752e9c
base_user_role_company 14.0.1.1.0
OCA-git-bot Nov 4, 2021
b7c3aa6
Added translation using Weblate (Italian)
Feb 15, 2022
31b92c7
[FIX] base_user_role_company: roles not properly applied on login
dreispt Feb 15, 2022
c6ef4fa
Translated using Weblate (Italian)
Feb 15, 2022
b0b99e0
[FIX] base_user_role_company: wrong menus on re-login
dreispt Mar 2, 2022
e81489f
[FIX] base_user_role_company: fix tests
dreispt Mar 3, 2022
8e0628d
[UPD] Update base_user_role_company.pot
oca-travis Mar 3, 2022
677b853
base_user_role_company 14.0.2.0.0
OCA-git-bot Mar 3, 2022
2aa2b91
Update translation files
oca-transbot Mar 3, 2022
20abc76
base_user_role_company 14.0.2.0.1
OCA-git-bot Mar 3, 2022
51e54c0
Translated using Weblate (Italian)
francesco-ooops Mar 7, 2023
581fb46
[IMP] base_user_role_company: pre-commit stuff
Urvisha-OSI Apr 5, 2023
81827d8
[MIG] base_user_role_company: Migration to 16.0
Urvisha-OSI Apr 5, 2023
a06728a
[UPD] Update base_user_role_company.pot
Aug 7, 2023
4f3f215
[UPD] README.rst
OCA-git-bot Aug 7, 2023
a9d2730
Update translation files
weblate Aug 7, 2023
2d62260
Added translation using Weblate (Spanish)
Ivorra78 Aug 25, 2023
636856b
Translated using Weblate (Spanish)
Ivorra78 Aug 25, 2023
62a2ce4
Added translation using Weblate (Portuguese)
pedrocs-exo Aug 31, 2023
17cca66
Translated using Weblate (Portuguese)
pedrocs-exo Aug 31, 2023
adc2775
[UPD] README.rst
OCA-git-bot Sep 3, 2023
123105f
[FIX] base_user_role_company: Pylint fix
etobella Oct 28, 2023
476a7e9
[UPD] Update base_user_role_company.pot
Oct 28, 2023
bc7eb51
[BOT] post-merge updates
OCA-git-bot Oct 28, 2023
19b974e
Update translation files
weblate Oct 29, 2023
f6ebd77
Translated using Weblate (Spanish)
Ivorra78 Nov 8, 2023
90bcc47
Translated using Weblate (Italian)
mymage Jan 3, 2024
e761802
base_user_role_company: allow same role in different companies
sebalix Feb 1, 2024
47dabe2
[BOT] post-merge updates
OCA-git-bot Feb 16, 2024
bd2f05f
[IMP] base_user_role_company: black, isort, prettier
rconjour Feb 26, 2024
a9a9375
[MIG] base_user_role_company: Migration to 17.0
rconjour Feb 26, 2024
b230874
Translated using Weblate (Italian)
mymage Mar 6, 2024
3b33180
Merge PR #270 into 17.0
OCA-git-bot Mar 9, 2024
ee371e8
[UPD] Update base_user_role_company.pot
Mar 9, 2024
5fe5154
[BOT] post-merge updates
OCA-git-bot Mar 9, 2024
32f575a
[ADD] base_dav
hbrunn Dec 12, 2018
54b7a7f
Fix CI errors
fkantelberg Jan 12, 2020
dd23c30
Mute radicale logger for testing
fkantelberg Jan 12, 2020
e194c4a
Use the collection as first argument in the creation of the items
fkantelberg Jan 16, 2020
f1a711c
Use related model_id field to build domain
fkantelberg Jul 13, 2020
f9b5973
Set default id for fields
fkantelberg Jul 29, 2020
555cf49
Add missing quotation
fkantelberg Jul 29, 2020
b5b9e20
[UPD] Update base_dav.pot
oca-travis Feb 11, 2021
8b51c3e
[UPD] README.rst
OCA-git-bot Feb 11, 2021
3911e59
[UPD] README.rst
OCA-git-bot Sep 3, 2023
596854d
[IMP] base_dav: pre-commit auto fixes
jaydeep32 Mar 20, 2024
9106fc5
[MIG] base_dav: Migration to 17.0
jaydeep32 Mar 20, 2024
360893e
Merge branch '17.0-mig-base_dav' of https://github.com/archeti-org/se…
jaydeep32 Mar 20, 2024
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
3 changes: 3 additions & 0 deletions base_dav/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ to Odoo via odoorpc. It should be possible to recycle most of the code
from this addon, which actually implements those plugins, but then
within Odoo.

In order to install this module and use it make sure you use right version of `radicale==2.1.12` library.


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

Expand Down
5 changes: 3 additions & 2 deletions base_dav/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
{
"name": "Caldav and Carddav support",
"version": "11.0.1.0.0",
"version": "17.0.1.0.0",
"author": "initOS GmbH,Therp BV,Odoo Community Association (OCA)",
"license": "AGPL-3",
"category": "Extra Tools",
"summary": "Access Odoo data as calendar or address book",
"website": "https://github.com/OCA/server-backend",
"depends": [
"base",
],
Expand All @@ -19,6 +20,6 @@
"security/ir.model.access.csv",
],
"external_dependencies": {
"python": ["radicale"],
"python": ["radicale==2.1.12"],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be >= ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, I use this specific module version because this module's code is only compatible with this 2.1.12 or older version of radical. If you check this #254 issue here, @AquaMCU has mentioned that he is having this strange error in the log,
so I solved that by changing the module version to radicale==2.1.12.

Also, if possible, can we add @AquaMCU to the discussion since he is the one who has migrated the module?
Actually, he was not able to create PR, so I simply made that for him

},
}
1 change: 1 addition & 0 deletions base_dav/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

try:
import radicale
# from radicale import config
except ImportError:
radicale = None

Expand Down
10 changes: 5 additions & 5 deletions base_dav/demo/dav_collection.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,27 @@
</record>
<record id="field_mapping_addressbook_n" model="dav.collection.field_mapping">
<field name="name">N</field>
<field name="field_id" ref="base.field_res_partner_name" />
<field name="field_id" ref="base.field_res_partner__name" />
<field name="collection_id" ref="collection_addressbook" />
</record>
<record id="field_mapping_addressbook_fn" model="dav.collection.field_mapping">
<field name="name">FN</field>
<field name="field_id" ref="base.field_res_partner_display_name" />
<field name="field_id" ref="base.field_res_partner__display_name" />
<field name="collection_id" ref="collection_addressbook" />
</record>
<record id="field_mapping_addressbook_photo" model="dav.collection.field_mapping">
<field name="name">photo</field>
<field name="field_id" ref="base.field_res_partner_image" />
<field name="field_id" ref="base.field_res_partner__image_1920" />
<field name="collection_id" ref="collection_addressbook" />
</record>
<record id="field_mapping_addressbook_email" model="dav.collection.field_mapping">
<field name="name">email</field>
<field name="field_id" ref="base.field_res_partner_email" />
<field name="field_id" ref="base.field_res_partner__email" />
<field name="collection_id" ref="collection_addressbook" />
</record>
<record id="field_mapping_addressbook_tel" model="dav.collection.field_mapping">
<field name="name">tel</field>
<field name="field_id" ref="base.field_res_partner_phone" />
<field name="field_id" ref="base.field_res_partner__phone" />
<field name="collection_id" ref="collection_addressbook" />
</record>
</odoo>
41 changes: 17 additions & 24 deletions base_dav/models/dav_collection.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
# Copyright 2019 Therp BV <https://therp.nl>
# Copyright 2019-2020 initOS GmbH <https://initos.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).

import os
import time
from operator import itemgetter
from urllib.parse import quote_plus

import vobject

from odoo import api, fields, models, tools
from odoo import SUPERUSER_ID, api, fields, models
from odoo.tools.safe_eval import safe_eval

from odoo.addons.base_dav.radicale.collection import Collection, FileItem, Item

# pylint: disable=missing-import-error
from ..controllers.main import PREFIX
from ..radicale.collection import Collection, FileItem, Item


class DavCollection(models.Model):
Expand Down Expand Up @@ -46,6 +47,7 @@ class DavCollection(models.Model):
string="Model",
required=True,
domain=[("transient", "=", False)],
ondelete="cascade",
)
domain = fields.Char(
required=True,
Expand All @@ -59,24 +61,17 @@ class DavCollection(models.Model):
)
url = fields.Char(compute="_compute_url")

@api.multi
def _compute_tag(self):
for this in self:
if this.dav_type == "calendar":
this.tag = "VCALENDAR"
elif this.dav_type == "addressbook":
this.tag = "VADDRESSBOOK"

@api.multi
def _compute_url(self):
base_url = self.env["ir.config_parameter"].get_param("web.base.url")
for this in self:
this.url = "%s%s/%s/%s" % (
base_url,
PREFIX,
self.env.user.login,
this.id,
)
this.url = f"{base_url}{PREFIX}/{self.env.user.login}/{this.id}"

@api.constrains("domain")
def _check_domain(self):
Expand All @@ -88,28 +83,26 @@ def _eval_context(self):
"user": self.env.user,
}

@api.multi
def _eval_domain(self):
self.ensure_one()
return list(tools.safe_eval(self.domain, self._eval_context()))
return list(safe_eval(self.domain, self._eval_context()))

@api.multi
def eval(self):
if not self:
return self.env["unknown"]
self.ensure_one()
self = self.with_user(SUPERUSER_ID)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This raises security concerns, why is this required?

return self.env[self.model_id.model].search(self._eval_domain())

@api.multi
def get_record(self, components):
self.ensure_one()
self = self.with_user(SUPERUSER_ID)
collection_model = self.env[self.model_id.model]

field_name = self.field_uuid.name or "id"
domain = [(field_name, "=", components[-1])] + self._eval_domain()
return collection_model.search(domain, limit=1)

@api.multi
def from_vobject(self, item):
self.ensure_one()

Expand All @@ -136,9 +129,9 @@ def from_vobject(self, item):

return result

@api.multi
def to_vobject(self, record):
self.ensure_one()
self = self.with_user(SUPERUSER_ID)
result = None
vobj = None
if self.dav_type == "calendar":
Expand All @@ -153,16 +146,20 @@ def to_vobject(self, record):
vobj.add(mapping.name).value = value

if "uid" not in vobj.contents:
vobj.add("uid").value = "%s,%s" % (record._name, record.id)
vobj.add("uid").value = f"{record._name},{record.id}"
if "rev" not in vobj.contents and "write_date" in record._fields:
vobj.add("rev").value = (
record.write_date.replace(":", "").replace(" ", "T").replace(".", "")
str(record.write_date)
.replace(":", "")
.replace(" ", "T")
.replace(".", "")
+ "Z"
)
return result

@api.model
def _odoo_to_http_datetime(self, value):
value = str(value).split(".")[0]
return time.strftime(
"%a, %d %b %Y %H:%M:%S GMT",
time.strptime(value, "%Y-%m-%d %H:%M:%S"),
Expand All @@ -172,7 +169,6 @@ def _odoo_to_http_datetime(self, value):
def _split_path(self, path):
return list(filter(None, os.path.normpath(path or "").strip("/").split("/")))

@api.multi
def dav_list(self, collection, path_components):
self.ensure_one()

Expand Down Expand Up @@ -217,7 +213,6 @@ def dav_list(self, collection, path_components):
result.append("/" + "/".join(path_components + [uuid]))
return result

@api.multi
def dav_delete(self, collection, components):
self.ensure_one()

Expand All @@ -227,7 +222,6 @@ def dav_delete(self, collection, components):
else:
self.get_record(components).unlink()

@api.multi
def dav_upload(self, collection, href, item):
self.ensure_one()

Expand All @@ -246,7 +240,7 @@ def dav_upload(self, collection, href, item):

record = collection_model.create(data)
uuid = components[-1] if self.field_uuid else record.id
href = "%s/%s" % (href, uuid)
href = f"{href}/{uuid}"
else:
record.write(data)

Expand All @@ -257,7 +251,6 @@ def dav_upload(self, collection, href, item):
last_modified=self._odoo_to_http_datetime(record.write_date),
)

@api.multi
def dav_get(self, collection, href):
self.ensure_one()

Expand Down
43 changes: 19 additions & 24 deletions base_dav/models/dav_collection_field_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from dateutil import tz

from odoo import api, fields, models, tools
from odoo.tools import safe_eval


class DavCollectionFieldMapping(models.Model):
Expand Down Expand Up @@ -36,10 +37,10 @@ class DavCollectionFieldMapping(models.Model):
"ir.model.fields",
required=True,
help="Field of the model the values are mapped to",
ondelete="cascade",
)
model_id = fields.Many2one(
"ir.model",
related="collection_id.model_id",
"ir.model", related="collection_id.model_id", ondelete="cascade"
)
import_code = fields.Text(
help="Code to import the value from a vobject. Use the variable "
Expand All @@ -50,35 +51,32 @@ class DavCollectionFieldMapping(models.Model):
"result for the output of the value and record as input"
)

@api.multi
def from_vobject(self, child):
self.ensure_one()
if self.mapping_type == "code":
return self._from_vobject_code(child)
return self._from_vobject_simple(child)

@api.multi
def _from_vobject_code(self, child):
self.ensure_one()
context = {
"datetime": datetime,
"dateutil": dateutil,
"datetime": safe_eval.datetime,
"dateutil": safe_eval.dateutil,
"item": child,
"result": None,
"tools": tools,
"tz": tz,
"vobject": vobject,
# "tools": tools,
# "tz": tz,
# "vobject": vobject,
}
tools.safe_eval(self.import_code, context, mode="exec", nocopy=True)
safe_eval.safe_eval(self.import_code, context, mode="exec", nocopy=True)
return context.get("result", {})

@api.multi
def _from_vobject_simple(self, child):
self.ensure_one()
name = self.name.lower()
conversion_funcs = [
"_from_vobject_%s_%s" % (self.field_id.ttype, name),
"_from_vobject_%s" % self.field_id.ttype,
f"_from_vobject_{self.field_id.ttype}_{name}",
f"_from_vobject_{self.field_id.ttype}",
]

for conversion_func in conversion_funcs:
Expand Down Expand Up @@ -115,7 +113,6 @@ def _from_vobject_binary(self, item):
def _from_vobject_char_n(self, item):
return item.family

@api.multi
def to_vobject(self, record):
self.ensure_one()
if self.mapping_type == "code":
Expand All @@ -127,27 +124,25 @@ def to_vobject(self, record):
return result.replace(tzinfo=tz.UTC)
return result

@api.multi
def _to_vobject_code(self, record):
self.ensure_one()
context = {
"datetime": datetime,
"dateutil": dateutil,
"datetime": safe_eval.datetime,
"dateutil": safe_eval.dateutil,
"record": record,
"result": None,
"tools": tools,
"tz": tz,
"vobject": vobject,
# "tools": tools,
# "tz": tz,
# "vobject": vobject,
}
tools.safe_eval(self.export_code, context, mode="exec", nocopy=True)
safe_eval.safe_eval(self.export_code, context, mode="exec", nocopy=True)
return context.get("result", None)

@api.multi
def _to_vobject_simple(self, record):
self.ensure_one()
conversion_funcs = [
"_to_vobject_%s_%s" % (self.field_id.ttype, self.name.lower()),
"_to_vobject_%s" % self.field_id.ttype,
f"_to_vobject_{self.field_id.ttype}_{self.name.lower()}",
f"_to_vobject_{self.field_id.ttype}",
]
value = record[self.field_id.name]
for conversion_func in conversion_funcs:
Expand Down
4 changes: 3 additions & 1 deletion base_dav/radicale/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
class Auth(BaseAuth):
def is_authenticated2(self, login, user, password):
env = request.env
uid = env["res.users"]._login(env.cr.dbname, user, password)
uid = env["res.users"]._login(
env.cr.dbname, user, password, user_agent_env={"interactive": True}
)
if uid:
request._env = env(user=uid)
return bool(uid)
1 change: 1 addition & 0 deletions base_dav/radicale/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def __init__(self, path):
)

def _odoo_to_http_datetime(self, value):
value = str(value).split(".")[0]
return time.strftime(
"%a, %d %b %Y %H:%M:%S GMT",
time.strptime(value, "%Y-%m-%d %H:%M:%S"),
Expand Down
5 changes: 5 additions & 0 deletions base_dav/readme/CONFIGURE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
To configure this module, you need to:

#. go to `Settings / WebDAV Collections` and create or edit your collections. There, you'll also see the URL to point your clients to.

Note that you need to configure a dbfilter if you use multiple databases.
2 changes: 2 additions & 0 deletions base_dav/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* Holger Brunn <[email protected]>
* Florian Kantelberg <[email protected]>
2 changes: 2 additions & 0 deletions base_dav/readme/CREDITS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
* Odoo Community Association: `Icon <https://github.com/OCA/maintainer-tools/blob/master/template/module/static/description/icon.svg>`_
* All the actual work is done by `Radicale <https://radicale.org>`_
3 changes: 3 additions & 0 deletions base_dav/readme/DESCRIPTION.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
This module adds WebDAV support to Odoo, specifically CalDAV and CardDAV.

You can configure arbitrary objects as a calendar or an address book, thus make arbitrary information accessible in external systems or your mobile.
7 changes: 7 additions & 0 deletions base_dav/readme/ROADMAP.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
* much better UX for configuring collections (probably provide a group that sees the current fully flexible field mappings, and by default show some dumbed down version where you can select some preselected vobject fields)
* support todo lists and journals
* support configuring default field mappings per model
* support plain WebDAV collections to make some model's records accessible as folders, and the records' attachments as files (r/w)
* support configuring lists of calendars so that you can have a calendar for every project and appointments are tasks, or a calendar for every sales team and appointments are sale orders. Lots of possibilities

Backporting this to <=v10 will be tricky because radicale only supports python3. Probably it will be quite a hassle to backport the relevant code, so it might be more sensible to just backport the configuration part, and implement the rest as radicale auth/storage plugin that talks to Odoo via odoorpc. It should be possible to recycle most of the code from this addon, which actually implements those plugins, but then within Odoo.
Empty file modified base_dav/static/description/icon.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion base_dav/static/description/index.html
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
Expand Down
Loading