def act(self,
            action,
            upload,
            upload_data,
            file_hash,
            designation,
            member,
            title=None):
        checkAuthor(action, member)
        checkNoUpload(upload, upload_data)

        fobj = RawFile.by_hash(file_hash)

        if fobj is None:
            raise ValidationError("File to publish does not exist.")

        mobj = fobj.proposal_metadata
        if mobj is None:
            raise ValidationError("File needs to have metadata.")

        if fobj.public():
            raise ValidationError("File is already public.")

        nmobj = ProposalMetadata(filename=mobj.filename,
                                 mime_type=mobj.mime_type,
                                 designation=designation,
                                 title=title,
                                 raw_file=fobj,
                                 action=mobj.action,
                                 file_public=True)

        fobj.proposal_metadata = nmobj

        db.session.delete(mobj)
        db.session.add(nmobj)
    def __init__(self,
                 members,
                 secretary,
                 president,
                 developer,
                 previous=None):

        mnames = set(m.name for m in members)
        if len(mnames) < len(members):
            raise ValidationError("Duplicate members in list.")

        self.members = members
        self.secretary = secretary
        self.president = president
        self.developer = developer

        if secretary not in self.members:
            raise ValidationError("Secretary not listed as member.")

        if president not in self.members:
            raise ValidationError("President not listed as member.")

        if developer not in self.members:
            raise ValidationError("Developer not listed as member.")

        self.previous = previous

        self.xUpdate()
Example #3
0
    def cast(self, ballot, method_name, answer):
        log.debug("Casting new member vote: %s, %s, %s", ballot, method_name,
                  answer)
        members_voted = set(b.author for b in self.ballots)

        if method_name != self.method_name:
            # should not happen - tVoteAnswer(..) should always set it correctly
            raise ValidationError("Wrong method '%s' expected '%s'." %
                                  (method_name, self.method_name))

        if not self.is_open:
            raise ValidationError("Vote is not open anymore.")

        if ballot.member_list != self.action.member_list:
            # should not happen as votes need to be closed to create new member lists
            raise ValidationError(
                "Cannot vote on old proposal with different member list.")

        if ballot.author in members_voted:
            raise ValidationError("Member '%s' voted already." %
                                  ballot.author.name)

        if not ballot.author.eligible():
            raise ValidationError("Member is not eligible to vote (anymore).")

        self.ballots.append(ballot)
        log.debug("Current ballot list: %s", self.ballots)
        self.xUpdate()
    def act(self, action, upload, upload_data, meta_hash, member, method):
        method_name, method_options = method
        checkAuthor(action, member)
        checkNoUpload(upload, upload_data)

        mobj = ProposalMetadata.by_hash(meta_hash)
        if mobj is None:
            raise ValidationError("Proposal metadata '%s' does not exist." %
                                  meta_hash)

        if not mobj.file_public:
            raise ValidationError("Proposal needs  to be published first.")

        fobj = mobj.raw_file

        if mobj.vote is not None:
            raise ValidationError("Vote already open for object '%s'/'%s'." %
                                  (fobj, mobj))

        with db.session.no_autoflush:
            vobj = ProposalVote(fobj, mobj, action, method_name,
                                method_options)
            robj = ProposalVoteResult(vobj)
        db.session.add(vobj)
        db.session.add(robj)

        return vobj
Example #5
0
    def cast(self, ballot, method_name, answer):
        log.debug("Casting vote: %s, %s, %s", ballot, method_name, answer)
        vote = self.vote

        members_voted = set(b.author for b in self.ballots)

        if not self.is_open:
            raise ValidationError("Vote is not open anymore.")

        # -----
        # FIXME: temporary technical fix for social problem:
        # member keys and updates to member list are trickling in for this first vote
        # Temporary disable checking of proposal being generated for current member list
        # -----
        #if ballot.member_list != vote.action.member_list:
        #    raise ValidationError("Cannot vote on old proposal with different member list.")

        if ballot.author in members_voted:
            raise ValidationError("Member '%s' voted already." %
                                  ballot.author.name)

        if method_name != vote.method_name:
            # should not happen - tVoteAnswer(..) should always set it correctly
            raise ValidationError("Wrong method '%s' expected '%s'." %
                                  (method_name, vote.method_name))

        if not ballot.author.eligible():
            raise ValidationError("Member is not eligible to vote (anymore).")

        self.ballots.append(ballot)
        log.debug("Current ballot list: %s", self.ballots)
        self.xUpdate()
