Commit Graph
49 Commits
Author SHA1 Message Date
stefan.tollkuehn 2b3e96e50a Reject normalized datetime-local inputs
createFromFormat() only returns false on hard parse failures.
Impossible dates such as 2026-02-31 were silently normalized
into March, so a confirmed event could land on a different day
than the booking link supplied. Non-padded values like
2026-2-3T10:00 were also accepted and reformatted.

Parse with a leading "!" so no current-date fields leak in,
require zero warnings and errors from getLastErrors(), and
round-trip the value through the format. Impossible dates,
out-of-range components and non-padded values now throw in
both the confirmation and the creation stage.
2026-10-26 13:39:07 +01:00
stefan.tollkuehn a9b7fd11af Announce the suggestion list to screen readers
The invitee input had no combobox semantics: assistive
technology could not tell that the widget owns a listbox with
suggestions. Mark the input as role="combobox" with
aria-autocomplete="list" and an initial aria-expanded="false",
point aria-controls at the list and give the JS-built list a
matching id so the reference resolves.
2026-10-23 14:08:59 +02:00
stefan.tollkuehn 5bba3a93cd Align invitee separators with the server
The server splits the attendee input on whitespace, commas and
semicolons, but the search widget only treated commas and
semicolons as separators. Typing "a@x.com b" therefore sent the
whole string as the search query instead of "b", and picking a
contact dropped the whitespace-separated entry.

Split on /[\s;,]+/ in both fragment() and commit() so the
widget agrees with parseAttendees() on what an entry is.
2026-10-23 14:07:28 +02:00
stefan.tollkuehn e5432a0a38 Fix stale contact suggestions reopening
hide() did not invalidate in-flight search requests. Clearing
the input or picking a contact while a request was pending let
the old response re-render and pop the suggestion list back
open. Bump requestSeq in hide() so every dismissal retires
pending responses.

