// AuthenticateDevice wraps the authentication logic for devices func AuthenticateDevice(r doorbot.Repositories, token string) (*doorbot.Device, error) { dr := r.DeviceRepository() device, err := dr.FindByToken(r.DB(), token) if err != nil { log.WithFields(log.Fields{ "error:": err, "device_token": token, "step": "device-get-by-token", }).Error("Api::Handlers->SecuredRouteHandler database error") return nil, err } if device == nil { log.WithFields(log.Fields{ "account_id": r.AccountScope(), "device_id": device.ID, }).Warn("Api::Handlers->SecuredRouteHandler device not found") return nil, nil } if device.IsEnabled == false { log.WithFields(log.Fields{ "account_id": r.AccountScope(), "device_id": device.ID, }).Warn("Api::Handlers->SecuredRouteHandler device disabled.") return nil, nil } return device, nil }
// Put updates a device func Put(render render.Render, r doorbot.Repositories, params martini.Params, vm DeviceViewModel) { id, err := strconv.ParseUint(params["id"], 10, 32) if err != nil { render.JSON(http.StatusBadRequest, doorbot.NewBadRequestErrorResponse([]string{"The id must be an unsigned integer"})) return } repo := r.DeviceRepository() device, err := repo.Find(r.DB(), uint(id)) if err != nil { log.WithFields(log.Fields{ "error": err, "account_id": r.AccountScope(), "device_id": id, "step": "device-find", }).Error("Api::Devices->Put database error") render.JSON(http.StatusInternalServerError, doorbot.NewInternalServerErrorResponse([]string{})) return } if device == nil { render.JSON(http.StatusNotFound, doorbot.NewEntityNotFoundResponse([]string{"The specified device does not exists"})) return } device.Name = vm.Device.Name device.DeviceID = vm.Device.DeviceID device.Make = vm.Device.Make device.Description = vm.Device.Description device.IsEnabled = vm.Device.IsEnabled _, err = repo.Update(r.DB(), device) if err != nil { log.WithFields(log.Fields{ "error": err, "account_id": r.AccountScope(), "device_id": id, "step": "device-update", }).Error("Api::Devices->Put database error") render.JSON(http.StatusInternalServerError, doorbot.NewInternalServerErrorResponse([]string{})) return } log.WithFields(log.Fields{ "account_id": r.AccountScope(), "device_id": id, }).Info("Api::Devices->Put device updated") vm.Device = device render.JSON(http.StatusOK, vm) }
// Register creates a new device func Register(render render.Render, r doorbot.Repositories, vm DeviceViewModel) { repo := r.DeviceRepository() device, err := repo.FindByToken(r.DB(), vm.Device.Token) if err != nil { log.WithFields(log.Fields{ "error": err, "account_id": r.AccountScope(), "device_token": vm.Device.Token, "step": "device-find", }).Error("Api::Devices->Register database error") render.Status(http.StatusInternalServerError) return } if device == nil { render.Status(http.StatusNotFound) return } device.Make = vm.Device.Make device.DeviceID = vm.Device.DeviceID device.IsEnabled = true _, err = repo.Update(r.DB(), device) if err != nil { log.WithFields(log.Fields{ "error": err, "account_id": r.AccountScope(), "device_id": device.ID, "step": "device-update", }).Error("Api::Devices->Register database error") render.Status(http.StatusInternalServerError) return } log.WithFields(log.Fields{ "account_id": r.AccountScope(), "device_id": device.ID, }).Info("Api::Devices->Put device registered") render.JSON(http.StatusOK, device) }
// Disable a device func Disable(render render.Render, r doorbot.Repositories, params martini.Params) { id, err := strconv.ParseUint(params["id"], 10, 32) if err != nil { render.JSON(http.StatusBadRequest, doorbot.NewBadRequestErrorResponse([]string{"the id must be an unsigned integer"})) return } repo := r.DeviceRepository() device, err := repo.Find(r.DB(), uint(id)) if err != nil { log.WithFields(log.Fields{ "error": err, "account_id": r.AccountScope(), "device_id": id, "step": "device-find", }).Error("Api::Devices->Disable database error") render.JSON(http.StatusInternalServerError, doorbot.NewInternalServerErrorResponse([]string{})) return } if device == nil { render.JSON(http.StatusNotFound, doorbot.NewEntityNotFoundResponse([]string{"The specified deevice does not exists."})) return } _, err = repo.Enable(r.DB(), device, false) if err != nil { log.WithFields(log.Fields{ "error": err, "account_id": r.AccountScope(), "device_id": id, "step": "device-disable", }).Error("Api::Devices->Disable database error") render.JSON(http.StatusInternalServerError, doorbot.NewInternalServerErrorResponse([]string{})) return } log.WithFields(log.Fields{ "account_id": r.AccountScope(), "device_id": id, }).Info("Api::Devices->Disabled device disabled") render.Status(http.StatusNoContent) }
// Index returns a list of devices func Index(render render.Render, r doorbot.Repositories) { repo := r.DeviceRepository() devices, err := repo.All(r.DB()) if err != nil { log.WithFields(log.Fields{ "error": err, "account_id": r.AccountScope(), }).Error("Api::Devices->Index database error") render.JSON(http.StatusInternalServerError, doorbot.NewInternalServerErrorResponse([]string{})) return } render.JSON(http.StatusOK, DevicesViewModel{Devices: devices}) }
// Get return a specific device func Get(render render.Render, r doorbot.Repositories, params martini.Params) { id, err := strconv.ParseUint(params["id"], 10, 32) if err != nil { render.JSON(http.StatusBadRequest, doorbot.NewBadRequestErrorResponse([]string{"The id must be an unsigned integer"})) return } repo := r.DeviceRepository() device, err := repo.Find(r.DB(), uint(id)) if device == nil || err != nil { log.WithFields(log.Fields{ "error": err, "account_id": r.AccountScope(), "device_id": id, }).Error("Api::Devices->Get database error") render.JSON(http.StatusNotFound, doorbot.NewEntityNotFoundResponse([]string{"The specified device does not exists"})) return } render.JSON(http.StatusOK, DeviceViewModel{Device: device}) }
// Post creates a new device func Post(render render.Render, r doorbot.Repositories, vm DeviceViewModel) { repo := r.DeviceRepository() vm.Device.Token = security.GenerateAPIToken() err := repo.Create(r.DB(), vm.Device) if err != nil { log.WithFields(log.Fields{ "error": err, "account_id": r.AccountScope(), }).Error("Api::Devices->Post database error") render.JSON(http.StatusInternalServerError, doorbot.NewInternalServerErrorResponse([]string{})) return } log.WithFields(log.Fields{ "account_id": r.AccountScope(), "device_id": vm.Device.ID, }).Info("Api::Devices->Put device created") render.JSON(http.StatusCreated, vm) }
func Token(render render.Render, account *doorbot.Account, r doorbot.Repositories, vm TokenRequest) { var person *doorbot.Person var device *doorbot.Device var policy *security.Policy switch vm.Authentication.Type { case auth.AuthorizationPerson: authRepo := r.AuthenticationRepository() personRepo := r.PersonRepository() authentication, err := authRepo.FindByProviderIDAndToken(r.DB(), auth.ProviderAPIToken, vm.Authentication.Token) if err != nil { log.WithFields(log.Fields{ "error": err, "account_id": account.ID, "token": vm.Authentication.Token, "step": "find-token", }).Error("Api::Auth->Token database error") render.JSON(http.StatusInternalServerError, doorbot.NewInternalServerErrorResponse([]string{})) return } if authentication == nil { log.WithFields(log.Fields{ "account_id": account.ID, "token": vm.Authentication.Token, "step": "find-token", }).Info("Api::Auth->Token no token found.") render.JSON(http.StatusUnauthorized, doorbot.NewUnauthorizedErrorResponse([]string{"Invalid token"})) return } person, err = personRepo.Find(r.DB(), authentication.PersonID) if err != nil { log.WithFields(log.Fields{ "error": err, "account_id": account.ID, "token": vm.Authentication.Token, "step": "find-person", }).Error("Api::Auth->Token database error") render.JSON(http.StatusInternalServerError, doorbot.NewInternalServerErrorResponse([]string{})) return } if person == nil { log.WithFields(log.Fields{ "account_id": account.ID, "token": vm.Authentication.Token, "step": "find-device", }).Warning("Api::Auth->Token person not found.") render.JSON(http.StatusUnauthorized, doorbot.NewUnauthorizedErrorResponse([]string{"Invalid token"})) return } policy = getPolicyForPerson(person) break case auth.AuthorizationDevice: deviceRepo := r.DeviceRepository() device, err := deviceRepo.FindByToken(r.DB(), vm.Authentication.Token) if err != nil { log.WithFields(log.Fields{ "error": err, "account_id": account.ID, "token": vm.Authentication.Token, "step": "find-device", }).Error("Api::Auth->Token database error") render.JSON(http.StatusInternalServerError, doorbot.NewInternalServerErrorResponse([]string{})) return } if device == nil { log.WithFields(log.Fields{ "account_id": account.ID, "token": vm.Authentication.Token, "step": "find-device", }).Info("Api::Auth->Token no device found.") render.JSON(http.StatusUnauthorized, doorbot.NewUnauthorizedErrorResponse([]string{"Invalid token"})) return } } resp := APITokenResponse{} resp.Authentication.Token = vm.Authentication.Token resp.Person = person resp.Policy = policy resp.Device = device render.JSON(http.StatusOK, resp) }