Commit Graph

925 Commits

Author SHA1 Message Date
Biplav Barua def123232a
feat: implement ListActivities pagination (#5468) 2026-03-04 19:08:47 +08:00
Steven 0cf8805184 refactor(sse): move status indicator to avatar badge
Replace the standalone SSE dot above UserMenu with a small badge
overlaid on the bottom-right of the user avatar. Only visible when
status is connecting (yellow) or disconnected (red) — invisible in the
normal connected state, removing constant visual noise.
2026-03-03 23:25:01 +08:00
milvasic ea0892a8b2
feat: add live refresh via Server-Sent Events (SSE) with visual indicator (#5638)
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: milvasic <milvasic@users.noreply.github.com>
2026-03-03 22:56:12 +08:00
Johnny 803d488a5f feat(mcp): refactor MCP server to standard protocol structure
- Replace PAT-only auth with optional auth supporting both PAT and JWT
  via auth.Authenticator.Authenticate(); unauthenticated requests see
  only public memos, matching REST API visibility semantics
- Inline auth middleware into mcp.go following fileserver pattern;
  remove auth_middleware.go
- Introduce memoJSON response type that correctly serialises store.Memo
  (including Payload.Tags and Payload.Property) without proto marshalling
- Add tools: list_memo_comments, create_memo_comment, list_tags
- Extend list_memos with state (NORMAL/ARCHIVED), order_by_pinned, and
  page parameters
- Extend update_memo with pinned and state parameters
- Extract #tags from content on create/update via regex to pre-populate
  Payload.Tags without requiring a full markdown service rebuild
- Add MCP Resources: memo://memos/{uid} template returns memo as
  Markdown with YAML frontmatter, allowing clients to read memos by URI
- Add MCP Prompts: capture (save a thought) and review (search + summarise)
2026-03-01 23:10:23 +08:00
Johnny 7c1defba01 feat(webhook): dispatch webhook on memo comment creation 2026-03-01 20:11:23 +08:00
Steven 26d10212c6 refactor: consolidate duplicated auth logic into auth package
Add ApplyToContext and AuthenticateToUser helpers to the auth package,
then remove the duplicated auth code spread across the MCP middleware,
file server, Connect interceptor, and gRPC-Gateway middleware.

- auth.ApplyToContext: single place to set claims/user into context after Authenticate()
- auth.AuthenticateToUser: resolves any credential (bearer token or refresh cookie) to a *store.User
- MCP middleware: replaced manual PAT DB lookup + expiry check with Authenticator.AuthenticateByPAT
- File server: replaced authenticateByBearerToken/authenticateByRefreshToken with AuthenticateToUser
- Connect interceptor + Gateway middleware: replaced duplicated context-setting block with ApplyToContext
- MCPService now accepts secret to construct its own Authenticator
2026-02-24 23:08:16 +08:00
Steven 47d9414702 feat: add MCP server with PAT authentication
Embeds a Model Context Protocol (MCP) server into the Memos HTTP
process, exposing memo operations as MCP tools at POST/GET /mcp using
Streamable HTTP transport.

Authentication is PAT-only — requests without a valid personal access
token receive HTTP 401. Six tools are exposed: list_memos, get_memo,
create_memo, update_memo, delete_memo, and search_memos, all scoped to the authenticated user.
2026-02-24 22:54:51 +08:00
Steven 704503e556 fix(store): allow memo/attachment deletion when local file is missing
Fixes two bugs reported in #5603:

1. store/attachment.go: ignore os.ErrNotExist when removing a local
   attachment file so that a missing file on disk (broken state from
   failed uploads) no longer blocks deletion of the DB record, allowing
   memos referencing corrupt attachments to be deleted normally.

2. memo_attachment_service.go: add nil guard on GetAttachment result
   before dereferencing it in SetMemoAttachments, preventing a nil
   pointer panic when an attachment UID no longer exists in the DB.
2026-02-23 10:26:40 +08:00
Steven 150371d211 fix(webhook): remediate SSRF vulnerability in webhook dispatcher
- Add plugin/webhook/validate.go as single source of truth for SSRF
  protection: reserved CIDR list parsed once at init(), isReservedIP(),
  and exported ValidateURL() used at registration/update time
- Replace unguarded http.Client in webhook.go with safeClient whose
  Transport uses a custom DialContext that re-resolves hostnames at
  dial time, defeating DNS rebinding attacks
- Call webhook.ValidateURL() in CreateUserWebhook and both
  UpdateUserWebhook paths to reject non-http/https schemes and
  reserved/private IP targets before persisting
- Strip internal service response body from non-2xx error log messages
  to prevent data leakage via application logs
2026-02-23 10:14:24 +08:00
Steven 71e8a06463 chore: upgrade Echo v4 to v5.0.3 2026-02-10 09:15:27 +08:00
Johnny b623162d37 chore: fix static check linter warnings 2026-02-08 21:37:02 +08:00
Johnny 984d9b461b fix: gracefully handle deleted memos in activity service to prevent inbox crashes 2026-02-08 21:26:18 +08:00
Johnny d9dc5be200 fix: replace echo.NewHTTPError with status.Errorf 2026-02-08 19:23:34 +08:00
Johnny 1696c6c414 fix: add nil check for currentUser in DeleteUser
Defense-in-depth fix: Add missing nil check before accessing
currentUser.ID and currentUser.Role in DeleteUser function.

While the auth interceptor should block unauthenticated requests,
this check prevents potential nil pointer panic if fetchCurrentUser
returns (nil, nil).
2026-01-31 23:08:09 +08:00
Johnny c7b48b800f fix: add access control checks for attachments, comments, and reactions
Security fixes for multiple authorization bypass vulnerabilities:

- GetAttachment: Add visibility check via checkAttachmentAccess helper
- UpdateAttachment: Add ownership check (creator or admin only)
- Fileserver: Require creator/admin auth for unlinked attachments
- ListMemoAttachments: Add memo visibility check
- CreateMemoComment: Add memo visibility check for target memo
- ListMemoReactions: Add memo visibility check
- UpsertMemoReaction: Add memo visibility check

All checks follow the existing pattern used in GetMemo for consistency.
2026-01-31 23:02:30 +08:00
Johnny 86fab0cf4c fix(fileserver): use streaming for video/audio to prevent memory exhaustion
- Add serveMediaStream() to stream video/audio without loading into memory
- Use http.ServeFile for local files (zero-copy, handles range requests)
- Redirect to S3 presigned URLs for S3-stored media files
- Refactor for better maintainability:
  - Extract constants and pre-compile lookup maps
  - Consolidate duplicated S3 client creation logic
  - Split authentication into focused helper methods
  - Group code by responsibility with section comments
  - Add setSecurityHeaders() and setMediaHeaders() helpers
2026-01-31 22:01:28 +08:00
Steven b32cba35c6 fix: add nil check for AnyResponse in WrapUnary method to prevent caching issues 2026-01-29 21:32:54 +08:00
Steven b0558824c4 feat: update instance profile to use admin user instead of initialized flag
- Changed InstanceProfile to include admin user field
- Updated GetInstanceProfile method to retrieve admin user
- Modified related tests to reflect changes in admin user retrieval
- Removed owner cache logic and tests, introducing new admin cache tests
2026-01-28 23:27:53 +08:00
Johnny a7b0d71f6e feat: implement EXIF metadata stripping for image uploads 2026-01-26 22:18:44 +08:00
Steven 501e8f1eae chore: implement read-write lock for owner cache 2026-01-22 22:11:47 +08:00
Steven edcddf3c95 chore: fix tests 2026-01-22 21:59:23 +08:00
Steven fd29a98c90 chore: fix linter 2026-01-22 21:03:05 +08:00
Steven ba099b72ed feat: update InstanceProfile to include initialization status
- Removed the owner field from InstanceProfile as it is no longer needed.
- Added an initialized field to InstanceProfile to indicate if the instance has completed first-time setup.
- Updated GetInstanceProfile method to set initialized based on the existence of an admin user.
- Modified tests to reflect changes in InstanceProfile and ensure correct behavior regarding instance initialization.
- Adjusted frontend logic to redirect users based on the initialized status instead of the owner field.
2026-01-22 20:59:40 +08:00
Steven 956ae0ebc5 fix: prevent browser caching of API responses in MetadataInterceptor 2026-01-21 08:12:23 +08:00
Johnny 0f3c9a467d refactor: migrate HOST roles to ADMIN
- Updated the isSuperUser function to only check for ADMIN role.
- Added SQL migration scripts for MySQL, PostgreSQL, and SQLite to change user roles from HOST to ADMIN.
- Created a new SQLite migration to alter the user table structure and ensure data integrity during the migration process.
2026-01-20 23:38:30 +08:00
Johnny 47ebb04dc3 refactor: remove mode flag and introduce explicit demo flag 2026-01-20 22:58:33 +08:00
Johnny dc7ec8a8ad feat: allow setting custom timestamps when creating memos and comments
Allow API users to set custom create_time, update_time, and display_time
when creating memos and comments. This enables importing historical data
with accurate timestamps.

Changes:
- Update proto definitions: change create_time and update_time from
  OUTPUT_ONLY to OPTIONAL to allow setting on creation
- Modify CreateMemo service to handle custom timestamps from request
- Update database drivers (SQLite, MySQL, PostgreSQL) to support
  inserting custom timestamps when provided
- Add comprehensive test coverage for custom timestamp functionality
- Maintain backward compatibility: auto-generated timestamps still
  work when custom values are not provided
- Fix golangci-lint issues in plugin/filter (godot and revive)

Fixes #5483
2026-01-17 12:56:03 +08:00
Steven 61dbca8dc2 fix: prevent browser cache from serving stale memo data (#5470)
This fixes a critical data loss issue where users editing the same memo
on multiple devices would overwrite each other's changes due to aggressive
browser caching, particularly in Chromium-based browsers and PWAs.

Changes:
- Backend: Add Cache-Control headers to all API responses to prevent
  browser HTTP caching
- Frontend: Force fresh fetch from server when opening memo editor by
  invalidating React Query cache
- Frontend: Reduce memo query staleTime from 60s to 10s for better
  collaborative editing support

Fixes #5470
2026-01-13 20:55:21 +08:00
Johnny f58533003b fix: clean up memo_relation and attachments when deleting memo
Fixes #5472

Move cleanup logic to store.DeleteMemo to ensure data consistency:
- Delete memo_relation records where memo is source (MemoID) or target (RelatedMemoID)
- Delete attachments linked to the memo (including S3/local files)

This prevents stale COMMENT records in memo_relation after deleting
a memo that has comments.
2026-01-12 23:18:04 +08:00
Johnny 7053edae27 fix: allow guests to view public memo comments
Add ListMemoComments to public endpoints whitelist so unauthenticated
users can see public comments. The service layer already filters
comments by visibility (only PUBLIC for guests).

Fixes #5471
2026-01-11 22:35:12 +08:00
Faizaan pochi da2dd80e2f
fix: return Unauthenticated instead of PermissionDenied on token expiration (#5454) 2026-01-08 23:21:33 +08:00
Faizaan pochi 7c3fcc297d
fix: allow public memo API access without authentication (#5451) 2026-01-07 20:52:04 +08:00
Steven fb4f3e70dc fix: resolve golangci-lint issues 2026-01-06 20:41:24 +08:00
Steven e1941e7843 fix: attachment type checks 2026-01-06 20:37:04 +08:00
Steven ac37738148 fix: default visibility setting 2026-01-05 21:46:35 +08:00
Johnny 5612fb8f41 feat: add HDR image and video support
- Add HDR detection utilities for wide color gamut formats (HEIC, HEIF, WebP)
- Apply colorSpace attribute to image/video elements for HDR-capable files
- Update frontend components (AttachmentCard, PreviewImageDialog, AttachmentList)
- Expand backend thumbnail generation to support HEIC, HEIF, WebP formats
- Add Color-Gamut response headers to advertise wide gamut support
- Extend avatar MIME type validation for HDR formats

Supported formats:
- Images: HEIC, HEIF, WebP, PNG, JPEG
- Videos: MP4, QuickTime, Matroska, WebM (VP9 Profile 2)

Browser support:
- Safari 14.1+, Chrome 118+, Edge 118+
- Gracefully degrades to sRGB on unsupported browsers
2026-01-03 13:16:56 +08:00
Johnny f66c750075 chore: simplify attachment file writing 2025-12-31 21:54:37 +08:00
Johnny d7284fe867 refactor: nest reaction resource names under memos 2025-12-30 23:29:54 +08:00
Johnny c2aea5a4b7 feat: implement refresh token rotation with sliding window sessions in the auth service 2025-12-30 23:00:15 +08:00
Johnny d7478b8003 perf: optimize memory usage for statistics and image processing 2025-12-30 00:06:23 +08:00
Johnny 5d677828a6 refactor: remove NSFW content settings from instance configuration 2025-12-29 20:13:54 +08:00
Johnny 78aa41336a feat: implement attachment filtering functionality 2025-12-28 18:47:59 +08:00
Johnny 6b0f90f355 chore: prevent sensitive data caching 2025-12-20 12:33:16 +08:00
Steven d0c3908168 refactor: remove deprecated Sessions and AccessTokens settings
- Remove ListSessions and RevokeSession RPC endpoints
- Remove Session message and SessionsSetting from UserSetting
- Remove ACCESS_TOKENS key and AccessTokensSetting
- Update references to use RefreshTokensUserSetting with its own ClientInfo
- Remove UserSessionsSection frontend component
- Clean up user store to remove session and access token settings
- Regenerate protobuf files

The system now uses:
- REFRESH_TOKENS for session management with sliding expiration
- PERSONAL_ACCESS_TOKENS for long-lived API tokens
2025-12-19 08:35:57 +08:00
Steven a6c32908a0 refactor(auth): remove legacy session cookie authentication
- Remove SessionCookieName and SessionSlidingDuration constants
- Remove ExtractSessionCookieFromHeader() function
- Remove SessionIDContextKey and GetSessionID() function
- Remove sessionID parameter from SetUserInContext()
- Remove SessionID field from AuthResult struct
- Remove session cookie extraction from middleware
- Update documentation to reflect JWT + PAT only auth

Session cookies were never being set since migration to refresh token
authentication. This change removes ~50 lines of dead code and clarifies
that the system uses JWT access tokens, refresh tokens, and PATs only.
2025-12-19 00:09:08 +08:00
Johnny 50606a850e fix(auth): resolve token refresh and persistence issues
- Fix cookie expiration timezone to use GMT (RFC 6265 compliance)
- Use Connect RPC client for token refresh instead of fetch
- Fix error code checking (numeric Code.Unauthenticated instead of string)
- Prevent infinite redirect loop when already on /auth page
- Fix protobuf Timestamp conversion using timestampDate helper
- Store access token in sessionStorage to avoid unnecessary refreshes on page reload
- Add refresh token cookie fallback for attachment authentication
- Improve error handling with proper type checking

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 20:56:54 +08:00
Johnny 7932f6d0d0
refactor: user auth improvements (#5360) 2025-12-18 18:15:51 +08:00
Johnny ea14280cb3 feat: enhance attachment handling with MIME type validation 2025-12-17 08:58:43 +08:00
Johnny 40e129b8af refactor(auth): streamline session authentication and cookie handling 2025-12-16 22:23:59 +08:00
Steven 6926764b91 fix: allow unauthenticated CreateUser for first user registration
Add CreateUser to PublicMethods ACL whitelist to fix "authentication required"
error during first-time setup. The CreateUser method already has proper security
logic that automatically assigns HOST role to the first user and enforces
DisallowUserRegistration setting for subsequent users.

Fixes #5352

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-15 23:18:30 +08:00