// get a service func (c *ServiceController) Get(params martini.Params, res http.ResponseWriter, req services.AuxRequestContext, db *services.DB) { service, found, err := models.FindServiceByObjectID(db.GetPostgresHandle(), params["id"]) if !found { services.Res(res).Error(404, "not_found", "service was not found") return } else if err != nil { c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } respObj, _ := services.StructToJsonToMap(service) services.Res(res).Json(respObj) }
// get an identity func (c *IdentityController) Get(params martini.Params, res http.ResponseWriter, req services.AuxRequestContext, db *services.DB) { identity, found, err := models.FindIdentityByObjectID(db.GetPostgresHandle(), params["id"]) if !found { services.Res(res).Error(404, "not_found", "identity was not found") return } else if err != nil { c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } // create response respObj, _ := services.StructToJsonToMap(identity) if identity.Issuer { respObj["soul_balance"] = identity.SoulBalance } services.Res(res).Json(respObj) }
// get an object by its id or pin func (c *ObjectController) Get(params martini.Params, res http.ResponseWriter, req services.AuxRequestContext, log *config.CustomLog, db *services.DB) { dbObj := db.GetPostgresHandle() object, found, err := models.FindObjectByObjectIDOrPin(dbObj, params["id"]) if !found { services.Res(res).Error(404, "not_found", "object was not found") return } else if err != nil { c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } // construct response. remove private fields respObj, _ := services.StructToJsonToMap(object) delete(respObj["wallet"].(map[string]interface{})["identity"].(map[string]interface{}), "soul_balance") delete(respObj["wallet"].(map[string]interface{})["identity"].(map[string]interface{}), "email") delete(respObj["service"].(map[string]interface{})["identity"].(map[string]interface{}), "soul_balance") delete(respObj["service"].(map[string]interface{})["identity"].(map[string]interface{}), "email") services.Res(res).Json(respObj) }
// generate and return client_credentials token func (c *AuthController) GetClientCredentialToken(res http.ResponseWriter, req services.AuxRequestContext, log *config.CustomLog, db *services.DB) { // get base64 encoded credentials base64Credential := services.StringSplit(req.Header.Get("Authorization"), " ")[1] base64CredentialDecoded := services.DecodeB64(base64Credential) credentials := services.StringSplit(base64CredentialDecoded, ":") // check if requesting client is a back service id if credentials[0] == BackOfficeId && credentials[1] == BackOfficeSecret { exp := int64(0) token, err := createJWTToken("", true, exp) if err != nil { log.Error(err) services.Res(res).Error(500, "", "server error") return } // create and save new token newToken := models.Token{ Token: token, Type: "bearer", ExpiresIn: time.Time{}, CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC(), } // persist token err = models.CreateToken(db.GetPostgresHandle(), &newToken) if err != nil { c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } services.Res(res).Json(newToken) return } // find service by client id service, found, err := models.FindServiceByClientId(db.GetPostgresHandle(), credentials[0]) if !found && err == nil { log.Error(err) services.Res(res).Error(404, "", "service not found") return } else if err != nil { c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } // compare secret if credentials[1] != service.ClientSecret { log.Error(err) services.Res(res).Error(401, "", "service credentials are invalid. ensure client id and secret are valid") return } // create access token exp := time.Now().Add(time.Hour * 1) token, err := createJWTToken(service.ObjectID, false, exp.UTC().Unix()) if err != nil { log.Error(err) services.Res(res).Error(500, "", "server error") return } // create and save new token newToken := models.Token{ Service: service, Token: token, Type: "bearer", ExpiresIn: exp.UTC(), CreatedAt: time.Now().UTC(), UpdatedAt: time.Now().UTC(), } // persist token err = models.CreateToken(db.GetPostgresHandle(), &newToken) if err != nil { c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } respObj, _ := services.StructToJsonToMap(newToken) respObj["service"] = services.DeleteKeys(respObj["service"].(map[string]interface{}), "client_id", "client_secret") services.Res(res).Json(respObj) }
// create a service func (c *ServiceController) Create(res http.ResponseWriter, req services.AuxRequestContext, db *services.DB) { // parse request body var body createBody 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 } // name is required if c.validate.IsEmpty(body.FullName) { services.Res(res).Error(400, "missing_parameter", "Missing required field: full_name") return } // full name must have max of 60 characters if !validator.StringLength(body.FullName, "1", "60") { services.Res(res).Error(400, "invalid_full_name", "full_name character limit is 60") return } // service name is required if c.validate.IsEmpty(body.ServiceName) { services.Res(res).Error(400, "missing_parameter", "Missing required field: service_name") return } // service name must have max of 30 characters if !validator.StringLength(body.ServiceName, "1", "60") { services.Res(res).Error(400, "invalid_service_name", "service_name character limit is 60") return } // description is required if c.validate.IsEmpty(body.Description) { services.Res(res).Error(400, "missing_parameter", "Missing required field: description") return } // description must have max of 140 characters if !validator.StringLength(body.Description, "1", "140") { services.Res(res).Error(400, "invalid_description", "description character limit is 140") return } // email is required if c.validate.IsEmpty(body.Email) { services.Res(res).Error(400, "missing_parameter", "Missing required field: email") return } // email must be valid 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, } // start db transaction dbTx := db.GetPostgresHandle().Begin() if err := models.CreateIdentity(dbTx, newIdentity); err != nil { dbTx.Rollback() c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } // create client credentials clientId := services.GetRandString(services.GetRandNumRange(32, 42)) clientSecret := services.GetRandString(services.GetRandNumRange(32, 42)) // create new service object newService := models.Service{ ObjectID: bson.NewObjectId().Hex(), Name: body.ServiceName, Description: body.Description, ClientID: clientId, ClientSecret: clientSecret, Identity: newIdentity, } // create service err := models.CreateService(dbTx, &newService) if err != nil { dbTx.Rollback() c.log.Error(err.Error()) services.Res(res).Error(500, "", "server error") return } // commit db transaction dbTx.Commit() // send response respObj, _ := services.StructToJsonToMap(newService) services.Res(res).Json(respObj) }
// 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) }