def test_plugin_and_or_rule_same_role_trustee_no_endorser(write_auth_req_validator, write_request_validation,
                                                          signatures, amount):
    validate(
        auth_constraint=AuthConstraintAnd(auth_constraints=[
            AuthConstraintOr(auth_constraints=[
                AuthConstraint(role=TRUSTEE, sig_count=2, need_to_be_owner=False),
                AuthConstraint(role=TRUSTEE, sig_count=2, need_to_be_owner=False,
                               metadata={PLUGIN_FIELD: 2}),
            ]),
            AuthConstraintOr(auth_constraints=[
                AuthConstraint(role=STEWARD, sig_count=3, need_to_be_owner=False),
                AuthConstraint(role=STEWARD, sig_count=3, need_to_be_owner=False,
                               metadata={PLUGIN_FIELD: 2}),
            ])
        ]),
        valid_actions=[
            Action(author=TRUSTEE, endorser=None, sigs={TRUSTEE: 2, STEWARD: 3},
                   is_owner=False, amount=2, extra_sigs=True),
            Action(author=TRUSTEE, endorser=None, sigs={TRUSTEE: 3, STEWARD: 3},
                   is_owner=False, amount=2, extra_sigs=True),

            Action(author=TRUSTEE, endorser=None, sigs={TRUSTEE: 2, STEWARD: 3},
                   is_owner=False, amount=None, extra_sigs=True),
            Action(author=TRUSTEE, endorser=None, sigs={TRUSTEE: 3, STEWARD: 3},
                   is_owner=False, amount=None, extra_sigs=True),
        ],
        author=TRUSTEE, endorser=None,
        all_signatures=signatures, is_owner=False, amount=amount,
        write_auth_req_validator=write_auth_req_validator,
        write_request_validation=write_request_validation
    )
def test_plugin_or_rule_one_amount_all_roles_endorser_no_endorser(
        write_auth_req_validator, write_request_validation, signatures,
        is_owner, amount, off_ledger_signature):
    validate(auth_constraint=AuthConstraintOr(auth_constraints=[
        AuthConstraint(role=ENDORSER, sig_count=1, need_to_be_owner=False),
        AuthConstraint(role='*',
                       sig_count=1,
                       need_to_be_owner=True,
                       off_ledger_signature=off_ledger_signature,
                       metadata={PLUGIN_FIELD: 3}),
    ]),
             valid_actions=[
                 Action(author=ENDORSER,
                        endorser=None,
                        sigs={ENDORSER: s},
                        is_owner=owner,
                        amount=None,
                        extra_sigs=True) for s in range(1, 4)
                 for owner in [True, False]
             ] + [
                 Action(author=ENDORSER,
                        endorser=None,
                        sigs={ENDORSER: s},
                        is_owner=True,
                        amount=3,
                        extra_sigs=True) for s in range(1, 4)
             ],
             author=ENDORSER,
             endorser=None,
             all_signatures=signatures,
             is_owner=is_owner,
             amount=amount,
             write_auth_req_validator=write_auth_req_validator,
             write_request_validation=write_request_validation)
def test_plugin_simple_rule_0_sig_owner_no_endorser(write_auth_req_validator,
                                                    write_request_validation,
                                                    signatures, is_owner,
                                                    off_ledger_signature,
                                                    amount):
    validate(auth_constraint=AuthConstraint(
        role='*',
        sig_count=0,
        need_to_be_owner=False,
        off_ledger_signature=off_ledger_signature,
        metadata={PLUGIN_FIELD: 2}),
             valid_actions=[
                 Action(author=IDENTITY_OWNER,
                        endorser=None,
                        sigs={},
                        is_owner=owner,
                        amount=2,
                        extra_sigs=False) for owner in [True, False]
             ] + [
                 Action(author=IDENTITY_OWNER,
                        endorser=None,
                        sigs={IDENTITY_OWNER: s},
                        is_owner=owner,
                        amount=2,
                        extra_sigs=False) for owner in [True, False]
                 for s in range(1, MAX_SIG_COUNT + 1)
             ],
             author=IDENTITY_OWNER,
             endorser=None,
             all_signatures=signatures,
             is_owner=is_owner,
             amount=amount,
             write_auth_req_validator=write_auth_req_validator,
             write_request_validation=write_request_validation)
