Repository navigation
Calendar time zones, recurrence checks and administration; Talk join link, password and lobby - #88
Open
BjoernSchotte wants to merge 6 commits into
Open
BjoernSchotte wants to merge 6 commits into
BjoernSchotte wants to merge 6 commits into
Conversation
create_conversation and get_conversation return url, the link to join (<base>/index.php/call/<token>, works without pretty URLs). set_conversation_password sets the password guests need for a public conversation; removing it needs the destructive level; the password is never echoed, also not in errors. set_conversation_lobby turns the lobby on (optionally until a future time) or off. Signed-off-by: Björn Schotte <bjoern.schotte@googlemail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nextcloud answers 998 ("Invalid query, please check the syntax") when no
route matches. For apps/<id>/ that means the app does not serve this
account: not installed, disabled, or limited to groups the user is not in
(seen with Talk restricted to some groups). The old message misled the
caller; app-level 404s keep their own message.
Signed-off-by: Björn Schotte <bjoern.schotte@googlemail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- NEXTCLOUD_MCP_TIMEZONE and a timezone argument: times without offset are wall time in that zone; events get TZID + VTIMEZONE (recurring events keep their wall time across DST). get_events accepts offsets in the range. - RRULE is checked (DAILY..YEARLY, known parts, COUNT/INTERVAL <= 1000, not COUNT and UNTIL together); UNTIL converted to UTC or a date. - conference_url: CONFERENCE (RFC 7986) plus LOCATION when empty, else a line in the description; update can replace or remove it. - create_event marks X-NC-MCP-CREATED-BY; update_event refuses events of others or with attendees unless allow_foreign=true; expected_summary on update and delete. Output has has_attendees/created_by_me, never attendee addresses. - Moving only the start keeps the duration; end before start is refused. Tests: 43 unit, 6 integration against Nextcloud 34 (shared calendar <uri>_shared_by_<owner>, read-only sharee cannot write). Signed-off-by: Björn Schotte <bjoern.schotte@googlemail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ublic link, delete, shares create_calendar (unique URI, also past trashed calendars; optional group share), share_calendar/unshare_calendar (users and groups), publish_calendar/unpublish_calendar, delete_calendar (expected_name guard), get_calendar_shares (owner only; Depth 1 on the home because Nextcloud omits owner-principal with Depth 0). Tests: unit + integration against Nextcloud 34 (group share visible to the member, sharees see no shares and cannot share). Signed-off-by: Björn Schotte <bjoern.schotte@googlemail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
search_files built its SEARCH scope from the path as given, so "a/../.." went to Nextcloud and failed there with an unclear error. The scope is now built from the path's segments: empty and "." segments are dropped, and ".." is refused with a clear error before any request is sent. The scope stays unencoded on purpose. Nextcloud's search plugin takes a relative scope href as a path without URL-decoding it, which the existing integration test for a folder named "search #1 %41 Ü" relies on. Signed-off-by: Björn Schotte <bjoern.schotte@googlemail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
README and PROGRESS.md list the nine new tools (231 plus upload_file_from_path), sync_progress.py maps the new calendar test modules to the Calendar row, and the counts are recomputed with scripts/sync_progress.py --write. Fixes the pyright error in the shared calendar fixture's type. Signed-off-by: Björn Schotte <bjoern.schotte@googlemail.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
We use this server so that an assistant can plan events for a group: create a calendar, share it, put
(recurring) events in it with a video link, and open a Talk room that guests can join. Doing this for real people
showed some gaps: times without an offset were taken as UTC, a bad
RRULEreached Nextcloud, there was no way togive a Talk room a guest password or lobby, no join link was returned, and nothing kept the assistant from
changing events that other people own. This PR closes these gaps. It is independent of #87 (multi-user mode) and does not need it.
Changes
Talk
create_conversationandget_conversationreturnurl, the link to join (<base>/index.php/call/<token>;works without pretty URLs; the token is URL-encoded).
set_conversation_password(write): sets the password guests need for a public conversation. Removing thepassword needs
destructive. The password is never echoed, also not in error messages.set_conversation_lobby(write): turns the lobby on (optionally until a future time) or off.Clearer error for apps that are not available (OCS 998)
Nextcloud answers OCS 998 ("Invalid query, please check the syntax") when no route matches. Under
apps/<id>/this means the app does not serve this account: not installed, disabled, or limited to groups the user is not in
(seen with Talk restricted to some groups). The error now says so. App-level 404s keep their own message.
Calendar events
NEXTCLOUD_MCP_TIMEZONE(IANA name, validated at start) and atimezonetool argument. Timeswithout an offset are wall time in that zone; events get
TZIDand aVTIMEZONE, so a weekly event stays at19:00 across daylight saving changes. Without either setting, times stay UTC as before.
get_eventsacceptsoffsets in the range. Moving only the start keeps the duration; an end before the start is refused.
DAILY..YEARLY, known parts,COUNT/INTERVALat most 1000, neverCOUNTandUNTILtogether.UNTILis converted to UTC (or a date for all-day events), as RFC 5545 requires.conference_url: stored asCONFERENCE(RFC 7986) and asLOCATIONwhen that is empty (as NextcloudCalendar does for Talk rooms), else as a
Video call: <url>line in the description. Only http(s) URLs areaccepted.
update_eventcan replace or remove it.create_eventmarks events withX-NC-MCP-CREATED-BY:<user id>.update_eventrefuses events without the caller's mark, or with attendees (Nextcloud would send themnotifications), unless
allow_foreign=true, so that a client can ask its user first.update_eventanddelete_eventtake an optionalexpected_summaryand refuse to act if the title differs. Event output showshas_attendeesandcreated_by_me, never attendee or organizer addresses.Calendar administration (new tools)
create_calendar(unique URI from the name, also avoiding URIs of trashed calendars; optional group share in thesame call),
share_calendar/unshare_calendar(users and groups, read or read-write),publish_calendar/unpublish_calendar(public read-only link),delete_calendar(destructive, with anexpected_nameguard; for asharee it removes the calendar from their account only) and
get_calendar_shares(owner only).get_calendar_sharesuses Depth 1 on the calendar home, because Nextcloud omitsowner-principalwith Depth 0.search_files: refuse..The SEARCH scope is now built from the path's segments: empty and
.segments are dropped, and..is refusedwith a clear error before a request is sent. Before,
a/../..went to Nextcloud and failed there with an unclearerror. The scope is deliberately not percent-encoded: SearchDAV's
PathHelpertakes a relative scope href asa path without URL-decoding it; the existing integration test for a folder named
search #1 %41 Üdepends on this.Security considerations
destructivelevel; all other new tools arewrite,get_calendar_sharesisread.conference_urlaccepts onlyhttp/https(nojavascript:etc.).expected_summary/expected_nameguards make it harder for an assistant to change ordelete the wrong thing in shared calendars. They are guards, not access control: Nextcloud's own permissions
still decide.
..insearch_filespaths is refused before a request is sent.Tests
tests/test_talk_admin.py(join link, password, lobby),tests/test_client_errors.py(OCS 998),tests/test_calendar_helpers.py(time zones, RRULE, conference URL, guards, slugs, principals),tests/test_files_helpers.py(_search_scope).tests/integration/test_calendar_guard.py(time zones across DST, bad RRULE creates nothing,video link, shared calendar
<uri>_shared_by_<owner>: the read-write sharee writes, the owner needsallow_foreign, a read-only sharee cannot write) andtests/integration/test_calendar_admin.py(group sharevisible to the member, sharees see no shares and cannot share, publish/unpublish, delete guard), plus the
..case in
tests/integration/test_files.py. These ran against Nextcloud 34 during development.ruff check,ruff format --check,isort --check src/andpyrightare clean; 773unit tests pass.
scripts/sync_progress.pymaps the new calendar test modules,and the counts were recomputed with it.
Backwards compatibility
NEXTCLOUD_MCP_TIMEZONEand without thetimezoneargument, times without an offset are UTC, as before.update_eventnow refuses events that this server did not create, or that have attendees,unless
allow_foreign=true. Events created before this change carry no mark, so updating them needsallow_foreign=trueonce. If you prefer this guard to be opt-in, I am happy to change it.RRULEvalues that were accepted before but are invalid or unbounded (e.g.COUNTwithUNTIL) are now refused.AI disclosure: this change was written with Claude Code (Claude Opus 5.5); commits carry a Co-Authored-By trailer.
🤖 Generated with Claude Code