def mutate(root, args, context, info): discussion_id = context.matchdict['discussion_id'] tag_id = args.get('id') tag_id = int(Node.from_global_id(tag_id)[1]) # The tag to replace or edit tag = models.Keyword.get(tag_id) require_instance_permission(CrudPermissions.UPDATE, tag, context) # The context of the mutation (Extract...) taggable = None taggable_id = args.get('taggable_id', None) if taggable_id: taggable_node = Node.from_global_id(taggable_id) taggable_id = int(taggable_node[1]) taggable = models.TaggableEntity.get_taggable_from_id( taggable_node[0], taggable_id) db = tag.db value = args.get('value') updated_tag = tag # The desired tag. None if not exists input_tag = models.Keyword.get_tag(value, discussion_id, db) if input_tag and taggable: # If we have an input_tag and taggable is not null, # we replace the current tag by the input_tag taggable.replace_tag(tag, input_tag) updated_tag = input_tag elif input_tag: # We can not change the value of the tag by an already existing tag value raise Exception("Tag already exists!") else: # If it's a new value, we replace the value of the current tag tag.value = value db.flush() return UpdateTag(tag=updated_tag)
class MusicQuery(ObjectType): genre = Node.Field(GenreNode) genres = DjangoFilterConnectionField(GenreNode) label = Node.Field(LabelNode) labels = DjangoFilterConnectionField(LabelNode) artist = Node.Field(ArtistNode) artists = DjangoFilterConnectionField(ArtistNode) album = Node.Field(AlbumNode) albums = DjangoFilterConnectionField(AlbumNode)
def mutate(root, args, context, info): cls = models.TokenVoteSpecification vote_spec_id = args.get('id') vote_spec_id = int(Node.from_global_id(vote_spec_id)[1]) title_entries = args.get('title_entries') instructions_entries = args.get('instructions_entries') exclusive_categories = args.get('exclusive_categories') token_categories = args.get('token_categories') with cls.default_db.no_autoflush as db: vote_spec = cls.get(vote_spec_id) require_instance_permission(CrudPermissions.UPDATE, vote_spec, context) update_langstring_from_input_entries( vote_spec, 'title', title_entries) update_langstring_from_input_entries( vote_spec, 'instructions', instructions_entries) vote_spec.is_custom = args.get('is_custom') vote_spec.exclusive_categories = exclusive_categories existing_token_categories = { token_category.id: token_category for token_category in vote_spec.token_categories} updated_token_categories = set() if token_categories and (not vote_spec.criterion_idea_id or vote_spec.is_custom): for idx, token_category_input in enumerate(token_categories): if not token_category_input.get('id', '-1').startswith('-'): id_ = int(Node.from_global_id(token_category_input['id'])[1]) updated_token_categories.add(id_) token_category = models.TokenCategorySpecification.get(id_) update_langstring_from_input_entries( token_category, 'name', token_category_input['title_entries']) token_category.total_number = token_category_input.get('total_number') token_category.color = token_category_input.get('color') else: title_ls = langstring_from_input_entries( token_category_input.get('title_entries', None)) total_number = token_category_input.get('total_number') typename = token_category_input.get('typename', 'category{}'.format(idx + 1)) color = token_category_input.get('color') vote_spec.token_categories.append( models.TokenCategorySpecification( total_number=total_number, typename=typename, name=title_ls, color=color) ) # remove token categories that are not in token_categories input for token_category_id in set(existing_token_categories.keys() ).difference(updated_token_categories): db.delete(existing_token_categories[token_category_id]) db.flush() return UpdateTokenVoteSpecification(vote_specification=vote_spec)
def mutate(root, args, context, info): options = args.get('options') if options is not None: cls = models.SelectField else: cls = models.TextField field_id = args.get('id') field_id = int(Node.from_global_id(field_id)[1]) field = cls.get(field_id) require_instance_permission(CrudPermissions.UPDATE, field, context) with cls.default_db.no_autoflush as db: title_entries = args.get('title_entries') if len(title_entries) == 0: raise Exception('field titleEntries needs at least one entry') update_langstring_from_input_entries(field, 'title', title_entries) field.order = args['order'] field.required = args['required'] field.hidden = args['hidden'] if options is not None: existing_options = { option.id: option for option in field.options } updated_options = set() for option_input in options: if not option_input.get('id', '-1').startswith('-'): # update the option id_ = int(Node.from_global_id(option_input['id'])[1]) updated_options.add(id_) option = models.SelectFieldOption.get(id_) update_langstring_from_input_entries( option, 'label', option_input['label_entries']) option.order = option_input['order'] else: # create the option label_ls = langstring_from_input_entries( option_input.get('label_entries', None)) order = option_input.get('order') field.options.append( models.SelectFieldOption(label=label_ls, order=order)) # remove options that are not in options input for option_id in set( existing_options.keys()).difference(updated_options): db.delete(existing_options[option_id]) db.flush() return UpdateTextField(field=field)
def mutate(root, args, context, info): options = args.get('options') if options is not None: cls = models.SelectField else: cls = models.TextField field_id = args.get('id') field_id = int(Node.from_global_id(field_id)[1]) field = cls.get(field_id) require_instance_permission(CrudPermissions.UPDATE, field, context) with cls.default_db.no_autoflush as db: title_entries = args.get('title_entries') if len(title_entries) == 0: raise Exception( 'field titleEntries needs at least one entry') update_langstring_from_input_entries(field, 'title', title_entries) field.order = args['order'] field.required = args['required'] field.hidden = args['hidden'] if options is not None: existing_options = { option.id: option for option in field.options} updated_options = set() for option_input in options: if not option_input.get('id', '-1').startswith('-'): # update the option id_ = int(Node.from_global_id(option_input['id'])[1]) updated_options.add(id_) option = models.SelectFieldOption.get(id_) update_langstring_from_input_entries( option, 'label', option_input['label_entries']) option.order = option_input['order'] else: # create the option label_ls = langstring_from_input_entries( option_input.get('label_entries', None)) order = option_input.get('order') field.options.append( models.SelectFieldOption( label=label_ls, order=order) ) # remove options that are not in options input for option_id in set(existing_options.keys() ).difference(updated_options): db.delete(existing_options[option_id]) db.flush() return UpdateTextField(field=field)
def mutate(root, args, context, info): cls = models.TokenVoteSpecification require_cls_permission(CrudPermissions.CREATE, cls, context) vote_session_id = args.get('vote_session_id') vote_session_id = int(Node.from_global_id(vote_session_id)[1]) title_entries = args.get('title_entries') instructions_entries = args.get('instructions_entries') exclusive_categories = args.get('exclusive_categories') token_categories = args.get('token_categories') is_custom = args.get('is_custom') with cls.default_db.no_autoflush as db: vote_session = db.query(models.VoteSession).get(vote_session_id) title_ls = langstring_from_input_entries(title_entries) instructions_ls = langstring_from_input_entries(instructions_entries) vote_spec = cls( title=title_ls, instructions=instructions_ls, exclusive_categories=exclusive_categories, is_custom=is_custom ) proposal_id = args.get('proposal_id') if proposal_id: proposal_id = int(Node.from_global_id(proposal_id)[1]) proposal = models.VoteProposal.get(proposal_id) vote_spec.criterion_idea = proposal vote_spec_template_id = args.get('vote_spec_template_id') if vote_spec_template_id: vote_spec_template_id = int(Node.from_global_id(vote_spec_template_id)[1]) vote_spec.vote_spec_template_id = vote_spec_template_id if token_categories and (not vote_spec.criterion_idea_id or vote_spec.is_custom): for idx, token_category in enumerate(token_categories): title_ls = langstring_from_input_entries( token_category.get('title_entries', None)) total_number = token_category.get('total_number') typename = token_category.get('typename', 'category{}'.format(idx + 1)) color = token_category.get('color') vote_spec.token_categories.append( models.TokenCategorySpecification( total_number=total_number, typename=typename, name=title_ls, color=color) ) db.add(vote_spec) vote_session.vote_specifications.append(vote_spec) db.flush() return CreateTokenVoteSpecification(vote_specification=vote_spec)
class Query(ObjectType): reporter = Node.Field(ReporterNode, description='Retrieve a single Reporter node.') reporters = DjangoFilterConnectionField( ReporterNode, description='Return a connection of Reporter.') publication = Node.Field(PublicationNode, description='Retrieve a single Publication node.') publications = DjangoFilterConnectionField( PublicationNode, description='Return a connection of Publication.') article = Node.Field(ArticleNode, description='Retrieve a single Article node.') articles = DjangoFilterConnectionField( ArticleNode, description='Return a connection of Article.')
def mutate(root, args, context, info): cls = models.ProfileField discussion_id = context.matchdict['discussion_id'] user_id = context.authenticated_userid agent_profile = models.AgentProfile.get(user_id) require_instance_permission(CrudPermissions.UPDATE, agent_profile, context) with cls.default_db.no_autoflush as db: for field_info in args.get('data'): profile_field_id = field_info['id'] profile_field_id = int(Node.from_global_id(profile_field_id)[1]) profile_field = cls.get(profile_field_id) if profile_field: require_instance_permission(CrudPermissions.UPDATE, profile_field, context) profile_field.value_data = field_info['value_data'] else: configurable_field_id = field_info['configurable_field_id'] configurable_field_id = int(Node.from_global_id(configurable_field_id)[1]) configurable_field = models.AbstractConfigurableField.get(configurable_field_id) if configurable_field.identifier == ConfigurableFieldIdentifiersEnum.FULLNAME.value: agent_profile.real_name_p = field_info['value_data']['value'] elif configurable_field.identifier == ConfigurableFieldIdentifiersEnum.EMAIL.value: agent_profile.preferred_email = field_info['value_data']['value'] elif configurable_field.identifier == ConfigurableFieldIdentifiersEnum.USERNAME.value: username = field_info['value_data']['value'] # same errors than in assembl/views/api2/auth.py if db.query(models.Username).filter( models.Username.user_id != agent_profile.id).filter( func.lower(models.Username.username) == username.lower()).count(): error = _("We already have a user with this username.") raise Exception(context.localizer.translate(error)) if len(username) > 20: error = _("The username must be less than 20 characters.") raise Exception(context.localizer.translate(error)) agent_profile.username_p = username elif configurable_field.identifier == ConfigurableFieldIdentifiersEnum.CUSTOM.value: require_cls_permission(CrudPermissions.CREATE, cls, context) profile_field = cls( agent_profile=agent_profile, configurable_field_id=configurable_field_id, discussion_id=discussion_id, value_data=field_info['value_data'] ) db.add(profile_field) db.flush() profile_fields = get_query(cls, context).filter(cls.discussion_id == discussion_id) return UpdateProfileFields(profile_fields=profile_fields)
def mutate(root, args, context, info): cls = models.GaugeVoteSpecification vote_spec_id = args.get('id') vote_spec_id = int(Node.from_global_id(vote_spec_id)[1]) title_entries = args.get('title_entries') instructions_entries = args.get('instructions_entries') choices = args.get('choices') with cls.default_db.no_autoflush as db: vote_spec = cls.get(vote_spec_id) require_instance_permission(CrudPermissions.UPDATE, vote_spec, context) update_langstring_from_input_entries(vote_spec, 'title', title_entries) update_langstring_from_input_entries(vote_spec, 'instructions', instructions_entries) vote_spec.is_custom = args.get('is_custom') existing_choices = { choice.id: choice for choice in vote_spec.choices } updated_choices = set() for idx, choice_input in enumerate(choices): if not choice_input.get('id', '-1').startswith('-'): # update the choice id_ = int(Node.from_global_id(choice_input['id'])[1]) updated_choices.add(id_) choice = models.GaugeChoiceSpecification.get(id_) update_langstring_from_input_entries( choice, 'label', choice_input['label_entries']) choice.value = choice_input['value'] else: # create a choice label_ls = langstring_from_input_entries( choice_input.get('label_entries', None)) value = choice_input.get('value') vote_spec.choices.append( models.GaugeChoiceSpecification(label=label_ls, value=value)) # remove choices that are not in choices input for choice_id in set( existing_choices.keys()).difference(updated_choices): db.delete(existing_choices[choice_id]) db.flush() return UpdateGaugeVoteSpecification(vote_specification=vote_spec)
def mutate(root, args, context, info): idea_id = args.get('idea_id') idea_id = int(Node.from_global_id(idea_id)[1]) idea = models.Idea.get(idea_id) discussion_id = context.matchdict["discussion_id"] discussion = models.Discussion.get(discussion_id) if idea is None: raise Exception( "A vote session requires an idea associated to it, check ideaId value") if idea.get_associated_phase() is not None: if idea.message_view_override != MessageView.voteSession.value: raise Exception( "A vote session can only be created or edited if the view of the associated idea is of type voteSession") db = idea.db vote_session = db.query(models.VoteSession).filter(models.VoteSession.idea_id == idea_id).first() if vote_session is None: require_cls_permission(CrudPermissions.CREATE, models.VoteSession, context) vote_session = models.VoteSession(discussion=discussion, idea=idea) else: require_instance_permission(CrudPermissions.UPDATE, vote_session, context) if args.get('see_current_votes', None) is not None: vote_session.see_current_votes = args['see_current_votes'] db = vote_session.db update_langstrings(vote_session, langstrings_defs, args) db.add(vote_session) db.flush() return UpdateVoteSession(vote_session=vote_session)
def mutate(root, args, context, info): model = models.User discussion_id = context.matchdict['discussion_id'] discussion = models.Discussion.get(discussion_id) user_id = context.authenticated_userid or Everyone global_id = args.get('id') id_ = int(Node.from_global_id(global_id)[1]) user = model.get(id_) # Global permission check. Permission is checked in the preferences setter # Is it necessary? permissions = get_permissions(user_id, discussion_id) allowed = user.user_can( user_id, CrudPermissions.UPDATE, permissions) if not allowed: raise HTTPUnauthorized("You don't have the authorization to update this haversting locale. If you think it's an error, please reconnect to assembl.") with model.default_db.no_autoflush as db: preferences = user.get_preferences_for_discussion(discussion) # Permission check in the preferences setter # See models.user_key_value and models.preferences preference_data_list preferences['harvesting_translation'] = args.get('translation') db.flush() return UpdateHarvestingTranslationPreference( preferences=preferences)
def mutate(root, args, context, info): EMBED_ATTACHMENT = models.AttachmentPurpose.EMBED_ATTACHMENT.value discussion_id = context.matchdict['discussion_id'] discussion = models.Discussion.get(discussion_id) post_id = args.get('post_id') post_id = int(Node.from_global_id(post_id)[1]) post = models.Post.get(post_id) cls = models.PostAttachment require_cls_permission(CrudPermissions.CREATE, cls, context) # add uploaded file as an attachment to the post attachment = args.get('file') if attachment is not None: filename = os.path.basename(context.POST[attachment].filename) mime_type = context.POST[attachment].type document = models.File( discussion=discussion, mime_type=mime_type, title=filename) document.add_file_data(context.POST[attachment].file) attachment = models.PostAttachment( document=document, discussion=discussion, creator_id=context.authenticated_userid, post=post, title=filename, attachmentPurpose=EMBED_ATTACHMENT ) post.db.add(attachment) post.db.flush() return AddPostAttachment(post=post)
def mutate(root, args, context, info): cls = models.VoteProposal require_cls_permission(CrudPermissions.CREATE, cls, context) vote_session_id = args.get('vote_session_id') vote_session_id = int(Node.from_global_id(vote_session_id)[1]) vote_session = models.VoteSession.get(vote_session_id) title_entries = args.get('title_entries') description_entries = args.get('description_entries') discussion_id = context.matchdict['discussion_id'] discussion = models.Discussion.get(discussion_id) with cls.default_db.no_autoflush as db: title_ls = langstring_from_input_entries(title_entries) description_ls = langstring_from_input_entries(description_entries) if vote_session is None: raise Exception( "A vote session is required before creating a proposal") idea = vote_session.idea proposal = cls( discussion_id=discussion_id, discussion=discussion, title=title_ls, description=description_ls ) db.add(proposal) order = len(idea.get_children()) + 1.0 db.add( models.IdeaLink(source=idea, target=proposal, order=args.get('order', order))) db.flush() return CreateProposal(proposal=proposal)
class Query(graphene.ObjectType): node = Node.Field() allAwss = MongoengineConnectionField(AWS) allAzures = MongoengineConnectionField(Azure) sortAWSByHost = MongoengineConnectionField(AWS) sortAzureByHost = MongoengineConnectionField(Azure) sortAWSByName = MongoengineConnectionField(AWS) sortAzureByName = MongoengineConnectionField(Azure) fetchAWSData = graphene.String() fetchAzureData = graphene.String() allAwsImages = MongoengineConnectionField(AWSImage) allAzureImages = MongoengineConnectionField(AzureImage) def resolve_sortAWSByHost(self, info, **args): return AwsModel.objects().order_by("-isFavorite", "host") def resolve_sortAzureByHost(self, info, **args): return AzureModel.objects().order_by("-isFavorite", "host") def resolve_sortAWSByName(self, info, **args): return AwsModel.objects().order_by("-isFavorite", "name") def resolve_sortAzureByName(self, info, **args): return AzureModel.objects().order_by("-isFavorite", "name") def resolve_fetchAWSData(self, info): init_aws() return "Success" def resolve_fetchAzureData(self, info): init_azure() return "Success"
class Query(graphene.ObjectType): node = Node.Field() reporter = graphene.Field(ReporterNode) article = graphene.Field(ArticleNode) def resolve_reporter(self, *args, **kwargs): return Reporter(id=1, first_name='ABA', last_name='X')
def test_mutation_add_extract_comment(admin_user, graphql_request, idea_in_thread_phase, top_post_in_thread_phase, extract_post_1_to_subidea_1_1): from graphene.relay import Node raw_id = int(Node.from_global_id(top_post_in_thread_phase)[1]) from assembl.models import Post post = Post.get(raw_id) post.extracts.append(extract_post_1_to_subidea_1_1) post.db.flush() extract_id = extract_post_1_to_subidea_1_1.graphene_id() idea_id = idea_in_thread_phase res = schema.execute(u""" mutation createPost { createPost( ideaId:"%s", extractId:"%s", subject:"Manger des choux à la crème", body:"Je recommande de manger des choux à la crème, c'est très bon, et ça permet de maintenir l'industrie de la patisserie française." ) { post { ... on Post { parentExtractId } } } } """ % (idea_id, extract_id), context_value=graphql_request) assert res.data['createPost']['post']['parentExtractId'] == extract_id
class Query(graphene.ObjectType): node = Node.Field() reporter = graphene.Field(ReporterNode) all_articles = SQLAlchemyConnectionField(ArticleNode.connection) def resolve_reporter(self, _info): return session.query(Reporter).first()
def mutate(root, args, context, info): cls = models.VoteProposal require_cls_permission(CrudPermissions.CREATE, cls, context) vote_session_id = args.get('vote_session_id') vote_session_id = int(Node.from_global_id(vote_session_id)[1]) vote_session = models.VoteSession.get(vote_session_id) title_entries = args.get('title_entries') description_entries = args.get('description_entries') discussion_id = context.matchdict['discussion_id'] discussion = models.Discussion.get(discussion_id) with cls.default_db.no_autoflush as db: title_ls = langstring_from_input_entries(title_entries) description_ls = langstring_from_input_entries(description_entries) if vote_session is None: raise Exception( "A vote session is required before creating a proposal") idea = vote_session.idea proposal = cls(discussion_id=discussion_id, discussion=discussion, title=title_ls, description=description_ls) db.add(proposal) order = len(idea.get_children()) + 1.0 db.add( models.IdeaLink(source=idea, target=proposal, order=args.get('order', order))) db.flush() return CreateProposal(proposal=proposal)
def mutate(root, args, context, info): cls = models.LandingPageModule configuration = args.get('configuration') order = args.get('order') enabled = args.get('enabled') module_id = args.get('id') module_id = int(Node.from_global_id(module_id)[1]) require_instance_permission(CrudPermissions.UPDATE, cls.get(module_id), context) with cls.default_db.no_autoflush as db: module = db.query(models.LandingPageModule).filter( models.LandingPageModule.id == module_id).one() module.enabled = enabled module.order = order module.configuration = configuration title_entries = args.get('title_entries') update_langstring_from_input_entries(module, 'title', title_entries) subtitle_entries = args.get('subtitle_entries') update_langstring_from_input_entries(module, 'subtitle', subtitle_entries) db.flush() return UpdateLandingPageModule(landing_page_module=module)
class Query(graphene.ObjectType): node = Node.Field() bikes = MongoengineConnectionField(BikeType) shop_list = graphene.List(ShopType) def resolve_shop_list(self, info): return Shop.objects.all()
class Query(graphene.ObjectType): node = Node.Field() # required by Relay spec courses = graphene.List(Course, required=False, description='Returns all courses') course = graphene.Field( Course, id=graphene.ID(required=True), required=False, description='Returns course by id', ) # assignment = graphene.Field( # Assignment, # id=graphene.ID(required=True), # required=False, # description='Returns assignment by id', # ) def resolve_courses(self, info): return [c for c in COURSES] def resolve_course(self, info, id): object_type, object_id = from_global_id(id) if object_type != 'Course': raise graphql.GraphQLError('Bad course id') return [c for c in COURSES if c.id == object_id][0]
def test_graphql_cors_request(discussion, test_webrequest, admin_user, test_app, test_session, graphql_registry): from assembl.views import create_get_route get_route = create_get_route(test_webrequest, discussion) old_pref = discussion.preferences['graphql_valid_cors'] cors_headers = "https://mycoolsite.com,https://myothercoolsite.net" # no space between comma, just as graphql view discussion.preferences['graphql_valid_cors'] = cors_headers.split(",") test_session.flush() route = get_route('graphql') query = graphql_registry['userQuery'] parameters = { "query": query, "variables": { "id": admin_user.graphene_id() } } resp = test_app.post( route, xhr=True, content_type='application/json', params=json.dumps(parameters) ) assert resp.status_code == 200 has_cors_headers = 'Access-Control-Allow-Origin' in [r[0] for r in resp.headerlist] body = json.loads(resp.body) user_id = int(Node.from_global_id(body['data']['user']['id'])[1]) assert user_id == admin_user.id assert has_cors_headers cors_header_list = [x[1] for x in resp.headerlist if x[0] == 'Access-Control-Allow-Origin'][0] assert cors_header_list == cors_headers discussion.preferences['graphql_valid_cors'] = old_pref test_session.flush()
def post_published_for_bright_mirror_participant( request, test_session, discussion, admin_user, participant1_user, bright_mirror): from assembl.models import Post, Idea, LangString, IdeaRelatedPostLink, PublicationStates from graphene.relay import Node idea_id = bright_mirror raw_id = int(Node.from_global_id(idea_id)[1]) idea = Idea.get(raw_id) p = Post( discussion=discussion, creator=participant1_user, subject=LangString.create(u"Published by participant"), body=LangString.create(u"A simple published fiction by participant"), type='post', publication_state=PublicationStates.PUBLISHED, message_id="*****@*****.**", creation_date = datetime.utcnow()) idc = IdeaRelatedPostLink( idea=idea, creator=admin_user, content=p) test_session.add(p) test_session.add(idc) test_session.flush() def fin(): print "finalizer post_published_for_bright_mirror" test_session.delete(p) test_session.delete(idc) test_session.flush() request.addfinalizer(fin) return p
def mutate(root, args, context, info): user_id = context.authenticated_userid or Everyone post_id = args.get('post_id') post_id = int(Node.from_global_id(post_id)[1]) post = models.Post.get(post_id) discussion_id = context.matchdict['discussion_id'] permissions = get_permissions(user_id, discussion_id) require_instance_permission(CrudPermissions.DELETE, post, context) # Same logic as in assembl/views/api2/post.py:delete_post_instance # Remove extracts associated to this post extracts_to_remove = post.db.query(models.Extract).filter( models.Extract.content_id == post.id).all() for extract in extracts_to_remove: extract.delete() if user_id == post.creator_id and P_DELETE_MY_POST in permissions: cause = models.PublicationStates.DELETED_BY_USER elif P_DELETE_POST in permissions: cause = models.PublicationStates.DELETED_BY_ADMIN post.delete_post(cause) post.db.flush() return DeletePost(post=post)
def mutate(root, args, context, info): idea_id = args.get('idea_id') idea_id = int(Node.from_global_id(idea_id)[1]) idea = models.Idea.get(idea_id) discussion_id = context.matchdict["discussion_id"] discussion = models.Discussion.get(discussion_id) if idea is None: raise Exception( "A vote session requires an idea associated to it, check ideaId value" ) if idea.get_associated_phase() is not None: if idea.message_view_override != MessageView.voteSession.value: raise Exception( "A vote session can only be created or edited if the view of the associated idea is of type voteSession" ) db = idea.db vote_session = db.query(models.VoteSession).filter( models.VoteSession.idea_id == idea_id).first() if vote_session is None: require_cls_permission(CrudPermissions.CREATE, models.VoteSession, context) vote_session = models.VoteSession(discussion=discussion, idea=idea) else: require_instance_permission(CrudPermissions.UPDATE, vote_session, context) if args.get('see_current_votes', None) is not None: vote_session.see_current_votes = args['see_current_votes'] db = vote_session.db update_langstrings(vote_session, langstrings_defs, args) db.add(vote_session) db.flush() return UpdateVoteSession(vote_session=vote_session)
def test_node_for_vote(self): link = LinkModel.objects.create(description='Test', url='http://a.com') user = create_test_user() vote = VoteModel.objects.create(link_id=link.pk, user_id=user.pk) vote_gid = Node.to_global_id('Vote', vote.pk) query = ''' query { node(id: "%s") { id ...on Vote { link { url } } } } ''' % vote_gid expected = { 'node': { 'id': vote_gid, 'link': { 'url': 'http://a.com', } } } schema = graphene.Schema(query=Query) result = schema.execute(query) self.assertIsNone(result.errors, msg=format_graphql_errors(result.errors)) self.assertEqual(result.data, expected, msg='\n'+repr(expected)+'\n'+repr(result.data))
def test_mutation_create_discussion_phase_empty_identifier(graphql_request, discussion_with_2_phase_interface_v2, graphql_registry): res = schema.execute( graphql_registry['createDiscussionPhase'], context_value=graphql_request, variable_values={ "lang": u"en", "identifier": None, "titleEntries": [ { "localeCode": "en", "value": u"My new phase" } ], "start": '2018-01-20T09:01:00.000001Z', "end": '2018-05-20T00:00:00.100001Z', "order": 1.0 } ) assert res.errors is None phase = res.data['createDiscussionPhase']['discussionPhase'] assert phase['id'] assert phase['identifier'] == Node.from_global_id(phase['id'])[1] assert phase['title'] == u'My new phase' assert phase['titleEntries'][0]['localeCode'] == u'en' assert phase['titleEntries'][0]['value'] == u'My new phase' assert phase['start'] == u'2018-01-20T09:01:00.000001+00:00' assert phase['end'] == u'2018-05-20T00:00:00.100001+00:00' assert phase['order'] == 1.0
class Query(graphene.ObjectType): node = Node.Field() reporter = graphene.Field(ReporterNode) article = graphene.Field(ArticleNode) def resolve_reporter(self, info): return Reporter(id=1, first_name="ABA", last_name="X")
def mutate(root, args, context, info): cls = models.Section section_id = args.get('id') section_id = int(Node.from_global_id(section_id)[1]) section = cls.get(section_id) require_instance_permission(CrudPermissions.UPDATE, section, context) with cls.default_db.no_autoflush as db: title_entries = args.get('title_entries') if title_entries is not None and len(title_entries) == 0: raise Exception( 'section titleEntries needs at least one entry') # Better to have this message than # 'NoneType' object has no attribute 'owner_object' # when creating the saobj below if title=None update_langstring_from_input_entries( section, 'title', title_entries) kwargs = {} kwargs['url'] = args.get('url', None) kwargs['order'] = args.get('order', 10.0) for attr, value in kwargs.items(): setattr(section, attr, value) db.flush() return UpdateSection(section=section)
def mutate(root, args, context, info): require_cls_permission(CrudPermissions.CREATE, models.Extract, context) discussion_id = context.matchdict['discussion_id'] user_id = context.authenticated_userid or Everyone post_id = args.get('post_id') post_id = int(Node.from_global_id(post_id)[1]) post = models.Post.get(post_id) new_extract = models.Extract(creator_id=user_id, owner_id=user_id, discussion_id=discussion_id, body=args.get('body'), important=args.get('important', False), content=post) post.db.add(new_extract) range = models.TextFragmentIdentifier( extract=new_extract, xpath_start=args.get('xpath_start'), offset_start=args.get('offset_start'), xpath_end=args.get('xpath_end'), offset_end=args.get('offset_end')) post.db.add(range) post.db.flush() return AddPostExtract(post=post)
def test_get_long_title_on_idea(graphql_request, idea_in_thread_phase): # This is the "What you need to know" idea_id = idea_in_thread_phase from graphene.relay import Node raw_id = int(Node.from_global_id(idea_id)[1]) from assembl.models import Idea idea = Idea.get(raw_id) idea.long_title = u'What you need to know' idea.db.flush() res = schema.execute(u""" query Idea($lang: String!, $id: ID!) { idea: node(id: $id) { ... on Idea { title(lang: $lang) longTitle description(lang: $lang) imgUrl } } } """, context_value=graphql_request, variable_values={ "id": idea_id, "lang": u'en', }) assert json.loads(json.dumps(res.data)) == { u'idea': { u'title': u'Understanding the dynamics and issues', u'longTitle': u'What you need to know', u'description': u'', u'imgUrl': None } }
def test_node_for_user(self): user = create_test_user() user_gid = Node.to_global_id('User', user.pk) query = ''' query { node(id: "%s") { id ...on User { name } } } ''' % user_gid expected = { 'node': { 'id': user_gid, 'name': user.name, } } schema = graphene.Schema(query=Query) result = schema.execute(query) self.assertIsNone(result.errors, msg=format_graphql_errors(result.errors)) self.assertEqual(result.data, expected, msg='\n' + repr(expected) + '\n' + repr(result.data))
def test_no_announcement_on_ideas(graphql_request, idea_with_en_fr): from graphene.relay import Node idea_id = idea_with_en_fr.id node_id = Node.to_global_id('Idea', idea_id) res = schema.execute(u""" query Idea($id: ID!, $lang: String!){ idea: node(id: $id) { ... on Idea { announcement { title(lang: $lang) body(lang: $lang) } } } }""", context_value=graphql_request, variable_values={ "id": node_id, "lang": "en" }) assert json.loads(json.dumps(res.data)) == { u'idea': { u'announcement': None } }
def mutate(root, args, context, info): cls = models.Section discussion_id = context.matchdict['discussion_id'] user_id = context.authenticated_userid or Everyone section_id = args.get('id') section_id = int(Node.from_global_id(section_id)[1]) section = cls.get(section_id) permissions = get_permissions(user_id, discussion_id) allowed = section.user_can(user_id, CrudPermissions.UPDATE, permissions) if not allowed: raise HTTPUnauthorized() with cls.default_db.no_autoflush as db: title_entries = args.get('title_entries') if title_entries is not None and len(title_entries) == 0: raise Exception( 'section titleEntries needs at least one entry') # Better to have this message than # 'NoneType' object has no attribute 'owner_object' # when creating the saobj below if title=None update_langstring_from_input_entries(section, 'title', title_entries) kwargs = {} kwargs['url'] = args.get('url', None) kwargs['order'] = args.get('order', 10.0) for attr, value in kwargs.items(): setattr(section, attr, value) db.flush() return UpdateSection(section=section)
def post_draft_for_bright_mirror( request, test_session, discussion, moderator_user, bright_mirror): from assembl.models import Post, Idea, LangString, IdeaRelatedPostLink, PublicationStates from graphene.relay import Node idea_id = bright_mirror raw_id = int(Node.from_global_id(idea_id)[1]) idea = Idea.get(raw_id) p = Post( discussion=discussion, creator=moderator_user, subject=LangString.create(u"Draft"), body=LangString.create(u"A simple draft fiction"), type='post', publication_state=PublicationStates.DRAFT, message_id="*****@*****.**", creation_date = datetime.utcnow() - timedelta(days=7)) idc = IdeaRelatedPostLink( idea=idea, creator=moderator_user, content=p) test_session.add(p) test_session.add(idc) test_session.flush() def fin(): print "finalizer post_draft_for_bright_mirror" test_session.delete(p) test_session.delete(idc) test_session.flush() request.addfinalizer(fin) return p
def mutate(root, args, context, info): model = models.User discussion_id = context.matchdict['discussion_id'] discussion = models.Discussion.get(discussion_id) user_id = context.authenticated_userid or Everyone global_id = args.get('id') id_ = int(Node.from_global_id(global_id)[1]) user = model.get(id_) # Global permission check. Permission is checked in the preferences setter # Is it necessary? permissions = get_permissions(user_id, discussion_id) allowed = user.user_can(user_id, CrudPermissions.UPDATE, permissions) if not allowed: raise HTTPUnauthorized( "The authenticated user can't update this harvesting locale") with model.default_db.no_autoflush as db: preferences = user.get_preferences_for_discussion(discussion) # Permission check in the preferences setter # See models.user_key_value and models.preferences preference_data_list preferences['harvesting_translation'] = args.get('translation') db.flush() return UpdateHarvestingTranslationPreference(preferences=preferences)
def mutate(root, args, context, info): discussion_id = context.matchdict['discussion_id'] discussion = models.Discussion.get(discussion_id) user_id = context.authenticated_userid or Everyone post_id = args.get('post_id') post_id = int(Node.from_global_id(post_id)[1]) post = models.Content.get(post_id) permissions = get_permissions(user_id, discussion_id) allowed = SentimentOfPost.user_can_cls( user_id, CrudPermissions.CREATE, permissions) if not allowed: raise HTTPUnauthorized() sentiment_type = args.get('type') if SentimentTypes.LIKE.name == sentiment_type: sentiment = LikeSentimentOfPost( post=post, discussion=discussion, actor_id=user_id) elif SentimentTypes.DISAGREE.name == sentiment_type: sentiment = DisagreeSentimentOfPost( post=post, discussion=discussion, actor_id=user_id) elif SentimentTypes.DONT_UNDERSTAND.name == sentiment_type: sentiment = DontUnderstandSentimentOfPost( post=post, discussion=discussion, actor_id=user_id) elif SentimentTypes.MORE_INFO.name == sentiment_type: sentiment = MoreInfoSentimentOfPost( post=post, discussion=discussion, actor_id=user_id) sentiment = sentiment.handle_duplication( permissions=permissions, user_id=user_id) sentiment.db.add(sentiment) sentiment.db.flush() return AddSentiment(post=post)
def mutate(root, args, context, info): cls = models.Section section_id = args.get('id') section_id = int(Node.from_global_id(section_id)[1]) section = cls.get(section_id) require_instance_permission(CrudPermissions.UPDATE, section, context) with cls.default_db.no_autoflush as db: title_entries = args.get('title_entries') if title_entries is not None and len(title_entries) == 0: raise Exception( 'section titleEntries needs at least one entry') # Better to have this message than # 'NoneType' object has no attribute 'owner_object' # when creating the saobj below if title=None update_langstring_from_input_entries(section, 'title', title_entries) kwargs = {} kwargs['url'] = args.get('url', None) kwargs['order'] = args.get('order', 10.0) for attr, value in kwargs.items(): setattr(section, attr, value) db.flush() return UpdateSection(section=section)
def mutate(root, args, context, info): discussion_id = context.matchdict['discussion_id'] taggable = None post = None taggable_id = args.get('taggable_id', None) if taggable_id: taggable_node = Node.from_global_id(taggable_id) taggable_id = int(taggable_node[1]) taggable = models.TaggableEntity.get_taggable_from_id( taggable_node[0], taggable_id) if isinstance(taggable, models.Post): post = taggable require_instance_permission(CrudPermissions.CREATE, taggable, context) value = args.get('value').lower() db = taggable.db tag = models.Keyword.get_tag(value, discussion_id, db) if not tag: tag = models.Keyword(value=value, discussion_id=discussion_id) if tag not in taggable.tags: taggable.tags = taggable.tags + [tag] db.flush() return AddTag(tag=tag, post=post)
def mutate(root, args, context, info): cls = models.Idea require_cls_permission(CrudPermissions.CREATE, cls, context) vote_session_id = args.get('vote_session_id') vote_session_id = int(Node.from_global_id(vote_session_id)[1]) vote_session = models.VoteSession.get(vote_session_id) title_entries = args.get('title_entries') description_entries = args.get('description_entries') discussion_id = context.matchdict['discussion_id'] discussion = models.Discussion.get(discussion_id) with cls.default_db.no_autoflush as db: title_ls = langstring_from_input_entries(title_entries) description_ls = langstring_from_input_entries(description_entries) proposal = cls(discussion_id=discussion_id, discussion=discussion, title=title_ls, description=description_ls) db.add(proposal) phase = vote_session.discussion_phase root_thematic = get_root_thematic_for_phase(phase) if root_thematic is None: raise Exception( "There is no root thematic for this vote session.") order = len(root_thematic.get_children()) + 1.0 db.add( models.IdeaLink(source=root_thematic, target=proposal, order=args.get('order', order))) db.flush() return CreateProposal(proposal=proposal)
def mutate(root, args, context, info): discussion_id = context.matchdict['discussion_id'] user_id = context.authenticated_userid or Everyone post_id = args.get('post_id') post_id = int(Node.from_global_id(post_id)[1]) post = models.Post.get(post_id) permissions = get_permissions(user_id, discussion_id) allowed = post.user_can(user_id, CrudPermissions.DELETE, permissions) if not allowed: raise HTTPUnauthorized() # Same logic as in assembl/views/api2/post.py:delete_post_instance # Remove extracts associated to this post extracts_to_remove = post.db.query( models.Extract).filter(models.Extract.content_id == post.id).all() for extract in extracts_to_remove: extract.delete() if user_id == post.creator_id and P_DELETE_MY_POST in permissions: cause = models.PublicationStates.DELETED_BY_USER elif P_DELETE_POST in permissions: cause = models.PublicationStates.DELETED_BY_ADMIN post.delete_post(cause) post.db.flush() return DeletePost(post=post)
def mutate(root, args, context, info): cls = models.GaugeVoteSpecification vote_spec_id = args.get('id') vote_spec_id = int(Node.from_global_id(vote_spec_id)[1]) title_entries = args.get('title_entries') instructions_entries = args.get('instructions_entries') choices = args.get('choices') with cls.default_db.no_autoflush as db: vote_spec = cls.get(vote_spec_id) require_instance_permission(CrudPermissions.UPDATE, vote_spec, context) update_langstring_from_input_entries( vote_spec, 'title', title_entries) update_langstring_from_input_entries( vote_spec, 'instructions', instructions_entries) vote_spec.is_custom = args.get('is_custom') existing_choices = { choice.id: choice for choice in vote_spec.choices} updated_choices = set() for idx, choice_input in enumerate(choices): if not choice_input.get('id', '-1').startswith('-'): # update the choice id_ = int(Node.from_global_id(choice_input['id'])[1]) updated_choices.add(id_) choice = models.GaugeChoiceSpecification.get(id_) update_langstring_from_input_entries( choice, 'label', choice_input['label_entries']) choice.value = choice_input['value'] else: # create a choice label_ls = langstring_from_input_entries( choice_input.get('label_entries', None)) value = choice_input.get('value') vote_spec.choices.append( models.GaugeChoiceSpecification( label=label_ls, value=value) ) # remove choices that are not in choices input for choice_id in set(existing_choices.keys() ).difference(updated_choices): db.delete(existing_choices[choice_id]) db.flush() return UpdateGaugeVoteSpecification(vote_specification=vote_spec)
def mutate(root, args, context, info): proposal_id = args.get('id') proposal_id = int(Node.from_global_id(proposal_id)[1]) proposal = models.VoteProposal.get(proposal_id) require_instance_permission(CrudPermissions.DELETE, proposal, context) proposal.is_tombstone = True proposal.db.flush() return DeleteProposal(success=True)
def mutate(root, args, context, info): extract_id = args.get('extract_id') extract_id = int(Node.from_global_id(extract_id)[1]) extract = models.Extract.get(extract_id) require_instance_permission(CrudPermissions.UPDATE, extract, context) # Publish the extract extract.extract_state = models.ExtractStates.PUBLISHED.value extract.db.flush() return ConfirmExtract(success=True)
def resolve_vote_session(self, args, context, info): discussion_id = context.matchdict['discussion_id'] discussion = models.Discussion.get(discussion_id) idea_id = args.get('idea_id') idea_id = int(Node.from_global_id(idea_id)[1]) vote_session = discussion.db.query(models.VoteSession).filter(models.VoteSession.idea_id == idea_id).first() if vote_session is not None: require_instance_permission(CrudPermissions.READ, vote_session, context) return vote_session
def mutate(root, args, context, info): resource_id = args.get('resource_id') resource_id = int(Node.from_global_id(resource_id)[1]) resource = models.Resource.get(resource_id) require_instance_permission(CrudPermissions.DELETE, resource, context) resource.db.delete(resource) resource.db.flush() return DeleteResource(success=True)
def mutate(root, args, context, info): post_id = args.get('post_id') post_id = int(Node.from_global_id(post_id)[1]) post = models.Post.get(post_id) require_instance_permission(CrudPermissions.DELETE, post, context) post.undelete_post() post.db.flush() return UndeletePost(post=post)
def mutate(root, args, context, info): cls = models.GaugeVoteSpecification require_cls_permission(CrudPermissions.CREATE, cls, context) vote_session_id = args.get('vote_session_id') vote_session_id = int(Node.from_global_id(vote_session_id)[1]) title_entries = args.get('title_entries') instructions_entries = args.get('instructions_entries') choices = args.get('choices') with cls.default_db.no_autoflush as db: vote_session = db.query(models.VoteSession).get(vote_session_id) title_ls = langstring_from_input_entries(title_entries) instructions_ls = langstring_from_input_entries(instructions_entries) vote_spec = cls( title=title_ls, instructions=instructions_ls, is_custom=args.get('is_custom') ) proposal_id = args.get('proposal_id') if proposal_id: proposal_id = int(Node.from_global_id(proposal_id)[1]) proposal = models.VoteProposal.get(proposal_id) vote_spec.criterion_idea = proposal vote_spec_template_id = args.get('vote_spec_template_id') if vote_spec_template_id: vote_spec_template_id = int(Node.from_global_id(vote_spec_template_id)[1]) vote_spec.vote_spec_template_id = vote_spec_template_id for idx, choice in enumerate(choices): label_ls = langstring_from_input_entries( choice['label_entries']) value = choice['value'] vote_spec.choices.append( models.GaugeChoiceSpecification( label=label_ls, value=value) ) db.add(vote_spec) vote_session.vote_specifications.append(vote_spec) db.flush() return CreateGaugeVoteSpecification(vote_specification=vote_spec)
def mutate(root, args, context, info): require_cls_permission(CrudPermissions.CREATE, models.TokenIdeaVote, context) discussion_id = context.matchdict['discussion_id'] discussion = models.Discussion.get(discussion_id) user_id = context.authenticated_userid vote_value = args.get('vote_value') proposal_id = args.get('proposal_id') proposal_id = int(Node.from_global_id(proposal_id)[1]) proposal = models.Idea.get(proposal_id) token_category_id = args.get('token_category_id') token_category_id = int(Node.from_global_id(token_category_id)[1]) token_category = models.TokenCategorySpecification.get(token_category_id) vote_spec_id = args.get('vote_spec_id') vote_spec_id = int(Node.from_global_id(vote_spec_id)[1]) vote_spec = models.AbstractVoteSpecification.get(vote_spec_id) vote = models.TokenIdeaVote.query.filter_by( vote_spec_id=vote_spec.id, tombstone_date=None, voter_id=user_id, token_category_id=token_category_id).first() if vote_value == 0: if vote is not None: vote.is_tombstone = True else: if vote is None or vote.vote_value != vote_value: vote = models.TokenIdeaVote( discussion=discussion, vote_spec=vote_spec, widget=vote_spec.widget, voter_id=user_id, idea=proposal, vote_value=vote_value, token_category=token_category) permissions = get_permissions(user_id, discussion_id) vote = vote.handle_duplication( permissions=permissions, user_id=user_id) vote.db.add(vote) proposal.db.flush() return AddTokenVote(vote_specification=vote_spec)
def mutate(root, args, context, info): extract_id = args.get('extract_id') extract_id = int(Node.from_global_id(extract_id)[1]) extract = models.Extract.get(extract_id) require_instance_permission(CrudPermissions.UPDATE, extract, context) extract.important = args.get('important', False) extract.extract_action = getattr( models.ExtractActionVocabulary.Enum, args.get('extract_action', ''), None) extract.extract_nature = getattr( models.ExtractNatureVocabulary.Enum, args.get('extract_nature', ''), None) body = args.get('body', None) if body: extract.body = body if args.get('idea_id'): idea_id = int(Node.from_global_id(args.get('idea_id'))[1]) extract.idea_id = idea_id extract.db.flush() return UpdateExtract(extract=extract)
def mutate(root, args, context, info): discussion_id = context.matchdict['discussion_id'] extract_id = args.get('id') extract_id = int(Node.from_global_id(extract_id)[1]) extract = models.Extract.get(extract_id) require_instance_permission(CrudPermissions.UPDATE, extract, context) db = extract.db tags = models.Keyword.get_tags(args.get('tags', []), discussion_id, db) extract.tags = tags['new_tags'] + tags['tags'] db.flush() return UpdateExtractTags(tags=extract.tags)
def mutate(root, args, context, info): section_id = args.get('section_id') section_id = int(Node.from_global_id(section_id)[1]) section = models.Section.get(section_id) if section.section_type != SectionTypesEnum.CUSTOM.value: return DeleteSection(success=False) require_instance_permission(CrudPermissions.DELETE, section, context) section.db.delete(section) section.db.flush() return DeleteSection(success=True)
def mutate(root, args, context, info): status = False require_cls_permission(CrudPermissions.CREATE, models.Extract, context) discussion_id = context.matchdict['discussion_id'] # Retrieve the user id user_id = context.authenticated_userid or Everyone extracts = args.get('extracts') status = True extract_nature = args.get('extract_nature', None) extract_nature = models.ExtractNatureVocabulary.Enum(extract_nature) if extract_nature else None extract_state = args.get('extract_state', None) # Add all of extracts for extract in extracts: post_id = extract.get('post_id') post_id = int(Node.from_global_id(post_id)[1]) post = models.Post.get(post_id) if post_id else None if not post: continue db = post.db extract_hash = models.Extract.get_extract_hash( extract.get('lang'), extract.get('xpath_start'), extract.get('xpath_end'), extract.get('offset_start'), extract.get('offset_end'), post_id) exist = db.query(exists().where(models.Extract.extract_hash == extract_hash)).scalar() if not exist: new_extract = models.Extract( creator_id=user_id, owner_id=user_id, discussion_id=discussion_id, body=extract.get('body'), important=extract.get('important', False), content=post, extract_nature=extract_nature, extract_state=extract_state, extract_hash=extract_hash ) new_extract.lang = extract.get('lang') db.add(new_extract) range = models.TextFragmentIdentifier( extract=new_extract, xpath_start=extract.get('xpath_start'), offset_start=extract.get('offset_start'), xpath_end=extract.get('xpath_end'), offset_end=extract.get('offset_end')) db.add(range) db.flush() return AddPostsExtract(status=status)
def mutate(root, args, context, info): extract_id = args.get('extract_id') extract_id = int(Node.from_global_id(extract_id)[1]) extract = models.Extract.get(extract_id) require_instance_permission(CrudPermissions.DELETE, extract, context) for fragment in extract.text_fragment_identifiers: fragment.delete() extract.tags = [] extract.delete() extract.db.flush() return DeleteExtract(success=True)
def mutate(root, args, context, info): cls = models.ProfileField discussion_id = context.matchdict['discussion_id'] user_id = context.authenticated_userid agent_profile = models.AgentProfile.get(user_id) require_instance_permission(CrudPermissions.UPDATE, agent_profile, context) with cls.default_db.no_autoflush as db: for field_info in args.get('data'): profile_field_id = field_info['id'] profile_field_id = int(Node.from_global_id(profile_field_id)[1]) profile_field = cls.get(profile_field_id) if profile_field: require_instance_permission(CrudPermissions.UPDATE, profile_field, context) profile_field.value_data = field_info['value_data'] else: configurable_field_id = field_info['configurable_field_id'] configurable_field_id = int(Node.from_global_id(configurable_field_id)[1]) configurable_field = models.AbstractConfigurableField.get(configurable_field_id) if configurable_field.identifier == ConfigurableFieldIdentifiersEnum.FULLNAME.value: agent_profile.real_name_p = field_info['value_data']['value'] elif configurable_field.identifier == ConfigurableFieldIdentifiersEnum.EMAIL.value: agent_profile.preferred_email = field_info['value_data']['value'] elif configurable_field.identifier == ConfigurableFieldIdentifiersEnum.USERNAME.value: agent_profile.username_p = field_info['value_data']['value'] elif configurable_field.identifier == ConfigurableFieldIdentifiersEnum.CUSTOM.value: require_cls_permission(CrudPermissions.CREATE, cls, context) profile_field = cls( agent_profile=agent_profile, configurable_field_id=configurable_field_id, discussion_id=discussion_id, value_data=field_info['value_data'] ) db.add(profile_field) db.flush() profile_fields = get_query(cls, context).filter(cls.discussion_id == discussion_id) return UpdateProfileFields(profile_fields=profile_fields)
def mutate(root, args, context, info): cls = models.AbstractConfigurableField field_id = args.get('id') field_id = int(Node.from_global_id(field_id)[1]) field = cls.get(field_id) require_instance_permission(CrudPermissions.DELETE, field, context) with cls.default_db.no_autoflush as db: db.query(models.ProfileField).filter( models.ProfileField.configurable_field_id == field_id).delete() db.flush() db.delete(field) db.flush() return DeleteTextField(success=True)