func (i IsNullChecker) IsFormat(data string) bool { return govalidator.IsNull(data) }
// enable a service to issuer status func (c *ServiceController) EnableIssuer(params martini.Params, res http.ResponseWriter, req services.AuxRequestContext, db *services.DB) { // parse request body var body enableIssuerBody if err := c.ParseJsonBody(req, &body); err != nil { services.Res(res).Error(400, "invalid_client", "request body is invalid or malformed. Expects valid json body") return } // service id is required if c.validate.IsEmpty(body.ServiceID) { services.Res(res).Error(400, "missing_parameter", "Missing required field: service_id") return } // ensure service exists service, found, err := models.FindServiceByObjectID(db.GetPostgresHandle(), body.ServiceID) if err != nil { c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } else if !found { services.Res(res).Error(404, "not_found", "service was not found") return } // object name is required if c.validate.IsEmpty(body.ObjectName) { services.Res(res).Error(400, "missing_parameter", "Missing required field: object_name") return } // ensure no other service has used the object name identity, found, err := models.FindIdentityByObjectName(db.GetPostgresHandle(), body.ObjectName) if err != nil { c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } else if found && identity.ObjectID != service.Identity.ObjectID { services.Res(res).Error(400, "invalid_object_name", "object name is not available, try a unique name") return } // base currency is required if validator.IsNull(body.BaseCurrency) { services.Res(res).Error(400, "missing_parameter", "Missing required field: base_currency") return } // base currency must be supported if !services.StringInStringSlice(config.SupportedBaseCurrencies, body.BaseCurrency) { services.Res(res).Error(400, "invalid_base_currency", "base currency is unknown") return } // set issuer to true service.Identity.Issuer = true service.Identity.ObjectName = strings.ToLower(body.ObjectName) service.Identity.BaseCurrency = body.BaseCurrency db.GetPostgresHandle().Save(&service) respObj, _ := services.StructToJsonToMap(service) respObj["identity"].(map[string]interface{})["soul_balance"] = service.Identity.SoulBalance services.Res(res).Json(respObj) }
// create an identity func (c *IdentityController) Create(res http.ResponseWriter, req services.AuxRequestContext, db *services.DB) { // parse request body var body identityCreateBody 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 } // full name is required if validator.IsNull(body.FullName) { services.Res(res).Error(400, "missing_parameter", "Missing required field: full_name") return } // email is required if validator.IsNull(body.Email) { services.Res(res).Error(400, "missing_parameter", "Missing required field: email") return } // email is required if !validator.IsEmail(body.Email) { services.Res(res).Error(400, "invalid_email", "email is invalid") return } // create identity newIdentity := models.Identity{ ObjectID: bson.NewObjectId().Hex(), FullName: body.FullName, Email: body.Email, } // if request is from Issuer controller, set issuer field to true if d := req.GetData("isIssuer"); d != nil && d.(bool) { // object is required if validator.IsNull(body.ObjectName) { services.Res(res).Error(400, "missing_parameter", "Missing required field: object_name") return } // base currency is required if validator.IsNull(body.BaseCurrency) { services.Res(res).Error(400, "missing_parameter", "Missing required field: base_currency") return } // base currency must be supported if !services.StringInStringSlice(config.SupportedBaseCurrencies, body.BaseCurrency) { services.Res(res).Error(400, "invalid_base_currency", "base currency is unknown") return } newIdentity.Issuer = true newIdentity.ObjectName = body.ObjectName newIdentity.BaseCurrency = body.BaseCurrency } err := models.CreateIdentity(db.GetPostgresHandle(), &newIdentity) if err != nil { c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } // create response respObj, _ := services.StructToJsonToMap(newIdentity) if newIdentity.Issuer { respObj["soul_balance"] = newIdentity.SoulBalance } services.Res(res).Json(respObj) }
// renew an issuer identity soul func (c *IdentityController) RenewSoul(res http.ResponseWriter, req services.AuxRequestContext, db *services.DB) { // parse request body var body soulRenewBody 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 } // soul balance is required if body.SoulBalance == 0 { services.Res(res).Error(400, "missing_parameter", "Missing required field: soul_balance") return } // soul balance must be greater than zero if body.SoulBalance < MinimumObjectUnit { services.Res(res).Error(400, "invalid_soul_balance", "Soul balance must be equal or greater than minimum object unit which is 0.00000001") return } // ensure identity exists 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 } // ensure identity is an issuer if !identity.Issuer { services.Res(res).Error(400, "invalid_identity", "identity is not an issuer") return } // add to soul balance newIdentity, err := models.AddToSoulByObjectID(db.GetPostgresHandle(), identity.ObjectID, body.SoulBalance) if err != nil { c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } // create response, hide some fields respObj, _ := services.StructToJsonToMap(newIdentity) if newIdentity.Issuer { respObj["soul_balance"] = newIdentity.SoulBalance } services.Res(res).Json(respObj) }
// 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) }
// create object controller func (c *ObjectController) Create(res http.ResponseWriter, req services.AuxRequestContext, log *config.CustomLog, db *services.DB) { // parse body var body objectCreateBody 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 } // TODO: get client id from access token clientID := "kl14zFDq4SHlmmmVNHgLtE0LqCo8BTjyShOH" // get db transaction object dbTx, err := db.GetPostgresHandleWithRepeatableReadTrans() if err != nil { c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } // get service service, _, _ := models.FindServiceByClientId(dbTx, clientID) // ensure service is an issuer if !service.Identity.Issuer { dbTx.Rollback() services.Res(res).Error(401, "unauthorized_service", "service is not an issuer") return } // type is required if validator.IsNull(body.Type) { dbTx.Rollback() services.Res(res).Error(400, "missing_parameter", "Missing required field: type") return } // ensure type is valid if strings.ToLower(body.Type) != models.ObjectValue && strings.ToLower(body.Type) != models.ObjectValueless { dbTx.Rollback() services.Res(res).Error(400, "invalid_type", "type can only be obj_value or obj_valueless") return } // wallet id is required if validator.IsNull(body.WalletID) { dbTx.Rollback() services.Res(res).Error(400, "missing_parameter", "Missing required field: wallet_id") return } // ensure number of objects is greater than 0 if body.NumberOfObjects < 1 { dbTx.Rollback() services.Res(res).Error(400, "invalid_number_objects", "number_objects must be atleast 1 but not more than 100") return } // ensure number of objects is not greater than 100(the limit) if body.NumberOfObjects > 100 { dbTx.Rollback() services.Res(res).Error(400, "invalid_number_objects", "number_objects must not be more than 100") return } // for object of value, validate unit per object if strings.ToLower(body.Type) == models.ObjectValue { if body.BalancePerObject == 0 { dbTx.Rollback() services.Res(res).Error(400, "missing_parameter", "Missing required field: unit_per_object") return } if body.BalancePerObject < MinimumObjectUnit { dbTx.Rollback() services.Res(res).Error(400, "invalid_unit_per_object", "unit_per_object must be equal or greater than the minimum object unit which is 0.00000001") return } soulBalanceRequired := float64(body.NumberOfObjects) * body.BalancePerObject if service.Identity.SoulBalance < soulBalanceRequired { dbTx.Rollback() services.Res(res).Error(400, "insufficient_soul_balance", fmt.Sprintf("not enough soul balance to create object(s). Requires %.2f soul balance", soulBalanceRequired)) return } // update services soul balance service.Identity.SoulBalance = service.Identity.SoulBalance - soulBalanceRequired } // if meta is provided, ensure it is not greater than the limit size if !c.validate.IsEmpty(body.Meta) && len([]byte(body.Meta)) > MaxMetaSize { dbTx.Rollback() services.Res(res).Error(400, "invalid_meta_size", fmt.Sprintf("Meta contains too much data. Max size is %d bytes", MaxMetaSize)) return } // ensure wallet exists wallet, found, err := models.FindWalletByObjectID(dbTx, body.WalletID) if err != nil { dbTx.Rollback() c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } else if !found { dbTx.Rollback() services.Res(res).Error(404, "invalid_wallet", "wallet_id is unknown") return } // ensure service owns the wallet if service.Identity.ObjectID != wallet.Identity.ObjectID { dbTx.Rollback() services.Res(res).Error(401, "invalid_wallet", "wallet is not owned by this service. Use a wallet created by this service") return } // create objects allNewObjects := []models.Object{} for i := 0; i < body.NumberOfObjects; i++ { // generate a pin countryCallCode := config.CurrencyCallCodes[strings.ToUpper(service.Identity.BaseCurrency)] newPin, err := services.NewObjectPin(strconv.Itoa(countryCallCode)) if err != nil { dbTx.Rollback() c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } newObj := NewObject(newPin, body.Type, service, wallet, body.BalancePerObject, body.Meta) err = models.CreateObject(dbTx, &newObj) if err != nil { dbTx.Rollback() c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } allNewObjects = append(allNewObjects, newObj) } // update identity's soul balance dbTx.Save(service.Identity).Commit() services.Res(res).Json(allNewObjects) }