def test_login_required_decorator_with_valid_token(self): """Tests the login required decorator called with valid token""" type_definitions = ariadne.gql(""" type Query { test: String! } """) query_type = ariadne.QueryType() def resolve_test(_, info): request = info.context self.assertTrue(hasattr(request, "user")) self.assertEqual(request.user, self.user) return "Test!" resolve_test = Mock(wraps=resolve_test) decorated_resolve_test = Mock(wraps=login_required(resolve_test)) query_type.set_field("test", decorated_resolve_test) schema = ariadne.make_executable_schema([type_definitions], [query_type]) middleware = [JSONWebTokenMiddleware()] token = JSONWebTokenBackend().create(self.user) request = HttpRequest() request.META[HTTP_AUTHORIZATION_HEADER] = f"Token {token}" settings = { "AUTHENTICATION_BACKENDS": ( "django_ariadne_jwt.backends.JSONWebTokenBackend", "django.contrib.auth.backends.ModelBackend", ) } with self.settings(**settings): ariadne.graphql_sync( schema, { "query": """ query { test } """ }, context_value=request, middleware=middleware, ) self.assertTrue(resolve_test.called)
async def dummy_client(self, ): """ Client for a dummy server """ type_defs = ariadne.gql(""" scalar JSON type Query { headers: JSON hello: String value_error_required: String! value_error: String type_error: String unauthenticated_error: String unauthorized_error: String } """) query = ariadne.QueryType() @query.field("hello") def hello(parent: Any, info: GraphQLResolveInfo): return "👋" @query.field("value_error") @query.field("value_error_required") def value_error(parent: Any, info: GraphQLResolveInfo): raise ValueError("this is a value error") @query.field("type_error") def type_error(parent: Any, info: GraphQLResolveInfo): raise TypeError("this is a type error") @query.field("unauthenticated_error") def unauthenticated_error(parent: Any, info: GraphQLResolveInfo): raise Unauthenticated("this is an unauthenticated error") @query.field("unauthorized_error") def unauthorized_error(parent: Any, info: GraphQLResolveInfo): raise Unauthorized("this is an unauthorized error") schema = make_executable_schema(type_defs, query) app = Starlette() app.mount("/", GraphQL(schema)) async with httpx.Client(app=app, base_url="http://prefect.io") as dummy_client: yield dummy_client
uuid_input(uuid: UUID): String! uuid_output: UUID! } type Mutation { hello_mutation(input: InputType): JSON! } input InputType { u: UUID! j: JSON! } """) query = ariadne.QueryType() mutation = ariadne.MutationType() @query.field("json_input") def json_input_resolver(parent: Any, info: GraphQLResolveInfo, json): return json["x"] @query.field("json_output") def json_output_resolver(parent: Any, info: GraphQLResolveInfo): return {"x": [1, 2]} @query.field("datetime_input") def datetime_input_resolver(parent: Any, info: GraphQLResolveInfo, dt):
def test_login_required_decorator_without_valid_token(self): """Tests the login required decorator called without valid token""" type_definitions = ariadne.gql(""" type Query { me: String! mustfail: String! } """) query_type = ariadne.QueryType() resolve_me = Mock(return_value="Me!") query_type.set_field("me", resolve_me) resolve_mustfail = Mock(return_value="FAIL!") decorated_resolve_mustfail = Mock( wraps=login_required(resolve_mustfail)) query_type.set_field("mustfail", decorated_resolve_mustfail) schema = ariadne.make_executable_schema([type_definitions], [query_type]) middleware = [JSONWebTokenMiddleware()] request = HttpRequest() settings = { "AUTHENTICATION_BACKENDS": ( "django_ariadne_jwt.backends.JSONWebTokenBackend", "django.contrib.auth.backends.ModelBackend", ) } with self.settings(**settings): success, result = ariadne.graphql_sync( schema, { "query": """ query { me mustfail } """ }, context_value=request, middleware=middleware, ) self.assertTrue(resolve_me.called) self.assertFalse(resolve_mustfail.called) self.assertIsNotNone(result) self.assertIn("errors", result) test_field_error_found = False for error_data in result["errors"]: if "mustfail" in error_data["path"]: test_field_error_found = True self.assertTrue(test_field_error_found)
def __init__(self): """ The schema generator generates a GraphQL schema. The purpose is to provide a schema to which resolvers are then attached, which is then given to Ariadne, and for resolvers to have information about expected types. For RPSL queries and types, this is dynamically generated based on the RPSL objects from irrd.rpsl. Other parts are fixed. This means that the schema is always the same for a given IRRd codebase - there are no runtime or user configurable parts. Along with generating the schema, some metadata is saved, e.g. self.graphql_types which allows resolvers to learn the GraphQL type for a certain field. This generator also creates Ariadne object types on self, which are used to attach resolvers to them. """ self._set_rpsl_query_fields() self._set_rpsl_object_interface_schema() self._set_rpsl_contact_schema() self._set_rpsl_object_schemas() self._set_enums() schema = self.enums schema += """ scalar ASN scalar IP schema { query: Query } type Query { rpslObjects(""" + self.rpsl_query_fields + """): [RPSLObject!] databaseStatus(sources: [String!]): [DatabaseStatus] asnPrefixes(asns: [ASN!]!, ipVersion: Int, sources: [String!]): [ASNPrefixes!] asSetPrefixes(setNames: [String!]!, ipVersion: Int, sources: [String!], excludeSets: [String!], sqlTrace: Boolean): [AsSetPrefixes!] recursiveSetMembers(setNames: [String!]!, depth: Int, sources: [String!], excludeSets: [String!], sqlTrace: Boolean): [SetMembers!] } type DatabaseStatus { source: String! authoritative: Boolean! objectClassFilter: [String!] rpkiRovFilter: Boolean! scopefilterEnabled: Boolean! localJournalKept: Boolean! serialOldestJournal: Int serialNewestJournal: Int serialLastExport: Int serialNewestMirror: Int lastUpdate: String synchronisedSerials: Boolean! } type RPSLJournalEntry { rpslPk: String! source: String! serialNrtm: Int! operation: String! origin: String objectClass: String! objectText: String! timestamp: String! } type ASNPrefixes { asn: ASN! prefixes: [IP!] } type AsSetPrefixes { rpslPk: String! prefixes: [IP!] } type SetMembers { rpslPk: String! rootSource: String! members: [String!] } """ schema += self.rpsl_object_interface_schema schema += self.rpsl_contact_schema schema += ''.join(self.rpsl_object_schemas.values()) schema += 'union RPSLContactUnion = RPSLPerson | RPSLRole' self.type_defs = ariadne.gql(schema) self.query_type = ariadne.QueryType() self.rpsl_object_type = ariadne.InterfaceType("RPSLObject") self.rpsl_contact_union_type = ariadne.UnionType("RPSLContactUnion") self.asn_scalar_type = ariadne.ScalarType("ASN") self.ip_scalar_type = ariadne.ScalarType("IP") self.object_types = [ self.query_type, self.rpsl_object_type, self.rpsl_contact_union_type, self.asn_scalar_type, self.ip_scalar_type ] for name in self.rpsl_object_schemas.keys(): self.object_types.append(ariadne.ObjectType(name)) self.object_types.append(ariadne.ObjectType("ASNPrefixes")) self.object_types.append(ariadne.ObjectType("AsSetPrefixes")) self.object_types.append(ariadne.ObjectType("SetMembers")) self.object_types.append(ariadne.EnumType("RPKIStatus", RPKIStatus)) self.object_types.append( ariadne.EnumType("ScopeFilterStatus", ScopeFilterStatus))
def tests_regular_requests(self): # fmt: off """Tests that the middleware is being called correctly on """ \ """regular requests""" # fmt: on type_definitions = ariadne.gql( """ type Query { test: String! } """ ) query_type = ariadne.QueryType() def resolve_test(_, info): request = info.context self.assertTrue(hasattr(request, "user")) self.assertEqual(request.user, self.user) return "Test!" resolve_test = Mock(wraps=resolve_test) query_type.set_field("test", resolve_test) schema = ariadne.make_executable_schema( [type_definitions], [query_type] ) middleware = JSONWebTokenMiddleware() token = create_jwt(self.user) request = HttpRequest() request.META[HTTP_AUTHORIZATION_HEADER] = f"Token {token}" settings = { "AUTHENTICATION_BACKENDS": ( "django_ariadne_jwt.backends.JSONWebTokenBackend", "django.contrib.auth.backends.ModelBackend", ) } with self.settings(**settings): # Spies on the JSONWebTokenMiddleware.resolve method def spy(*args, **kwargs): return JSONWebTokenMiddleware.resolve( middleware, *args, **kwargs ) spy = Mock(wraps=spy) with patch.object(middleware, "resolve", new=spy): ariadne.graphql_sync( schema, { "query": """ query { test } """ }, context_value=request, middleware=[middleware], ) self.assertTrue(spy.called) self.assertTrue(resolve_test.called)