feat: use workspace setting service in frontend

This commit is contained in:
Steven 2023-09-12 21:34:05 +08:00
parent aa247ccef2
commit 8992d48b3e
11 changed files with 120 additions and 301 deletions

View File

@ -66,13 +66,13 @@ func (s *APIV1Service) registerAuthRoutes(g *echo.Group, secret string) {
g.POST("/auth/signup", func(c echo.Context) error { g.POST("/auth/signup", func(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
disallowSignUpSetting, err := s.Store.GetWorkspaceSetting(ctx, &store.FindWorkspaceSetting{ enableSignUpSetting, err := s.Store.GetWorkspaceSetting(ctx, &store.FindWorkspaceSetting{
Key: store.WorkspaceDisallowSignUp, Key: storepb.WorkspaceSettingKey_WORKSAPCE_SETTING_ENABLE_SIGNUP,
}) })
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to get workspace setting, err: %s", err)).SetInternal(err) return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to get workspace setting, err: %s", err)).SetInternal(err)
} }
if disallowSignUpSetting != nil && disallowSignUpSetting.Value == "true" { if enableSignUpSetting != nil && !enableSignUpSetting.GetEnableSignup() {
return echo.NewHTTPError(http.StatusForbidden, "sign up has been disabled") return echo.NewHTTPError(http.StatusForbidden, "sign up has been disabled")
} }

View File

@ -1,10 +1,10 @@
package v1 package v1
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
storepb "github.com/boojack/slash/proto/gen/store"
"github.com/boojack/slash/server/profile" "github.com/boojack/slash/server/profile"
"github.com/boojack/slash/store" "github.com/boojack/slash/store"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
@ -15,25 +15,6 @@ type WorkspaceSetting struct {
Value string `json:"value"` Value string `json:"value"`
} }
type WorkspaceSettingUpsert struct {
Key string `json:"key"`
Value string `json:"value"`
}
func (upsert WorkspaceSettingUpsert) Validate() error {
if upsert.Key == store.WorkspaceDisallowSignUp.String() {
value := false
err := json.Unmarshal([]byte(upsert.Value), &value)
if err != nil {
return fmt.Errorf("failed to unmarshal workspace setting disallow signup value")
}
} else {
return fmt.Errorf("invalid workspace setting key")
}
return nil
}
type WorkspaceProfile struct { type WorkspaceProfile struct {
Profile *profile.Profile `json:"profile"` Profile *profile.Profile `json:"profile"`
DisallowSignUp bool `json:"disallowSignUp"` DisallowSignUp bool `json:"disallowSignUp"`
@ -47,87 +28,16 @@ func (s *APIV1Service) registerWorkspaceRoutes(g *echo.Group) {
DisallowSignUp: false, DisallowSignUp: false,
} }
disallowSignUpSetting, err := s.Store.GetWorkspaceSetting(ctx, &store.FindWorkspaceSetting{ enableSignUpSetting, err := s.Store.GetWorkspaceSetting(ctx, &store.FindWorkspaceSetting{
Key: store.WorkspaceDisallowSignUp, Key: storepb.WorkspaceSettingKey_WORKSAPCE_SETTING_ENABLE_SIGNUP,
}) })
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to find workspace setting, err: %s", err)).SetInternal(err) return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to find workspace setting, err: %s", err)).SetInternal(err)
} }
if disallowSignUpSetting != nil { if enableSignUpSetting != nil {
workspaceProfile.DisallowSignUp = disallowSignUpSetting.Value == "true" workspaceProfile.DisallowSignUp = !enableSignUpSetting.GetEnableSignup()
} }
return c.JSON(http.StatusOK, workspaceProfile) return c.JSON(http.StatusOK, workspaceProfile)
}) })
g.POST("/workspace/setting", func(c echo.Context) error {
ctx := c.Request().Context()
userID, ok := c.Get(UserIDContextKey).(int32)
if !ok {
return echo.NewHTTPError(http.StatusUnauthorized, "missing user in session")
}
user, err := s.Store.GetUser(ctx, &store.FindUser{
ID: &userID,
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to find user, err: %s", err)).SetInternal(err)
}
if user == nil || user.Role != store.RoleAdmin {
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
}
upsert := &WorkspaceSettingUpsert{}
if err := json.NewDecoder(c.Request().Body).Decode(upsert); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("failed to decode request body, err: %s", err)).SetInternal(err)
}
if err := upsert.Validate(); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("invalid request body, err: %s", err)).SetInternal(err)
}
workspaceSetting, err := s.Store.UpsertWorkspaceSetting(ctx, &store.WorkspaceSetting{
Key: store.WorkspaceSettingKey(upsert.Key),
Value: upsert.Value,
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to upsert workspace setting, err: %s", err)).SetInternal(err)
}
return c.JSON(http.StatusOK, convertWorkspaceSettingFromStore(workspaceSetting))
})
g.GET("/workspace/setting", func(c echo.Context) error {
ctx := c.Request().Context()
userID, ok := c.Get(UserIDContextKey).(int32)
if !ok {
return echo.NewHTTPError(http.StatusUnauthorized, "missing user in session")
}
user, err := s.Store.GetUser(ctx, &store.FindUser{
ID: &userID,
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to find user, err: %s", err)).SetInternal(err)
}
if user == nil || user.Role != store.RoleAdmin {
return echo.NewHTTPError(http.StatusUnauthorized, "Unauthorized")
}
list, err := s.Store.ListWorkspaceSettings(ctx, &store.FindWorkspaceSetting{})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, fmt.Sprintf("failed to list workspace settings, err: %s", err)).SetInternal(err)
}
workspaceSettingList := []*WorkspaceSetting{}
for _, workspaceSetting := range list {
workspaceSettingList = append(workspaceSettingList, convertWorkspaceSettingFromStore(workspaceSetting))
}
return c.JSON(http.StatusOK, workspaceSettingList)
})
}
func convertWorkspaceSettingFromStore(workspaceSetting *store.WorkspaceSetting) *WorkspaceSetting {
return &WorkspaceSetting{
Key: workspaceSetting.Key.String(),
Value: workspaceSetting.Value,
}
} }

