コード例 #1
0
ファイル: api.py プロジェクト: vtbassmatt/TripSplitter
    def get(self, trip_key):

        errors = []
        output = ""
        user = users.get_current_user()
        authz = Authz(user)
        self.response.headers["Content-type"] = "application/json"

        try:
            # get the trip
            trip = Trip.get(trip_key)

            # verify the user is authorized to read the trip
            authz.readTrip(trip)

            # format trip data
            output = GqlEncoder().encode(trip)

        except db.BadKeyError:
            errors.append({"message": "Invalid trip key"})
        except PermissionError:
            errors.append(
                {"message": "You are not authorized to view that trip"})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error loading trip"})

        if len(errors) > 0:
            output = json.dumps({"error": errors})

        self.response.out.write(output)
コード例 #2
0
ファイル: api.py プロジェクト: vtbassmatt/TripSplitter
    def get(self, trip_key):

        errors = []
        output = ""
        user = users.get_current_user()
        authz = Authz(user)
        self.response.headers["Content-type"] = "application/json"

        try:
            # get the trip
            trip = Trip.get(trip_key)

            # verify the user is authorized to read the trip
            authz.readTrip(trip)

            # format trip data
            output = GqlEncoder().encode(trip)

        except db.BadKeyError:
            errors.append({"message": "Invalid trip key"})
        except PermissionError:
            errors.append({"message": "You are not authorized to view that trip"})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error loading trip"})

        if len(errors) > 0:
            output = json.dumps({"error": errors})

        self.response.out.write(output)
コード例 #3
0
ファイル: scaffold.py プロジェクト: vtbassmatt/TripSplitter
    def _expenseScaffold(self, trip_key):
        if trip_key == '':
            return "Pass in a trip key like this:  /expense<u>$tripkey</u>"

        trip = Trip.get(trip_key)

        return self._expenseScaffoldInternal(trip)
コード例 #4
0
ファイル: api.py プロジェクト: vtbassmatt/TripSplitter
    def get(self, trip_key, expense_key):

        errors = []
        output = ""
        user = users.get_current_user()
        authz = Authz(user)
        self.response.headers["Content-type"] = "application/json"

        # first, verify they have access to the trip
        try:
            # get the trip
            trip = Trip.get(trip_key)

            # verify the user is authorized to read the trip
            authz.readTrip(trip)

        except PermissionError:
            errors.append(
                {"message": "You are not authorized to view that trip"})
        except db.BadKeyError:
            errors.append({"message": "Invalid trip key"})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error loading trip"})

        # if errors encountered so far, bail
        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})
            self.response.out.write(output)
            return

        # this is a read of an existing expense
        # instead of directly authorizing the read of an expense, we
        # ensure that the expense is tied to the specified trip
        try:
            # get the expense
            expense = Expense.get(expense_key)

            # ensure the expense belongs to the trip
            if expense.parent_key() != trip.key():
                raise PermissionError("Expense is not tied to that trip")

            # format expense data
            output = GqlEncoder().encode(expense)

        except db.BadKeyError:
            errors.append({"message": "Invalid expense key"})
        except PermissionError as e:
            errors.append({"message": e.args})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error loading expense"})

        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})

        self.response.out.write(output)
コード例 #5
0
ファイル: api.py プロジェクト: vtbassmatt/TripSplitter
    def get(self, trip_key, expense_key):

        errors = []
        output = ""
        user = users.get_current_user()
        authz = Authz(user)
        self.response.headers["Content-type"] = "application/json"

        # first, verify they have access to the trip
        try:
            # get the trip
            trip = Trip.get(trip_key)

            # verify the user is authorized to read the trip
            authz.readTrip(trip)

        except PermissionError:
            errors.append({"message": "You are not authorized to view that trip"})
        except db.BadKeyError:
            errors.append({"message": "Invalid trip key"})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error loading trip"})

        # if errors encountered so far, bail
        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})
            self.response.out.write(output)
            return

        # this is a read of an existing expense
        # instead of directly authorizing the read of an expense, we
        # ensure that the expense is tied to the specified trip
        try:
            # get the expense
            expense = Expense.get(expense_key)

            # ensure the expense belongs to the trip
            if expense.parent_key() != trip.key():
                raise PermissionError("Expense is not tied to that trip")

            # format expense data
            output = GqlEncoder().encode(expense)

        except db.BadKeyError:
            errors.append({"message": "Invalid expense key"})
        except PermissionError as e:
            errors.append({"message": e.args})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error loading expense"})

        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})

        self.response.out.write(output)