Add a Vitest + jsdom harness with black-box tests for the
invitee widget, covering the stale-response race both on
field clear and on contact pick.
2026-10-23 14:04:32 +02:00
stefan.tollkuehn e1a3fd12f0 fix indentation 2026-10-23 13:52:45 +02:00
stefan.tollkuehn 00dbbe3421 Document organizer behavior in README
Since the event organizer is the calendar owner's email
address and the link parameter is display information,
the README explains both roles and the CalDAV
scheduling constraint, including the profile email
requirement for working invitations.
2026-10-22 19:49:21 +02:00
stefan.tollkuehn aa35d28f60 fix app path 2026-10-22 19:46:13 +02:00
stefan.tollkuehn 6312c18a91 Harden invitee input and contact names
Security audit found two gaps. Sabre only quotes ICS
parameter values containing space, newline, quote, colon,
semicolon, caret, comma or plus, so a bare carriage
return in a contact name would be written into the
serialized event unquoted and break the line structure;
names with control characters are now dropped. The raw
attendee input and the search query had no length
bound, a huge POST field was fully split, iterated and
echoed back on re-render, a cheap CPU sink; both are
now capped, the query at the longest possible email
fragment.
2026-10-22 19:33:03 +02:00
stefan.tollkuehn 97cea7e90b Make calendar owner the event organizer
The ICS organizer was taken from the external link's
organizer parameter. The CalDAV backend only schedules
invitations when the organizer matches the calendar
owner, so invites never went out under that value. The
event now names the authenticated user's email address;
the link organizer remains the fallback for users
without a profile email and stays visible on the
confirm page as meeting information.
2026-10-22 19:23:25 +02:00
stefan.tollkuehn 9ae3f0a344 Fix 412 on contact search by opting out CSRF
Nextcloud checks the CSRF token on every controller method
without NoCSRFRequired, GET included. The invitee input's
bare fetch sends no request token, so the search answered
412 Precondition Failed. The endpoint is a read-only
address book query without side effects, so the attribute
is safe here.
2026-10-22 19:06:03 +02:00
stefan.tollkuehn cc1fd4e508 Add live contact search to invitee input
The static datalist only carried the first 50 address book
contacts, so typed fragments could not match anything beyond
that. A new read-only GET /contacts/search endpoint queries
the full address book per keystroke, and a small vanilla JS
combobox shows the results and replaces only the fragment
after the last separator, so comma-separated lists keep
working. The server-rendered datalist remains as the no-JS
fallback; the JS removes the list attribute at runtime so
the native popup does not double the custom one.
2026-10-22 18:50:46 +02:00
stefan.tollkuehn 0e5b190971 hide -webkit-calendar-picker-indicator 2026-10-22 18:39:11 +02:00
stefan.tollkuehn 6bfffb675d dropdown arrow for atocal attendees input 2026-10-22 18:37:34 +02:00
stefan.tollkuehn 819109d5a4 dropdown field arrow 2026-10-22 18:35:57 +02:00
stefan.tollkuehn 97ebaf3c06 fix width for atocal-row inputs 2026-10-22 18:33:07 +02:00
stefan.tollkuehn 2070e9c390 add option to invite users to new calendar entry 2026-10-22 18:19:12 +02:00
stefan.tollkuehn 8910a46d1d fix css never been loaded 2026-10-22 17:55:51 +02:00
stefan.tollkuehn 5fc89dfff4 first try of styling things for better usability 2026-10-22 17:40:27 +02:00
stefan.tollkuehn 2703773fe1 - fix: add constructor
- test
2026-10-22 17:33:58 +02:00
stefan.tollkuehn 5febe2c27a add LICENSE text AGPL 3 2026-10-08 14:13:27 +02:00
stefan.tollkuehn 2d141ee46c write tests 2026-10-08 14:09:12 +02:00
stefan.tollkuehn 9abacef435 fix: Event creation could still throw uncaught exceptions 2026-10-08 13:56:49 +02:00
stefan.tollkuehn d485640f57 reject bidi overrides and line separators 2026-10-08 13:54:15 +02:00
stefan.tollkuehn 2e3859795f strengthen assertHttpsUrl 2026-10-08 13:52:03 +02:00
stefan.tollkuehn 9d268c967e bugfix: Application.php did not match the controller constructor resulting a broken app 2026-10-08 13:49:54 +02:00
stefan.tollkuehn ce0b6ccbc7 calendar key uniqueness is now more robust 2026-10-08 13:44:55 +02:00
stefan.tollkuehn f759c2c8d5 translation for german and formal german 2026-10-08 13:42:01 +02:00
stefan.tollkuehn a9b3bcc5d4 show information to user to check if info is valid 2026-10-08 13:36:29 +02:00
stefan.tollkuehn 8b54abe7d4 extract calendar app id to constant 2026-10-08 13:33:07 +02:00
stefan.tollkuehn de814e9530 - check if calender app is enabled or fall back to a plain redirect 2026-10-08 13:32:10 +02:00
stefan.tollkuehn 828feb753a - catch InvalidArgumentException for confirm and create
- more userfriendly error page for malformed links
2026-10-08 13:29:03 +02:00
stefan.tollkuehn 35d5185084 - fix typo
- add function assertClean to reject invalid UFT-8 an control characters
2026-10-08 13:24:12 +02:00
stefan.tollkuehn 3be0490b68 check if calendar is writeable 2026-10-08 13:20:16 +02:00
stefan.tollkuehn 830b53054c - make url validation more robust 2026-10-08 13:04:56 +02:00
stefan.tollkuehn fa398f5b36 fetch writeable calendars of user and display a dropdown in confirm dialog with list of calendars to choose for the event 2026-10-08 12:53:40 +02:00
stefan.tollkuehn f51bb830ab display url in confirmation dialog 2026-10-08 11:10:48 +02:00
stefan.tollkuehn e985c66908 - remove occurances of jitsi-launch as AToCal is more generic
- translate internal documentation
- fix cancelUrl
2026-10-08 11:04:33 +02:00
stefan.tollkuehn b4fc9db09a fix typo 2026-10-08 10:36:24 +02:00
stefan.tollkuehn 29edf89cb2 remove hardcoded nextcloud url 2026-10-08 10:35:31 +02:00
stefan.tollkuehn 5bdbc7477c add default alert (15min before event starts) 2026-10-08 10:14:32 +02:00
stefan.tollkuehn b100d9c986 - rename from jitsi_calendar to atocal, to reflect more the usage. This plugin allows to create events
- add initial documentation
2026-10-08 09:48:54 +02:00
stefan.tollkuehn 8c5d19375e compatibility for nextcloud 35 2026-10-08 09:32:40 +02:00
stefan.tollkuehn 853228b6a9 fix wrong getCalendarsForUser using getCalendarsForPrincipal 2026-10-07 22:57:00 +02:00
stefan.tollkuehn ee452aecec fix CSRF problems 2026-10-07 22:49:50 +02:00
stefan.tollkuehn 8194b25600 test CSRF error 2026-10-07 22:44:33 +02:00
stefan.tollkuehn a2925ac6d1 - mergeUrlIntoDescription
- friendly error if no Personal calendar
- use users timezone if possible
2026-10-07 22:20:07 +02:00
stefan.tollkuehn 8a647ad1a8 use Personal calendar instead of first writeable calendar 2026-10-07 22:05:57 +02:00
stefan.tollkuehn 61079a5542 fixes introduced by Mistral 2026-10-07 22:02:19 +02:00
stefan.tollkuehn 7aac2718b5 initial commit 2026-10-07 21:57:34 +02:00