zcash-grant-system/backend/grant/proposal/views.py

216 lines
6.9 KiB
Python
Raw Normal View History

from dateutil.parser import parse
2018-11-07 11:19:12 -08:00
from functools import wraps
2018-09-10 09:55:26 -07:00
2018-11-07 11:19:12 -08:00
from flask import Blueprint, g
2018-10-22 15:31:33 -07:00
from flask_yoloapi import endpoint, parameter
2018-09-10 09:55:26 -07:00
from sqlalchemy.exc import IntegrityError
from grant.comment.models import Comment, comment_schema
2018-09-10 09:55:26 -07:00
from grant.milestone.models import Milestone
from grant.user.models import User, SocialMedia, Avatar
2018-11-07 11:19:12 -08:00
from grant.utils.auth import requires_sm, requires_team_member_auth
2018-11-13 08:07:09 -08:00
from grant.utils.exceptions import ValidationException
from .models import Proposal, proposals_schema, proposal_schema, ProposalUpdate, proposal_update_schema, proposal_team, db
2018-09-10 09:55:26 -07:00
2018-09-18 15:20:17 -07:00
blueprint = Blueprint("proposal", __name__, url_prefix="/api/v1/proposals")
2018-09-10 09:55:26 -07:00
@blueprint.route("/<proposal_id>", methods=["GET"])
@endpoint.api()
2018-09-10 09:55:26 -07:00
def get_proposal(proposal_id):
proposal = Proposal.query.filter_by(id=proposal_id).first()
2018-09-10 09:55:26 -07:00
if proposal:
dumped_proposal = proposal_schema.dump(proposal)
return dumped_proposal
2018-09-10 09:55:26 -07:00
else:
return {"message": "No proposal matching id"}, 404
2018-09-10 09:55:26 -07:00
@blueprint.route("/<proposal_id>/comments", methods=["GET"])
@endpoint.api()
2018-09-10 09:55:26 -07:00
def get_proposal_comments(proposal_id):
proposal = Proposal.query.filter_by(id=proposal_id).first()
if proposal:
dumped_proposal = proposal_schema.dump(proposal)
return {
"proposalId": proposal_id,
"totalComments": len(dumped_proposal["comments"]),
"comments": dumped_proposal["comments"]
}
2018-09-10 09:55:26 -07:00
else:
return {"message": "No proposal matching id"}, 404
2018-09-10 09:55:26 -07:00
@blueprint.route("/<proposal_id>/comments", methods=["POST"])
2018-11-07 11:19:12 -08:00
@requires_sm
2018-10-22 15:31:33 -07:00
@endpoint.api(
parameter('content', type=str, required=True)
)
def post_proposal_comments(proposal_id, user_id, content):
proposal = Proposal.query.filter_by(id=proposal_id).first()
if proposal:
2018-11-07 11:19:12 -08:00
comment = Comment(
proposal_id=proposal_id,
user_id=g.current_user.id,
content=content
)
db.session.add(comment)
db.session.commit()
dumped_comment = comment_schema.dump(comment)
return dumped_comment, 201
else:
2018-10-22 15:31:33 -07:00
return {"message": "No proposal matching id"}, 404
2018-09-10 09:55:26 -07:00
@blueprint.route("/", methods=["GET"])
2018-10-22 15:31:33 -07:00
@endpoint.api(
parameter('stage', type=str, required=False)
)
def get_proposals(stage):
2018-09-10 09:55:26 -07:00
if stage:
proposals = (
2018-11-13 08:07:09 -08:00
Proposal.query.filter_by(status="LIVE", stage=stage)
.order_by(Proposal.date_created.desc())
.all()
2018-09-10 09:55:26 -07:00
)
else:
proposals = Proposal.query.order_by(Proposal.date_created.desc()).all()
dumped_proposals = proposals_schema.dump(proposals)
2018-10-22 15:31:33 -07:00
return dumped_proposals
2018-09-10 09:55:26 -07:00
2018-11-13 08:07:09 -08:00
@blueprint.route("/drafts", methods=["POST"])
@requires_sm
@endpoint.api()
def make_proposal_draft():
proposal = Proposal.create(status="DRAFT")
proposal.team.append(g.current_user)
db.session.add(proposal)
db.session.commit()
return proposal_schema.dump(proposal), 201
2018-09-10 09:55:26 -07:00
2018-11-13 08:07:09 -08:00
@blueprint.route("/drafts", methods=["GET"])
2018-11-07 11:19:12 -08:00
@requires_sm
2018-11-13 08:07:09 -08:00
@endpoint.api()
def get_proposal_drafts():
proposals = (
Proposal.query
.filter_by(status="DRAFT")
.join(proposal_team)
.filter(proposal_team.c.user_id == g.current_user.id)
.order_by(Proposal.date_created.desc())
.all()
2018-09-10 09:55:26 -07:00
)
2018-11-13 08:07:09 -08:00
return proposals_schema.dump(proposals), 200
2018-09-10 09:55:26 -07:00
2018-11-13 08:07:09 -08:00
@blueprint.route("/<proposal_id>", methods=["PUT"])
@requires_team_member_auth
@endpoint.api(
parameter('title', type=str),
parameter('brief', type=str),
parameter('category', type=str),
2018-11-14 09:27:40 -08:00
parameter('content', type=str),
2018-11-13 08:07:09 -08:00
parameter('target', type=str),
parameter('payoutAddress', type=str),
parameter('trustees', type=list),
parameter('deadlineDuration', type=int),
parameter('voteDuration', type=int),
parameter('milestones', type=list)
)
def update_proposal(milestones, proposal_id, **kwargs):
2018-11-13 08:07:09 -08:00
# Update the base proposal fields
try:
g.current_proposal.update(**kwargs)
2018-11-13 08:07:09 -08:00
except ValidationException as e:
return {"message": "Invalid proposal parameters: {}".format(str(e))}, 400
db.session.add(g.current_proposal)
2018-09-26 01:46:30 -07:00
2018-11-13 08:07:09 -08:00
# Delete & re-add milestones
[db.session.delete(x) for x in g.current_proposal.milestones]
2018-11-13 08:07:09 -08:00
if milestones:
for mdata in milestones:
m = Milestone(
title=mdata["title"],
content=mdata["content"],
date_estimated=parse(mdata["dateEstimated"]),
2018-11-13 08:07:09 -08:00
payout_percent=str(mdata["payoutPercent"]),
immediate_payout=mdata["immediatePayout"],
proposal_id=g.current_proposal.id
)
2018-11-13 08:07:09 -08:00
db.session.add(m)
# Commit
db.session.commit()
return proposal_schema.dump(g.current_proposal), 200
2018-09-10 09:55:26 -07:00
@blueprint.route("/<proposal_id>", methods=["DELETE"])
2018-11-13 08:07:09 -08:00
@requires_team_member_auth
@endpoint.api()
2018-11-15 08:02:16 -08:00
def delete_proposal_draft(proposal_id):
2018-11-13 08:07:09 -08:00
if g.current_proposal.status != 'DRAFT':
return {"message": "Cannot delete non-draft proposals"}, 400
db.session.delete(g.current_proposal)
db.session.commit()
return None, 202
2018-09-26 01:46:30 -07:00
2018-11-13 08:07:09 -08:00
@blueprint.route("/<proposal_id>/publish", methods=["PUT"])
@requires_team_member_auth
@endpoint.api(
parameter('contractAddress', type=str, required=True)
)
2018-11-14 14:03:50 -08:00
def publish_proposal(proposal_id, contract_address):
2018-09-10 09:55:26 -07:00
try:
2018-11-13 08:07:09 -08:00
g.current_proposal.proposal_address = contract_address
g.current_proposal.publish()
except ValidationException as e:
return {"message": "Invalid proposal parameters: {}".format(str(e))}, 400
db.session.add(g.current_proposal)
db.session.commit()
return proposal_schema.dump(g.current_proposal), 200
@blueprint.route("/<proposal_id>/updates", methods=["GET"])
@endpoint.api()
def get_proposal_updates(proposal_id):
proposal = Proposal.query.filter_by(id=proposal_id).first()
if proposal:
dumped_proposal = proposal_schema.dump(proposal)
return dumped_proposal["updates"]
else:
return {"message": "No proposal matching id"}, 404
@blueprint.route("/<proposal_id>/updates/<update_id>", methods=["GET"])
@endpoint.api()
def get_proposal_update(proposal_id, update_id):
proposal = Proposal.query.filter_by(id=proposal_id).first()
if proposal:
update = ProposalUpdate.query.filter_by(proposal_id=proposal.id, id=update_id).first()
if update:
return update
else:
return {"message": "No update matching id"}
else:
return {"message": "No proposal matching id"}, 404
@blueprint.route("/<proposal_id>/updates", methods=["POST"])
2018-11-07 11:19:12 -08:00
@requires_team_member_auth
@requires_sm
@endpoint.api(
parameter('title', type=str, required=True),
parameter('content', type=str, required=True)
)
def post_proposal_update(proposal_id, title, content):
2018-11-07 11:19:12 -08:00
update = ProposalUpdate(
proposal_id=g.current_proposal.id,
title=title,
content=content
)
db.session.add(update)
db.session.commit()
2018-11-07 11:19:12 -08:00
dumped_update = proposal_update_schema.dump(update)
return dumped_update, 201