feature: add usercenter

- add usercenter manager for user/auth
This commit is contained in:
ICKelin
2020-10-08 21:05:13 +08:00
parent df1ba8cfce
commit d8014ce534
6 changed files with 403 additions and 1 deletions

3
.gitignore vendored
View File

@@ -3,4 +3,5 @@ bin
log
*.log
dist
webui
webui
tool

41
usercenter/config.go Normal file
View File

@@ -0,0 +1,41 @@
package main
import (
"encoding/json"
"io/ioutil"
"github.com/pelletier/go-toml"
)
type Config struct {
ListenAddr string `toml:"listenAddr"`
MongoUrl string `toml:"mongoUrl"`
DBName string `toml:"dbname"`
Log Log `toml:"log"`
}
type Log struct {
Level string `toml:"level"`
Path string `toml:"path"`
Days int64 `toml:"days"`
}
func ParseConfig(path string) (*Config, error) {
cnt, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
var cfg Config
err = toml.Unmarshal(cnt, &cfg)
if err != nil {
return nil, err
}
return &cfg, nil
}
func (c *Config) String() string {
b, _ := json.MarshalIndent(c, "", "\t")
return string(b)
}

26
usercenter/main.go Normal file
View File

@@ -0,0 +1,26 @@
package main
import (
"flag"
"fmt"
"github.com/ICKelin/cframe/pkg/database"
log "github.com/ICKelin/cframe/pkg/logs"
)
func main() {
flgConf := flag.String("c", "", "config file")
flag.Parse()
conf, err := ParseConfig(*flgConf)
if err != nil {
fmt.Println(err)
return
}
log.Init(conf.Log.Path, conf.Log.Level, conf.Log.Days)
// initial mongodb url
database.NewModelManager(conf.MongoUrl, conf.DBName)
s := NewServer(conf.ListenAddr)
fmt.Println(s.ListenAndServe())
}

View File

@@ -0,0 +1,49 @@
package models
import (
"fmt"
"time"
"github.com/ICKelin/cframe/pkg/database"
"gopkg.in/mgo.v2/bson"
)
var (
C_AUTH = "authorize"
)
type Auth struct {
database.Model `bson:",inline"`
UserId bson.ObjectId `json:"userId" bson:"userId"`
Token string `json:"token" bson:"token"`
ExpiredIn int64 `json:"expiredIn" bson:"expiredIn"`
}
type AuthManager struct {
database.ModelManager
}
func GetAuthManager() *AuthManager {
return &AuthManager{}
}
func (m *AuthManager) AddAuth(authInfo *Auth) (*Auth, error) {
authInfo.CreatedAt = time.Now().Unix()
authInfo.UpdatedAt = time.Now().Unix()
err := m.Insert(C_AUTH, authInfo)
return authInfo, err
}
func (m *AuthManager) GetAuthByToken(token string) (*Auth, error) {
var result *Auth
var query = bson.M{}
query["invalid"] = false
query["token"] = token
// query["expiredIn"] = bson.M{"$gte": time.Now().Unix()}
err := m.FindOne(C_AUTH, query, &result)
if result == nil {
return nil, fmt.Errorf("not found")
}
return result, err
}

106
usercenter/models/user.go Normal file
View File

@@ -0,0 +1,106 @@
package models
import (
"fmt"
"time"
"github.com/ICKelin/cframe/pkg/database"
"gopkg.in/mgo.v2/bson"
)
var (
C_USER = "user"
)
type User struct {
database.Model `bson:",inline"`
Username string `json:"username" bson:"username"`
Password string `json:"-" bson:"password"`
Secret string `json:"secret" bson:"secret"`
Email string `json:"email" bson:"email"`
About string `json:"about" bson:"about"`
}
type UserManager struct {
database.ModelManager
}
func GetUserManager() *UserManager {
return &UserManager{}
}
func (m *UserManager) CreateUser(user *User) (*User, error) {
user.CreatedAt = time.Now().Unix()
user.UpdatedAt = time.Now().Unix()
user.Id = bson.NewObjectId()
err := m.Insert(C_USER, user)
if err != nil {
return nil, err
}
return user, err
}
func (m *UserManager) GetUserBySecret(secret string) (*User, error) {
var result *User
var query = bson.M{}
query["secret"] = secret
query["invalid"] = false
err := m.FindOne(C_USER, query, &result)
if result == nil {
return nil, fmt.Errorf("not found")
}
return result, err
}
func (m *UserManager) GetUserByName(name string) (*User, error) {
var result *User
var query = bson.M{}
query["username"] = name
query["invalid"] = false
err := m.FindOne(C_USER, query, &result)
if result == nil {
return nil, fmt.Errorf("not found")
}
return result, err
}
func (m *UserManager) GetUserByEmail(email string) (*User, error) {
var result *User
var query = bson.M{}
query["email"] = email
query["invalid"] = false
err := m.FindOne(C_USER, query, &result)
if result == nil {
return nil, fmt.Errorf("not found")
}
return result, err
}
func (m *UserManager) GetUserById(userId bson.ObjectId) (*User, error) {
var result *User
var query = bson.M{}
query["_id"] = userId
query["invalid"] = false
err := m.FindOne(C_USER, query, &result)
if result == nil {
return nil, fmt.Errorf("not found")
}
return result, err
}
func (m *UserManager) VerifyUser(username, password string) (*User, error) {
var result *User
var query = bson.M{}
query["username"] = username
query["password"] = password
query["invalid"] = false
err := m.FindOne(C_USER, query, &result)
if result == nil {
return nil, fmt.Errorf("not found")
}
return result, err
}

