Beispiel #1
0
    def start_auth(self, request):
        try:
            if not self.get_arguments(request, "service"):
                self.write(request, error_format("Missing argument 'service'"), 400)
                self.finish(request)
            else:
                service_name = self.get_argument(request, "service")
                got_error = False
                try:
                    service = self.get_service(self.get_argument(request, "service"), request)
                except KeyError:
                    got_error = True
                    self.write(request, error_format("Service '%s' unknown" % service_name), 404)
                if not got_error:
                    args = self.arguments(request)
                    del args["service"]
                    got_error = False
                    try:
                        auth_url = yield service.start_authorization(
                            client_name=self.get_client_name(request), args=args
                        )
                    except LightningError as exc:
                        got_error = True
                        self.write(request, exc.error_msg, exc.code)

                    if not got_error:
                        self.write(request, {"redirect": auth_url})
            self.finish(request)
        except Exception as exc:
            self.write_error(request, exc)
            self.finish(request)
Beispiel #2
0
 def test_post_too_many_guids(self):
     return self.post_and_verify(
         path='/data/loopback/time',
         args=dict(guid=['asdf', 'efgh']),
         response_code=400,
         result=error_format("Too many GUIDs provided"),
     )
Beispiel #3
0
 def test_post_unknown_guid(self):
     return self.post_and_verify(
         path='/data/loopback/time',
         args=dict(guid='asdf'),
         response_code=400,
         result=error_format("Unknown GUID provided"),
     )
Beispiel #4
0
    def revoke_auth(self, request):
        service_name = self.name
        """Revoke OAuth token callback for service.
        If a user revoke's our application's permissions in the service's
        settings, the service will hit this callback so we can remove the
        user's token and any other data.
        """
        try:
            signed_request = self.get_arguments(request, "signed_request")
            client_name = self.get_client_name(request)
            if not signed_request:
                raise HandlerError("Missing argument 'signed_request'", 400)

            service = self.get_service(service_name, request)
            user_id = yield service.service_revoke_authorization(client_name=client_name, args=self.arguments(request))
            ret = yield self.application.db.delete_oauth_token(
                client_name=client_name, service_name=service_name, user_id=user_id
            )
            if not ret:
                raise HandlerError("Revocation failed", 404)

            self.write(request, {"success": "Revocation successful"})
            self.finish(request)
        except HandlerError as exc:
            self.write(request, error_format(exc.message), exc.code)
            self.finish(request)
Beispiel #5
0
    def delete_auth(self, request):
        try:
            guid = self.name
            authz = yield Authz(uuid=guid).get_token(self.application.db)
            if not authz:
                raise HandlerError("guid '%s' not found" % guid, 404)

            # Grab the service.
            service = self.get_service(authz.service_name, request)
            # Delete the token and call the revocation method.
            data_ret = yield defer.gatherResults(
                [
                    service.revoke_authorization(authorization={"token": authz.token}),
                    self.application.db.delete_user_data(
                        uuid=guid, user_id=authz.user_id, service_name=authz.service_name
                    ),
                ]
            )
            ret = yield self.application.db.delete_oauth_token(uuid=guid)

            if not ret or not data_ret:
                raise HandlerError("Revocation failed", 404)

            self.write(request, {"success": "Revocation successful"})
            self.finish(request)
        except HandlerError as exc:
            self.write(request, error_format(exc.message), exc.code)
            self.finish(request)
Beispiel #6
0
 def test_post_unauthorized_bad_guid(self):
     return self.post_and_verify(
         path='/api/loopback/sleep_post',
         args=dict(guid='asdf'),
         response_code=401,
         result=error_format("User not authorized"),
     )
Beispiel #7
0
 def test_delete_not_found(self):
     # Confirm that attempting to delete
     return self.delete_and_verify(
         path='/auth/not_found',
         response_code=404,
         result=error_format("guid 'not_found' not found"),
     )
Beispiel #8
0
    def test_get_view_multiple_guids_same_guid(self):
        yield self.post_and_verify(
            path="/view",
            args=json.dumps(
                dict(
                    name="foo",
                    definition=[
                        {"service": "loopback", "method": "num_foo"},
                        {"service": "loopback", "method": "random"},
                    ],
                )
            ),
            response_code=200,
            result={"success": "View 'foo' created"},
        )

        yield self.set_authorization(user_id="1234")
        uuid_one = self.uuid

        yield self.get_and_verify(
            path="/view/foo/invoke",
            args=dict(guid=[uuid_one, uuid_one]),
            response_code=400,
            result=error_format("Duplicate GUIDs '%s' provided" % uuid_one),
        )
