diff --git a/api/user_setting.go b/api/user_setting.go index a396261f..c6f3a202 100644 --- a/api/user_setting.go +++ b/api/user_setting.go @@ -16,6 +16,8 @@ const ( UserSettingAppearanceKey UserSettingKey = "appearance" // UserSettingMemoVisibilityKey is the key type for user preference memo default visibility. UserSettingMemoVisibilityKey UserSettingKey = "memoVisibility" + // UserSettingResourceVisibilityKey is the key type for user preference resource default visibility. + UserSettingResourceVisibilityKey UserSettingKey = "resourceVisibility" ) // String returns the string format of UserSettingKey type. @@ -27,14 +29,17 @@ func (key UserSettingKey) String() string { return "appearance" case UserSettingMemoVisibilityKey: return "memoVisibility" + case UserSettingResourceVisibilityKey: + return "resourceVisibility" } return "" } var ( - UserSettingLocaleValue = []string{"en", "zh", "vi", "fr", "nl", "sv", "de", "es", "uk", "ru", "it", "hant", "ko"} - UserSettingAppearanceValue = []string{"system", "light", "dark"} - UserSettingMemoVisibilityValue = []Visibility{Private, Protected, Public} + UserSettingLocaleValue = []string{"en", "zh", "vi", "fr", "nl", "sv", "de", "es", "uk", "ru", "it", "hant", "ko"} + UserSettingAppearanceValue = []string{"system", "light", "dark"} + UserSettingMemoVisibilityValue = []Visibility{Private, Protected, Public} + UserSettingResourceVisibilityValue = []Visibility{Private, Protected, Public} ) type UserSetting struct { @@ -78,6 +83,15 @@ func (upsert UserSettingUpsert) Validate() error { if !slices.Contains(UserSettingMemoVisibilityValue, memoVisibilityValue) { return fmt.Errorf("invalid user setting memo visibility value") } + } else if upsert.Key == UserSettingResourceVisibilityKey { + resourceVisibilityValue := Private + err := json.Unmarshal([]byte(upsert.Value), &resourceVisibilityValue) + if err != nil { + return fmt.Errorf("failed to unmarshal user setting resource visibility value") + } + if !slices.Contains(UserSettingResourceVisibilityValue, resourceVisibilityValue) { + return fmt.Errorf("invalid user setting resource visibility value") + } } else { return fmt.Errorf("invalid user setting key") } @@ -88,7 +102,7 @@ func (upsert UserSettingUpsert) Validate() error { type UserSettingFind struct { UserID int - Key *UserSettingKey `json:"key"` + Key UserSettingKey `json:"key"` } type UserSettingDelete struct { diff --git a/server/memo.go b/server/memo.go index c4795863..143988d1 100644 --- a/server/memo.go +++ b/server/memo.go @@ -30,10 +30,9 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { } if memoCreate.Visibility == "" { - userSettingMemoVisibilityKey := api.UserSettingMemoVisibilityKey userMemoVisibilitySetting, err := s.Store.FindUserSetting(ctx, &api.UserSettingFind{ UserID: userID, - Key: &userSettingMemoVisibilityKey, + Key: api.UserSettingMemoVisibilityKey, }) if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user setting").SetInternal(err) diff --git a/server/resource.go b/server/resource.go index 593707ef..2e16def3 100644 --- a/server/resource.go +++ b/server/resource.go @@ -42,7 +42,28 @@ func (s *Server) registerResourceRoutes(g *echo.Group) { if resourceCreate.ExternalLink != "" && !strings.HasPrefix(resourceCreate.ExternalLink, "http") { return echo.NewHTTPError(http.StatusBadRequest, "Invalid external link") } - resourceCreate.Visibility = api.Private + if resourceCreate.Visibility == "" { + userResourceVisibilitySetting, err := s.Store.FindUserSetting(ctx, &api.UserSettingFind{ + UserID: userID, + Key: api.UserSettingResourceVisibilityKey, + }) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user setting").SetInternal(err) + } + + if userResourceVisibilitySetting != nil { + resourceVisibility := api.Private + err := json.Unmarshal([]byte(userResourceVisibilitySetting.Value), &resourceVisibility) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "Failed to unmarshal user setting value").SetInternal(err) + } + resourceCreate.Visibility = resourceVisibility + } else { + // Private is the default resource visibility. + resourceCreate.Visibility = api.Private + } + } + resource, err := s.Store.CreateResource(ctx, resourceCreate) if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create resource").SetInternal(err) @@ -100,12 +121,11 @@ func (s *Server) registerResourceRoutes(g *echo.Group) { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to read file").SetInternal(err) } resourceCreate = &api.ResourceCreate{ - CreatorID: userID, - Filename: filename, - Type: filetype, - Size: size, - Blob: fileBytes, - Visibility: api.Private, + CreatorID: userID, + Filename: filename, + Type: filetype, + Size: size, + Blob: fileBytes, } } else { storage, err := s.Store.FindStorage(ctx, &api.StorageFind{ID: &storageServiceID}) @@ -136,13 +156,34 @@ func (s *Server) registerResourceRoutes(g *echo.Group) { Filename: filename, Type: filetype, ExternalLink: link, - Visibility: api.Private, } } else { return echo.NewHTTPError(http.StatusInternalServerError, "Unsupported storage type") } } + if resourceCreate.Visibility == "" { + userResourceVisibilitySetting, err := s.Store.FindUserSetting(ctx, &api.UserSettingFind{ + UserID: userID, + Key: api.UserSettingResourceVisibilityKey, + }) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user setting").SetInternal(err) + } + + if userResourceVisibilitySetting != nil { + resourceVisibility := api.Private + err := json.Unmarshal([]byte(userResourceVisibilitySetting.Value), &resourceVisibility) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "Failed to unmarshal user setting value").SetInternal(err) + } + resourceCreate.Visibility = resourceVisibility + } else { + // Private is the default resource visibility. + resourceCreate.Visibility = api.Private + } + } + resource, err := s.Store.CreateResource(ctx, resourceCreate) if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create resource").SetInternal(err) diff --git a/store/user_setting.go b/store/user_setting.go index 64f14b05..2782defd 100644 --- a/store/user_setting.go +++ b/store/user_setting.go @@ -120,8 +120,8 @@ func upsertUserSetting(ctx context.Context, tx *sql.Tx, upsert *api.UserSettingU func findUserSettingList(ctx context.Context, tx *sql.Tx, find *api.UserSettingFind) ([]*userSettingRaw, error) { where, args := []string{"1 = 1"}, []interface{}{} - if v := find.Key; v != nil { - where, args = append(where, "key = ?"), append(args, v.String()) + if v := find.Key.String(); v != "" { + where, args = append(where, "key = ?"), append(args, v) } where, args = append(where, "user_id = ?"), append(args, find.UserID) diff --git a/web/src/components/Settings/PreferencesSection.tsx b/web/src/components/Settings/PreferencesSection.tsx index 28ff71e6..79708f34 100644 --- a/web/src/components/Settings/PreferencesSection.tsx +++ b/web/src/components/Settings/PreferencesSection.tsx @@ -34,6 +34,10 @@ const PreferencesSection = () => { await userStore.upsertUserSetting("memoVisibility", value); }; + const handleDefaultResourceVisibilityChanged = async (value: string) => { + await userStore.upsertUserSetting("resourceVisibility", value); + }; + const handleIsFoldingEnabledChanged = (event: React.ChangeEvent) => { userStore.upsertLocalSetting({ ...localSetting, enableFoldMemo: event.target.checked }); }; @@ -72,6 +76,24 @@ const PreferencesSection = () => { ))} +
+ Default resource visibility + +