def tAddress(x):
    if len(x) > 35:
        raise ValidationError("Invalid address '%s' (too long)." % x)
    try:
        bitcoin.b58check_to_bin(x)
    except:
        raise ValidationError("Invalid address '%s'." % x)
    return x
def tDesignation(x):
    # designation for proposals
    if len(x) > 10:
        raise ValidationError("Invalid designation '%s' (too long)." % x)

    if not re.match("^[a-zA-Z0-9_-]+$", x):
        raise ValidationError("Invalid designation '%s'." % x)

    return x
    def act(self, action, upload, upload_data, member, result_hash):
        checkAuthor(action, member)
        checkNoUpload(upload, upload_data)

        result = ProposalVoteResult.by_hash(result_hash)
        if result is None:
            raise ValidationError("Proposal result '%s' does not exist." %
                                  result_hash)

        if not result.is_open:
            raise ValidationError("Result is already closed.")
        result.close()
def tMemberName(x):
    if len(x) > 30:
        raise ValidationError("Invalid member name '%s' (too long)." % x)

    if not re.match("^[a-zA-Z0-9_-]+$", x):
        raise ValidationError("Invalid member name '%s'." % x)

    if x in ["president", "developer", "secretary"]:
        raise ValidationError(
            "Invalid member name '%s'. Can't be any of the official BU rules."
            % x)

    return x
def tAccRejAbs(x):
    """ A value accept, reject or accept, returned as string. """
    if x in ["accept", "reject", "abstain", "spoil"]:
        return x
    else:
        raise ValidationError(
            "Expected accept, reject or abstain (or spoil), got '%s'." % x)
def tYesNo(x):
    """ A boolean, specified as yes(true) or no(false). """
    if x == "yes":
        return True
    elif x == "no":
        return False
    else:
        raise ValidationError("Expected yes or no, got '%s'." % x)
Example #12
0
    def __init__(self, data=None):
        self.data = data
        dhash = hashlib.sha256(data).hexdigest()
        orf = RawFile.by_hash(dhash)
        if orf is not None:
            raise ValidationError("Raw file with hash '%s' exists already." %
                                  dhash)

        self.xUpdate()
    def act(self, action, upload, upload_data, name, address, member):
        checkAuthor(action, member)
        checkNoUpload(upload, upload_data)

        with db.session.no_autoflush:
            if Member.by_name(name) is not None:
                raise ValidationError("Member '%s' exists already." % name)

            if Member.by_address(address) is not None:
                raise ValidationError(
                    "Member '%s' already uses address '%s'." %
                    (Member.by_address(address).name, address))

            m = Member(name=name, address=address)

            nme = MemberElectionResult(m, action)

        db.session.add(m)
        db.session.add(nme)
    def act(self, action, upload, upload_data, hashes, member):
        checkAuthor(action, member)
        checkNoUpload(upload, upload_data)

        all_objects = get_all_objects()

        objects = set()
        objs_ext = set()

        # go through list of objects and add them plus all immediate
        # dependencies to objs_ext, plus do some sanity checks
        # FIXME: inefficient!
        for hash in hashes:
            if hash not in all_objects:
                raise ValidationError("Object with hash %s not found." % hash)
            obj = all_objects[hash]

            if obj == Global.current_member_list():
                raise ValidationError(
                    "Objects cannot be deleted as list contains the current member list."
                )

            objects.add(obj)
            objs_ext.add(obj)
            for user in users_of(obj):
                objs_ext.add(user)

        # now compare - if they are not the same, the votemaster has not
        # explicitly listed all relevant objects for deletion, which is
        # regarded as an error to avoid mistakes
        if objects != objs_ext:
            raise ValidationError(
                "Set of objects to delete is not including all dependencies.",
                error_page={
                    "template": "error_delete_objects_mismatch.html",
                    "action": action,
                    "objects": objects,
                    "ext_objs": objs_ext,
                    "missing": objs_ext - objects
                })

        for obj in objects:
            db.session.delete(obj)
    def __call__(self, s):
        sanitize_input(s)
        shl = shlex.shlex(s)
        shl.wordchars += "-%:"
        try:
            tokens = list(shl)
        except ValueError:
            raise ValidationError("Parse error.")

        return self.parse(tokens)
Example #16
0
    def __init__(self, vote):
        if vote is None:
            raise ValidationError("Vote needed.")

        if vote.result is not None:
            raise ValidationError("Vote already has a result attached.")

        self.vote = vote

        with db.session.no_autoflush:
            self.Nmemb_eligible_opened = sum(
                member.eligible()
                for member in vote.action.member_list.members)

        self.is_open = True

        self.reconstruct()

        self.xUpdate()