Beispiel #9
0
 def test_unsupported_url_json_response_delete(self):
     return self.delete_and_verify(
         path='/does/not/exist',
         response_code=404,
         response_type='application/json',
         result=error_format("'/does/not/exist' not found"),
     )
Beispiel #10
0
 def _test_post_error(self, args, error):
     return self.post_and_verify(
         path='/status',
         args=args,
         response_code=400,
         result=error_format(error),
     )
Beispiel #11
0
 def test_get_bad_service(self):
     yield self.set_authorization(user_id="2345")
     yield self.get_and_verify(
         path="/stream",
         args=dict(guid=self.uuid, service="no_such_service"),
         response_code=404,
         result=error_format("Service 'no_such_service' unknown"),
     )
Beispiel #12
0
 def test_post_guid_for_wrong_service(self):
     yield self.set_authorization(client_name='testing2')
     yield self.post_and_verify(
         path='/data/loopback/time',
         args=dict(guid=self.uuid),
         response_code=400,
         result=error_format("Unknown GUID provided"),
     )
Beispiel #13
0
 def test_get_bad_uuid_for_service(self):
     yield self.set_authorization()
     yield self.get_and_verify(
         path="/stream",
         args=dict(guid=self.uuid, service="loopback2"),
         response_code=400,
         result=error_format("Unknown GUIDs provided"),
     )
Beispiel #14
0
 def test_get_bad_forward(self):
     yield self.set_authorization()
     yield self.get_and_verify(
         path="/stream",
         args=dict(guid=self.uuid, forward="a"),
         response_code=400,
         result=error_format("Bad value for 'forward'"),
     )
Beispiel #15
0
 def test_post_guid_for_wrong_service(self):
     yield self.set_authorization(service_name='loopback2')
     yield self.post_and_verify(
         path='/api/loopback/sleep_post',
         args=dict(guid=self.uuid),
         response_code=401,
         result=error_format("User not authorized"),
     )
Beispiel #16
0
    def finish_auth(self, request):
        try:
            if not self.get_arguments(request, "service"):
                raise HandlerError("Missing argument 'service'", 400)

            service_name = self.get_argument(request, "service")
            try:
                service = self.get_service(service_name, request)
            except KeyError:
                raise HandlerError("Service '%s' unknown" % service_name, 404)

            client_name = self.get_client_name(request)

            authorization = yield service.finish_authorization(client_name=client_name, args=self.arguments(request))

            # Upon successful initial authz, enqueue the daemon for right away.
            if authorization.is_new and service.daemon_class.__name__ in daemons.DAEMONS and self.application.redis:
                try:
                    from twistedpyres import ResQ

                    resq = ResQ(redis=self.application.redis)

                    for method in service.daemon_class._recurring:
                        yield resq.enqueue_at(
                            (datetime.now() + timedelta(seconds=1)),
                            service.daemon_class,
                            {"sql": service.datastore.config, "environment": service.environment},
                            authorization.uuid,
                            method,
                            redis=self.application.redis,
                        )

                except Exception as e:
                    logging.error("Error trying to queue: %s" % e.message)
                    raise e
            self.set_header(request, "Location", "/auth/%s" % authorization.uuid)
            self.write(request, {"guid": authorization.uuid}, status=201)
            self.finish(request)

            # Set account timestamp after we return a guid since this may be an
            # expensive API call.
            if authorization.is_new:
                if "account_created_timestamp" in service._methods["GET"]:
                    try:
                        yield service.account_created_timestamp(authorization=authorization)
                    except Exception as e:
                        logging.error("Error getting account timestamp: %s" % e)

        except LightningError as exc:
            self.write(request, exc.error_msg, exc.code)
            self.finish(request)
        except HandlerError as exc:
            self.write(request, error_format(exc.message), exc.code)
            self.finish(request)
        except Exception as exc:
            logging.error(exc)
            self.write_error(request, exc)
            self.finish(request)
