Commit graph

188 commits

Author SHA1 Message Date
52973ffa9a Show host on event slot cards
All checks were successful
/ build (push) Successful in 1m31s
/ deploy (push) Has been skipped
2025-07-16 20:36:28 +02:00
31f80daa86 Fix admin user list being empty
All checks were successful
/ build (push) Successful in 1m33s
/ deploy (push) Has been skipped
After 4ff3dcb the admin user list became empty due to a messing fetch of
the userStore on the admin page.
2025-07-16 20:12:26 +02:00
9013e85ff0 Scroll the now line into view on navigation
All checks were successful
/ build (push) Successful in 1m34s
/ deploy (push) Successful in 16s
When displaying the schedule, scroll it such that the now line is on the
left to make what is displayed by default the most immediately useful
information.
2025-07-16 19:58:01 +02:00
ae1c653af6 Separate event dipslay from event slot display
Pull out the list of events into its own page sorted by name and show
the event slots in chronological order on the schedule page, with past
slots hidden by default.  This makes the content underneath the schedule
the most immediately useful to have in the moment, while the full list
is kept separately and in a predictable order.
2025-07-16 19:37:23 +02:00
848a330f3a Add editing and display of event host
Display and allow editing of the host field of events.
2025-07-16 19:07:36 +02:00
085e348aa8 Hide empty crew list in EventCard
It used to be that the assigned property was not present for clients who
are not crew, but this changed with the client state refactor.  It makes
more sense to only show the crew field if there are any crew present.
2025-07-16 19:02:55 +02:00
4ff3dcb3fe Remove use of async components
When async components are added dynamically to the tree via v-for list
that change their order and position gets messed up.  I am not sure what
causes this, so I will just work around the issue for now and not use
async components.

Components that need async data loaded will instead depend on the parent
page fetching this data during its setup.
2025-07-16 18:59:11 +02:00
345caec57f Run build workflow on tags being pushed
All checks were successful
/ build (push) Successful in 1m28s
/ deploy (push) Has been skipped
For some reason filtering by tags and braches "is not intended", so run
on everything being pushed for now.
2025-07-09 21:22:31 +02:00
281dd1b984 Fix AUTH variables missing PUBLIC prefix in docs 2025-07-09 19:26:38 +02:00
df64d43b38 Sync lock file after manual edits
All checks were successful
/ build (push) Successful in 2m24s
/ deploy (push) Successful in 16s
The package file was manually edited in 2d5af78 to get rid of some
"latest" version specifiers, but this was not synced to the lock file.
2025-07-09 18:36:19 +02:00
f69381c44c Set verbatimModuleSyntax for server code
Some checks failed
/ build (push) Failing after 28s
/ deploy (push) Has been skipped
The nuxi typecheck command complains about type only imports that are
not declared as such, but the VsCode environment does not.  There's
probably a missmatch somewhere in the configuration for Nuxt that I'm
not going to dig into.  Workaround this issue for now by setting the
option in the tsconfig.json file for the server.
2025-07-09 18:10:42 +02:00
0d0e38e4b6 Refactor demo login as an authentication method
Use the authentication method system for the demo login and the
generated accounts.  This makes it possible to toggle it off on
production systems as these shouldn't have it enabled at all.
2025-07-09 18:01:26 +02:00
a33c8e9dac Use SameSite Lax for session cookie
When a user browses to a page from another site, for example via a
shared link we want the browser to send the session cookie so that
the page renders as the user and not confusingly being logged out.

This may cause CSRF vulenrabilities, later work to add CSRF tokens
should be considered.
2025-07-09 15:35:17 +02:00
aaa2faffb1 Implement register and login with Telegram
Add the concept of authentication methods that authenticate an account
where using the telegram login widget is one such method.  If a login is
done with an authentication method that's not associated with any
account the session ends up with the data from the authentication
method in order to allow registering a new account with the
authentication method.

This has to be stored on the session as otherwise it wouldn't be
possible to implement authentication methods such as OAuth2 that takes
the user to a third-party site and then redirects the browser back.
2025-07-09 15:34:57 +02:00
2d6bcebc5a Add note about quoting in configuration guide
The way Nuxt handles environment variables is weird.  Document this to
help others from not falling into its pitfalls.
2025-07-09 14:59:19 +02:00
3f492edea2 Separate rotation and expiry of sessions
If a session is rotate in the middle of a server side rendering then
some random portions of requests made on the server side will fail with
a session taken error as the server is not going to update the cookies
of the client during these requests.

To avoid this pitfall extend the expiry time of sessions to be 10
seconds after the session has been rotated.  This is accomplished by
introducing a new timestamp on sessions called the rotateAt at time
alongside the expiresAt time.  Sessions used after rotateAt that haven't
been rotated get rotated into a new session and the existing session
gets the expiresAt time set to 10 seconds in the future.  Sessions that
are past the expiredAt time have no access.