コード例 #6
0
    def deleteTrip(self, trip):
        """Determines whether the user is allowed to delete a particular trip
        
        trip can be a trip key or a trip object"""
        if isinstance(trip, Trip):
            pass
        else:
            trip = Trip.get(trip)

        # logic determining whether the user can delete the trip
        if self.user == trip.owner:
            return

        raise PermissionError('User not allowed to delete this trip')
コード例 #7
0
ファイル: authz.py プロジェクト: vtbassmatt/TripSplitter
 def deleteTrip(self, trip):
     """Determines whether the user is allowed to delete a particular trip
     
     trip can be a trip key or a trip object"""
     if isinstance(trip, Trip):
         pass
     else:
         trip = Trip.get(trip)
     
     # logic determining whether the user can delete the trip
     if self.user == trip.owner:
         return
     
     raise PermissionError('User not allowed to delete this trip')
コード例 #8
0
ファイル: api.py プロジェクト: vtbassmatt/TripSplitter
    def get(self, trip_key):

        errors = []
        output = ""
        user = users.get_current_user()
        authz = Authz(user)
        self.response.headers["Content-type"] = "application/json"

        # verify access to the trip
        try:
            # get the trip
            trip = Trip.get(trip_key)

            # verify the user is authorized to read the trip
            authz.readTrip(trip)

        except PermissionError:
            errors.append(
                {"message": "You are not authorized to view that trip"})
        except db.BadKeyError:
            errors.append({"message": "Invalid trip key"})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error loading trip"})

        # if errors encountered so far, bail
        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})
            self.response.out.write(output)
            return

        # next, get the list of expenses
        try:
            expenses = Expense.all()
            expenses.ancestor(trip)
            output = GqlEncoder().encode(expenses.fetch(limit=200))
        except db.BadKeyError:
            errors.append({"message": "Invalid trip key"})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error listing expenses"})

        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"errors": errors})

        self.response.headers["Content-type"] = "application/json"
        self.response.out.write(output)
コード例 #9
0
ファイル: api.py プロジェクト: vtbassmatt/TripSplitter
    def get(self, trip_key):

        errors = []
        output = ""
        user = users.get_current_user()
        authz = Authz(user)
        self.response.headers["Content-type"] = "application/json"

        # verify access to the trip
        try:
            # get the trip
            trip = Trip.get(trip_key)

            # verify the user is authorized to read the trip
            authz.readTrip(trip)

        except PermissionError:
            errors.append({"message": "You are not authorized to view that trip"})
        except db.BadKeyError:
            errors.append({"message": "Invalid trip key"})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error loading trip"})

        # if errors encountered so far, bail
        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})
            self.response.out.write(output)
            return

        # next, get the list of expenses
        try:
            expenses = Expense.all()
            expenses.ancestor(trip)
            output = GqlEncoder().encode(expenses.fetch(limit=200))
        except db.BadKeyError:
            errors.append({"message": "Invalid trip key"})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error listing expenses"})

        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"errors": errors})

        self.response.headers["Content-type"] = "application/json"
        self.response.out.write(output)
