Commit Graph

97 Commits

Author SHA1 Message Date
kolaente cae89caef2 feat(api/v2): add bot user CRUD on /api/v2
Port the BotUser resource from /api/v1's /user/bots routes to the
Huma-backed /api/v2, preserving every v1 behavior:

- Full CRUD at /user/bots and /user/bots/{bot} with v2 verbs (POST
  creates, PUT updates; PATCH is synthesised by AutoPatch).
- ReadAll returns only the caller's own bots; read/update/delete of an
  unowned or missing bot is refused with 403, since ownership is resolved
  by loading the user (no existence disclosure, no 404 branch).
- Create requires a real user account and rejects link shares, the
  bot- username prefix is enforced, and bots are created without an
  email or password — all delegated to the unchanged model layer.
- ReadOne surfaces max_permission via the shared value-embed pattern and
  carries an ETag for conditional requests.

doc/readOnly tags are added to the exposed user.User fields the bot
response surfaces, and to BotUser.Status, so the v2 OpenAPI schema is
documented. The model and v1 routes are untouched.

The webtest ports the v1 model-level permission matrix to the v2 HTTP
surface and adds the v2-only ETag/304 and merge-patch coverage.
2026-06-05 08:51:39 +00:00
kolaente 78ca1904b5
docs(api/v2): mark server-controlled label and user fields read-only 2026-05-31 15:27:44 +02:00
kolaente 3415981d1c feat(models): add BotUser CRUD wrapper 2026-05-01 14:44:10 +00:00
kolaente 83c5190c9b feat(user): add BotOwnerID field and IsBot helper 2026-05-01 14:44:10 +00:00
kolaente af8beb5758 fix(user): skip last-admin guard when target is already unreachable
GuardLastAdmin counted only active, non-deletion-scheduled admins, but gated only on target.IsAdmin. Demoting or deleting an already-disabled or deletion-scheduled admin would then be blocked whenever exactly one active admin remained, even though removing a user who isn't in the reachable set can't reduce the count. Return early when the target isn't part of the counted set.
2026-04-20 18:55:06 +00:00
kolaente d24b96b99c feat(user): extract last-admin guard and close invariant gaps 2026-04-20 18:55:06 +00:00
kolaente 7c7e060d16 feat(auth): include is_admin in JWT claims 2026-04-20 18:55:06 +00:00
kolaente deccc9d29b feat(user): add IsAdmin field to User struct 2026-04-20 18:55:06 +00:00
kolaente 033922309f fix(auth): reject disabled/locked users in CheckUserCredentials
Defense-in-depth: CheckUserCredentials now checks user status after
validating credentials. While current callers are already protected
by upstream checks, this prevents future auth bypass if new code
calls CheckUserCredentials without a subsequent status check.

Ref: GHSA-94xm-jj8x-3cr4
2026-03-23 16:37:26 +00:00
kolaente 37394fb336 fix(user): use getUser directly for uniqueness checks in UpdateUser
The username and email uniqueness checks don't need status filtering —
they just need to know if the name/email exists regardless of account
status. Use getUser (which skips the status check) instead of the
public wrappers, reducing cyclomatic complexity back under the threshold.
2026-03-23 12:06:16 +00:00
kolaente 8409bdb120 refactor(user): export IsErrUserStatusError for use across packages
Make isErrUserStatusError public and replace all verbose
!IsErrAccountDisabled(err) && !IsErrAccountLocked(err) checks
with the shorter IsErrUserStatusError(err) call.
2026-03-23 12:06:16 +00:00
kolaente 91c0f386c6 fix(user): handle status errors in pkg/user callers, remove redundant checks 2026-03-23 12:06:16 +00:00
kolaente 04704e0fde fix(user): reject disabled/locked users in getUser by default
getUser now returns ErrAccountDisabled or ErrAccountLocked (alongside
the full user object) for users with StatusDisabled or StatusAccountLocked.
Callers that need disabled/locked users discard the error; all others
propagate it automatically.

