Beispiel #1
0
// AccountScopeHandler setup the account scope using the requested host
func AccountScopeHandler() martini.Handler {

	return func(render render.Render, c martini.Context, req *http.Request, res http.ResponseWriter, config *doorbot.DoorbotConfig, r doorbot.Repositories) {
		var account *doorbot.Account

		// Get the request host OR fallback to the host header.
		host := req.Host

		if len(host) == 0 {
			host = req.Header.Get("Host")
		}

		if len(host) == 0 {
			render.Status(http.StatusBadRequest)
			return
		}

		// Strip the :port section of the host
		if i := strings.Index(host, ":"); i >= 0 {
			host = host[:i]
		}

		// Get the subdomain ( test.doorbot.com  -> test )
		host_parts := strings.Split(host, ".")

		if len(host_parts) < 3 {
			render.Status(http.StatusForbidden)
			return
		}

		host = strings.TrimSpace(host_parts[0])

		ar := r.AccountRepository()
		account, err := ar.FindByHost(r.DB(), host)
		if err != nil {
			log.WithFields(log.Fields{
				"host": host,
				"step": "account-find-by-host",
			}).Error("Api::Handlers->AccountScopeHandler database error")

			panic(err)
		}

		// Redirect to the home page if the account does not exists.
		if account == nil {
			log.WithFields(log.Fields{
				"host": host,
			}).Info("Api::Handlers->AccountScopeHandler account not found")

			http.NotFound(res, req)
			return
		}

		c.Map(account)
	}

}
Beispiel #2
0
// GatekeeperRouteHandler hanldes securing the register process
func GatekeeperRouteHandler() martini.Handler {
	return func(req *http.Request, render render.Render, c martini.Context) {
		// Map a nil account
		var account *doorbot.Account
		c.Map(account)

		store := &auth.Authorization{}

		parts, err := parseAuthorization(req, render)
		if err != nil {
			return
		}

		mode := parts[0]
		token := parts[1]

		switch mode {
		case "dashboard":
			if token == "gatekeeper" {
				store.Type = auth.AuthorizationGatekeeper
				return
			} else {
				log.Warn("Api::Handlers->GatekeeperRouteHandler invalid dashboard authentication")
				render.Status(http.StatusUnauthorized)
				return
			}
		case "android":
			if token == "gatekeeper" {
				store.Type = auth.AuthorizationGatekeeper
				return
			} else {
				log.Warn("Api::Handlers->GateKeeperRouteHandler invalid android authentication")
				render.Status(http.StatusUnauthorized)
				return
			}
		default:
			log.WithFields(log.Fields{
				"mode":  mode,
				"token": token,
			}).Info("Api::Handlers->GatekeeperRouteHandler invalid authorization type")
			render.Status(http.StatusForbidden)
			return
		}
	}
}
Beispiel #3
0
// AdminRouteHandler verifies the request comes in from an administrator
func AdminRouteHandler() martini.Handler {
	return func(render render.Render, c martini.Context, req *http.Request, r doorbot.Repositories) {
		session := &auth.Authorization{}

		parts, err := parseAuthorization(req, render)
		if err != nil {
			return
		}

		mode := parts[0]
		token := parts[1]

		if mode != "administrator" {
			render.Status(http.StatusForbidden)
			return
		}

		administrator, err := auth.AuthenticateAdministrator(r, token)

		if err != nil {
			render.Status(http.StatusInternalServerError)
			return
		}

		if administrator == nil {
			render.Status(http.StatusUnauthorized)
			return
		}

		session.Type = auth.AuthorizationAdministrator
		log.WithFields(log.Fields{
			"administrator_id": administrator.ID,
			"url":              req.URL,
		}).Info("Api::Handlers->AdminRouteHandler admin request")

		c.Map(session)
		c.Map(administrator)
	}
}
Beispiel #4
0
// ManagerRestrictedRouteHandler ensure the request is made on behalf of the owner / account manager
func ManagerRestrictedRouteHandler() martini.Handler {

	return func(render render.Render, c martini.Context, req *http.Request, a *doorbot.Account, session *auth.Authorization) {
		// Let adminstrators access the resources
		if session.Type == auth.AuthorizationAdministrator {
			return
		}

		// Let owner / manager access the resources
		if session.Type == auth.AuthorizationPerson && session.Person != nil {
			if session.Person.IsAccountManager() {
				return
			}
		}

		render.Status(http.StatusForbidden)
	}

}
Beispiel #5
0
// NewServer returns a martini instance for the API endpoints
func NewServer(c *doorbot.DoorbotConfig) *martini.Martini {
	m := martini.Classic()

	m.Use(render.Renderer())
	m.Map(c)

	m.Use(CORSHandler())

	doorbot.MapDatabase(m.Martini, c)
	doorbot.UseRepositories(m.Martini)

	m.Use(func(req *http.Request, render render.Render) {
		if req.Method == "OPTIONS" {
			render.Status(http.StatusOK)
			return
		}
	})

	BindRoutes(m.Router)

	return m.Martini
}
Beispiel #6
0
// SecuredRouteHandler returns a martini.Handler responsible of handling authentication
func SecuredRouteHandler() martini.Handler {
	return func(render render.Render, c martini.Context, req *http.Request, r doorbot.Repositories, a *doorbot.Account) {

		if a == nil {
			log.Println("Doorbot::SecuredRouteHandler No account mapped.")
			render.Status(http.StatusForbidden)
			return
		}

		session := &auth.Authorization{}

		parts, err := parseAuthorization(req, render)
		if err != nil {
			return
		}

		mode := parts[0]
		token := parts[1]

		switch mode {
		case "administrator":
			administrator, err := auth.AuthenticateAdministrator(r, token)

			if err != nil {
				render.Status(http.StatusInternalServerError)
				return
			}

			if administrator == nil {
				log.WithFields(log.Fields{
					"administrator_token": token,
					"url": req.URL,
				}).Warn("Api::Handlers->SecuredRouteHandler administrator not found.")
				render.Status(http.StatusUnauthorized)
				return
			}

			log.WithFields(log.Fields{
				"url":              req.URL,
				"administrator_id": administrator.ID,
			}).Info("Api::Handlers->SecuredRouteHandler adminstrator request")

			c.Map(administrator)
			session.Administrator = administrator
			session.Type = auth.AuthorizationAdministrator
			session.Policy = security.NewAdministratorPolicy()

		case "device":

			device, err := auth.AuthenticateDevice(r, token)

			if err != nil {
				render.Status(http.StatusInternalServerError)
				return
			}

			if device == nil {
				render.Status(http.StatusUnauthorized)
				return
			}

			log.WithFields(log.Fields{
				"url":        req.URL,
				"device_id":  device.ID,
				"account_id": a.ID,
			}).Info("Api::Handlers->SecuredRouteHandler device request")

			session.Type = auth.AuthorizationDevice
			session.Device = device
			session.Policy = security.NewDevicePolicy()

		case "person":

			person, err := auth.AuthenticatePerson(r, token)

			if err != nil {
				render.Status(http.StatusInternalServerError)
				return
			}

			if person == nil {
				render.Status(http.StatusUnauthorized)
				return
			}

			log.WithFields(log.Fields{
				"url":        req.URL,
				"account_id": a.ID,
				"person_id":  person.ID,
			}).Info("Api::Handlers->SecuredRouteHandler person request")

			session.Person = person
			session.Type = auth.AuthorizationPerson

			switch person.AccountType {
			case doorbot.AccountOwner:
				session.Policy = security.NewOwnerPolicy()
				break
			case doorbot.AccountManager:
				session.Policy = security.NewManagerPolicy()
				break
			case doorbot.AccountMember:
				session.Policy = security.NewMemberPolicy()
				break
			}

		default:
			log.WithFields(log.Fields{
				"url":        req.URL,
				"account_id": a.ID,
			}).Info("Api::Handlers->SecuredRouteHandler Unauthorized access (invalid auth type)")
			render.Status(http.StatusForbidden)
			return
		}

		c.Map(session)
	}
}