コード例 #10
0
ファイル: api.py プロジェクト: vtbassmatt/TripSplitter
    def delete(self, trip_key):

        errors = []
        output = ""
        user = users.get_current_user()
        authz = Authz(user)
        self.response.headers["Content-type"] = "application/json"

        try:
            # get the trip
            trip = Trip.get(trip_key)

            # verify the user is authorized to delete the trip
            authz.deleteTrip(trip)

            # delete related expenses
            try:
                expenses = Expense.all()
                expenses.ancestor(trip)
                expenses.fetch(limit=200)
                db.delete(expenses)
            except Exception as e:
                logging.exception(e)
                errors.append({
                    "message":
                    "Unexpected error deleting associated expenses"
                })

            # delete the trip
            trip.delete()

        except db.BadKeyError:
            errors.append({"message": "Invalid trip key"})
        except PermissionError:
            errors.append(
                {"message": "You are not authorized to delete that trip"})
        except db.NotSavedError:
            errors.append({"message": "Unable to delete trip"})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error deleting trip"})

        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})

        self.response.out.write(output)
コード例 #11
0
ファイル: api.py プロジェクト: vtbassmatt/TripSplitter
    def delete(self, trip_key):

        errors = []
        output = ""
        user = users.get_current_user()
        authz = Authz(user)
        self.response.headers["Content-type"] = "application/json"

        try:
            # get the trip
            trip = Trip.get(trip_key)

            # verify the user is authorized to delete the trip
            authz.deleteTrip(trip)

            # delete related expenses
            try:
                expenses = Expense.all()
                expenses.ancestor(trip)
                expenses.fetch(limit=200)
                db.delete(expenses)
            except Exception as e:
                logging.exception(e)
                errors.append({"message": "Unexpected error deleting associated expenses"})

            # delete the trip
            trip.delete()

        except db.BadKeyError:
            errors.append({"message": "Invalid trip key"})
        except PermissionError:
            errors.append({"message": "You are not authorized to delete that trip"})
        except db.NotSavedError:
            errors.append({"message": "Unable to delete trip"})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error deleting trip"})

        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})

        self.response.out.write(output)
コード例 #12
0
    def updateTrip(self, trip):
        """Determines whether the user is allowed to update a particular trip
        
        trip can be a trip key or a trip object"""
        if isinstance(trip, Trip):
            pass
        else:
            trip = Trip.get(trip)

        # logic determining whether the user can update the trip
        # if the user is the owner, OK
        if self.user == trip.owner:
            return
        # if there is a TripAccess object, OK
        tripaccess_query = TripAccess.all()
        tripaccess_query.filter('user = '******'trip = ', trip)
        tripaccess = tripaccess_query.fetch(limit=10)
        if len(tripaccess) > 0:
            return

        raise PermissionError('User not allowed to update this trip')
コード例 #13
0
ファイル: authz.py プロジェクト: vtbassmatt/TripSplitter
 def updateTrip(self, trip):
     """Determines whether the user is allowed to update a particular trip
     
     trip can be a trip key or a trip object"""
     if isinstance(trip, Trip):
         pass
     else:
         trip = Trip.get(trip)
     
     # logic determining whether the user can update the trip
     # if the user is the owner, OK
     if self.user == trip.owner:
         return
     # if there is a TripAccess object, OK
     tripaccess_query = TripAccess.all()
     tripaccess_query.filter('user = '******'trip = ', trip)
     tripaccess = tripaccess_query.fetch(limit=10)
     if len(tripaccess) > 0:
         return
     
     raise PermissionError('User not allowed to update this trip')
コード例 #14
0
ファイル: authz.py プロジェクト: vtbassmatt/TripSplitter
    def deleteExpense(self, expense):
        """Determines whether the user is allowed to delete an expense"""
        if isinstance(expense, Expense):
            pass
        else:
            expense = Expense.get(expense)
        
        # determine if the user owns the related trip
        try:
            trip = Trip.get(expense.parent_key())
        except db.BadKeyError:
            raise PermissionError('User cannot delete this expense because the trip could not be loaded')
        
        # if yes, they are allowed to delete the expense
        if self.user == trip.owner:
            return
        
        # if they own the expense itself, then they can delete it
        if self.user == expense.creator:
            return

        raise PermissionError('User cannot delete this expense')
