Exemplo n.º 1
0
def auth_async(code):
    try:
        result = yield _fetch_async(
            'https://www.googleapis.com/oauth2/v4/token',
            method='POST',
            payload=urllib.urlencode({
                'client_id':
                '_REMOVED_',
                'code':
                code,
                'grant_type':
                'authorization_code',
                'redirect_uri':
                'cam.reaction.ReactionCam:/youtube_oauth2redirect',
            }),
            follow_redirects=False,
            deadline=10)
        data = json.loads(result.content)
    except Exception as e:
        logging.exception('YouTube token exchange failed.')
        raise errors.ServerError()
    if result.status_code != 200:
        logging.debug('Could not exchange code: %r', data)
        raise errors.InvalidArgument('Failed to exchange code for token')
    try:
        id_token = data.pop('id_token')
        id_hdr, id_bdy, id_sig = (p + ('=' * (-len(p) % 4))
                                  for p in id_token.split('.'))
        profile = json.loads(base64.b64decode(id_bdy))
        assert 'sub' in profile
    except:
        logging.debug('Could not extract profile data: %r', data)
        raise errors.InvalidArgument('Missing profile in token response')
    raise ndb.Return((data, profile))
Exemplo n.º 2
0
def get_video_async(video_id, snippet=True, statistics=False):
    if not (snippet or statistics):
        raise errors.InvalidArgument(
            'Specify at least one of snippet, statistics')
    parts = []
    if snippet:
        parts.append('snippet')
    if statistics:
        parts.append('statistics')
    try:
        qs = urllib.urlencode({
            'id': video_id,
            'key': config.YOUTUBE_API_KEY,
            'part': ','.join(parts),
        })
        result = yield _fetch_async(
            'https://www.googleapis.com/youtube/v3/videos?%s' % (qs, ),
            follow_redirects=False,
            deadline=10)
        data = json.loads(result.content)
    except Exception as e:
        logging.exception('YouTube call failed.')
        raise errors.ServerError()
    if result.status_code == 404:
        raise errors.ResourceNotFound('That video does not exist')
    elif result.status_code != 200:
        logging.debug('Could not get YouTube video (%d): %r',
                      result.status_code, data)
        raise errors.InvalidArgument('Invalid video id')
    if data['pageInfo']['totalResults'] == 0:
        raise ndb.Return(None)
    if not data['items']:
        logging.warning('Expected at least one item in data: %r', data)
        raise ndb.Return(None)
    raise ndb.Return(data['items'][0])
Exemplo n.º 3
0
 def _tx(self, method, *args, **kwargs):
     for _ in xrange(2):
         stream = method(self._stream.key, *args, **kwargs)
         if stream: break
     else:
         # If the loop falls through, stream was never set.
         raise errors.ServerError(
             'Failed to update stream (transaction rolled back)')
     self._stream = stream
     self._chunks = None
Exemplo n.º 4
0
 def validate(self, secret):
     result = models.Challenge.validate(self.client, self.identifier,
                                        secret)
     if result == models.Challenge.SUCCESS:
         return True
     elif result == models.Challenge.INVALID_SECRET:
         raise errors.InvalidArgument('An invalid secret was provided')
     elif result == models.Challenge.TOO_MANY_ATTEMPTS:
         raise errors.ResourceNotFound('Too many attempts')
     elif result == models.Challenge.EXPIRED:
         raise errors.ResourceNotFound('Challenge has expired')
     # Unexpected result.
     raise errors.ServerError()
Exemplo n.º 5
0
 def react_to_chunk(self, chunk_id, reaction_type):
     chunk_key = ndb.Key('Chunk', int(chunk_id), parent=self.key)
     stream, chunk = models.Stream.set_chunk_reaction(
         chunk_key, self.account.key, reaction_type)
     if not stream:
         raise errors.ServerError(
             'Failed to update stream (transaction rolled back)')
     self._stream = stream
     self._chunks = None
     self.notify(notifs.ON_STREAM_CHUNK_REACTION,
                 add_stream=True,
                 chunk=chunk)
     return chunk
Exemplo n.º 6
0
def itunes(receipt_data, url='https://buy.itunes.apple.com/verifyReceipt'):
    try:
        result = urlfetch.fetch(url=url,
                                method=urlfetch.POST,
                                payload=json.dumps(
                                    {'receipt-data': receipt_data}),
                                deadline=30)
        data = json.loads(result.content)
    except Exception:
        logging.exception('Could not get result from Apple payment server.')
        raise errors.ServerError()
    if result.status_code != 200:
        logging.error('Apple payment server HTTP %d: %r', result.status_code,
                      data)
        raise errors.InvalidArgument(
            'Failed to validate receipt data with Apple')
    status = data.get('status')
    if not isinstance(status, (int, long)):
        logging.error('Could not get status: %r', data)
        raise errors.ServerError()
    if status == 0:
        return data
    elif status in (21000, 21002, 21003):
        raise errors.InvalidArgument('Invalid receipt data provided')
    elif status == 21005:
        raise errors.ExternalError()
    elif status == 21007:
        return itunes(receipt_data,
                      url='https://sandbox.itunes.apple.com/verifyReceipt')
    elif status == 21008:
        return itunes(receipt_data)
    elif status == 21010:
        raise errors.InvalidArgument('Invalid purchase')
    elif 21100 <= status <= 21199:
        logging.error('Internal data access error: %r', data)
        raise errors.InvalidArgument('Invalid receipt data provided')
    logging.error('Unsupported status: %r', data)
    raise errors.NotSupported()
Exemplo n.º 7
0
def _s3_upload(data, data_sha256, extension, mime_type):
    filename = data_sha256 + extension
    try:
        result = _aws4_signed_fetch(region='us-east-1', service='s3',
                                    headers={'x-amz-acl': 'public-read',
                                             'x-amz-content-sha256': data_sha256,
                                             'Content-Type': mime_type},
                                    method='PUT', host='s3.amazonaws.com',
                                    path='/%s/%s' % (config.S3_BUCKET, filename),
                                    payload=data, payload_sha256=data_sha256)
    except:
        logging.exception('Could not upload to S3.')
        raise errors.ServerError()
    if result.status_code != 200:
        logging.debug('Could not upload file: %r', result.content)
        raise errors.InvalidArgument('Failed to upload file')
    return config.S3_BUCKET_CDN + filename
Exemplo n.º 8
0
def get_channels_async(youtube_refresh_token):
    try:
        qs = urllib.urlencode({
            'youtube_token': youtube_refresh_token,
        })
        result = yield _fetch_async(
            'https://upload.reaction.cam/v2/channels?%s' % (qs, ),
            follow_redirects=False,
            headers={'Authorization': 'Bearer ' + ACCESS_TOKEN},
            deadline=10)
        data = json.loads(result.content)
    except Exception as e:
        logging.exception('YouTube call failed.')
        raise errors.ServerError()
    if result.status_code in (400, 401):
        # TODO: We should probably invalidate the token.
        raise ndb.Return([])
    if result.status_code != 200:
        logging.debug('Could not get channels (%d): %r', result.status_code,
                      data)
        raise errors.ExternalError('Could not get channels')
    raise ndb.Return(data['channels'])