package main import ( "encoding/json" "errors" "fmt" "regexp" "github.com/gorilla/websocket" ) const ( MSG_TYPE_AUTH string = "auth" MSG_TYPE_SET_ID string = "set-id" MSG_TYPE_INVALID_HOST string = "invalid-host" MSG_TYPE_FULFILL string = "fulfill" ) type AuthRequestClient struct { conn *websocket.Conn app *App } type AuthRequestProtocolMessage struct { MessageType string `json:"type"` Parameters map[string]string `json:"parameters"` } func (c *AuthRequestClient) ReceiveRequest() (*AuthRequest, error) { message, err := c.receiveProtocolMessage() if err != nil { return nil, err } if message.MessageType != MSG_TYPE_AUTH { return nil, errors.New( fmt.Sprintf( "Wrong protocol message type, expected message of type \"%s\", got \"%s\"", MSG_TYPE_AUTH, message.MessageType, ), ) } host, ok := message.Parameters["host"] if !ok || !validHost(host) { response := &AuthRequestProtocolMessage{ MessageType: MSG_TYPE_INVALID_HOST, Parameters: make(map[string]string), } c.conn.WriteJSON(response) // Invalid or no host provided, let's try again return c.ReceiveRequest() } r := &AuthRequest{ Client: c, Instance: host, } (*c.app.Logger).Info("Returning AuthRequest") return r, nil } func (c *AuthRequestClient) receiveProtocolMessage() (*AuthRequestProtocolMessage, error) { _, message, err := c.conn.ReadMessage() (*c.app.Logger).Info("Read message") if err != nil { return nil, err } protocolMessage := &AuthRequestProtocolMessage{} err = json.Unmarshal(message, protocolMessage) if err != nil { return nil, err } return protocolMessage, nil } func (c *AuthRequestClient) PropagateID(ID string) error { message := &AuthRequestProtocolMessage{ MessageType: MSG_TYPE_SET_ID, Parameters: map[string]string{ "id": ID, }, } return c.conn.WriteJSON(message) } func (c *AuthRequestClient) Close() { c.conn.Close() } func (c *AuthRequestClient) FulFillRequest(token *AuthToken) error { message := &AuthRequestProtocolMessage{ MessageType: MSG_TYPE_FULFILL, Parameters: map[string]string{ "token": token.Token, }, } return c.conn.WriteJSON(message) } func validHost(host string) bool { re, _ := regexp.Compile(`^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$`) if re.MatchString(host) { return true } return false }