def post(self, ar, grant=None, character=None): from brave.core.character.model import EVECharacter from brave.core.application.model import ApplicationGrant ar = self.ar(ar) u = user._current_obj() if not grant: # Deny access. ar.user = u ar.grant = None ar.expires = datetime.utcnow() + timedelta( minutes=10) # extend to allow time for verification ar.save() target = URL(ar.failure) target.query.update(dict(token=str(ar.id))) return 'json:', dict(success=True, location=str(target)) try: character = EVECharacter.objects.get(owner=u, id=character) except EVECharacter.DoesNotExist: return 'json:', dict(success=False, message="Unknown character ID.") except: log.exception("Error loading character.") return 'json:', dict(success=False, message="Error loading character.") # TODO: Non-zero grants. grant = ApplicationGrant(user=u, application=ar.application, mask=0, expires=datetime.utcnow() + timedelta(days=30), character=character) grant.save() ar.user = u ar.grant = grant ar.expires = datetime.utcnow() + timedelta( minutes=10) # extend to allow time for verification ar.save() target = URL(ar.success) target.query.update(dict(token=str(grant.id))) return 'json:', dict(success=True, location=str(target))
def _partial(self, path, params, anchor): """Prepare a resource path.""" base, current, controller = self._base url = URL() if not path: url.path = str(URL(current).path) else: url.path = base if path.startswith('/') else controller url.path.append(path[1:] if path.startswith('/') else path) url.query = params url.fragment = anchor return str(url)
def get(self, ar): from brave.core.application.model import ApplicationGrant ar = self.ar(ar) u = user._current_obj() grant = ApplicationGrant.objects(user=u, application=ar.application).first() if not grant: # TODO: We need a 'just logged in' flag in the request. characters = list(u.characters.order_by('name').all()) if len(characters): default = u.primary or characters[0] else: return ( 'brave.core.template.authorize', dict( success=False, message= _("This application requires that you have a character connected to your" " account. Please <a href=\"/key/\">add an API key</a> to your account." ), ar=ar)) return 'brave.core.template.authorize', dict(success=True, ar=ar, characters=characters, default=default) ngrant = ApplicationGrant(user=u, application=ar.application, mask=grant.mask, expires=datetime.utcnow() + timedelta(days=30), character=grant.character) ngrant.save() ar.user = u ar.grant = ngrant ar.expires = datetime.utcnow() + timedelta( minutes=10) # extend to allow time for verification ar.save() r = grant.delete() target = URL(ar.success) target.query.update(dict(token=str(ngrant.id))) raise HTTPFound(location=str(target))
def _full(self, path, params, anchor, protocol, host, port): """Prepare a complete URL.""" base, current, controller = self._base url = URL(current) url.path = self._partial(path, None, None) if protocol: url.scheme = protocol if host: url.host = host if port: url.port = port url.params = params url.fragment = anchor return str(url)
def authorize(self, success=None, failure=None): """Prepare a incoming session request. Error 'message' attributes are temporary; base your logic on the status and code attributes. success: web.core.url:URL (required) failure: web.core.url:URL (required) returns: location: web.core.url:URL the location to direct users to """ # Ensure success and failure URLs are present. if success is None: response.status_int = 400 return dict( status='error', code='argument.success.missing', message= "URL to return users to upon successful authentication is missing from your request." ) if failure is None: response.status_int = 400 return dict( status='error', code='argument.failure.missing', message= "URL to return users to upon authentication failure or dismissal is missing from your request." ) # Also ensure they are valid URIs. try: success_ = success success = URL(success) except: response.status_int = 400 return dict(status='error', code='argument.success.malformed', message="Successful authentication URL is malformed.") try: failure_ = failure failure = URL(failure) except: response.status_int = 400 return dict( status='error', code='argument.response.malformed', message= "URL to return users to upon successful authentication is missing from your request." ) # Deny localhost/127.0.0.1 loopbacks and 192.* and 10.* unless in development mode. if not boolean(config.get('debug', False)) and (success.host in ('localhost', '127.0.0.1') or \ success.host.startswith('192.168.') or \ success.host.startswith('10.')): response.status_int = 400 return dict( status='error', code='development-only', message= "Loopback and local area-network URLs disallowd in production." ) # Check blacklist and bail early. if AuthenticationBlacklist.objects( reduce(__or__, [ Q(scheme=success.scheme), Q(scheme=failure.scheme), Q(protocol=success.port or success.scheme), Q(protocol=failure.port or failure.scheme), ] + ([] if not success.host else [Q(domain=success.host)]) + ([] if not failure.host else [Q( domain=failure.host)]))).count(): response.status_int = 400 return dict( status='error', code='blacklist', message="You have been blacklisted. To dispute, contact {0}". format(config['mail.blackmail.author'])) # TODO: Check DNS. Yes, really. # Generate authentication token. log.info("Creating request for {0} with callbacks {1} and {2}.".format( request.service, success_, failure_)) ar = AuthenticationRequest( request. service, # We have an authenticated request, so we know the service ID is valid. success=success_, failure=failure_) ar.save() return dict(location=url.complete('/authorize/{0}'.format(ar.id)))