def get(self, jti): # Grab the jwt out of the database jwt = DownloadLink.get(jti) # If no jwt, error response if jwt is None: raise HTTPError( 404, reason='Download Not Found. Link may have expired.') # If jwt doesn't validate, error response jwt_data = jose_jwt.decode(jwt, qiita_config.jwt_secret, 'HS256') if jwt_data is None: raise HTTPError(403, reason='Invalid JWT') # Triple check expiration and user permissions user = User(jwt_data["sub"]) artifact = Artifact(jwt_data["artifactId"]) utc_millis = datetime.now(timezone.utc).timestamp() * 1000 if utc_millis < jwt_data["iat"]: raise HTTPError(403, reason="This download link is not yet valid") if utc_millis > jwt_data["exp"]: raise HTTPError(403, reason="This download link has expired") if jwt_data["perm"] != "download": raise HTTPError(403, reason="This download link is invalid") check_artifact_access(user, artifact) # All checks out, let's give them the files then! to_download = self._list_artifact_files_nginx(artifact) if not to_download: raise HTTPError(422, reason='Nothing to download. If ' 'this is a mistake contact: ' '*****@*****.**') else: self._write_nginx_file_list(to_download) zip_fn = 'artifact_%s_%s.zip' % ( jwt_data["artifactId"], datetime.now().strftime( '%m%d%y-%H%M%S')) self._set_nginx_headers(zip_fn) self.finish()
def post(self, artifact_id): # Generate a new download link: # 1. Build a signed jwt specifying the user and # the artifact they wish to download # 2. Write that jwt to the database keyed by its jti # (jwt ID/ json token identifier) # 3. Return the jti as a short url to be used for download user = self.current_user artifact = Artifact(artifact_id) # Check that user is currently allowed to access artifact, else throw check_artifact_access(user, artifact) # Generate a jwt id as a random uuid in base64 jti = b64encode(uuid4().bytes).decode("utf-8") # Sign a jwt allowing access utcnow = datetime.now(timezone.utc) jwt = jose_jwt.encode({ "artifactId": str(artifact_id), "perm": "download", "sub": str(user._id), "email": str(user.email), "iat": int(utcnow.timestamp() * 1000), "exp": int((utcnow + timedelta(days=7)).timestamp() * 1000), "jti": jti }, qiita_config.jwt_secret, algorithm='HS256' ) # Save the jwt to the database DownloadLink.create(jwt) url = qiita_config.base_url + '/private_download/' + jti user_msg = "This link will expire in 7 days on: " + \ (utcnow + timedelta(days=7)).strftime('%Y-%m-%d') self.set_status(200) self.finish({"url": url, "msg": user_msg})
def test_check_artifact_access(self): # "Study" artifact a = Artifact(1) # The user has access u = User('*****@*****.**') check_artifact_access(u, a) # Admin has access to everything admin = User('*****@*****.**') check_artifact_access(admin, a) # Demo user doesn't have access demo_u = User('*****@*****.**') with self.assertRaises(HTTPError): check_artifact_access(demo_u, a) # "Analysis" artifact a = Artifact(8) a.visibility = 'private' check_artifact_access(u, a) check_artifact_access(admin, a) with self.assertRaises(HTTPError): check_artifact_access(demo_u, a) check_artifact_access(User('*****@*****.**'), a) a.visibility = 'public' check_artifact_access(demo_u, a)
def test_check_artifact_access(self): # "Study" artifact a = Artifact(1) # The user has access u = User('*****@*****.**') check_artifact_access(u, a) # Admin has access to everything admin = User('*****@*****.**') check_artifact_access(admin, a) # Demo user doesn't have access demo_u = User('*****@*****.**') with self.assertRaises(HTTPError): check_artifact_access(demo_u, a) # "Analysis" artifact a = Artifact(8) a.visibility = 'private' check_artifact_access(u, a) check_artifact_access(admin, a) with self.assertRaises(HTTPError): check_artifact_access(demo_u, a) check_artifact_access(User('*****@*****.**'), a) a.visibility = 'public' check_artifact_access(demo_u, a)