Beispiel #17
0
    def add_data(self, request):

        try:
            service_name = self.service_name
            method_name = self.method_name

            try:
                service = self.get_service(service_name, request)
            except KeyError:
                raise HandlerError("Service '%s' unknown" % service_name, 404)

            if not method_name in service.methods()['GET']:
                raise HandlerError("Method '%s' on service '%s' unknown" % (method_name, service_name), 404)

            guids = self.get_arguments(request, 'guid')
            if not len(guids):
                raise HandlerError("No GUID provided", 400)

            elif len(guids) > 1:
                raise HandlerError("Too many GUIDs provided", 400)

            authorization = yield Authz(
                uuid=guids[0],
                client_name=self.get_client_name(request),
            ).get_token(self.application.db)

            if not authorization:
                raise HandlerError("Unknown GUID provided", 400)

            values = self.get_arguments(request, 'value')
            if not len(values):
                raise HandlerError("No value provided", 400)

            elif len(values) > 1:
                raise HandlerError("Too many values provided", 400)

            timestamp = int(self.get_argument(request, 'timestamp', time.time()))
            try:
                yield service.write_new_value(
                    authorization=authorization,
                    method=method_name,
                    data=json.loads(values[0]),
                    timestamp=timestamp,
                )
            except ValueError:
                raise HandlerError("Invalid JSON provided", 400)

            except KeyError:
                raise HandlerError("Wrong key for data provided", 400)

            self.write(request, {'success': '/%s/%s written' % (service_name, method_name)})
            self.finish(request)
        except HandlerError as exc:
            self.write(request, error_format(exc.message), exc.code)
            self.finish(request)
        except Exception as exc:
            self.write_error(request, exc)
            self.finish(request)
Beispiel #18
0
    def test_loopback_broken(self):
        yield self.set_authorization()

        yield self.get_and_verify(
            path='/api/loopback/broken',
            args=dict(guid=self.uuid),
            response_code=500,
            result=error_format('500 This method is intentionally broken'),
        )
Beispiel #19
0
 def test_start_authorize_failure(self):
     return self.get_and_verify(
         path='/auth',
         args=dict(
             service='loopback',
         ),
         response_code=400,
         result=error_format("Missing arguments: 'redirect_uri', 'username'", code=400),
     )
Beispiel #20
0
 def test_get_multiple_uuids_same_service(self):
     yield self.set_authorization(user_id="1234")
     uuid1 = self.uuid
     yield self.set_authorization(user_id="2345")
     yield self.get_and_verify(
         path="/stream",
         args=dict(guid=[uuid1, self.uuid]),
         response_code=400,
         result=error_format("Multiple GUIDs for one service provided"),
     )
Beispiel #21
0
    def test_post_no_value(self):
        yield self.set_authorization()

        yield self.post_and_verify(
            path='/data/loopback/time',
            args=dict(
                guid=self.uuid,
            ),
            response_code=400,
            result=error_format("No value provided"),
        )
Beispiel #22
0
    def test_post_wrong_key(self):
        yield self.set_authorization()

        yield self.post_and_verify(
            path='/data/loopback/time',
            args=dict(
                guid=self.uuid,
                value=json.dumps({'num': 100}),
            ),
            response_code=400,
            result=error_format("Wrong key for data provided"),
        )
Beispiel #23
0
    def test_post_too_many_values(self):
        yield self.set_authorization()

        yield self.post_and_verify(
            path='/data/loopback/time',
            args=dict(
                guid=self.uuid,
                value=['a', 'b'],
            ),
            response_code=400,
            result=error_format("Too many values provided"),
        )
Beispiel #24
0
    def write_error(self, request, exc, status=500):
        "Decorate the write_error() method with useful JSONification"
        if status == 404:
            error = "'%s' not found" % (self.request.path)
        elif status == 405:
            error = "'%s' not supported for '%s'" % (
                self.request.method, self.request.path
            )
        elif status == 500:
            email_message = []

            if exc:
                # Prepare the items for
                email_message.append('%s - (REMOTE IP: %s) %s %s' % (
                    status,
                    request.getClientIP(),
                    request.method,
                    request.uri
                ))

                email_message.append('HEADERS: ' + str(request.requestHeaders))

                # (error_type, error, traceback) = kwargs['exception'].exc_info
                # append to the email message
                # email_message.append('ERROR TYPE: ' + str(error_type))
                # email_message.append('STACK TRACE:\n' + ''.join(format_list(extract_tb(traceback))))

                try:
                    error = exc.log_message
                # This means it wasn't an HTTPError
                except AttributeError as e:
                    error = str(exc)
            else:
                error = 'Internal Server Error'

            # add the specific email error to the top of the email
            email_message.insert(0, 'ERROR: ' + error)

            # send the email
            self.application.email.send(
                subject='ERROR: %s [%s %s]' % (
                    error,
                    request.method,
                    request.uri
                ),
                message='\n\n'.join(email_message)
            )
            # write to log
            logging.error(error)

        request.setResponseCode(status)
        self.write(request, error_format(error), status)