def tSafeString(x):
    """ String that hopefully cannot be used to render any HTML/JS tricks.
    FIXME: review!
    """
    if x[0] == "'":
        if x[-1] != "'":
            raise ValidationError(
                "String starting with \"'\" needs to end with \"'\".")
    elif x[0] == '"':
        if x[-1] != '"':
            raise ValidationError(
                "String starting with '\"' needs to end with '\"'.")
    else:
        raise ValidationError("Please put string in quote marks.")

    x = x[1:-1]

    if not re.match("^[a-zA-Z0-9_ .:;!?+\-*/#@%=^\(\)\[\]\$]*$", x):
        raise ValidationError("Unsafe string '%s'." % x)
    return x
Example #18
0
def set_member_last_vote_time(args):
    import time
    import dbenv

    member = Member.by_name(args.name)
    if member is None:
        raise ValidationError("No recent member '%s' exists." % args.name)

    Global.set_member_last_vote_time(
        member, time.mktime(time.strptime(args.last_vote_time, "%d-%m-%Y")))
    db.session.commit()
    def act(self, action, upload, upload_data, vote_hash, member,
            answer_tuple):
        from vote_methods import vote_methods

        method_name, answer = answer_tuple

        checkAuthor(action, member)
        checkNoUpload(upload, upload_data)

        vote = ProposalVote.by_hash(vote_hash)

        if vote is None:  # pragma: no cover
            # should not happen as voteanswer type check checks that vote_hash is valid implicitly
            raise ValidationError("Vote '%s' does not exist." % vote_hash)

        if vote.result is None:  # pragma: no cover
            # should never happen as all proposal votes are created
            # with result object attached and SQLAlchemy should check this
            raise ValidationError("Vote result does not exist.")
        vote.result.cast(action, method_name, answer)
Example #20
0
    def __init__(self, raw_file, proposal_metadata, action, method_name,
                 method_options):
        if proposal_metadata.vote is not None:
            raise ValidationError("Vote on proposal(metadata) that " +
                                  "has already a vote attached.")

        self.raw_file = raw_file
        self.proposal_metadata = proposal_metadata
        self.action = action
        self.method_name = method_name
        self.method_options = method_options
        self.xUpdate()
def tVoteMethod(context, tokens):
    from vote_methods import vote_methods
    methodname = tokens[0]
    tokens = tokens[1:]
    if methodname not in vote_methods:
        raise ValidationError("Invalid voting method '%s'." % methodname)

    method = vote_methods[methodname]()
    ae = AExpr(method.spec_template, atypes)
    avars = ae.parse(tokens)
    method.checkSpecification(**avars)
    return (methodname, avars)
Example #22
0
def addMember(name, address, pgp_pubkey, number, last_vote_time):
    ml = Global.current_member_list()

    if len(list(ml.applications())):
        raise ValidationError("Current member list has new members applying.")

    if name in [m.name for m in ml.members]:
        raise ValidationError("Member '%s' exists in current member list." %
                              name)

    member = Member.by_name(name)
    if member is not None:
        raise ValidationError("Recent member '%s' exists." % name)

    new_member = Member(name=name,
                        address=address,
                        pgp_pubkey=pgp_pubkey,
                        number=number)
    hmember = Member.by_hash(new_member.hashref())
    if hmember is not None:
        # FIXME: maybe implement pointing to old member definition here
        log.info("Use existing member with same info.")
        new_member = hmember

    new_memberlist = ml.members.copy()
    new_memberlist.append(new_member)

    new_memberlist = MemberList(members=new_memberlist,
                                secretary=ml.secretary,
                                president=ml.president,
                                developer=ml.developer,
                                previous=ml)

    if hmember is None:
        db.session.add(new_member)
    db.session.add(new_memberlist)
    db.session.flush()  # need to flush so that Global.set* works below

    Global.set_member_last_vote_time(new_member, last_vote_time)
    Global.set_current_member_list(new_memberlist)
    def __init__(self, action):
        self.action = action

        s = action.actstr.find(" ")
        act = action.actstr[:s]

        if act not in action_map:
            raise ValidationError("Unknown action '%s'." % act)
        self.act = act
        self.ae = action_map[act]()

        self.expr = aparser.AExpr(self.ae.template, atypes)
        self.actvars = self.expr(action.actstr[s + 1:])
    def act(self, action, upload, upload_data, new_number, membername,
            votemaster):
        checkAuthor(action, votemaster)
        checkNoUpload(upload, upload_data)

        if new_number <= 0:
            raise ValidationError(
                "Member number must be set to a positive number, not %d." %
                new_number)

        member = Member.by_name(membername)

        updateMemberinCurrentMemberList(membername, "unchanged", "unchanged",
                                        new_number)
    def act(self, action, upload, upload_data, name, address, member,
            answer_tuple):
        method_name, answer = answer_tuple

        checkAuthor(action, member)
        checkNoUpload(upload, upload_data)

        member = Member.by_name(name)
        if member is None:
            raise ValidationError("Member '%s' not found." % name)

        if member.address != address:
            raise ValidationError(
                "Address '%s' for new member '%s' different from expected '%s'."
                % (address, name, member.address))

        election = MemberElectionResult.by_member(member)

        if election is None:
            raise ValidationError("No election for member '%s' exists." %
                                  member.name)

        election.cast(action, method_name, answer)
