mirror of
https://github.com/cadmium-im/zirconium-go.git
synced 2024-11-23 10:52:24 +00:00
Implement user authorization (login)
This commit is contained in:
parent
123610d33b
commit
0f6d2ff3d9
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
/zr
|
||||
/.config.toml
|
@ -16,8 +16,10 @@ func main() {
|
||||
var cfg core.Config
|
||||
var configPath string
|
||||
var generateConfig bool
|
||||
|
||||
defer logger.Init("auth-server", true, false, ioutil.Discard).Close() // TODO Make ability to use file for log output
|
||||
flag.StringVar(&configPath, "config", "", "Path to config")
|
||||
flag.BoolVar(&generateConfig, "gen_config", false, "Generate the config")
|
||||
flag.BoolVar(&generateConfig, "gen-config", false, "Generate the config")
|
||||
flag.Parse()
|
||||
if generateConfig == true {
|
||||
sampleConfig := &core.Config{}
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
type AppContext struct {
|
||||
router *Router
|
||||
authManager *AuthManager
|
||||
connectionHandler *ConnectionHandler
|
||||
sessionManager *SessionManager
|
||||
websocketServer *WebsocketServer
|
||||
cfg *Config
|
||||
database *mongo.Database
|
||||
@ -32,19 +32,22 @@ func NewAppContext(cfg *Config) *AppContext {
|
||||
}
|
||||
appContext.router = router
|
||||
|
||||
authManager, err := NewAuthManager()
|
||||
um, err := NewUserManager(appContext.database)
|
||||
if err != nil {
|
||||
logger.Fatalf("Unable to initialize user manager: %s", err.Error())
|
||||
}
|
||||
appContext.userManager = um
|
||||
|
||||
authManager, err := NewAuthManager(um, cfg.ServerID, router)
|
||||
if err != nil {
|
||||
logger.Fatalf("Unable to initialize authentication manager: %s", err.Error())
|
||||
}
|
||||
appContext.authManager = authManager
|
||||
|
||||
um := NewUserManager(appContext.database)
|
||||
appContext.userManager = um
|
||||
sessionManager := NewSessionManager(router)
|
||||
appContext.sessionManager = sessionManager
|
||||
|
||||
connHandler := NewConnectionHandler(router)
|
||||
appContext.connectionHandler = connHandler
|
||||
|
||||
wss := NewWebsocketServer(cfg, connHandler)
|
||||
wss := NewWebsocketServer(cfg, sessionManager)
|
||||
appContext.websocketServer = wss
|
||||
|
||||
return appContext
|
||||
@ -72,6 +75,5 @@ func (ac *AppContext) connectToDatabase() {
|
||||
}
|
||||
|
||||
func (ac *AppContext) Run() error {
|
||||
// TODO
|
||||
return nil
|
||||
return ac.websocketServer.Run()
|
||||
}
|
||||
|
81
core/auth_handler.go
Normal file
81
core/auth_handler.go
Normal file
@ -0,0 +1,81 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"github.com/cadmium-im/zirconium-go/core/models"
|
||||
"github.com/cadmium-im/zirconium-go/core/models/auth"
|
||||
"github.com/cadmium-im/zirconium-go/core/utils"
|
||||
"github.com/fatih/structs"
|
||||
"github.com/google/logger"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
type AuthHandler struct {
|
||||
serverID string
|
||||
authManager *AuthManager
|
||||
}
|
||||
|
||||
func NewAuthHandler(am *AuthManager, serverID string) *AuthHandler {
|
||||
return &AuthHandler{
|
||||
authManager: am,
|
||||
serverID: serverID,
|
||||
}
|
||||
}
|
||||
|
||||
func (ah *AuthHandler) HandleMessage(s *Session, message models.BaseMessage) {
|
||||
var authRequest auth.AuthRequest
|
||||
err := mapstructure.Decode(message.Payload, &authRequest)
|
||||
if err != nil {
|
||||
logger.Errorf(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
switch authRequest.Type {
|
||||
case "urn:cadmium:auth:simple":
|
||||
{
|
||||
token, claims, err := ah.authManager.HandleSimpleAuth(authRequest.Fields["username"].(string), authRequest.Fields["password"].(string))
|
||||
if err != nil {
|
||||
if mongo.ErrNoDocuments == err {
|
||||
msg := utils.PrepareErrorMessage(message, "auth-failed", "invalid username", ah.serverID)
|
||||
_ = s.Send(msg)
|
||||
return
|
||||
}
|
||||
logger.Errorf(err.Error())
|
||||
msg := utils.PrepareMessageInternalServerError(message, err, ah.serverID)
|
||||
_ = s.Send(msg)
|
||||
return
|
||||
}
|
||||
ar := auth.AuthResponse{
|
||||
Token: token,
|
||||
DeviceID: claims.DeviceID,
|
||||
}
|
||||
payload := structs.Map(ar)
|
||||
msg := models.NewBaseMessage(message.ID, message.MessageType, ah.serverID, nil, true, payload)
|
||||
_ = s.Send(msg)
|
||||
s.Claims = claims
|
||||
return
|
||||
}
|
||||
case "urn:cadmium:auth:token":
|
||||
{
|
||||
claims, err := ah.authManager.ValidateToken(authRequest.Fields["token"].(string))
|
||||
if err != nil {
|
||||
logger.Errorf(err.Error())
|
||||
msg := utils.PrepareMessageInternalServerError(message, err, ah.serverID)
|
||||
_ = s.Send(msg)
|
||||
return
|
||||
}
|
||||
s.Claims = claims
|
||||
msg := models.NewBaseMessage(message.ID, message.MessageType, ah.serverID, nil, true, nil)
|
||||
_ = s.Send(msg)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ah *AuthHandler) IsAuthorizationRequired() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (ah *AuthHandler) HandlingType() string {
|
||||
return "urn:cadmium:auth"
|
||||
}
|
@ -3,6 +3,8 @@ package core
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/alexedwards/argon2id"
|
||||
"github.com/cadmium-im/zirconium-go/core/utils"
|
||||
"time"
|
||||
|
||||
"github.com/cadmium-im/zirconium-go/core/models"
|
||||
@ -16,6 +18,8 @@ const (
|
||||
)
|
||||
|
||||
type AuthManager struct {
|
||||
serverID string
|
||||
userManager *UserManager
|
||||
signingKey string // For now it is random bytes string represented in Base64
|
||||
}
|
||||
|
||||
@ -25,17 +29,22 @@ type JWTCustomClaims struct {
|
||||
jwt.StandardClaims
|
||||
}
|
||||
|
||||
func NewAuthManager() (*AuthManager, error) {
|
||||
am := &AuthManager{}
|
||||
bytes, err := GenRandomBytes(SigningKeyBytesAmount)
|
||||
func NewAuthManager(um *UserManager, serverID string, r *Router) (*AuthManager, error) {
|
||||
am := &AuthManager{
|
||||
userManager: um,
|
||||
serverID: serverID,
|
||||
}
|
||||
bytes, err := utils.GenRandomBytes(SigningKeyBytesAmount)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
am.signingKey = base64.RawStdEncoding.EncodeToString(bytes)
|
||||
ah := NewAuthHandler(am, serverID)
|
||||
r.RegisterC2SHandler(ah)
|
||||
return am, nil
|
||||
}
|
||||
|
||||
func (am *AuthManager) CreateNewToken(entityID *models.EntityID, deviceID string, tokenExpireTimeDuration time.Duration) (string, error) {
|
||||
func (am *AuthManager) CreateNewToken(entityID *models.EntityID, deviceID string, tokenExpireTimeDuration time.Duration) (*JWTCustomClaims, string, error) {
|
||||
timeNow := time.Now()
|
||||
expiringTime := timeNow.Add(tokenExpireTimeDuration)
|
||||
|
||||
@ -59,9 +68,9 @@ func (am *AuthManager) CreateNewToken(entityID *models.EntityID, deviceID string
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
tokenString, err := token.SignedString(am.signingKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, "", err
|
||||
}
|
||||
return tokenString, nil
|
||||
return &claims, tokenString, nil
|
||||
}
|
||||
|
||||
func (am *AuthManager) ValidateToken(tokenString string) (*JWTCustomClaims, error) {
|
||||
@ -84,3 +93,28 @@ func (am *AuthManager) ValidateToken(tokenString string) (*JWTCustomClaims, erro
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (am *AuthManager) HandleSimpleAuth(username string, pass string) (string, *JWTCustomClaims, error) {
|
||||
user, err := am.userManager.GetByUsername(username)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
match, err := argon2id.ComparePasswordAndHash(pass, user.PasswordHash)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
if !match {
|
||||
return "", nil, fmt.Errorf("incorrect password")
|
||||
}
|
||||
|
||||
eid, err := models.NewEntityID("@", user.UUID, am.serverID)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
claims, token, err := am.CreateNewToken(eid, "ABCDEF", TokenExpireTimeDuration)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
return token, claims, nil
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ type BaseMessage struct {
|
||||
ID string `json:"id"`
|
||||
MessageType string `json:"type"`
|
||||
From string `json:"from"`
|
||||
To []string `json:"to"`
|
||||
To []string `json:"to,omitempty"`
|
||||
Ok bool `json:"ok"`
|
||||
Payload map[string]interface{} `json:"payload"`
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
package models
|
||||
|
||||
type ProtocolError struct {
|
||||
ErrCode string `json:"code"`
|
||||
ErrText string `json:"text"`
|
||||
ErrPayload map[string]interface{} `json:"payload"`
|
||||
ErrCode string `structs:"code"`
|
||||
ErrText string `structs:"text"`
|
||||
ErrPayload map[string]interface{} `structs:"payload,omitempty"`
|
||||
}
|
||||
|
10
core/models/user.go
Normal file
10
core/models/user.go
Normal file
@ -0,0 +1,10 @@
|
||||
package models
|
||||
|
||||
import "go.mongodb.org/mongo-driver/bson/primitive"
|
||||
|
||||
type User struct {
|
||||
ID primitive.ObjectID `json:"-" bson:"_id"`
|
||||
UUID string `json:"uuid"`
|
||||
Username string `json:"username"`
|
||||
PasswordHash string `json:"-" bson:"passwordHash"`
|
||||
}
|
@ -2,13 +2,14 @@ package core
|
||||
|
||||
import (
|
||||
"github.com/cadmium-im/zirconium-go/core/models"
|
||||
"github.com/cadmium-im/zirconium-go/core/utils"
|
||||
"github.com/fatih/structs"
|
||||
"github.com/google/logger"
|
||||
)
|
||||
|
||||
type Router struct {
|
||||
appContext *AppContext
|
||||
handlers map[string][]C2SMessageHandler
|
||||
connections []*Session
|
||||
}
|
||||
|
||||
type C2SMessageHandler interface {
|
||||
@ -30,10 +31,10 @@ func (r *Router) RouteMessage(origin *Session, message models.BaseMessage) {
|
||||
if handlers != nil {
|
||||
for _, v := range handlers {
|
||||
if v.IsAuthorizationRequired() {
|
||||
if len(origin.entityID) == 0 {
|
||||
if origin.Claims == nil {
|
||||
logger.Warningf("Connection %s isn't authorized", origin.connID)
|
||||
|
||||
msg := PrepareMessageUnauthorized(message, r.appContext.cfg.ServerDomains[0]) // fixme: domain
|
||||
msg := utils.PrepareMessageUnauthorized(message, r.appContext.cfg.ServerDomains[0]) // fixme: domain
|
||||
_ = origin.Send(msg)
|
||||
}
|
||||
}
|
||||
@ -45,7 +46,7 @@ func (r *Router) RouteMessage(origin *Session, message models.BaseMessage) {
|
||||
ErrText: "Server doesn't implement message type " + message.MessageType,
|
||||
ErrPayload: make(map[string]interface{}),
|
||||
}
|
||||
errMsg := models.NewBaseMessage(message.ID, message.MessageType, r.appContext.cfg.ServerID, []string{message.From}, false, StructToMap(protocolError))
|
||||
errMsg := models.NewBaseMessage(message.ID, message.MessageType, r.appContext.cfg.ServerID, []string{message.From}, false, structs.Map(protocolError))
|
||||
logger.Infof("Drop message with type %s because server hasn't proper handlers", message.MessageType)
|
||||
_ = origin.Send(errMsg)
|
||||
}
|
||||
|
@ -8,8 +8,7 @@ import (
|
||||
type Session struct {
|
||||
wsConn *websocket.Conn
|
||||
connID string
|
||||
entityID []*models.EntityID
|
||||
deviceID *string
|
||||
Claims *JWTCustomClaims
|
||||
}
|
||||
|
||||
func (s *Session) Send(message models.BaseMessage) error {
|
||||
|
@ -7,24 +7,23 @@ import (
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type ConnectionHandler struct {
|
||||
type SessionManager struct {
|
||||
router *Router
|
||||
connections map[string]*Session
|
||||
}
|
||||
|
||||
func NewConnectionHandler(r *Router) *ConnectionHandler {
|
||||
return &ConnectionHandler{
|
||||
func NewSessionManager(r *Router) *SessionManager {
|
||||
return &SessionManager{
|
||||
router: r,
|
||||
connections: make(map[string]*Session),
|
||||
}
|
||||
}
|
||||
|
||||
func (ch *ConnectionHandler) HandleNewConnection(wsocket *websocket.Conn) {
|
||||
randomUUID, _ := uuid.NewRandom()
|
||||
uuidStr := randomUUID.String()
|
||||
func (ch *SessionManager) HandleNewConnection(wsocket *websocket.Conn) {
|
||||
randomUUID := uuid.New().String()
|
||||
o := &Session{
|
||||
wsConn: wsocket,
|
||||
connID: uuidStr,
|
||||
connID: randomUUID,
|
||||
}
|
||||
ch.connections[o.connID] = o
|
||||
go func() {
|
@ -1,6 +1,15 @@
|
||||
package core
|
||||
|
||||
import "go.mongodb.org/mongo-driver/mongo"
|
||||
import (
|
||||
"context"
|
||||
"github.com/cadmium-im/zirconium-go/core/models"
|
||||
"github.com/cadmium-im/zirconium-go/core/utils"
|
||||
"github.com/google/uuid"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
const (
|
||||
UsersCollectionName = "users"
|
||||
@ -10,12 +19,52 @@ type UserManager struct {
|
||||
usersCol *mongo.Collection
|
||||
}
|
||||
|
||||
func NewUserManager(db *mongo.Database) *UserManager {
|
||||
func NewUserManager(db *mongo.Database) (*UserManager, error) {
|
||||
col := db.Collection(UsersCollectionName)
|
||||
|
||||
um := &UserManager{
|
||||
usersCol: col,
|
||||
}
|
||||
|
||||
return um
|
||||
err := um.initMongo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return um, nil
|
||||
}
|
||||
|
||||
func (um *UserManager) initMongo() error {
|
||||
usernameIndex := mongo.IndexModel{
|
||||
Keys: bson.M{
|
||||
"username": 1,
|
||||
}, Options: options.Index().SetUnique(true),
|
||||
}
|
||||
|
||||
exists, err := utils.IsCollectionExists(context.Background(), um.usersCol.Database(), um.usersCol.Name())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if exists {
|
||||
_, err := um.usersCol.Indexes().DropAll(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = um.usersCol.Indexes().CreateMany(context.Background(), []mongo.IndexModel{usernameIndex})
|
||||
return err
|
||||
}
|
||||
|
||||
func (um *UserManager) SaveUser(user *models.User) error {
|
||||
user.ID = primitive.NewObjectID()
|
||||
user.UUID = uuid.New().String()
|
||||
_, err := um.usersCol.InsertOne(context.Background(), user)
|
||||
return err
|
||||
}
|
||||
|
||||
func (um *UserManager) GetByUsername(username string) (*models.User, error) {
|
||||
var user models.User
|
||||
err := um.usersCol.FindOne(context.Background(), bson.D{{"username", username}}).Decode(&user)
|
||||
return &user, err
|
||||
}
|
||||
|
@ -1,50 +0,0 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"reflect"
|
||||
|
||||
"github.com/cadmium-im/zirconium-go/core/models"
|
||||
)
|
||||
|
||||
func GenRandomBytes(size int) (blk []byte, err error) {
|
||||
blk = make([]byte, size)
|
||||
_, err = rand.Read(blk)
|
||||
return
|
||||
}
|
||||
|
||||
func StructToMap(item interface{}) map[string]interface{} {
|
||||
res := map[string]interface{}{}
|
||||
if item == nil {
|
||||
return res
|
||||
}
|
||||
v := reflect.TypeOf(item)
|
||||
reflectValue := reflect.ValueOf(item)
|
||||
reflectValue = reflect.Indirect(reflectValue)
|
||||
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
tag := v.Field(i).Tag.Get("json")
|
||||
field := reflectValue.Field(i).Interface()
|
||||
if tag != "" && tag != "-" {
|
||||
if v.Field(i).Type.Kind() == reflect.Struct {
|
||||
res[tag] = StructToMap(field)
|
||||
} else {
|
||||
res[tag] = field
|
||||
}
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func PrepareMessageUnauthorized(msg models.BaseMessage, serverDomain string) models.BaseMessage {
|
||||
protocolError := models.ProtocolError{
|
||||
ErrCode: "unauthorized",
|
||||
ErrText: "Unauthorized access",
|
||||
ErrPayload: make(map[string]interface{}),
|
||||
}
|
||||
errMsg := models.NewBaseMessage(msg.ID, msg.MessageType, serverDomain, []string{msg.From}, false, StructToMap(protocolError))
|
||||
return errMsg
|
||||
}
|
91
core/utils/utils.go
Normal file
91
core/utils/utils.go
Normal file
@ -0,0 +1,91 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"github.com/alexedwards/argon2id"
|
||||
"github.com/cadmium-im/zirconium-go/core/models"
|
||||
"github.com/fatih/structs"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrPasswordIsEmpty = fmt.Errorf("the password is empty")
|
||||
ErrPasswordIsTooShort = fmt.Errorf("the password is too short")
|
||||
)
|
||||
|
||||
func GenRandomBytes(size int) (blk []byte, err error) {
|
||||
blk = make([]byte, size)
|
||||
_, err = rand.Read(blk)
|
||||
return
|
||||
}
|
||||
|
||||
func PrepareMessageUnauthorized(msg models.BaseMessage, serverDomain string) models.BaseMessage {
|
||||
protocolError := models.ProtocolError{
|
||||
ErrCode: "unauthorized",
|
||||
ErrText: "Unauthorized access",
|
||||
ErrPayload: make(map[string]interface{}),
|
||||
}
|
||||
errMsg := models.NewBaseMessage(msg.ID, msg.MessageType, serverDomain, []string{msg.From}, false, structs.Map(protocolError))
|
||||
return errMsg
|
||||
}
|
||||
|
||||
func PrepareMessageInternalServerError(msg models.BaseMessage, err error, serverID string) models.BaseMessage {
|
||||
protocolError := models.ProtocolError{
|
||||
ErrCode: "internal-server-error",
|
||||
ErrText: err.Error(),
|
||||
ErrPayload: nil,
|
||||
}
|
||||
var to []string
|
||||
if msg.From != "" {
|
||||
to = append(to, msg.From)
|
||||
}
|
||||
errMsg := models.NewBaseMessage(msg.ID, msg.MessageType, serverID, to, false, structs.Map(protocolError))
|
||||
return errMsg
|
||||
}
|
||||
|
||||
func PrepareErrorMessage(msg models.BaseMessage, errorType string, errorText string, serverID string) models.BaseMessage {
|
||||
protocolError := models.ProtocolError{
|
||||
ErrCode: errorType,
|
||||
ErrText: errorText,
|
||||
ErrPayload: nil,
|
||||
}
|
||||
var to []string
|
||||
if msg.From != "" {
|
||||
to = append(to, msg.From)
|
||||
}
|
||||
errMsg := models.NewBaseMessage(msg.ID, msg.MessageType, serverID, to, false, structs.Map(protocolError))
|
||||
return errMsg
|
||||
}
|
||||
|
||||
func HashPassword(password string) (string, error) {
|
||||
return argon2id.CreateHash(password, argon2id.DefaultParams)
|
||||
}
|
||||
|
||||
func ValidatePassword(password string) error {
|
||||
if password == "" {
|
||||
return ErrPasswordIsEmpty
|
||||
}
|
||||
if len(password) < 4 {
|
||||
return ErrPasswordIsTooShort
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func IsCollectionExists(ctx context.Context, db *mongo.Database, collectionName string) (bool, error) {
|
||||
isExists := false
|
||||
names, err := db.ListCollectionNames(ctx, bson.D{{"name", collectionName}})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
if name == collectionName {
|
||||
isExists = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return isExists, nil
|
||||
}
|
@ -16,14 +16,14 @@ var wsUpgrader = websocket.Upgrader{
|
||||
|
||||
type WebsocketServer struct {
|
||||
r *mux.Router
|
||||
connHandler *ConnectionHandler
|
||||
sessionManager *SessionManager
|
||||
cfg *Config
|
||||
}
|
||||
|
||||
func NewWebsocketServer(cfg *Config, connHandler *ConnectionHandler) *WebsocketServer {
|
||||
func NewWebsocketServer(cfg *Config, sessionManager *SessionManager) *WebsocketServer {
|
||||
wss := &WebsocketServer{}
|
||||
|
||||
wss.connHandler = connHandler
|
||||
wss.sessionManager = sessionManager
|
||||
wss.cfg = cfg
|
||||
r := mux.NewRouter()
|
||||
wss.r = r
|
||||
@ -36,7 +36,7 @@ func NewWebsocketServer(cfg *Config, connHandler *ConnectionHandler) *WebsocketS
|
||||
logger.Errorf(err.Error())
|
||||
return
|
||||
}
|
||||
wss.connHandler.HandleNewConnection(ws)
|
||||
wss.sessionManager.HandleNewConnection(ws)
|
||||
})
|
||||
|
||||
return wss
|
||||
|
4
go.mod
4
go.mod
@ -3,12 +3,14 @@ module github.com/cadmium-im/zirconium-go
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v0.3.1
|
||||
github.com/alexedwards/argon2id v0.0.0-20210326052512-e2135f7c9c77 // indirect
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/google/logger v1.0.1
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/gorilla/mux v1.7.3
|
||||
github.com/gorilla/websocket v1.4.1
|
||||
github.com/mitchellh/mapstructure v1.4.1 // indirect
|
||||
github.com/pelletier/go-toml v1.7.0
|
||||
go.mongodb.org/mongo-driver v1.5.1
|
||||
)
|
||||
|
11
go.sum
11
go.sum
@ -1,5 +1,7 @@
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/alexedwards/argon2id v0.0.0-20210326052512-e2135f7c9c77 h1:X6U+/fhTYeDYS3sN4xHcoORJhhar+zSgrNeraapuRK4=
|
||||
github.com/alexedwards/argon2id v0.0.0-20210326052512-e2135f7c9c77/go.mod h1:Kmn5t2Rb93Q4NTprN4+CCgARGvigKMJyxP0WckpTUp0=
|
||||
github.com/aws/aws-sdk-go v1.34.28 h1:sscPpn/Ns3i0F4HPEWAVcwdIRaZZCuL7llJ2/60yPIk=
|
||||
github.com/aws/aws-sdk-go v1.34.28/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -7,6 +9,8 @@ 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=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
@ -65,6 +69,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
|
||||
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
|
||||
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
|
||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/pelletier/go-toml v1.7.0 h1:7utD74fnzVc/cpcyy8sjrlFr5vYpypUixARcHIMIGuI=
|
||||
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
|
||||
@ -105,6 +111,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM=
|
||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
|
||||
@ -122,6 +130,9 @@ golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2 h1:T5DasATyLQfmbTpfEXx/IOL9vfjzW6up+ZDkmHvIf2s=
|
||||
golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
Loading…
Reference in New Issue
Block a user