diff --git a/budget/api.py b/budget/api.py index ddaf65c..3df8ab2 100644 --- a/budget/api.py +++ b/budget/api.py @@ -2,6 +2,7 @@ from flask import * from models import db, Project, Person, Bill +from forms import ProjectForm from utils import for_all_methods from rest import RESTResource, need_auth# FIXME make it an ext @@ -21,7 +22,7 @@ def check_project(*args, **kwargs): if auth and "project_id" in kwargs and \ auth.username == kwargs["project_id"]: project = Project.query.get(auth.username) - if project.password == auth.password: + if project and project.password == auth.password: return project return False @@ -29,7 +30,13 @@ def check_project(*args, **kwargs): class ProjectHandler(object): def add(self): - pass + form = ProjectForm(csrf_enabled=False) + if form.validate(): + project = form.save(Project()) + db.session.add(project) + db.session.commit() + return 201, project.id + return 400, form.errors @need_auth(check_project, "project") def get(self, project): @@ -37,11 +44,18 @@ class ProjectHandler(object): @need_auth(check_project, "project") def delete(self, project): - return "delete" + db.session.delete(project) + db.session.commit() + return 200, "DELETED" @need_auth(check_project, "project") def update(self, project): - return "update" + form = ProjectForm(csrf_enabled=False) + if form.validate(): + form.save(project) + db.session.commit() + return 200, "UPDATED" + return 400, form.errors class MemberHandler(object): @@ -49,23 +63,34 @@ class MemberHandler(object): def get(self, project, member_id): member = Person.query.get(member_id) if not member or member.project != project: - return Response('Not Found', status=404) + return 404, "Not Found" return member def list(self, project): return project.members def add(self, project): - pass + form = MemberForm(csrf_enabled=False) + if form.validate(): + member = Person() + form.save(project, member) + db.session.commit() + return 200, member.id + return 400, form.errors def update(self, project, member_id): - pass + form = MemberForm(csrf_enabled=False) + if form.validate(): + member = Person.query.get(member_id, project) + form.save(project, member) + db.session.commit() + return 200, member + return 400, form.errors def delete(self, project, member_id): if project.remove_member(member_id): - return Response('OK', status=200) - else: - return Response('Not Found', status=404) + return 200, "OK" + return 404, "Not Found" class BillHandler(object): @@ -73,22 +98,34 @@ class BillHandler(object): def get(self, project, bill_id): bill = Bill.query.get(project, bill_id) if not bill: - return Response('Not Found', status=404) + return 404, "Not Found" return bill def list(self, project): return project.get_bills().all() def add(self, project): - pass + form = BillForm(csrf_enabled=False) + if form.validate(): + bill = Bill() + form.save(bill) + db.session.add(bill) + db.session.commit() + return 200, bill.id + return 400, form.errors def update(self, project, bill_id): - pass + form = BillForm(csrf_enabled=False) + if form.validate(): + form.save(bill) + db.session.commit() + return 200, bill.id + return 400, form.errors def delete(self, project, bill_id): bill = Bill.query.delete(project, bill_id) if not bill: - return Response('Not Found', status=404) + return 404, "Not Found" return bill diff --git a/budget/forms.py b/budget/forms.py index 7ac48cc..cfd5788 100644 --- a/budget/forms.py +++ b/budget/forms.py @@ -1,6 +1,6 @@ from flaskext.wtf import * from wtforms.widgets import html_params -from models import Project, Person, Bill +from models import Project, Person, Bill, db from datetime import datetime @@ -39,6 +39,15 @@ class ProjectForm(Form): contact_email=self.contact_email.data) return project + def update(self, project): + """Update the project with the information from the form""" + project.name = self.name.data + project.id = self.id.data + project.password = self.password.data + project.contact_email = self.contact_email.data + + return project + class AuthenticationForm(Form): id = TextField("Project identifier", validators=[Required()]) @@ -76,19 +85,26 @@ class BillForm(Form): class MemberForm(Form): - def __init__(self, project, *args, **kwargs): - super(MemberForm, self).__init__(*args, **kwargs) - self.project = project name = TextField("Name", validators=[Required()]) submit = SubmitField("Add a member") + def __init__(self, project, *args, **kwargs): + super(MemberForm, self).__init__(*args, **kwargs) + self.project = project + def validate_name(form, field): if Person.query.filter(Person.name == field.data)\ .filter(Person.project == form.project)\ .filter(Person.activated == True).all(): raise ValidationError("This project already have this member") + def save(self, project, person): + # if the user is already bound to the project, just reactivate him + person.name = self.name.data + person.project = project + + return person class InviteForm(Form): emails = TextAreaField("People to notify") diff --git a/budget/models.py b/budget/models.py index e56ae4e..5ee7b07 100644 --- a/budget/models.py +++ b/budget/models.py @@ -1,7 +1,8 @@ from collections import defaultdict from datetime import datetime -from flaskext.sqlalchemy import SQLAlchemy +from flaskext.sqlalchemy import SQLAlchemy, BaseQuery +from flask import g from sqlalchemy import orm @@ -75,6 +76,20 @@ class Project(db.Model): class Person(db.Model): + class PersonQuery(BaseQuery): + def get_by_name(self, name, project): + return Person.query.filter(Person.name == name)\ + .filter(Project.id == project.id).one() + + def get(self, id, project=None): + if not project: + project = g.project + return Person.query.filter(Person.id == id)\ + .filter(Project.id == project.id).one() + + + query_class = PersonQuery + _to_serialize = ("id", "name", "activated") id = db.Column(db.Integer, primary_key=True) @@ -106,7 +121,7 @@ billowers = db.Table('billowers', class Bill(db.Model): - class BillQuery(orm.query.Query): + class BillQuery(BaseQuery): def get(self, project, id): try: diff --git a/budget/rest.py b/budget/rest.py index 8ade14b..f237217 100644 --- a/budget/rest.py +++ b/budget/rest.py @@ -114,7 +114,7 @@ def need_auth(authentifier, name=None, remove_attr=True): del kwargs["%s_id" % name] return func(*args, **kwargs) else: - raise werkzeug.exceptions.Forbidden() + return 403, "Forbidden" return wrapped return wrapper @@ -128,13 +128,15 @@ def serialize(func): # get the mimetype mime = request.accept_mimetypes.best_match(SERIALIZERS.keys()) data = func(*args, **kwargs) + serializer = SERIALIZERS[mime] - if isinstance(data, werkzeug.Response): - return data - else: - # serialize it - return werkzeug.Response(SERIALIZERS[mime].encode(data), - status=200, mimetype=mime) + status = 200 + if len(data) == 2: + status, data = data + + # serialize it + return werkzeug.Response(serializer.encode(data), + status=status, mimetype=mime) return wrapped diff --git a/budget/web.py b/budget/web.py index 61d67e5..5667b05 100644 --- a/budget/web.py +++ b/budget/web.py @@ -188,18 +188,11 @@ def add_member(): form = MemberForm(g.project) if request.method == "POST": if form.validate(): - # if the user is already bound to the project, just reactivate him - person = Person.query.filter(Person.name == form.name.data)\ - .filter(Project.id == g.project.id).all() - if person: - person[0].activated = True - db.session.commit() - flash("%s is part of this project again" % person[0].name) - return redirect(url_for(".list_bills")) - - db.session.add(Person(name=form.name.data, project=g.project)) + member = form.save(g.project, Person()) db.session.commit() + flash("%s is had been added" % member.name) return redirect(url_for(".list_bills")) + return render_template("add_member.html", form=form) @main.route("//members//reactivate", methods=["GET",])