def test_plugin_or_rule_all_amount_trustee_no_endorser(
        write_auth_req_validator, write_request_validation, signatures,
        is_owner, amount):
    validate(auth_constraint=AuthConstraintOr(auth_constraints=[
        AuthConstraint(role=TRUSTEE,
                       sig_count=1,
                       need_to_be_owner=False,
                       metadata={PLUGIN_FIELD: 1}),
        AuthConstraint(role=STEWARD,
                       sig_count=1,
                       need_to_be_owner=False,
                       metadata={PLUGIN_FIELD: 2}),
        AuthConstraint(role=ENDORSER,
                       sig_count=1,
                       need_to_be_owner=True,
                       metadata={PLUGIN_FIELD: 3}),
    ]),
             valid_actions=[
                 Action(author=TRUSTEE,
                        endorser=None,
                        sigs={TRUSTEE: s},
                        is_owner=owner,
                        amount=1,
                        extra_sigs=True) for s in range(1, 4)
                 for owner in [True, False]
             ] + [
                 Action(author=TRUSTEE,
                        endorser=None,
                        sigs={
                            TRUSTEE: s1,
                            STEWARD: s2
                        },
                        is_owner=owner,
                        amount=2,
                        extra_sigs=True) for s1 in range(1, 4)
                 for s2 in range(1, 4) for owner in [True, False]
             ] + [
                 Action(author=TRUSTEE,
                        endorser=None,
                        sigs={
                            TRUSTEE: s1,
                            ENDORSER: s2
                        },
                        is_owner=True,
                        amount=3,
                        extra_sigs=True) for s1 in range(1, 4)
                 for s2 in range(1, 4)
             ],
             author=TRUSTEE,
             endorser=None,
             all_signatures=signatures,
             is_owner=is_owner,
             amount=amount,
             write_auth_req_validator=write_auth_req_validator,
             write_request_validation=write_request_validation)
def test_plugin_simple_rule_3_sig_owner_endorser(write_auth_req_validator,
                                                 write_request_validation,
                                                 signatures, is_owner, amount):
    validate(auth_constraint=AuthConstraint(role=TRUSTEE,
                                            sig_count=3,
                                            need_to_be_owner=False,
                                            metadata={PLUGIN_FIELD: 2}),
             valid_actions=[
                 Action(author=IDENTITY_OWNER,
                        endorser=ENDORSER,
                        sigs={
                            TRUSTEE: 3,
                            IDENTITY_OWNER: s1,
                            ENDORSER: s2
                        },
                        is_owner=owner,
                        amount=2,
                        extra_sigs=True) for s1 in range(1, MAX_SIG_COUNT + 1)
                 for s2 in range(1, MAX_SIG_COUNT + 1)
                 for owner in [True, False]
             ],
             author=IDENTITY_OWNER,
             endorser=ENDORSER,
             all_signatures=signatures,
             is_owner=is_owner,
             amount=amount,
             write_auth_req_validator=write_auth_req_validator,
             write_request_validation=write_request_validation)
def test_plugin_simple_rule_1_sig_all_roles_trustee_endorser(
        write_auth_req_validator, write_request_validation, signatures,
        is_owner, off_ledger_signature, amount):
    validate(auth_constraint=AuthConstraint(
        role='*',
        sig_count=1,
        need_to_be_owner=True,
        off_ledger_signature=off_ledger_signature,
        metadata={PLUGIN_FIELD: 2}),
             valid_actions=[
                 Action(author=TRUSTEE,
                        endorser=ENDORSER,
                        sigs={
                            TRUSTEE: s1,
                            ENDORSER: s2
                        },
                        is_owner=True,
                        amount=2,
                        extra_sigs=True) for s1 in range(1, MAX_SIG_COUNT + 1)
                 for s2 in range(1, MAX_SIG_COUNT + 1)
             ],
             author=TRUSTEE,
             endorser=ENDORSER,
             all_signatures=signatures,
             is_owner=is_owner,
             amount=amount,
             write_auth_req_validator=write_auth_req_validator,
             write_request_validation=write_request_validation)
