-
-
Notifications
You must be signed in to change notification settings - Fork 274
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
[15.0][ADD] base_ical #231
Conversation
Thanks @hbrunn for this great PR! I've done some functional testing and found the following issues:
My configuration: |
1, 2: will fix that soon |
Calling the provided URL is not yet possible for me:
Maybe releated to Point 2. |
1 and the last access error are fixed, 2 I fail to reproduce on runboat (or locally), we'll have to discuss that later I think |
Very strange. Cannot reproduce this behaviour either now. Also ordinary users may access the profile and edit the ics-calendar records. The ics-export works now as expected. I didn't restart the Odoo process before maybe. May this be the reason? And I checked it only on my local system. |
On another instance, I have the same issue |
The issue |
There hasn't been any activity on this pull request in the past 4 months, so it has been marked as stale and it will be closed automatically if no further activity occurs in the next 30 days. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat! This is a much more robust implementation of something I attempted myself in odoo/odoo#53986.
active = fields.Boolean(default=True) | ||
ical_id = fields.Many2one("base.ical", required=True, ondelete="cascade") | ||
user_id = fields.Many2one("res.users", required=True, ondelete="cascade") | ||
token = fields.Char(required=True, default=lambda self: secrets.token_urlsafe()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll raise the same argument here that I (correctly) lost in my own pull request (odoo/odoo#53986 (comment)), that it is a bad idea to introduce a new authentication mechanism, especially one that stores a text/plain token in the database. I ended up using a res.users.apikeys
with a custom scope.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for this, very good point. Bad news is however that this needs quite some effort, and there's no further funding for this module at the moment.
I'll add this to my OCA-TODOs, but it goes to the end of the queue, so no ETA unfortunately
@@ -4,3 +4,4 @@ mysqlclient | |||
pymssql<=2.2.5 | |||
sqlalchemy | |||
sqlalchemy-hana | |||
vobject |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This package requirement suggests that this module should land in https://github.com/OCA/calendar instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually don't mind very much where to put this, if other reviewers feel it should go there, I'll be happy to oblige.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vobject
also offers vtodo
if you want to support it (based on mail.activity
) which works quite nicely if you use a html2text function for the description. This would open a new possibility and would go further than a way to sync calendar clients. This would mean that it shouldn't be in calendar if we make it possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion it would be slightly easier to discover this module (by functional users) and be more intuitive in /OCA/calendar even though if it would support vtodo in the future.
@@ -0,0 +1,4 @@ | |||
The development of this module has been financially supported by: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete this placeholder file?
preview = fields.Text(compute="_compute_preview") | ||
expression_dtstamp = fields.Char( | ||
required=True, | ||
vevent_field="dtstamp", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am unfamiliar with this capability of Odoo fields. You're able to decorate the field with a custom vevent_field argument?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can add arbitrary arguments, you should however add it in _valid_field_parameter
to avoid a warning. Very handy as this makes the code below much more concise
) | ||
user_url = fields.Char(compute="_compute_user_fields", string="URL") | ||
user_active = fields.Boolean(compute="_compute_user_fields") | ||
auto = fields.Boolean( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like auto=True
has too large a blast radius unless paired with some sort of group or base_user_role
based restriction?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's why it's off by default. It is actually restricted to backend users below, so it depends very much on your specific case if it's a good idea to turn this on or not
from odoo import http | ||
|
||
|
||
class MyController(http.Controller): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MyController should probably be renamed to something more specific.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left some notes with a suggestion. If you like I could also spend some time to implement those and/or the swap to res.users.apikeys. Just comment if you would appreciate the suggestion/support and what you would like to see.
<field name="model" invisible="True" /> | ||
<field | ||
name="domain" | ||
placeholder="[('user_id', '=', user.id)]" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you want to introduce the domain widget here?
placeholder="[('user_id', '=', user.id)]" | |
placeholder="[('user_id', '=', user.id)]" | |
widget="domain" | |
options="{'model': 'model'} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd love to, but it can't handle expressions - that would need quite some work in the domain widget itself to make this work
|
||
For example, for model ``calendar.event``, you'd fill in ``record.allday and record.start_date or record.start`` as `DTSTART` and ``record.allday and record.stop_date or record.stop`` as `DTEND`. | ||
|
||
For model ``hr.leave``, you'd write ``(record.request_unit_half or record.request_unit_hours) and record.date_from or record.date_from.date()`` for `DTSTART` and ``(record.request_unit_half or record.request_unit_hours) and record.date_to or (record.date_to.date() + timedelta(days=1))`` for `DTEND` - this is a bit more complex because of the way Odoo handles the begin and end times of leaves, and you'll want the extra day as most clients interpret the end date as non-inclusive. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shows a bit of the disadvantage of the approach here because you need quite complex or ... and ... or
constructs to achieve some stuff because you can't use variables in such snippets. For calendar.event it would be nice to use the core function _get_ics_file
too. I would suggest to use a single multi-line snippet with a defined interface and use safe_eval in "exec" mode. The downside is that it's more complicated but more flexible and allows additional fields like DESCRIPTION
, RRULE
...
# Also add vobject to the context
context["events"] = self._get_events()
safe_eval.safe_eval(self.code, context, mode="exec", nocopy=True)
# We could define that result can either be a list of dict or an iCalendar object
result = context.get("result", None)
if isinstance(result, list):
calendar = vobject.iCalendar()
for event in result:
vobj = cal.add("vevent")
for key, val in event.items():
# TZ check for datetime etc.
vobj.add(key).value = val
return calendar.serialize()
return result
Snippets could be:
- calendar.event:
result = events._get_ics_file()
- hr.leave:
result = []
for event in events:
if event.request_unit_half or event.request_unit_hours:
dtstart = event.date_from
dtend = event.date_to
else:
dtstart = event.date_from.date()
dtend = event.date_from.date()
result.append(
{
"dtstart": dtstart,
"dtend": dtend,
"summary": event.name,
"uid": ..., # a bit unsure but I would just pass a function -> record to uid to the snippet
}
)
Funnily enough that would make it possible to generate vtodo
based on mail.activity
aswell.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can't we have both? As in (pseudo-python):
result = {
'dtend': eval(expression_dtend),
...
}
if code_full:
safe_eval(code_full, locals)
result.update(**locals['result'])
and the field for code_full would go to base.group_noone
or a dedicated one? Then for simple cases admins can use the fields, if you want to do anything fancy you switch to the full code mode.
I'm all for injecting some helper functions in the eval context, and vtodos, sure. I think I'd also implement this with a simple mode (radio for this is a vevent or vtodo, showing/hiding the appropriate expression fields) and the full code mode where you can overwrite all of the above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both might be complicated because the _get_ics_file
are generating full calendars => I would run the snippet on multiple events instead of one event which would make merging both hard.
Maybe I can go with a switch for either simple or advanced mode but mixing is complex. In the end it boils down to the administrator to set it up. We could also just offer an advanced mode but some snippets for various basic cases.
@@ -4,3 +4,4 @@ mysqlclient | |||
pymssql<=2.2.5 | |||
sqlalchemy | |||
sqlalchemy-hana | |||
vobject |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
vobject
also offers vtodo
if you want to support it (based on mail.activity
) which works quite nicely if you use a html2text function for the description. This would open a new possibility and would go further than a way to sync calendar clients. This would mean that it shouldn't be in calendar if we make it possible.
if not token: | ||
return http.request.not_found() | ||
response = http.request.make_response( | ||
token.ical_id.with_user(token.user_id)._get_ical(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sudo()
would be still active here which might work or might cause problems when the domain isn't defined correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fortunately with_user
resets the su flag - otherwise we'd see a lot of nasty privilege escalations out there
@fkantelberg if you've time and/or even funding for developing this further, please, by all means go ahead and do so. Just ping me on your PR, then I'll close this one, as I won't be able to work on this any time soon. My current OCA time itch is OCA/server-ux#849 |
I tested it for model |
I assume that would need this addon exporting VALARM components, which it doesn't. Should be easy to add though. |
Syncing from upstream OCA/server-backend (15.0)
This module allows administrators to configure iCalendars based on an arbitrary selection on arbitrary models.
Users can selectively subscribe to them by enabling them in their profile form.
This is useful for exposing Odoo data to calendaring application like Nextcloud.
Configuration
To configure this module, you need to:
Go to Settings/Technical/iCalendars
Create a calendar, fill in the model you want to expose and possibly a domain to restrict records. You can use the
user
variable to restrict things relative to the user using the calendarA few iCalendar-fields have defaults that should work for any model, you'll have to fill in expressions manually though for the start and end date of the records.
For example, for model
calendar.event
, you'd fill inrecord.allday and record.start_date or record.start
asDTSTART
andrecord.allday and record.stop_date or record.stop
asDTEND
.For model
hr.leave
, you'd write(record.request_unit_half or record.request_unit_hours) and record.date_from or record.date_from.date()
forDTSTART
and(record.request_unit_half or record.request_unit_hours) and record.date_to or (record.date_to.date() + timedelta(days=1))
forDTEND
- this is a bit more complex because of the way Odoo handles the begin and end times of leaves, and you'll want the extra day as most clients interpret the end date as non-inclusive.Existing calendars are available for users in the tab
Calendars
of their profile form, where they can enable them to obtain a link they can paste into whatever client they are going to useUsage
To use this module, you need to:
Enable
on one of the calendars listed in tabCalendars