Exemple #1
0
func (a *ApplicationController) CreateApplicationHandler(c *gin.Context) {
	body := &ApplicationModel{}

	if err := c.Bind(body); err != nil {
		log.Error(RestError(c, err))
		return
	}

	if body.Name == "" {
		log.Error(RestErrorInvalidBody(c))
		return
	}

	email := ApiUser(c).Email
	app := models.JSON{
		db.ID_FIELD:         body.Id,
		db.NAME_FIELD:       body.Name,
		db.OWNER_FIELD:      email,
		db.MASTER_KEY_FIELD: strings.ToUpper(utils.GetCleanUUID()),
	}

	appId, err := a.DbService.CreateApp(email, app)
	if err != nil {
		log.Error(RestError(c, err))
		return
	}

	RespondId(appId, c)
}
Exemple #2
0
func (a *AuthController) registerUser(c *gin.Context, isApp bool) {
	var u models.JSON

	if err := c.Bind(&u); err != nil {
		log.Error(RestErrorInvalidBody(c))
		return
	}

	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(u[db.PASSWORD_FIELD].(string)), 10)
	if err != nil {
		log.Error(RestError(c, err))
		return
	}

	user := models.JSON{
		db.EMAIL_FIELD:         u[db.EMAIL_FIELD],
		db.PASSWORD_FIELD:      hashedPassword,
		db.REGISTERED_AT_FIELD: time.Now(),
	}

	if isApp {
		user[db.APP_ID_FIELD] = c.Param(APP_ID_PARAM)
	} else {
		user[db.APPS_FIELD] = []interface{}{}
	}

	err = a.DbService.CreateUser(user, isApp)
	if err != nil {
		log.Error(RestError(c, err))
	}
}
Exemple #3
0
func authorizeMiddleware(stop bool) gin.HandlerFunc {
	return func(c *gin.Context) {
		authHeader := c.Request.Header.Get("Authorization")

		if authHeader != "" {
			authHeaderParts := strings.SplitN(authHeader, " ", 2)
			if len(authHeaderParts) != 2 {
				log.Error(RestErrorUnauthorized(c))
				return
			}

			authType := strings.ToLower(authHeaderParts[0])
			authValue := authHeaderParts[1]

			//TODO: authorization for master token, master key, normal token, app id only
			var token *jwt.Token
			var err error
			user := &apiUser{}
			if authType == "bearer" {
				token, err = authWithToken(c, authValue)
				if err == nil {
					user.Email = token.Claims["user"].(string)
					user.InApp = token.Claims["inApp"].(bool)
					user.Master = !user.InApp //we can use the token instead of a master key
					user.Key = authValue
				}
			} else if authType == "masterkey" {
				email, err := authWithMaster(c, authValue)
				if err == nil {
					user.Email = email
					user.InApp = false
					user.Master = true
					user.Key = authValue
				}
			} else {
				c.Next()
				return
			}

			c.Set("user", user)

			if err != nil {
				log.Error(RestError(c, err))
				return
			}

			c.Next()
		} else {
			if !stop {
				c.Next()
			} else {
				log.Error(RestErrorUnauthorized(c))
			}
		}
	}
}
func (p WsMessageReceiver) handlePublish(im interceptorMessage, msg *gowamp.Publish) (interface{}, error) {

	if string(msg.Topic) == "wamp.session.on_leave" {
		args := msg.Arguments
		if len(args) == 0 {
			return nil, nil
		}

		if leavingSessionId, ok := args[0].(gowamp.ID); ok {
			log.Info("Broadcasting session leave:", leavingSessionId)
			p.broadcaster.Broadcast(leavingSessionId)
			return nil, nil
		}

		log.Info("Leave:", args)
		return nil, nil
	}

	if string(msg.Topic) == "wamp.session.on_join" {
		return nil, nil
	}

	if len(msg.Arguments) == 0 {
		return nil, nil
	}

	m, ok := msg.Arguments[0].(string)
	if !ok {
		m = models.String(msg.Arguments[0])
	}

	var clientMessage messaging.Message
	converError := clientMessage.FromString(m)
	if converError != nil {
		log.Error(converError)
		return nil, converError
	}

	if clientMessage.Origin == messaging.ORIGIN_API {
		return nil, nil
	}

	log.Info("Websocket message received:", clientMessage)
	data, apiError := p.ClientProcessor.Process(clientMessage)
	if apiError != nil {
		log.Error(apiError)
	}

	return data, apiError
}
func (p RpcMessageReceiver) makeErrorResult(err error) *gowamp.CallResult {
	log.Error(err)
	return &gowamp.CallResult{
		Err:  gowamp.URI(err.Error()),
		Args: []interface{}{err},
	}
}
Exemple #6
0
func NewWebSocketServer() (*gowamp.WebsocketServer, *gowamp.Client, *wsInterceptor, error) {
	interceptor := NewWsInterceptor()

	r := gowamp.Realm{}
	r.Interceptor = interceptor

	realms := map[string]gowamp.Realm{}
	realms[config.CONST_DEFAULT_REALM] = r
	wsServer, err := gowamp.NewWebsocketServer(realms)
	if err != nil {
		return nil, nil, nil, err
	}

	wsServer.Upgrader.CheckOrigin = func(r *http.Request) bool {
		//allow connections from any origin
		return true
	}

	c, err := wsServer.GetLocalClient(config.CONST_DEFAULT_REALM, nil)
	if err != nil {
		log.Error(err)
		return nil, nil, nil, err
	}

	http.Handle("/", wsServer)
	http.HandleFunc("/_status", func(w http.ResponseWriter, r *http.Request) {
		log.Info("_status check")
		//we are fine
	})

	return wsServer, c, interceptor, nil
}
Exemple #7
0
func validateAppOperationsAuthorizationMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		user := ApiUser(c)
		if user.InApp && !user.Master {
			log.Error(RestErrorUnauthorized(c), user)
			return
		}
	}
}
Exemple #8
0
func String(input interface{}) string {
	b, err := json.Marshal(input)
	if err != nil {
		log.Error(err)
		return "{}"
	}

	return string(b)
}
Exemple #9
0
func (a *ApplicationController) GetApplicationsHandler(c *gin.Context) {
	email := ApiUser(c).Email
	apps, err := a.DbService.GetApps(email)
	if err != nil {
		log.Error(RestError(c, err))
		return
	}

	c.JSON(http.StatusOK, apps)
}
Exemple #10
0
func validateAppPermissionsMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		user := ApiUser(c)
		if !user.Master {
			log.Error(RestErrorUnauthorized(c), user)
			c.Next()
			return
		}
	}
}
Exemple #11
0
func (t *TypesController) DeleteType(c *gin.Context) {
	appId := c.Param("appId")
	typeName := c.Param("typeName")

	err := t.DbService.DeleteAllItems(appId, typeName)
	if err != nil {
		log.Error(RestError(c, err))
		return
	}
}
Exemple #12
0
func validateAppMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		appId := c.Param("appId")
		log.Info(appId)
		if appId == "" {
			log.Error(RestError(c, "Invalid app id."))
		} else {
			c.Next()
		}
	}
}
Exemple #13
0
func (t *TypesController) GetTypesHandler(c *gin.Context) {
	appId := c.Param("appId")

	types, err := t.DbService.GetTypes(appId)
	if err != nil {
		log.Error(RestError(c, err))
		return
	}

	c.JSON(http.StatusOK, types)
}
Exemple #14
0
func (a *AuthController) loginUser(c *gin.Context, isApp bool) {
	var u UserModel

	if err := c.Bind(&u); err != nil {
		log.Error(RestError(c, err))
		return
	}

	appId := ""
	if isApp {
		appId = c.Param(APP_ID_PARAM)
	}

	user, err := a.DbService.GetUser(u.Email, isApp, appId)
	if err != nil {
		log.Error(RestError(c, err))
		return
	}

	err = bcrypt.CompareHashAndPassword(user[db.PASSWORD_FIELD].([]byte), []byte(u.Password))
	if err != nil {
		log.Error(RestError(c, err))
		return
	}

	token := jwt.New(jwt.GetSigningMethod("HS256"))
	token.Claims["user"] = u.Email
	token.Claims["expiration"] = time.Now().Add(time.Minute + 60).Unix()
	token.Claims["inApp"] = isApp

	tokenStr, err := token.SignedString([]byte(""))

	if err != nil {
		log.Error(RestError(c, err))
		return
	}

	c.JSON(http.StatusOK, models.JSON{
		"token": tokenStr,
	})
}
func (p MessageProcessor) shouldProcessMessage(m Message) bool {
	key := m.GetRedisKey()
	timestamp := p.redisClient.Get(key).Val()
	if timestamp == "" {
		return true
	}

	cachedTime, parseTimeError := time.Parse(time.RFC3339, timestamp)
	if parseTimeError == nil {
		log.Error("Error parsing message time:", parseTimeError)
		return true
	}

	messageTime, parseTimeError := time.Parse(time.RFC3339, m.Timestamp)
	if parseTimeError == nil {
		log.Error("Error parsing message time:", parseTimeError)
		return true
	}

	return cachedTime.Before(messageTime)
}
Exemple #16
0
func (b *Broadcaster) Broadcast(v interface{}) {
	defer func() {
		if err := recover(); err != nil {
			log.Error(err)
		}
	}()

	log.Info(b.listeners)
	for _, ch := range b.listeners {
		ch <- v
	}
}
Exemple #17
0
func (t *TypesController) DeleteTypeItemById(c *gin.Context) {
	//appId := c.Param("appId")
	//typeName := c.Param("typeName")
	itemId := c.Param("itemId")

	//TODO: same as above
	err := t.DbService.DeleteItemById(itemId)
	if err != nil {
		log.Error(RestError(c, err))
		return
	}
}
Exemple #18
0
func (t *TypesController) UpdateTypeItemById(c *gin.Context) {
	//appId := c.Param("appId")
	//typeName := c.Param("typeName")
	itemId := c.Param("itemId")
	//TODO: same as get
	body := webUtils.GetBody(c)
	err := t.DbService.UpdateItemById(itemId, body)
	if err != nil {
		log.Error(RestError(c, err))
		return
	}
}
Exemple #19
0
func (t *TypesController) InsertInTypeHandler(c *gin.Context) {
	appId := c.Param("appId")
	typeName := c.Param("typeName")
	body := webUtils.GetBody(c)

	id, err := t.DbService.CreateItem(appId, typeName, body)
	if err != nil {
		log.Error(RestError(c, err))
		return
	}

	RespondId(id, c)
}
Exemple #20
0
func (a *ApplicationController) GetApplicationHandler(c *gin.Context) {
	//user := ApiUser(c).Email
	appId := c.Param("appId")

	//TODO: permissions
	app, err := a.DbService.GetApp(appId)
	if err != nil {
		log.Error(RestError(c, err))
		return
	}

	c.JSON(http.StatusOK, app)
}
Exemple #21
0
func (c *Client) Connect() {
	for {
		conn, err := c.connect()
		if err == nil {
			c.isConnected = true
			c.connection = conn
			log.Info("Connected to", c.Addr)
			break
		} else {
			log.Error("Error connecting to", c.Addr, err)
			time.Sleep(time.Second * 5)
		}
	}
}
Exemple #22
0
func main() {
	r.SetVerbose(true)

	defer utils.Recover()
	utils.ListenSignals()
	utils.Liveness()

	err := server.Initialize()
	if err != nil {
		panic(err)
	}

	log.Info("Realtime service listening")
	log.Error(http.ListenAndServe(config.Get(config.KEY_REALTIME_PORT), nil))
}
Exemple #23
0
func Liveness() {
	interval := 1 * time.Second
	pid := strconv.Itoa(os.Getpid())
	filename := "hearthbeat"
	cwd, err := os.Getwd()
	filepath := path.Join(cwd, filename)
	if err != nil {
		panic(err)
	}

	go func() {
		hearthbeat := func() {
			if _, err := os.Stat(filepath); os.IsNotExist(err) {
				f, createErr := os.Create(filepath)
				if createErr != nil {
					log.Error("Error creating hearthbeat:", createErr)
					return
				}

				_, writeErr := f.WriteString(pid)
				if writeErr != nil {
					log.Error("Error writing heartbeat:", writeErr)
					return
				}
			}
		}

		t := time.Tick(interval)
		for {
			select {
			case <-t:
				hearthbeat()
			}
		}
	}()
}
Exemple #24
0
func (t *TypesController) GetTypeItemById(c *gin.Context) {
	//appId := c.Param("appId")
	//typeName := c.Param("typeName")
	itemId := c.Param("itemId")
	//TODO: this should work out of the box since all ids are unique in the data table
	//no specific app and type needed
	//TODO: permissions

	item, err := t.DbService.GetItemById(itemId)
	if err != nil {
		log.Error(RestError(c, err))
		return
	}

	c.JSON(http.StatusOK, item)
}
Exemple #25
0
func (t *TypesController) GetTypeDataHandler(c *gin.Context) {
	appId := c.Param("appId")
	typeName := c.Param("typeName")
	opts := GetHeaderOptions(c)

	items, err := t.DbService.GetItems(appId, typeName, opts.Filter)
	if err != nil {
		log.Error(RestError(c, err))
		return
	}

	if items == nil {
		items = make([]models.JSON, 0)
	}

	c.JSON(http.StatusOK, items)
}
Exemple #26
0
func (c *ApiClient) SendRequest(url, method string, body interface{}, isArray bool) (interface{}, error) {
	log.Info(
		"Sending request",
		"BaseUrl:", c.BaseUrl,
		"Url:", url,
		"Method:", method,
		"Body:", body,
		"Token:", c.Token,
		"AppId:", c.AppId,
		"NotifyRealtime", c.NotifyRealTime,
	)

	var bodyStr = ""
	if body != nil {
		b, err := json.Marshal(body)
		if err != nil {
			log.Error(err)
			return nil, err
		}

		bodyStr = string(b)
	}

	req, err := http.NewRequest(method, c.BaseUrl+url, strings.NewReader(bodyStr))
	if err != nil {
		log.Error(err)
		return nil, err
	}

	opts := models.Options{}

	//todo: in app and not in app token
	if c.Token != "" {
		req.Header.Set("Authorization", "Bearer "+c.Token)
	}

	if c.ClientId != "" {
		opts.ClientId = &c.ClientId
	}

	opts.Notify = &c.NotifyRealTime
	opts.Filter = c.Filter
	//opts.Origin = c.Origin

	optsS, err := opts.String()
	if err != nil {
		log.Error(err)
		return nil, err
	}

	req.Header.Set("NeutrinoOptions", optsS)

	client := http.Client{}
	res, err := client.Do(req)
	if err != nil {
		log.Info(err)
		return nil, err
	}

	if res == nil {
		log.Error("Unknown error")
		return nil, nil
	}

	if res.StatusCode != http.StatusOK {
		log.Info(res, err)
		return nil, err
	}

	defer res.Body.Close()
	if err != nil {
		log.Error(err)
		return nil, err
	}

	bodyRes, err := ioutil.ReadAll(res.Body)
	if err != nil {
		log.Error(err)
		return nil, err
	}

	if string(bodyRes) == "" {
		log.Info("Empty body response!")
		return nil, nil
	}

	var result interface{}
	log.Info("API response: ", string(bodyRes))
	if isArray {
		jsonArray := make([]models.JSON, 0)
		err = json.Unmarshal(bodyRes, &jsonArray)
		result = jsonArray
	} else {
		m := models.JSON{}
		err = json.Unmarshal(bodyRes, &m)
		result = m
	}

	if err != nil {
		log.Error(err)
		return nil, err
	}

	return result, nil
}
func (p WsMessageReceiver) handleSubscribe(im interceptorMessage, msg *gowamp.Subscribe) {
	opts := models.SubscribeOptions{}
	err := models.Convert(msg.Options, &opts)
	if err != nil {
		log.Error(err)
		return
	}

	topic := fmt.Sprintf("%v", msg.Topic)
	topicArguments := strings.Split(topic, ".")

	opts.Topic = topic
	if opts.IsSpecial() {
		baseTopic := messaging.BuildTopicArbitrary(topicArguments[:len(topicArguments)-1]...)
		opts.BaseTopic = baseTopic
	} else {
		opts.BaseTopic = topic
	}

	log.Info("Listening for changefeed:", opts)
	d := db.NewDbService()
	newValuesChan := make(chan map[string]interface{})

	//for create and delete we want to listen for changes for the whole collection, for update only for the specific item
	if opts.Operation == messaging.OP_CREATE || opts.Operation == messaging.OP_DELETE {
		err = d.Changes(opts.AppId, opts.Type, opts.Filter, newValuesChan)
	} else if opts.Operation == messaging.OP_UPDATE {
		opts.ItemId = topicArguments[len(topicArguments)-1]
		err = d.ChangesId(opts.ItemId, newValuesChan)
	}

	if err != nil {
		log.Error(err)
		return
	}

	messageBuilder := messaging.GetMessageBuilder()
	go func() {
		leaveChan := make(chan interface{})
		p.broadcaster.Subscribe(leaveChan)

		for {
			select {
			case val := <-newValuesChan:
				p.processDatabaseUpdate(val, &messageBuilder, opts)
			case leaveVal := <-leaveChan:
				sessionId := leaveVal.(gowamp.ID)
				if im.sess.Id == sessionId {
					//TODO: newValuesChan seems to be automatically closed by the rethinkdb driver
					//investigate whether we need to do something else

					_, leaveChanOpened := <-leaveChan
					if leaveChanOpened {
						close(leaveChan)
					}

					p.broadcaster.Remove(leaveChan)
					return
				}
			}
		}
	}()
}
func (p WsMessageReceiver) processDatabaseUpdate(
	val map[string]interface{},
	builder *messaging.MessageBuilder,
	opts models.SubscribeOptions,
) {
	messageBuilder := *builder

	pld := models.JSON{}
	var dbOp string
	newVal := val["new_val"]
	oldVal := val["old_val"]

	if newVal != nil && oldVal == nil {
		dbOp = messaging.OP_CREATE
	} else if newVal == nil && oldVal != nil {
		dbOp = messaging.OP_DELETE
	} else {
		dbOp = messaging.OP_UPDATE
	}

	//only emit messages with the same operation as the subscriber
	if dbOp != opts.Operation {
		return
	}

	var dbVal map[string]interface{}
	if dbOp == messaging.OP_CREATE {
		if newVal == nil {
			log.Error("Invalid message:", val)
			return
		}

		dbVal = newVal.(map[string]interface{})
	} else if dbOp == messaging.OP_DELETE && oldVal != nil {
		if oldVal == nil {
			log.Error("Invalid message:", val)
			return
		}

		dbVal = oldVal.(map[string]interface{})
	} else {
		//update
		if newVal == nil {
			log.Error("Invalid message:", val)
			return
		}

		dbVal = newVal.(map[string]interface{})
	}

	pld = pld.FromMap(dbVal)
	pld = utils.BlacklistFields([]string{db.TYPE_FIELD, db.APP_ID_FIELD}, pld)

	msg := messageBuilder.Build(
		dbOp,
		messaging.ORIGIN_API,
		pld,
		models.Options{},
		opts.Type,
		opts.AppId,
		"", //TODO: token?
	)
	msg.Topic = opts.Topic

	log.Info("Publishing database feed: ", strings.ToUpper(msg.Operation), opts, val, msg)

	publishArgs := []interface{}{msg}
	p.WsClient.Publish(opts.Topic, publishArgs, nil)
}
Exemple #29
0
func Recover() {
	e := recover()
	if e != nil {
		log.Error(e)
	}
}