コード例 #15
0
    def deleteExpense(self, expense):
        """Determines whether the user is allowed to delete an expense"""
        if isinstance(expense, Expense):
            pass
        else:
            expense = Expense.get(expense)

        # determine if the user owns the related trip
        try:
            trip = Trip.get(expense.parent_key())
        except db.BadKeyError:
            raise PermissionError(
                'User cannot delete this expense because the trip could not be loaded'
            )

        # if yes, they are allowed to delete the expense
        if self.user == trip.owner:
            return

        # if they own the expense itself, then they can delete it
        if self.user == expense.creator:
            return

        raise PermissionError('User cannot delete this expense')
コード例 #16
0
ファイル: api.py プロジェクト: vtbassmatt/TripSplitter
    def put(self, trip_key):

        errors = []
        output = ""
        user = users.get_current_user()
        authz = Authz(user)
        self.response.headers["Content-type"] = "application/json"

        try:
            # get the trip
            trip = Trip.get(trip_key)

            # verify the user is authorized to update the trip
            authz.updateTrip(trip)

        except db.BadKeyError:
            errors.append({"message": "Invalid trip key"})
        except PermissionError:
            errors.append(
                {"message": "You are not authorized to view that trip"})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error loading trip"})

        # bail if we hit authz errors
        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})
            self.response.out.write(output)
            return

        # now that we know the user is authorized, perform the update
        logging.debug(self.request.body)
        try:
            data = TripUnpacker().unpack_put(self.request)
            logging.debug(data)

            properties = ('name', 'password', 'start_date', 'end_date',
                          'travelers')
            for prop in properties:
                if prop in data:
                    # TODO: validate the data (for instance, dates will almost
                    #       certainly fail without some scrubbing)
                    scrubbed = self._scrub(prop, data[prop])
                    setattr(trip, prop, scrubbed)

            trip.put()

            # per the Backbone documentation, this method needs to:
            #   "[w]hen returning a JSON response, send down the attributes of
            #   the model that have been changed by the server, and need to be
            #   updated on the client"
            # Dates need to be shown because their formatting can change
            output = GqlEncoder().encode({
                'modify_date': trip.modify_date,
                'start_date': trip.start_date,
                'end_date': trip.end_date,
            })

        except NotImplementedError as e:
            errors.append({"message": e.args})
        except db.BadValueError as e:
            errors.append({"message": e.args})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error updating trip"})

        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})

        self.response.out.write(output)
コード例 #17
0
ファイル: api.py プロジェクト: vtbassmatt/TripSplitter
    def post(self, trip_key):
        errors = []
        output = ""
        user = users.get_current_user()
        authz = Authz(user)
        self.response.headers["Content-type"] = "application/json"

        # check for authorization to create expenses for this trip & verify this
        # is in fact a request to create a new expense
        try:
            # get the trip
            trip = Trip.get(trip_key)

            # verify the user is authorized to create an expense on this trip
            authz.createExpense(trip)

        except PermissionError as e:
            # this permission error could have come from authz or locally
            errors.append({"message": e.args})
        except db.BadKeyError:
            errors.append({"message": "Invalid trip key"})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error loading trip"})

        # bail if we hit authz errors
        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})
            self.response.out.write(output)
            return

        # having passed authz, let's try creating the expense
        data = ExpenseUnpacker().unpack_post(self.request)

        if data["description"] == "" or data["value"] == "" or data["payer"] == "":
            errors.append({"message": "Description, value, and payer are required."})
        elif len(data["travelers"]) == 0:
            errors.append({"message": "At least one person must be specified as a traveler."})
        else:
            try:
                expense = Expense(
                    parent=trip.key(),
                    creator=user,
                    description=data["description"],
                    value=int(data["value"]),
                    currency="USD",
                )

                # get the expense date
                expense_date = dateparse(data["expense_date"])
                expense.expense_date = expense_date.date()

                # TODO: make sure these travelers are actually on the trip
                expense.travelers = data["travelers"]

                # TODO: ensure the payer is actually a traveler
                expense.payer = data["payer"]

                expense.put()

                output = GqlEncoder().encode(
                    {
                        "id": "%s" % expense.key(),
                        "modify_date": expense.modify_date,
                        "expense_date": expense.expense_date,
                        "value": expense.value,
                    }
                )
            except Exception as e:
                logging.exception(e)
                errors.append({"message": "Unexpected error creating expense"})

        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})

        self.response.out.write(output)
