예제 #1
0
    def post(self, ctx):
        auth.verify_privilege(ctx.user, 'posts:create')
        content = ctx.get_file('content', required=True)
        tag_names = ctx.get_param_as_list('tags', required=True)
        safety = ctx.get_param_as_string('safety', required=True)
        source = ctx.get_param_as_string('source',
                                         required=False,
                                         default=None)
        if ctx.has_param('contentUrl') and not source:
            source = ctx.get_param_as_string('contentUrl')
        relations = ctx.get_param_as_list('relations', required=False) or []
        notes = ctx.get_param_as_list('notes', required=False) or []
        flags = ctx.get_param_as_list('flags', required=False) or []

        post = posts.create_post(content, tag_names, ctx.user)
        posts.update_post_safety(post, safety)
        posts.update_post_source(post, source)
        posts.update_post_relations(post, relations)
        posts.update_post_notes(post, notes)
        posts.update_post_flags(post, flags)
        if ctx.has_file('thumbnail'):
            posts.update_post_thumbnail(post, ctx.get_file('thumbnail'))
        ctx.session.add(post)
        snapshots.save_entity_creation(post, ctx.user)
        ctx.session.commit()
        tags.export_to_json()
        return posts.serialize_post_with_details(post, ctx.user)
예제 #2
0
 def put(self, ctx, post_id):
     post = posts.get_post_by_id(post_id)
     if ctx.has_file('content'):
         auth.verify_privilege(ctx.user, 'posts:edit:content')
         posts.update_post_content(post, ctx.get_file('content'))
     if ctx.has_param('tags'):
         auth.verify_privilege(ctx.user, 'posts:edit:tags')
         posts.update_post_tags(post, ctx.get_param_as_list('tags'))
     if ctx.has_param('safety'):
         auth.verify_privilege(ctx.user, 'posts:edit:safety')
         posts.update_post_safety(post, ctx.get_param_as_string('safety'))
     if ctx.has_param('source'):
         auth.verify_privilege(ctx.user, 'posts:edit:source')
         posts.update_post_source(post, ctx.get_param_as_string('source'))
     elif ctx.has_param('contentUrl'):
         posts.update_post_source(post, ctx.get_param_as_string('contentUrl'))
     if ctx.has_param('relations'):
         auth.verify_privilege(ctx.user, 'posts:edit:relations')
         posts.update_post_relations(post, ctx.get_param_as_list('relations'))
     if ctx.has_param('notes'):
         auth.verify_privilege(ctx.user, 'posts:edit:notes')
         posts.update_post_notes(post, ctx.get_param_as_list('notes'))
     if ctx.has_param('flags'):
         auth.verify_privilege(ctx.user, 'posts:edit:flags')
         posts.update_post_flags(post, ctx.get_param_as_list('flags'))
     if ctx.has_file('thumbnail'):
         auth.verify_privilege(ctx.user, 'posts:edit:thumbnail')
         posts.update_post_thumbnail(post, ctx.get_file('thumbnail'))
     post.last_edit_time = datetime.datetime.now()
     ctx.session.flush()
     snapshots.save_entity_modification(post, ctx.user)
     ctx.session.commit()
     tags.export_to_json()
     return posts.serialize_post_with_details(post, ctx.user)
