server/tags: let mods set default category

This commit is contained in:
rr- 2016-05-22 18:49:38 +02:00
parent 4b3640bf2e
commit 77998f1660
13 changed files with 100 additions and 7 deletions

34
API.md
View file

@ -19,6 +19,7 @@
- [Updating tag category](#updating-tag-category)
- [Getting tag category](#getting-tag-category)
- [Deleting tag category](#deleting-tag-category)
- [Setting default tag category](#setting-default-tag-category)
- Tags
- [Listing tags](#listing-tags)
- [Creating tag](#creating-tag)
@ -185,7 +186,8 @@ data.
- **Description**
Creates a new tag category using specified parameters. Name must match
`tag_category_name_regex` from server's configuration.
`tag_category_name_regex` from server's configuration. First category
created becomes the default category.
## Updating tag category
- **Request**
@ -260,6 +262,31 @@ data.
Deletes existing tag category. The tag category to be deleted must have no
usages.
## Setting default tag category
- **Request**
`PUT /tag-category/<name>/default`
- **Input**
```json5
{}
```
- **Output**
A [detailed tag category resource](#detailed-tag-category).
- **Errors**
- the tag category does not exist
- privileges are too low
- **Description**
Sets given tag category as default. All new tags created manually or
automatically will have this category.
## Listing tags
- **Request**
@ -1405,6 +1432,7 @@ experience.
"name": <name>,
"color": <color>,
"usages": <usages>
"default": <is_default>
}
```
@ -1413,6 +1441,7 @@ experience.
- `<name>`: the category name.
- `<color>`: the category color.
- `<usages>`: how many tags is the given category used with.
- `<is_default>`: whether the tag category is the default one.
## Detailed tag category
**Description**
@ -1723,7 +1752,8 @@ A snapshot is a version of a database resource.
```json5
{
"name": "character",
"color": "#FF0000"
"color": "#FF0000",
"default": false
}
```

View file

@ -98,6 +98,7 @@ privileges:
'tag_categories:list': anonymous # note: will be available as data_url/tags.json anyway
'tag_categories:view': anonymous
'tag_categories:delete': moderator
'tag_categories:set_default': moderator
'comments:create': regular
'comments:delete:any': moderator

View file

@ -9,7 +9,8 @@ from szurubooru.api.tag_api import (
TagSiblingsApi)
from szurubooru.api.tag_category_api import (
TagCategoryListApi,
TagCategoryDetailApi)
TagCategoryDetailApi,
DefaultTagCategoryApi)
from szurubooru.api.comment_api import (
CommentListApi,
CommentDetailApi,

View file

@ -60,3 +60,13 @@ class TagCategoryDetailApi(BaseApi):
ctx.session.commit()
tags.export_to_json()
return {}
class DefaultTagCategoryApi(BaseApi):
def put(self, ctx, category_name):
auth.verify_privilege(ctx.user, 'tag_categories:set_default')
category = tag_categories.get_category_by_name(category_name)
tag_categories.set_default_category(category)
snapshots.save_entity_modification(category, ctx.user)
ctx.session.commit()
tags.export_to_json()
return tag_categories.serialize_category_with_details(category)

View file

@ -98,6 +98,7 @@ def create_app():
app.add_route('/tag-categories/', api.TagCategoryListApi())
app.add_route('/tag-category/{category_name}', api.TagCategoryDetailApi())
app.add_route('/tag-category/{category_name}/default', api.DefaultTagCategoryApi())
app.add_route('/tags/', api.TagListApi())
app.add_route('/tag/{tag_name}', api.TagDetailApi())
app.add_route('/tag-merge/', api.TagMergeApi())

View file

@ -1,4 +1,4 @@
from sqlalchemy import Column, Integer, Unicode, table
from sqlalchemy import Column, Integer, Unicode, Boolean, table
from sqlalchemy.orm import column_property
from sqlalchemy.sql.expression import func, select
from szurubooru.db.base import Base
@ -10,6 +10,7 @@ class TagCategory(Base):
tag_category_id = Column('id', Integer, primary_key=True)
name = Column('name', Unicode(32), nullable=False)
color = Column('color', Unicode(32), nullable=False, default='#000000')
default = Column('default', Boolean, nullable=False, default=False)
def __init__(self, name=None):
self.name = name

View file

@ -28,6 +28,7 @@ def get_tag_category_snapshot(category):
return {
'name': category.name,
'color': category.color,
'default': True if category.default else False,
}
# pylint: disable=invalid-name

View file

@ -19,6 +19,7 @@ def serialize_category(category):
'name': category.name,
'color': category.color,
'usages': category.tag_count,
'default': category.default,
}
def serialize_category_with_details(category):
@ -31,6 +32,8 @@ def create_category(name, color):
category = db.TagCategory()
update_category_name(category, name)
update_category_color(category, color)
if not get_all_categories():
category.default = True
return category
def update_category_name(category, name):
@ -76,14 +79,27 @@ def get_all_categories():
return db.session.query(db.TagCategory).all()
def try_get_default_category():
return db.session \
category = db.session \
.query(db.TagCategory) \
.order_by(db.TagCategory.tag_category_id.asc()) \
.limit(1) \
.filter(db.TagCategory.default) \
.first()
# if for some reason (e.g. as a result of migration) there's no default
# category, get the first record available.
if not category:
category = db.session \
.query(db.TagCategory) \
.order_by(db.TagCategory.tag_category_id.asc()) \
.first()
return category
def get_default_category():
category = try_get_default_category()
if not category:
raise TagCategoryNotFoundError('No tag category created yet.')
return category
def set_default_category(category):
old_category = try_get_default_category()
if old_category:
old_category.default = False
category.default = True

View file

@ -0,0 +1,22 @@
'''
Add default column to tag categories
Revision ID: 055d0e048fb3
Created at: 2016-05-22 18:12:58.149678
'''
import sqlalchemy as sa
from alembic import op
revision = '055d0e048fb3'
down_revision = '49ab4e1139ef'
branch_labels = None
depends_on = None
def upgrade():
op.add_column('tag_category', sa.Column('default', sa.Boolean(), nullable=True))
op.execute(sa.table('tag_category', sa.column('default')).update().values(default=False))
op.alter_column('tag_category', 'default', nullable=False)
def downgrade():
op.drop_column('tag_category', 'default')

View file

@ -25,6 +25,7 @@ def test_creating_category(test_ctx):
'name': 'meta',
'color': 'black',
'usages': 0,
'default': True,
}
assert len(result['snapshots']) == 1
category = db.session.query(db.TagCategory).one()

View file

@ -42,6 +42,7 @@ def test_retrieving_single(test_ctx):
'name': 'cat',
'color': 'dummy',
'usages': 0,
'default': False,
},
'snapshots': [],
}

View file

@ -41,6 +41,7 @@ def test_simple_updating(test_ctx):
'name': 'changed',
'color': 'white',
'usages': 0,
'default': False,
}
assert len(result['snapshots']) == 1
assert tag_categories.try_get_category_by_name('name') is None

View file

@ -92,6 +92,13 @@ def test_serializing_tag_category(tag_category_factory):
assert snapshots.get_tag_category_snapshot(category) == {
'name': 'name',
'color': 'color',
'default': False,
}
category.default = True
assert snapshots.get_tag_category_snapshot(category) == {
'name': 'name',
'color': 'color',
'default': True,
}
def test_merging_modification_to_creation(tag_factory, user_factory):