Merge pull request #298 from grant-project/random-ids

Generate random ID for public facing entities
This commit is contained in:
Daniel Ternyak 2019-03-04 19:45:34 -06:00 committed by GitHub
commit b74fe6ba15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 29 additions and 32 deletions

View File

@ -3,6 +3,7 @@ import datetime
from functools import reduce from functools import reduce
from grant.extensions import ma, db from grant.extensions import ma, db
from grant.utils.ma_fields import UnixDate from grant.utils.ma_fields import UnixDate
from grant.utils.misc import gen_random_id
from sqlalchemy.orm import raiseload from sqlalchemy.orm import raiseload
HIDDEN_CONTENT = '~~comment removed by admin~~' HIDDEN_CONTENT = '~~comment removed by admin~~'
@ -25,6 +26,7 @@ class Comment(db.Model):
replies = db.relationship("Comment") replies = db.relationship("Comment")
def __init__(self, proposal_id, user_id, parent_comment_id, content): def __init__(self, proposal_id, user_id, parent_comment_id, content):
self.id = gen_random_id(Comment)
self.proposal_id = proposal_id self.proposal_id = proposal_id
self.user_id = user_id self.user_id = user_id
self.parent_comment_id = parent_comment_id self.parent_comment_id = parent_comment_id

View File

@ -4,6 +4,7 @@ from grant.extensions import ma, db
from grant.utils.exceptions import ValidationException from grant.utils.exceptions import ValidationException
from grant.utils.ma_fields import UnixDate from grant.utils.ma_fields import UnixDate
from grant.utils.enums import MilestoneStage from grant.utils.enums import MilestoneStage
from grant.utils.misc import gen_random_id
class MilestoneException(Exception): class MilestoneException(Exception):
@ -52,6 +53,7 @@ class Milestone(db.Model):
stage: str = MilestoneStage.IDLE, stage: str = MilestoneStage.IDLE,
proposal_id=int, proposal_id=int,
): ):
self.id = gen_random_id(Milestone)
self.title = title self.title = title
self.content = content self.content = content
self.stage = stage self.stage = stage

View File

@ -9,7 +9,7 @@ from grant.comment.models import Comment
from grant.email.send import send_email from grant.email.send import send_email
from grant.extensions import ma, db from grant.extensions import ma, db
from grant.utils.exceptions import ValidationException from grant.utils.exceptions import ValidationException
from grant.utils.misc import dt_to_unix, make_url from grant.utils.misc import dt_to_unix, make_url, gen_random_id
from grant.utils.requests import blockchain_get from grant.utils.requests import blockchain_get
from grant.settings import PROPOSAL_STAKING_AMOUNT from grant.settings import PROPOSAL_STAKING_AMOUNT
from grant.utils.enums import ( from grant.utils.enums import (
@ -64,6 +64,7 @@ class ProposalUpdate(db.Model):
content = db.Column(db.Text, nullable=False) content = db.Column(db.Text, nullable=False)
def __init__(self, proposal_id: int, title: str, content: str): def __init__(self, proposal_id: int, title: str, content: str):
self.id = gen_random_id(ProposalUpdate)
self.proposal_id = proposal_id self.proposal_id = proposal_id
self.title = title self.title = title
self.content = content self.content = content
@ -93,6 +94,7 @@ class ProposalContribution(db.Model):
user_id: int = None, user_id: int = None,
staking: bool = False, staking: bool = False,
): ):
self.id = gen_random_id(ProposalUpdate)
self.proposal_id = proposal_id self.proposal_id = proposal_id
self.amount = amount self.amount = amount
self.user_id = user_id self.user_id = user_id
@ -180,6 +182,7 @@ class ProposalArbiter(db.Model):
user = db.relationship("User", uselist=False, lazy=True, back_populates="arbiter_proposals") user = db.relationship("User", uselist=False, lazy=True, back_populates="arbiter_proposals")
def __init__(self, proposal_id: int, user_id: int = None, status: str = ProposalArbiterStatus.MISSING): def __init__(self, proposal_id: int, user_id: int = None, status: str = ProposalArbiterStatus.MISSING):
self.id = gen_random_id(ProposalArbiter)
self.proposal_id = proposal_id self.proposal_id = proposal_id
self.user_id = user_id self.user_id = user_id
self.status = status self.status = status
@ -249,6 +252,7 @@ class Proposal(db.Model):
deadline_duration: int = 5184000, # 60 days deadline_duration: int = 5184000, # 60 days
category: str = '' category: str = ''
): ):
self.id = gen_random_id(Proposal)
self.date_created = datetime.datetime.now() self.date_created = datetime.datetime.now()
self.status = status self.status = status
self.title = title self.title = title

View File

