def build_ValidationError(): ValidationErrorItem = g.ObjectType( 'ValidationErrorItem', fields=g.fields({ 'name': str, 'messages': g.NNList(g.String), }), ) def resolve_errors(obj, info): # note .error, obj is boxed with kocherga.django.errors.BoxedError return [{ 'name': k, 'messages': [str(e) for e in v] } for k, v in obj.error.message_dict.items()] return g.ObjectType( 'ValidationError', fields={ 'errors': g.Field( g.NNList(ValidationErrorItem), resolve=resolve_errors, ), }, )
class ofdFiscalDrives(helpers.BaseField): def resolve(self, _, info): return models.OfdFiscalDrive.objects.all() permissions = [user_perm('kkm.ofd')] result = g.NNList(types.OfdFiscalDrive)
class vkGroups(helpers.BaseField): def resolve(self, obj, info): all_groups = models.VkAnnouncement.objects.all_groups() return [{'name': name} for name in all_groups] permissions = [permissions.manage_events] result = g.NNList(types.VkGroup)
def build_StructBlockValidationError(): FieldValidationError = g.ObjectType( 'WagtailStructBlockFieldValidationError', fields=lambda: g.fields({ 'name': str, 'error': WagtailBlockValidationError }), ) return g.ObjectType( 'WagtailStructBlockValidationError', fields=lambda: g.fields({ 'error_message': valdiation_error_message_field, 'errors': g.Field( g.NNList(FieldValidationError), resolve=lambda obj, info: [{ 'name': k, 'error': v } for k, v in obj.data[0].params.items()], ), }), interfaces=[WagtailBlockValidationError], )
def build_WagtailStreamFieldValidationError(): def resolve_block_errors(obj, info): result = [] for k, v in obj['params'].items(): assert isinstance(v, ErrorList) if k == '__all__': continue # non-block error result.append({'block_id': k, 'error': v}) return result def resolve_non_block_error(obj, info): error = obj['params'].get('__all__') if error is None: return None return str(error) return g.ObjectType( 'WagtailStreamFieldValidationError', g.fields({ 'block_errors': g.Field( g.NNList(WagtailStreamBlockValidationError), resolve=resolve_block_errors, ), 'non_block_error': g.Field(g.String, resolve=resolve_non_block_error), }), )
def build_comments_field(permissions: List[helpers.PermissionType]): def resolve(obj, info, **pager): assert isinstance(obj, models.Commentable) return obj.comments.all() result = g.NNList(types.Comment) return g.Field(result, resolve=check_permissions(permissions)(resolve))
class imageTemplatesAll(helpers.BaseField): def resolve(self, _, info): names = models.list_templates() return [models.Template.by_name(name) for name in names] permissions = [staffonly] result = g.NNList(types.ImageTemplate)
class timepadCategories(helpers.BaseField): def resolve(self, obj, info): categories = kocherga.events.models.announcement.timepad.timepad_categories() return categories permissions = [permissions.manage_events] result = g.NNList(types.TimepadCategory)
def authPermissionsAll(helper): @check_permissions([user_perm("auth.audit")]) def resolve(_, info): return auth_models.Permission.objects.all() Result = g.NNList(types.AuthPermission) return g.Field(Result, resolve=resolve)
class projects(helpers.BaseField): def resolve(self, _, info): qs = models.ProjectPage.objects.all().live() qs = filter_queryset_by_page_permissions(info.context, qs) return list(qs) permissions = [ ] # not neded, projects are filtered by permissions in resolve() result = g.NNList(types.ProjectPage)
class wagtailCollectionsForImageUpload(helpers.BaseField): def resolve(self, _, info, filter=None): return CollectionPermissionPolicy( Image).collections_user_has_permission_for(info.context.user, 'add') permissions = [] result = g.NNList(types.WagtailCollection)
class wagtailAllBlockStructures(helpers.BaseField): def resolve(self, _, info): return [{ 'name': pair[0], 'structure': pair[1] } for pair in blocks_registry.all()] permissions = [] result = g.NNList(BlockStructureWithName)
def wagtailPages(helper): def resolve(_, info): # page.specific is slow! # But we call wagtailPages only on getStaticPaths once per build, so that should be ok. return [ page.specific for page in get_page_queryset_for_request(info.context) ] return g.Field(g.NNList(types.WagtailPage), resolve=resolve)
def instances_field(): @check_permissions([permissions.manage_events]) def resolve(obj, info, limit=None): return obj.instances(limit=limit) return g.Field( g.NNList(Event), args=g.arguments({'limit': Optional[int]}), resolve=resolve, )
def service_fields(account_type): return g.fields({ 'slug': str, 'accounts': g.Field( g.NNList(account_type), resolve=lambda obj, info: obj.list_accounts(), ), })
class search(helpers.BaseFieldWithInput): def resolve(self, _, info, input): query = input['query'] if not query: # don't want to find anything by an empty query return { 'results': [], 'more': False, } results = [] import kocherga.events.models events = get_search_backend().search( query, kocherga.events.models.Event.objects.public_only(). filter_by_period(from_date=datetime.now(tz=TZ) - timedelta(days=2)), )[:2] results.extend([{'event': event} for event in events]) qs = get_page_queryset_for_request(info.context).search(query) limit = input.pop('limit', None) if limit: # ask for one more to determine if there are more results qs = qs[:limit + 1] pages = list(qs) more = False if limit: more = len(pages) > limit pages = pages[:limit] results.extend([{'page': page.specific} for page in pages]) return { 'results': results, 'more': more, } permissions = [] input = { 'query': str, 'limit': Optional[int], } result = { 'results': g.NNList(SearchItem), 'more': bool, }
class external_accounts_field(helpers.BaseField): def resolve(self, obj, info): services = external_services_registry.all_services() result = [] for s in services: account = s.user_account(obj) if account: result.append(account) return result permissions = [user_perm('external_services.view_access')] result = g.NNList(ExternalServiceAccount)
def create_EventsListBlock(): def resolve_value(obj, info): qs = kocherga.events.models.Event.objects.public_only( ).filter_by_period(from_date=datetime.today()) return qs[:20] return g.ObjectType( 'EventsListBlock', interfaces=[WagtailBlock], fields=g.fields({ 'id': 'ID!', 'events': g.Field(g.NNList(event_types.Event), resolve=resolve_value), }), )
class wagtailCollectionPermissions(helpers.BaseField): WagtailCollectionPermission = g.ObjectType( 'WagtailCollectionPermission', fields=g.fields({ 'id': 'ID!', 'permission': g.NN(AuthPermission), 'collection': g.NN(wagtail_types.WagtailCollection), }), ) permissions = [] def resolve(self, group, info): return group.collection_permissions.all() result = g.NNList(WagtailCollectionPermission)
class watchmenShifts(helpers.BaseField): def resolve(self, _, info, from_date, to_date): from_date = datetime.strptime(from_date, '%Y-%m-%d').date() to_date = datetime.strptime(to_date, '%Y-%m-%d').date() if (to_date - from_date).days > 12 * 7: raise Exception("12 weeks max is allowed") return models.Shift.objects.items_range(from_date, to_date) permissions = [staffonly] args = { 'from_date': str, 'to_date': str, } result = g.NNList(types.WatchmenShift)
class ProjectIndexPage_projects(helpers.BaseField): def resolve(self, _, info, is_active=None): qs = models.ProjectPage.objects.all().live() qs = filter_queryset_by_page_permissions(info.context, qs) # TODO - filter by site for parity with `wagtailPage` GraphQL query if is_active is not None: qs = qs.filter(is_active=is_active) return list(qs) permissions = [] args = { 'is_active': Optional[bool], } result = g.NNList(ProjectPage)
class ratioTicketTypes(helpers.BaseFieldWithInput): def resolve(self, _, info, input): qs = models.TicketType.objects.for_active_trainings() if input.get('id'): qs = qs.filter(uuid=input['id']) if input.get('training_type'): qs = qs.filter(training__training_type=input['training_type']) return qs # this query is public, it's used in order form permissions = [] input = { 'id': 'ID', # get one ticket type by id 'training_type': Optional[str], # filter by training.training_type } result = g.NNList(types.RatioTicketType)
class watchmenWatchmenAll(helpers.BaseField): def resolve(self, _, info, currentStaff=False, currentRole=False): queryset = models.Watchman.objects.all() # TODO - move to model's manager if currentStaff: queryset = queryset.filter(member__user__is_staff=True) if currentRole: queryset = queryset.filter(priority__lt=3) return list(queryset) permissions = [staffonly] args = { 'currentStaff': Optional[bool], 'currentRole': Optional[bool], } result = g.NNList(types.WatchmenWatchman)
def create_PhotoRibbonBlock(): def resolve_value(obj, info, spec): return [image.get_rendition(spec) for image in obj.value] return g.ObjectType( 'PhotoRibbonBlock', interfaces=[WagtailBlock], fields=g.fields({ 'id': 'ID!', 'value': g.Field( g.NNList(WagtailImageRendition), args=g.arguments({'spec': str}), resolve=resolve_value, ), }), )
class wagtailImageSearch(helpers.BaseFieldWithInput): def resolve(self, _, info, input): images = wagtail.images.permissions.permission_policy.instances_user_has_any_permission_for( info.context.user, ['change', 'delete']).order_by('-created_at') query = input['query'] images = images.search(query) return { 'results': list(images), } permissions = [] input = { 'query': str, } result = { 'results': g.NNList(types.WagtailImage), # 'more': bool, # TODO }
class searchUsers(helpers.BaseFieldWithInput): def resolve(self, _, info, input): query = input['query'] if not query: # don't want to find anything by an empty query return { 'results': [], 'more': False, } qs = get_search_backend().search( query, models.User, fields=['email', 'first_name', 'last_name']) # TODO - logic copy-pasted from kocherga.wagtail.schema.queries.search, generalize limit = input.pop('limit', None) or 10 # Ask for one more to determine if there are more results qs = qs[:limit + 1] results = list(qs) more = len(results) > limit results = results[:limit] return { 'results': results, 'more': more, } permissions = [user_perm('auth.audit')] input = { 'query': str, 'limit': Optional[int], } result = { 'results': g.NNList(types.AuthUser), 'more': bool, }
def emailSubscribeChannelCreate(_): @check_permissions([staffonly]) def resolve(_, info, params): slug = params['slug'] interest_ids = params['interest_ids'] interests = models.MailchimpInterest.objects.filter(pk__in=interest_ids).all() instance = models.SubscribeChannel.objects.create(slug=slug) instance.interests.set(interests) return True # input EmailSubscribeChannelCreateInput { # slug: String! # interest_ids: [ID!]! # } Input = g.InputObjectType( 'EmailSubscribeChannelCreateInput', g.input_fields({'slug': str, 'interest_ids': g.NNList(g.ID)}), ) # TODO - rename params -> input return g.Field( g.Boolean, args=g.arguments({'params': g.NN(Input)}), resolve=resolve )
class wagtailPagePermissions(helpers.BaseField): # TODO - enum? PAGE_PERMISSION_TYPES is a constant in wagtail _permission_type = g.NN(g.String) WagtailSpecificPagePermission = g.ObjectType( 'WagtailSpecificPagePermission', fields=g.fields({ 'id': 'ID!', 'permission_type': _permission_type, 'page': g.NN(wagtail_types.WagtailPage), }), ) WagtailRootPagePermission = g.ObjectType( 'WagtailRootPagePermission', fields=g.fields({ 'id': 'ID!', 'permission_type': _permission_type, }), ) # TODO - interface instead of union? would be better for querying WagtailPagePermission = g.UnionType( 'WagtailPagePermission', types=[WagtailRootPagePermission, WagtailSpecificPagePermission], resolve_type=lambda obj, info, *_: ('WagtailRootPagePermission' if obj.page.is_root() else 'WagtailSpecificPagePermission'), ) # AuthGroup is very private so we don't need additional checks here permissions = [] def resolve(self, group, info): return group.page_permissions.all() result = g.NNList(WagtailPagePermission)
def suggested_dates_field(): def resolve(obj, info, limit, until_ts=None, from_date=None, to_date=None): from_date_parsed = None to_date_parsed = None if from_date: from_date_parsed = datetime.strptime(from_date, '%Y-%m-%d').date() if to_date: to_date_parsed = datetime.strptime(to_date, '%Y-%m-%d').date() elif until_ts: to_date_parsed = datetime.fromtimestamp(until_ts, tz=TZ).date() return obj.suggested_dates(from_date=from_date_parsed, to_date=to_date_parsed, limit=limit) return g.Field( g.NNList(g.String), args=g.arguments({ 'limit': int, 'from_date': Optional[str], 'to_date': Optional[str], 'until_ts': Optional[int], # deprecated }), resolve=resolve, )
from kocherga.auth.schema import types as auth_types from kocherga.graphql import django_utils, g from .. import models Comment = django_utils.DjangoObjectType( 'Comment', model=models.Comment, db_fields=['id', 'created', 'text'], extra_fields={ 'author': g.NN(auth_types.AuthUser), }, ) Commentable = g.InterfaceType( 'Commentable', fields={ 'comments_count': g.NN(g.Int), 'comments': g.NNList(Comment), }, )