def tVoteAnswer(context, tokens):  # FIXME: code duplication
    from tproposalvote import ProposalVote
    from vote_methods import vote_methods

    if "vote_hash" not in context:
        raise ValidationError("Expected 'vote_hash' in context.")

    vote = ProposalVote.by_hash(context["vote_hash"])

    if vote is None:
        raise ValidationError("Vote '%s' does not exist." %
                              context["vote_hash"])

    method_name = vote.method_name

    if method_name not in vote_methods:
        raise ValidationError("Invalid voting method '%s'." % method_name)

    method = vote_methods[method_name]()

    ae = AExpr(method.vote_template, atypes)
    avars = ae.parse(tokens)
    method.checkAnswer(vote, **avars)
    return (method_name, avars)
    def act(self, action, upload, upload_data, pubkey_hash, membername,
            votemaster):
        checkAuthor(action, votemaster)
        checkUpload(upload, upload_data)

        dhash = hashlib.sha256(upload_data).hexdigest()

        if dhash != pubkey_hash:
            raise ValidationError(
                "Uploaded PGP key data data has hash %s but expected %s as in action."
                % (fobj.hashref(), file_hash))

        updateMemberinCurrentMemberList(membername, "unchanged",
                                        upload_data.decode("ascii"),
                                        "unchanged")
Example #28
0
    def __init__(self, new_member, action):

        # FIXME: might be too stringent (re-joining members etc.?) review
        if len(new_member.member_lists):
            # should have been tested in actionexec already
            raise ValidationError("Member is already member of a member list.")

        self.new_member = new_member
        self.action = action

        with db.session.no_autoflush:
            self.Nmemb_eligible_opened = sum(
                member.eligible() for member in action.member_list.members)

        self.is_open = True
        self.reconstruct()
        self.xUpdate()
    def act(self, action, upload, upload_data, names, member):
        checkAuthor(action, member)
        checkNoUpload(upload, upload_data)

        ml = Global.current_member_list()
        mers = ml.applications()

        names = set(names)
        app_names = set(a.new_member.name for a in mers)

        if app_names != names:
            raise ValidationError(
                "Currently, all new member elections must be closed at once.")

        members_voted_in = dict((r.new_member.name, r.new_member) for r in mers
                                if r.summarize()["accepted"])

        new_members = []

        # loop over names given to close-member-election action to keep the
        # order (member numbers) intact
        for name in names:
            if name in members_voted_in:
                m = members_voted_in[name]

                # "deprecate" tempory member objects used for voting
                m.most_recent = False

                # create new members - with auto-assigned member numbers
                new_members.append(
                    Member(name=m.name,
                           address=m.address,
                           pgp_pubkey=m.pgp_pubkey,
                           number="assign-new"))

        new_memberlist = MemberList(members=ml.members + new_members,
                                    secretary=ml.secretary,
                                    president=ml.president,
                                    developer=ml.developer,
                                    previous=ml)

        for mer in mers:
            mer.close()

        db.session.add(new_memberlist)
        Global.set_current_member_list(new_memberlist)
def tVoteMaster(membername):
    vmr = Global.get_votemaster_roles()

    if membername in vmr:
        # member is listed directly? -> pass
        return membername

    cml = Global.current_member_list()

    # FIXME: factor some stuff out here
    if ((cml.president.name == membername and "president" in vmr)
            or (cml.secretary.name == membername and "secretary" in vmr)
            or (cml.developer.name == membername and "developer" in vmr)):
        # listed as any of the official roles -> pass
        return membername

    raise ValidationError("Member '%s' needs to be vote master." % membername)