mirror of
https://github.com/usememos/memos.git
synced 2025-03-23 06:00:08 +01:00
feat: add resource visibility to user setting (#1190)
This commit is contained in:
parent
ae61ade2b1
commit
9577f6dbe8
@ -16,6 +16,8 @@ const (
|
|||||||
UserSettingAppearanceKey UserSettingKey = "appearance"
|
UserSettingAppearanceKey UserSettingKey = "appearance"
|
||||||
// UserSettingMemoVisibilityKey is the key type for user preference memo default visibility.
|
// UserSettingMemoVisibilityKey is the key type for user preference memo default visibility.
|
||||||
UserSettingMemoVisibilityKey UserSettingKey = "memoVisibility"
|
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.
|
// String returns the string format of UserSettingKey type.
|
||||||
@ -27,14 +29,17 @@ func (key UserSettingKey) String() string {
|
|||||||
return "appearance"
|
return "appearance"
|
||||||
case UserSettingMemoVisibilityKey:
|
case UserSettingMemoVisibilityKey:
|
||||||
return "memoVisibility"
|
return "memoVisibility"
|
||||||
|
case UserSettingResourceVisibilityKey:
|
||||||
|
return "resourceVisibility"
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
UserSettingLocaleValue = []string{"en", "zh", "vi", "fr", "nl", "sv", "de", "es", "uk", "ru", "it", "hant", "ko"}
|
UserSettingLocaleValue = []string{"en", "zh", "vi", "fr", "nl", "sv", "de", "es", "uk", "ru", "it", "hant", "ko"}
|
||||||
UserSettingAppearanceValue = []string{"system", "light", "dark"}
|
UserSettingAppearanceValue = []string{"system", "light", "dark"}
|
||||||
UserSettingMemoVisibilityValue = []Visibility{Private, Protected, Public}
|
UserSettingMemoVisibilityValue = []Visibility{Private, Protected, Public}
|
||||||
|
UserSettingResourceVisibilityValue = []Visibility{Private, Protected, Public}
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserSetting struct {
|
type UserSetting struct {
|
||||||
@ -78,6 +83,15 @@ func (upsert UserSettingUpsert) Validate() error {
|
|||||||
if !slices.Contains(UserSettingMemoVisibilityValue, memoVisibilityValue) {
|
if !slices.Contains(UserSettingMemoVisibilityValue, memoVisibilityValue) {
|
||||||
return fmt.Errorf("invalid user setting memo visibility value")
|
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 {
|
} else {
|
||||||
return fmt.Errorf("invalid user setting key")
|
return fmt.Errorf("invalid user setting key")
|
||||||
}
|
}
|
||||||
@ -88,7 +102,7 @@ func (upsert UserSettingUpsert) Validate() error {
|
|||||||
type UserSettingFind struct {
|
type UserSettingFind struct {
|
||||||
UserID int
|
UserID int
|
||||||
|
|
||||||
Key *UserSettingKey `json:"key"`
|
Key UserSettingKey `json:"key"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserSettingDelete struct {
|
type UserSettingDelete struct {
|
||||||
|
@ -30,10 +30,9 @@ func (s *Server) registerMemoRoutes(g *echo.Group) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if memoCreate.Visibility == "" {
|
if memoCreate.Visibility == "" {
|
||||||
userSettingMemoVisibilityKey := api.UserSettingMemoVisibilityKey
|
|
||||||
userMemoVisibilitySetting, err := s.Store.FindUserSetting(ctx, &api.UserSettingFind{
|
userMemoVisibilitySetting, err := s.Store.FindUserSetting(ctx, &api.UserSettingFind{
|
||||||
UserID: userID,
|
UserID: userID,
|
||||||
Key: &userSettingMemoVisibilityKey,
|
Key: api.UserSettingMemoVisibilityKey,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user setting").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find user setting").SetInternal(err)
|
||||||
|
@ -42,7 +42,28 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
|
|||||||
if resourceCreate.ExternalLink != "" && !strings.HasPrefix(resourceCreate.ExternalLink, "http") {
|
if resourceCreate.ExternalLink != "" && !strings.HasPrefix(resourceCreate.ExternalLink, "http") {
|
||||||
return echo.NewHTTPError(http.StatusBadRequest, "Invalid external link")
|
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)
|
resource, err := s.Store.CreateResource(ctx, resourceCreate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create resource").SetInternal(err)
|
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)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to read file").SetInternal(err)
|
||||||
}
|
}
|
||||||
resourceCreate = &api.ResourceCreate{
|
resourceCreate = &api.ResourceCreate{
|
||||||
CreatorID: userID,
|
CreatorID: userID,
|
||||||
Filename: filename,
|
Filename: filename,
|
||||||
Type: filetype,
|
Type: filetype,
|
||||||
Size: size,
|
Size: size,
|
||||||
Blob: fileBytes,
|
Blob: fileBytes,
|
||||||
Visibility: api.Private,
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
storage, err := s.Store.FindStorage(ctx, &api.StorageFind{ID: &storageServiceID})
|
storage, err := s.Store.FindStorage(ctx, &api.StorageFind{ID: &storageServiceID})
|
||||||
@ -136,13 +156,34 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
|
|||||||
Filename: filename,
|
Filename: filename,
|
||||||
Type: filetype,
|
Type: filetype,
|
||||||
ExternalLink: link,
|
ExternalLink: link,
|
||||||
Visibility: api.Private,
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Unsupported storage type")
|
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)
|
resource, err := s.Store.CreateResource(ctx, resourceCreate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create resource").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create resource").SetInternal(err)
|
||||||
|
@ -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) {
|
func findUserSettingList(ctx context.Context, tx *sql.Tx, find *api.UserSettingFind) ([]*userSettingRaw, error) {
|
||||||
where, args := []string{"1 = 1"}, []interface{}{}
|
where, args := []string{"1 = 1"}, []interface{}{}
|
||||||
|
|
||||||
if v := find.Key; v != nil {
|
if v := find.Key.String(); v != "" {
|
||||||
where, args = append(where, "key = ?"), append(args, v.String())
|
where, args = append(where, "key = ?"), append(args, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
where, args = append(where, "user_id = ?"), append(args, find.UserID)
|
where, args = append(where, "user_id = ?"), append(args, find.UserID)
|
||||||
|
@ -34,6 +34,10 @@ const PreferencesSection = () => {
|
|||||||
await userStore.upsertUserSetting("memoVisibility", value);
|
await userStore.upsertUserSetting("memoVisibility", value);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDefaultResourceVisibilityChanged = async (value: string) => {
|
||||||
|
await userStore.upsertUserSetting("resourceVisibility", value);
|
||||||
|
};
|
||||||
|
|
||||||
const handleIsFoldingEnabledChanged = (event: React.ChangeEvent<HTMLInputElement>) => {
|
const handleIsFoldingEnabledChanged = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
userStore.upsertLocalSetting({ ...localSetting, enableFoldMemo: event.target.checked });
|
userStore.upsertLocalSetting({ ...localSetting, enableFoldMemo: event.target.checked });
|
||||||
};
|
};
|
||||||
@ -72,6 +76,24 @@ const PreferencesSection = () => {
|
|||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="form-label selector">
|
||||||
|
<span className="normal-text">Default resource visibility</span>
|
||||||
|
<Select
|
||||||
|
className="!min-w-[10rem] w-auto text-sm"
|
||||||
|
value={setting.resourceVisibility}
|
||||||
|
onChange={(_, visibility) => {
|
||||||
|
if (visibility) {
|
||||||
|
handleDefaultResourceVisibilityChanged(visibility);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{visibilitySelectorItems.map((item) => (
|
||||||
|
<Option key={item.value} value={item.value} className="whitespace-nowrap">
|
||||||
|
{item.text}
|
||||||
|
</Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
<label className="form-label selector">
|
<label className="form-label selector">
|
||||||
<span className="normal-text">{t("setting.preference-section.enable-folding-memo")}</span>
|
<span className="normal-text">{t("setting.preference-section.enable-folding-memo")}</span>
|
||||||
<Switch className="ml-2" checked={localSetting.enableFoldMemo} onChange={handleIsFoldingEnabledChanged} />
|
<Switch className="ml-2" checked={localSetting.enableFoldMemo} onChange={handleIsFoldingEnabledChanged} />
|
||||||
|
@ -10,6 +10,7 @@ const defaultSetting: Setting = {
|
|||||||
locale: "en",
|
locale: "en",
|
||||||
appearance: getSystemColorScheme(),
|
appearance: getSystemColorScheme(),
|
||||||
memoVisibility: "PRIVATE",
|
memoVisibility: "PRIVATE",
|
||||||
|
resourceVisibility: "PRIVATE",
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultLocalSetting: LocalSetting = {
|
const defaultLocalSetting: LocalSetting = {
|
||||||
|
8
web/src/types/modules/setting.d.ts
vendored
8
web/src/types/modules/setting.d.ts
vendored
@ -4,6 +4,7 @@ interface Setting {
|
|||||||
locale: Locale;
|
locale: Locale;
|
||||||
appearance: Appearance;
|
appearance: Appearance;
|
||||||
memoVisibility: Visibility;
|
memoVisibility: Visibility;
|
||||||
|
resourceVisibility: Visibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface LocalSetting {
|
interface LocalSetting {
|
||||||
@ -26,7 +27,12 @@ interface UserMemoVisibilitySetting {
|
|||||||
value: Visibility;
|
value: Visibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserSetting = UserLocaleSetting | UserAppearanceSetting | UserMemoVisibilitySetting;
|
interface UserResourceVisibilitySetting {
|
||||||
|
key: "resourceVisibility";
|
||||||
|
value: Visibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserSetting = UserLocaleSetting | UserAppearanceSetting | UserMemoVisibilitySetting | UserResourceVisibilitySetting;
|
||||||
|
|
||||||
interface UserSettingUpsert {
|
interface UserSettingUpsert {
|
||||||
key: keyof Setting;
|
key: keyof Setting;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user