def before_request():
g.auth = True
g.requestId = gen_requestId()
g.registries= registries
g.registry = ApiRegistryManager(ActiveRegistry=g.registries.getActive)
g.sysInfo = {"Version": __version__, "Author": __author__, "Email": __email__, "Doc": __doc__}
logger.info("Start Once Access, and this requestId is {}".format(g.requestId))
#?????????????????????requestId????????????API, ??????.
python类auth()的实例源码
def _get_package(auth, owner, package_name):
"""
Helper for looking up a package and checking permissions.
Only useful for *_list functions; all others should use more efficient queries.
"""
package = (
Package.query
.filter_by(owner=owner, name=package_name)
.join(Package.access)
.filter(Access.user.in_([auth.user, PUBLIC]))
.one_or_none()
)
if package is None:
raise PackageNotFoundException(owner, package_name, auth.user is not PUBLIC)
return package
def _mp_track(**kwargs):
if g.user_agent['browser']['name'] == 'QuiltCli':
source = 'cli'
else:
source = 'web'
# Use the user ID if the user is logged in; otherwise, let MP use the IP address.
distinct_id = g.auth.user if g.auth.user != PUBLIC else None
# Try to get the ELB's forwarded IP, and fall back to the actual IP (in dev).
ip_addr = request.headers.get('x-forwarded-for', request.remote_addr)
# Set common attributes sent with each event. kwargs cannot override these.
all_args = dict(
kwargs,
time=time.time(),
ip=ip_addr,
user=g.auth.user,
source=source,
browser_name=g.user_agent['browser']['name'],
browser_version=g.user_agent['browser']['version'],
platform_name=g.user_agent['platform']['name'],
platform_version=g.user_agent['platform']['version'],
deployment_id=DEPLOYMENT_ID,
)
mp.track(distinct_id, MIXPANEL_EVENT, all_args)
def _get_or_create_customer():
assert HAVE_PAYMENTS, "Payments are not enabled"
assert g.auth.user != PUBLIC
db_customer = Customer.query.filter_by(id=g.auth.user).one_or_none()
if db_customer is None:
try:
# Insert a placeholder with no Stripe ID just to lock the row.
db_customer = Customer(id=g.auth.user)
db.session.add(db_customer)
db.session.flush()
except IntegrityError:
# Someone else just created it, so look it up.
db.session.rollback()
db_customer = Customer.query.filter_by(id=g.auth.user).one()
else:
# Create a new customer.
plan = PaymentPlan.FREE.value
customer = stripe.Customer.create(
email=g.auth.email,
description=g.auth.user,
)
stripe.Subscription.create(
customer=customer.id,
plan=plan,
)
db_customer.stripe_customer_id = customer.id
db.session.commit()
customer = stripe.Customer.retrieve(db_customer.stripe_customer_id)
assert customer.subscriptions.total_count == 1
return customer
def package_get(owner, package_name, package_hash):
subpath = request.args.get('subpath')
instance = _get_instance(g.auth, owner, package_name, package_hash)
contents = json.loads(instance.contents, object_hook=decode_node)
subnode = contents
for component in subpath.split('/') if subpath else []:
try:
subnode = subnode.children[component]
except (AttributeError, KeyError):
raise ApiException(requests.codes.not_found, "Invalid subpath: %r" % component)
all_hashes = set(find_object_hashes(subnode))
urls = {
blob_hash: _generate_presigned_url(S3_GET_OBJECT, owner, blob_hash)
for blob_hash in all_hashes
}
_mp_track(
type="install",
package_owner=owner,
package_name=package_name,
subpath=subpath,
)
return dict(
contents=contents,
urls=urls,
created_by=instance.created_by,
created_at=_utc_datetime_to_ts(instance.created_at),
updated_by=instance.updated_by,
updated_at=_utc_datetime_to_ts(instance.updated_at),
)
def package_preview(owner, package_name, package_hash):
instance = _get_instance(g.auth, owner, package_name, package_hash)
contents = json.loads(instance.contents, object_hook=decode_node)
readme = contents.children.get('README')
if isinstance(readme, FileNode):
assert len(readme.hashes) == 1
readme_url = _generate_presigned_url(S3_GET_OBJECT, owner, readme.hashes[0])
else:
readme_url = None
contents_preview = _generate_preview(contents)
_mp_track(
type="preview",
package_owner=owner,
package_name=package_name,
)
return dict(
preview=contents_preview,
readme_url=readme_url,
created_by=instance.created_by,
created_at=_utc_datetime_to_ts(instance.created_at),
updated_by=instance.updated_by,
updated_at=_utc_datetime_to_ts(instance.updated_at),
)
def package_list(owner, package_name):
package = _get_package(g.auth, owner, package_name)
instances = (
Instance.query
.filter_by(package=package)
)
return dict(
hashes=[instance.hash for instance in instances]
)
def package_delete(owner, package_name):
if g.auth.user != owner:
raise ApiException(requests.codes.forbidden,
"Only the package owner can delete packages.")
package = _get_package(g.auth, owner, package_name)
db.session.delete(package)
db.session.commit()
return dict()
def version_put(owner, package_name, package_version):
# TODO: Write access for collaborators.
if g.auth.user != owner:
raise ApiException(
requests.codes.forbidden,
"Only the package owner can create versions"
)
user_version = package_version
package_version = normalize_version(package_version)
data = request.get_json()
package_hash = data['hash']
instance = (
Instance.query
.filter_by(hash=package_hash)
.join(Instance.package)
.filter_by(owner=owner, name=package_name)
.one_or_none()
)
if instance is None:
raise ApiException(requests.codes.not_found, "Package hash does not exist")
version = Version(
package_id=instance.package_id,
version=package_version,
user_version=user_version,
instance=instance
)
try:
db.session.add(version)
db.session.commit()
except IntegrityError:
raise ApiException(requests.codes.conflict, "Version already exists")
return dict()
def version_get(owner, package_name, package_version):
package_version = normalize_version(package_version)
package = _get_package(g.auth, owner, package_name)
instance = (
Instance.query
.join(Instance.versions)
.filter_by(package=package, version=package_version)
.one_or_none()
)
if instance is None:
raise ApiException(
requests.codes.not_found,
"Version %s does not exist" % package_version
)
_mp_track(
type="get_hash",
package_owner=owner,
package_name=package_name,
package_version=package_version,
)
return dict(
hash=instance.hash,
created_by=instance.created_by,
created_at=_utc_datetime_to_ts(instance.created_at),
updated_by=instance.updated_by,
updated_at=_utc_datetime_to_ts(instance.updated_at),
)
def tag_get(owner, package_name, package_tag):
package = _get_package(g.auth, owner, package_name)
instance = (
Instance.query
.join(Instance.tags)
.filter_by(package=package, tag=package_tag)
.one_or_none()
)
if instance is None:
raise ApiException(
requests.codes.not_found,
"Tag %r does not exist" % package_tag
)
_mp_track(
type="get_hash",
package_owner=owner,
package_name=package_name,
package_tag=package_tag,
)
return dict(
hash=instance.hash,
created_by=instance.created_by,
created_at=_utc_datetime_to_ts(instance.created_at),
updated_by=instance.updated_by,
updated_at=_utc_datetime_to_ts(instance.updated_at),
)
def access_delete(owner, package_name, user):
if g.auth.user != owner:
raise ApiException(
requests.codes.forbidden,
"Only the package owner can revoke access"
)
if user == owner:
raise ApiException(
requests.codes.forbidden,
"Cannot revoke the owner's access"
)
if HAVE_PAYMENTS and user == PUBLIC:
customer = _get_or_create_customer()
plan = _get_customer_plan(customer)
if plan == PaymentPlan.FREE:
raise ApiException(
requests.codes.payment_required,
"Insufficient permissions. " +
"Upgrade your plan to create private packages: https://quiltdata.com/profile."
)
access = (
Access.query
.with_for_update()
.filter_by(user=user)
.join(Access.package)
.filter_by(owner=owner, name=package_name)
.one_or_none()
)
if access is None:
raise PackageNotFoundException(owner, package_name)
db.session.delete(access)
db.session.commit()
return dict()
def access_list(owner, package_name):
accesses = (
Access.query
.join(Access.package)
.filter_by(owner=owner, name=package_name)
)
can_access = [access.user for access in accesses]
is_collaborator = g.auth.user in can_access
is_public = PUBLIC in can_access
if is_public or is_collaborator:
return dict(users=can_access)
else:
raise PackageNotFoundException(owner, package_name)
def search():
query = request.args.get('q', '')
keywords = query.split()
if len(keywords) > 5:
# Let's not overload the DB with crazy queries.
raise ApiException(requests.codes.bad_request, "Too many search terms (max is 5)")
filter_list = [
sa.func.instr(
sa.sql.collate(sa.func.concat(Package.owner, '/', Package.name), UTF8_GENERAL_CI),
keyword
) > 0
for keyword in keywords
]
results = (
db.session.query(Package, sa.func.max(Access.user == PUBLIC))
.filter(sa.and_(*filter_list))
.join(Package.access)
.filter(Access.user.in_([g.auth.user, PUBLIC]))
.group_by(Package.id)
.order_by(
sa.sql.collate(Package.owner, UTF8_GENERAL_CI),
sa.sql.collate(Package.name, UTF8_GENERAL_CI)
)
.all()
)
return dict(
packages=[
dict(
owner=package.owner,
name=package.name,
is_public=is_public,
) for package, is_public in results
]
)
def invitation_user_list():
invitations = (
db.session.query(Invitation, Package)
.filter_by(email=g.auth.email)
.join(Invitation.package)
.all()
)
return dict(invitations=[dict(invitation_id=invite.id,
owner=package.owner,
package=package.name,
email=invite.email,
invited_at=invite.invited_at)
for invite, package in invitations])
def invitation_package_list(owner, package_name):
package = _get_package(g.auth, owner, package_name)
invitations = (
Invitation.query
.filter_by(package_id=package.id)
)
return dict(invitations=[dict(invitation_id=invite.id,
owner=package.owner,
package=package.name,
email=invite.email,
invited_at=invite.invited_at)
for invite in invitations])
def send_request(method, path, body=None, transaction=True, impersonate_as=None, retry_num=10):
oa_uri = request.headers.get('aps-controller-uri')
url = urljoin(oa_uri, path)
headers = {'Content-Type': 'application/json'}
if impersonate_as:
headers['aps-resource-id'] = impersonate_as
if transaction and request.headers.get('aps-transaction-id'):
headers['aps-transaction-id'] = request.headers.get('aps-transaction-id')
data = None if body is None else json.dumps(body)
retry_num = retry_num if retry_num > 0 else 1
with Session() as s:
prepared = Request(
method=method,
url=url,
data=data,
headers=headers,
auth=g.auth
).prepare()
while retry_num > 0:
retry_num -= 1
try:
g.log['out'].append(dict(request=None, response=None))
g.log['out'][-1]['request'] = log_outgoing_request(prepared)
resp = s.send(prepared, timeout=OA.request_timeout, verify=False)
g.log['out'][-1]['response'] = log_outgoing_response(resp)
except requests.exceptions.Timeout:
err = ErrorResponse(None, 'Request to OA timed out. '
'Timeout: {}'.format(OA.request_timeout))
raise OACommunicationException(err)
except Exception as e:
err = ErrorResponse(None, str(e))
raise OACommunicationException(err)
if resp.status_code == 200:
return resp.json()
elif resp.status_code != 400:
raise OACommunicationException(resp)
raise OACommunicationException(resp)
def api(require_login=True, schema=None):
"""
Decorator for API requests.
Handles auth and adds the username as the first argument.
"""
if schema is not None:
Draft4Validator.check_schema(schema)
validator = Draft4Validator(schema)
else:
validator = None
def innerdec(f):
@wraps(f)
def wrapper(*args, **kwargs):
g.auth = Auth(PUBLIC, None)
user_agent_str = request.headers.get('user-agent', '')
g.user_agent = httpagentparser.detect(user_agent_str, fill_none=True)
if validator is not None:
try:
validator.validate(request.get_json(cache=True))
except ValidationError as ex:
raise ApiException(requests.codes.bad_request, ex.message)
auth = request.headers.get(AUTHORIZATION_HEADER)
g.auth_header = auth
if auth is None:
if require_login:
raise ApiException(requests.codes.unauthorized, "Not logged in")
else:
headers = {
AUTHORIZATION_HEADER: auth
}
try:
resp = requests.get(OAUTH_USER_API, headers=headers)
resp.raise_for_status()
data = resp.json()
# TODO(dima): Generalize this.
user = data.get('current_user', data.get('login'))
assert user
email = data['email']
g.auth = Auth(user, email)
except requests.HTTPError as ex:
if resp.status_code == requests.codes.unauthorized:
raise ApiException(
requests.codes.unauthorized,
"Invalid credentials"
)
else:
raise ApiException(requests.codes.server_error, "Server error")
except (ConnectionError, requests.RequestException) as ex:
raise ApiException(requests.codes.server_error, "Server error")
return f(*args, **kwargs)
return wrapper
return innerdec
def tag_put(owner, package_name, package_tag):
# TODO: Write access for collaborators.
if g.auth.user != owner:
raise ApiException(
requests.codes.forbidden,
"Only the package owner can modify tags"
)
data = request.get_json()
package_hash = data['hash']
instance = (
Instance.query
.filter_by(hash=package_hash)
.join(Instance.package)
.filter_by(owner=owner, name=package_name)
.one_or_none()
)
if instance is None:
raise ApiException(requests.codes.not_found, "Package hash does not exist")
# Update an existing tag or create a new one.
tag = (
Tag.query
.with_for_update()
.filter_by(package_id=instance.package_id, tag=package_tag)
.one_or_none()
)
if tag is None:
tag = Tag(
package_id=instance.package_id,
tag=package_tag,
instance=instance
)
db.session.add(tag)
else:
tag.instance = instance
db.session.commit()
return dict()