View File

@ -15,6 +15,7 @@ func isUnauthorizeAllowedMethod(methodName string) bool {
var allowedMethodsOnlyForAdmin = map[string]bool{ var allowedMethodsOnlyForAdmin = map[string]bool{
"/slash.api.v2.UserService/CreateUser": true, "/slash.api.v2.UserService/CreateUser": true,
"/slash.api.v2.UserService/DeleteUser": true, "/slash.api.v2.UserService/DeleteUser": true,
"/slash.api.v2.WorkspaceSettingService/UpdateWorkspaceSetting": true,
} }
// isOnlyForAdminAllowedMethod returns true if the method is allowed to be called only by admin. // isOnlyForAdminAllowedMethod returns true if the method is allowed to be called only by admin.

View File

@ -24,7 +24,7 @@ func NewWorkspaceSettingService(store *store.Store) *WorkspaceSettingService {
} }
func (s *WorkspaceSettingService) GetWorkspaceSetting(ctx context.Context, _ *apiv2pb.GetWorkspaceSettingRequest) (*apiv2pb.GetWorkspaceSettingResponse, error) { func (s *WorkspaceSettingService) GetWorkspaceSetting(ctx context.Context, _ *apiv2pb.GetWorkspaceSettingRequest) (*apiv2pb.GetWorkspaceSettingResponse, error) {
workspaceSettings, err := s.Store.ListWorkspaceSettingsV1(ctx, &store.FindWorkspaceSettingV1{}) workspaceSettings, err := s.Store.ListWorkspaceSettings(ctx, &store.FindWorkspaceSetting{})
if err != nil { if err != nil {
return nil, status.Errorf(codes.Internal, "failed to list workspace settings: %v", err) return nil, status.Errorf(codes.Internal, "failed to list workspace settings: %v", err)
} }
@ -50,7 +50,7 @@ func (s *WorkspaceSettingService) UpdateWorkspaceSetting(ctx context.Context, re
for _, path := range request.UpdateMask { for _, path := range request.UpdateMask {
if path == "enable_signup" { if path == "enable_signup" {
if _, err := s.Store.UpsertWorkspaceSettingV1(ctx, &storepb.WorkspaceSetting{ if _, err := s.Store.UpsertWorkspaceSetting(ctx, &storepb.WorkspaceSetting{
Key: storepb.WorkspaceSettingKey_WORKSAPCE_SETTING_ENABLE_SIGNUP, Key: storepb.WorkspaceSettingKey_WORKSAPCE_SETTING_ENABLE_SIGNUP,
Value: &storepb.WorkspaceSetting_EnableSignup{ Value: &storepb.WorkspaceSetting_EnableSignup{
EnableSignup: request.Setting.EnableSignup, EnableSignup: request.Setting.EnableSignup,
@ -59,7 +59,7 @@ func (s *WorkspaceSettingService) UpdateWorkspaceSetting(ctx context.Context, re
return nil, status.Errorf(codes.Internal, "failed to update workspace setting: %v", err) return nil, status.Errorf(codes.Internal, "failed to update workspace setting: %v", err)
} }
} else if path == "resource_relative_path" { } else if path == "resource_relative_path" {
if _, err := s.Store.UpsertWorkspaceSettingV1(ctx, &storepb.WorkspaceSetting{ if _, err := s.Store.UpsertWorkspaceSetting(ctx, &storepb.WorkspaceSetting{
Key: storepb.WorkspaceSettingKey_WORKSPACE_SETTING_RESOURCE_RELATIVE_PATH, Key: storepb.WorkspaceSettingKey_WORKSPACE_SETTING_RESOURCE_RELATIVE_PATH,
Value: &storepb.WorkspaceSetting_ResourceRelativePath{ Value: &storepb.WorkspaceSetting_ResourceRelativePath{
ResourceRelativePath: request.Setting.ResourceRelativePath, ResourceRelativePath: request.Setting.ResourceRelativePath,

View File

@ -1,31 +1,40 @@
import { Checkbox } from "@mui/joy"; import { Checkbox } from "@mui/joy";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { getWorkspaceProfile, upsertWorkspaceSetting } from "../../helpers/api"; import { WorkspaceSetting } from "@/types/proto/api/v2/workspace_setting_service_pb";
import { getWorkspaceSetting, updateWorkspaceSetting } from "../../helpers/api";
const WorkspaceSection: React.FC = () => { const WorkspaceSection: React.FC = () => {
const [disallowSignUp, setDisallowSignUp] = useState<boolean>(false); const [workspaceSetting, setWorkspaceSetting] = useState<WorkspaceSetting>();
useEffect(() => { useEffect(() => {
getWorkspaceProfile().then(({ data }) => { getWorkspaceSetting().then(({ data }) => {
setDisallowSignUp(data.disallowSignUp); setWorkspaceSetting(data.setting);
}); });
}, []); }, []);
const handleDisallowSignUpChange = async (value: boolean) => { const handleDisallowSignUpChange = async (value: boolean) => {
await upsertWorkspaceSetting("disallow-signup", JSON.stringify(value)); const { data } = await updateWorkspaceSetting(
setDisallowSignUp(value); {
...workspaceSetting,
enableSignup: value,
} as WorkspaceSetting,
["enable_signup"]
);
setWorkspaceSetting(data.setting);
}; };
if (!workspaceSetting) return <></>;
return ( return (
<div className="w-full flex flex-col justify-start items-start space-y-4"> <div className="w-full flex flex-col justify-start items-start space-y-4">
<p className="text-base font-semibold leading-6 text-gray-900">Workspace settings</p> <p className="text-base font-semibold leading-6 text-gray-900">Workspace settings</p>
<div className="w-full flex flex-col justify-start items-start"> <div className="w-full flex flex-col justify-start items-start">
<Checkbox <Checkbox
label="Disable user signup" label="Enable user signup"
checked={disallowSignUp} checked={workspaceSetting.enableSignup}
onChange={(event) => handleDisallowSignUpChange(event.target.checked)} onChange={(event) => handleDisallowSignUpChange(event.target.checked)}
/> />
<p className="mt-2 text-gray-500">Once disabled, other users cannot signup.</p> <p className="mt-2 text-gray-500">Once enabled, other users can signup.</p>
</div> </div>
</div> </div>
); );

View File

@ -1,4 +1,9 @@
import axios from "axios"; import axios from "axios";
import {
GetWorkspaceSettingResponse,
UpdateWorkspaceSettingResponse,
WorkspaceSetting,
} from "@/types/proto/api/v2/workspace_setting_service_pb";
export function getWorkspaceProfile() { export function getWorkspaceProfile() {
return axios.get<WorkspaceProfile>("/api/v1/workspace/profile"); return axios.get<WorkspaceProfile>("/api/v1/workspace/profile");
@ -75,10 +80,14 @@ export function deleteShortcutById(shortcutId: ShortcutId) {
return axios.delete(`/api/v1/shortcut/${shortcutId}`); return axios.delete(`/api/v1/shortcut/${shortcutId}`);
} }
export function upsertWorkspaceSetting(key: string, value: string) { export function getWorkspaceSetting() {
return axios.post(`/api/v1/workspace/setting`, { return axios.get<GetWorkspaceSettingResponse>(`/api/v2/workspace/settings`);
key, }
value,
export function updateWorkspaceSetting(setting: WorkspaceSetting, updateMask: string[]) {
return axios.post<UpdateWorkspaceSettingResponse>(`/api/v2/workspace/settings`, {
setting,
updateMask,
}); });
} }

View File

@ -6,6 +6,7 @@ import (
"net/http" "net/http"
"os" "os"
storepb "github.com/boojack/slash/proto/gen/store"
"github.com/boojack/slash/server/profile" "github.com/boojack/slash/server/profile"
"github.com/boojack/slash/store" "github.com/boojack/slash/store"
"github.com/h2non/filetype" "github.com/h2non/filetype"
@ -30,16 +31,16 @@ func (s *ResourceService) Register(g *echo.Group) {
ctx := c.Request().Context() ctx := c.Request().Context()
resourceID := c.Param("resourceId") resourceID := c.Param("resourceId")
resourceRelativePathSetting, err := s.Store.GetWorkspaceSetting(ctx, &store.FindWorkspaceSetting{ resourceRelativePathSetting, err := s.Store.GetWorkspaceSetting(ctx, &store.FindWorkspaceSetting{
Key: store.WorkspaceResourceRelativePath, Key: storepb.WorkspaceSettingKey_WORKSPACE_SETTING_RESOURCE_RELATIVE_PATH,
}) })
if err != nil { if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "failed to workspace resource relative path setting").SetInternal(err) return echo.NewHTTPError(http.StatusBadRequest, "failed to workspace resource relative path setting").SetInternal(err)
} }
if resourceRelativePathSetting == nil || resourceRelativePathSetting.Value == "" { if resourceRelativePathSetting == nil {
return echo.NewHTTPError(http.StatusBadRequest, "found no workspace resource relative path setting") return echo.NewHTTPError(http.StatusBadRequest, "found no workspace resource relative path setting")
} }
resourceRelativePath := resourceRelativePathSetting.Value resourceRelativePath := resourceRelativePathSetting.GetResourceRelativePath()
resourcePath := fmt.Sprintf("%s/%s", resourceRelativePath, resourceID) resourcePath := fmt.Sprintf("%s/%s", resourceRelativePath, resourceID)
buf, err := os.ReadFile(resourcePath) buf, err := os.ReadFile(resourcePath)
if err != nil { if err != nil {

View File

@ -8,6 +8,7 @@ import (
apiv1 "github.com/boojack/slash/api/v1" apiv1 "github.com/boojack/slash/api/v1"
apiv2 "github.com/boojack/slash/api/v2" apiv2 "github.com/boojack/slash/api/v2"
storepb "github.com/boojack/slash/proto/gen/store"
"github.com/boojack/slash/server/profile" "github.com/boojack/slash/server/profile"
"github.com/boojack/slash/store" "github.com/boojack/slash/store"
"github.com/google/uuid" "github.com/google/uuid"
@ -120,21 +121,23 @@ func (s *Server) GetEcho() *echo.Echo {
} }
func (s *Server) getSystemSecretSessionName(ctx context.Context) (string, error) { func (s *Server) getSystemSecretSessionName(ctx context.Context) (string, error) {
secretSessionNameValue, err := s.Store.GetWorkspaceSetting(ctx, &store.FindWorkspaceSetting{ secretSessionSetting, err := s.Store.GetWorkspaceSetting(ctx, &store.FindWorkspaceSetting{
Key: store.WorkspaceDisallowSignUp, Key: storepb.WorkspaceSettingKey_WORKSPACE_SETTING_SECRET_SESSION,
}) })
if err != nil { if err != nil {
return "", err return "", err
} }
if secretSessionNameValue == nil || secretSessionNameValue.Value == "" { if secretSessionSetting == nil {
tempSecret := uuid.New().String() tempSecret := uuid.New().String()
secretSessionNameValue, err = s.Store.UpsertWorkspaceSetting(ctx, &store.WorkspaceSetting{ secretSessionSetting, err = s.Store.UpsertWorkspaceSetting(ctx, &storepb.WorkspaceSetting{
Key: store.WorkspaceSecretSessionName, Key: storepb.WorkspaceSettingKey_WORKSPACE_SETTING_SECRET_SESSION,
Value: string(tempSecret), Value: &storepb.WorkspaceSetting_SecretSession{
SecretSession: tempSecret,
},
}) })
if err != nil { if err != nil {
return "", err return "", err
} }
} }
return secretSessionNameValue.Value, nil return secretSessionSetting.GetSecretSession(), nil
} }

View File

@ -2,35 +2,19 @@ package store
import ( import (
"context" "context"
"errors"
"strconv"
"strings" "strings"
storepb "github.com/boojack/slash/proto/gen/store"
"google.golang.org/protobuf/encoding/protojson"
) )
type WorkspaceSettingKey string
const (
// WorkspaceSecretSessionName is the key type for secret session name.
WorkspaceSecretSessionName WorkspaceSettingKey = "secret-session-name"
// WorkspaceDisallowSignUp is the key type for disallow sign up in workspace level.
WorkspaceDisallowSignUp WorkspaceSettingKey = "disallow-signup"
// WorkspaceResourceRelativePath is the key type for resource relative path.
WorkspaceResourceRelativePath WorkspaceSettingKey = "resource-relative-path"
)
// String returns the string format of WorkspaceSettingKey type.
func (key WorkspaceSettingKey) String() string {
return string(key)
}
type WorkspaceSetting struct {
Key WorkspaceSettingKey
Value string
}
type FindWorkspaceSetting struct { type FindWorkspaceSetting struct {
Key WorkspaceSettingKey Key storepb.WorkspaceSettingKey
} }
func (s *Store) UpsertWorkspaceSetting(ctx context.Context, upsert *WorkspaceSetting) (*WorkspaceSetting, error) { func (s *Store) UpsertWorkspaceSetting(ctx context.Context, upsert *storepb.WorkspaceSetting) (*storepb.WorkspaceSetting, error) {
stmt := ` stmt := `
INSERT INTO workspace_setting ( INSERT INTO workspace_setting (
key, key,
@ -40,7 +24,24 @@ func (s *Store) UpsertWorkspaceSetting(ctx context.Context, upsert *WorkspaceSet
ON CONFLICT(key) DO UPDATE ON CONFLICT(key) DO UPDATE
SET value = EXCLUDED.value SET value = EXCLUDED.value
` `
if _, err := s.db.ExecContext(ctx, stmt, upsert.Key, upsert.Value); err != nil { var valueString string
if upsert.Key == storepb.WorkspaceSettingKey_WORKSPACE_SETTING_SECRET_SESSION {
valueString = upsert.GetSecretSession()
} else if upsert.Key == storepb.WorkspaceSettingKey_WORKSAPCE_SETTING_ENABLE_SIGNUP {
valueString = strconv.FormatBool(upsert.GetEnableSignup())
} else if upsert.Key == storepb.WorkspaceSettingKey_WORKSPACE_SETTING_RESOURCE_RELATIVE_PATH {
valueString = upsert.GetResourceRelativePath()
} else if upsert.Key == storepb.WorkspaceSettingKey_WORKSPACE_SETTING_AUTO_BACKUP {
valueBytes, err := protojson.Marshal(upsert.GetAutoBackup())
if err != nil {
return nil, err
}
valueString = string(valueBytes)
} else {
return nil, errors.New("invalid workspace setting key")
}
if _, err := s.db.ExecContext(ctx, stmt, upsert.Key.String(), valueString); err != nil {
return nil, err return nil, err
} }
@ -49,11 +50,11 @@ func (s *Store) UpsertWorkspaceSetting(ctx context.Context, upsert *WorkspaceSet
return workspaceSetting, nil return workspaceSetting, nil
} }
func (s *Store) ListWorkspaceSettings(ctx context.Context, find *FindWorkspaceSetting) ([]*WorkspaceSetting, error) { func (s *Store) ListWorkspaceSettings(ctx context.Context, find *FindWorkspaceSetting) ([]*storepb.WorkspaceSetting, error) {
where, args := []string{"1 = 1"}, []any{} where, args := []string{"1 = 1"}, []any{}
if find.Key != "" { if find.Key != storepb.WorkspaceSettingKey_WORKSPACE_SETTING_KEY_UNSPECIFIED {
where, args = append(where, "key = ?"), append(args, find.Key) where, args = append(where, "key = ?"), append(args, find.Key.String())
} }
query := ` query := `
@ -69,15 +70,36 @@ func (s *Store) ListWorkspaceSettings(ctx context.Context, find *FindWorkspaceSe
defer rows.Close() defer rows.Close()
list := []*WorkspaceSetting{} list := []*storepb.WorkspaceSetting{}
for rows.Next() { for rows.Next() {
workspaceSetting := &WorkspaceSetting{} workspaceSetting := &storepb.WorkspaceSetting{}
var keyString, valueString string
if err := rows.Scan( if err := rows.Scan(
&workspaceSetting.Key, &keyString,
&workspaceSetting.Value, &valueString,
); err != nil { ); err != nil {
return nil, err return nil, err
} }
workspaceSetting.Key = storepb.WorkspaceSettingKey(storepb.WorkspaceSettingKey_value[keyString])
if workspaceSetting.Key == storepb.WorkspaceSettingKey_WORKSPACE_SETTING_SECRET_SESSION {
workspaceSetting.Value = &storepb.WorkspaceSetting_SecretSession{SecretSession: valueString}
} else if workspaceSetting.Key == storepb.WorkspaceSettingKey_WORKSAPCE_SETTING_ENABLE_SIGNUP {
enableSignup, err := strconv.ParseBool(valueString)
if err != nil {
return nil, err
}
workspaceSetting.Value = &storepb.WorkspaceSetting_EnableSignup{EnableSignup: enableSignup}
} else if workspaceSetting.Key == storepb.WorkspaceSettingKey_WORKSPACE_SETTING_RESOURCE_RELATIVE_PATH {
workspaceSetting.Value = &storepb.WorkspaceSetting_ResourceRelativePath{ResourceRelativePath: valueString}
} else if workspaceSetting.Key == storepb.WorkspaceSettingKey_WORKSPACE_SETTING_AUTO_BACKUP {
autoBackupSetting := &storepb.AutoBackupWorkspaceSetting{}
if err := protojson.Unmarshal([]byte(valueString), autoBackupSetting); err != nil {
return nil, err
}
workspaceSetting.Value = &storepb.WorkspaceSetting_AutoBackup{AutoBackup: autoBackupSetting}
} else {
return nil, errors.New("invalid workspace setting key")
}
list = append(list, workspaceSetting) list = append(list, workspaceSetting)
} }
@ -93,10 +115,10 @@ func (s *Store) ListWorkspaceSettings(ctx context.Context, find *FindWorkspaceSe
return list, nil return list, nil
} }
func (s *Store) GetWorkspaceSetting(ctx context.Context, find *FindWorkspaceSetting) (*WorkspaceSetting, error) { func (s *Store) GetWorkspaceSetting(ctx context.Context, find *FindWorkspaceSetting) (*storepb.WorkspaceSetting, error) {
if find.Key != "" { if find.Key != storepb.WorkspaceSettingKey_WORKSAPCE_SETTING_ENABLE_SIGNUP {
if cache, ok := s.workspaceSettingCache.Load(find.Key); ok { if cache, ok := s.workspaceSettingCache.Load(find.Key); ok {
return cache.(*WorkspaceSetting), nil return cache.(*storepb.WorkspaceSetting), nil
} }
} }

View File

@ -1,137 +0,0 @@
package store
import (
"context"
"errors"
"strconv"
"strings"
storepb "github.com/boojack/slash/proto/gen/store"
"google.golang.org/protobuf/encoding/protojson"
)
type FindWorkspaceSettingV1 struct {
Key storepb.WorkspaceSettingKey
}
func (s *Store) UpsertWorkspaceSettingV1(ctx context.Context, upsert *storepb.WorkspaceSetting) (*storepb.WorkspaceSetting, error) {
stmt := `
INSERT INTO workspace_setting (
key,
value
)
VALUES (?, ?)
ON CONFLICT(key) DO UPDATE
SET value = EXCLUDED.value
`
var valueString string
if upsert.Key == storepb.WorkspaceSettingKey_WORKSPACE_SETTING_SECRET_SESSION {
valueString = upsert.GetSecretSession()
} else if upsert.Key == storepb.WorkspaceSettingKey_WORKSAPCE_SETTING_ENABLE_SIGNUP {
valueString = strconv.FormatBool(upsert.GetEnableSignup())
} else if upsert.Key == storepb.WorkspaceSettingKey_WORKSPACE_SETTING_RESOURCE_RELATIVE_PATH {
valueString = upsert.GetResourceRelativePath()
} else if upsert.Key == storepb.WorkspaceSettingKey_WORKSPACE_SETTING_AUTO_BACKUP {
valueBytes, err := protojson.Marshal(upsert.GetAutoBackup())
if err != nil {
return nil, err
}
valueString = string(valueBytes)
} else {
return nil, errors.New("invalid workspace setting key")
}
if _, err := s.db.ExecContext(ctx, stmt, upsert.Key.String(), valueString); err != nil {
return nil, err
}
workspaceSetting := upsert
s.workspaceSettingCache.Store(workspaceSetting.Key, workspaceSetting)
return workspaceSetting, nil
}
func (s *Store) ListWorkspaceSettingsV1(ctx context.Context, find *FindWorkspaceSettingV1) ([]*storepb.WorkspaceSetting, error) {
where, args := []string{"1 = 1"}, []any{}
if find.Key != storepb.WorkspaceSettingKey_WORKSPACE_SETTING_KEY_UNSPECIFIED {
where, args = append(where, "key = ?"), append(args, find.Key.String())
}
query := `
SELECT
key,
value
FROM workspace_setting
WHERE ` + strings.Join(where, " AND ")
rows, err := s.db.QueryContext(ctx, query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
list := []*storepb.WorkspaceSetting{}
for rows.Next() {
workspaceSetting := &storepb.WorkspaceSetting{}
var keyString, valueString string
if err := rows.Scan(
&keyString,
&valueString,
); err != nil {
return nil, err
}
workspaceSetting.Key = storepb.WorkspaceSettingKey(storepb.WorkspaceSettingKey_value[keyString])
if workspaceSetting.Key == storepb.WorkspaceSettingKey_WORKSPACE_SETTING_SECRET_SESSION {
workspaceSetting.Value = &storepb.WorkspaceSetting_SecretSession{SecretSession: valueString}
} else if workspaceSetting.Key == storepb.WorkspaceSettingKey_WORKSAPCE_SETTING_ENABLE_SIGNUP {
enableSignup, err := strconv.ParseBool(valueString)
if err != nil {
return nil, err
}
workspaceSetting.Value = &storepb.WorkspaceSetting_EnableSignup{EnableSignup: enableSignup}
} else if workspaceSetting.Key == storepb.WorkspaceSettingKey_WORKSPACE_SETTING_RESOURCE_RELATIVE_PATH {
workspaceSetting.Value = &storepb.WorkspaceSetting_ResourceRelativePath{ResourceRelativePath: valueString}
} else if workspaceSetting.Key == storepb.WorkspaceSettingKey_WORKSPACE_SETTING_AUTO_BACKUP {
autoBackupSetting := &storepb.AutoBackupWorkspaceSetting{}
if err := protojson.Unmarshal([]byte(valueString), autoBackupSetting); err != nil {
return nil, err
}
workspaceSetting.Value = &storepb.WorkspaceSetting_AutoBackup{AutoBackup: autoBackupSetting}
} else {
return nil, errors.New("invalid workspace setting key")
}
list = append(list, workspaceSetting)
}
if err := rows.Err(); err != nil {
return nil, err
}
for _, workspaceSetting := range list {
s.workspaceSettingCache.Store(workspaceSetting.Key, workspaceSetting)
}
return list, nil
}
func (s *Store) GetWorkspaceSettingV1(ctx context.Context, find *FindWorkspaceSettingV1) (*storepb.WorkspaceSetting, error) {
if find.Key != storepb.WorkspaceSettingKey_WORKSAPCE_SETTING_ENABLE_SIGNUP {
if cache, ok := s.workspaceSettingCache.Load(find.Key); ok {
return cache.(*storepb.WorkspaceSetting), nil
}
}
list, err := s.ListWorkspaceSettingsV1(ctx, find)
if err != nil {
return nil, err
}
if len(list) == 0 {
return nil, nil
}
workspaceSetting := list[0]
s.workspaceSettingCache.Store(workspaceSetting.Key, workspaceSetting)
return workspaceSetting, nil
}

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"testing" "testing"
storepb "github.com/boojack/slash/proto/gen/store"
"github.com/boojack/slash/store" "github.com/boojack/slash/store"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -13,13 +14,13 @@ func TestWorkspaceSettingStore(t *testing.T) {
ctx := context.Background() ctx := context.Background()
ts := NewTestingStore(ctx, t) ts := NewTestingStore(ctx, t)
tempSecret := uuid.New().String() tempSecret := uuid.New().String()
workspaceSetting, err := ts.UpsertWorkspaceSetting(ctx, &store.WorkspaceSetting{ workspaceSetting, err := ts.UpsertWorkspaceSetting(ctx, &storepb.WorkspaceSetting{
Key: store.WorkspaceSecretSessionName, Key: storepb.WorkspaceSettingKey_WORKSPACE_SETTING_SECRET_SESSION,
Value: string(tempSecret), Value: &storepb.WorkspaceSetting_SecretSession{SecretSession: tempSecret},
}) })
require.NoError(t, err) require.NoError(t, err)
foundWorkspaceSetting, err := ts.GetWorkspaceSetting(ctx, &store.FindWorkspaceSetting{ foundWorkspaceSetting, err := ts.GetWorkspaceSetting(ctx, &store.FindWorkspaceSetting{
Key: store.WorkspaceSecretSessionName, Key: storepb.WorkspaceSettingKey_WORKSPACE_SETTING_SECRET_SESSION,
}) })
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, workspaceSetting, foundWorkspaceSetting) require.Equal(t, workspaceSetting, foundWorkspaceSetting)