From f3757deecf31745d79932fc2c02b869cba10e741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Sun, 19 Mar 2023 21:07:22 +0800 Subject: [PATCH] finish register --- backend/api.go | 34 ++++++++++++++++++++++++++++++++++ backend/global/user.go | 30 +++++++++++++++++++----------- backend/message.go | 12 +++++++++--- backend/register.go | 27 +++++++++++++++++++++++++++ backend/utils/method.go | 11 +---------- frontend/vben/mock/sys/user.ts | 4 ++-- 6 files changed, 92 insertions(+), 26 deletions(-) create mode 100644 backend/register.go diff --git a/backend/api.go b/backend/api.go index 7bd5e41..268a4c7 100644 --- a/backend/api.go +++ b/backend/api.go @@ -3,6 +3,7 @@ package backend import ( "encoding/json" "net/http" + "strings" "github.com/fumiama/paper-manager/backend/utils" ) @@ -75,6 +76,39 @@ func init() { writeresult(w, codeSuccess, nil, messageOk, typeSuccess) }} + apimap["/api/register"] = &apihandler{"POST", func(w http.ResponseWriter, r *http.Request) { + type registerbody struct { + Username string `json:"username"` + Mobile string `json:"mobile"` + Password string `json:"password"` + } + if r.Header.Get("Authorization") != "" { + writeresult(w, codeError, nil, errInvalidToken.Error(), typeError) + return + } + var body registerbody + defer r.Body.Close() + err := json.NewDecoder(r.Body).Decode(&body) + if err != nil { + writeresult(w, codeError, nil, err.Error(), typeError) + return + } + ip := r.RemoteAddr + i := strings.LastIndex(ip, ":") + if i >= 0 { + ip = ip[:i] + } + err = register(ip, body.Username, body.Mobile, body.Password) + if err != nil { + writeresult(w, codeError, nil, err.Error(), typeError) + return + } + type message struct { + M string `json:"msg"` + } + writeresult(w, codeSuccess, &message{M: "成功, 请耐心等待通知"}, messageOk, typeSuccess) + }} + apimap["/api/getUsersCount"] = &apihandler{"GET", func(w http.ResponseWriter, r *http.Request) { token := r.Header.Get("Authorization") n, err := getUsersCount(token) diff --git a/backend/global/user.go b/backend/global/user.go index c8de40b..f8eebf9 100644 --- a/backend/global/user.go +++ b/backend/global/user.go @@ -3,7 +3,6 @@ package global import ( "errors" "strconv" - "strings" "time" "github.com/fumiama/paper-manager/backend/utils" @@ -65,7 +64,7 @@ var ( ErrEmptyName = errors.New("empty name") ErrInvalidUsersCount = errors.New("invalid users count") ErrEmptyUserID = errors.New("empty user ID") - ErrEmptyContect = errors.New("empty contact") + ErrEmptyContact = errors.New("empty contact") ErrUsernameExists = errors.New("username exists") ErrInvalidName = errors.New("invalid name") ) @@ -201,7 +200,7 @@ func (u *UserDatabase) UpdateUserPassword(id int, npwd string) error { // UpdateUserContact ... func (u *UserDatabase) UpdateUserContact(id int, ncont string) error { if ncont == "" { - return ErrEmptyContect + return ErrEmptyContact } user, err := u.GetUserByID(id) if err != nil { @@ -214,9 +213,8 @@ func (u *UserDatabase) UpdateUserContact(id int, ncont string) error { return u.db.Insert(UserTableUser, &user) } -// GetUserByName avoids sql injection by removing ; ' " = +// GetUserByName avoids sql injection by limiting username to 0-9A-Za-z func (u *UserDatabase) GetUserByName(username string) (user User, err error) { - username = strings.NewReplacer(";", "", "'", "", `"`, "", "=", "").Replace(username) for _, c := range username { if !(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') { err = ErrInvalidName @@ -229,9 +227,8 @@ func (u *UserDatabase) GetUserByName(username string) (user User, err error) { return } -// IsNameExists avoids sql injection by removing ; ' " = +// IsNameExists avoids sql injection by limiting username to 0-9A-Za-z func (u *UserDatabase) IsNameExists(username string) bool { - username = strings.NewReplacer(";", "", "'", "", `"`, "", "=", "").Replace(username) for _, c := range username { if !(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') { return false @@ -354,17 +351,25 @@ func (u *UserDatabase) SendMessage(m *Message) error { } // NotifyRegister will send register notification to all supers -func (u *UserDatabase) NotifyRegister(name, cont, pswd string) error { +func (u *UserDatabase) NotifyRegister(ip, name, cont, pswd string) error { if name == "" { return ErrEmptyName } + if cont == "" { + return ErrEmptyContact + } + if pswd == "" { + return ErrEmptyPassword + } for _, c := range name { if !(c >= '0' && c <= '9') && !(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') { return ErrInvalidName } } - if pswd == "" { - return ErrEmptyPassword + + _, err := u.GetUserByName(name) + if err == nil { + return ErrInvalidName } tos, err := u.GetSuperIDs() @@ -374,7 +379,7 @@ func (u *UserDatabase) NotifyRegister(name, cont, pswd string) error { m := Message{ Date: time.Now().Unix(), - Text: "收到来自 " + name + " 的注册请求, 联系方式: " + cont, + Text: "收到来自 " + ip + ", 用户名 " + name + " 的注册请求, 联系方式: " + cont, Name: name, Cont: cont, Pswd: pswd, @@ -424,6 +429,9 @@ func (u *UserDatabase) notifyContactChange(name, cont string) error { if name == "" { return ErrEmptyName } + if cont == "" { + return ErrEmptyContact + } tos, err := u.GetSuperIDs() if err != nil { diff --git a/backend/message.go b/backend/message.go index e9ad0fb..42e5449 100644 --- a/backend/message.go +++ b/backend/message.go @@ -27,11 +27,17 @@ func getMessageList(token string) ([]messageList, error) { return nil, nil } ml := make([]messageList, len(ms)) + am := make(map[string]string, 64) for i, m := range ms { avtr := "" - u, err := global.UserDB.GetUserByName(m.Name) - if err == nil { - avtr = u.Avtr + if a, ok := am[m.Name]; ok { + avtr = a + } else { + u, err := global.UserDB.GetUserByName(m.Name) + if err == nil { + avtr = u.Avtr + am[m.Name] = u.Avtr + } } ml[i].ID = *m.ID ml[i].Avatar = avtr diff --git a/backend/register.go b/backend/register.go new file mode 100644 index 0000000..be209a0 --- /dev/null +++ b/backend/register.go @@ -0,0 +1,27 @@ +package backend + +import ( + "errors" + "time" + + "github.com/FloatTech/ttl" + "github.com/fumiama/paper-manager/backend/global" +) + +var registerlimit = ttl.NewCache[string, bool](time.Minute * 10) + +var ( + errRegisterTooFast = errors.New("register too fast") + errInvalidIP = errors.New("invalid IP") +) + +func register(ip, name, mobile, npwd string) error { + if registerlimit.Get(ip) { + return errRegisterTooFast + } + if ip == "" { + return errInvalidIP + } + registerlimit.Set(ip, true) + return global.UserDB.NotifyRegister(ip, name, mobile, npwd) +} diff --git a/backend/utils/method.go b/backend/utils/method.go index fdf78c0..b57208d 100644 --- a/backend/utils/method.go +++ b/backend/utils/method.go @@ -6,19 +6,10 @@ import ( "github.com/sirupsen/logrus" ) -// IP gets ip from r.Header's X-FORWARDED-FOR or r.RemoteAddr -func IP(r *http.Request) string { - forwarded := r.Header.Get("X-FORWARDED-FOR") - if forwarded != "" { - return forwarded - } - return r.RemoteAddr -} - // IsMethod check if the method meets the requirement // and response 405 Method Not Allowed if not matched func IsMethod(m string, w http.ResponseWriter, r *http.Request) bool { - logrus.Infoln("[utils.IsMethod] accept", IP(r), r.Method, r.URL) + logrus.Infoln("[utils.IsMethod] accept", r.RemoteAddr, r.Method, r.URL) if r.Method != m { http.Error(w, "405 Method Not Allowed", http.StatusMethodNotAllowed) return false diff --git a/frontend/vben/mock/sys/user.ts b/frontend/vben/mock/sys/user.ts index 951aea8..60eb203 100644 --- a/frontend/vben/mock/sys/user.ts +++ b/frontend/vben/mock/sys/user.ts @@ -103,7 +103,7 @@ export default [ }, }, // mock register - { + /*{ url: '/api/register', timeout: 200, method: 'post', @@ -113,7 +113,7 @@ export default [ msg: '已将用户' + username + '电话' + mobile + '的注册请求上报, 请耐心等待!', }) }, - }, + },*/ /*{ url: '/api/getUserInfo', method: 'get',