This makes the logic around session expiry simpler, and also makes it
possible to audit when a session got rotated, and to mark sessions as
expired without a chance to rotate to a new session without having to
resort to a finished flag.
2025-07-09 14:54:54 +02:00
352362b9c3 Ignore deleted users when looking up a user
After the change to converting users to tombstones instead of removing
them from the database several places would accidentally use deleted
user accounts instead of ignoring them.
2025-07-08 16:23:31 +02:00
f4e4dc9f11 Allow abandoning anonymous taken sessions
If an anonymous session is detected as taken the logic preventing the
session from being accidentally deleted would also prevent the user from
recovering from a taken anonymous session.
2025-07-08 16:13:46 +02:00
ebeedff5d0 Add error page for when a session has been taken
Describe to the user what it means when a session has been detected as
taken and provide a means to abandoned the session and log in again.
2025-07-08 16:13:46 +02:00
011687b391 Close event streams for expired sessions
When a session expires close any event streams that have been opened
with that session.  This prevents an attacker with a leaked session
cookie from opening a stream and receiving updates indefinitely without
being detected.

By sending the session the event stream is opened with when the stream
is established this closure on session expiry also serves as a way for
a user agent to be notified whenever its own access level changes.
2025-07-08 16:13:46 +02:00
2d5af78568 Update dependencies 2025-07-07 23:40:27 +02:00
ce1eab7ede Fix syntax error in .editorconfig 2025-07-07 22:51:15 +02:00
1775fac5fd Refactor sessions to frequently rotate
In order to minimise the window of opportunity to steal a session,
automatically rotate it onto a new session on a frequent basis.  This
makes a session cookie older than the automatic rollover time less
likely to grant access and more likely to be detected.

Should a stolen session cookie get rotated while the attacker is using
it, the user will be notificed that their session has been taken the
next time they open the app if the user re-visits the website before the
session is discarded.
2025-07-07 22:50:59 +02:00
d9b78bff69 Move container image to public/owltide
All checks were successful
/ build (push) Successful in 1m33s
/ deploy (push) Successful in 16s
2025-07-02 00:25:43 +02:00
4e6468adac Move the mascot above the title in README.md
All checks were successful
/ build (push) Successful in 1m42s
/ deploy (push) Successful in 16s
2025-07-01 19:51:28 +02:00
526a60c040 Add short-eared owl as the Owltide mascot and icon
All checks were successful
/ build (push) Successful in 2m29s
/ deploy (push) Successful in 26s
I've settled on a short-eared owl (Asio Flammeus) to serve as the mascot
and icon for Owltide. This is not a settled and final decision, but
rather a branding that's good enough for now.

To create the mascot I sketched some owls that I have saved to
/assets/mascot/owl-sketch.png and then selected one I liked.  Going
clockwise from the top right the sketches were based on the reference
photos [1], [2], and [3] found by searching for "owl" on Wikimedia
Commons.  I then lightly refined it to work as a small icon.

To avoid confusing terms that only make sense for software the artworks
are licensed under the Creative Commons Attribution-ShareAlike 4.0
License.  This has a similar spirit to the AGPL and ensures that should
improvements be made upon them they can be incorporated in the project.

[1]: https://commons.wikimedia.org/wiki/File:Athene_cunicularia_-near_Goiania,_Goias,_Brazil-8_edit.jpg
[2]: https://commons.wikimedia.org/wiki/File:Hibou_des_marais.jpg
[3]: https://commons.wikimedia.org/wiki/File:Uhu-muc.jpg
2025-07-01 19:41:59 +02:00
e6cda256ae Set html lang attribute to en 2025-07-01 18:48:01 +02:00
9592cd3160 Name the application Owltide
The name is inspired by the watchful owl perching from the tree tops
with complete overview of all that's going on combined with -tide in
the sense it's used for in words like summertide and eastertide.
2025-07-01 18:41:24 +02:00
1b5fd9f72a Group .license files in VsCode explorer
Add fileNesting rule to group the .license files with the files they
belong to.
2025-06-30 19:29:36 +02:00
e52972853d License under AGPL version 3 or later
I firmly believe in free software.

The application I'm making here have capabilities that I've not seen in
any system.  It presents itself as an opportunity to collaborate on a
tool that serves the people rather than corporations.  Whose incentives
are to help people rather, not make the most money.  And whose terms
ensure that these freedoms and incentives cannot be taken back or
subverted.

I license this software under the AGPL.
2025-06-30 18:58:24 +02:00
344b9acbf8 Render events without a location
All checks were successful
/ build (push) Successful in 1m31s
/ deploy (push) Successful in 16s
Show events that have no locations set. This is useful when drafting a
schedule and having events who's location have yet to be decided.
2025-06-30 16:39:51 +02:00
5144bf2b37 Allow shifts without a role
Allow a shift to have no role associated with it in order to simplify
conflict resolution around situations like a shift being created while
the role it was assoiated with was deleted. This also allows for shifts
that are freestanding to be created in case having a role doesn't make
sense for it.
2025-06-30 16:36:47 +02:00
1d2edf7535 Add dialog showing diff of changes to save
Add a save dialog at the bottom of the screen that is present whenever
there are unsaved changes.  This dialog provides a diff between the
client and server state so that the user can easily confirm the changes
they are about to make are the correct changes before applying them to
the server.
2025-06-30 15:43:15 +02:00
60f898e986 Set updatedAt in the past in demo schedule
Make sure that all of the entities generated in the demo schedule are
updated in the past. Otherwise updates for them will end up rejected
for being before the current entity's updateAt property.