GHSA-94xm-jj8x-3cr4
2026-03-23 12:06:16 +00:00
kolaente f42a045bdc feat: add StatusAccountLocked user status for TOTP lockouts 2026-03-20 11:23:21 +00:00
kolaente 49bba7f830 fix: eliminate nested database sessions to prevent table locks
Refactor functions that created their own sessions when called from
within existing transactions, which caused "database table is locked"
errors in SQLite's shared-cache mode.

Changes:
- Add files.CreateWithSession() to reuse caller's session
- Refactor DeleteBackgroundFileIfExists() to accept session parameter
- Add variadic session parameter to notifications.Notify() and
  Notifiable.ShouldNotify() interface
- Update all Notify callers (~17 sites) to pass their session through
- Use files.CreateWithSession in SaveBackgroundFile and NewAttachment
- Fix test code to commit sessions before assertions
2026-02-25 11:03:02 +01:00
kolaente e90cb2631d fix(auth): remove unnecessary fields from JWT token payloads
Remove email, name, emailRemindersEnabled, and isLocalUser from user JWT
claims, and isLocalUser from link share JWT claims. These fields are never
used from the token - the backend always fetches the full user from the
database by ID, and the frontend fetches user data from the /user API
endpoint immediately after login.

Also simplify GetUserFromClaims to only extract id and username, and
remove the now-unnecessary email override in the frontend's
refreshUserInfo.
2026-02-08 21:30:07 +01:00
renovate[bot] 9a61453e86
fix(deps): update module github.com/labstack/echo/v4 to v5 (#2131)
Closes https://github.com/go-vikunja/vikunja/pull/2133

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: kolaente <k@knt.li>
2026-01-24 20:38:32 +01:00
Weijie Zhao 4fe0763010
fix: properly quote email sender names containing @ symbols (#1768)
When user names contain @ symbols, the email library fails to parse
the sender address format "Name @ Symbol via Vikunja <email@domain.com>".
This fix uses Go's net/mail.Address to properly format the sender
address according to RFC 5322, which automatically quotes names
containing special characters.

Fixes the error: "getting sender address: no FROM address set"
2025-11-07 11:44:24 +01:00
Dominik Pschenitschni feb17792e4
fix(user): persist status on email updates (#1084) 2025-08-04 14:07:00 +00:00
kolaente da0f6fb366 feat(auth): allow passing custom settings links to user account via openid claims 2025-08-03 13:25:32 +02:00
kolaente 42534cdd79
fix: don't panic when using api token when not correctly put into context (#1119) 2025-07-15 21:26:28 +00:00
Weijie Zhao a214d68a44
feat(auth): sync avatar from OpenID providers (#821) 2025-06-16 15:59:31 +02:00
Dominik Pschenitschni 296577a875
fix: correct license header references (#882)
See originals:
- https://www.gnu.org/licenses/agpl-3.0.txt
- https://www.gnu.org/licenses/gpl-3.0.txt
2025-06-10 12:18:38 +02:00
kolaente 5a93379d81
fix(ldap): update user name and email during login 2025-03-20 17:24:00 +01:00
kolaente e12ebfebed
feat(ldap): sync avatar from ldap 2025-03-18 18:28:54 +01:00
kolaente c6cade3aeb
feat(i18n): automatically set language during registration 2025-03-02 13:21:24 +01:00
kolaente e11a3026b9
feat: translate notifications 2025-03-02 11:41:38 +01:00
kolaente 65df9e5ef9
fix: return meaningful error message when selecting an invalid timezone 2025-02-21 17:20:51 +01:00
kolaente 88761db2b1
fix(auth): check for existence of field before casting
Resolves https://vikunja.sentry.io/share/issue/6a21a679011a40b290ac531dd96c2adc/
2025-01-22 09:45:14 +01:00
kolaente 2522cffa61
fix(auth): return proper error when a jwt claim contains wrong data
Resolves https://vikunja.sentry.io/share/issue/69b578ccc3794de58cecfc7b8291ae64/
2025-01-14 16:38:49 +01:00
kolaente 33b9917c7d
fix(auth): return correct error when trying to do a user action as a link share
Resolves https://vikunja.sentry.io/share/issue/77f7aa4cda9442439deba3cfe2cb32c6/
2025-01-14 15:01:13 +01:00
kolaente 28a58303f0
fix(auth): convert to int when failed password value is not int
Resolves https://github.com/go-vikunja/vikunja/issues/377
2024-12-13 20:46:36 +01:00
kolaente 44a43b9f86
fix(auth): restrict max password length to 72 bytes
Bcrypt allows a maximum of 72 bytes. This is part of the algorithm and not something we could change in Vikunja. The solution here was to restrict the password during registration to a max length of 72 bytes. In the future, this should be changed to hash passwords with sha512 or similar before hashing them with bcrypt. Because they should also be salted in that case and the added complexity during the migration phase, this was not implemented yet.
The change in this commit only improves the error handling to return an input error instead of a server error when the user enters a password > 72 bytes.

Resolves https://vikunja.sentry.io/share/issue/e8e0b64612d84504942feee002ac498a/
2024-09-10 18:23:06 +02:00
kolaente 2063da9eec
chore(web): move web handler package to Vikunja 2024-08-29 16:15:28 +02:00
kolaente a5c51d4b1e feat: emoji reactions for tasks and comments (#2196)
This PR adds reactions for tasks and comments, similar to what you can do on Gitea, GitHub, Slack and plenty of other tools.

Reviewed-on: https://kolaente.dev/vikunja/vikunja/pulls/2196
Co-authored-by: kolaente <k@knt.li>
Co-committed-by: kolaente <k@knt.li>
2024-03-12 19:25:58 +00:00
kolaente ad8fa93cae
fix(user): make disable command actually work 2024-01-21 12:24:41 +01:00
kolaente 9a29b29a04
fix(user): allow openid users to request their deletion
Resolves https://community.vikunja.io/t/delete-user-not-possible-when-using-oidc/1689/4
2023-10-11 19:06:59 +02:00
kolaente 80b40bb2c0
feat(notify): don't notify disabled users 2023-09-04 14:23:56 +02:00
edel 11810c9b3e
fix: validate usernames on registration 2023-09-01 17:40:31 +02:00
kolaente e518fb1191
chore: remove year from copyright headers
Resolves https://kolaente.dev/vikunja/api/pulls/1483
2023-09-01 08:32:28 +02:00
kolaente 40037f25f2
fix(user): don't crash when attempting to change a user's password
Resolves https://kolaente.dev/vikunja/api/issues/1587
Resolves https://github.com/go-vikunja/api/issues/79
2023-08-23 15:56:18 +02:00
kolaente 04e2c51fac
feat: allow saving frontend settings via api 2023-06-11 17:49:14 +02:00
kolaente 359d0512cc
fix: upgrade jwt v5 2023-05-23 16:37:16 +02:00
kolaente 349e6a5905
feat: rename lists to projects 2023-03-13 14:28:06 +01:00
kolaente 530bb0a63c
fix(user): make reset the user's name to empty actually work 2023-01-23 18:30:01 +01:00
kolaente 79b31673e2
fix: return 9:00 as default time for reminders if none was set
Resolves https://kolaente.dev/vikunja/api/issues/1211
2022-07-19 16:38:48 +02:00
kolaente 4429ba2da1
fix(caldav): make sure the caldav tokens of non-local accounts are properly checked 2022-07-04 18:08:46 +02:00
kolaente 8869adfc27
feat: add setting to change overdue tasks reminder email time 2022-06-16 16:20:26 +02:00
konrad e4b50e84a4 feat: add caldav tokens (#1065)
# Description

This PR adds API routes to create and manage caldav tokens. These tokens can be used instead of a user password - required for users who are using external auth providers and don't have a password.

Fixes #842

Frontend: https://kolaente.dev/vikunja/frontend/pulls/1186

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/1065
2022-03-30 18:25:56 +00:00
konrad 1322cb16d7 feat: add long-lived api tokens (#1085)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/1085
Co-authored-by: konrad <k@knt.li>
Co-committed-by: konrad <k@knt.li>
2022-02-06 13:18:08 +00:00