aboutsummaryrefslogtreecommitdiff
path: root/ihatemoney/api.py
diff options
context:
space:
mode:
Diffstat (limited to 'ihatemoney/api.py')
-rw-r--r--ihatemoney/api.py213
1 files changed, 0 insertions, 213 deletions
diff --git a/ihatemoney/api.py b/ihatemoney/api.py
deleted file mode 100644
index 67c6cc1..0000000
--- a/ihatemoney/api.py
+++ /dev/null
@@ -1,213 +0,0 @@
-# coding: utf8
-from flask import Blueprint, request, current_app
-from flask_restful import Resource, Api, abort
-from flask_cors import CORS
-from wtforms.fields.core import BooleanField
-
-from ihatemoney.models import db, Project, Person, Bill
-from ihatemoney.forms import ProjectForm, EditProjectForm, MemberForm, get_billform_for
-from werkzeug.security import check_password_hash
-from functools import wraps
-
-
-api = Blueprint("api", __name__, url_prefix="/api")
-CORS(api)
-restful_api = Api(api)
-
-
-def need_auth(f):
- """Check the request for basic authentication for a given project.
-
- Return the project if the authorization is good, abort the request with a 401 otherwise
- """
-
- @wraps(f)
- def wrapper(*args, **kwargs):
- auth = request.authorization
- project_id = kwargs.get("project_id")
-
- # Use Basic Auth
- if auth and project_id and auth.username == project_id:
- project = Project.query.get(auth.username)
- if project and check_password_hash(project.password, auth.password):
- # The whole project object will be passed instead of project_id
- kwargs.pop("project_id")
- return f(*args, project=project, **kwargs)
- else:
- # Use Bearer token Auth
- auth_header = request.headers.get("Authorization", "")
- auth_token = ""
- try:
- auth_token = auth_header.split(" ")[1]
- except IndexError:
- abort(401)
- project_id = Project.verify_token(auth_token, token_type="non_timed_token")
- if auth_token and project_id:
- project = Project.query.get(project_id)
- if project:
- kwargs.pop("project_id")
- return f(*args, project=project, **kwargs)
- abort(401)
-
- return wrapper
-
-
-class ProjectsHandler(Resource):
- def post(self):
- form = ProjectForm(meta={"csrf": False})
- if form.validate() and current_app.config.get("ALLOW_PUBLIC_PROJECT_CREATION"):
- project = form.save()
- db.session.add(project)
- db.session.commit()
- return project.id, 201
- return form.errors, 400
-
-
-class ProjectHandler(Resource):
- method_decorators = [need_auth]
-
- def get(self, project):
- return project
-
- def delete(self, project):
- db.session.delete(project)
- db.session.commit()
- return "DELETED"
-
- def put(self, project):
- form = EditProjectForm(meta={"csrf": False})
- if form.validate() and current_app.config.get("ALLOW_PUBLIC_PROJECT_CREATION"):
- form.update(project)
- db.session.commit()
- return "UPDATED"
- return form.errors, 400
-
-
-class ProjectStatsHandler(Resource):
- method_decorators = [need_auth]
-
- def get(self, project):
- return project.members_stats
-
-
-class APIMemberForm(MemberForm):
- """ Member is not disablable via a Form.
-
- But we want Member.enabled to be togglable via the API.
- """
-
- activated = BooleanField(false_values=("false", "", "False"))
-
- def save(self, project, person):
- person.activated = self.activated.data
- return super(APIMemberForm, self).save(project, person)
-
-
-class MembersHandler(Resource):
- method_decorators = [need_auth]
-
- def get(self, project):
- return project.members
-
- def post(self, project):
- form = MemberForm(project, meta={"csrf": False})
- if form.validate():
- member = Person()
- form.save(project, member)
- db.session.commit()
- return member.id, 201
- return form.errors, 400
-
-
-class MemberHandler(Resource):
- method_decorators = [need_auth]
-
- def get(self, project, member_id):
- member = Person.query.get(member_id, project)
- if not member or member.project != project:
- return "Not Found", 404
- return member
-
- def put(self, project, member_id):
- form = APIMemberForm(project, meta={"csrf": False}, edit=True)
- if form.validate():
- member = Person.query.get(member_id, project)
- form.save(project, member)
- db.session.commit()
- return member
- return form.errors, 400
-
- def delete(self, project, member_id):
- if project.remove_member(member_id):
- return "OK"
- return "Not Found", 404
-
-
-class BillsHandler(Resource):
- method_decorators = [need_auth]
-
- def get(self, project):
- return project.get_bills().all()
-
- def post(self, project):
- form = get_billform_for(project, True, meta={"csrf": False})
- if form.validate():
- bill = Bill()
- form.save(bill, project)
- db.session.add(bill)
- db.session.commit()
- return bill.id, 201
- return form.errors, 400
-
-
-class BillHandler(Resource):
- method_decorators = [need_auth]
-
- def get(self, project, bill_id):
- bill = Bill.query.get(project, bill_id)
- if not bill:
- return "Not Found", 404
- return bill, 200
-
- def put(self, project, bill_id):
- form = get_billform_for(project, True, meta={"csrf": False})
- if form.validate():
- bill = Bill.query.get(project, bill_id)
- form.save(bill, project)
- db.session.commit()
- return bill.id, 200
- return form.errors, 400
-
- def delete(self, project, bill_id):
- bill = Bill.query.delete(project, bill_id)
- db.session.commit()
- if not bill:
- return "Not Found", 404
- return "OK", 200
-
-
-class TokenHandler(Resource):
- method_decorators = [need_auth]
-
- def get(self, project):
- if not project:
- return "Not Found", 404
-
- token = project.generate_token()
- return {"token": token}, 200
-
-
-restful_api.add_resource(ProjectsHandler, "/projects")
-restful_api.add_resource(ProjectHandler, "/projects/<string:project_id>")
-restful_api.add_resource(TokenHandler, "/projects/<string:project_id>/token")
-restful_api.add_resource(MembersHandler, "/projects/<string:project_id>/members")
-restful_api.add_resource(
- ProjectStatsHandler, "/projects/<string:project_id>/statistics"
-)
-restful_api.add_resource(
- MemberHandler, "/projects/<string:project_id>/members/<int:member_id>"
-)
-restful_api.add_resource(BillsHandler, "/projects/<string:project_id>/bills")
-restful_api.add_resource(
- BillHandler, "/projects/<string:project_id>/bills/<int:bill_id>"
-)