This also sets the origin for the schedule to be yesterday to make it
easiser to demo the schedule between friday and tuesday.
2025-06-30 15:20:57 +02:00
f24dbae5eb Fix logic errors from mixing up client and server
All checks were successful
/ build (push) Successful in 1m33s
/ deploy (push) Successful in 16s
Fix discard and apiUpdate in Location, Role and Shift sometimes breaking
due to the field and serverField versions of the fields being mixed up.
2025-06-29 20:39:05 +02:00
f79f49b0f6 Fix schedule breaking on 2001-09-09 01:46:40Z
Array.sort() sorts by UTF-16 code points even when the items in the
array are numbers.  Fix the schedule breaking when events cross
different powers of 10 in Unix time which caused the junctions to no
longer be sorted by the numeric value of their Unix time.
2025-06-29 20:30:39 +02:00
27c4720328 Fix changes not being detected in SelectDropdown
When modifying the set instead of replacing it with a new set the change
detection logic in Vue.js doesn't properly propagate the change, causing
certain computed properties that depend on them to go stale.

Fix by creating a new set here, which will emit a modelValue:update
event which will propagate through the v-model bindings.
2025-06-29 20:26:32 +02:00
0c5b4c756f Make the first user created an admin
All checks were successful
/ build (push) Successful in 1m31s
/ deploy (push) Successful in 16s
To easily bootstrap of administration of the system make the first
regular user account created into an admin account.
2025-06-28 01:30:39 +02:00
e5e923bc8d Implement database administration
Add routes and admin panel elements for creating a database backup,
restoring from a backup, deleting the existing schedule, and replacing
the database with the demo schedule.  These server as crude ways to
manage the data stored in the system.
2025-06-28 01:30:39 +02:00
b2f48e98e0 Add API utility for requiring an admin session 2025-06-28 00:55:26 +02:00
b0d5cdf791 Refactor slot editing to use searchable selections
All checks were successful
/ build (push) Successful in 1m36s
/ deploy (push) Successful in 16s
Instead of having to type in exactly the name of events or shifts and
then hope you remembered it right, replace these interactions with the
custom select component that gives a complete list of the available
choices and allows quickly searching for the right one.
2025-06-27 18:59:23 +02:00
da65103e05 Use toRaw when calling Set.difference
Vue's proxy handling interferres with the new Set methods causing them
to throw a TypeError when used on Set objects that are replaced by
proxies. Workaround by dropping the proxy when using these.

See https://github.com/vuejs/core/issues/11398
2025-06-27 18:52:16 +02:00
73b28834a1 Allow orphaned event and shit slots
When editing the slots of events and shifts there are certain situations
where the event or shift a slot should belong to becomes unclear or
difficult to reliably assign.  For example when adding a new slot in the
UI it may be desirable to do so before the user has input the event
or shift the slot should belong to.

In these cases, not being able to store the slot into the schedule makes
the UI logic needlessly complicated.  Allow slots to be added that do
not have its assiated relation linked up to make editing and handling
such scenarios easier.
2025-06-27 18:34:37 +02:00
d49ed38185 Add custom select component
The selection of locations, events, roles, shifts and users using the
native <select> element makes for awkward and difficult interactions.
Add an alternative select control that fixes the issues with the poor
handling and navigation of the control when having many options.

The custom select component can handle the selection of either one or
many entity from a ClientMap of entiteis with a name. Typing into the
text box searches the entities by name, arrow keys can navigate and
enter confirms the chosen entity by toggling it's presence in the
selection.
2025-06-27 18:20:24 +02:00
3f9f218ed0 Add composable for string sort and search
To avoid hydration matches string operations need to do the same thing
on the client and server. Add utilities for performing sorting and fuzzy
matching of strings that uses the account's locale.
2025-06-27 18:13:51 +02:00
016930f933 Render overlapping events/shifts in separate rows
All checks were successful
/ build (push) Successful in 1m33s
/ deploy (push) Successful in 15s
Instead of merging overlapping events and shifts when displaying them in
the timetable which causes a very confusing display, add new rows when
events overlap so that each event can be fully displayed without any
overlapping in the table.
2025-06-25 15:38:47 +02:00
5662b890de Fix userStore fetching when not allowed
All checks were successful
/ build (push) Successful in 1m32s
/ deploy (push) Successful in 26s
Fix userStore attempting to fetch the users list when it's either not
logged in or not allowed to fetch the users, causing the schedule page
to not render.
2025-06-24 16:18:28 +02:00
e01e162367 Add About page with info about the project
Provide a rudimentary description of what this project does, existing
features and future planned work.
2025-06-24 16:00:55 +02:00
9299fa2682 Add cards for shifts 2025-06-24 15:41:53 +02:00
afd7aeea04 De-duplicate serverUserToApi
All checks were successful
/ build (push) Successful in 1m32s
/ deploy (push) Successful in 15s
2025-06-24 15:31:47 +02:00