diff --git a/api/Pipfile b/api/Pipfile index 106066ecd9..eee0d82f59 100644 --- a/api/Pipfile +++ b/api/Pipfile @@ -29,6 +29,7 @@ flask-migrate = "*" pytest = "*" pyotp = "*" pyjwt = "*" +python-slugify = "*" [scripts] test = "python -m pytest" diff --git a/api/Pipfile.lock b/api/Pipfile.lock index a3b216ee76..a4ee2d0a36 100644 --- a/api/Pipfile.lock +++ b/api/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "b7cfc60c14492f7d38a230f76839f44c0dc534e5a72feba8de7a51a92be4ce07" + "sha256": "466060c557e96174eeb5361e5953eae7ed6188e509a40e9888954b1b29da5191" }, "pipfile-spec": 6, "requires": { @@ -108,10 +108,10 @@ }, "click": { "hashes": [ - "sha256:8a18b4ea89d8820c5d0c7da8a64b2c324b4dabb695804dbfea19b9be9d88c0cc", - "sha256:e345d143d80bf5ee7534056164e5e112ea5e22716bbb1ce727941f4c8b471b9a" + "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", + "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" ], - "version": "==7.1.1" + "version": "==7.1.2" }, "docopt": { "hashes": [ @@ -424,6 +424,13 @@ ], "version": "==1.0.4" }, + "python-slugify": { + "hashes": [ + "sha256:a8fc3433821140e8f409a9831d13ae5deccd0b033d4744d94b31fea141bdd84c" + ], + "index": "pypi", + "version": "==4.0.0" + }, "requests": { "hashes": [ "sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee", @@ -477,6 +484,13 @@ "index": "pypi", "version": "==1.3.16" }, + "text-unidecode": { + "hashes": [ + "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", + "sha256:bad6603bb14d279193107714b288be206cac565dfa49aa5b105294dd5c4aab93" + ], + "version": "==1.3" + }, "urllib3": { "hashes": [ "sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527", @@ -510,10 +524,10 @@ "develop": { "astroid": { "hashes": [ - "sha256:71ea07f44df9568a75d0f354c49143a4575d90645e9fead6dfb52c26a85ed13a", - "sha256:840947ebfa8b58f318d42301cf8c0a20fd794a33b61cc4638e28e9e61ba32f42" + "sha256:4c17cea3e592c21b6e222f673868961bad77e1f985cb1694ed077475a89229c1", + "sha256:d8506842a3faf734b81599c8b98dcc423de863adcc1999248480b18bd31a0f38" ], - "version": "==2.3.3" + "version": "==2.4.1" }, "attrs": { "hashes": [ @@ -655,11 +669,11 @@ }, "pylint": { "hashes": [ - "sha256:3db5468ad013380e987410a8d6956226963aed94ecb5f9d3a28acca6d9ac36cd", - "sha256:886e6afc935ea2590b462664b161ca9a5e40168ea99e5300935f6591ad467df4" + "sha256:b95e31850f3af163c2283ed40432f053acbc8fc6eba6a069cb518d9dbf71848c", + "sha256:dd506acce0427e9e08fb87274bcaa953d38b50a58207170dbf5b36cf3e16957b" ], "index": "pypi", - "version": "==2.4.4" + "version": "==2.5.2" }, "pyparsing": { "hashes": [ @@ -691,6 +705,13 @@ ], "version": "==1.14.0" }, + "toml": { + "hashes": [ + "sha256:229f81c57791a41d65e399fc06bf0848bab550a9dfd5ed66df18ce5f05e73d5c", + "sha256:235682dd292d5899d361a811df37e04a8828a5b1da3115886b73cf81ebc9100e" + ], + "version": "==0.10.0" + }, "typed-ast": { "hashes": [ "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355", @@ -734,9 +755,9 @@ }, "wrapt": { "hashes": [ - "sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1" + "sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7" ], - "version": "==1.11.2" + "version": "==1.12.1" } } } diff --git a/api/functions/auth_wrappers.py b/api/functions/auth_wrappers.py index ad371f05bc..778fe01b78 100644 --- a/api/functions/auth_wrappers.py +++ b/api/functions/auth_wrappers.py @@ -46,6 +46,8 @@ def check_user_claims(user_claims): elif user_claims: user_id = user_claims[0]['user_id'] with app.app_context(): + # XXX: affiliations should have been eager loaded with joinedload + # when user was initally pulled from the db. user_aff = User_affiliations.query.filter( User_affiliations.user_id == user_id).all() user_aff = orm_to_dict(user_aff) diff --git a/api/functions/sign_in_user.py b/api/functions/sign_in_user.py index c160311827..ff959a8c85 100644 --- a/api/functions/sign_in_user.py +++ b/api/functions/sign_in_user.py @@ -56,11 +56,13 @@ def sign_in_user(user_name, password): } user_roles.append(temp_dict) else: + # XXX: Roles is [] || [""] || [{}]? + # why not just []? user_roles = ["none"] try: payload = { "exp": datetime.datetime.utcnow() - + datetime.timedelta(days=0, seconds=1800), + + datetime.timedelta(days=0, seconds=1800), # XXX: too short "iat": datetime.datetime.utcnow(), "user_id": user.id, "roles": user_roles, diff --git a/api/migrations/versions/1860746a39e4_.py b/api/migrations/versions/1860746a39e4_.py new file mode 100644 index 0000000000..5ffc9eaef5 --- /dev/null +++ b/api/migrations/versions/1860746a39e4_.py @@ -0,0 +1,76 @@ +"""empty message + +Revision ID: b781fb62a115 +Revises: 1860746a39e4 +Create Date: 2020-05-06 13:19:46.906351 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = "b781fb62a115" +down_revision = "1860746a39e4" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column("organizations", sa.Column("name", sa.String(), nullable=True)) + op.add_column("organizations", sa.Column("slug", sa.String(), nullable=True)) + op.create_index( + op.f("ix_organizations_slug"), "organizations", ["slug"], unique=False + ) + op.drop_constraint("user_user_aff_key", "user_affiliations", type_="foreignkey") + op.drop_constraint( + "user_affiliations_organization_id_fkey", + "user_affiliations", + type_="foreignkey", + ) + op.create_foreign_key( + "user_affiliations_organization_id_fkey", + "user_affiliations", + "organizations", + ["organization_id"], + ["id"], + onupdate="CASCADE", + ondelete="CASCADE", + ) + op.create_foreign_key( + "user_affiliations_users_id_fkey", + "user_affiliations", + "users", + ["user_id"], + ["id"], + onupdate="CASCADE", + ondelete="CASCADE", + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint( + "user_affiliations_users_id_fkey", "user_affiliations", type_="foreignkey" + ) + op.drop_constraint( + "user_affiliations_organization_id_fkey", + "user_affiliations", + type_="foreignkey", + ) + op.create_foreign_key( + "user_affiliations_organization_id_fkey", + "user_affiliations", + "organizations", + ["organization_id"], + ["id"], + ) + op.create_foreign_key( + "user_user_aff_key", "user_affiliations", "users", ["user_id"], ["id"] + ) + op.drop_index(op.f("ix_organizations_slug"), table_name="organizations") + op.drop_column("organizations", "slug") + op.drop_column("organizations", "name") + # ### end Alembic commands ### diff --git a/api/migrations/versions/b781fb62a115_.py b/api/migrations/versions/b781fb62a115_.py new file mode 100644 index 0000000000..871b25c83b --- /dev/null +++ b/api/migrations/versions/b781fb62a115_.py @@ -0,0 +1,30 @@ +"""empty message + +Revision ID: 1860746a39e4 +Revises: cf42b66dbc12 +Create Date: 2020-04-30 22:30:22.681303 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.schema import Sequence, CreateSequence + + +# revision identifiers, used by Alembic. +revision = "1860746a39e4" +down_revision = "cf42b66dbc12" +branch_labels = None +depends_on = None + + +def upgrade(): + op.execute(CreateSequence(Sequence("dmarc_reports_id_seq"))) + op.execute( + "ALTER TABLE dmarc_reports ALTER COLUMN id SET DEFAULT nextval('public.dmarc_reports_id_seq')" + ) + op.execute("ALTER SEQUENCE dmarc_reports_id_seq OWNED BY dmarc_reports.id") + + +def downgrade(): + op.execute("ALTER TABLE dmarc_reports ALTER COLUMN id DROP DEFAULT") + op.execute("DROP SEQUENCE dmarc_reports_id_seq") diff --git a/api/models/Organizations.py b/api/models/Organizations.py index 93272c94ef..784cb72c6e 100644 --- a/api/models/Organizations.py +++ b/api/models/Organizations.py @@ -1,8 +1,8 @@ -from graphene import Time -from sqlalchemy.types import Integer, Boolean, DateTime, Float -from sqlalchemy import Column, String, ForeignKey +from sqlalchemy.types import Integer +from sqlalchemy import Column, String from sqlalchemy.orm import relationship from sqlalchemy.dialects.postgresql import JSONB +from slugify import slugify from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method from db import Base @@ -11,11 +11,17 @@ class Organizations(Base): __tablename__ = "organizations" id = Column(Integer, primary_key=True) + name = Column(String) + slug = Column(String, index=True) acronym = Column(String) org_tags = Column(JSONB) - domains = relationship( - "Domains", back_populates="organization", cascade="all, delete" - ) + domains = relationship("Domains", back_populates="organization", cascade="all, delete") users = relationship( - "User_affiliations", back_populates="user_organization", cascade="all, delete" + "User_affiliations", back_populates="user_organization", passive_deletes=True ) + + def __init__(self, **kwargs): + super(Organizations, self).__init__(**kwargs) + self.slug = slugify(kwargs.get("name", "")) + if self.org_tags is None: + self.org_tags = dict() diff --git a/api/models/User_affiliations.py b/api/models/User_affiliations.py index b0d22d73c9..9494479d4f 100644 --- a/api/models/User_affiliations.py +++ b/api/models/User_affiliations.py @@ -8,12 +8,31 @@ class User_affiliations(Base): __tablename__ = "user_affiliations" id = Column(Integer, primary_key=True, autoincrement=True) - user_id = Column(Integer, ForeignKey("users.id"), primary_key=True) - organization_id = Column(Integer, ForeignKey("organizations.id")) + user_id = Column( + Integer, + ForeignKey( + "users.id", + onupdate="CASCADE", + ondelete="CASCADE", + # name is required on FK or rollback is broken + name="user_affiliations_users_id_fkey", + ), + primary_key=True, + ) + organization_id = Column( + Integer, + ForeignKey( + "organizations.id", + onupdate="CASCADE", + ondelete="CASCADE", + # name is required on FK or rollback is broken + name="user_affiliations_organization_id_fkey", + ), + ) permission = Column(String) user = relationship( "Users", back_populates="user_affiliation", cascade="all, delete" ) user_organization = relationship( - "Organizations", back_populates="users", cascade="all, delete" + "Organizations", back_populates="users", cascade="all, delete", ) diff --git a/api/models/Users.py b/api/models/Users.py index 8606e087d8..3c360e054f 100644 --- a/api/models/Users.py +++ b/api/models/Users.py @@ -1,9 +1,13 @@ from sqlalchemy.types import Integer, Boolean, Float +from slugify import slugify from functions.orm_to_dict import orm_to_dict from sqlalchemy import Column, String, ForeignKey from sqlalchemy import event from app import bcrypt +from models.Organizations import Organizations +from models.User_affiliations import User_affiliations from sqlalchemy.orm import relationship, validates +from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method from db import Base @@ -20,9 +24,24 @@ class Users(Base): failed_login_attempt_time = Column(Float, default=0, nullable=True) tfa_validated = Column(Boolean, default=False) user_affiliation = relationship( - "User_affiliations", back_populates="user", cascade="all, delete" + "User_affiliations", back_populates="user", passive_deletes=True, ) + def __init__(self, **kwargs): + super(Users, self).__init__(**kwargs) + # XXX: This is gross but matches the expections of the + # Acronym scalar type. + acronym = slugify(self.user_name).upper()[:10] + self.user_affiliation.append( + User_affiliations( + permission="admin", + user_organization=Organizations( + name=self.user_name, + acronym=acronym, + ) + ) + ) + @hybrid_method def find_by_user_name(self, user_name): return self.query.filter(self.user_name == user_name).first() diff --git a/api/models/__init__.py b/api/models/__init__.py index 3db59e5fc2..7da071b2f3 100644 --- a/api/models/__init__.py +++ b/api/models/__init__.py @@ -12,7 +12,7 @@ class Domains(Base): __tablename__ = "domains" - id = Column(Integer, primary_key=True) + id = Column(Integer, primary_key=True, autoincrement=True) domain = Column(String) last_run = Column(DateTime) organization_id = Column(Integer, ForeignKey("organizations.id")) @@ -41,7 +41,7 @@ class Dmarc_Reports(Base): class Scans(Base): __tablename__ = "scans" - id = Column(Integer, primary_key=True) + id = Column(Integer, primary_key=True, autoincrement=True) domain_id = Column(Integer, ForeignKey("domains.id")) scan_date = Column(DateTime) initiated_by = Column(Integer, ForeignKey("users.id")) diff --git a/api/schemas/organizations.py b/api/schemas/organizations.py index 62dda48aca..4d271fb174 100644 --- a/api/schemas/organizations.py +++ b/api/schemas/organizations.py @@ -30,12 +30,12 @@ class Meta: "domains", "users" ) + name = graphene.String( + description="The full name of the organization." + ) acronym = Acronym( description="The acronym of the organization." ) - description = graphene.String( - description="The full name of the organization." - ) zone = graphene.String( description="The zone which the organization belongs to." ) @@ -61,20 +61,20 @@ class Meta: def resolve_acronym(self: OrgModel, info): return self.acronym - def resolve_description(self: OrgModel, info): - return self.org_tags["description"] + def resolve_name(self: OrgModel, info): + return self.name def resolve_zone(self: OrgModel, info): - return self.org_tags["zone"] + return self.org_tags.get("zone", None) def resolve_sector(self: OrgModel, info): - return self.org_tags["sector"] + return self.org_tags.get("sector", None) def resolve_province(self: OrgModel, info): - return self.org_tags["province"] + return self.org_tags.get("province", None) def resolve_city(self: OrgModel, info): - return self.org_tags["city"] + return self.org_tags.get("city", None) def resolve_domains(self: OrgModel, info): query = DomainsSchema.get_query(info) diff --git a/api/schemas/organizations_mutations.py b/api/schemas/organizations_mutations.py index ad256e2688..c3556a5819 100644 --- a/api/schemas/organizations_mutations.py +++ b/api/schemas/organizations_mutations.py @@ -1,14 +1,10 @@ import graphene - from graphql import GraphQLError - from app import app from db import db_session - from functions.auth_wrappers import require_token from functions.auth_functions import is_super_admin from functions.input_validators import cleanse_input - from models import ( Organizations, User_affiliations, @@ -20,7 +16,6 @@ Dkim_scans, Dmarc_scans, Mx_scans, - ) from scalars.organization_acronym import Acronym @@ -30,69 +25,61 @@ class CreateOrganization(graphene.Mutation): """ Mutation allows the creation of an organization inside the database. """ + class Arguments: - acronym = Acronym( - description="Acronym of organization.", - required=True - ) - description = graphene.String( - description="Full name of organization.", - required=True - ) + acronym = Acronym(description="Acronym of organization.", required=True) + name = graphene.String(description="Full name of organization.", required=True) zone = graphene.String( - description="The zone which the organization belongs to.", - required=True + description="The zone which the organization belongs to.", required=True ) sector = graphene.String( - description="The sector which the organization belongs to.", - required=True + description="The sector which the organization belongs to.", required=True ) province = graphene.String( description="The province in which the organization is located in.", - required=True + required=True, ) city = graphene.String( description="The city in which the organization is located in.", - required=True + required=True, ) # If the update passed or failed status = graphene.Boolean() with app.app_context(): + @require_token def mutate(self, info, **kwargs): - user_roles = kwargs.get('user_roles') - acronym = cleanse_input(kwargs.get('acronym')) - description = cleanse_input(kwargs.get('description')) - zone = cleanse_input(kwargs.get('zone')) - sector = cleanse_input(kwargs.get('sector')) - province = cleanse_input(kwargs.get('province')) - city = cleanse_input(kwargs.get('city')) + user_roles = kwargs.get("user_roles") + name = cleanse_input(kwargs.get("name")) + acronym = cleanse_input(kwargs.get("acronym")) + zone = cleanse_input(kwargs.get("zone")) + sector = cleanse_input(kwargs.get("sector")) + province = cleanse_input(kwargs.get("province")) + city = cleanse_input(kwargs.get("city")) if is_super_admin(user_role=user_roles): # Check to see if organization already exists - org_orm = db_session.query(Organizations).filter( - Organizations.acronym == acronym - ).first() + org_orm = ( + db_session.query(Organizations) + .filter(Organizations.acronym == acronym) + .first() + ) if org_orm is not None: - raise GraphQLError("Error, Organization alredy exists") + raise GraphQLError("Error, Organization already exists") # Generate org tags org_tags = { - "description": description, "zone": zone, "sector": sector, "province": province, - "city": city + "city": city, } # Create new org entry in db - new_org = Organizations( - acronym=acronym, - org_tags=org_tags - ) + new_org = Organizations(name=name, acronym=acronym, org_tags=org_tags) # Add new org entry into the session db_session.add(new_org) @@ -114,89 +101,82 @@ def mutate(self, info, **kwargs): class UpdateOrganization(graphene.Mutation): class Arguments: acronym = Acronym( - description="Organization that will be updated.", - required=True + description="Organization that will be updated.", required=True ) updated_acronym = Acronym( - description="Organization Acronym you would like updated", - required=False - ) - description = graphene.String( - description="Full name of organization.", - required=False + description="Organization Acronym you would like updated", required=False ) + name = graphene.String(description="Full name of organization.", required=False) zone = graphene.String( - description="The zone which the organization belongs to.", - required=False + description="The zone which the organization belongs to.", required=False ) sector = graphene.String( - description="The sector which the organization belongs to.", - required=False + description="The sector which the organization belongs to.", required=False ) province = graphene.String( description="The province in which the organization is located in.", - required=False + required=False, ) city = graphene.String( description="The city in which the organization is located in.", - required=False + required=False, ) # If the update passed or failed status = graphene.Boolean() with app.app_context(): + @require_token def mutate(self, info, **kwargs): # Get arguments from mutation - user_roles = kwargs.get('user_roles') - acronym = cleanse_input(kwargs.get('acronym')) - updated_acronym = cleanse_input(kwargs.get('updated_acronym')) - description = cleanse_input(kwargs.get('description')) - zone = cleanse_input(kwargs.get('zone')) - sector = cleanse_input(kwargs.get('sector')) - province = cleanse_input(kwargs.get('province')) - city = cleanse_input(kwargs.get('city')) - + user_roles = kwargs.get("user_roles") + name = cleanse_input(kwargs.get("name")) + acronym = cleanse_input(kwargs.get("acronym")) + updated_acronym = cleanse_input(kwargs.get("updated_acronym")) + description = cleanse_input(kwargs.get("description")) + zone = cleanse_input(kwargs.get("zone")) + sector = cleanse_input(kwargs.get("sector")) + province = cleanse_input(kwargs.get("province")) + city = cleanse_input(kwargs.get("city")) + + # XXX: only the Super User can edit orgs? if is_super_admin(user_role=user_roles): # Get requested org orm - org_orm = db_session.query(Organizations).filter( - Organizations.acronym == acronym - ).first() + org_orm = ( + db_session.query(Organizations) + .filter(Organizations.acronym == acronym) + .first() + ) # Check to see if org exists if org_orm is None: raise GraphQLError("Error, organization does not exist.") # Check to see if organization acronym already in use - update_org_orm = db_session.query(Organizations).filter( - Organizations.acronym == updated_acronym - ).first() + update_org_orm = ( + db_session.query(Organizations) + .filter(Organizations.acronym == updated_acronym) + .first() + ) if update_org_orm is not None: raise GraphQLError("Error, acronym already in use.") - # Generate org tags - org_tags = { - "description": description, - "zone": zone, - "sector": sector, - "province": province, - "city": city - } if updated_acronym is not acronym: # Update orm - Organizations.query.filter( - Organizations.acronym == acronym - ).update( - { - 'acronym': updated_acronym, - 'org_tags': org_tags - } - ) + org_orm.name = name + org_orm.acronym = updated_acronym + org_orm.org_tags = { + "zone": zone, + "sector": sector, + "province": province, + "city": city, + } # Push update to db and return status + try: db_session.commit() return UpdateOrganization(status=True) @@ -214,87 +194,83 @@ class RemoveOrganization(graphene.Mutation): """ Mutation allows the removal of an organization inside the database. """ + class Arguments: acronym = Acronym( - description="The organization you wish to remove", - required=True + description="The organization you wish to remove", required=True ) status = graphene.Boolean() with app.app_context(): + @require_token def mutate(self, info, **kwargs): # Get arguments from mutation - user_roles = kwargs.get('user_roles') - acronym = cleanse_input(kwargs.get('acronym')) + user_roles = kwargs.get("user_roles") + acronym = cleanse_input(kwargs.get("acronym")) # Restrict the deletion of SA Org if acronym == "SA": raise GraphQLError("Error, you cannot remove this organization") # Check to see if org exists - org_orm = db_session.query(Organizations).filter( - Organizations.acronym == acronym - ).first() + org_orm = ( + db_session.query(Organizations) + .filter(Organizations.acronym == acronym) + .first() + ) if org_orm is None: raise GraphQLError("Error, organization does not exist") # Check Permissions if is_super_admin(user_role=user_roles): + # XXX shouldn't cascade delete do all of this for us? try: - # Get Org ID - org_orm = Organizations.query.filter( - Organizations.acronym == acronym - ).first() - # Get All Domains domain_orm = Domains.query.filter( Domains.organization_id == org_orm.id ).all() - # Loop Through All Domains - for domain in domain_orm: - # Get All Scans - scan_orm = Scans.query.filter( - Scans.domain_id == domain.id - ).all() - # Delete All Related Scans - for scan in scan_orm: + if len(domain_orm) > 0: + # Loop Through All Domains + for domain in domain_orm: + # Get All Scans + scan_orm = Scans.query.filter( + Scans.domain_id == domain.id + ).all() + # Delete All Related Scans + for scan in scan_orm: + try: + Dkim_scans.query.filter( + Dkim_scans.id == scan.id + ).delete() + Dmarc_scans.query.filter( + Dmarc_scans.id == scan.id + ).delete() + Https_scans.query.filter( + Https_scans.id == scan.id + ).delete() + Mx_scans.query.filter( + Mx_scans.id == scan.id + ).delete() + Spf_scans.query.filter( + Spf_scans.id == scan.id + ).delete() + Ssl_scans.query.filter( + Ssl_scans.id == scan.id + ).delete() + Scans.query.filter(Scans.id == scan.id).delete() + except Exception as e: + print("Scans: " + e) + return RemoveOrganization(status=False) + # Delete Domains try: - Dkim_scans.query.filter( - Dkim_scans.id == scan.id - ).delete() - Dmarc_scans.query.filter( - Dmarc_scans.id == scan.id - ).delete() - Https_scans.query.filter( - Https_scans.id == scan.id - ).delete() - Mx_scans.query.filter( - Mx_scans.id == scan.id - ).delete() - Spf_scans.query.filter( - Spf_scans.id == scan.id - ).delete() - Ssl_scans.query.filter( - Ssl_scans.id == scan.id - ).delete() - Scans.query.filter( - Scans.id == scan.id - ).delete() + Domains.query.filter(Domains.id == domain.id).delete() except Exception as e: - print("Scans: " + e) + print("Domain: " + str(e)) return RemoveOrganization(status=False) - # Delete Domains - try: - Domains.query.filter( - Domains.id == domain.id - ).delete() - except Exception as e: - print("Domain: " + str(e)) - return RemoveOrganization(status=False) try: # Get all user aff @@ -305,11 +281,10 @@ def mutate(self, info, **kwargs): print("user_aff: " + str(e)) return RemoveOrganization(status=False) - Organizations.query.filter( - Organizations.acronym == acronym - ).delete() + db_session.delete(org_orm) db_session.commit() return RemoveOrganization(status=True) + except Exception as e: print("organization: " + str(e)) db_session.rollback() diff --git a/api/tests/test_auth_functions.py b/api/tests/test_auth_functions.py index f3bd729334..c5f6a61ecd 100644 --- a/api/tests/test_auth_functions.py +++ b/api/tests/test_auth_functions.py @@ -1,6 +1,5 @@ import pytest from app import app -from db import db_session from models import Users, User_affiliations, Organizations from functions.auth_functions import ( is_super_admin, diff --git a/api/tests/test_cost_check.py b/api/tests/test_cost_check.py index 2f042a7d36..6cb68c7d1d 100644 --- a/api/tests/test_cost_check.py +++ b/api/tests/test_cost_check.py @@ -3,12 +3,13 @@ from werkzeug.test import create_environ from flask import Request from unittest import TestCase -from db import db_session +from db import DB from app import app from queries import schema from models import Users from backend.security_check import SecurityAnalysisBackend +_, cleanup, db_session = DB() @pytest.fixture(scope="class") def user_schema_test_db_init(): @@ -22,11 +23,9 @@ def user_schema_test_db_init(): db_session.add(test_super_admin) db_session.commit() - yield + yield + cleanup() - with app.app_context(): - Users.query.delete() - db_session.commit() ## diff --git a/api/tests/test_createOrganization_mutation.py b/api/tests/test_createOrganization_mutation.py new file mode 100644 index 0000000000..caedb6c104 --- /dev/null +++ b/api/tests/test_createOrganization_mutation.py @@ -0,0 +1,308 @@ +import pytest +from json_web_token import tokenize, auth_header +from flask import Request +from pytest import fail +from graphene.test import Client +from unittest import TestCase +from werkzeug.test import create_environ +from app import app +from db import DB +from queries import schema +from backend.security_check import SecurityAnalysisBackend +from models import ( + Organizations, + Domains, + Users, + User_affiliations, + Scans, + Dkim_scans, + Dmarc_scans, + Https_scans, + Mx_scans, + Spf_scans, + Ssl_scans, +) + +s, cleanup, session = DB() + + +@pytest.fixture +def save(): + with app.app_context(): + yield s + cleanup() + + +def test_mutation_createOrganization_fails_for_existing_orgs(save): + """ + Test To See If SA Can Create Organization + """ + sa_user = Users( + display_name="testsuperadmin", + user_name="testsuperadmin@testemail.ca", + password="testpassword123", + ) + sa_user.user_affiliation.append( + User_affiliations( + permission="super_admin", + user_organization=Organizations( + acronym="SA", org_tags={"name": "SA"}, name="Super Admin" + ), + ) + ) + + save(sa_user) + + token = tokenize(user_id=sa_user.id, roles=sa_user.roles) + + result = Client(schema).execute( + """ + mutation { + created_org:createOrganization( + name: "Super Admin" + acronym: "SA" + zone: "Test Zone" + sector: "Test Sector" + province: "Nova Scotia" + city: "Halifax" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "expected createOrganization to fail for an existing org. Instead: {}".format( + result + ) + ) + + +def test_mutation_createOrganization_as_super_user(save): + """ + Test To See If SA Can Create Organization + """ + sa_user = Users( + display_name="testsuperadmin", + user_name="testsuperadmin@testemail.ca", + password="testpassword123", + ) + sa_user.user_affiliation.append( + User_affiliations( + permission="super_admin", + user_organization=Organizations( + acronym="SA", org_tags={"name": "SA"}, name="Super Admin" + ), + ) + ) + + save(sa_user) + + token = tokenize(user_id=sa_user.id, roles=sa_user.roles) + + result = Client(schema).execute( + """ + mutation { + created_org:createOrganization( + name: "Test Organization" + acronym: "TEST_ORG" + zone: "Test Zone" + sector: "Test Sector" + province: "Nova Scotia" + city: "Halifax" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" in result: + fail( + "expected createOrganization to succeed for super admin. Instead: {}".format( + result + ) + ) + + created_org = result["data"].values() + [status] = created_org + + assert status == {"status": True} + + +def test_mutation_createOrganization_fails_for_write_users(save): + write_user = Users( + display_name="writer", + user_name="writer@example.com", + password="testpassword123", + ) + + write_user.user_affiliation.append( + User_affiliations( + permission="user_write", + user_organization=Organizations(acronym="ORG1", name="Org One"), + ) + ) + + save(write_user) + + token = tokenize(user_id=write_user.id, roles=write_user.roles) + + result = Client(schema).execute( + """ + mutation { + createOrganization( + acronym: "USER_W_NEW" + name: "Test Organization" + zone: "Test Zone" + sector: "Test Sector" + province: "Nova Scotia" + city: "Halifax" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "expected createOrganization to fail for user_write users. Instead: {}".format( + result + ) + ) + + errors, data = result.values() + [first] = errors + message, _, _ = first.values() + assert message == "Error, you do not have permission to create organizations" + + +def test_mutation_createOrganization_fails_for_admin_users(save): + admin = Users( + display_name="admin", user_name="admin@example.com", password="testpassword123", + ) + + save(admin) + + token = tokenize(user_id=admin.id, roles=admin.roles) + + result = Client(schema).execute( + """ + mutation { + createOrganization( + name: "New thing" + acronym: "NEW" + zone: "Test Zone" + sector: "Test Sector" + province: "Nova Scotia" + city: "Halifax" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "expected createOrganization to fail for admins. Instead: {}".format(result) + ) + + errors, data = result.values() + [first] = errors + message, _, _ = first.values() + assert message == "Error, you do not have permission to create organizations" + + +def test_mutation_createOrganization_fails_for_read_users(save): + reader = Users( + display_name="reader", + user_name="reader@example.com", + password="testpassword123", + ) + + reader.user_affiliation.append( + User_affiliations( + permission="user_read", + user_organization=Organizations(acronym="ORG1", name="Org One"), + ) + ) + + save(reader) + + token = tokenize(user_id=reader.id, roles=reader.roles) + + result = Client(schema).execute( + """ + mutation { + createOrganization( + acronym: "USER_R_NEW" + name: "Test Organization" + zone: "Test Zone" + sector: "Test Sector" + province: "Nova Scotia" + city: "Halifax" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "expected createOrganization to fail for read users. Instead: {}".format( + result + ) + ) + + errors, data = result.values() + [first] = errors + message, _, _ = first.values() + assert message == "Error, you do not have permission to create organizations" + + +def test_mutation_createOrganization_fails_for_admin_users(save): + admin = Users( + display_name="admin", user_name="admin@example.com", password="testpassword123", + ) + + save(admin) + + token = tokenize(user_id=admin.id, roles=admin.roles) + + result = Client(schema).execute( + """ + mutation { + createOrganization( + name: "New thing" + acronym: "NEW" + zone: "Test Zone" + sector: "Test Sector" + province: "Nova Scotia" + city: "Halifax" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "expected createOrganization to fail for admins. Instead: {}".format(result) + ) + + errors, data = result.values() + [first] = errors + message, _, _ = first.values() + assert message == "Error, you do not have permission to create organizations" diff --git a/api/tests/test_db_migrate.py b/api/tests/test_db_migrate.py deleted file mode 100644 index 152c746f81..0000000000 --- a/api/tests/test_db_migrate.py +++ /dev/null @@ -1,22 +0,0 @@ -import sys -import os -from os.path import dirname, join, expanduser, normpath, realpath -import pytest -from sqlalchemy import create_engine -from manage import * -from db import db_session, Base, engine - -class TestDBCreation: - def test_created_schema_contains_expected_tables(self): - """This test determines that the postgres db is created with the expected tables""" - # Arrange - tables = set() - - # Act - tables.add("alembic_version") - - for key in Base.metadata.tables.keys(): - tables.add(key) - - # Assert - assert tables == set(engine.table_names()) diff --git a/api/tests/test_depth_check.py b/api/tests/test_depth_check.py index e6184763e0..8daca23bb2 100644 --- a/api/tests/test_depth_check.py +++ b/api/tests/test_depth_check.py @@ -2,102 +2,100 @@ from flask import Request import pytest from graphene.test import Client -from unittest import TestCase from app import app -from db import db_session +from db import DB from queries import schema from models import Users from backend.security_check import SecurityAnalysisBackend -@pytest.fixture(scope="class") -def user_schema_test_db_init(): +@pytest.fixture +def save(): with app.app_context(): - test_super_admin = Users( - id=2, - display_name="testsuperadmin", - user_name="testsuperadmin@testemail.ca", - password="testpassword123", - ) - db_session.add(test_super_admin) - db_session.commit() + save, cleanup, _ = DB() + yield save + cleanup() - yield - with app.app_context(): - Users.query.delete() - db_session.commit() +def test_valid_depth_query(save): + test_super_admin = Users( + display_name="testsuperadmin", + user_name="testsuperadmin@testemail.ca", + password="testpassword123", + ) + save(test_super_admin) + backend = SecurityAnalysisBackend() + client = Client(schema) + get_token = client.execute( + """ + mutation{ + signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ + authToken + } + } + """, + backend=backend, + ) -## -# This class of tests works within the 'createUser' api endpoint -@pytest.mark.usefixtures("user_schema_test_db_init") -class TestDepthCheck(TestCase): - def test_valid_depth_query(self): - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None + assert get_token["data"]["signIn"]["authToken"] is not None + token = get_token["data"]["signIn"]["authToken"] + assert token is not None - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) + environ = create_environ() + environ.update(HTTP_AUTHORIZATION=token) + request_headers = Request(environ) - query = client.execute( - """ - { - user { - displayName - } - } - """, - context_value=request_headers, - backend=backend, - ) - result_refr = {"data": {"user": [{"displayName": "testsuperadmin"}]}} - self.assertDictEqual(result_refr, query) + results = client.execute( + """ + { + user { + displayName + } + } + """, + context_value=request_headers, + backend=backend, + ) + user = results["data"].values() + [[details]] = user + assert details == {"displayName": "testsuperadmin"} + + +def test_invalid_depth_query(save): + test_super_admin = Users( + display_name="testsuperadmin", + user_name="testsuperadmin@testemail.ca", + password="testpassword123", + ) + save(test_super_admin) - def test_invalid_depth_query(self): - backend = SecurityAnalysisBackend(10) - client = Client(schema) - executed = client.execute( - """ - { - getSectorById(id: 1) { - groups{ - edges{ - node{ - groupSector{ - groups{ - edges{ - node{ - groupSector{ - groups{ - edges{ - node{ - groupSector{ - groups{ - edges{ - node{ - groupSector{ - groups{ - edges{ - node{ - groupSector - } - } + backend = SecurityAnalysisBackend(10) + client = Client(schema) + executed = client.execute( + """ + { + getSectorById(id: 1) { + groups{ + edges{ + node{ + groupSector{ + groups{ + edges{ + node{ + groupSector{ + groups{ + edges{ + node{ + groupSector{ + groups{ + edges{ + node{ + groupSector{ + groups{ + edges{ + node{ + groupSector } } } @@ -117,9 +115,11 @@ def test_invalid_depth_query(self): } } } - """, - backend=backend, - ) - assert executed["errors"] - assert executed["errors"][0] - assert executed["errors"][0]["message"] == "Query is too complex" + } + } + """, + backend=backend, + ) + assert executed["errors"] + assert executed["errors"][0] + assert executed["errors"][0]["message"] == "Query is too complex" diff --git a/api/tests/test_dmarc_reports.py b/api/tests/test_dmarc_reports.py new file mode 100644 index 0000000000..39fd898968 --- /dev/null +++ b/api/tests/test_dmarc_reports.py @@ -0,0 +1,20 @@ +from pytest import fail +from app import app +from sqlalchemy import exc +from db import db_session +from models import ( + Dmarc_Reports, +) + +def test_should_save_without_raising_an_error(): + with app.app_context(): + try: + report = Dmarc_Reports( + start_date="2018-10-01 13:07:12", + end_date="2018-10-01 13:07:12", + report={}, + ) + db_session.add(report) + db_session.commit() + except exc.IntegrityError: + fail("Saving Dmarc_Reports model instance failed") diff --git a/api/tests/test_domains_mutations.py b/api/tests/test_domains_mutations.py index 3873eb2d7d..2ad1b27546 100644 --- a/api/tests/test_domains_mutations.py +++ b/api/tests/test_domains_mutations.py @@ -6,7 +6,7 @@ from app import app from queries import schema from backend.security_check import SecurityAnalysisBackend -from db import db_session +from db import DB from models import ( Organizations, Domains, @@ -21,206 +21,194 @@ Ssl_scans, ) +save, cleanup, session = DB() @pytest.fixture(scope="class") def domain_test_db_init(): with app.app_context(): + org1 = Organizations(acronym="ORG1") + org2 = Organizations(acronym="ORG2") + save(org1) + save(org2) + test_read = Users( - id=1, display_name="testuserread", user_name="testuserread@testemail.ca", password="testpassword123", + user_affiliation=[ + User_affiliations( + user_organization=org1, permission="user_read" + ) + ] ) - db_session.add(test_read) + save(test_read) test_super_admin = Users( - id=2, display_name="testsuperadmin", user_name="testsuperadmin@testemail.ca", password="testpassword123", + user_affiliation=[ + User_affiliations( + user_organization=org2, permission="super_admin" + ) + ] ) - db_session.add(test_super_admin) + save(test_super_admin) test_admin = Users( - id=3, display_name="testadmin", user_name="testadmin@testemail.ca", password="testpassword123", + user_affiliation=[ + User_affiliations( + user_organization=org1, permission="admin" + ) + ] ) - db_session.add(test_admin) - test_admin = Users( - id=4, + save(test_admin) + test_admin2 = Users( display_name="testadmin2", user_name="testadmin2@testemail.ca", password="testpassword123", + user_affiliation=[ + User_affiliations( + user_organization=org2, permission="admin" + ) + ] ) - db_session.add(test_admin) + save(test_admin2) test_write = Users( - id=5, display_name="testuserwrite", user_name="testuserwrite@testemail.ca", password="testpassword123", + user_affiliation=[ + User_affiliations( + user_organization=org1, permission="user_write" + ) + ] ) - db_session.add(test_write) + save(test_write) test_write2 = Users( - id=6, display_name="testuserwrite2", user_name="testuserwrite2@testemail.ca", password="testpassword123", + user_affiliation=[ + User_affiliations( + user_organization=org2, permission="user_write" + ) + ] ) - db_session.add(test_write2) + save(test_write2) - org = Organizations(id=1, acronym="ORG1") - db_session.add(org) - org = Organizations(id=2, acronym="ORG2") - db_session.add(org) - test_user_read_role = User_affiliations( - user_id=1, organization_id=1, permission="user_read" - ) - db_session.add(test_user_read_role) - test_super_admin_role = User_affiliations( - user_id=2, organization_id=2, permission="super_admin" - ) - db_session.add(test_super_admin_role) - test_admin_role = User_affiliations( - user_id=3, organization_id=1, permission="admin" - ) - db_session.add(test_admin_role) - test_admin_role = User_affiliations( - user_id=4, organization_id=2, permission="admin" - ) - db_session.add(test_admin_role) - test_user_write_role = User_affiliations( - user_id=5, organization_id=1, permission="user_write" - ) - db_session.add(test_user_write_role) - test_user_write_role_2 = User_affiliations( - user_id=6, organization_id=2, permission="user_write" - ) - db_session.add(test_user_write_role_2) - - sa_update_domain = Domains(domain="sa.update.domain.ca", organization_id=1) - db_session.add(sa_update_domain) - sa_remove_domain = Domains(domain="sa.remove.domain.ca", organization_id=1) - db_session.add(sa_remove_domain) + sa_update_domain = Domains(domain="sa.update.domain.ca", organization_id=org1.id) + session.add(sa_update_domain) + sa_remove_domain = Domains(domain="sa.remove.domain.ca", organization_id=org1.id) + session.add(sa_remove_domain) org_admin_update_domain = Domains( - domain="admin.update.domain.ca", organization_id=1 + domain="admin.update.domain.ca", organization_id=org1.id ) - db_session.add(org_admin_update_domain) - org_admin_domain = Domains(domain="admin.remove.domain.ca", organization_id=1) - db_session.add(org_admin_domain) + session.add(org_admin_update_domain) + org_admin_domain = Domains(domain="admin.remove.domain.ca", organization_id=org1.id) + session.add(org_admin_domain) org_admin_update_domain2 = Domains( - domain="admin2.update.domain.ca", organization_id=1 + domain="admin2.update.domain.ca", organization_id=org1.id ) - db_session.add(org_admin_update_domain2) - org_admin_domain2 = Domains(domain="admin2.remove.domain.ca", organization_id=1) - db_session.add(org_admin_domain2) + session.add(org_admin_update_domain2) + org_admin_domain2 = Domains(domain="admin2.remove.domain.ca", organization_id=org1.id) + session.add(org_admin_domain2) user_write_update_domain = Domains( - domain="user.write.update.domain.ca", organization_id=1 + domain="user.write.update.domain.ca", organization_id=org1.id ) - db_session.add(user_write_update_domain) + session.add(user_write_update_domain) user_write_domain = Domains( - domain="user.write.remove.domain.ca", organization_id=1 + domain="user.write.remove.domain.ca", organization_id=org1.id ) - db_session.add(user_write_domain) + session.add(user_write_domain) user_write_update_domain_2 = Domains( - domain="user2.write.update.domain.ca", organization_id=1 + domain="user2.write.update.domain.ca", organization_id=org1.id ) - db_session.add(user_write_update_domain_2) + session.add(user_write_update_domain_2) user_write_domain_2 = Domains( - domain="user2.write.remove.domain.ca", organization_id=1 + domain="user2.write.remove.domain.ca", organization_id=org1.id ) - db_session.add(user_write_domain_2) + session.add(user_write_domain_2) user_read_update_domain = Domains( - domain="user.read.update.domain.ca", organization_id=1 + domain="user.read.update.domain.ca", organization_id=org1.id ) - db_session.add(user_read_update_domain) + session.add(user_read_update_domain) user_read_domain = Domains( - domain="user.read.remove.domain.ca", organization_id=1 + domain="user.read.remove.domain.ca", organization_id=org1.id ) - db_session.add(user_read_domain) - db_session.commit() + session.add(user_read_domain) + session.commit() # Super Admin Scans domain_id = ( - db_session.query(Domains) + session.query(Domains) .filter(Domains.domain == "sa.remove.domain.ca") .first() .id ) - sa_scan = Scans(id=1, domain_id=domain_id) - db_session.add(sa_scan) - db_session.commit() - sa_dkim = Dkim_scans(id=1) - db_session.add(sa_dkim) - sa_dmarc = Dmarc_scans(id=1) - db_session.add(sa_dmarc) - sa_https = Https_scans(id=1) - db_session.add(sa_https) - sa_ssl = Ssl_scans(id=1) - db_session.add(sa_ssl) - sa_spf = Spf_scans(id=1) - db_session.add(sa_spf) - db_session.commit() + sa_scan = Scans(domain_id=domain_id) + save(sa_scan) + sa_dkim = Dkim_scans(id=sa_scan.id) + session.add(sa_dkim) + sa_dmarc = Dmarc_scans(id=sa_scan.id) + session.add(sa_dmarc) + sa_https = Https_scans(id=sa_scan.id) + session.add(sa_https) + sa_ssl = Ssl_scans(id=sa_scan.id) + session.add(sa_ssl) + sa_spf = Spf_scans(id=sa_scan.id) + session.add(sa_spf) + session.commit() # Admin Scans domain_id = ( - db_session.query(Domains) + session.query(Domains) .filter(Domains.domain == "admin.remove.domain.ca") .first() .id ) - admin_scan = Scans(id=2, domain_id=domain_id) - db_session.add(admin_scan) - db_session.commit() - admin_dkim = Dkim_scans(id=2) - db_session.add(admin_dkim) - admin_dmarc = Dmarc_scans(id=2) - db_session.add(admin_dmarc) - admin_https = Https_scans(id=2) - db_session.add(admin_https) - admin_ssl = Ssl_scans(id=2) - db_session.add(admin_ssl) - admin_spf = Spf_scans(id=2) - db_session.add(admin_spf) - db_session.commit() + admin_scan = Scans(domain_id=domain_id) + session.add(admin_scan) + session.commit() + admin_dkim = Dkim_scans(id=admin_scan.id) + session.add(admin_dkim) + admin_dmarc = Dmarc_scans(id=admin_scan.id) + session.add(admin_dmarc) + admin_https = Https_scans(id=admin_scan.id) + session.add(admin_https) + admin_ssl = Ssl_scans(id=admin_scan.id) + session.add(admin_ssl) + admin_spf = Spf_scans(id=admin_scan.id) + session.add(admin_spf) + session.commit() # User Write Scans domain_id = ( - db_session.query(Domains) + session.query(Domains) .filter(Domains.domain == "user.write.remove.domain.ca") .first() .id ) - user_w_scan = Scans(id=3, domain_id=domain_id) - db_session.add(user_w_scan) - db_session.commit() - user_w_dkim = Dkim_scans(id=3) - db_session.add(user_w_dkim) - user_w_dmarc = Dmarc_scans(id=3) - db_session.add(user_w_dmarc) - user_w_https = Https_scans(id=3) - db_session.add(user_w_https) - user_w_ssl = Ssl_scans(id=3) - db_session.add(user_w_ssl) - user_w_spf = Spf_scans(id=3) - db_session.add(user_w_spf) - db_session.commit() - - yield + user_w_scan = Scans(domain_id=domain_id) + session.add(user_w_scan) + session.commit() + user_w_dkim = Dkim_scans(id=user_w_scan.id) + session.add(user_w_dkim) + user_w_dmarc = Dmarc_scans(id=user_w_scan.id) + session.add(user_w_dmarc) + user_w_https = Https_scans(id=user_w_scan.id) + session.add(user_w_https) + user_w_ssl = Ssl_scans(id=user_w_scan.id) + session.add(user_w_ssl) + user_w_spf = Spf_scans(id=user_w_scan.id) + session.add(user_w_spf) + session.commit() + + yield + cleanup() - with app.app_context(): - Ssl_scans.query.delete() - Spf_scans.query.delete() - Mx_scans.query.delete() - Https_scans.query.delete() - Dmarc_scans.query.delete() - Dkim_scans.query.delete() - Scans.query.delete() - Domains.query.delete() - User_affiliations.query.delete() - Organizations.query.delete() - Users.query.delete() - db_session.commit() @pytest.mark.usefixtures("domain_test_db_init") @@ -378,17 +366,17 @@ def test_domain_removal_super_admin(self): assert executed["data"]["removeDomain"]["status"] assert ( - not db_session.query(Domains) + not session.query(Domains) .filter(Domains.domain == "sa.remove.domain.ca") .all() ) - assert not db_session.query(Scans).filter(Scans.id == 1).all() - assert not db_session.query(Dkim_scans).filter(Dkim_scans.id == 1).all() - assert not db_session.query(Dmarc_scans).filter(Dmarc_scans.id == 1).all() - assert not db_session.query(Https_scans).filter(Https_scans.id == 1).all() - assert not db_session.query(Mx_scans).filter(Mx_scans.id == 1).all() - assert not db_session.query(Ssl_scans).filter(Ssl_scans.id == 1).all() - assert not db_session.query(Spf_scans).filter(Spf_scans.id == 1).all() + assert not session.query(Scans).filter(Scans.id == 1).all() + assert not session.query(Dkim_scans).filter(Dkim_scans.id == 1).all() + assert not session.query(Dmarc_scans).filter(Dmarc_scans.id == 1).all() + assert not session.query(Https_scans).filter(Https_scans.id == 1).all() + assert not session.query(Mx_scans).filter(Mx_scans.id == 1).all() + assert not session.query(Ssl_scans).filter(Ssl_scans.id == 1).all() + assert not session.query(Spf_scans).filter(Spf_scans.id == 1).all() def test_domain_creation_super_admin_acronym_sa(self): """ @@ -588,17 +576,17 @@ def test_domain_removal_org_admin(self): assert executed["data"]["removeDomain"]["status"] assert ( - not db_session.query(Domains) + not session.query(Domains) .filter(Domains.domain == "admin.remove.domain.ca") .all() ) - assert not db_session.query(Scans).filter(Scans.id == 2).all() - assert not db_session.query(Dkim_scans).filter(Dkim_scans.id == 2).all() - assert not db_session.query(Dmarc_scans).filter(Dmarc_scans.id == 2).all() - assert not db_session.query(Https_scans).filter(Https_scans.id == 2).all() - assert not db_session.query(Mx_scans).filter(Mx_scans.id == 2).all() - assert not db_session.query(Ssl_scans).filter(Ssl_scans.id == 2).all() - assert not db_session.query(Spf_scans).filter(Spf_scans.id == 2).all() + assert not session.query(Scans).filter(Scans.id == 2).all() + assert not session.query(Dkim_scans).filter(Dkim_scans.id == 2).all() + assert not session.query(Dmarc_scans).filter(Dmarc_scans.id == 2).all() + assert not session.query(Https_scans).filter(Https_scans.id == 2).all() + assert not session.query(Mx_scans).filter(Mx_scans.id == 2).all() + assert not session.query(Ssl_scans).filter(Ssl_scans.id == 2).all() + assert not session.query(Spf_scans).filter(Spf_scans.id == 2).all() # Different Org Admin def test_domain_creation_diff_org_admin(self): @@ -786,7 +774,7 @@ def test_domain_creation_user_write(self): backend=backend, ) result_refr = {"data": {"domain": [{"url": "user.write.create.domain.ca"}]}} - self.assertDictEqual(result_refr, executed) + assert result_refr == executed def test_domain_modification_user_write(self): """ @@ -904,17 +892,17 @@ def test_domain_removal_user_write(self): assert executed["errors"][0]["message"] == "Error, domain does not exist" assert ( - not db_session.query(Domains) + not session.query(Domains) .filter(Domains.domain == "user.write.remove.domain.ca") .all() ) - assert not db_session.query(Scans).filter(Scans.id == 3).all() - assert not db_session.query(Dkim_scans).filter(Dkim_scans.id == 3).all() - assert not db_session.query(Dmarc_scans).filter(Dmarc_scans.id == 3).all() - assert not db_session.query(Https_scans).filter(Https_scans.id == 3).all() - assert not db_session.query(Mx_scans).filter(Mx_scans.id == 3).all() - assert not db_session.query(Ssl_scans).filter(Ssl_scans.id == 3).all() - assert not db_session.query(Spf_scans).filter(Spf_scans.id == 3).all() + assert not session.query(Scans).filter(Scans.id == 3).all() + assert not session.query(Dkim_scans).filter(Dkim_scans.id == 3).all() + assert not session.query(Dmarc_scans).filter(Dmarc_scans.id == 3).all() + assert not session.query(Https_scans).filter(Https_scans.id == 3).all() + assert not session.query(Mx_scans).filter(Mx_scans.id == 3).all() + assert not session.query(Ssl_scans).filter(Ssl_scans.id == 3).all() + assert not session.query(Spf_scans).filter(Spf_scans.id == 3).all() # Different Org User Write def test_domain_creation_diff_org_user_write(self): diff --git a/api/tests/test_domains_resolver_access_control.py b/api/tests/test_domains_resolver_access_control.py index 4ffd527dca..b35ea0e9ea 100644 --- a/api/tests/test_domains_resolver_access_control.py +++ b/api/tests/test_domains_resolver_access_control.py @@ -4,11 +4,12 @@ from unittest import TestCase from werkzeug.test import create_environ from app import app -from db import db_session +from db import DB from models import Organizations, Domains, Users, User_affiliations from queries import schema from backend.security_check import SecurityAnalysisBackend +_, cleanup, db_session = DB() @pytest.fixture(scope="class") def domain_test_db_init(): @@ -58,14 +59,9 @@ def domain_test_db_init(): db_session.add(domain) db_session.commit() - yield + yield - with app.app_context(): - Domains.query.delete() - User_affiliations.query.delete() - Organizations.query.delete() - Users.query.delete() - db_session.commit() + cleanup() @pytest.mark.usefixtures("domain_test_db_init") diff --git a/api/tests/test_domains_resolver_values.py b/api/tests/test_domains_resolver_values.py index e1bcfa9067..9bc348351c 100644 --- a/api/tests/test_domains_resolver_values.py +++ b/api/tests/test_domains_resolver_values.py @@ -1,12 +1,11 @@ import pytest +from pytest import fail +from json_web_token import tokenize, auth_header from flask import Request from graphene.test import Client -from unittest import TestCase -from werkzeug.test import create_environ from app import app -from db import db_session +from db import DB from queries import schema -from backend.security_check import SecurityAnalysisBackend from models import ( Organizations, Domains, @@ -21,863 +20,418 @@ Spf_scans, Ssl_scans, ) +from tests.testdata import accurateplastics_report +s, cleanup, session = DB() -@pytest.fixture(scope="class") -def domain_test_db_init(): +@pytest.fixture +def save(): with app.app_context(): - test_user = Users( - id=1, - display_name="testuserread", - user_name="testuserread@testemail.ca", - password="testpassword123", - ) - db_session.add(test_user) + yield s + session.rollback() + cleanup() - org = Organizations( - id=1, acronym="ORG1", org_tags={"description": "Organization 1"} - ) - db_session.add(org) - test_user_read_role = User_affiliations( - user_id=1, organization_id=1, permission="user_read" - ) - db_session.add(test_user_read_role) - - domain = Domains(id=1, domain="accurateplastics.com", organization_id=1) - db_session.add(domain) - domain = Domains(id=2, domain="addisonfoods.com", organization_id=1) - db_session.add(domain) - - test_dmarc_report = Dmarc_Reports( - id=1, - domain_id=1, - start_date="2018-10-01 13:07:12", - end_date="2018-10-01 13:07:12", - report={ - "xml_schema": "draft", - "report_metadata": { - "org_name": "accurateplastics.com", - "org_email": "administrator@accurateplastics.com", - "org_extra_contact_info": "null", - "report_id": "example.com:1538463741", - "begin_date": "2018-10-01 13:07:12", - "end_date": "2018-10-01 13:07:12", - "errors": [ - "Invalid XML: not well-formed (invalid token): line 5, column 17" - ], - }, - "policy_published": { - "domain": "example.com", - "adkim": "r", - "aspf": "r", - "p": "none", - "sp": "reject", - "pct": "100", - "fo": "0", - }, - "records": [ - { - "source": { - "ip_address": "12.20.127.122", - "country": "US", - "reverse_dns": "null", - "base_domain": "null", - }, - "count": 1, - "alignment": {"spf": False, "dkim": False, "dmarc": False}, - "policy_evaluated": { - "disposition": "none", - "dkim": "fail", - "spf": "fail", - "policy_override_reasons": ["TESTING TEXT"], - }, - "identifiers": { - "header_from": "example.com", - "envelope_from": "null", - "envelope_to": "null", - }, - "auth_results": { - "dkim": [ - { - "domain": "toptierhighticket.club", - "selector": "default", - "result": "pass", - } - ], - "spf": [ - {"domain": "null", "scope": "mfrom", "result": "none"} +def test_get_domain_resolver_dmarc_report(save): + """ + Test to see if all values appear + """ + user = Users( + display_name="testuserread", + user_name="testuserread@testemail.ca", + password="testpassword123", + user_affiliation=[ + User_affiliations( + permission="user_read", + user_organization=Organizations( + acronym="ORG1", + domains=[ + Domains( + domain="accurateplastics.com", + dmarc_reports=[ + Dmarc_Reports( + start_date="2018-10-01 13:07:12", + end_date="2018-10-01 13:07:12", + report=accurateplastics_report, + ) ], - }, - } - ], - }, - ) - db_session.add(test_dmarc_report) - db_session.commit() + ), + Domains(domain="addisonfoods.com"), + ], + ), + ) + ], + ) + save(user) - yield + token = tokenize(user_id=user.id, roles=user.roles) - with app.app_context(): - Dkim_scans.query.delete() - Dmarc_scans.query.delete() - Https_scans.query.delete() - Mx_scans.query.delete() - Spf_scans.query.delete() - Ssl_scans.query.delete() - Scans.query.delete() - Dmarc_Reports.query.delete() - Domains.query.delete() - User_affiliations.query.delete() - Organizations.query.delete() - Users.query.delete() - db_session.commit() - - -@pytest.mark.usefixtures("domain_test_db_init") -class TestDomainsResolver(TestCase): - def test_get_domain_resolver_dmarc_report(self): - """ - Test to see if all values appear + result = Client(schema).execute( """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ - authToken + { + domain(url: "accurateplastics.com") { + url + dmarcReport { + edges { + node { + reportId + orgName + orgEmail + startDate + endDate + } } } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None + } + } + """, + context_value=auth_header(token), + ) - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) + if "errors" in result: + fail("Expected dmarcReport query to succeed. Instead: {}".format(result)) - executed = client.execute( - """ + expected = { + "data": { + "domain": [ { - domain(url: "accurateplastics.com") { - url - dmarcReport { - edges { - node { - reportId - orgName - orgEmail - startDate - endDate - errors - policyPublished { - domain - adkim - p - sp - pct - fo - } - records { - count - source { - ipAddress - country - reverseDns - baseDomain - } - alignment { - spf - dkim - dmarc - } - policyEvaluated { - disposition - dkim - spf - policyOverrideReasons - } - identifiers { - headerFrom - envelopeFrom - envelopeTo - } - authResults { - dkim { - domain - selector - result - } - spf { - domain - scope - result - } - } - } + "url": "accurateplastics.com", + "dmarcReport": { + "edges": [ + { + "node": { + "reportId": "example.com:1538463741", + "orgName": "accurateplastics.com", + "orgEmail": "administrator@accurateplastics.com", + "startDate": "2018-10-01T13:07:12", + "endDate": "2018-10-01T13:07:12", } } - } - } + ] + }, } - """, - context_value=request_headers, - backend=backend, + ] + } + } + assert expected == result + + +def test_get_domain_resolver_dmarc_report_in_date_range(save): + """ + Test to see if all values appear + """ + user = Users( + display_name="testuserread", + user_name="testuserread@testemail.ca", + password="testpassword123", + user_affiliation=[ + User_affiliations( + permission="user_read", + user_organization=Organizations( + acronym="ORG1", + domains=[ + Domains( + domain="accurateplastics.com", + dmarc_reports=[ + Dmarc_Reports( + start_date="2018-10-01 13:07:12", + end_date="2018-10-01 13:07:12", + report=accurateplastics_report, + ) + ], + ), + ], + ), ) - result_refr = { - "data": { - "domain": [ - { - "url": "accurateplastics.com", - "dmarcReport": { - "edges": [ - { - "node": { - "reportId": "example.com:1538463741", - "orgName": "accurateplastics.com", - "orgEmail": "administrator@accurateplastics.com", - "startDate": "2018-10-01T13:07:12", - "endDate": "2018-10-01T13:07:12", - "errors": [ - "Invalid XML: not well-formed (invalid token): line 5, column 17" - ], - "policyPublished": { - "domain": "example.com", - "adkim": "r", - "p": "none", - "sp": "reject", - "pct": 100, - "fo": 0, - }, - "records": [ - { - "count": 1, - "source": { - "ipAddress": "12.20.127.122", - "country": "US", - "reverseDns": "null", - "baseDomain": "null", - }, - "alignment": { - "spf": False, - "dkim": False, - "dmarc": False, - }, - "policyEvaluated": { - "disposition": "none", - "dkim": "fail", - "spf": "fail", - "policyOverrideReasons": [ - "TESTING TEXT" - ], - }, - "identifiers": { - "headerFrom": "example.com", - "envelopeFrom": "null", - "envelopeTo": "null", - }, - "authResults": { - "dkim": [ - { - "domain": "toptierhighticket.club", - "selector": "default", - "result": "pass", - } - ], - "spf": [ - { - "domain": "null", - "scope": "mfrom", - "result": "none", - } - ], - }, - } - ], - } - } - ] - }, - } - ] - } - } - self.assertDictEqual(result_refr, executed) + ], + ) + save(user) - def test_get_domain_resolver_dmarc_report_in_date_range(self): - """ - Test to see if all values appear within the date range + token = tokenize(user_id=user.id, roles=user.roles) + + result = Client(schema).execute( """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None + { + domain(url: "accurateplastics.com") { + url + dmarcReport(startDate: "2018-01-01" endDate: "2018-12-31") { + edges { + node { + reportId + orgName + orgEmail + startDate + endDate + } + } + } + } + } + """, + context_value=auth_header(token), + ) - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) + if "errors" in result: + fail("Expected dmarcReport query to succeed. Instead: {}".format(result)) - executed = client.execute( - """ + expected = { + "data": { + "domain": [ { - domain(url: "accurateplastics.com") { - url - dmarcReport(startDate: "2018-01-01" endDate: "2018-12-31") { - edges { - node { - reportId - orgName - orgEmail - startDate - endDate - errors - policyPublished { - domain - adkim - p - sp - pct - fo - } - records { - count - source { - ipAddress - country - reverseDns - baseDomain - } - alignment { - spf - dkim - dmarc - } - policyEvaluated { - disposition - dkim - spf - policyOverrideReasons - } - identifiers { - headerFrom - envelopeFrom - envelopeTo - } - authResults { - dkim { - domain - selector - result - } - spf { - domain - scope - result - } - } - } + "url": "accurateplastics.com", + "dmarcReport": { + "edges": [ + { + "node": { + "reportId": "example.com:1538463741", + "orgName": "accurateplastics.com", + "orgEmail": "administrator@accurateplastics.com", + "startDate": "2018-10-01T13:07:12", + "endDate": "2018-10-01T13:07:12", } } - } - } + ] + }, } - """, - context_value=request_headers, - backend=backend, + ] + } + } + assert expected == result + + +def test_get_domain_resolver_dmarc_report_for_date_range_with_no_reports(save): + user = Users( + display_name="testuserread", + user_name="testuserread@testemail.ca", + password="testpassword123", + user_affiliation=[ + User_affiliations( + permission="user_read", + user_organization=Organizations( + acronym="ORG1", + domains=[ + Domains( + domain="accurateplastics.com", + dmarc_reports=[ + Dmarc_Reports( + start_date="2018-10-01 13:07:12", + end_date="2018-10-01 13:07:12", + report=accurateplastics_report, + ) + ], + ), + ], + ), ) - result_refr = { - "data": { - "domain": [ - { - "url": "accurateplastics.com", - "dmarcReport": { - "edges": [ - { - "node": { - "reportId": "example.com:1538463741", - "orgName": "accurateplastics.com", - "orgEmail": "administrator@accurateplastics.com", - "startDate": "2018-10-01T13:07:12", - "endDate": "2018-10-01T13:07:12", - "errors": [ - "Invalid XML: not well-formed (invalid token): line 5, column 17" - ], - "policyPublished": { - "domain": "example.com", - "adkim": "r", - "p": "none", - "sp": "reject", - "pct": 100, - "fo": 0, - }, - "records": [ - { - "count": 1, - "source": { - "ipAddress": "12.20.127.122", - "country": "US", - "reverseDns": "null", - "baseDomain": "null", - }, - "alignment": { - "spf": False, - "dkim": False, - "dmarc": False, - }, - "policyEvaluated": { - "disposition": "none", - "dkim": "fail", - "spf": "fail", - "policyOverrideReasons": [ - "TESTING TEXT" - ], - }, - "identifiers": { - "headerFrom": "example.com", - "envelopeFrom": "null", - "envelopeTo": "null", - }, - "authResults": { - "dkim": [ - { - "domain": "toptierhighticket.club", - "selector": "default", - "result": "pass", - } - ], - "spf": [ - { - "domain": "null", - "scope": "mfrom", - "result": "none", - } - ], - }, - } - ], - } - } - ] - }, - } - ] - } - } - self.assertDictEqual(result_refr, executed) + ], + ) + save(user) - def test_get_domain_resolver_dmarc_report_out_of_date_range(self): - """ - Test to see if no values appear out of date range + token = tokenize(user_id=user.id, roles=user.roles) + + result = Client(schema).execute( """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, + { + domain(url: "accurateplastics.com") { + url + dmarcReport(startDate: "2019-01-01" endDate: "2019-12-31") { + edges { + node { + reportId + orgName + orgEmail + startDate + endDate + } + } + } + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "Expected dmarcReport query for report dates we don't have to fail. Instead: {}".format( + result ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None + ) - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - executed = client.execute( - """ - { - domain(url: "accurateplastics.com") { - url - dmarcReport(startDate: "2019-01-01" endDate: "2019-12-31") { - edges { - node { - reportId - orgName - orgEmail - startDate - endDate - errors - policyPublished { - domain - adkim - p - sp - pct - fo - } - records { - count - source { - ipAddress - country - reverseDns - baseDomain - } - alignment { - spf - dkim - dmarc - } - policyEvaluated { - disposition - dkim - spf - policyOverrideReasons - } - identifiers { - headerFrom - envelopeFrom - envelopeTo - } - authResults { - dkim { - domain - selector - result - } - spf { - domain - scope - result - } - } - } - } - } - } - } - } - """, - context_value=request_headers, - backend=backend, - ) - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, no reports for that domain in that date range." +def test_domain_resolver_dmarc_report_for_domain_with_no_reports_will_fail(save): + user = Users( + display_name="testuserread", + user_name="testuserread@testemail.ca", + password="testpassword123", + user_affiliation=[ + User_affiliations( + permission="user_read", + user_organization=Organizations( + acronym="ORG1", domains=[Domains(domain="addisonfoods.com"),], + ), ) + ], + ) + save(user) - def test_get_domain_resolver_dmarc_report_domain_missing_report(self): - """ - Test to see if no values appear out when domain has no report + token = tokenize(user_id=user.id, roles=user.roles) + + result = Client(schema).execute( """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, + { + domain(url: "addisonfoods.com") { + url + dmarcReport { + edges { + node { + reportId + orgName + orgEmail + startDate + endDate + } + } + } + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "Expected dmarcReport query for report dates we don't have to fail. Instead: {}".format( + result ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None + ) - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) + [error] = result["errors"] + assert error["message"] == "Error, no reports for that domain." - executed = client.execute( - """ - { - domain(url: "addisonfoods.com") { - url - dmarcReport { - edges { - node { - reportId - orgName - orgEmail - startDate - endDate - errors - policyPublished { - domain - adkim - p - sp - pct - fo - } - records { - count - source { - ipAddress - country - reverseDns - baseDomain - } - alignment { - spf - dkim - dmarc - } - policyEvaluated { - disposition - dkim - spf - policyOverrideReasons - } - identifiers { - headerFrom - envelopeFrom - envelopeTo - } - authResults { - dkim { - domain - selector - result - } - spf { - domain - scope - result - } - } - } - } - } - } - } - } - """, - context_value=request_headers, - backend=backend, - ) - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] == "Error, no reports for that domain." + +def test_get_domain_resolver_dmarc_report_returns_error_if_start_date_is_missing(save): + user = Users( + display_name="testuserread", + user_name="testuserread@testemail.ca", + password="testpassword123", + user_affiliation=[ + User_affiliations( + permission="user_read", + user_organization=Organizations( + acronym="ORG1", + domains=[ + Domains( + domain="accurateplastics.com", + dmarc_reports=[ + Dmarc_Reports( + start_date="2018-10-01 13:07:12", + end_date="2018-10-01 13:07:12", + report=accurateplastics_report, + ) + ], + ), + ], + ), ) + ], + ) + save(user) - def test_get_domain_resolver_dmarc_report_no_start_date(self): - """ - Test to see if no values appear when start date missing + token = tokenize(user_id=user.id, roles=user.roles) + + result = Client(schema).execute( """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, + { + domain(url: "accurateplastics.com") { + url + dmarcReport(endDate: "2019-12-31") { + edges { + node { + reportId + orgName + orgEmail + startDate + endDate + } + } + } + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "Expected dmarcReport query with no start date to fail. Instead: {}".format( + result ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None + ) - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) + [error] = result["errors"] + assert error["message"] == "Error, both start and end dates are required." - executed = client.execute( - """ - { - domain(url: "addisonfoods.com") { - url - dmarcReport(endDate: "2018-01-01") { - edges { - node { - reportId - orgName - orgEmail - startDate - endDate - errors - policyPublished { - domain - adkim - p - sp - pct - fo - } - records { - count - source { - ipAddress - country - reverseDns - baseDomain - } - alignment { - spf - dkim - dmarc - } - policyEvaluated { - disposition - dkim - spf - policyOverrideReasons - } - identifiers { - headerFrom - envelopeFrom - envelopeTo - } - authResults { - dkim { - domain - selector - result - } - spf { - domain - scope - result - } - } - } - } - } - } - } - } - """, - context_value=request_headers, - backend=backend, - ) - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, both start and end dates are required." - ) - def test_get_domain_resolver_dmarc_report_no_end_date(self): - """ - Test to see if no values appear when end date missing - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, +def test_get_domain_resolver_dmarc_report_returns_error_if_end_date_is_missing(save): + user = Users( + display_name="testuserread", + user_name="testuserread@testemail.ca", + password="testpassword123", + user_affiliation=[ + User_affiliations( + permission="user_read", + user_organization=Organizations( + acronym="ORG1", + domains=[ + Domains( + domain="accurateplastics.com", + dmarc_reports=[ + Dmarc_Reports( + start_date="2018-10-01 13:07:12", + end_date="2018-10-01 13:07:12", + report=accurateplastics_report, + ) + ], + ), + ], + ), ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None + ], + ) + save(user) - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) + token = tokenize(user_id=user.id, roles=user.roles) - executed = client.execute( - """ - { - domain(url: "addisonfoods.com") { - url - dmarcReport(startDate: "2018-01-01") { - edges { - node { - reportId - orgName - orgEmail - startDate - endDate - errors - policyPublished { - domain - adkim - p - sp - pct - fo - } - records { - count - source { - ipAddress - country - reverseDns - baseDomain - } - alignment { - spf - dkim - dmarc - } - policyEvaluated { - disposition - dkim - spf - policyOverrideReasons - } - identifiers { - headerFrom - envelopeFrom - envelopeTo - } - authResults { - dkim { - domain - selector - result - } - spf { - domain - scope - result - } - } - } - } - } - } - } - } - """, - context_value=request_headers, - backend=backend, - ) - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, both start and end dates are required." + result = Client(schema).execute( + """ + { + domain(url: "accurateplastics.com") { + url + dmarcReport(startDate: "2019-12-31") { + edges { + node { + reportId + orgName + orgEmail + startDate + endDate + } + } + } + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "Expected dmarcReport query with no start date to fail. Instead: {}".format( + result ) + ) + + [error] = result["errors"] + assert error["message"] == "Error, both start and end dates are required." diff --git a/api/tests/test_organization_mutations.py b/api/tests/test_organization_mutations.py deleted file mode 100644 index 52596f772f..0000000000 --- a/api/tests/test_organization_mutations.py +++ /dev/null @@ -1,1102 +0,0 @@ -import pytest -from flask import Request -from graphene.test import Client -from unittest import TestCase -from werkzeug.test import create_environ -from app import app -from db import db_session -from queries import schema -from backend.security_check import SecurityAnalysisBackend -from models import ( - Organizations, - Domains, - Users, - User_affiliations, - Scans, - Dkim_scans, - Dmarc_scans, - Https_scans, - Mx_scans, - Spf_scans, - Ssl_scans, -) - - -@pytest.fixture(scope="class") -def organization_mutation_db_init(): - with app.app_context(): - test_super_admin = Users( - id=1, - display_name="testsuperadmin", - user_name="testsuperadmin@testemail.ca", - password="testpassword123", - ) - db_session.add(test_super_admin) - test_admin = Users( - id=2, - display_name="testadmin", - user_name="testadmin@testemail.ca", - password="testpassword123", - ) - db_session.add(test_admin) - test_write = Users( - id=3, - display_name="testuserwrite", - user_name="testuserwrite@testemail.ca", - password="testpassword123", - ) - db_session.add(test_write) - test_read = Users( - id=4, - display_name="testuserread", - user_name="testuserread@testemail.ca", - password="testpassword123", - ) - db_session.add(test_read) - - # Super Admin Test Values - sa_org = Organizations(acronym="SA") - db_session.add(sa_org) - db_session.commit() - org_orm = ( - db_session.query(Organizations) - .filter(Organizations.acronym == "SA") - .first() - ) - sa_user_aff = User_affiliations( - organization_id=org_orm.id, user_id=1, permission="super_admin" - ) - db_session.add(sa_user_aff) - db_session.commit() - sa_check_org = Organizations(acronym="SA_CHECK") - db_session.add(sa_check_org) - sa_update_org = Organizations(acronym="SA_UPDATE") - db_session.add(sa_update_org) - sa_delete_org = Organizations(acronym="SA_DELETE") - db_session.add(sa_delete_org) - db_session.commit() - org_orm = ( - db_session.query(Organizations) - .filter(Organizations.acronym == "SA_DELETE") - .first() - ) - sa_domain = Domains(id=1, organization_id=org_orm.id) - db_session.add(sa_domain) - sa_scan = Scans(id=1, domain_id=1) - db_session.add(sa_scan) - db_session.commit() - sa_dkim = Dkim_scans(id=1) - db_session.add(sa_dkim) - sa_dmarc = Dmarc_scans(id=1) - db_session.add(sa_dmarc) - sa_https = Https_scans(id=1) - db_session.add(sa_https) - sa_mx = Mx_scans(id=1) - db_session.add(sa_mx) - sa_spf = Spf_scans(id=1) - db_session.add(sa_spf) - sa_ssl = Ssl_scans(id=1) - db_session.add(sa_ssl) - db_session.commit() - - # Admin Db Inserts - admin_org = Organizations(acronym="ADMIN_ORG") - db_session.add(admin_org) - db_session.commit() - org_orm = ( - db_session.query(Organizations) - .filter(Organizations.acronym == "ADMIN_ORG") - .first() - ) - admin_aff = User_affiliations( - organization_id=org_orm.id, user_id=2, permission="admin" - ) - db_session.add(admin_aff) - - # User Write Db Inserts - user_write_org = Organizations(acronym="USER_W_ORG") - db_session.add(user_write_org) - db_session.commit() - org_orm = ( - db_session.query(Organizations) - .filter(Organizations.acronym == "USER_W_ORG") - .first() - ) - user_write_aff = User_affiliations( - organization_id=org_orm.id, user_id=3, permission="user_write" - ) - db_session.add(user_write_aff) - - # User Read Db Inserts - user_read_org = Organizations(acronym="USER_R_ORG") - db_session.add(user_read_org) - db_session.commit() - org_orm = ( - db_session.query(Organizations) - .filter(Organizations.acronym == "USER_R_ORG") - .first() - ) - user_read_aff = User_affiliations( - organization_id=org_orm.id, user_id=4, permission="user_read" - ) - db_session.add(user_read_aff) - db_session.commit() - - yield - - with app.app_context(): - Dkim_scans.query.delete() - Dmarc_scans.query.delete() - Https_scans.query.delete() - Mx_scans.query.delete() - Spf_scans.query.delete() - Ssl_scans.query.delete() - Scans.query.delete() - Domains.query.delete() - User_affiliations.query.delete() - Organizations.query.delete() - Users.query.delete() - db_session.commit() - - -@pytest.mark.usefixtures("organization_mutation_db_init") -class TestOrganizationMutations(TestCase): - # Super Admin Tests - def test_sa_org_mutation_create_org(self): - """ - Test To See If SA Can Create Organization - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - createOrganization( - acronym: "TEST_ORG" - description: "Test Organization" - zone: "Test Zone" - sector: "Test Sector" - province: "Nova Scotia" - city: "Halifax" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["data"] - assert executed["data"]["createOrganization"] - assert executed["data"]["createOrganization"]["status"] - - executed = client.execute( - """ - { - organization(org: "TEST_ORG") { - edges { - node { - acronym - description - zone - sector - province - city - } - } - } - } - """, - context_value=request_headers, - backend=backend, - ) - result_refr = { - "data": { - "organization": { - "edges": [ - { - "node": { - "acronym": "TEST_ORG", - "description": "Test Organization", - "zone": "Test Zone", - "sector": "Test Sector", - "province": "Nova Scotia", - "city": "Halifax", - } - } - ] - } - } - } - self.assertDictEqual(result_refr, executed) - - def test_sa_org_mutation_create_org_already_exists(self): - """ - Test Error Check For Existing Org - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - createOrganization( - acronym: "SA_CHECK" - description: "Test Organization" - zone: "Test Zone" - sector: "Test Sector" - province: "Nova Scotia" - city: "Halifax" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] == "Error, Organization alredy exists" - ) - - def test_sa_org_mutation_update_org(self): - """ - Test To See If SA Can Update an Organization - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - updateOrganization( - acronym: "TEST_ORG" - updatedAcronym: "NEW_ORG" - description: "Test Organization" - zone: "Test Zone" - sector: "Test Sector" - province: "Nova Scotia" - city: "Halifax" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["data"] - assert executed["data"]["updateOrganization"] - assert executed["data"]["updateOrganization"]["status"] - - executed = client.execute( - """ - { - organization(org: "NEW_ORG") { - edges { - node { - acronym - description - zone - sector - province - city - } - } - } - } - """, - context_value=request_headers, - backend=backend, - ) - result_refr = { - "data": { - "organization": { - "edges": [ - { - "node": { - "acronym": "NEW_ORG", - "description": "Test Organization", - "zone": "Test Zone", - "sector": "Test Sector", - "province": "Nova Scotia", - "city": "Halifax", - } - } - ] - } - } - } - self.assertDictEqual(result_refr, executed) - - def test_sa_org_mutation_update_org_acronym_already_in_use(self): - """ - Test To See Error appears when acronym already taken - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - updateOrganization( - acronym: "SA_UPDATE" - updatedAcronym: "SA" - description: "Test Organization" - zone: "Test Zone" - sector: "Test Sector" - province: "Nova Scotia" - city: "Halifax" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["errors"] - assert executed["errors"][0] - assert executed["errors"][0]["message"] == "Error, acronym already in use." - - def test_sa_org_mutation_update_org_does_not_exist(self): - """ - Test To See Error appears when org does not exist - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - updateOrganization( - acronym: "TEST_ORG" - updatedAcronym: "SA" - description: "Test Organization" - zone: "Test Zone" - sector: "Test Sector" - province: "Nova Scotia" - city: "Halifax" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, organization does not exist." - ) - - def test_sa_org_mutation_remove_org(self): - """ - Test To See If SA Can Remove an Organization - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - org_id = ( - db_session.query(Organizations) - .filter(Organizations.acronym == "SA_DELETE") - .first() - .id - ) - - executed = client.execute( - """ - mutation { - removeOrganization( - acronym: "SA_DELETE" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["data"] - assert executed["data"]["removeOrganization"] - assert executed["data"]["removeOrganization"]["status"] - - check_org_orm = ( - db_session.query(Organizations) - .filter(Organizations.acronym == "SA_DELETE") - .first() - ) - assert check_org_orm is None - - check_user_aff = ( - db_session.query(User_affiliations) - .filter(User_affiliations.organization_id == org_id) - .all() - ) - assert not check_user_aff - - assert not db_session.query(Domains).all() - assert not db_session.query(Scans).all() - assert not db_session.query(Ssl_scans).all() - assert not db_session.query(Spf_scans).all() - assert not db_session.query(Mx_scans).all() - assert not db_session.query(Https_scans).all() - assert not db_session.query(Dmarc_scans).all() - assert not db_session.query(Dkim_scans).all() - - def test_sa_org_mutation_remove_org_sa_org(self): - """ - Test To See If SA Can't Remove SA Organization - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - removeOrganization( - acronym: "SA" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, you cannot remove this organization" - ) - - def test_sa_org_mutation_remove_org_does_not_exist(self): - """ - Test Error appears when trying to remove an org that doesn't exist - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - removeOrganization( - acronym: "RANDOM" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] == "Error, organization does not exist" - ) - - # Admin Test - def test_admin_org_mutation_create_org_fail(self): - """ - Test That Admin can't create orgs - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - createOrganization( - acronym: "ADMIN_NEW" - description: "Test Organization" - zone: "Test Zone" - sector: "Test Sector" - province: "Nova Scotia" - city: "Halifax" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, you do not have permission to create organizations" - ) - - def test_admin_org_mutation_update_org_fail(self): - """ - Test That Admin can't update orgs - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - updateOrganization( - acronym: "ADMIN_ORG" - description: "Test Organization" - zone: "Test Zone" - sector: "Test Sector" - province: "Nova Scotia" - city: "Halifax" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, you do not have permission to update organizations" - ) - - def test_admin_org_mutation_remove_org_fail(self): - """ - Test That Admin can't remove orgs - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - removeOrganization( - acronym: "ADMIN_ORG" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, you do not have permission to remove organizations." - ) - - # User Write Test - def test_user_write_org_mutation_create_org_fail(self): - """ - Test That User Write can't create orgs - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserwrite@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - createOrganization( - acronym: "USER_W_NEW" - description: "Test Organization" - zone: "Test Zone" - sector: "Test Sector" - province: "Nova Scotia" - city: "Halifax" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, you do not have permission to create organizations" - ) - - def test_user_write_org_mutation_update_org_fail(self): - """ - Test That User Write can't update orgs - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserwrite@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - updateOrganization( - acronym: "USER_W_ORG" - description: "Test Organization" - zone: "Test Zone" - sector: "Test Sector" - province: "Nova Scotia" - city: "Halifax" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, you do not have permission to update organizations" - ) - - def test_user_write_org_mutation_remove_org_fail(self): - """ - Test That User Write can't remove orgs - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserwrite@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - removeOrganization( - acronym: "USER_W_ORG" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, you do not have permission to remove organizations." - ) - - # User Read Test - def test_user_read_org_mutation_create_org_fail(self): - """ - Test That user read can't create orgs - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - createOrganization( - acronym: "USER_R_NEW" - description: "Test Organization" - zone: "Test Zone" - sector: "Test Sector" - province: "Nova Scotia" - city: "Halifax" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, you do not have permission to create organizations" - ) - - def test_user_read_org_mutation_update_org_fail(self): - """ - Test That user read can't update orgs - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - updateOrganization( - acronym: "USER_R_ORG" - description: "Test Organization" - zone: "Test Zone" - sector: "Test Sector" - province: "Nova Scotia" - city: "Halifax" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, you do not have permission to update organizations" - ) - - def test_user_read_org_mutation_remove_org_fail(self): - """ - Test That user read can't remove orgs - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - mutation { - removeOrganization( - acronym: "USER_R_ORG" - ) { - status - } - } - """, - context_value=request_headers, - backend=backend, - ) - - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, you do not have permission to remove organizations." - ) diff --git a/api/tests/test_organization_resolver_access_control.py b/api/tests/test_organization_resolver_access_control.py index 9b539ceae6..d3345174c4 100644 --- a/api/tests/test_organization_resolver_access_control.py +++ b/api/tests/test_organization_resolver_access_control.py @@ -1,419 +1,228 @@ import pytest +import json from flask import Request +from json_web_token import tokenize, auth_header from graphene.test import Client from unittest import TestCase from werkzeug.test import create_environ from app import app -from db import db_session +from db import DB from models import Organizations, Users, User_affiliations from queries import schema from backend.security_check import SecurityAnalysisBackend -@pytest.fixture(scope="class") -def org_perm_test_db_init(): - with app.app_context(): - test_user = Users( - id=1, - display_name="testuserread", - user_name="testuserread@testemail.ca", - password="testpassword123", - ) - db_session.add(test_user) - test_super_admin = Users( - id=2, - display_name="testsuperadmin", - user_name="testsuperadmin@testemail.ca", - password="testpassword123", - ) - db_session.add(test_super_admin) +s, cleanup, session = DB() - org = Organizations( - id=1, acronym="ORG1", org_tags={"description": "Organization 1"} - ) - db_session.add(org) - org = Organizations( - id=2, acronym="ORG2", org_tags={"description": "Organization 2"} - ) - db_session.add(org) - org = Organizations( - id=3, acronym="ORG3", org_tags={"description": "Organization 3"} - ) - db_session.add(org) - - test_admin_role = User_affiliations( - user_id=1, organization_id=1, permission="user_read" - ) - db_session.add(test_admin_role) - test_admin_role = User_affiliations( - user_id=2, organization_id=1, permission="super_admin" - ) - db_session.add(test_admin_role) - db_session.commit() - - yield +@pytest.fixture +def save(): with app.app_context(): - User_affiliations.query.delete() - Organizations.query.delete() - Users.query.delete() - db_session.commit() - - -@pytest.mark.usefixtures("org_perm_test_db_init") -class TestOrgResolverWithOrgs(TestCase): - # Super Admin Tests - def test_get_org_resolvers_by_org_super_admin_single_node(self): - """ - Test org resolver by organization as a super admin, single node return + yield s + cleanup() + + +def test_get_org_resolvers_by_org_super_admin_single_node(save): + """ + Test org resolver by organization as a super admin, single node return + """ + org1 = Organizations( + name="Org1", acronym="ORG1", org_tags={"name": "Organization 1"} + ) + org2 = Organizations( + name="Org2", acronym="ORG2", org_tags={"name": "Organization 2"} + ) + org3 = Organizations( + name="Org3", acronym="ORG3", org_tags={"name": "Organization 3"} + ) + + reader = Users( + display_name="testuserread", + user_name="testuserread@testemail.ca", + password="testpassword123", + ) + super_admin = Users( + display_name="testsuperadmin", + user_name="testsuperadmin@testemail.ca", + password="testpassword123", + ) + + super_admin.user_affiliation.append( + User_affiliations(permission="super_admin", user_organization=org1) + ) + + reader.user_affiliation.append( + User_affiliations(permission="user_read", user_organization=org1) + ) + + save(reader) + save(super_admin) + + token = tokenize(user_id=super_admin.id, roles=super_admin.roles) + + result = Client(schema).execute( """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ - authToken + { + organization(org: "ORG1") { + edges { + node { + acronym } } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - { - organization(org: "ORG1") { - edges { - node { - acronym - } - } - } - } - """, - context_value=request_headers, - backend=backend, - ) - result_refr = { - "data": {"organization": {"edges": [{"node": {"acronym": "ORG1"}}]}} } - self.assertDictEqual(result_refr, executed) - - def test_get_org_resolvers_super_admin_multi_node(self): + } + """, + context_value=auth_header(token), + ) + assert result == { + "data": {"organization": {"edges": [{"node": {"acronym": "ORG1"}}]}} + } + + +def test_org_resolvers_returns_all_orgs_to_super_admin(save): + """ + Test organization resolver as a super admin, multi node return + """ + org1 = Organizations(name="Org1", acronym="ORG1") + + reader = Users( + display_name="testuserread", + user_name="testuserread@testemail.ca", + password="testpassword123", + user_affiliation=[ + User_affiliations(permission="user_read", user_organization=org1) + ], + ) + super_admin = Users( + display_name="testsuperadmin", + user_name="testsuperadmin@testemail.ca", + password="testpassword123", + user_affiliation=[ + User_affiliations(permission="super_admin", user_organization=org1) + ], + ) + + save(reader) + save(super_admin) + + token = tokenize(user_id=super_admin.id, roles=super_admin.roles) + + result = Client(schema).execute( """ - Test organization resolver as a super admin, multi node return - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - { - organizations { - edges { - node { - acronym - } - } - } - } - """, - context_value=request_headers, - backend=backend, - ) - result_refr = { - "data": { - "organizations": { - "edges": [ - {"node": {"acronym": "ORG1"}}, - {"node": {"acronym": "ORG2"}}, - {"node": {"acronym": "ORG3"}}, - ] + { + organizations { + edges { + node { + name } } } - self.assertDictEqual(result_refr, executed) - - # User read tests - def test_get_org_resolvers_by_org_user_read_single_node(self): - """ - Test orgnization resolver by org as user read, return as - single node - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - { - organization(org: "ORG1") { - edges { - node { - acronym - } - } - } - } - """, - context_value=request_headers, - backend=backend, - ) - result_refr = { - "data": {"organization": {"edges": [{"node": {"acronym": "ORG1"}}]}} + } + """, + context_value=auth_header(token), + ) + assert result == { + "data": { + "organizations": { + "edges": [ + {"node": {"name": "Org1"}}, + {"node": {"name": "testsuperadmin@testemail.ca"}}, + {"node": {"name": "testuserread@testemail.ca"}}, + ] } - self.assertDictEqual(result_refr, executed) - - def test_get_org_resolvers_by_org_user_read_multi_node(self): + } + } + + +def test_org_resolvers_returns_single_org1_and_users_own_org_for_read_users(save): + org1 = Organizations(name="Org1", acronym="ORG1") + org2 = Organizations(name="SA", acronym="SA") + + reader = Users( + display_name="testuserread", + user_name="testuserread@testemail.ca", + password="testpassword123", + user_affiliation=[ + User_affiliations(permission="user_read", user_organization=org1) + ], + ) + super_admin = Users( + display_name="testsuperadmin", + user_name="testsuperadmin@testemail.ca", + password="testpassword123", + user_affiliation=[ + User_affiliations(permission="super_admin", user_organization=org1), + User_affiliations(permission="super_admin", user_organization=org2), + ], + ) + + save(reader) + save(super_admin) + + token = tokenize(user_id=reader.id, roles=reader.roles) + + result = Client(schema).execute( """ - Test domain resolver get domain by org as user read, return as - multi node - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ - authToken + { + organizations { + edges { + node { + name } } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - { - organizations { - edges { - node { - acronym - } - } - } - } - """, - context_value=request_headers, - backend=backend, - ) - result_refr = { - "data": {"organizations": {"edges": [{"node": {"acronym": "ORG1"}}]}} } - self.assertDictEqual(result_refr, executed) - - def test_get_org_resolvers_by_org_user_read_no_access(self): - """ - Test domain resolver get domain by url as user read, user has no rights - to view domains related to that org - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - { - organization(org: "ORG2") { - edges { - node { - acronym - } - } - } - } - """, - context_value=request_headers, - backend=backend, - ) - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, you do not have permission to view that organization" - ) - - -@pytest.fixture(scope="class") -def org_no_perm_test_db_init(): - - with app.app_context(): - test_super_admin = Users( - id=2, - display_name="testsuperadmin", - user_name="testsuperadmin@testemail.ca", - password="testpassword123", - ) - db_session.add(test_super_admin) - test_admin_role = User_affiliations(user_id=2, permission="super_admin") - db_session.add(test_admin_role) - db_session.commit() + } + """, + context_value=auth_header(token), + ) + assert result == { + "data": { + "organizations": { + "edges": [ + {"node": {"name": "Org1"}}, + {"node": {"name": "testuserread@testemail.ca"}}, + ] + } + } + } - yield - with app.app_context(): - User_affiliations.query.delete() - Users.query.delete() - db_session.commit() +def test_org_resolvers_does_not_show_orgs_reader_is_not_affiliated_with(save): + org1 = Organizations(name="Org1", acronym="ORG1") + org2 = Organizations(name="Org2", acronym="ORG2") + reader = Users( + display_name="testuserread", + user_name="testuserread@testemail.ca", + password="testpassword123", + user_affiliation=[ + User_affiliations(permission="user_read", user_organization=org1) + ], + ) -@pytest.mark.usefixtures("org_no_perm_test_db_init") -class TestOrgResolverWithoutOrgs(TestCase): - def test_get_org_resolvers_super_admin_no_orgs(self): - """ - Test org resolver by organization as a super admin, no orgs exist - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None + save(reader) - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) + token = tokenize(user_id=reader.id, roles=reader.roles) - executed = client.execute( - """ - { - organizations { - edges { - node { - acronym - } - } - } - } - """, - context_value=request_headers, - backend=backend, - ) - assert executed["errors"] - assert executed["errors"][0] - assert executed["errors"][0]["message"] == "Error, no organizations to view" - - def test_get_org_resolvers_by_org_super_admin_no_orgs(self): - """ - Test org resolver by organization as a super admin, no orgs exist + result = Client(schema).execute( """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) - - executed = client.execute( - """ - { - organization(org: "ORG3"){ - edges { - node { - acronym - } - } + { + organization(org: "ORG2") { + edges { + node { + name } } - """, - context_value=request_headers, - backend=backend, - ) - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] == "Error, organization does not exist" + } + } + """, + context_value=auth_header(token), + ) + if "errors" not in result: + fail( + "Expected read user request for non-affiliated org to error. Instead: {}".format( + result ) + ) + [err] = result["errors"] + assert err["message"] == "Error, organization does not exist" diff --git a/api/tests/test_organization_resolver_values.py b/api/tests/test_organization_resolver_values.py index b228a97595..5275a4ec0f 100644 --- a/api/tests/test_organization_resolver_values.py +++ b/api/tests/test_organization_resolver_values.py @@ -1,523 +1,586 @@ import pytest +import json +from pytest import fail from flask import Request from graphene.test import Client from unittest import TestCase from werkzeug.test import create_environ from app import app -from db import db_session +from db import DB from models import Organizations, Domains, Users, User_affiliations from queries import schema from backend.security_check import SecurityAnalysisBackend +save, cleanup, db_session = DB() + @pytest.fixture(scope="class") def org_perm_test_db_init(): with app.app_context(): - test_user = Users( - id=1, - display_name="testuserread", - user_name="testuserread@testemail.ca", - password="testpassword123", - ) - db_session.add(test_user) - test_super_admin = Users( - id=2, - display_name="testsuperadmin", - user_name="testsuperadmin@testemail.ca", - password="testpassword123", - ) - db_session.add(test_super_admin) - - org = Organizations( - id=1, + org1 = Organizations( acronym="ORG1", + domains=[Domains(domain="somecooldomain.ca")], org_tags={ - "description": "Organization 1", + "name": "Organization 1", "zone": "Prov", "sector": "Banking", "province": "Alberta", "city": "Calgary", }, ) - db_session.add(org) - org = Organizations( - id=2, + save(org1) + org2 = Organizations( acronym="ORG2", + domains=[Domains(domain="anothercooldomain.ca")], org_tags={ - "description": "Organization 2", + "name": "Organization 2", "zone": "Muni", "sector": "Transportation", "province": "NS", "city": "Halifax", }, ) - db_session.add(org) - org = Organizations( - id=3, + save(org2) + org3 = Organizations( acronym="ORG3", + domains=[Domains(domain="somelamedomain.ca")], org_tags={ - "description": "Organization 3", + "name": "Organization 3", "zone": "Federal", "sector": "Arts", "province": "Ontario", "city": "Toronto", }, ) - db_session.add(org) - - test_admin_role = User_affiliations( - user_id=1, organization_id=1, permission="user_read" + save(org3) + user = Users( + display_name="testuserread", + user_name="testuserread@testemail.ca", + password="testpassword123", + user_affiliation=[ + User_affiliations(user_organization=org1, permission="user_read") + ], ) - db_session.add(test_admin_role) - test_admin_role = User_affiliations( - user_id=2, organization_id=1, permission="super_admin" + super_admin = Users( + display_name="testsuperadmin", + user_name="testsuperadmin@testemail.ca", + password="testpassword123", + user_affiliation=[ + User_affiliations(user_organization=org1, permission="super_admin") + ], ) - db_session.add(test_admin_role) - domain = Domains(id=1, domain="somecooldomain.ca", organization_id=1) - db_session.add(domain) - domain = Domains(id=2, domain="anothercooldomain.ca", organization_id=2) - db_session.add(domain) - domain = Domains(id=3, domain="somelamedomain.ca", organization_id=3) - db_session.add(domain) - db_session.commit() + save(user) + save(super_admin) - yield + yield - with app.app_context(): - Domains.query.delete() - User_affiliations.query.delete() - Organizations.query.delete() - Users.query.delete() - db_session.commit() + cleanup() @pytest.mark.usefixtures("org_perm_test_db_init") -class TestOrgResolverWithOrgsAndValues(TestCase): - # Super Admin Tests - def test_get_org_resolvers_by_org_super_admin_single_node(self): - """ - Test org resolver by organization as a super admin, single node return - with all values - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ - authToken - } +# Super Admin Tests +def test_get_org_resolvers_by_org_super_admin_single_node(): + """ + Test org resolver by organization as a super admin, single node return + with all values + """ + with app.app_context(): + backend = SecurityAnalysisBackend() + client = Client(schema) + get_token = client.execute( + """ + mutation{ + signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ + authToken } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None + } + """, + backend=backend, + ) + assert get_token["data"]["signIn"]["authToken"] is not None + token = get_token["data"]["signIn"]["authToken"] + assert token is not None - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) + environ = create_environ() + environ.update(HTTP_AUTHORIZATION=token) + request_headers = Request(environ) - executed = client.execute( - """ - { - organization(org: "ORG1") { - edges { - node { - acronym - description - zone - sector - province - city - domains { - edges { - node { - url - } + actual = client.execute( + """ + { + organization(org: "ORG1") { + edges { + node { + acronym + name + zone + sector + province + city + domains { + edges { + node { + url } } - affiliatedUsers { - edges { - node { - user { - displayName - } - permission + } + affiliatedUsers { + edges { + node { + user { + displayName } + permission } } } } } } - """, - context_value=request_headers, - backend=backend, - ) - result_refr = { - "data": { - "organization": { - "edges": [ - { - "node": { - "acronym": "ORG1", - "description": "Organization 1", - "zone": "Prov", - "sector": "Banking", - "province": "Alberta", - "city": "Calgary", - "domains": { - "edges": [ - {"node": {"url": "somecooldomain.ca"}} - ] - }, - "affiliatedUsers": { - "edges": [ - { - "node": { - "user": { - "displayName": "testuserread" - }, - "permission": "USER_READ", - } - }, - { - "node": { - "user": { - "displayName": "testsuperadmin" - }, - "permission": "SUPER_ADMIN", - } - }, - ] - }, - } + } + """, + context_value=request_headers, + backend=backend, + ) + expected = { + "data": { + "organization": { + "edges": [ + { + "node": { + "acronym": "ORG1", + "name": None, + "zone": "Prov", + "sector": "Banking", + "province": "Alberta", + "city": "Calgary", + "domains": { + "edges": [{"node": {"url": "somecooldomain.ca"}}] + }, + "affiliatedUsers": { + "edges": [ + { + "node": { + "user": {"displayName": "testuserread"}, + "permission": "USER_READ", + } + }, + { + "node": { + "user": { + "displayName": "testsuperadmin" + }, + "permission": "SUPER_ADMIN", + } + }, + ] + }, } - ] - } + } + ] } } - self.assertDictEqual(result_refr, executed) + } - def test_get_org_resolvers_super_admin_multi_node(self): - """ - Test organization resolver as a super admin, multi node return with - all values - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ - authToken - } - } - """, - backend=backend, + if "errors" in actual: + fail( + "Expected super admin to return results for all users but got: {}".format( + result["errors"] + ) ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) + assert actual == expected - executed = client.execute( - """ - { - organizations { - edges { - node { - acronym - description - zone - sector - province - city - domains { - edges { - node { - url - } + +@pytest.mark.usefixtures("org_perm_test_db_init") +def test_get_org_resolvers_super_admin_multi_node(): + """ + Test organization resolver as a super admin, multi node return with + all values + """ + with app.app_context(): + backend = SecurityAnalysisBackend() + client = Client(schema) + get_token = client.execute( + """ + mutation{ + signIn(userName:"testsuperadmin@testemail.ca", password:"testpassword123"){ + authToken + } + } + """, + backend=backend, + ) + if "errors" in get_token: + print(get_token["errors"]) + assert get_token["data"]["signIn"]["authToken"] is not None + token = get_token["data"]["signIn"]["authToken"] + assert token is not None + + environ = create_environ() + environ.update(HTTP_AUTHORIZATION=token) + request_headers = Request(environ) + + actual = client.execute( + """ + { + organizations { + edges { + node { + acronym + name + zone + sector + province + city + domains { + edges { + node { + url } } - affiliatedUsers { - edges { - node { - user { - displayName - } - permission + } + affiliatedUsers { + edges { + node { + user { + displayName } + permission } } } } } } - """, - context_value=request_headers, - backend=backend, - ) - result_refr = { - "data": { - "organizations": { - "edges": [ - { - "node": { - "acronym": "ORG1", - "description": "Organization 1", - "zone": "Prov", - "sector": "Banking", - "province": "Alberta", - "city": "Calgary", - "domains": { - "edges": [ - {"node": {"url": "somecooldomain.ca"}} - ] - }, - "affiliatedUsers": { - "edges": [ - { - "node": { - "user": { - "displayName": "testuserread" - }, - "permission": "USER_READ", - } - }, - { - "node": { - "user": { - "displayName": "testsuperadmin" - }, - "permission": "SUPER_ADMIN", - } - }, - ] - }, - } - }, - { - "node": { - "acronym": "ORG2", - "description": "Organization 2", - "zone": "Muni", - "sector": "Transportation", - "province": "NS", - "city": "Halifax", - "domains": { - "edges": [ - {"node": {"url": "anothercooldomain.ca"}} - ] - }, - "affiliatedUsers": {"edges": []}, - } - }, - { - "node": { - "acronym": "ORG3", - "description": "Organization 3", - "zone": "Federal", - "sector": "Arts", - "province": "Ontario", - "city": "Toronto", - "domains": { - "edges": [ - {"node": {"url": "somelamedomain.ca"}} - ] - }, - "affiliatedUsers": {"edges": []}, - } - }, - ] - } - } } - self.assertDictEqual(result_refr, executed) + """, + context_value=request_headers, + backend=backend, + ) - # User read tests - def test_get_org_resolvers_by_org_user_read_single_node(self): - """ - Test org resolver with an org as a user read, multi node return with - all values - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ - authToken - } + expected = { + "data": { + "organizations": { + "edges": [ + { + "node": { + "acronym": "ORG1", + "name": None, + "zone": "Prov", + "sector": "Banking", + "province": "Alberta", + "city": "Calgary", + "domains": { + "edges": [{"node": {"url": "somecooldomain.ca"}}] + }, + "affiliatedUsers": { + "edges": [ + { + "node": { + "user": {"displayName": "testuserread"}, + "permission": "USER_READ", + } + }, + { + "node": { + "user": { + "displayName": "testsuperadmin" + }, + "permission": "SUPER_ADMIN", + } + }, + ] + }, + } + }, + { + "node": { + "acronym": "ORG2", + "name": None, + "zone": "Muni", + "sector": "Transportation", + "province": "NS", + "city": "Halifax", + "domains": { + "edges": [{"node": {"url": "anothercooldomain.ca"}}] + }, + "affiliatedUsers": {"edges": []}, + } + }, + { + "node": { + "acronym": "ORG3", + "name": None, + "zone": "Federal", + "sector": "Arts", + "province": "Ontario", + "city": "Toronto", + "domains": { + "edges": [{"node": {"url": "somelamedomain.ca"}}] + }, + "affiliatedUsers": {"edges": []}, + } + }, + { + "node": { + "acronym": "TESTUSERRE", + "name": "testuserread@testemail.ca", + "zone": None, + "sector": None, + "province": None, + "city": None, + "domains": {"edges": []}, + "affiliatedUsers": { + "edges": [ + { + "node": { + "user": {"displayName": "testuserread"}, + "permission": "ADMIN", + } + } + ] + }, + } + }, + { + "node": { + "acronym": "TESTSUPERA", + "name": "testsuperadmin@testemail.ca", + "zone": None, + "sector": None, + "province": None, + "city": None, + "domains": {"edges": []}, + "affiliatedUsers": { + "edges": [ + { + "node": { + "user": { + "displayName": "testsuperadmin" + }, + "permission": "ADMIN", + } + } + ] + }, + } + }, + ] } - """, - backend=backend, + } + } + + if "errors" in actual: + fail( + "Expected super admin to return results for all users but got: {}".format( + actual["errors"] + ) ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) + assert actual == expected - executed = client.execute( - """ - { - organization(org: "ORG1") { - edges { - node { - acronym - description - zone - sector - province - city - domains { - edges { - node { - url - } + +# User read tests +@pytest.mark.usefixtures("org_perm_test_db_init") +def test_get_org_resolvers_by_org_user_read_single_node(): + """ + Test org resolver with an org as a user read, multi node return with + all values + """ + with app.app_context(): + backend = SecurityAnalysisBackend() + client = Client(schema) + get_token = client.execute( + """ + mutation{ + signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ + authToken + } + } + """, + backend=backend, + ) + assert get_token["data"]["signIn"]["authToken"] is not None + token = get_token["data"]["signIn"]["authToken"] + assert token is not None + + environ = create_environ() + environ.update(HTTP_AUTHORIZATION=token) + request_headers = Request(environ) + + actual = client.execute( + """ + { + organization(org: "ORG1") { + edges { + node { + acronym + name + zone + sector + province + city + domains { + edges { + node { + url } } - affiliatedUsers { - edges { - node { - user { - displayName - } - permission + } + affiliatedUsers { + edges { + node { + user { + displayName } + permission } } } } } } - """, - context_value=request_headers, - backend=backend, - ) - result_refr = { - "data": { - "organization": { - "edges": [ - { - "node": { - "acronym": "ORG1", - "description": "Organization 1", - "zone": "Prov", - "sector": "Banking", - "province": "Alberta", - "city": "Calgary", - "domains": { - "edges": [ - {"node": {"url": "somecooldomain.ca"}} - ] - }, - "affiliatedUsers": {"edges": []}, - } + } + """, + context_value=request_headers, + backend=backend, + ) + expected = { + "data": { + "organization": { + "edges": [ + { + "node": { + "acronym": "ORG1", + "name": None, + "zone": "Prov", + "sector": "Banking", + "province": "Alberta", + "city": "Calgary", + "domains": { + "edges": [{"node": {"url": "somecooldomain.ca"}}] + }, + "affiliatedUsers": {"edges": []}, } - ] - } + } + ] } } - self.assertDictEqual(result_refr, executed) + } - def test_get_org_resolvers_by_org_user_read_multi_node(self): - """ - Test organizations resolver as a user read, multi node return with - all values - """ - with app.app_context(): - backend = SecurityAnalysisBackend() - client = Client(schema) - get_token = client.execute( - """ - mutation{ - signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ - authToken - } + assert actual == expected + + +@pytest.mark.usefixtures("org_perm_test_db_init") +def test_get_org_resolvers_by_org_user_read_multi_node(): + """ + Test organizations resolver as a user read, multi node return with + all values + """ + with app.app_context(): + backend = SecurityAnalysisBackend() + client = Client(schema) + get_token = client.execute( + """ + mutation{ + signIn(userName:"testuserread@testemail.ca", password:"testpassword123"){ + authToken } - """, - backend=backend, - ) - assert get_token["data"]["signIn"]["authToken"] is not None - token = get_token["data"]["signIn"]["authToken"] - assert token is not None + } + """, + backend=backend, + ) + assert get_token["data"]["signIn"]["authToken"] is not None + token = get_token["data"]["signIn"]["authToken"] + assert token is not None - environ = create_environ() - environ.update(HTTP_AUTHORIZATION=token) - request_headers = Request(environ) + environ = create_environ() + environ.update(HTTP_AUTHORIZATION=token) + request_headers = Request(environ) - executed = client.execute( - """ - { - organizations { - edges { - node { - acronym - description - zone - sector - province - city - domains { - edges { - node { - url - } + actual = client.execute( + """ + { + organizations { + edges { + node { + acronym + name + zone + sector + province + city + domains { + edges { + node { + url } } - affiliatedUsers { - edges { - node { - user { - displayName - } - permission + } + affiliatedUsers { + edges { + node { + user { + displayName } + permission } } } } } } - """, - context_value=request_headers, - backend=backend, - ) - result_refr = { - "data": { - "organizations": { - "edges": [ - { - "node": { - "acronym": "ORG1", - "description": "Organization 1", - "zone": "Prov", - "sector": "Banking", - "province": "Alberta", - "city": "Calgary", - "domains": { - "edges": [ - {"node": {"url": "somecooldomain.ca"}} - ] - }, - "affiliatedUsers": {"edges": []}, - } + } + """, + context_value=request_headers, + backend=backend, + ) + expected = { + "data": { + "organizations": { + "edges": [ + { + "node": { + "acronym": "ORG1", + "name": None, + "zone": "Prov", + "sector": "Banking", + "province": "Alberta", + "city": "Calgary", + "domains": { + "edges": [{"node": {"url": "somecooldomain.ca"}}] + }, + "affiliatedUsers": {"edges": []}, } - ] - } + }, + { + "node": { + "acronym": "TESTUSERRE", + "name": "testuserread@testemail.ca", + "zone": None, + "sector": None, + "province": None, + "city": None, + "domains": {"edges": []}, + "affiliatedUsers": { + "edges": [ + { + "node": { + "user": {"displayName": "testuserread"}, + "permission": "ADMIN", + } + } + ] + }, + } + }, + ] } } - self.assertDictEqual(result_refr, executed) + } + + if "errors" in actual: + fail("Expect success but errors were returned: {}".format(result["errors"])) + assert actual == expected diff --git a/api/tests/test_organizations.py b/api/tests/test_organizations.py new file mode 100644 index 0000000000..8247e25b3c --- /dev/null +++ b/api/tests/test_organizations.py @@ -0,0 +1,17 @@ +import pytest +from app import app +from models import Organizations +from db import DB + +s, cleanup, _ = DB() + +@pytest.fixture +def save(): + with app.app_context(): + yield s + cleanup() + + +def test_orgs_make_a_slug_from_the_name(): + org = Organizations(name="Treasury Board Secretariat") + assert org.slug == "treasury-board-secretariat" diff --git a/api/tests/test_removeOrganization_mutation.py b/api/tests/test_removeOrganization_mutation.py new file mode 100644 index 0000000000..83ccf37857 --- /dev/null +++ b/api/tests/test_removeOrganization_mutation.py @@ -0,0 +1,290 @@ +import pytest +from json_web_token import tokenize +from flask import Request +from pytest import fail +from graphene.test import Client +from unittest import TestCase +from werkzeug.test import create_environ +from app import app +from db import DB +from queries import schema +from backend.security_check import SecurityAnalysisBackend +from models import ( + Organizations, + Domains, + Users, + User_affiliations, + Scans, + Dkim_scans, + Dmarc_scans, + Https_scans, + Mx_scans, + Spf_scans, + Ssl_scans, +) + +s, cleanup, session = DB() + +def auth_header(token): + env = create_environ() + env.update(HTTP_AUTHORIZATION=token) + return Request(env) + + +@pytest.fixture +def save(): + with app.app_context(): + yield s + cleanup() + + +def test_mutation_removeOrganization_succeeds_for_super_admin(save): + sa_user = Users( + display_name="testsuperadmin", + user_name="testsuperadmin@testemail.ca", + password="testpassword123", + ) + sa_user.user_affiliation.append( + User_affiliations( + permission="super_admin", + user_organization=Organizations(acronym="SA", name="Super Admin"), + ) + ) + sa_user.user_affiliation.append( + User_affiliations( + permission="super_admin", + user_organization=Organizations(acronym="ORG1", name="Org One"), + ) + ) + + save(sa_user) + + token = tokenize(user_id=sa_user.id, roles=sa_user.roles) + + result = Client(schema).execute( + """ + mutation { + removed:removeOrganization(acronym: "ORG1") { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" in result: + fail( + "expected removeOrganization to succeed for SA user. Instead: {}".format( + result + ) + ) + + created_org = result["data"].values() + [status] = created_org + + assert status == {"status": True} + + +def test_mutation_removeOrganization_does_not_remove_super_admin_org(save): + sa_user = Users( + display_name="testsuperadmin", + user_name="testsuperadmin@testemail.ca", + password="testpassword123", + ) + sa_user.user_affiliation.append( + User_affiliations( + permission="super_admin", + user_organization=Organizations(acronym="SA", name="Super Admin"), + ) + ) + + save(sa_user) + + token = tokenize(user_id=sa_user.id, roles=sa_user.roles) + + result = Client(schema).execute( + """ + mutation { + removed:removeOrganization(acronym: "SA") { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "expected removing the SA org to fail, even for SA user. Instead: {}".format( + result + ) + ) + + errors, data = result.values() + [first] = errors + message, _, _ = first.values() + assert message == "Error, you cannot remove this organization" + + +def test_mutation_removeOrganization_fails_if_org_does_not_exist(save): + sa_user = Users( + display_name="testsuperadmin", + user_name="testsuperadmin@testemail.ca", + password="testpassword123", + ) + sa_user.user_affiliation.append( + User_affiliations( + permission="super_admin", + user_organization=Organizations(acronym="SA", name="Super Admin"), + ) + ) + + save(sa_user) + + token = tokenize(user_id=sa_user.id, roles=sa_user.roles) + + result = Client(schema).execute( + """ + mutation { + removeOrganization( + acronym: "RANDOM" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "expected removeOrganization to fail for orgs that don't exist. Instead: {}".format( + result + ) + ) + + errors, data = result.values() + [first] = errors + message, _, _ = first.values() + assert message == "Error, organization does not exist" + + +def test_mutation_removeOrganization_fails_for_admin_users(save): + admin = Users( + display_name="admin", user_name="admin@example.com", password="testpassword123", + ) + admin.user_affiliation.append( + User_affiliations( + permission="admin", + user_organization=Organizations(acronym="ORG1", name="Org One",), + ) + ) + + save(admin) + + token = tokenize(user_id=admin.id, roles=admin.roles) + + result = Client(schema).execute( + """ + mutation { + removeOrganization( + acronym: "ORG1" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "expected removeOrganization to fail for admins. Instead: {}".format(result) + ) + + errors, data = result.values() + [first] = errors + message, _, _ = first.values() + assert message == "Error, you do not have permission to remove organizations." + + +def test_mutation_removeOrganization_fails_for_write_users(save): + write_user = Users( + display_name="writer", user_name="write_user@example.com", password="testpassword123", + ) + + write_user.user_affiliation.append( + User_affiliations( + permission="user_write", + user_organization=Organizations(acronym="ORG1", name="Org One"), + ) + ) + + save(write_user) + + token = tokenize(user_id=write_user.id, roles=write_user.roles) + + result = Client(schema).execute( + """ + mutation { + removeOrganization( + acronym: "ORG1" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "expected removeOrganization to fail for write users. Instead: {}".format(result) + ) + + errors, data = result.values() + [first] = errors + message, _, _ = first.values() + assert message == "Error, you do not have permission to remove organizations." + + +def test_mutation_removeOrganization_fails_for_read_users(save): + reader = Users( + display_name="reader", + user_name="reader@example.com", + password="testpassword123", + ) + + reader.user_affiliation.append( + User_affiliations( + permission="user_read", + user_organization=Organizations(acronym="ORG1", name="Org One"), + ) + ) + + save(reader) + + token = tokenize(user_id=reader.id, roles=reader.roles) + + result = Client(schema).execute( + """ + mutation { + removeOrganization( + acronym: "ORG1" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "expected removeOrganization to fail for read users. Instead: {}".format(result) + ) + + errors, data = result.values() + [first] = errors + message, _, _ = first.values() + assert message == "Error, you do not have permission to remove organizations." diff --git a/api/tests/test_updateOrganization_mutation.py b/api/tests/test_updateOrganization_mutation.py new file mode 100644 index 0000000000..bb64594348 --- /dev/null +++ b/api/tests/test_updateOrganization_mutation.py @@ -0,0 +1,338 @@ +import pytest +from json_web_token import tokenize, auth_header +from flask import Request +from pytest import fail +from graphene.test import Client +from unittest import TestCase +from werkzeug.test import create_environ +from app import app +from db import DB +from queries import schema +from backend.security_check import SecurityAnalysisBackend +from models import ( + Organizations, + Domains, + Users, + User_affiliations, + Scans, + Dkim_scans, + Dmarc_scans, + Https_scans, + Mx_scans, + Spf_scans, + Ssl_scans, +) + +s, cleanup, session = DB() + + +@pytest.fixture +def save(): + with app.app_context(): + yield s + cleanup() + + +def test_mutation_updateOrganization_succeeds_as_super_user(save): + sa_user = Users( + display_name="testsuperadmin", + user_name="testsuperadmin@testemail.ca", + password="testpassword123", + ) + sa_user.user_affiliation.append( + User_affiliations( + permission="super_admin", + user_organization=Organizations(acronym="SA", name="Super Admin"), + ) + ) + sa_user.user_affiliation.append( + User_affiliations( + permission="super_admin", + user_organization=Organizations(acronym="ORG1", name="Org One"), + ) + ) + + save(sa_user) + + token = tokenize(user_id=sa_user.id, roles=sa_user.roles) + + result = Client(schema).execute( + """ + mutation { + updateOrganization( + name: "Org One" + acronym: "ORG1" + updatedAcronym: "O1" + zone: "Test Zone" + sector: "Test Sector" + province: "Nova Scotia" + city: "Halifax" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" in result: + fail( + "expected updateOrganization to succeed for super admin. Instead: {}".format( + result + ) + ) + + created_org = result["data"].values() + [status] = created_org + + assert status == {"status": True} + + +def test_mutation_updateOrganization_fails_if_names_clash(save): + sa_user = Users( + display_name="testsuperadmin", + user_name="testsuperadmin@testemail.ca", + password="testpassword123", + ) + sa_user.user_affiliation.append( + User_affiliations( + permission="super_admin", + user_organization=Organizations(acronym="SA", name="Super Admin"), + ) + ) + sa_user.user_affiliation.append( + User_affiliations( + permission="super_admin", + user_organization=Organizations(acronym="ORG1", name="Org One"), + ) + ) + + save(sa_user) + + token = tokenize(user_id=sa_user.id, roles=sa_user.roles) + + result = Client(schema).execute( + """ + mutation { + updateOrganization( + name: "Org One" + acronym: "ORG1" + updatedAcronym: "SA" + zone: "Test Zone" + sector: "Test Sector" + province: "Nova Scotia" + city: "Halifax" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "expected updateOrganization to fail when renaming clashes. Instead: {}".format( + result + ) + ) + + errors, data = result.values() + [first] = errors + message, _, _ = first.values() + assert message == "Error, acronym already in use." + + +def test_mutation_updateOrganization_fails_if_org_does_not_exist(save): + sa_user = Users( + display_name="testsuperadmin", + user_name="testsuperadmin@testemail.ca", + password="testpassword123", + ) + sa_user.user_affiliation.append( + User_affiliations( + permission="super_admin", + user_organization=Organizations(acronym="SA", name="Super Admin"), + ) + ) + + save(sa_user) + + token = tokenize(user_id=sa_user.id, roles=sa_user.roles) + + result = Client(schema).execute( + """ + mutation { + updateOrganization( + name: "Org One" + acronym: "ORG1" + updatedAcronym: "O1" + zone: "Test Zone" + sector: "Test Sector" + province: "Nova Scotia" + city: "Halifax" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "expected updateOrganization to fail for orgs that don't exist. Instead: {}".format( + result + ) + ) + + errors, data = result.values() + [first] = errors + message, _, _ = first.values() + assert message == "Error, organization does not exist." + + +def test_mutation_updateOrganization_fails_for_admin_users(save): + admin = Users( + display_name="admin", user_name="admin@example.com", password="testpassword123", + ) + + admin.user_affiliation.append( + User_affiliations( + permission="admin", + user_organization=Organizations(acronym="ORG1", name="Org One"), + ) + ) + + save(admin) + + token = tokenize(user_id=admin.id, roles=admin.roles) + + result = Client(schema).execute( + """ + mutation { + updateOrganization( + acronym: "ORG1" + updatedAcronym: "O1" + name: "Test Organization" + zone: "Test Zone" + sector: "Test Sector" + province: "Nova Scotia" + city: "Halifax" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "expected createOrganization to fail for admins. Instead: {}".format(result) + ) + + errors, data = result.values() + [first] = errors + message, _, _ = first.values() + assert message == "Error, you do not have permission to update organizations" + + +def test_mutation_updateOrganization_fails_for_write_users(save): + write_user = Users( + display_name="writer", + user_name="write_user@example.com", + password="testpassword123", + ) + + write_user.user_affiliation.append( + User_affiliations( + permission="user_write", + user_organization=Organizations(acronym="ORG1", name="Org One"), + ) + ) + + save(write_user) + + token = tokenize(user_id=write_user.id, roles=write_user.roles) + + result = Client(schema).execute( + """ + mutation { + updateOrganization( + acronym: "ORG1" + updatedAcronym: "O1" + name: "Test Organization" + zone: "Test Zone" + sector: "Test Sector" + province: "Nova Scotia" + city: "Halifax" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "expected createOrganization to fail for write users. Instead: {}".format( + result + ) + ) + + errors, data = result.values() + [first] = errors + message, _, _ = first.values() + assert message == "Error, you do not have permission to update organizations" + + +def test_mutation_updateOrganization_fails_for_read_users(save): + reader = Users( + display_name="reader", + user_name="reader@example.com", + password="testpassword123", + ) + + reader.user_affiliation.append( + User_affiliations( + permission="user_read", + user_organization=Organizations(acronym="ORG1", name="Org One"), + ) + ) + + save(reader) + + token = tokenize(user_id=reader.id, roles=reader.roles) + + result = Client(schema).execute( + """ + mutation { + updateOrganization( + acronym: "ORG1" + updatedAcronym: "O1" + name: "Test Organization" + zone: "Test Zone" + sector: "Test Sector" + province: "Nova Scotia" + city: "Halifax" + ) { + status + } + } + """, + context_value=auth_header(token), + ) + + if "errors" not in result: + fail( + "expected createOrganization to fail for read users. Instead: {}".format( + result + ) + ) + + errors, data = result.values() + [first] = errors + message, _, _ = first.values() + assert message == "Error, you do not have permission to update organizations" diff --git a/api/tests/test_user_access_control.py b/api/tests/test_user_access_control.py index 634b02031d..481d79d95f 100644 --- a/api/tests/test_user_access_control.py +++ b/api/tests/test_user_access_control.py @@ -1,14 +1,17 @@ import pytest +from pytest import fail from flask import Request from graphene.test import Client from unittest import TestCase from werkzeug.test import create_environ from app import app -from db import db_session +from db import DB from models import Organizations, Users, User_affiliations from queries import schema from backend.security_check import SecurityAnalysisBackend +_, cleanup, db_session = DB() + @pytest.fixture(scope="class") def user_resolver_ac_test_db_init(): @@ -78,13 +81,8 @@ def user_resolver_ac_test_db_init(): db_session.add(test_user_write_role) db_session.commit() - yield - - with app.app_context(): - User_affiliations.query.delete() - Organizations.query.delete() - Users.query.delete() - db_session.commit() + yield + cleanup() @pytest.mark.usefixtures("user_resolver_ac_test_db_init") @@ -263,7 +261,7 @@ def test_get_user_user_write(self): ) # User read tests - def test_get_user_user_read(self): + def test_get_reader_can_access_their_own_info(self): """ Test to see if user resolver access control to ensure users with user write access cannot access this query @@ -289,7 +287,7 @@ def test_get_user_user_read(self): environ.update(HTTP_AUTHORIZATION=token) request_headers = Request(environ) - executed = client.execute( + results = client.execute( """ { user(userName: "testuserread@testemail.ca") { @@ -300,9 +298,4 @@ def test_get_user_user_read(self): context_value=request_headers, backend=backend, ) - assert executed["errors"] - assert executed["errors"][0] - assert ( - executed["errors"][0]["message"] - == "Error, you do not have permission to view this users information" - ) + assert results == {"data": {"user": [{"displayName": "testuserread"}]}} diff --git a/api/tests/test_user_mutations.py b/api/tests/test_user_mutations.py index 4d72fe5b3e..32109cdc4b 100644 --- a/api/tests/test_user_mutations.py +++ b/api/tests/test_user_mutations.py @@ -2,12 +2,13 @@ import pytest from graphene.test import Client from app import app -from db import db_session +from db import DB from queries import schema from models import Users from backend.security_check import SecurityAnalysisBackend from functions.error_messages import * +_, cleanup, db_session = DB() @pytest.fixture(scope="class") def user_schema_test_db_init(): @@ -26,11 +27,9 @@ def user_schema_test_db_init(): db_session.add(test_admin) db_session.commit() - yield + yield + cleanup() - with app.app_context(): - Users.query.delete() - db_session.commit() ## diff --git a/api/tests/test_user_values.py b/api/tests/test_user_values.py index e58a29a645..cbf2bc9ed2 100644 --- a/api/tests/test_user_values.py +++ b/api/tests/test_user_values.py @@ -4,58 +4,48 @@ from unittest import TestCase from werkzeug.test import create_environ from app import app -from db import db_session +from db import DB from models import Organizations, Users, User_affiliations from queries import schema from backend.security_check import SecurityAnalysisBackend +save, cleanup, session = DB() @pytest.fixture(scope="class") def user_resolver_test_db_init(): with app.app_context(): + org1 = Organizations(acronym="ORG1") + test_user = Users( - id=1, display_name="testuserread", user_name="testuserread@testemail.ca", password="testpassword123", preferred_lang="English", tfa_validated=False, + user_affiliation=[ + User_affiliations( + user_organization=org1, permission="user_read" + ) + ] ) - db_session.add(test_user) + save(test_user) + session.add(test_user) test_super_admin = Users( - id=2, display_name="testsuperadmin", user_name="testsuperadmin@testemail.ca", password="testpassword123", + user_affiliation=[ + User_affiliations( + user_organization=org1, permission="super_admin" + ) + ] ) - db_session.add(test_super_admin) - - org = Organizations(id=1, acronym="ORG1") - db_session.add(org) - org = Organizations(id=2, acronym="ORG2") - db_session.add(org) - org = Organizations(id=3, acronym="ORG3") - db_session.add(org) - - test_admin_role = User_affiliations( - user_id=1, organization_id=1, permission="user_read" - ) - db_session.add(test_admin_role) - test_admin_role = User_affiliations( - user_id=2, organization_id=1, permission="super_admin" - ) - db_session.add(test_admin_role) - - db_session.commit() + save(test_super_admin) - yield + yield + cleanup() - with app.app_context(): - User_affiliations.query.delete() - Organizations.query.delete() - Users.query.delete() - db_session.commit() @pytest.mark.usefixtures("user_resolver_test_db_init") @@ -86,7 +76,7 @@ def test_get_another_users_information(self): environ.update(HTTP_AUTHORIZATION=token) request_headers = Request(environ) - executed = client.execute( + results = client.execute( """ { user(userName: "testuserread@testemail.ca") { @@ -94,20 +84,13 @@ def test_get_another_users_information(self): displayName lang tfa - affiliations { - edges { - node { - userId - } - } - } } } """, context_value=request_headers, backend=backend, ) - result_refr = { + expected = { "data": { "user": [ { @@ -115,12 +98,11 @@ def test_get_another_users_information(self): "displayName": "testuserread", "lang": "English", "tfa": False, - "affiliations": {"edges": [{"node": {"userId": 1}}]}, } ] } } - self.assertDictEqual(result_refr, executed) + self.assertDictEqual(expected, results) def test_get_another_users_information_user_does_not_exist(self): """ @@ -152,16 +134,6 @@ def test_get_another_users_information_user_does_not_exist(self): { user(userName: "IdontThinkSo@testemail.ca") { userName - displayName - lang - tfa - affiliations { - edges { - node { - userId - } - } - } } } """, @@ -206,13 +178,6 @@ def test_get_own_user_information(self): displayName lang tfa - affiliations { - edges { - node { - userId - } - } - } } } """, @@ -227,7 +192,6 @@ def test_get_own_user_information(self): "displayName": "testuserread", "lang": "English", "tfa": False, - "affiliations": {"edges": [{"node": {"userId": 1}}]}, } ] } diff --git a/api/tests/test_users.py b/api/tests/test_users.py index 8edb0887a2..9b4c0d2557 100644 --- a/api/tests/test_users.py +++ b/api/tests/test_users.py @@ -3,7 +3,7 @@ from models import Users, User_affiliations, Organizations from db import DB -s, cleanup, _ = DB() +s, cleanup, session = DB() @pytest.fixture @@ -43,6 +43,20 @@ def test_user_model_encrypts_the_user_password(): assert len(user.password) is 60 +def test_user_is_admin_on_their_default_org(): + acceptable_password = "twelvechars!" + user = Users( + user_name="foo", + display_name="Foo", + preferred_lang="English", + password=acceptable_password, + ) + + for affiliation in user.user_affiliation: + assert affiliation.permission is "admin" + assert affiliation.user_organization.acronym == "FOO" + + def test_users_roles_can_be_accessed_by_a_roles_method(save): acceptable_password = "twelvechars!" user = Users( @@ -62,5 +76,5 @@ def test_users_roles_can_be_accessed_by_a_roles_method(save): ) # Before save org_id and user_id are None - role = filter(lambda d: d["permission"] == "user_write", user.roles) - assert user.roles == [{"org_id": None, "permission": "user_write", "user_id": None}] + role = [r for r in user.roles if r['permission'] == "user_write"] + assert role == [{"org_id": None, "permission": "user_write", "user_id": None}] diff --git a/api/tests/test_users_access_control.py b/api/tests/test_users_access_control.py index 2b899c5711..38c5a18cf2 100644 --- a/api/tests/test_users_access_control.py +++ b/api/tests/test_users_access_control.py @@ -1,90 +1,76 @@ import pytest from flask import Request +from json_web_token import tokenize, auth_header from graphene.test import Client from unittest import TestCase from werkzeug.test import create_environ from app import app -from db import db_session +from db import DB from models import Organizations, Users, User_affiliations from queries import schema from backend.security_check import SecurityAnalysisBackend +save, cleanup, db_session = DB() + + @pytest.fixture(scope="class") def users_resolver_test_db_init(): with app.app_context(): - test_read = Users( - id=1, + org1 = Organizations(acronym="ORG1") + org2 = Organizations(acronym="ORG2") + org3 = Organizations(acronym="ORG3") + + reader = Users( display_name="testuserread", user_name="testuserread@testemail.ca", password="testpassword123", + user_affiliation=[ + User_affiliations(user_organization=org1, permission="user_read") + ] ) - db_session.add(test_read) - test_super_admin = Users( - id=2, + super_admin = Users( display_name="testsuperadmin", user_name="testsuperadmin@testemail.ca", password="testpassword123", + user_affiliation=[ + User_affiliations(user_organization=org2, permission="super_admin") + ] ) - db_session.add(test_super_admin) - test_admin = Users( - id=3, + org1_admin = Users( display_name="testadmin", user_name="testadmin@testemail.ca", password="testpassword123", + user_affiliation=[ + User_affiliations(user_organization=org1, permission="admin") + ] ) - db_session.add(test_admin) - test_admin = Users( - id=4, + org2_admin = Users( display_name="testadmin2", user_name="testadmin2@testemail.ca", password="testpassword123", + user_affiliation=[ + User_affiliations(user_organization=org2, permission="admin") + ] ) - db_session.add(test_admin) - test_write = Users( - id=5, + writer = Users( display_name="testuserwrite", user_name="testuserwrite@testemail.ca", password="testpassword123", + user_affiliation=[ + User_affiliations(user_organization=org1, permission="user_write") + ] ) - db_session.add(test_write) + save(reader) + save(super_admin) + save(org1_admin) + save(org2_admin) + save(writer) - org = Organizations(id=1, acronym="ORG1") - db_session.add(org) - org = Organizations(id=2, acronym="ORG2") - db_session.add(org) - org = Organizations(id=3, acronym="ORG3") - db_session.add(org) - - test_user_read_role = User_affiliations( - user_id=1, organization_id=1, permission="user_read" - ) - db_session.add(test_user_read_role) - test_super_admin_role = User_affiliations( - user_id=2, organization_id=2, permission="super_admin" - ) - db_session.add(test_super_admin_role) - test_admin_role = User_affiliations( - user_id=3, organization_id=1, permission="admin" - ) - db_session.add(test_admin_role) - test_admin_role = User_affiliations( - user_id=4, organization_id=2, permission="admin" - ) - db_session.add(test_admin_role) - test_user_write_role = User_affiliations( - user_id=5, organization_id=1, permission="user_write" - ) - db_session.add(test_user_write_role) - db_session.commit() - yield + yield + cleanup() - with app.app_context(): - User_affiliations.query.delete() - Organizations.query.delete() - Users.query.delete() - db_session.commit() @pytest.mark.usefixtures("users_resolver_test_db_init") diff --git a/api/tests/testdata/__init__.py b/api/tests/testdata/__init__.py new file mode 100644 index 0000000000..da1b4f94ab --- /dev/null +++ b/api/tests/testdata/__init__.py @@ -0,0 +1,56 @@ +accurateplastics_report = { + "xml_schema": "draft", + "report_metadata": { + "org_name": "accurateplastics.com", + "org_email": "administrator@accurateplastics.com", + "org_extra_contact_info": "null", + "report_id": "example.com:1538463741", + "begin_date": "2018-10-01 13:07:12", + "end_date": "2018-10-01 13:07:12", + "errors": ["Invalid XML: not well-formed (invalid token): line 5, column 17"], + }, + "policy_published": { + "domain": "example.com", + "adkim": "r", + "aspf": "r", + "p": "none", + "sp": "reject", + "pct": "100", + "fo": "0", + }, + "records": [ + { + "source": { + "ip_address": "12.20.127.122", + "country": "US", + "reverse_dns": "null", + "base_domain": "null", + }, + "count": 1, + "alignment": {"spf": False, "dkim": False, "dmarc": False}, + "policy_evaluated": { + "disposition": "none", + "dkim": "fail", + "spf": "fail", + "policy_override_reasons": ["TESTING TEXT"], + }, + "identifiers": { + "header_from": "example.com", + "envelope_from": "null", + "envelope_to": "null", + }, + "auth_results": { + "dkim": [ + { + "domain": "toptierhighticket.club", + "selector": "default", + "result": "pass", + } + ], + "spf": [{"domain": "null", "scope": "mfrom", "result": "none"}], + }, + } + ], +} + +