def test_plugin_or_error_msg_not_enough_amount_multiple_metadata_fields(write_auth_req_validator):
    set_auth_constraint(write_auth_req_validator,
                        AuthConstraintOr(auth_constraints=[
                            AuthConstraint(role=TRUSTEE, sig_count=1, need_to_be_owner=False),
                            AuthConstraint(role=STEWARD, sig_count=1, need_to_be_owner=False,
                                           metadata=OrderedDict([
                                               (PLUGIN_FIELD, 10),
                                               ("aaa", "bbb")
                                           ]))
                        ]))
    req, actions = build_req_and_action(Action(author=STEWARD, endorser=None,
                                               sigs={STEWARD: 1},
                                               is_owner=True,
                                               amount=5,
                                               extra_sigs=False))

    with pytest.raises(UnauthorizedClientRequest) as excinfo:
        write_auth_req_validator.validate(req, actions)
    expected = os.linesep.join([
        "Rule for this action is: 1 TRUSTEE signature is required OR 1 STEWARD signature is required with additional metadata new_field 10 aaa bbb",
        "Failed checks:",
        "Constraint: 1 TRUSTEE signature is required, Error: Not enough TRUSTEE signatures",
        "Constraint: 1 STEWARD signature is required with additional metadata new_field 10 aaa bbb, Error: not enough amount in plugin field"
    ])
    assert expected in str(excinfo.value.args[0])
def test_plugin_or_rule_one_amount_same_role_endorser_endorser(
        write_auth_req_validator, write_request_validation, signatures,
        is_owner, amount):
    validate(auth_constraint=AuthConstraintOr(auth_constraints=[
        AuthConstraint(role=ENDORSER, sig_count=1, need_to_be_owner=False),
        AuthConstraint(role=ENDORSER,
                       sig_count=1,
                       need_to_be_owner=False,
                       metadata={PLUGIN_FIELD: 2}),
    ]),
             valid_actions=[
                 Action(author=ENDORSER,
                        endorser=ENDORSER,
                        sigs={ENDORSER: s},
                        is_owner=owner,
                        amount=amount,
                        extra_sigs=True) for s in range(1, 4)
                 for owner in [True, False] for amount in [2, None]
             ],
             author=ENDORSER,
             endorser=ENDORSER,
             all_signatures=signatures,
             is_owner=is_owner,
             amount=amount,
             write_auth_req_validator=write_auth_req_validator,
             write_request_validation=write_request_validation)
def test_plugin_or_rule_one_amount_diff_roles_owner_no_endorser(
        write_auth_req_validator, write_request_validation, signatures,
        is_owner, amount):
    validate(auth_constraint=AuthConstraintOr(auth_constraints=[
        AuthConstraint(role=ENDORSER, sig_count=1, need_to_be_owner=False),
        AuthConstraint(role=IDENTITY_OWNER,
                       sig_count=1,
                       need_to_be_owner=True,
                       metadata={PLUGIN_FIELD: 1}),
    ]),
             valid_actions=[
                 Action(author=IDENTITY_OWNER,
                        endorser=None,
                        sigs={IDENTITY_OWNER: s},
                        is_owner=True,
                        amount=1,
                        extra_sigs=False) for s in range(1, MAX_SIG_COUNT + 1)
             ],
             author=IDENTITY_OWNER,
             endorser=None,
             all_signatures=signatures,
             is_owner=is_owner,
             amount=amount,
             write_auth_req_validator=write_auth_req_validator,
             write_request_validation=write_request_validation)
def test_plugin_complex_with_or_rule_with_not_allowed_trustee_no_endorser(
        write_auth_req_validator, write_request_validation, signatures,
        is_owner, off_ledger_signature, amount):
    validate(auth_constraint=AuthConstraintOr(auth_constraints=[
        AuthConstraintForbidden(),
        AuthConstraint(role="*",
                       sig_count=1,
                       need_to_be_owner=False,
                       off_ledger_signature=off_ledger_signature,
                       metadata={PLUGIN_FIELD: 2})
    ]),
             valid_actions=[
                 Action(author=TRUSTEE,
                        endorser=None,
                        sigs={TRUSTEE: s1},
                        is_owner=owner,
                        amount=2,
                        extra_sigs=True) for s1 in range(1, MAX_SIG_COUNT + 1)
                 for owner in [True, False]
             ],
             author=TRUSTEE,
             endorser=None,
             all_signatures=signatures,
             is_owner=is_owner,
             amount=amount,
             write_auth_req_validator=write_auth_req_validator,
             write_request_validation=write_request_validation)
