mirror of
https://github.com/aykhans/slash-e.git
synced 2025-04-16 12:23:12 +00:00
feat: add secret session workspace setting
This commit is contained in:
parent
106cdfa7da
commit
2fb0d145a2
@ -57,7 +57,7 @@ func (s *APIV1Service) registerAuthRoutes(g *echo.Group, secret string) {
|
||||
g.POST("/auth/signup", func(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
disallowSignUpSetting, err := s.Store.GetWorkspaceSetting(ctx, &store.FindWorkspaceSetting{
|
||||
Key: WorkspaceDisallowSignUp.String(),
|
||||
Key: store.WorkspaceDisallowSignUp,
|
||||
})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to get workspace setting").SetInternal(err)
|
||||
|
@ -22,7 +22,7 @@ func NewAPIV1Service(profile *profile.Profile, store *store.Store) *APIV1Service
|
||||
func (s *APIV1Service) Start(apiGroup *echo.Group, secret string) {
|
||||
apiV1Group := apiGroup.Group("/api/v1")
|
||||
apiV1Group.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return JWTMiddleware(s, next, string(secret))
|
||||
return JWTMiddleware(s, next, secret)
|
||||
})
|
||||
s.registerWorkspaceRoutes(apiV1Group)
|
||||
s.registerAuthRoutes(apiV1Group, secret)
|
||||
@ -31,7 +31,7 @@ func (s *APIV1Service) Start(apiGroup *echo.Group, secret string) {
|
||||
|
||||
redirectorGroup := apiGroup.Group("/s")
|
||||
redirectorGroup.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return JWTMiddleware(s, next, string(secret))
|
||||
return JWTMiddleware(s, next, secret)
|
||||
})
|
||||
s.registerRedirectorRoutes(redirectorGroup)
|
||||
}
|
||||
|
@ -10,33 +10,18 @@ import (
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type WorkspaceSettingKey string
|
||||
|
||||
const (
|
||||
// WorkspaceDisallowSignUp is the key type for disallow sign up in workspace level.
|
||||
WorkspaceDisallowSignUp WorkspaceSettingKey = "disallow-signup"
|
||||
)
|
||||
|
||||
// String returns the string format of WorkspaceSettingKey type.
|
||||
func (key WorkspaceSettingKey) String() string {
|
||||
if key == WorkspaceDisallowSignUp {
|
||||
return "disallow-signup"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type WorkspaceSetting struct {
|
||||
Key WorkspaceSettingKey `json:"key"`
|
||||
Value string `json:"value"`
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
type WorkspaceSettingUpsert struct {
|
||||
Key WorkspaceSettingKey `json:"key"`
|
||||
Value string `json:"value"`
|
||||
Key string `json:"key"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
func (upsert WorkspaceSettingUpsert) Validate() error {
|
||||
if upsert.Key == WorkspaceDisallowSignUp {
|
||||
if upsert.Key == store.WorkspaceDisallowSignUp.String() {
|
||||
value := false
|
||||
err := json.Unmarshal([]byte(upsert.Value), &value)
|
||||
if err != nil {
|
||||
@ -63,7 +48,7 @@ func (s *APIV1Service) registerWorkspaceRoutes(g *echo.Group) {
|
||||
}
|
||||
|
||||
disallowSignUpSetting, err := s.Store.GetWorkspaceSetting(ctx, &store.FindWorkspaceSetting{
|
||||
Key: WorkspaceDisallowSignUp.String(),
|
||||
Key: store.WorkspaceDisallowSignUp,
|
||||
})
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to get workspace setting")
|
||||
@ -97,11 +82,11 @@ func (s *APIV1Service) registerWorkspaceRoutes(g *echo.Group) {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post workspace setting request").SetInternal(err)
|
||||
}
|
||||
if err := upsert.Validate(); err != nil {
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "system setting invalidate").SetInternal(err)
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "Invalid system setting key or value").SetInternal(err)
|
||||
}
|
||||
|
||||
workspaceSetting, err := s.Store.UpsertWorkspaceSetting(ctx, &store.WorkspaceSetting{
|
||||
Key: upsert.Key.String(),
|
||||
Key: store.WorkspaceSettingKey(upsert.Key),
|
||||
Value: upsert.Value,
|
||||
})
|
||||
if err != nil {
|
||||
@ -142,7 +127,7 @@ func (s *APIV1Service) registerWorkspaceRoutes(g *echo.Group) {
|
||||
|
||||
func convertWorkspaceSettingFromStore(workspaceSetting *store.WorkspaceSetting) *WorkspaceSetting {
|
||||
return &WorkspaceSetting{
|
||||
Key: WorkspaceSettingKey(workspaceSetting.Key),
|
||||
Key: workspaceSetting.Key.String(),
|
||||
Value: workspaceSetting.Value,
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ var (
|
||||
}
|
||||
|
||||
storeInstance := store.New(db.DBInstance, profile)
|
||||
s, err := server.NewServer(profile, storeInstance)
|
||||
s, err := server.NewServer(ctx, profile, storeInstance)
|
||||
if err != nil {
|
||||
cancel()
|
||||
fmt.Printf("failed to create server, error: %+v\n", err)
|
||||
|
4
go.mod
4
go.mod
@ -18,15 +18,12 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/gorilla/context v1.1.1 // indirect
|
||||
github.com/labstack/echo/v4 v4.10.1
|
||||
github.com/labstack/gommon v0.4.0 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/gorilla/securecookie v1.1.1
|
||||
github.com/gorilla/sessions v1.2.1
|
||||
github.com/labstack/echo-contrib v0.14.0
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/spf13/viper v1.15.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
@ -39,6 +36,7 @@ require (
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
|
13
go.sum
13
go.sum
@ -47,6 +47,7 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -126,12 +127,8 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
@ -148,11 +145,11 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/labstack/echo-contrib v0.14.0 h1:tVHJjhqOcB183bzAeNDVwKgf1GWRAM6k9PvIVKEjQ/A=
|
||||
github.com/labstack/echo-contrib v0.14.0/go.mod h1:0tmJZUHWLU7zGvMoxZwotRxHgUqBfW37T6bHg17SgAw=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/labstack/echo/v4 v4.10.1 h1:rB+D8In9PWjsp1OpHaqK+t04nQv/SBD1IoIcXCg0lpY=
|
||||
github.com/labstack/echo/v4 v4.10.1/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
|
||||
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
||||
@ -171,6 +168,7 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
||||
@ -181,7 +179,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qq
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
|
||||
github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
|
||||
|
@ -10,8 +10,6 @@ import (
|
||||
"github.com/boojack/shortify/store"
|
||||
|
||||
"github.com/gorilla/securecookie"
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/labstack/echo-contrib/session"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
)
|
||||
@ -23,7 +21,7 @@ type Server struct {
|
||||
Store *store.Store
|
||||
}
|
||||
|
||||
func NewServer(profile *profile.Profile, store *store.Store) (*Server, error) {
|
||||
func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store) (*Server, error) {
|
||||
e := echo.New()
|
||||
e.Debug = true
|
||||
e.HideBanner = true
|
||||
@ -53,12 +51,15 @@ func NewServer(profile *profile.Profile, store *store.Store) (*Server, error) {
|
||||
|
||||
embedFrontend(e)
|
||||
|
||||
// In dev mode, set the const secret key to make signin session persistence.
|
||||
secret := "iamshortify"
|
||||
// In dev mode, we'd like to set the const secret key to make signin session persistence.
|
||||
secret := "shortify"
|
||||
if profile.Mode == "prod" {
|
||||
secret = string(securecookie.GenerateRandomKey(16))
|
||||
var err error
|
||||
secret, err = s.getSystemSecretSessionName(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
e.Use(session.Middleware(sessions.NewCookieStore([]byte(secret))))
|
||||
|
||||
apiGroup := e.Group("")
|
||||
// Register API v1 routes.
|
||||
@ -88,3 +89,23 @@ func (s *Server) Shutdown(ctx context.Context) {
|
||||
|
||||
fmt.Printf("server stopped properly\n")
|
||||
}
|
||||
|
||||
func (s *Server) getSystemSecretSessionName(ctx context.Context) (string, error) {
|
||||
secretSessionNameValue, err := s.Store.GetWorkspaceSetting(ctx, &store.FindWorkspaceSetting{
|
||||
Key: store.WorkspaceDisallowSignUp,
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if secretSessionNameValue == nil || secretSessionNameValue.Value == "" {
|
||||
tempSecret := securecookie.GenerateRandomKey(16)
|
||||
secretSessionNameValue, err = s.Store.UpsertWorkspaceSetting(ctx, &store.WorkspaceSetting{
|
||||
Key: store.WorkspaceSecretSessionName,
|
||||
Value: string(tempSecret),
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
return secretSessionNameValue.Value, nil
|
||||
}
|
||||
|
@ -6,13 +6,33 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
type WorkspaceSettingKey string
|
||||
|
||||
const (
|
||||
// WorkspaceDisallowSignUp is the key type for disallow sign up in workspace level.
|
||||
WorkspaceDisallowSignUp WorkspaceSettingKey = "disallow-signup"
|
||||
// WorkspaceSecretSessionName is the key type for secret session name.
|
||||
WorkspaceSecretSessionName WorkspaceSettingKey = "secret-session-name"
|
||||
)
|
||||
|
||||
// String returns the string format of WorkspaceSettingKey type.
|
||||
func (key WorkspaceSettingKey) String() string {
|
||||
switch key {
|
||||
case WorkspaceDisallowSignUp:
|
||||
return "disallow-signup"
|
||||
case WorkspaceSecretSessionName:
|
||||
return "secret-session-name"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type WorkspaceSetting struct {
|
||||
Key string
|
||||
Key WorkspaceSettingKey
|
||||
Value string
|
||||
}
|
||||
|
||||
type FindWorkspaceSetting struct {
|
||||
Key string
|
||||
Key WorkspaceSettingKey
|
||||
}
|
||||
|
||||
func (s *Store) UpsertWorkspaceSetting(ctx context.Context, upsert *WorkspaceSetting) (*WorkspaceSetting, error) {
|
||||
|
30
test/store/workspace_setting_test.go
Normal file
30
test/store/workspace_setting_test.go
Normal file
@ -0,0 +1,30 @@
|
||||
package teststore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/boojack/shortify/store"
|
||||
"github.com/gorilla/securecookie"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestWorkspaceSettingStore(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
ts := NewTestingStore(ctx, t)
|
||||
tempSecret := securecookie.GenerateRandomKey(16)
|
||||
workspaceSetting, err := ts.UpsertWorkspaceSetting(ctx, &store.WorkspaceSetting{
|
||||
Key: store.WorkspaceSecretSessionName,
|
||||
Value: string(tempSecret),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
foundWorkspaceSetting, err := ts.GetWorkspaceSetting(ctx, &store.FindWorkspaceSetting{
|
||||
Key: store.WorkspaceSecretSessionName,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, workspaceSetting, foundWorkspaceSetting)
|
||||
workspaceSettings, err := ts.ListWorkspaceSettings(ctx, &store.FindWorkspaceSetting{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(workspaceSettings))
|
||||
require.Equal(t, foundWorkspaceSetting, workspaceSettings[0])
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user