예제 #3
0
def update_tag(ctx: rest.Context, params: Dict[str, str]) -> rest.Response:
    tag = _get_tag(params)
    versions.verify_version(tag, ctx)
    versions.bump_version(tag)
    if ctx.has_param('names'):
        auth.verify_privilege(ctx.user, 'tags:edit:names')
        tags.update_tag_names(tag, ctx.get_param_as_string_list('names'))
    if ctx.has_param('category'):
        auth.verify_privilege(ctx.user, 'tags:edit:category')
        tags.update_tag_category_name(tag, ctx.get_param_as_string('category'))
    if ctx.has_param('description'):
        auth.verify_privilege(ctx.user, 'tags:edit:description')
        tags.update_tag_description(tag,
                                    ctx.get_param_as_string('description'))
    if ctx.has_param('suggestions'):
        auth.verify_privilege(ctx.user, 'tags:edit:suggestions')
        suggestions = ctx.get_param_as_string_list('suggestions')
        _create_if_needed(suggestions, ctx.user)
        tags.update_tag_suggestions(tag, suggestions)
    if ctx.has_param('implications'):
        auth.verify_privilege(ctx.user, 'tags:edit:implications')
        implications = ctx.get_param_as_string_list('implications')
        _create_if_needed(implications, ctx.user)
        tags.update_tag_implications(tag, implications)
    tag.last_edit_time = datetime.utcnow()
    ctx.session.flush()
    snapshots.modify(tag, ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return _serialize(ctx, tag)
예제 #4
0
def create_post(ctx, _params=None):
    anonymous = ctx.get_param_as_bool('anonymous', default=False)
    if anonymous:
        auth.verify_privilege(ctx.user, 'posts:create:anonymous')
    else:
        auth.verify_privilege(ctx.user, 'posts:create:identified')
    content = ctx.get_file('content', required=True)
    tag_names = ctx.get_param_as_list('tags', required=False, default=[])
    safety = ctx.get_param_as_string('safety', required=True)
    source = ctx.get_param_as_string('source', required=False, default=None)
    if ctx.has_param('contentUrl') and not source:
        source = ctx.get_param_as_string('contentUrl')
    relations = ctx.get_param_as_list('relations', required=False) or []
    notes = ctx.get_param_as_list('notes', required=False) or []
    flags = ctx.get_param_as_list('flags', required=False) or []

    post, new_tags = posts.create_post(
        content, tag_names, None if anonymous else ctx.user)
    if len(new_tags):
        auth.verify_privilege(ctx.user, 'tags:create')
    posts.update_post_safety(post, safety)
    posts.update_post_source(post, source)
    posts.update_post_relations(post, relations)
    posts.update_post_notes(post, notes)
    posts.update_post_flags(post, flags)
    if ctx.has_file('thumbnail'):
        posts.update_post_thumbnail(post, ctx.get_file('thumbnail'))
    ctx.session.add(post)
    ctx.session.flush()
    snapshots.create(post, None if anonymous else ctx.user)
    for tag in new_tags:
        snapshots.create(tag, None if anonymous else ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return _serialize_post(ctx, post)
예제 #5
0
    def put(self, ctx, tag_name):
        tag = tags.get_tag_by_name(tag_name)
        if not tag:
            raise tags.TagNotFoundError('Tag %r not found.' % tag_name)

        if ctx.has_param('names'):
            auth.verify_privilege(ctx.user, 'tags:edit:names')
            tags.update_names(tag, ctx.get_param_as_list('names'))

        if ctx.has_param('category'):
            auth.verify_privilege(ctx.user, 'tags:edit:category')
            tags.update_category_name(tag, ctx.get_param_as_string('category'))

        if ctx.has_param('suggestions'):
            auth.verify_privilege(ctx.user, 'tags:edit:suggestions')
            tags.update_suggestions(tag, ctx.get_param_as_list('suggestions'))

        if ctx.has_param('implications'):
            auth.verify_privilege(ctx.user, 'tags:edit:implications')
            tags.update_implications(tag, ctx.get_param_as_list('implications'))

        tag.last_edit_time = datetime.datetime.now()
        snapshots.modify(tag, ctx.user)
        ctx.session.commit()
        tags.export_to_json()
        return _serialize_tag_with_details(tag)
예제 #6
0
    def post(self, ctx):
        auth.verify_privilege(ctx.user, 'posts:create')
        content = ctx.get_file('content', required=True)
        tag_names = ctx.get_param_as_list('tags', required=True)
        safety = ctx.get_param_as_string('safety', required=True)
        source = ctx.get_param_as_string('source', required=False, default=None)
        if ctx.has_param('contentUrl') and not source:
            source = ctx.get_param_as_string('contentUrl')
        relations = ctx.get_param_as_list('relations', required=False) or []
        notes = ctx.get_param_as_list('notes', required=False) or []
        flags = ctx.get_param_as_list('flags', required=False) or []

        post = posts.create_post(content, tag_names, ctx.user)
        posts.update_post_safety(post, safety)
        posts.update_post_source(post, source)
        posts.update_post_relations(post, relations)
        posts.update_post_notes(post, notes)
        posts.update_post_flags(post, flags)
        if ctx.has_file('thumbnail'):
            posts.update_post_thumbnail(post, ctx.get_file('thumbnail'))
        ctx.session.add(post)
        snapshots.save_entity_creation(post, ctx.user)
        ctx.session.commit()
        tags.export_to_json()
        return posts.serialize_post_with_details(post, ctx.user)
예제 #7
0
def update_tag(ctx, params):
    tag = tags.get_tag_by_name(params['tag_name'])
    versions.verify_version(tag, ctx)
    versions.bump_version(tag)
    if ctx.has_param('names'):
        auth.verify_privilege(ctx.user, 'tags:edit:names')
        tags.update_tag_names(tag, ctx.get_param_as_list('names'))
    if ctx.has_param('category'):
        auth.verify_privilege(ctx.user, 'tags:edit:category')
        tags.update_tag_category_name(
            tag, ctx.get_param_as_string('category'))
    if ctx.has_param('description'):
        auth.verify_privilege(ctx.user, 'tags:edit:description')
        tags.update_tag_description(
            tag, ctx.get_param_as_string('description', default=None))
    if ctx.has_param('suggestions'):
        auth.verify_privilege(ctx.user, 'tags:edit:suggestions')
        suggestions = ctx.get_param_as_list('suggestions')
        _create_if_needed(suggestions, ctx.user)
        tags.update_tag_suggestions(tag, suggestions)
    if ctx.has_param('implications'):
        auth.verify_privilege(ctx.user, 'tags:edit:implications')
        implications = ctx.get_param_as_list('implications')
        _create_if_needed(implications, ctx.user)
        tags.update_tag_implications(tag, implications)
    tag.last_edit_time = datetime.datetime.utcnow()
    ctx.session.flush()
    snapshots.modify(tag, ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return _serialize(ctx, tag)
예제 #8
0
 def delete(self, ctx, post_id):
     auth.verify_privilege(ctx.user, 'posts:delete')
     post = posts.get_post_by_id(post_id)
     snapshots.save_entity_deletion(post, ctx.user)
     ctx.session.delete(post)
     ctx.session.commit()
     tags.export_to_json()
     return {}
예제 #9
0
 def delete(self, ctx, post_id):
     auth.verify_privilege(ctx.user, 'posts:delete')
     post = posts.get_post_by_id(post_id)
     snapshots.save_entity_deletion(post, ctx.user)
     ctx.session.delete(post)
     ctx.session.commit()
     tags.export_to_json()
     return {}
예제 #10
0
def delete_tag(ctx: rest.Context, params: Dict[str, str]) -> rest.Response:
    tag = _get_tag(params)
    versions.verify_version(tag, ctx)
    auth.verify_privilege(ctx.user, 'tags:delete')
    snapshots.delete(tag, ctx.user)
    tags.delete(tag)
    ctx.session.commit()
    tags.export_to_json()
    return {}
예제 #11
0
def delete_post(ctx, params):
    auth.verify_privilege(ctx.user, 'posts:delete')
    post = posts.get_post_by_id(params['post_id'])
    versions.verify_version(post, ctx)
    snapshots.delete(post, ctx.user)
    posts.delete(post)
    ctx.session.commit()
    tags.export_to_json()
    return {}
예제 #12
0
def delete_post(ctx: rest.Context, params: Dict[str, str]) -> rest.Response:
    auth.verify_privilege(ctx.user, 'posts:delete')
    post = _get_post(params)
    versions.verify_version(post, ctx)
    snapshots.delete(post, ctx.user)
    posts.delete(post)
    ctx.session.commit()
    tags.export_to_json()
    return {}
예제 #13
0
def delete_tag(ctx, params):
    tag = tags.get_tag_by_name(params['tag_name'])
    versions.verify_version(tag, ctx)
    auth.verify_privilege(ctx.user, 'tags:delete')
    snapshots.delete(tag, ctx.user)
    tags.delete(tag)
    ctx.session.commit()
    tags.export_to_json()
    return {}
예제 #14
0
def set_tag_category_as_default(ctx, params):
    auth.verify_privilege(ctx.user, 'tag_categories:set_default')
    category = tag_categories.get_category_by_name(
        params['category_name'], lock=True)
    tag_categories.set_default_category(category)
    ctx.session.flush()
    snapshots.modify(category, ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return _serialize(ctx, category)
예제 #15
0
def delete_tag_category(ctx, params):
    category = tag_categories.get_category_by_name(
        params['category_name'], lock=True)
    versions.verify_version(category, ctx)
    auth.verify_privilege(ctx.user, 'tag_categories:delete')
    tag_categories.delete_category(category)
    snapshots.delete(category, ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return {}
예제 #16
0
def test_export_to_json(
        tmpdir,
        query_counter,
        config_injector,
        post_factory,
        tag_factory,
        tag_category_factory):
    config_injector({'data_dir': str(tmpdir)})
    cat1 = tag_category_factory(name='cat1', color='black')
    cat2 = tag_category_factory(name='cat2', color='white')
    tag = tag_factory(names=['alias1', 'alias2'], category=cat2)
    tag.suggestions = [
        tag_factory(names=['sug1'], category=cat1),
        tag_factory(names=['sug2'], category=cat1),
    ]
    tag.implications = [
        tag_factory(names=['imp1'], category=cat1),
        tag_factory(names=['imp2'], category=cat1),
    ]
    post = post_factory()
    post.tags = [tag]
    db.session.add_all([post, tag])
    db.session.flush()

    with query_counter:
        tags.export_to_json()
        assert len(query_counter.statements) == 5

    export_path = os.path.join(str(tmpdir), 'tags.json')
    assert os.path.exists(export_path)
    with open(export_path, 'r') as handle:
        actual_json = json.loads(handle.read())
        assert actual_json['tags']
        assert actual_json['categories']
        actual_json['tags'].sort(key=lambda tag: tag['names'][0])
        actual_json['categories'].sort(key=lambda category: category['name'])
        assert actual_json == {
            'tags': [
                {
                    'names': ['alias1', 'alias2'],
                    'usages': 1,
                    'category': 'cat2',
                    'suggestions': ['sug1', 'sug2'],
                    'implications': ['imp1', 'imp2'],
                },
                {'names': ['imp1'], 'usages': 0, 'category': 'cat1'},
                {'names': ['imp2'], 'usages': 0, 'category': 'cat1'},
                {'names': ['sug1'], 'usages': 0, 'category': 'cat1'},
                {'names': ['sug2'], 'usages': 0, 'category': 'cat1'},
            ],
            'categories': [
                {'name': 'cat1', 'color': 'black'},
                {'name': 'cat2', 'color': 'white'},
            ]
        }
예제 #17
0
def test_export(
        tmpdir,
        query_counter,
        config_injector,
        tag_factory,
        tag_category_factory):
    config_injector({
        'data_dir': str(tmpdir)
    })
    cat1 = tag_category_factory(name='cat1', color='black')
    cat2 = tag_category_factory(name='cat2', color='white')
    db.session.add_all([cat1, cat2])
    db.session.flush()
    sug1 = tag_factory(names=['sug1'], category=cat1)
    sug2 = tag_factory(names=['sug2'], category=cat1)
    imp1 = tag_factory(names=['imp1'], category=cat1)
    imp2 = tag_factory(names=['imp2'], category=cat1)
    tag = tag_factory(names=['alias1', 'alias2'], category=cat2)
    tag.post_count = 1
    db.session.add_all([tag, sug1, sug2, imp1, imp2, cat1, cat2])
    db.session.flush()
    db.session.add_all([
        db.TagSuggestion(tag.tag_id, sug1.tag_id),
        db.TagSuggestion(tag.tag_id, sug2.tag_id),
        db.TagImplication(tag.tag_id, imp1.tag_id),
        db.TagImplication(tag.tag_id, imp2.tag_id),
    ])
    db.session.flush()

    with query_counter:
        tags.export_to_json()
        assert len(query_counter.statements) == 2

    export_path = os.path.join(config.config['data_dir'], 'tags.json')
    assert os.path.exists(export_path)
    with open(export_path, 'r') as handle:
        assert json.loads(handle.read()) == {
            'tags': [
                {
                    'names': ['alias1', 'alias2'],
                    'usages': 1,
                    'category': 'cat2',
                    'suggestions': ['sug1', 'sug2'],
                    'implications': ['imp1', 'imp2'],
                },
                {'names': ['sug1'], 'usages': 0, 'category': 'cat1'},
                {'names': ['sug2'], 'usages': 0, 'category': 'cat1'},
                {'names': ['imp1'], 'usages': 0, 'category': 'cat1'},
                {'names': ['imp2'], 'usages': 0, 'category': 'cat1'},
            ],
            'categories': [
                {'name': 'cat1', 'color': 'black'},
                {'name': 'cat2', 'color': 'white'},
            ]
        }
예제 #18
0
 def post(self, ctx):
     auth.verify_privilege(ctx.user, 'tag_categories:create')
     name = ctx.get_param_as_string('name', required=True)
     color = ctx.get_param_as_string('color', required=True)
     category = tag_categories.create_category(name, color)
     ctx.session.add(category)
     ctx.session.flush()
     snapshots.save_entity_creation(category, ctx.user)
     ctx.session.commit()
     tags.export_to_json()
     return tag_categories.serialize_category_with_details(category)
예제 #19
0
def set_tag_category_as_default(
        ctx: rest.Context, params: Dict[str, str]) -> rest.Response:
    auth.verify_privilege(ctx.user, 'tag_categories:set_default')
    category = tag_categories.get_category_by_name(
        params['category_name'], lock=True)
    tag_categories.set_default_category(category)
    ctx.session.flush()
    snapshots.modify(category, ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return _serialize(ctx, category)
예제 #20
0
def delete_tag_category(
        ctx: rest.Context, params: Dict[str, str]) -> rest.Response:
    category = tag_categories.get_category_by_name(
        params['category_name'], lock=True)
    versions.verify_version(category, ctx)
    auth.verify_privilege(ctx.user, 'tag_categories:delete')
    tag_categories.delete_category(category)
    snapshots.delete(category, ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return {}
예제 #21
0
 def post(self, ctx):
     auth.verify_privilege(ctx.user, 'tag_categories:create')
     name = ctx.get_param_as_string('name', required=True)
     color = ctx.get_param_as_string('color', required=True)
     category = tag_categories.create_category(name, color)
     ctx.session.add(category)
     ctx.session.flush()
     snapshots.create(category, ctx.user)
     ctx.session.commit()
     tags.export_to_json()
     return _serialize_category_with_details(category)
예제 #22
0
 def delete(self, ctx, tag_name):
     tag = tags.get_tag_by_name(tag_name)
     if tag.post_count > 0:
         raise tags.TagIsInUseError(
             'Tag has some usages and cannot be deleted. ' +
             'Please untag relevant posts first.')
     auth.verify_privilege(ctx.user, 'tags:delete')
     snapshots.save_entity_deletion(tag, ctx.user)
     tags.delete(tag)
     ctx.session.commit()
     tags.export_to_json()
     return {}
예제 #23
0
 def delete(self, ctx, tag_name):
     tag = tags.get_tag_by_name(tag_name)
     if tag.post_count > 0:
         raise tags.TagIsInUseError(
             'Tag has some usages and cannot be deleted. ' +
             'Please untag relevant posts first.')
     auth.verify_privilege(ctx.user, 'tags:delete')
     snapshots.save_entity_deletion(tag, ctx.user)
     tags.delete(tag)
     ctx.session.commit()
     tags.export_to_json()
     return {}
예제 #24
0
def create_tag_category(
        ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response:
    auth.verify_privilege(ctx.user, 'tag_categories:create')
    name = ctx.get_param_as_string('name')
    color = ctx.get_param_as_string('color')
    category = tag_categories.create_category(name, color)
    ctx.session.add(category)
    ctx.session.flush()
    snapshots.create(category, ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return _serialize(ctx, category)
예제 #25
0
 def post(self, ctx):
     source_tag_name = ctx.get_param_as_string('remove', required=True) or ''
     target_tag_name = ctx.get_param_as_string('mergeTo', required=True) or ''
     source_tag = tags.get_tag_by_name(source_tag_name)
     target_tag = tags.get_tag_by_name(target_tag_name)
     if source_tag.tag_id == target_tag.tag_id:
         raise tags.InvalidTagRelationError('Cannot merge tag with itself.')
     auth.verify_privilege(ctx.user, 'tags:merge')
     snapshots.save_entity_deletion(source_tag, ctx.user)
     tags.merge_tags(source_tag, target_tag)
     ctx.session.commit()
     tags.export_to_json()
     return tags.serialize_tag_with_details(target_tag)
예제 #26
0
def merge_tags(ctx, _params=None):
    source_tag_name = ctx.get_param_as_string('remove', required=True) or ''
    target_tag_name = ctx.get_param_as_string('mergeTo', required=True) or ''
    source_tag = tags.get_tag_by_name(source_tag_name)
    target_tag = tags.get_tag_by_name(target_tag_name)
    versions.verify_version(source_tag, ctx, 'removeVersion')
    versions.verify_version(target_tag, ctx, 'mergeToVersion')
    versions.bump_version(target_tag)
    auth.verify_privilege(ctx.user, 'tags:merge')
    tags.merge_tags(source_tag, target_tag)
    snapshots.merge(source_tag, target_tag, ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return _serialize(ctx, target_tag)
예제 #27
0
 def post(self, ctx):
     source_tag_name = ctx.get_param_as_string('remove',
                                               required=True) or ''
     target_tag_name = ctx.get_param_as_string('mergeTo',
                                               required=True) or ''
     source_tag = tags.get_tag_by_name(source_tag_name)
     target_tag = tags.get_tag_by_name(target_tag_name)
     if source_tag.tag_id == target_tag.tag_id:
         raise tags.InvalidTagRelationError('Cannot merge tag with itself.')
     auth.verify_privilege(ctx.user, 'tags:merge')
     snapshots.save_entity_deletion(source_tag, ctx.user)
     tags.merge_tags(source_tag, target_tag)
     ctx.session.commit()
     tags.export_to_json()
     return tags.serialize_tag_with_details(target_tag)
예제 #28
0
 def delete(self, ctx, category_name):
     category = tag_categories.get_category_by_name(category_name)
     auth.verify_privilege(ctx.user, 'tag_categories:delete')
     if len(tag_categories.get_all_category_names()) == 1:
         raise tag_categories.TagCategoryIsInUseError(
             'Cannot delete the default category.')
     if category.tag_count > 0:
         raise tag_categories.TagCategoryIsInUseError(
             'Tag category has some usages and cannot be deleted. ' +
             'Please remove this category from relevant tags first..')
     snapshots.save_entity_deletion(category, ctx.user)
     ctx.session.delete(category)
     ctx.session.commit()
     tags.export_to_json()
     return {}
예제 #29
0
 def put(self, ctx, category_name):
     category = tag_categories.get_category_by_name(category_name)
     if ctx.has_param('name'):
         auth.verify_privilege(ctx.user, 'tag_categories:edit:name')
         tag_categories.update_category_name(
             category, ctx.get_param_as_string('name'))
     if ctx.has_param('color'):
         auth.verify_privilege(ctx.user, 'tag_categories:edit:color')
         tag_categories.update_category_color(
             category, ctx.get_param_as_string('color'))
     ctx.session.flush()
     snapshots.save_entity_modification(category, ctx.user)
     ctx.session.commit()
     tags.export_to_json()
     return tag_categories.serialize_category_with_details(category)
예제 #30
0
def merge_tags(ctx: rest.Context,
               _params: Dict[str, str] = {}) -> rest.Response:
    source_tag_name = ctx.get_param_as_string('remove')
    target_tag_name = ctx.get_param_as_string('mergeTo')
    source_tag = tags.get_tag_by_name(source_tag_name)
    target_tag = tags.get_tag_by_name(target_tag_name)
    versions.verify_version(source_tag, ctx, 'removeVersion')
    versions.verify_version(target_tag, ctx, 'mergeToVersion')
    versions.bump_version(target_tag)
    auth.verify_privilege(ctx.user, 'tags:merge')
    tags.merge_tags(source_tag, target_tag)
    snapshots.merge(source_tag, target_tag, ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return _serialize(ctx, target_tag)
예제 #31
0
    def post(self, ctx):
        auth.verify_privilege(ctx.user, 'tags:create')

        names = ctx.get_param_as_list('names', required=True)
        category = ctx.get_param_as_string('category', required=True)
        suggestions = ctx.get_param_as_list(
            'suggestions', required=False, default=[])
        implications = ctx.get_param_as_list(
            'implications', required=False, default=[])

        tag = tags.create_tag(names, category, suggestions, implications)
        ctx.session.add(tag)
        ctx.session.flush()
        snapshots.create(tag, ctx.user)
        ctx.session.commit()
        tags.export_to_json()
        return _serialize_tag_with_details(tag)
예제 #32
0
 def put(self, ctx, category_name):
     category = tag_categories.get_category_by_name(category_name)
     if not category:
         raise tag_categories.TagCategoryNotFoundError(
             'Tag category %r not found.' % category_name)
     if ctx.has_param('name'):
         auth.verify_privilege(ctx.user, 'tag_categories:edit:name')
         tag_categories.update_name(
             category, ctx.get_param_as_string('name'))
     if ctx.has_param('color'):
         auth.verify_privilege(ctx.user, 'tag_categories:edit:color')
         tag_categories.update_color(
             category, ctx.get_param_as_string('color'))
     snapshots.modify(category, ctx.user)
     ctx.session.commit()
     tags.export_to_json()
     return _serialize_category_with_details(category)
예제 #33
0
def update_tag_category(ctx, params):
    category = tag_categories.get_category_by_name(
        params['category_name'], lock=True)
    versions.verify_version(category, ctx)
    versions.bump_version(category)
    if ctx.has_param('name'):
        auth.verify_privilege(ctx.user, 'tag_categories:edit:name')
        tag_categories.update_category_name(
            category, ctx.get_param_as_string('name'))
    if ctx.has_param('color'):
        auth.verify_privilege(ctx.user, 'tag_categories:edit:color')
        tag_categories.update_category_color(
            category, ctx.get_param_as_string('color'))
    ctx.session.flush()
    snapshots.modify(category, ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return _serialize(ctx, category)
예제 #34
0
def update_tag_category(
        ctx: rest.Context, params: Dict[str, str]) -> rest.Response:
    category = tag_categories.get_category_by_name(
        params['category_name'], lock=True)
    versions.verify_version(category, ctx)
    versions.bump_version(category)
    if ctx.has_param('name'):
        auth.verify_privilege(ctx.user, 'tag_categories:edit:name')
        tag_categories.update_category_name(
            category, ctx.get_param_as_string('name'))
    if ctx.has_param('color'):
        auth.verify_privilege(ctx.user, 'tag_categories:edit:color')
        tag_categories.update_category_color(
            category, ctx.get_param_as_string('color'))
    ctx.session.flush()
    snapshots.modify(category, ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return _serialize(ctx, category)
예제 #35
0
def update_post(ctx: rest.Context, params: Dict[str, str]) -> rest.Response:
    post = _get_post(params)
    versions.verify_version(post, ctx)
    versions.bump_version(post)
    if ctx.has_file('content'):
        auth.verify_privilege(ctx.user, 'posts:edit:content')
        posts.update_post_content(post, ctx.get_file('content'))
    if ctx.has_param('tags'):
        auth.verify_privilege(ctx.user, 'posts:edit:tags')
        new_tags = posts.update_post_tags(
            post, ctx.get_param_as_string_list('tags'))
        if len(new_tags):
            auth.verify_privilege(ctx.user, 'tags:create')
            db.session.flush()
            for tag in new_tags:
                snapshots.create(tag, ctx.user)
    if ctx.has_param('safety'):
        auth.verify_privilege(ctx.user, 'posts:edit:safety')
        posts.update_post_safety(post, ctx.get_param_as_string('safety'))
    if ctx.has_param('source'):
        auth.verify_privilege(ctx.user, 'posts:edit:source')
        posts.update_post_source(post, ctx.get_param_as_string('source'))
    elif ctx.has_param('contentUrl'):
        posts.update_post_source(post, ctx.get_param_as_string('contentUrl'))
    if ctx.has_param('relations'):
        auth.verify_privilege(ctx.user, 'posts:edit:relations')
        posts.update_post_relations(
            post, ctx.get_param_as_int_list('relations'))
    if ctx.has_param('notes'):
        auth.verify_privilege(ctx.user, 'posts:edit:notes')
        posts.update_post_notes(post, ctx.get_param_as_list('notes'))
    if ctx.has_param('flags'):
        auth.verify_privilege(ctx.user, 'posts:edit:flags')
        posts.update_post_flags(post, ctx.get_param_as_string_list('flags'))
    if ctx.has_file('thumbnail'):
        auth.verify_privilege(ctx.user, 'posts:edit:thumbnail')
        posts.update_post_thumbnail(post, ctx.get_file('thumbnail'))
    post.last_edit_time = datetime.utcnow()
    ctx.session.flush()
    snapshots.modify(post, ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return _serialize_post(ctx, post)
예제 #36
0
    def post(self, ctx):
        auth.verify_privilege(ctx.user, 'tags:create')

        names = ctx.get_param_as_list('names', required=True)
        category = ctx.get_param_as_string('category', required=True)
        suggestions = ctx.get_param_as_list('suggestions',
                                            required=False,
                                            default=[])
        implications = ctx.get_param_as_list('implications',
                                             required=False,
                                             default=[])

        tag = tags.create_tag(names, category, suggestions, implications)
        ctx.session.add(tag)
        ctx.session.flush()
        snapshots.save_entity_creation(tag, ctx.user)
        ctx.session.commit()
        tags.export_to_json()
        return tags.serialize_tag_with_details(tag)
예제 #37
0
 def post(self, ctx):
     source_tag_name = ctx.get_param_as_string('remove', required=True) or ''
     target_tag_name = ctx.get_param_as_string('merge-to', required=True) or ''
     source_tag = tags.get_tag_by_name(source_tag_name)
     target_tag = tags.get_tag_by_name(target_tag_name)
     if not source_tag:
         raise tags.TagNotFoundError(
             'Source tag %r not found.' % source_tag_name)
     if not target_tag:
         raise tags.TagNotFoundError(
             'Source tag %r not found.' % target_tag_name)
     if source_tag.tag_id == target_tag.tag_id:
         raise tags.InvalidTagRelationError(
             'Cannot merge tag with itself.')
     auth.verify_privilege(ctx.user, 'tags:merge')
     tags.merge_tags(source_tag, target_tag)
     snapshots.delete(source_tag, ctx.user)
     ctx.session.commit()
     tags.export_to_json()
     return _serialize_tag_with_details(target_tag)
예제 #38
0
def update_post(ctx, params):
    post = posts.get_post_by_id(params['post_id'])
    versions.verify_version(post, ctx)
    versions.bump_version(post)
    if ctx.has_file('content'):
        auth.verify_privilege(ctx.user, 'posts:edit:content')
        posts.update_post_content(post, ctx.get_file('content'))
    if ctx.has_param('tags'):
        auth.verify_privilege(ctx.user, 'posts:edit:tags')
        new_tags = posts.update_post_tags(post, ctx.get_param_as_list('tags'))
        if len(new_tags):
            auth.verify_privilege(ctx.user, 'tags:create')
            db.session.flush()
            for tag in new_tags:
                snapshots.create(tag, ctx.user)
    if ctx.has_param('safety'):
        auth.verify_privilege(ctx.user, 'posts:edit:safety')
        posts.update_post_safety(post, ctx.get_param_as_string('safety'))
    if ctx.has_param('source'):
        auth.verify_privilege(ctx.user, 'posts:edit:source')
        posts.update_post_source(post, ctx.get_param_as_string('source'))
    elif ctx.has_param('contentUrl'):
        posts.update_post_source(post, ctx.get_param_as_string('contentUrl'))
    if ctx.has_param('relations'):
        auth.verify_privilege(ctx.user, 'posts:edit:relations')
        posts.update_post_relations(post, ctx.get_param_as_list('relations'))
    if ctx.has_param('notes'):
        auth.verify_privilege(ctx.user, 'posts:edit:notes')
        posts.update_post_notes(post, ctx.get_param_as_list('notes'))
    if ctx.has_param('flags'):
        auth.verify_privilege(ctx.user, 'posts:edit:flags')
        posts.update_post_flags(post, ctx.get_param_as_list('flags'))
    if ctx.has_file('thumbnail'):
        auth.verify_privilege(ctx.user, 'posts:edit:thumbnail')
        posts.update_post_thumbnail(post, ctx.get_file('thumbnail'))
    post.last_edit_time = datetime.datetime.utcnow()
    ctx.session.flush()
    snapshots.modify(post, ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return _serialize_post(ctx, post)
예제 #39
0
def create_tag(ctx: rest.Context,
               _params: Dict[str, str] = {}) -> rest.Response:
    auth.verify_privilege(ctx.user, 'tags:create')

    names = ctx.get_param_as_string_list('names')
    category = ctx.get_param_as_string('category')
    description = ctx.get_param_as_string('description', default='')
    suggestions = ctx.get_param_as_string_list('suggestions', default=[])
    implications = ctx.get_param_as_string_list('implications', default=[])

    _create_if_needed(suggestions, ctx.user)
    _create_if_needed(implications, ctx.user)

    tag = tags.create_tag(names, category, suggestions, implications)
    tags.update_tag_description(tag, description)
    ctx.session.add(tag)
    ctx.session.flush()
    snapshots.create(tag, ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return _serialize(ctx, tag)
예제 #40
0
def create_tag(ctx, _params=None):
    auth.verify_privilege(ctx.user, 'tags:create')

    names = ctx.get_param_as_list('names', required=True)
    category = ctx.get_param_as_string('category', required=True)
    description = ctx.get_param_as_string(
        'description', required=False, default=None)
    suggestions = ctx.get_param_as_list(
        'suggestions', required=False, default=[])
    implications = ctx.get_param_as_list(
        'implications', required=False, default=[])

    _create_if_needed(suggestions, ctx.user)
    _create_if_needed(implications, ctx.user)

    tag = tags.create_tag(names, category, suggestions, implications)
    tags.update_tag_description(tag, description)
    ctx.session.add(tag)
    ctx.session.flush()
    snapshots.create(tag, ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return _serialize(ctx, tag)
예제 #41
0
 def put(self, ctx, tag_name):
     tag = tags.get_tag_by_name(tag_name)
     if ctx.has_param('names'):
         auth.verify_privilege(ctx.user, 'tags:edit:names')
         tags.update_tag_names(tag, ctx.get_param_as_list('names'))
     if ctx.has_param('category'):
         auth.verify_privilege(ctx.user, 'tags:edit:category')
         tags.update_tag_category_name(tag,
                                       ctx.get_param_as_string('category'))
     if ctx.has_param('suggestions'):
         auth.verify_privilege(ctx.user, 'tags:edit:suggestions')
         tags.update_tag_suggestions(tag,
                                     ctx.get_param_as_list('suggestions'))
     if ctx.has_param('implications'):
         auth.verify_privilege(ctx.user, 'tags:edit:implications')
         tags.update_tag_implications(tag,
                                      ctx.get_param_as_list('implications'))
     tag.last_edit_time = datetime.datetime.now()
     ctx.session.flush()
     snapshots.save_entity_modification(tag, ctx.user)
     ctx.session.commit()
     tags.export_to_json()
     return tags.serialize_tag_with_details(tag)
예제 #42
0
 def put(self, ctx, tag_name):
     tag = tags.get_tag_by_name(tag_name)
     if ctx.has_param('names'):
         auth.verify_privilege(ctx.user, 'tags:edit:names')
         tags.update_tag_names(tag, ctx.get_param_as_list('names'))
     if ctx.has_param('category'):
         auth.verify_privilege(ctx.user, 'tags:edit:category')
         tags.update_tag_category_name(
             tag, ctx.get_param_as_string('category'))
     if ctx.has_param('suggestions'):
         auth.verify_privilege(ctx.user, 'tags:edit:suggestions')
         tags.update_tag_suggestions(
             tag, ctx.get_param_as_list('suggestions'))
     if ctx.has_param('implications'):
         auth.verify_privilege(ctx.user, 'tags:edit:implications')
         tags.update_tag_implications(
             tag, ctx.get_param_as_list('implications'))
     tag.last_edit_time = datetime.datetime.now()
     ctx.session.flush()
     snapshots.save_entity_modification(tag, ctx.user)
     ctx.session.commit()
     tags.export_to_json()
     return tags.serialize_tag_with_details(tag)
예제 #43
0
 def put(self, ctx, post_id):
     post = posts.get_post_by_id(post_id)
     if ctx.has_file('content'):
         auth.verify_privilege(ctx.user, 'posts:edit:content')
         posts.update_post_content(post, ctx.get_file('content'))
     if ctx.has_param('tags'):
         auth.verify_privilege(ctx.user, 'posts:edit:tags')
         posts.update_post_tags(post, ctx.get_param_as_list('tags'))
     if ctx.has_param('safety'):
         auth.verify_privilege(ctx.user, 'posts:edit:safety')
         posts.update_post_safety(post, ctx.get_param_as_string('safety'))
     if ctx.has_param('source'):
         auth.verify_privilege(ctx.user, 'posts:edit:source')
         posts.update_post_source(post, ctx.get_param_as_string('source'))
     elif ctx.has_param('contentUrl'):
         posts.update_post_source(post,
                                  ctx.get_param_as_string('contentUrl'))
     if ctx.has_param('relations'):
         auth.verify_privilege(ctx.user, 'posts:edit:relations')
         posts.update_post_relations(post,
                                     ctx.get_param_as_list('relations'))
     if ctx.has_param('notes'):
         auth.verify_privilege(ctx.user, 'posts:edit:notes')
         posts.update_post_notes(post, ctx.get_param_as_list('notes'))
     if ctx.has_param('flags'):
         auth.verify_privilege(ctx.user, 'posts:edit:flags')
         posts.update_post_flags(post, ctx.get_param_as_list('flags'))
     if ctx.has_file('thumbnail'):
         auth.verify_privilege(ctx.user, 'posts:edit:thumbnail')
         posts.update_post_thumbnail(post, ctx.get_file('thumbnail'))
     post.last_edit_time = datetime.datetime.now()
     ctx.session.flush()
     snapshots.save_entity_modification(post, ctx.user)
     ctx.session.commit()
     tags.export_to_json()
     return posts.serialize_post_with_details(post, ctx.user)
예제 #44
0
def create_post(
        ctx: rest.Context, _params: Dict[str, str] = {}) -> rest.Response:
    anonymous = ctx.get_param_as_bool('anonymous', default=False)
    if anonymous:
        auth.verify_privilege(ctx.user, 'posts:create:anonymous')
    else:
        auth.verify_privilege(ctx.user, 'posts:create:identified')
    content = ctx.get_file('content')
    tag_names = ctx.get_param_as_string_list('tags', default=[])
    safety = ctx.get_param_as_string('safety')
    source = ctx.get_param_as_string('source', default='')
    if ctx.has_param('contentUrl') and not source:
        source = ctx.get_param_as_string('contentUrl', default='')
    relations = ctx.get_param_as_int_list('relations', default=[])
    notes = ctx.get_param_as_list('notes', default=[])
    flags = ctx.get_param_as_string_list('flags', default=[])

    post, new_tags = posts.create_post(
        content, tag_names, None if anonymous else ctx.user)
    if len(new_tags):
        auth.verify_privilege(ctx.user, 'tags:create')
    posts.update_post_safety(post, safety)
    posts.update_post_source(post, source)
    posts.update_post_relations(post, relations)
    posts.update_post_notes(post, notes)
    posts.update_post_flags(post, flags)
    if ctx.has_file('thumbnail'):
        posts.update_post_thumbnail(post, ctx.get_file('thumbnail'))
    ctx.session.add(post)
    ctx.session.flush()
    snapshots.create(post, None if anonymous else ctx.user)
    for tag in new_tags:
        snapshots.create(tag, None if anonymous else ctx.user)
    ctx.session.commit()
    tags.export_to_json()
    return _serialize_post(ctx, post)
예제 #45
0
def test_export_to_json(tmpdir, query_counter, config_injector, post_factory,
                        tag_factory, tag_category_factory):
    config_injector({'data_dir': str(tmpdir)})
    cat1 = tag_category_factory(name='cat1', color='black')
    cat2 = tag_category_factory(name='cat2', color='white')
    tag = tag_factory(names=['alias1', 'alias2'], category=cat2)
    tag.suggestions = [
        tag_factory(names=['sug1'], category=cat1),
        tag_factory(names=['sug2'], category=cat1),
    ]
    tag.implications = [
        tag_factory(names=['imp1'], category=cat1),
        tag_factory(names=['imp2'], category=cat1),
    ]
    post = post_factory()
    post.tags = [tag]
    db.session.add_all([post, tag])
    db.session.flush()

    with query_counter:
        tags.export_to_json()
        assert len(query_counter.statements) == 5

    export_path = os.path.join(str(tmpdir), 'tags.json')
    assert os.path.exists(export_path)
    with open(export_path, 'r') as handle:
        actual_json = json.loads(handle.read())
        assert actual_json['tags']
        assert actual_json['categories']
        actual_json['tags'].sort(key=lambda tag: tag['names'][0])
        actual_json['categories'].sort(key=lambda category: category['name'])
        assert actual_json == {
            'tags': [
                {
                    'names': ['alias1', 'alias2'],
                    'usages': 1,
                    'category': 'cat2',
                    'suggestions': ['sug1', 'sug2'],
                    'implications': ['imp1', 'imp2'],
                },
                {
                    'names': ['imp1'],
                    'usages': 0,
                    'category': 'cat1'
                },
                {
                    'names': ['imp2'],
                    'usages': 0,
                    'category': 'cat1'
                },
                {
                    'names': ['sug1'],
                    'usages': 0,
                    'category': 'cat1'
                },
                {
                    'names': ['sug2'],
                    'usages': 0,
                    'category': 'cat1'
                },
            ],
            'categories': [
                {
                    'name': 'cat1',
                    'color': 'black'
                },
                {
                    'name': 'cat2',
                    'color': 'white'
                },
            ]
        }
예제 #46
0
def test_export(tmpdir, query_counter, config_injector, tag_factory,
                tag_category_factory):
    config_injector({'data_dir': str(tmpdir)})
    cat1 = tag_category_factory(name='cat1', color='black')
    cat2 = tag_category_factory(name='cat2', color='white')
    db.session.add_all([cat1, cat2])
    db.session.flush()
    sug1 = tag_factory(names=['sug1'], category=cat1)
    sug2 = tag_factory(names=['sug2'], category=cat1)
    imp1 = tag_factory(names=['imp1'], category=cat1)
    imp2 = tag_factory(names=['imp2'], category=cat1)
    tag = tag_factory(names=['alias1', 'alias2'], category=cat2)
    tag.post_count = 1
    db.session.add_all([tag, sug1, sug2, imp1, imp2, cat1, cat2])
    db.session.flush()
    db.session.add_all([
        db.TagSuggestion(tag.tag_id, sug1.tag_id),
        db.TagSuggestion(tag.tag_id, sug2.tag_id),
        db.TagImplication(tag.tag_id, imp1.tag_id),
        db.TagImplication(tag.tag_id, imp2.tag_id),
    ])
    db.session.flush()

    with query_counter:
        tags.export_to_json()
        assert len(query_counter.statements) == 2

    export_path = os.path.join(config.config['data_dir'], 'tags.json')
    assert os.path.exists(export_path)
    with open(export_path, 'r') as handle:
        assert json.loads(handle.read()) == {
            'tags': [
                {
                    'names': ['alias1', 'alias2'],
                    'usages': 1,
                    'category': 'cat2',
                    'suggestions': ['sug1', 'sug2'],
                    'implications': ['imp1', 'imp2'],
                },
                {
                    'names': ['sug1'],
                    'usages': 0,
                    'category': 'cat1'
                },
                {
                    'names': ['sug2'],
                    'usages': 0,
                    'category': 'cat1'
                },
                {
                    'names': ['imp1'],
                    'usages': 0,
                    'category': 'cat1'
                },
                {
                    'names': ['imp2'],
                    'usages': 0,
                    'category': 'cat1'
                },
            ],
            'categories': [
                {
                    'name': 'cat1',
                    'color': 'black'
                },
                {
                    'name': 'cat2',
                    'color': 'white'
                },
            ]
        }