feat: add password auth flag

This commit is contained in:
Steven 2024-07-27 19:24:37 +08:00
parent b9006f8ce0
commit 8bf7cdfd31
14 changed files with 236 additions and 216 deletions

View File

@ -14,6 +14,7 @@ import (
"github.com/usememos/memos/server"
"github.com/usememos/memos/server/profile"
"github.com/usememos/memos/server/version"
"github.com/usememos/memos/store"
"github.com/usememos/memos/store/db"
)
@ -30,13 +31,6 @@ const (
)
var (
mode string
addr string
port int
data string
driver string
dsn string
public bool
instanceProfile *profile.Profile
rootCmd = &cobra.Command{
@ -47,26 +41,26 @@ var (
dbDriver, err := db.NewDBDriver(instanceProfile)
if err != nil {
cancel()
slog.Error("failed to create db driver", err)
slog.Error("failed to create db driver", "error", err)
return
}
if err := dbDriver.Migrate(ctx); err != nil {
cancel()
slog.Error("failed to migrate database", err)
slog.Error("failed to migrate database", "error", err)
return
}
storeInstance := store.New(dbDriver, instanceProfile)
if err := storeInstance.MigrateManually(ctx); err != nil {
cancel()
slog.Error("failed to migrate manually", err)
slog.Error("failed to migrate manually", "error", err)
return
}
s, err := server.NewServer(ctx, instanceProfile, storeInstance)
if err != nil {
cancel()
slog.Error("failed to create server", err)
slog.Error("failed to create server", "error", err)
return
}
@ -78,7 +72,7 @@ var (
if err := s.Start(ctx); err != nil {
if err != http.ErrServerClosed {
slog.Error("failed to start server", err)
slog.Error("failed to start server", "error", err)
cancel()
}
}
@ -102,15 +96,14 @@ func Execute() error {
}
func init() {
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVarP(&mode, "mode", "m", "demo", `mode of server, can be "prod" or "dev" or "demo"`)
rootCmd.PersistentFlags().StringVarP(&addr, "addr", "a", "", "address of server")
rootCmd.PersistentFlags().IntVarP(&port, "port", "p", 8081, "port of server")
rootCmd.PersistentFlags().StringVarP(&data, "data", "d", "", "data directory")
rootCmd.PersistentFlags().StringVarP(&driver, "driver", "", "", "database driver")
rootCmd.PersistentFlags().StringVarP(&dsn, "dsn", "", "", "database source name(aka. DSN)")
rootCmd.PersistentFlags().BoolVarP(&public, "public", "", false, "")
rootCmd.PersistentFlags().String("mode", "demo", `mode of server, can be "prod" or "dev" or "demo"`)
rootCmd.PersistentFlags().String("addr", "", "address of server")
rootCmd.PersistentFlags().Int("port", 8081, "port of server")
rootCmd.PersistentFlags().String("data", "", "data directory")
rootCmd.PersistentFlags().String("driver", "sqlite", "database driver")
rootCmd.PersistentFlags().String("dsn", "", "database source name(aka. DSN)")
rootCmd.PersistentFlags().Bool("public", false, "")
rootCmd.PersistentFlags().Bool("password-auth", true, "")
err := viper.BindPFlag("mode", rootCmd.PersistentFlags().Lookup("mode"))
if err != nil {
@ -140,22 +133,32 @@ func init() {
if err != nil {
panic(err)
}
err = viper.BindPFlag("password-auth", rootCmd.PersistentFlags().Lookup("password-auth"))
if err != nil {
panic(err)
}
viper.SetDefault("mode", "demo")
viper.SetDefault("driver", "sqlite")
viper.SetDefault("addr", "")
viper.SetDefault("port", 8081)
viper.SetDefault("public", false)
viper.SetDefault("password-auth", true)
viper.SetEnvPrefix("memos")
}
func initConfig() {
viper.AutomaticEnv()
var err error
instanceProfile, err = profile.GetProfile()
if err != nil {
slog.Error("failed to get profile", err)
return
instanceProfile = &profile.Profile{
Mode: viper.GetString("mode"),
Addr: viper.GetString("addr"),
Port: viper.GetInt("port"),
Data: viper.GetString("data"),
Driver: viper.GetString("driver"),
DSN: viper.GetString("dsn"),
Public: viper.GetBool("public"),
PasswordAuth: viper.GetBool("password-auth"),
Version: version.GetCurrentVersion(viper.GetString("mode")),
}
if err := instanceProfile.Validate(); err != nil {
panic(err)
}
fmt.Printf(`---
@ -167,9 +170,10 @@ addr: %s
port: %d
mode: %s
public: %t
password-auth: %t
driver: %s
---
`, instanceProfile.Version, instanceProfile.Data, instanceProfile.DSN, instanceProfile.Addr, instanceProfile.Port, instanceProfile.Mode, instanceProfile.Public, instanceProfile.Driver)
`, instanceProfile.Version, instanceProfile.Data, instanceProfile.DSN, instanceProfile.Addr, instanceProfile.Port, instanceProfile.Mode, instanceProfile.Public, instanceProfile.PasswordAuth, instanceProfile.Driver)
}
func printGreetings() {

View File

@ -3149,3 +3149,6 @@ definitions:
public:
type: boolean
description: public is a flag that the instance is open for other users.
passwordAuth:
type: boolean
description: password_auth is a flag whether the instance allows password authentication.

21
go.mod
View File

@ -41,17 +41,28 @@ require (
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/rs/cors v1.10.1 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/stoewer/go-strcase v1.3.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/exp v0.0.0-20240409090435-93d18d7e34b8 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
modernc.org/libc v1.52.1 // indirect
modernc.org/mathutil v1.6.0 // indirect
@ -77,30 +88,20 @@ require (
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect
github.com/aws/smithy-go v1.20.3 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/soheilhy/cmux v0.1.5
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/protobuf v1.34.2
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

6
go.sum
View File

@ -455,12 +455,14 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=

View File

@ -23,6 +23,8 @@ message WorkspaceProfile {
string mode = 3;
// public is a flag that the instance is open for other users.
bool public = 4;
// password_auth is a flag whether the instance allows password authentication.
bool password_auth = 5;
}
message GetWorkspaceProfileRequest {}

View File

@ -35,6 +35,8 @@ type WorkspaceProfile struct {
Mode string `protobuf:"bytes,3,opt,name=mode,proto3" json:"mode,omitempty"`
// public is a flag that the instance is open for other users.
Public bool `protobuf:"varint,4,opt,name=public,proto3" json:"public,omitempty"`
// password_auth is a flag whether the instance allows password authentication.
PasswordAuth bool `protobuf:"varint,5,opt,name=password_auth,json=passwordAuth,proto3" json:"password_auth,omitempty"`
}
func (x *WorkspaceProfile) Reset() {
@ -97,6 +99,13 @@ func (x *WorkspaceProfile) GetPublic() bool {
return false
}
func (x *WorkspaceProfile) GetPasswordAuth() bool {
if x != nil {
return x.PasswordAuth
}
return false
}
type GetWorkspaceProfileRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -142,37 +151,40 @@ var file_api_v1_workspace_service_proto_rawDesc = []byte{
0x63, 0x65, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x12, 0x0c, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x1a, 0x1c,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x6e, 0x0a, 0x10,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x93, 0x01, 0x0a,
0x10, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c,
0x65, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69,
0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x18,
0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x12, 0x23, 0x0a,
0x0d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x05,
0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x41, 0x75,
0x74, 0x68, 0x22, 0x1c, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61,
0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x32, 0x97, 0x01, 0x0a, 0x10, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65,
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72,
0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x28, 0x2e,
0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74,
0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65,
0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f,
0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e,
0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x6d, 0x6f, 0x64, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x18, 0x04,
0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x22, 0x1c, 0x0a, 0x1a,
0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66,
0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x32, 0x97, 0x01, 0x0a, 0x10, 0x57,
0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
0x82, 0x01, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65,
0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x28, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70,
0x61, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31,
0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c,
0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x61, 0x70, 0x69, 0x2f,
0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2f, 0x70, 0x72, 0x6f,
0x66, 0x69, 0x6c, 0x65, 0x42, 0xad, 0x01, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d,
0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42, 0x15, 0x57, 0x6f, 0x72, 0x6b, 0x73,
0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f,
0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75,
0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x3b, 0x61,
0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4d, 0x41, 0x58, 0xaa, 0x02, 0x0c, 0x4d, 0x65, 0x6d,
0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f,
0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x73,
0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64,
0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x3a, 0x3a, 0x41, 0x70, 0x69,
0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e,
0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65,
0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12,
0x19, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61,
0x63, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x42, 0xad, 0x01, 0x0a, 0x10, 0x63,
0x6f, 0x6d, 0x2e, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x76, 0x31, 0x42,
0x15, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x30, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x75, 0x73, 0x65, 0x6d, 0x65, 0x6d, 0x6f, 0x73, 0x2f, 0x6d, 0x65,
0x6d, 0x6f, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x61, 0x70,
0x69, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x70, 0x69, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4d, 0x41, 0x58,
0xaa, 0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x2e, 0x41, 0x70, 0x69, 0x2e, 0x56, 0x31, 0xca,
0x02, 0x0c, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0xe2, 0x02,
0x18, 0x4d, 0x65, 0x6d, 0x6f, 0x73, 0x5c, 0x41, 0x70, 0x69, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50,
0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0e, 0x4d, 0x65, 0x6d, 0x6f,
0x73, 0x3a, 0x3a, 0x41, 0x70, 0x69, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (

View File

@ -8,30 +8,29 @@ import (
"strings"
"github.com/pkg/errors"
"github.com/spf13/viper"
"github.com/usememos/memos/server/version"
)
// Profile is the configuration to start main server.
type Profile struct {
// Mode can be "prod" or "dev" or "demo"
Mode string `json:"mode"`
Mode string
// Addr is the binding address for server
Addr string `json:"-"`
Addr string
// Port is the binding port for server
Port int `json:"-"`
Port int
// Data is the data directory
Data string `json:"-"`
Data string
// DSN points to where memos stores its own data
DSN string `json:"-"`
DSN string
// Driver is the database driver
// sqlite, mysql
Driver string `json:"-"`
Driver string
// Version is the current version of server
Version string `json:"version"`
Version string
// Pubic is the flag whether the instance is public for others.
Public bool `json:"public"`
Public bool
// PasswordAuth is the flag whether the instance uses password authentication.
PasswordAuth bool
}
func (p *Profile) IsDev() bool {
@ -57,45 +56,36 @@ func checkDataDir(dataDir string) (string, error) {
return dataDir, nil
}
// GetProfile will return a profile for dev or prod.
func GetProfile() (*Profile, error) {
profile := Profile{}
err := viper.Unmarshal(&profile)
if err != nil {
return nil, err
func (p *Profile) Validate() error {
if p.Mode != "demo" && p.Mode != "dev" && p.Mode != "prod" {
p.Mode = "demo"
}
if profile.Mode != "demo" && profile.Mode != "dev" && profile.Mode != "prod" {
profile.Mode = "demo"
}
if profile.Mode == "prod" && profile.Data == "" {
if p.Mode == "prod" && p.Data == "" {
if runtime.GOOS == "windows" {
profile.Data = filepath.Join(os.Getenv("ProgramData"), "memos")
if _, err := os.Stat(profile.Data); os.IsNotExist(err) {
if err := os.MkdirAll(profile.Data, 0770); err != nil {
fmt.Printf("Failed to create data directory: %s, err: %+v\n", profile.Data, err)
return nil, err
p.Data = filepath.Join(os.Getenv("ProgramData"), "memos")
if _, err := os.Stat(p.Data); os.IsNotExist(err) {
if err := os.MkdirAll(p.Data, 0770); err != nil {
fmt.Printf("Failed to create data directory: %s, err: %+v\n", p.Data, err)
return err
}
}
} else {
profile.Data = "/var/opt/memos"
p.Data = "/var/opt/memos"
}
}
dataDir, err := checkDataDir(profile.Data)
dataDir, err := checkDataDir(p.Data)
if err != nil {
fmt.Printf("Failed to check dsn: %s, err: %+v\n", dataDir, err)
return nil, err
return err
}
profile.Data = dataDir
if profile.Driver == "sqlite" && profile.DSN == "" {
dbFile := fmt.Sprintf("memos_%s.db", profile.Mode)
profile.DSN = filepath.Join(dataDir, dbFile)
p.Data = dataDir
if p.Driver == "sqlite" && p.DSN == "" {
dbFile := fmt.Sprintf("memos_%s.db", p.Mode)
p.DSN = filepath.Join(dataDir, dbFile)
}
profile.Version = version.GetCurrentVersion(profile.Mode)
return &profile, nil
return nil
}

View File

@ -224,7 +224,7 @@ func (s *APIV1Service) SignOut(ctx context.Context, _ *v1pb.SignOutRequest) (*em
Name: fmt.Sprintf("%s%d", UserNamePrefix, user.ID),
AccessToken: accessToken,
}); err != nil {
slog.Error("failed to delete access token", slog.Any("err", err))
slog.Error("failed to delete access token", "error", err)
}
}
}

View File

@ -13,9 +13,10 @@ import (
func (s *APIV1Service) GetWorkspaceProfile(ctx context.Context, _ *v1pb.GetWorkspaceProfileRequest) (*v1pb.WorkspaceProfile, error) {
workspaceProfile := &v1pb.WorkspaceProfile{
Version: s.Profile.Version,
Mode: s.Profile.Mode,
Public: s.Profile.Public,
Version: s.Profile.Version,
Mode: s.Profile.Mode,
Public: s.Profile.Public,
PasswordAuth: s.Profile.PasswordAuth,
}
owner, err := s.GetInstanceOwner(ctx)
if err != nil {
@ -24,8 +25,9 @@ func (s *APIV1Service) GetWorkspaceProfile(ctx context.Context, _ *v1pb.GetWorks
if owner != nil {
workspaceProfile.Owner = owner.Name
} else {
// If owner is not found, set public to true.
// If owner is not found, set Public/PasswordAuth to true.
workspaceProfile.Public = true
workspaceProfile.PasswordAuth = true
}
return workspaceProfile, nil
}

View File

@ -102,19 +102,19 @@ func (s *Server) Start(ctx context.Context) error {
go func() {
grpcListener := muxServer.MatchWithWriters(cmux.HTTP2MatchHeaderFieldSendSettings("content-type", "application/grpc"))
if err := s.grpcServer.Serve(grpcListener); err != nil {
slog.Error("failed to serve gRPC", err)
slog.Error("failed to serve gRPC", "error", err)
}
}()
go func() {
httpListener := muxServer.Match(cmux.HTTP1Fast(http.MethodPatch))
s.echoServer.Listener = httpListener
if err := s.echoServer.Start(address); err != nil {
slog.Error("failed to start echo server", err)
slog.Error("failed to start echo server", "error", err)
}
}()
go func() {
if err := muxServer.Serve(); err != nil {
slog.Error("mux server listen error", err)
slog.Error("mux server listen error", "error", err)
}
}()
s.StartBackgroundRunners(ctx)

View File

@ -63,7 +63,7 @@ func (p *S3ObjectPresigner) CheckAndPresign(ctx context.Context) {
s3Client, err := s3.NewClient(ctx, s3Config)
if err != nil {
slog.Error("Failed to create S3 client", slog.Any("err", err))
slog.Error("Failed to create S3 client", "error", err)
continue
}

View File

@ -52,7 +52,7 @@ func (d *DB) GetCurrentDBSize(ctx context.Context) (int64, error) {
" GROUP BY `table_schema`"
rows, err := d.db.QueryContext(ctx, query, d.config.DBName)
if err != nil {
slog.Error("Query db size error, make sure you have enough privilege", err)
slog.Error("Query db size error, make sure you have enough privilege", "error", err)
return 0, err
}
defer rows.Close()

View File

@ -116,57 +116,61 @@ const SignIn = () => {
{workspaceGeneralSetting.customProfile?.title || "Memos"}
</p>
</div>
<form className="w-full mt-2" onSubmit={handleFormSubmit}>
<div className="flex flex-col justify-start items-start w-full gap-4">
<div className="w-full flex flex-col justify-start items-start">
<span className="leading-8 text-gray-600">{t("common.username")}</span>
<Input
className="w-full"
size="lg"
type="text"
readOnly={actionBtnLoadingState.isLoading}
placeholder={t("common.username")}
value={username}
onChange={handleUsernameInputChanged}
required
{commonContext.profile.passwordAuth ? (
<form className="w-full mt-2" onSubmit={handleFormSubmit}>
<div className="flex flex-col justify-start items-start w-full gap-4">
<div className="w-full flex flex-col justify-start items-start">
<span className="leading-8 text-gray-600">{t("common.username")}</span>
<Input
className="w-full"
size="lg"
type="text"
readOnly={actionBtnLoadingState.isLoading}
placeholder={t("common.username")}
value={username}
onChange={handleUsernameInputChanged}
required
/>
</div>
<div className="w-full flex flex-col justify-start items-start">
<span className="leading-8 text-gray-600">{t("common.password")}</span>
<Input
className="w-full"
size="lg"
type="password"
readOnly={actionBtnLoadingState.isLoading}
placeholder={t("common.password")}
value={password}
onChange={handlePasswordInputChanged}
required
/>
</div>
</div>
<div className="flex flex-row justify-start items-center w-full mt-6">
<Checkbox
className="dark:!text-gray-400"
label={t("common.remember-me")}
checked={remember}
onChange={(e) => setRemember(e.target.checked)}
/>
</div>
<div className="w-full flex flex-col justify-start items-start">
<span className="leading-8 text-gray-600">{t("common.password")}</span>
<Input
<div className="flex flex-row justify-end items-center w-full mt-6">
<Button
className="w-full"
size="lg"
type="password"
readOnly={actionBtnLoadingState.isLoading}
placeholder={t("common.password")}
value={password}
onChange={handlePasswordInputChanged}
required
/>
size="md"
type="submit"
disabled={actionBtnLoadingState.isLoading}
loading={actionBtnLoadingState.isLoading}
onClick={handleSignInButtonClick}
>
{t("common.sign-in")}
</Button>
</div>
</div>
<div className="flex flex-row justify-start items-center w-full mt-6">
<Checkbox
className="dark:!text-gray-400"
label={t("common.remember-me")}
checked={remember}
onChange={(e) => setRemember(e.target.checked)}
/>
</div>
<div className="flex flex-row justify-end items-center w-full mt-6">
<Button
className="w-full"
size="md"
type="submit"
disabled={actionBtnLoadingState.isLoading}
loading={actionBtnLoadingState.isLoading}
onClick={handleSignInButtonClick}
>
{t("common.sign-in")}
</Button>
</div>
</form>
{commonContext.profile.public && (
</form>
) : (
<p className="w-full text-2xl mt-2 dark:text-gray-500">Password auth is not allowed.</p>
)}
{commonContext.profile.public && commonContext.profile.passwordAuth && (
<p className="w-full mt-4 text-sm">
<span className="dark:text-gray-500">{t("auth.sign-up-tip")}</span>
<Link to="/auth/signup" className="cursor-pointer ml-2 text-blue-600 hover:underline" unstable_viewTransition>

View File

@ -1,6 +1,6 @@
import { Button, Input } from "@mui/joy";
import { ClientError } from "nice-grpc-web";
import { useEffect, useState } from "react";
import { useState } from "react";
import { toast } from "react-hot-toast";
import { Link } from "react-router-dom";
import AppearanceSelect from "@/components/AppearanceSelect";
@ -26,12 +26,6 @@ const SignUp = () => {
const workspaceGeneralSetting =
workspaceSettingStore.getWorkspaceSettingByKey(WorkspaceSettingKey.GENERAL).generalSetting || WorkspaceGeneralSetting.fromPartial({});
useEffect(() => {
if (!commonContext.profile.public) {
toast.error("Sign up is not allowed.");
}
}, []);
const handleUsernameInputChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
const text = e.target.value as string;
setUsername(text);
@ -85,49 +79,55 @@ const SignUp = () => {
{workspaceGeneralSetting.customProfile?.title || "Memos"}
</p>
</div>
<p className="w-full text-2xl mt-2 dark:text-gray-500">{t("auth.create-your-account")}</p>
<form className="w-full mt-2" onSubmit={handleFormSubmit}>
<div className="flex flex-col justify-start items-start w-full gap-4">
<div className="w-full flex flex-col justify-start items-start">
<span className="leading-8 text-gray-600">{t("common.username")}</span>
<Input
className="w-full"
size="lg"
type="text"
readOnly={actionBtnLoadingState.isLoading}
placeholder={t("common.username")}
value={username}
onChange={handleUsernameInputChanged}
required
/>
</div>
<div className="w-full flex flex-col justify-start items-start">
<span className="leading-8 text-gray-600">{t("common.password")}</span>
<Input
className="w-full"
size="lg"
type="password"
readOnly={actionBtnLoadingState.isLoading}
placeholder={t("common.password")}
value={password}
onChange={handlePasswordInputChanged}
required
/>
</div>
</div>
<div className="flex flex-row justify-end items-center w-full mt-6">
<Button
className="w-full"
size="md"
type="submit"
disabled={actionBtnLoadingState.isLoading}
loading={actionBtnLoadingState.isLoading}
onClick={handleSignUpButtonClick}
>
{t("common.sign-up")}
</Button>
</div>
</form>
{commonContext.profile.public ? (
<>
<p className="w-full text-2xl mt-2 dark:text-gray-500">{t("auth.create-your-account")}</p>
<form className="w-full mt-2" onSubmit={handleFormSubmit}>
<div className="flex flex-col justify-start items-start w-full gap-4">
<div className="w-full flex flex-col justify-start items-start">
<span className="leading-8 text-gray-600">{t("common.username")}</span>
<Input
className="w-full"
size="lg"
type="text"
readOnly={actionBtnLoadingState.isLoading}
placeholder={t("common.username")}
value={username}
onChange={handleUsernameInputChanged}
required
/>
</div>
<div className="w-full flex flex-col justify-start items-start">
<span className="leading-8 text-gray-600">{t("common.password")}</span>
<Input
className="w-full"
size="lg"
type="password"
readOnly={actionBtnLoadingState.isLoading}
placeholder={t("common.password")}
value={password}
onChange={handlePasswordInputChanged}
required
/>
</div>
</div>
<div className="flex flex-row justify-end items-center w-full mt-6">
<Button
className="w-full"
size="md"
type="submit"
disabled={actionBtnLoadingState.isLoading}
loading={actionBtnLoadingState.isLoading}
onClick={handleSignUpButtonClick}
>
{t("common.sign-up")}
</Button>
</div>
</form>
</>
) : (
<p className="w-full text-2xl mt-2 dark:text-gray-500">Sign up is not allowed.</p>
)}
{!commonContext.profile.owner ? (
<p className="w-full mt-4 text-sm font-medium dark:text-gray-500">{t("auth.host-tip")}</p>
) : (