Example #1
0
// create a wallet
func (c *WalletController) Create(res http.ResponseWriter, req services.AuxRequestContext, db *services.DB) {

	// parse body
	var body walletCreateBody
	if err := c.ParseJsonBody(req, &body); err != nil {
		services.Res(res).Error(400, "invalid_body", "request body is invalid or malformed. Expects valid json body")
		return
	}

	// identity id is required
	if validator.IsNull(body.IdentityId) {
		services.Res(res).Error(400, "missing_parameter", "Missing required field: identity_id")
		return
	}

	// handle is required
	if validator.IsNull(body.Handle) {
		services.Res(res).Error(400, "missing_parameter", "Missing required field: handle")
		return
	}

	// password is required
	if validator.IsNull(body.Password) {
		services.Res(res).Error(400, "missing_parameter", "Missing required field: password")
		return
	}

	// identity id must exist
	identity, found, err := models.FindIdentityByObjectID(db.GetPostgresHandle(), body.IdentityId)
	if !found {
		services.Res(res).Error(404, "invalid_identity", "identity_id is unknown")
		return
	} else if err != nil {
		c.log.Error(err.Error())
		services.Res(res).Error(500, "", "server error")
		return
	}

	// handle must be unique across wallets
	_, found, err = models.FindWalletByHandle(db.GetPostgresHandle(), body.Handle)
	if found {
		services.Res(res).Error(400, "handle_registered", "handle has been registered to another wallet")
		return
	} else if err != nil {
		c.log.Error(err.Error())
		services.Res(res).Error(500, "", "server error")
		return
	}

	// password length must be 6 characters
	if len(body.Password) < 6 {
		services.Res(res).Error(400, "invalid_password", "password is too short. minimum length is 6 characters")
		return
	}

	// securely hash password
	hashedPassword, err := services.Bcrypt(body.Password, 10)
	if err != nil {
		c.log.Error("unable to hash password. reason: " + err.Error())
		services.Res(res).Error(500, "", "server error")
		return
	} else {
		body.Password = hashedPassword
	}

	// create wallet object
	newWallet := models.Wallet{
		ObjectID: bson.NewObjectId().Hex(),
		Identity: identity,
		Handle:   body.Handle,
		Password: body.Password,
	}

	// create wallet
	err = models.CreateWallet(db.GetPostgresHandle(), &newWallet)
	if err != nil {
		c.log.Error(err.Error())
		services.Res(res).Error(500, "", "server error")
		return
	}

	respObj, _ := services.StructToJsonToMap(newWallet)
	services.Res(res).Json(respObj)
}
Example #2
0
// open an object for charge/consumption. An object opened in this method
// will be consumable without restriction
func (c *ObjectController) Open(params martini.Params, res http.ResponseWriter, req services.AuxRequestContext, log *config.CustomLog, db *services.DB) {

	// TODO: get from access token
	// authorizing wallet id
	authWalletID := "55c679145fe09c74ed000001"

	// parse body
	var body objectOpenBody
	if err := c.ParseJsonBody(req, &body); err != nil {
		services.Res(res).Error(400, "invalid_body", "request body is invalid or malformed. Expects valid json body")
		return
	}

	// ensure open method is provided
	if c.validate.IsEmpty(body.OpenMethod) {
		services.Res(res).Error(400, "invalid_parameter", "open_method: open method is required")
		return
	}

	// ensure a known open method is provided
	if body.OpenMethod != "open" && body.OpenMethod != "open_timed" && body.OpenMethod != "open_pin" {
		services.Res(res).Error(400, "invalid_parameter", "unknown open type method")
		return
	}

	dbTx, err := db.GetPostgresHandleWithRepeatableReadTrans()
	if err != nil {
		c.log.Error(err.Error())
		services.Res(res).Error(500, "", "server error")
		return
	}

	// get the object
	object, found, err := models.FindObjectByObjectID(dbTx, params["id"])
	if !found {
		dbTx.Rollback()
		services.Res(res).Error(404, "not_found", "object was not found")
		return
	} else if err != nil {
		dbTx.Rollback()
		c.log.Error(err.Error())
		services.Res(res).Error(500, "", "server error")
		return
	}

	// ensure object belongs to authorizing wallet
	if object.Wallet.ObjectID != authWalletID {
		dbTx.Rollback()
		services.Res(res).Error(401, "unauthorized", "objects: object does not belong to authorizing wallet")
		return
	}

	// set object's open property to true and open_method to `open`
	clearOpen(&object)
	object.Open = true
	object.OpenMethod = models.ObjectOpenDefault

	// for open_timed,
	// set 'open_time' field to indicate object open window
	if body.OpenMethod == "open_timed" {

		// ensure time field is provided
		if body.Time == 0 {
			dbTx.Rollback()
			services.Res(res).Error(400, "invalid_parameter", "time: open window time is required. use unix time")
			return
		}

		// time must be in the future
		now := time.Now().UTC()
		if !now.Before(services.UnixToTime(body.Time).UTC()) {
			dbTx.Rollback()
			services.Res(res).Error(400, "invalid_parameter", "time: use a unix time pointing to a period in the future")
			return
		}

		object.OpenMethod = models.ObjectOpenTimed
		object.OpenTime = body.Time
	}

	// for open_pin
	// open pin sets a pin for used by charge API
	if body.OpenMethod == "open_pin" {

		// ensure pin is provided
		if c.validate.IsEmpty(body.Pin) {
			dbTx.Rollback()
			services.Res(res).Error(400, "invalid_parameter", "pin: pin is required")
			return
		}

		// pin must be numeric
		if !validator.IsNumeric(body.Pin) {
			dbTx.Rollback()
			services.Res(res).Error(400, "invalid_parameter", "pin: pin must contain only numeric characters. e.g 4345")
			return
		}

		// pin length must be between 4 - 12 characters
		if len(body.Pin) < 4 || len(body.Pin) > 12 {
			dbTx.Rollback()
			services.Res(res).Error(400, "invalid_parameter", "pin: pin must have a minimum character length of 4 and maximum of 12")
			return
		}

		// hash pin using bcrypt
		pinHash, err := services.Bcrypt(body.Pin, 10)
		if err != nil {
			c.log.Error("unable to hash password. reason: " + err.Error())
			services.Res(res).Error(500, "", "server error")
			return
		}

		object.OpenMethod = models.ObjectOpenPin
		object.OpenPin = pinHash
	}

	dbTx.Save(&object).Commit()
	services.Res(res).Json(object)
}