179
usercenter/server.go Normal file
View File

@@ -0,0 +1,179 @@
package main
import (
"context"
"encoding/base64"
"net"
"time"
"github.com/ICKelin/cframe/codec/proto"
log "github.com/ICKelin/cframe/pkg/logs"
"github.com/ICKelin/cframe/usercenter/models"
uuid "github.com/satori/go.uuid"
"google.golang.org/grpc"
)
type Server struct {
addr string
userManager *models.UserManager
authManager *models.AuthManager
}
func NewServer(addr string) *Server {
return &Server{
addr: addr,
userManager: models.GetUserManager(),
authManager: models.GetAuthManager(),
}
}
func (s *Server) ListenAndServe() error {
listener, err := net.Listen("tcp", s.addr)
if err != nil {
return err
}
log.Info("listenning %v success", s.addr)
srv := grpc.NewServer()
proto.RegisterUserServiceServer(srv, s)
return srv.Serve(listener)
}
func (s *Server) GetUserBySecret(ctx context.Context,
req *proto.GetUserBySecretReq) (*proto.GetUserBySecretReply, error) {
user, err := s.userManager.GetUserBySecret(req.Secret)
if err != nil {
log.Error("get user by secret %s fail: %v", req.Secret, err)
return &proto.GetUserBySecretReply{Code: 50000, Message: err.Error()}, nil
}
return &proto.GetUserBySecretReply{
UserInfo: &proto.UserInfo{
UserId: user.Id.Hex(),
UserName: user.Username,
UserSecret: user.Secret,
},
}, nil
}
func (s *Server) AddUser(ctx context.Context,
req *proto.AddUserReq) (*proto.AddUserReply, error) {
badReq := &proto.AddUserReply{Code: 40000, Message: "Bad Param"}
if len(req.UserName) <= 0 ||
len(req.Password) <= 0 ||
len(req.Email) <= 0 {
return badReq, nil
}
// verify user
exist, _ := s.userManager.GetUserByName(req.UserName)
if exist != nil {
return &proto.AddUserReply{Code: 50000, Message: "user exist"}, nil
}
exist, _ = s.userManager.GetUserByEmail(req.Email)
if exist != nil {
return &proto.AddUserReply{Code: 50000, Message: "email exist"}, nil
}
userInfo := &models.User{
Username: req.UserName,
Password: req.Password,
Email: req.Email,
About: req.About,
Secret: generateSecret(),
}
r, err := s.userManager.CreateUser(userInfo)
if err != nil {
return &proto.AddUserReply{Code: 50000, Message: err.Error()}, nil
}
return &proto.AddUserReply{
UserInfo: &proto.UserInfo{
UserId: r.Id.Hex(),
UserName: r.Username,
UserEmail: r.Email,
About: r.About,
UserSecret: r.Secret,
},
}, nil
}
func (s *Server) GetUserInfo(ctx context.Context,
req *proto.GetUserInfoReq) (*proto.GetUserInfoReply, error) {
user, err := s.userManager.VerifyUser(req.UserName, req.Password)
if err != nil {
return &proto.GetUserInfoReply{Code: 50000, Message: err.Error()}, nil
}
return &proto.GetUserInfoReply{
UserInfo: &proto.UserInfo{
UserId: user.Id.Hex(),
UserName: user.Username,
UserSecret: user.Secret,
UserEmail: user.Email,
CreatedAt: user.CreatedAt,
},
}, nil
}
func (s *Server) Authorize(ctx context.Context,
req *proto.AuthorizeReq) (*proto.AuthorizeReply, error) {
userInfo, err := s.userManager.VerifyUser(req.Username, req.Password)
if err != nil {
// TODO: verify by email
return &proto.AuthorizeReply{Code: 50000, Message: err.Error()}, nil
}
authInfo := &models.Auth{
UserId: userInfo.Id,
Token: generateToken(),
ExpiredIn: time.Now().Add(time.Hour * 1).Unix(),
}
r, err := s.authManager.AddAuth(authInfo)
if err != nil {
return &proto.AuthorizeReply{Code: 50000, Message: err.Error()}, nil
}
return &proto.AuthorizeReply{Data: &proto.AuthorizeReplyBody{
UserId: userInfo.Id.Hex(),
Token: r.Token,
ExpiredIn: r.ExpiredIn,
}}, nil
}
func (s *Server) GetUserByToken(ctx context.Context,
req *proto.GetUserByTokenReq) (*proto.GetUserByTokenReply, error) {
authInfo, err := s.authManager.GetAuthByToken(req.Token)
if err != nil {
log.Error("get user by token fail: %v", err)
return &proto.GetUserByTokenReply{Code: 50000, Message: err.Error()}, nil
}
userInfo, err := s.userManager.GetUserById(authInfo.UserId)
if err != nil {
log.Error("get user info fail: %v", err)
return &proto.GetUserByTokenReply{Code: 50000, Message: err.Error()}, nil
}
return &proto.GetUserByTokenReply{Data: &proto.UserInfo{
UserId: userInfo.Id.Hex(),
UserName: userInfo.Username,
UserEmail: userInfo.Email,
UserSecret: userInfo.Secret,
About: userInfo.About,
CreatedAt: userInfo.CreatedAt,
}}, nil
}
func generateSecret() string {
uniq := uuid.NewV4()
return base64.StdEncoding.EncodeToString(uniq.Bytes())
}
func generateToken() string {
uniq := uuid.NewV4()
return base64.StdEncoding.EncodeToString(uniq.Bytes())
}