Beispiel #25
0
 def test_post_unauthorized_too_many_guids(self):
     yield self.set_authorization(
         user_id='a1234', token='some token',
     )
     first_uuid = self.uuid
     yield self.set_authorization(
         user_id='b2345', token='some other token',
     )
     yield self.post_and_verify(
         path='/api/loopback/sleep_post',
         args=dict(guid=[first_uuid, self.uuid]),
         response_code=401,
         result=error_format("Too many GUIDs"),
     )
Beispiel #26
0
    def delete_view(self, request):
        try:
            name = self.view_name
            view = yield self.application.db.get_view(name)
            if not view:
                self.write(request, error_format("View '%s' unknown" % name), 404)
            else:
                yield self.application.db.delete_view(name)

                self.write(request, {'definition': view})
            self.finish(request)
        except Exception as exc:
            self.write_error(request, exc)
            self.finish(request)
Beispiel #27
0
    def invoke_post_method(self, request):
        try:
            service_name = self.service_name
            method_name = self.method_name

            try:
                service = self.get_service(service_name, request)
            except KeyError:
                raise HandlerError("Service '%s' unknown" % service_name, 404)

            if not method_name in service.methods()['POST']:
                raise HandlerError("Method '%s' on service '%s' unknown" % (method_name, service_name), 404)

            guids = self.get_arguments(request, 'guid')
            if not len(guids):
                raise HandlerError("User not authorized", 401)

            authorizations = yield Authz(
                uuid=guids,
                client_name=self.get_client_name(request),
                service_name=self.decode_client_servicename(service_name, request),
            ).get_token(self.application.db)

            if len(authorizations) > 1:
                raise HandlerError('Too many GUIDs', 401)

            elif len(authorizations) != 1:
                raise HandlerError('User not authorized', 401)

            ret = None
            try:
                ret = yield getattr(service, method_name)(
                    authorization=authorizations[0],
                    arguments=self.arguments(request),
                )
            except LightningError as exc:
                raise HandlerError(exc.error_msg, exc.code)

            if ret:
                self.write(request, ret)
            else:
                self.write(request, {'success': None})
            self.finish(request)
        except HandlerError as exc:
            self.write(request, error_format(exc.message), exc.code)
            self.finish(request)
        except Exception as exc:
            self.write_error(request, exc)
            self.finish(request)
Beispiel #28
0
    def test_get_view_no_guid(self):
        yield self.post_and_verify(
            path="/view",
            args=json.dumps(
                dict(
                    name="foo",
                    definition=[
                        {"service": "loopback", "method": "num_foo"},
                        {"service": "loopback", "method": "random"},
                    ],
                )
            ),
            response_code=200,
            result={"success": "View 'foo' created"},
        )

        yield self.get_and_verify(
            path="/view/foo/invoke", response_code=401, result=error_format("User not authorized")
        )
Beispiel #29
0
    def show_auth(self, request):
        try:
            guid = self.name
            authz = yield Authz(uuid=guid).get_token(self.application.db)
            if not authz:
                raise HandlerError("guid '%s' not found" % guid, 404)

            self.write(
                request,
                {
                    "service_name": authz.service_name,
                    "user_id": authz.user_id,
                    "account_created_timestamp": authz.account_created_timestamp,
                    "guid": guid,
                },
            )
            self.finish(request)
        except HandlerError as exc:
            self.write(request, error_format(exc.message), exc.code)
            self.finish(request)
Beispiel #30
0
    def render_GET(self, request):
        "Handle get requests"

        try:
            service_name = self.service_name
            try:
                service = self.get_service(service_name, request)
            except KeyError:
                raise HandlerError("Service '%s' unknown" % service_name, 404)

            methods = service.methods() or []
            self.write(request, {'methods': methods})

        except HandlerError as exc:
            self.write(request, error_format(exc.message), exc.code)
        except Exception as exc:
            self.write_error(request, exc)


        return ""