@ -1,7 +1,7 @@
from datetime import datetime from datetime import datetime
from grant.extensions import ma, db from grant.extensions import ma, db
from grant.utils.enums import RFPStatus from grant.utils.enums import RFPStatus
from grant.utils.misc import dt_to_unix from grant.utils.misc import dt_to_unix, gen_random_id
from grant.utils.enums import Category from grant.utils.enums import Category
@ -49,6 +49,7 @@ class RFP(db.Model):
): ):
# TODO add status assert # TODO add status assert
assert Category.includes(category) assert Category.includes(category)
self.id = gen_random_id(RFP)
self.date_created = datetime.now() self.date_created = datetime.now()
self.title = title self.title = title
self.brief = brief self.brief = brief

View File

@ -10,7 +10,7 @@ from grant.email.subscription_settings import (
email_subscriptions_to_dict email_subscriptions_to_dict
) )
from grant.extensions import ma, db, security from grant.extensions import ma, db, security
from grant.utils.misc import make_url from grant.utils.misc import make_url, gen_random_id
from grant.utils.social import generate_social_url from grant.utils.social import generate_social_url
from grant.utils.upload import extract_avatar_filename, construct_avatar_url from grant.utils.upload import extract_avatar_filename, construct_avatar_url
from grant.utils import totp_2fa from grant.utils import totp_2fa
@ -96,6 +96,7 @@ class Avatar(db.Model):
self._image_url = extract_avatar_filename(image_url) self._image_url = extract_avatar_filename(image_url)
def __init__(self, image_url, user_id): def __init__(self, image_url, user_id):
self.id = gen_random_id(Avatar)
self.image_url = image_url self.image_url = image_url
self.user_id = user_id self.user_id = user_id
@ -143,6 +144,7 @@ class User(db.Model, UserMixin):
display_name=None, display_name=None,
title=None, title=None,
): ):
self.id = gen_random_id(User)
self.email_address = email_address self.email_address = email_address
self.display_name = display_name self.display_name = display_name
self.title = title self.title = title

View File

@ -34,26 +34,6 @@ from .models import (
blueprint = Blueprint('user', __name__, url_prefix='/api/v1/users') blueprint = Blueprint('user', __name__, url_prefix='/api/v1/users')
@blueprint.route("/", methods=["GET"])
@query({
"proposalId": fields.Str(required=False, missing=None)
})
def get_users(proposal_id):
proposal = Proposal.query.filter_by(id=proposal_id).first()
if not proposal:
users = User.query.all()
else:
users = (
User.query
.join(proposal_team)
.join(Proposal)
.filter(proposal_team.c.proposal_id == proposal.id)
.all()
)
result = users_schema.dump(users)
return result
@blueprint.route("/me", methods=["GET"]) @blueprint.route("/me", methods=["GET"])
@auth.requires_auth @auth.requires_auth
def get_me(): def get_me():

View File

@ -64,3 +64,16 @@ def make_preview(content: str, max_length: int):
truncated = True truncated = True
return content + '...' if truncated else content return content + '...' if truncated else content
def gen_random_id(model):
min_id = 100000
max_id = pow(2, 31) - 1
random_id = random.randint(min_id, max_id)
# If it already exists, generate a new one (recursively)
existing = model.query.filter_by(id=random_id).first()
if existing:
random_id = gen_random_id(model)
return random_id

View File

@ -34,14 +34,6 @@ class TestUserAPI(BaseUserConfig):
# should not be able to add social # should not be able to add social
self.assertFalse(user_db.social_medias) self.assertFalse(user_db.social_medias)
def test_get_all_users(self):
users_get_resp = self.app.get(
"/api/v1/users/"
)
self.assert200(users_get_resp)
users_json = users_get_resp.json
self.assertEqual(users_json[0]["displayName"], self.user.display_name)
def test_get_single_user_by_id(self): def test_get_single_user_by_id(self):
users_get_resp = self.app.get( users_get_resp = self.app.get(
"/api/v1/users/{}".format(self.user.id) "/api/v1/users/{}".format(self.user.id)
@ -163,11 +155,12 @@ class TestUserAPI(BaseUserConfig):
self.assert200(user_update_resp, user_update_resp.json) self.assert200(user_update_resp, user_update_resp.json)
user_json = user_update_resp.json user_json = user_update_resp.json
print(user_json)
self.assertFalse(user_json["avatar"]) self.assertFalse(user_json["avatar"])
self.assertFalse(len(user_json["socialMedias"])) self.assertFalse(len(user_json["socialMedias"]))
self.assertEqual(user_json["displayName"], updated_user["displayName"]) self.assertEqual(user_json["displayName"], updated_user["displayName"])
self.assertEqual(user_json["title"], updated_user["title"]) self.assertEqual(user_json["title"], updated_user["title"])
mock_remove_avatar.assert_called_with(test_user["avatar"]["link"], 1) mock_remove_avatar.assert_called_with(test_user["avatar"]["link"], self.user.id)
def test_update_user_400_when_required_param_not_passed(self): def test_update_user_400_when_required_param_not_passed(self):
self.login_default_user() self.login_default_user()