diff --git a/.gitignore b/.gitignore index e1107d0..46763ea 100644 --- a/.gitignore +++ b/.gitignore @@ -332,6 +332,7 @@ flycheck_*.el # log *.log /server/logs +/server/cmd/dbmigration/logs # data /server/data diff --git a/server/cmd/dbmigration/main.go b/server/cmd/dbmigration/main.go new file mode 100644 index 0000000..ebfbfb9 --- /dev/null +++ b/server/cmd/dbmigration/main.go @@ -0,0 +1,57 @@ +// Copyright © 2023 OpenIM open source community. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "flag" + "reflect" + + "github.com/OpenIMSDK/OpenKF/server/internal/config" + "github.com/OpenIMSDK/OpenKF/server/internal/conn/db" + "github.com/OpenIMSDK/OpenKF/server/internal/models" + "github.com/OpenIMSDK/OpenKF/server/internal/utils" + "github.com/OpenIMSDK/OpenKF/server/pkg/log" +) + +func init() { + // arg + configPath := flag.String("c", "../../config.yaml", "config file path") + flag.Parse() + + config.ConfigInit(*configPath) + utils.OpenKFBanner() + log.InitLogger() + db.InitMysqlDB() +} + +// migrate table +func main() { + // get db instance + db := db.GetMysqlDB() + + // tables + tables := []interface{}{ + models.User{}, + } + + // migrate + for _, table := range tables { + err := db.AutoMigrate(&table) + if err != nil { + log.Panicf("OpenKF Table Migration", "Migrate table %v... failed", reflect.TypeOf(table)) + } + log.Infof("OpenKF Table Migration", "Migrate table %v... ok", reflect.TypeOf(table)) + } +} diff --git a/server/cmd/gendao/main.go b/server/cmd/gendao/main.go new file mode 100644 index 0000000..a0c1579 --- /dev/null +++ b/server/cmd/gendao/main.go @@ -0,0 +1,17 @@ +// Copyright © 2023 OpenIM open source community. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +// todo: generate dao with template diff --git a/server/cmd/genhooks/main.go b/server/cmd/genhooks/main.go new file mode 100644 index 0000000..dc5cbd2 --- /dev/null +++ b/server/cmd/genhooks/main.go @@ -0,0 +1,44 @@ +// Copyright © 2023 OpenIM open source community. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "flag" + "os" + + "github.com/OpenIMSDK/OpenKF/server/cmd/genhooks/pkg" +) + +var ( + hookName string + urlPattern string + savePath string +) + +func init() { + flag.StringVar(&hookName, "name", "", "hook name") + flag.StringVar(&urlPattern, "pattern", "", "url pattern") + flag.StringVar(&savePath, "path", "../../internal/middleware/hooks", "save path") + flag.Parse() + + if hookName == "" || savePath == "" { + flag.Usage() + os.Exit(1) + } +} + +func main() { + pkg.NewHookGenerator(hookName, urlPattern, savePath).Generate().Format().Flush() +} diff --git a/server/cmd/genhooks/pkg/gen.go b/server/cmd/genhooks/pkg/gen.go new file mode 100644 index 0000000..d1202be --- /dev/null +++ b/server/cmd/genhooks/pkg/gen.go @@ -0,0 +1,75 @@ +// Copyright © 2023 OpenIM open source community. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pkg + +import ( + "bytes" + "fmt" + "go/format" + "io/fs" + "io/ioutil" + "strings" +) + +type HookGenerator struct { + buf *bytes.Buffer + config *config + savePath string +} + +type config struct { + HookName string + UrlPattern string +} + +func NewHookGenerator(hookName, urlPattern, savePath string) *HookGenerator { + return &HookGenerator{ + buf: bytes.NewBuffer(nil), + config: &config{ + HookName: hookName, + UrlPattern: urlPattern, + }, + savePath: savePath, + } +} + +func (g *HookGenerator) Generate() *HookGenerator { + if err := hookTemplate.Execute(g.buf, g.config); err != nil { + panic(err) + } + + return g +} + +func (g *HookGenerator) Format() *HookGenerator { + formatOut, err := format.Source(g.buf.Bytes()) + if err != nil { + panic(err) + } + g.buf = bytes.NewBuffer(formatOut) + + return g +} + +func (g *HookGenerator) Flush() { + filename := fmt.Sprintf("gen_%s_hook.go", strings.ToLower(g.config.HookName)) + if err := ioutil.WriteFile( + fmt.Sprintf("%s/%s", g.savePath, filename), + g.buf.Bytes(), + fs.ModePerm); err != nil { + panic(err) + } + fmt.Println("[OpenKF] gen file ok: ", fmt.Sprintf("%s/%s", g.savePath, filename)) +} diff --git a/server/cmd/genhooks/pkg/template.go b/server/cmd/genhooks/pkg/template.go new file mode 100644 index 0000000..138880f --- /dev/null +++ b/server/cmd/genhooks/pkg/template.go @@ -0,0 +1,68 @@ +// Copyright © 2023 OpenIM open source community. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package pkg + +import "html/template" + +func checkTemplate(t string) *template.Template { + return template.Must(template.New("").Parse(t)) +} + +var hookTemplate = checkTemplate(` +// Copyright © 2023 OpenIM open source community. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hooks + +import ( + urltrie "github.com/OpenIMSDK/OpenKF/server/internal/middleware/hooks/url_trie" + "github.com/gin-gonic/gin" +) + +func init() { + urltrie.RegisterHook({{.HookName}}{}) + fmt.Println("RegisterHook", "Register Hook[{{.HookName}}] success...") +} + +type {{.HookName}} struct { + urltrie.Hook +} + +// EDIT THIS TO YOUR OWN HOOK PATTERN +func (h {{.HookName}}) Pattern() string { + return "{{.UrlPattern}}" +} + +// EDIT THIS TO YOUR OWN HOOK BEFORE RUN +func (h {{.HookName}}) BeforeRun(c *gin.Context) { + c.Next() +} + +// EDIT THIS TO YOUR OWN HOOK AFTER RUN +func (h {{.HookName}}) AfterRun(c *gin.Context) { + c.Next() +} +`) diff --git a/server/config-example.yaml b/server/config-example.yaml index f0f599b..e985ba0 100644 --- a/server/config-example.yaml +++ b/server/config-example.yaml @@ -32,6 +32,9 @@ mysql: username: root password: 123123 database: openkf + max_lifetime: 120 + max_open_conns: 100 + max_idle_conns: 20 redis: ip: 127.0.0.1 diff --git a/server/config.yaml b/server/config.yaml index f0f599b..e985ba0 100644 --- a/server/config.yaml +++ b/server/config.yaml @@ -32,6 +32,9 @@ mysql: username: root password: 123123 database: openkf + max_lifetime: 120 + max_open_conns: 100 + max_idle_conns: 20 redis: ip: 127.0.0.1 diff --git a/server/internal/config/config.go b/server/internal/config/config.go index 64aa174..f0b28c5 100644 --- a/server/internal/config/config.go +++ b/server/internal/config/config.go @@ -37,11 +37,14 @@ func ConfigInit(configPath string) { Port: GetInt("server.port"), }, Mysql: Mysql{ - Ip: GetString("mysql.ip"), - Port: GetInt("mysql.port"), - Username: GetString("mysql.username"), - Password: GetString("mysql.password"), - Database: GetString("mysql.database"), + Ip: GetString("mysql.ip"), + Port: GetInt("mysql.port"), + Username: GetString("mysql.username"), + Password: GetString("mysql.password"), + Database: GetString("mysql.database"), + MaxLifetime: GetIntOrDefault("mysql.max_lifetime", 120), + MaxOpenConns: GetIntOrDefault("mysql.max_open_conns", 100), + MaxIdleConns: GetIntOrDefault("mysql.max_idle_conns", 20), }, Redis: Redis{ Ip: GetString("redis.ip"), @@ -96,11 +99,14 @@ type Server struct { } type Mysql struct { - Ip string `mapstructure:"ip"` - Port int `mapstructure:"port"` - Username string `mapstructure:"username"` - Password string `mapstructure:"password"` - Database string `mapstructure:"database"` + Ip string `mapstructure:"ip"` + Port int `mapstructure:"port"` + Username string `mapstructure:"username"` + Password string `mapstructure:"password"` + Database string `mapstructure:"database"` + MaxLifetime int `mapstructure:"max_lifetime"` + MaxOpenConns int `mapstructure:"max_open_conns"` + MaxIdleConns int `mapstructure:"max_idle_conns"` } type Redis struct { diff --git a/server/internal/config/viper.go b/server/internal/config/viper.go index ad8973d..b493889 100644 --- a/server/internal/config/viper.go +++ b/server/internal/config/viper.go @@ -32,18 +32,36 @@ func initViper(configPath string) { fmt.Println("Load ok") } +// get config func GetInterface(key string) interface{} { return viper.Get(key) } - func GetString(key string) string { return viper.GetString(key) } - func GetInt(key string) int { return viper.GetInt(key) } - func GetBool(key string) bool { return viper.GetBool(key) } + +// get config or use default +func GetStringOrDefault(key string, defaultValue string) string { + if viper.IsSet(key) { + return viper.GetString(key) + } + return defaultValue +} +func GetIntOrDefault(key string, defaultValue int) int { + if viper.IsSet(key) { + return viper.GetInt(key) + } + return defaultValue +} +func GetBoolOrDefault(key string, defaultValue bool) bool { + if viper.IsSet(key) { + return viper.GetBool(key) + } + return defaultValue +} diff --git a/server/internal/client/mail.go b/server/internal/conn/client/mail.go similarity index 100% rename from server/internal/client/mail.go rename to server/internal/conn/client/mail.go diff --git a/server/internal/client/minio.go b/server/internal/conn/client/minio.go similarity index 100% rename from server/internal/client/minio.go rename to server/internal/conn/client/minio.go diff --git a/server/internal/db/mysql.go b/server/internal/conn/db/mysql.go similarity index 93% rename from server/internal/db/mysql.go rename to server/internal/conn/db/mysql.go index c7de389..2e9c7ae 100644 --- a/server/internal/db/mysql.go +++ b/server/internal/conn/db/mysql.go @@ -90,10 +90,11 @@ func InitMysqlDB() { if err != nil { log.Panic("Mysql", err.Error(), " db.DB() failed ") } - // default is unlimited - sqlDB.SetConnMaxLifetime(time.Second * time.Duration(0)) - sqlDB.SetMaxOpenConns(0) - sqlDB.SetMaxIdleConns(0) + + // set connect result + sqlDB.SetConnMaxLifetime(time.Second * time.Duration(config.Config.Mysql.MaxLifetime)) + sqlDB.SetMaxOpenConns(config.Config.Mysql.MaxOpenConns) + sqlDB.SetMaxIdleConns(config.Config.Mysql.MaxIdleConns) db.Set("gorm:table_options", "CHARSET=utf8mb4") db.Set("gorm:table_options", "collation=utf8_unicode_ci") diff --git a/server/internal/db/redis.go b/server/internal/conn/db/redis.go similarity index 100% rename from server/internal/db/redis.go rename to server/internal/conn/db/redis.go diff --git a/server/internal/middleware/hooks/global_hook.go b/server/internal/middleware/hooks/global_hook.go new file mode 100644 index 0000000..b4b048b --- /dev/null +++ b/server/internal/middleware/hooks/global_hook.go @@ -0,0 +1,45 @@ +// Copyright © 2023 OpenIM open source community. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hooks + +import ( + "fmt" + + urltrie "github.com/OpenIMSDK/OpenKF/server/internal/middleware/hooks/url_trie" + "github.com/OpenIMSDK/OpenKF/server/pkg/log" + "github.com/gin-gonic/gin" +) + +func init() { + urltrie.RegisterHook(GlobalHook{}) + fmt.Println("RegisterHook", "Register Hook[GlobalHook] success...") +} + +type GlobalHook struct { + urltrie.Hook +} + +func (h GlobalHook) Pattern() string { + return "/*" +} + +func (h GlobalHook) BeforeRun(c *gin.Context) { + log.Debugf("GlobalHook", "path: %v", c.Request.URL.Path) + c.Next() +} + +func (h GlobalHook) AfterRun(c *gin.Context) { + c.Next() +} diff --git a/server/internal/middleware/hooks/init.go b/server/internal/middleware/hooks/init.go new file mode 100644 index 0000000..08b15ca --- /dev/null +++ b/server/internal/middleware/hooks/init.go @@ -0,0 +1,19 @@ +// Copyright © 2023 OpenIM open source community. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hooks + +// Manual import hooks packages and do init +func InitHooks() { +} diff --git a/server/internal/middleware/hooks/mail_hook.go b/server/internal/middleware/hooks/mail_hook.go new file mode 100644 index 0000000..b58bb3f --- /dev/null +++ b/server/internal/middleware/hooks/mail_hook.go @@ -0,0 +1,45 @@ +// Copyright © 2023 OpenIM open source community. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package hooks + +import ( + "fmt" + + urltrie "github.com/OpenIMSDK/OpenKF/server/internal/middleware/hooks/url_trie" + "github.com/OpenIMSDK/OpenKF/server/pkg/log" + "github.com/gin-gonic/gin" +) + +func init() { + urltrie.RegisterHook(MailHook{}) + fmt.Println("RegisterHook", "Register Hook[MailHook] success...") +} + +type MailHook struct { + urltrie.Hook +} + +func (h MailHook) Pattern() string { + return "/api/v1/register/email/code" +} + +func (h MailHook) BeforeRun(c *gin.Context) { + log.Debugf("GlobalHook", "path: %v", c.Request.URL.Path) + c.Next() +} + +func (h MailHook) AfterRun(c *gin.Context) { + c.Next() +} diff --git a/server/internal/middleware/hooks/url_trie/hook.go b/server/internal/middleware/hooks/url_trie/hook.go new file mode 100644 index 0000000..4c43595 --- /dev/null +++ b/server/internal/middleware/hooks/url_trie/hook.go @@ -0,0 +1,61 @@ +// Copyright © 2023 OpenIM open source community. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package urltrie + +import ( + "net/url" + + "github.com/OpenIMSDK/OpenKF/server/pkg/log" + "github.com/gin-gonic/gin" +) + +// Mapping for store url pattern and hook +var hookTrie *Trie + +func init() { + hookTrie = NewTrie() +} + +// Register url & hook to trie +func RegisterHook(hook Hook) { + hookTrie.Insert(hook.Pattern(), hook) +} + +// Enable hook for interceptor +func RunHook() gin.HandlerFunc { + return func(c *gin.Context) { + raw := c.Request.URL.Path + + // get path from url + p, err := url.Parse(raw) + if err != nil { + log.Errorf("Hook", "parse url error: %v", err) + } + + path := p.Path + hooks, ok := hookTrie.Match(path) + if !ok { + c.Next() + return + } + + // run hooks + for _, hook := range hooks { + hook.BeforeRun(c) + c.Next() + hook.AfterRun(c) + } + } +} diff --git a/server/internal/middleware/hooks/url_trie/trie.go b/server/internal/middleware/hooks/url_trie/trie.go new file mode 100644 index 0000000..1ffe9d5 --- /dev/null +++ b/server/internal/middleware/hooks/url_trie/trie.go @@ -0,0 +1,155 @@ +// Copyright © 2023 OpenIM open source community. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package urltrie + +import ( + "strings" + + "github.com/gin-gonic/gin" +) + +// Hook for interceptor +type Hook interface { + // Register with url pattern + // Support * wildcard, you can use it like this: + // /api/v1/*, and the url like /api/v1/123 will be matched + Pattern() string + + // Hooks + // BeforeRun will be called before controller, you can do something here + BeforeRun(c *gin.Context) + // AfterRun will be called after controller, you can do something here + AfterRun(c *gin.Context) +} + +const WILDCARD = "*" + +type node struct { + children map[string]*node + hooks []Hook + data string + + // for wildcard + isWildcard bool + isEnd bool +} + +type Trie struct { + root *node +} + +func NewTrie() *Trie { + return &Trie{ + root: &node{ + children: make(map[string]*node), + }, + } +} + +// Insert url with hooks +func (t *Trie) Insert(url string, hooks ...Hook) { + current := t.root + + // split url with '/' + parts := strings.Split(url, "/") + for _, part := range parts { + if part == "" { + continue + } + + child, exists := current.children[part] + if !exists { + child = &node{ + children: make(map[string]*node), + data: part, + } + // match wildcard + if part == WILDCARD { + child.isWildcard = true + } + + // set child node + current.children[part] = child + } + + current = child + } + + // Set hooks to last node + current.isEnd = true + current.hooks = append(current.hooks, hooks...) +} + +// Match url with hooks +func (t *Trie) Match(url string) ([]Hook, bool) { + current := t.root + + parts := strings.Split(url, "/") + var matchedValues []Hook + // use stack to save matched children nodes + stack := make([]*node, 0) + for _, c := range current.children { + stack = append(stack, c) + } + + for _, part := range parts { + if part == "" { + continue + } + + if len(stack) == 0 { + if len(matchedValues) > 0 { + return matchedValues, true + } else { + return matchedValues, false + } + } + + // get current level length + levelLen := len(stack) + for i := 0; i < levelLen; i++ { + // pop + current = stack[0] + stack = stack[1:] + if current.isEnd { + if current.isWildcard || current.data == part { + // Match the last node, append the values + matchedValues = append(matchedValues, current.hooks...) + } + continue + } + + // find wildcard node + if current.isWildcard { + for _, child := range current.children { + stack = append(stack, child) + } + } + + // find expect node + if current.data == part { + for _, child := range current.children { + stack = append(stack, child) + } + } + } + } + + if len(matchedValues) > 0 { + return matchedValues, true + } else { + return matchedValues, false + } +} diff --git a/server/internal/middleware/hooks/url_trie/trie_test.go b/server/internal/middleware/hooks/url_trie/trie_test.go new file mode 100644 index 0000000..aa3d1df --- /dev/null +++ b/server/internal/middleware/hooks/url_trie/trie_test.go @@ -0,0 +1,59 @@ +// Copyright © 2023 OpenIM open source community. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package urltrie + +import ( + "fmt" + "reflect" + "testing" +) + +func TestUrlTrie(t *testing.T) { + type Hook1 struct { + Hook + } + type Hook2 struct { + Hook + } + type Hook3 struct { + Hook + } + + trie := NewTrie() + trie.Insert("/gin", Hook1{}) + trie.Insert("/api/v1/123", Hook2{}) + trie.Insert("/openkf/*", Hook3{}) + + values, matched := trie.Match("/gin") + if matched { + fmt.Printf("Matched, values: %#v\n", reflect.ValueOf(values)) // Output: Matched, values: [1 2] + } else { + fmt.Println("No match found") + } + + values, matched = trie.Match("/openim") + if matched { + fmt.Printf("Matched, values: %#v\n", reflect.ValueOf(values)) // Output: Matched, values: [1 2] + } else { + fmt.Println("No match found") + } + + values, matched = trie.Match("/openkf/v1") + if matched { + fmt.Printf("Matched, values: %#v\n", reflect.ValueOf(values)) // Output: Matched, values: [1 2] + } else { + fmt.Println("No match found") + } +} diff --git a/server/models/.gitkeep b/server/internal/models/.gitkeep similarity index 100% rename from server/models/.gitkeep rename to server/internal/models/.gitkeep diff --git a/server/internal/models/base.go b/server/internal/models/base.go new file mode 100644 index 0000000..ae280ec --- /dev/null +++ b/server/internal/models/base.go @@ -0,0 +1,14 @@ +// Copyright © 2023 OpenIMSDK open source community. All rights reserved. +// Licensed under the MIT License (the "License"); +// you may not use this file except in compliance with the License. + +package models + +import "time" + +type Model struct { + ID uint `gorm:"primary_key" json:"id"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` + DeletedAt *time.Time `sql:"index" json:"deleted_at"` +} diff --git a/server/internal/models/user.go b/server/internal/models/user.go new file mode 100644 index 0000000..9dfa93b --- /dev/null +++ b/server/internal/models/user.go @@ -0,0 +1,11 @@ +// Copyright © 2023 OpenIMSDK open source community. All rights reserved. +// Licensed under the MIT License (the "License"); +// you may not use this file except in compliance with the License. + +package models + +type User struct { + Model + Username string `json:"username" gorm:"type:varchar(20);not null;unique"` + Password string `json:"password" gorm:"type:varchar(20);not null"` +} diff --git a/server/internal/router/router.go b/server/internal/router/router.go index f253cd0..ea88b3e 100644 --- a/server/internal/router/router.go +++ b/server/internal/router/router.go @@ -22,6 +22,7 @@ import ( "github.com/OpenIMSDK/OpenKF/server/internal/api" "github.com/OpenIMSDK/OpenKF/server/internal/config" "github.com/OpenIMSDK/OpenKF/server/internal/middleware" + urltrie "github.com/OpenIMSDK/OpenKF/server/internal/middleware/hooks/url_trie" "github.com/gin-gonic/gin" ) @@ -33,16 +34,17 @@ func InitRouter() *gin.Engine { } r := gin.Default() - r.Use(middleware.EnableCROS()) + r.Use(urltrie.RunHook(), middleware.EnableCROS()) // swagger r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) apiv1 := r.Group("/api/v1") { - email := apiv1.Group("/email") + register := apiv1.Group("/register") { - email.POST("/code", api.SendCode) + register.POST("/email/code", api.SendCode) + // register.POST("/github", api.GithubRegister) } } diff --git a/server/internal/service/init.go b/server/internal/service/init.go index a1696b4..8c52556 100644 --- a/server/internal/service/init.go +++ b/server/internal/service/init.go @@ -7,7 +7,7 @@ package service import ( "context" - "github.com/OpenIMSDK/OpenKF/server/internal/db" + "github.com/OpenIMSDK/OpenKF/server/internal/conn/db" "github.com/gin-gonic/gin" "github.com/go-redis/redis/v8" "gorm.io/gorm" diff --git a/server/internal/service/mail.go b/server/internal/service/mail.go index eeba33c..bf29f4c 100644 --- a/server/internal/service/mail.go +++ b/server/internal/service/mail.go @@ -7,8 +7,9 @@ package service import ( "time" - "github.com/OpenIMSDK/OpenKF/server/internal/client" + "github.com/OpenIMSDK/OpenKF/server/internal/conn/client" "github.com/OpenIMSDK/OpenKF/server/internal/utils" + "github.com/OpenIMSDK/OpenKF/server/pkg/log" ) func (svc *Service) SendCode(email string) (err error) { @@ -29,3 +30,7 @@ func (svc *Service) SendCode(email string) (err error) { return err } + +func (svc *Service) Test() { + log.Info("test...") +} diff --git a/server/main.go b/server/main.go index 90cc12a..c036f89 100644 --- a/server/main.go +++ b/server/main.go @@ -18,9 +18,10 @@ import ( "flag" "fmt" - "github.com/OpenIMSDK/OpenKF/server/internal/client" "github.com/OpenIMSDK/OpenKF/server/internal/config" - "github.com/OpenIMSDK/OpenKF/server/internal/db" + "github.com/OpenIMSDK/OpenKF/server/internal/conn/client" + "github.com/OpenIMSDK/OpenKF/server/internal/conn/db" + "github.com/OpenIMSDK/OpenKF/server/internal/middleware/hooks" "github.com/OpenIMSDK/OpenKF/server/internal/router" "github.com/OpenIMSDK/OpenKF/server/internal/utils" "github.com/OpenIMSDK/OpenKF/server/pkg/log" @@ -39,6 +40,7 @@ func init() { db.InitMysqlDB() db.InitRedisDB() client.InitMinio() + hooks.InitHooks() } //go:generate go env -w GO111MODULE=on