+ # Load password file
+ if os.path.isfile(constants.RAPI_USERS_FILE):
+ self._users = http.auth.ReadPasswordFile(constants.RAPI_USERS_FILE)
+ else:
+ self._users = None
+
+ def _GetRequestContext(self, req):
+ """Returns the context for a request.
+
+ The context is cached in the req.private variable.
+
+ """
+ if req.private is None:
+ (HandlerClass, items, args) = \
+ self._resmap.getController(req.request_path)
+
+ ctx = RemoteApiRequestContext()
+ ctx.handler = HandlerClass(items, args, req)
+
+ method = req.request_method.upper()
+ try:
+ ctx.handler_fn = getattr(ctx.handler, method)
+ except AttributeError, err:
+ raise http.HttpBadRequest("Method %s is unsupported for path %s" %
+ (method, req.request_path))
+
+ ctx.handler_access = getattr(ctx.handler, "%s_ACCESS" % method, None)
+
+ # Require permissions definition (usually in the base class)
+ if ctx.handler_access is None:
+ raise AssertionError("Permissions definition missing")
+
+ req.private = ctx
+
+ return req.private
+
+ def GetAuthRealm(self, req):
+ """Override the auth realm for queries.
+
+ """
+ ctx = self._GetRequestContext(req)
+ if ctx.handler_access:
+ return self.AUTH_REALM
+ else:
+ return None
+
+ def Authenticate(self, req, username, password):
+ """Checks whether a user can access a resource.
+
+ """
+ ctx = self._GetRequestContext(req)
+
+ # Check username and password
+ valid_user = False
+ if self._users:
+ user = self._users.get(username, None)
+ if user and user.password == password:
+ valid_user = True
+
+ if not valid_user:
+ # Unknown user or password wrong
+ return False
+
+ if (not ctx.handler_access or
+ set(user.options).intersection(ctx.handler_access)):
+ # Allow access
+ return True
+
+ # Access forbidden
+ raise http.HttpForbidden()
+