def test_plugin_simple_rule_0_sig_trustee_no_endorser(write_auth_req_validator,
                                                      write_request_validation,
                                                      signatures, is_owner,
                                                      off_ledger_signature,
                                                      amount):
    validate(auth_constraint=AuthConstraint(
        role='*',
        sig_count=0,
        need_to_be_owner=False,
        off_ledger_signature=off_ledger_signature,
        metadata={PLUGIN_FIELD: 2}),
             valid_actions=[
                 Action(author=TRUSTEE,
                        endorser=None,
                        sigs=signature,
                        is_owner=owner,
                        amount=2,
                        extra_sigs=True) for signature in signatures
                 for owner in [True, False]
             ],
             author=TRUSTEE,
             endorser=None,
             all_signatures=signatures,
             is_owner=is_owner,
             amount=amount,
             write_auth_req_validator=write_auth_req_validator,
             write_request_validation=write_request_validation)
def test_plugin_or_rule_diff_amount_same_role_endorser_no_endorser(
        write_auth_req_validator, write_request_validation, signatures,
        is_owner, amount):
    validate(auth_constraint=AuthConstraintOr(auth_constraints=[
        AuthConstraint(role=ENDORSER,
                       sig_count=2,
                       need_to_be_owner=False,
                       metadata={PLUGIN_FIELD: 2}),
        AuthConstraint(role=ENDORSER,
                       sig_count=3,
                       need_to_be_owner=False,
                       metadata={PLUGIN_FIELD: 1}),
    ]),
             valid_actions=[
                 Action(author=ENDORSER,
                        endorser=None,
                        sigs={ENDORSER: 2},
                        is_owner=True,
                        amount=2,
                        extra_sigs=True),
                 Action(author=ENDORSER,
                        endorser=None,
                        sigs={ENDORSER: 3},
                        is_owner=True,
                        amount=1,
                        extra_sigs=True),
                 Action(author=ENDORSER,
                        endorser=None,
                        sigs={ENDORSER: 2},
                        is_owner=False,
                        amount=2,
                        extra_sigs=True),
                 Action(author=ENDORSER,
                        endorser=None,
                        sigs={ENDORSER: 3},
                        is_owner=False,
                        amount=1,
                        extra_sigs=True)
             ],
             author=ENDORSER,
             endorser=None,
             all_signatures=signatures,
             is_owner=is_owner,
             amount=amount,
             write_auth_req_validator=write_auth_req_validator,
             write_request_validation=write_request_validation)
def test_plugin_simple_error_msg_extra_plugin_field(write_auth_req_validator):
    set_auth_constraint(write_auth_req_validator,
                        AuthConstraint(role=IDENTITY_OWNER, sig_count=1, need_to_be_owner=True))
    req, actions = build_req_and_action(Action(author=IDENTITY_OWNER, endorser=None,
                                               sigs={IDENTITY_OWNER: 1},
                                               is_owner=True,
                                               amount=5,
                                               extra_sigs=False))

    with pytest.raises(UnauthorizedClientRequest) as excinfo:
        write_auth_req_validator.validate(req, actions)
    assert ("plugin field must be absent") in str(excinfo.value)
def test_plugin_simple_error_msg_not_enough_amount(write_auth_req_validator):
    set_auth_constraint(write_auth_req_validator,
                        AuthConstraint(role=IDENTITY_OWNER, sig_count=1, need_to_be_owner=True,
                                       metadata={PLUGIN_FIELD: 10}))
    req, actions = build_req_and_action(Action(author=IDENTITY_OWNER, endorser=None,
                                               sigs={IDENTITY_OWNER: 1},
                                               is_owner=True,
                                               amount=5,
                                               extra_sigs=False))

    with pytest.raises(UnauthorizedClientRequest) as excinfo:
        write_auth_req_validator.validate(req, actions)
    assert ("not enough amount in plugin field") in str(excinfo.value)