コード例 #18
0
ファイル: api.py プロジェクト: vtbassmatt/TripSplitter
    def put(self, trip_key):

        errors = []
        output = ""
        user = users.get_current_user()
        authz = Authz(user)
        self.response.headers["Content-type"] = "application/json"

        try:
            # get the trip
            trip = Trip.get(trip_key)

            # verify the user is authorized to update the trip
            authz.updateTrip(trip)

        except db.BadKeyError:
            errors.append({"message": "Invalid trip key"})
        except PermissionError:
            errors.append({"message": "You are not authorized to view that trip"})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error loading trip"})

        # bail if we hit authz errors
        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})
            self.response.out.write(output)
            return

        # now that we know the user is authorized, perform the update
        logging.debug(self.request.body)
        try:
            data = TripUnpacker().unpack_put(self.request)
            logging.debug(data)

            properties = ("name", "password", "start_date", "end_date", "travelers")
            for prop in properties:
                if prop in data:
                    # TODO: validate the data (for instance, dates will almost
                    #       certainly fail without some scrubbing)
                    scrubbed = self._scrub(prop, data[prop])
                    setattr(trip, prop, scrubbed)

            trip.put()

            # per the Backbone documentation, this method needs to:
            #   "[w]hen returning a JSON response, send down the attributes of
            #   the model that have been changed by the server, and need to be
            #   updated on the client"
            # Dates need to be shown because their formatting can change
            output = GqlEncoder().encode(
                {"modify_date": trip.modify_date, "start_date": trip.start_date, "end_date": trip.end_date}
            )

        except NotImplementedError as e:
            errors.append({"message": e.args})
        except db.BadValueError as e:
            errors.append({"message": e.args})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error updating trip"})

        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})

        self.response.out.write(output)
コード例 #19
0
ファイル: api.py プロジェクト: vtbassmatt/TripSplitter
    def post(self, trip_key):
        errors = []
        output = ""
        user = users.get_current_user()
        authz = Authz(user)
        self.response.headers["Content-type"] = "application/json"

        # check for authorization to create expenses for this trip & verify this
        # is in fact a request to create a new expense
        try:
            # get the trip
            trip = Trip.get(trip_key)

            # verify the user is authorized to create an expense on this trip
            authz.createExpense(trip)

        except PermissionError as e:
            # this permission error could have come from authz or locally
            errors.append({"message": e.args})
        except db.BadKeyError:
            errors.append({"message": "Invalid trip key"})
        except Exception as e:
            logging.exception(e)
            errors.append({"message": "Unexpected error loading trip"})

        # bail if we hit authz errors
        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})
            self.response.out.write(output)
            return

        # having passed authz, let's try creating the expense
        data = ExpenseUnpacker().unpack_post(self.request)

        if data['description'] == "" or data['value'] == "" or data[
                'payer'] == "":
            errors.append(
                {"message": "Description, value, and payer are required."})
        elif len(data['travelers']) == 0:
            errors.append({
                "message":
                "At least one person must be specified as a traveler."
            })
        else:
            try:
                expense = Expense(
                    parent=trip.key(),
                    creator=user,
                    description=data['description'],
                    value=int(data['value']),
                    currency="USD",
                )

                # get the expense date
                expense_date = dateparse(data['expense_date'])
                expense.expense_date = expense_date.date()

                # TODO: make sure these travelers are actually on the trip
                expense.travelers = data['travelers']

                # TODO: ensure the payer is actually a traveler
                expense.payer = data['payer']

                expense.put()

                output = GqlEncoder().encode({
                    "id": "%s" % expense.key(),
                    'modify_date': expense.modify_date,
                    'expense_date': expense.expense_date,
                    'value': expense.value,
                })
            except Exception as e:
                logging.exception(e)
                errors.append({"message": "Unexpected error creating expense"})

        if len(errors) > 0:
            self.response.set_status(400)
            output = json.dumps({"error": errors})

        self.response.out.write(output)