mirror of
https://github.com/aykhans/slash-e.git
synced 2025-04-20 22:07:15 +00:00
feat: use workspace setting service in frontend
This commit is contained in:
parent
aa247ccef2
commit
8992d48b3e
@ -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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
|
@ -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,
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
|
@ -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,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
|
||||||
}
|
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user