def test_plugin_and_or_rule_diff_role_trustee_no_endorser(write_auth_req_validator, write_request_validation,
                                                          signatures, is_owner, amount):
    validate(
        auth_constraint=AuthConstraintAnd(auth_constraints=[
            AuthConstraintOr(auth_constraints=[
                AuthConstraint(role=TRUSTEE, sig_count=2, need_to_be_owner=False,
                               metadata={PLUGIN_FIELD: 3}),
                AuthConstraint(role=STEWARD, sig_count=2, need_to_be_owner=False,
                               metadata={PLUGIN_FIELD: 3}),
            ]),
            AuthConstraintOr(auth_constraints=[
                AuthConstraint(role=ENDORSER, sig_count=3, need_to_be_owner=False,
                               metadata={PLUGIN_FIELD: 3}),
                AuthConstraint(role=IDENTITY_OWNER, sig_count=3, need_to_be_owner=True,
                               metadata={PLUGIN_FIELD: 3}),
            ])
        ]),
        valid_actions=[Action(author=TRUSTEE, endorser=None, sigs={ENDORSER: 3, TRUSTEE: s},
                              is_owner=owner, amount=3, extra_sigs=True)
                       for s in range(2, 4)
                       for owner in [True, False]] +
                      [Action(author=TRUSTEE, endorser=None, sigs={STEWARD: s1, ENDORSER: 3, TRUSTEE: s2},
                              is_owner=owner, amount=3, extra_sigs=True)
                       for s1 in range(2, 4)
                       for s2 in range(1, MAX_SIG_COUNT + 1)
                       for owner in [True, False]] +
                      [Action(author=TRUSTEE, endorser=None, sigs={STEWARD: s1, IDENTITY_OWNER: 3, TRUSTEE: s2},
                              is_owner=True, amount=3, extra_sigs=True)
                       for s1 in range(2, 4)
                       for s2 in range(1, MAX_SIG_COUNT + 1)],

        author=TRUSTEE, endorser=None,
        all_signatures=signatures, is_owner=is_owner, amount=amount,
        write_auth_req_validator=write_auth_req_validator,
        write_request_validation=write_request_validation
    )
def test_plugin_simple_rule_1_sig_endorser_no_endorser(
        write_auth_req_validator, write_request_validation, signatures,
        is_owner, amount):
    validate(auth_constraint=AuthConstraint(role=ENDORSER,
                                            sig_count=1,
                                            need_to_be_owner=True,
                                            metadata={PLUGIN_FIELD: 2}),
             valid_actions=[
                 Action(author=ENDORSER,
                        endorser=None,
                        sigs={ENDORSER: s},
                        is_owner=True,
                        amount=2,
                        extra_sigs=True) for s in range(1, MAX_SIG_COUNT + 1)
             ],
             author=ENDORSER,
             endorser=None,
             all_signatures=signatures,
             is_owner=is_owner,
             amount=amount,
             write_auth_req_validator=write_auth_req_validator,
             write_request_validation=write_request_validation)
def test_plugin_simple_rule_1_sig_owner_no_endorser(write_auth_req_validator,
                                                    write_request_validation,
                                                    signatures, is_owner,
                                                    amount):
    validate(auth_constraint=AuthConstraint(role=IDENTITY_OWNER,
                                            sig_count=1,
                                            need_to_be_owner=True,
                                            metadata={PLUGIN_FIELD: 2}),
             valid_actions=[
                 Action(author=IDENTITY_OWNER,
                        endorser=None,
                        sigs={IDENTITY_OWNER: 1},
                        is_owner=True,
                        amount=2,
                        extra_sigs=False)
             ],
             author=IDENTITY_OWNER,
             endorser=None,
             all_signatures=signatures,
             is_owner=is_owner,
             amount=amount,
             write_auth_req_validator=write_auth_req_validator,
             write_request_validation=write_request_validation)
def test_plugin_complex_trustee_no_endorser(write_auth_req_validator,
                                            write_request_validation,
                                            signatures, is_owner, amount):
    validate(
        auth_constraint=AuthConstraintOr(auth_constraints=[
            # 1st
            AuthConstraintAnd(auth_constraints=[
                AuthConstraint(role=TRUSTEE,
                               sig_count=3,
                               need_to_be_owner=False,
                               metadata={PLUGIN_FIELD: 1}),
                AuthConstraintOr(auth_constraints=[
                    AuthConstraintAnd(auth_constraints=[
                        AuthConstraint(role=STEWARD,
                                       sig_count=1,
                                       need_to_be_owner=False,
                                       metadata={PLUGIN_FIELD: 1}),
                        AuthConstraint(role=ENDORSER,
                                       sig_count=1,
                                       need_to_be_owner=False,
                                       metadata={PLUGIN_FIELD: 1}),
                    ]),
                    AuthConstraint(role=STEWARD,
                                   sig_count=2,
                                   need_to_be_owner=False,
                                   metadata={PLUGIN_FIELD: 1}),
                    AuthConstraint(role=ENDORSER,
                                   sig_count=2,
                                   need_to_be_owner=False,
                                   metadata={PLUGIN_FIELD: 1}),
                ])
            ]),
            # 2d
            AuthConstraintAnd(auth_constraints=[
                AuthConstraint(role=TRUSTEE,
                               sig_count=3,
                               need_to_be_owner=False,
                               metadata={PLUGIN_FIELD: 3}),
                AuthConstraint(role=IDENTITY_OWNER,
                               sig_count=1,
                               need_to_be_owner=True,
                               metadata={PLUGIN_FIELD: 3})
            ]),
            # 3d
            AuthConstraintAnd(auth_constraints=[
                AuthConstraint(
                    role=TRUSTEE, sig_count=3, need_to_be_owner=False),
                AuthConstraintOr(auth_constraints=[
                    AuthConstraint(
                        role=STEWARD, sig_count=2, need_to_be_owner=False),
                    AuthConstraint(
                        role=ENDORSER, sig_count=2, need_to_be_owner=True),
                ])
            ]),
            # 4th
            AuthConstraintAnd(auth_constraints=[
                AuthConstraint(role=TRUSTEE,
                               sig_count=2,
                               need_to_be_owner=False,
                               metadata={PLUGIN_FIELD: 2}),
                AuthConstraint(role=IDENTITY_OWNER,
                               sig_count=1,
                               need_to_be_owner=True,
                               metadata={PLUGIN_FIELD: 2})
            ]),
        ]),
        valid_actions=[
            Action(
                author=TRUSTEE,
                endorser=None,
                sigs={
                    TRUSTEE: 3,
                    STEWARD: s1,
                    ENDORSER: s2
                },  # 1st
                is_owner=owner,
                amount=1,
                extra_sigs=True) for s1 in range(1, 4) for s2 in range(1, 4)
            for owner in [True, False]
        ] + [
            Action(author=TRUSTEE,
                   endorser=None,
                   sigs={
                       TRUSTEE: 3,
                       STEWARD: s
                   },
                   is_owner=owner,
                   amount=1,
                   extra_sigs=True) for s in range(2, 4)
            for owner in [True, False]
        ] + [
            Action(
                author=TRUSTEE,
                endorser=None,
                sigs={
                    TRUSTEE: 3,
                    IDENTITY_OWNER: s
                },  # 2d
                is_owner=True,
                amount=3,
                extra_sigs=True) for s in range(1, 4)
        ] + [
            Action(
                author=TRUSTEE,
                endorser=None,
                sigs={
                    TRUSTEE: 3,
                    STEWARD: s
                },  # 3d
                is_owner=owner,
                amount=None,
                extra_sigs=True) for s in range(2, 4)
            for owner in [True, False]
        ] + [
            Action(author=TRUSTEE,
                   endorser=None,
                   sigs={
                       TRUSTEE: 3,
                       ENDORSER: s
                   },
                   is_owner=owner,
                   amount=None,
                   extra_sigs=True) for s in range(2, 4)
            for owner in [True, False]
        ] + [
            Action(
                author=TRUSTEE,
                endorser=None,
                sigs={
                    TRUSTEE: 2,
                    IDENTITY_OWNER: s
                },  # 4th
                is_owner=True,
                amount=2,
                extra_sigs=True) for s in range(1, 4)
        ],
        author=TRUSTEE,
        endorser=None,
        all_signatures=signatures,
        is_owner=is_owner,
        amount=amount,
        write_auth_req_validator=write_auth_req_validator,
        write_request_validation=write_request_validation)