diff --git a/client/html/pool_input.tpl b/client/html/pool_input.tpl index 0c2a3fd9..483e7905 100644 --- a/client/html/pool_input.tpl +++ b/client/html/pool_input.tpl @@ -1,7 +1,6 @@
-
diff --git a/client/html/pool_summary.tpl b/client/html/pool_summary.tpl index 8f4e27d0..2b70d270 100644 --- a/client/html/pool_summary.tpl +++ b/client/html/pool_summary.tpl @@ -6,12 +6,12 @@
- Aliases:
- + Aliases:
+
diff --git a/client/js/controllers/pool_controller.js b/client/js/controllers/pool_controller.js index e243cd89..22920f09 100644 --- a/client/js/controllers/pool_controller.js +++ b/client/js/controllers/pool_controller.js @@ -54,8 +54,7 @@ class PoolController { this._view.addEventListener('submit', e => this._evtUpdate(e)); this._view.addEventListener('merge', e => this._evtMerge(e)); this._view.addEventListener('delete', e => this._evtDelete(e)); - }, - error => { + }, error => { this._view = new EmptyView(); this._view.showError(error.message); }); @@ -68,9 +67,7 @@ class PoolController { _evtSaved(e, section) { misc.disableExitConfirmation(); if (this._name !== e.detail.pool.names[0]) { - router.replace( - uri.formatClientLink('pool', e.detail.pool.id, section), - null, false); + router.replace(uri.formatClientLink('pool', e.detail.pool.id, section), null, false); } } @@ -87,9 +84,9 @@ class PoolController { e.detail.pool.description = e.detail.description; } if (e.detail.posts !== undefined) { - e.detail.pool.posts.clear() + e.detail.pool.posts.clear(); for (let post_id of e.detail.posts) { - e.detail.pool.posts.add(Post.fromResponse({ id: parseInt(post_id) })) + e.detail.pool.posts.add(Post.fromResponse({ id: parseInt(post_id) })); } } e.detail.pool.save().then(() => { diff --git a/client/js/controllers/pool_create_controller.js b/client/js/controllers/pool_create_controller.js index ef6dded2..0684693e 100644 --- a/client/js/controllers/pool_create_controller.js +++ b/client/js/controllers/pool_create_controller.js @@ -16,8 +16,7 @@ class PoolCreateController { return; } - PoolCategoryList.get() - .then(poolCategoriesResponse => { + PoolCategoryList.get().then(poolCategoriesResponse => { const categories = {}; for (let category of poolCategoriesResponse.results) { categories[category.name] = category.name; diff --git a/client/js/controls/pool_input_control.js b/client/js/controls/pool_input_control.js index a8272066..95dfc5cb 100644 --- a/client/js/controls/pool_input_control.js +++ b/client/js/controls/pool_input_control.js @@ -81,105 +81,105 @@ class PoolInputControl extends events.EventTarget { return Promise.resolve(); } - this.pools.add(pool, false) + this.pools.add(pool, false) - const listItemNode = this._createListItemNode(pool); - if (!pool.category) { - listItemNode.classList.add('new'); - } - this._poolListNode.prependChild(listItemNode); - _fadeOutListItemNodeStatus(listItemNode); + const listItemNode = this._createListItemNode(pool); + if (!pool.category) { + listItemNode.classList.add('new'); + } + this._poolListNode.prependChild(listItemNode); + _fadeOutListItemNodeStatus(listItemNode); - this.dispatchEvent(new CustomEvent('add', { - detail: {pool: pool, source: source}, - })); - this.dispatchEvent(new CustomEvent('change')); + this.dispatchEvent(new CustomEvent('add', { + detail: {pool: pool, source: source}, + })); + this.dispatchEvent(new CustomEvent('change')); - return Promise.resolve(); + return Promise.resolve(); } - deletePool(pool) { - if (!this.pools.hasPoolId(pool.id)) { - return; + deletePool(pool) { + if (!this.pools.hasPoolId(pool.id)) { + return; + } + this.pools.removeById(pool.id); + this._hideAutoComplete(); + + this._deleteListItemNode(pool); + + this.dispatchEvent(new CustomEvent('remove', { + detail: {pool: pool}, + })); + this.dispatchEvent(new CustomEvent('change')); } - this.pools.removeById(pool.id); - this._hideAutoComplete(); - this._deleteListItemNode(pool); + _createListItemNode(pool) { + const className = pool.category ? + misc.makeCssName(pool.category, 'pool') : + null; - this.dispatchEvent(new CustomEvent('remove', { - detail: {pool: pool}, - })); - this.dispatchEvent(new CustomEvent('change')); - } + const poolLinkNode = document.createElement('a'); + if (className) { + poolLinkNode.classList.add(className); + } + poolLinkNode.setAttribute( + 'href', uri.formatClientLink('pool', pool.names[0])); - _createListItemNode(pool) { - const className = pool.category ? - misc.makeCssName(pool.category, 'pool') : - null; + const poolIconNode = document.createElement('i'); + poolIconNode.classList.add('fa'); + poolIconNode.classList.add('fa-pool'); + poolLinkNode.appendChild(poolIconNode); - const poolLinkNode = document.createElement('a'); - if (className) { - poolLinkNode.classList.add(className); + const searchLinkNode = document.createElement('a'); + if (className) { + searchLinkNode.classList.add(className); + } + searchLinkNode.setAttribute( + 'href', uri.formatClientLink( + 'posts', {query: "pool:" + pool.id})); + searchLinkNode.textContent = pool.names[0] + ' '; + + const usagesNode = document.createElement('span'); + usagesNode.classList.add('pool-usages'); + usagesNode.setAttribute('data-pseudo-content', pool.postCount); + + const removalLinkNode = document.createElement('a'); + removalLinkNode.classList.add('remove-pool'); + removalLinkNode.setAttribute('href', ''); + removalLinkNode.setAttribute('data-pseudo-content', '×'); + removalLinkNode.addEventListener('click', e => { + e.preventDefault(); + this.deletePool(pool); + }); + + const listItemNode = document.createElement('li'); + listItemNode.appendChild(removalLinkNode); + listItemNode.appendChild(poolLinkNode); + listItemNode.appendChild(searchLinkNode); + listItemNode.appendChild(usagesNode); + for (let name of pool.names) { + this._poolToListItemNode.set(name, listItemNode); + } + return listItemNode; } - poolLinkNode.setAttribute( - 'href', uri.formatClientLink('pool', pool.names[0])); - const poolIconNode = document.createElement('i'); - poolIconNode.classList.add('fa'); - poolIconNode.classList.add('fa-pool'); - poolLinkNode.appendChild(poolIconNode); - - const searchLinkNode = document.createElement('a'); - if (className) { - searchLinkNode.classList.add(className); + _deleteListItemNode(pool) { + const listItemNode = this._getListItemNode(pool); + if (listItemNode) { + listItemNode.parentNode.removeChild(listItemNode); + } + for (let name of pool.names) { + this._poolToListItemNode.delete(name); + } } - searchLinkNode.setAttribute( - 'href', uri.formatClientLink( - 'posts', {query: "pool:" + pool.id})); - searchLinkNode.textContent = pool.names[0] + ' '; - const usagesNode = document.createElement('span'); - usagesNode.classList.add('pool-usages'); - usagesNode.setAttribute('data-pseudo-content', pool.postCount); - - const removalLinkNode = document.createElement('a'); - removalLinkNode.classList.add('remove-pool'); - removalLinkNode.setAttribute('href', ''); - removalLinkNode.setAttribute('data-pseudo-content', '×'); - removalLinkNode.addEventListener('click', e => { - e.preventDefault(); - this.deletePool(pool); - }); - - const listItemNode = document.createElement('li'); - listItemNode.appendChild(removalLinkNode); - listItemNode.appendChild(poolLinkNode); - listItemNode.appendChild(searchLinkNode); - listItemNode.appendChild(usagesNode); - for (let name of pool.names) { - this._poolToListItemNode.set(name, listItemNode); + _getListItemNode(pool) { + return this._poolToListItemNode.get(pool.names[0]); } - return listItemNode; - } - _deleteListItemNode(pool) { - const listItemNode = this._getListItemNode(pool); - if (listItemNode) { - listItemNode.parentNode.removeChild(listItemNode); + _hideAutoComplete() { + this._autoCompleteControl.hide(); } - for (let name of pool.names) { - this._poolToListItemNode.delete(name); - } - } - - _getListItemNode(pool) { - return this._poolToListItemNode.get(pool.names[0]); - } - - _hideAutoComplete() { - this._autoCompleteControl.hide(); - } } module.exports = PoolInputControl; diff --git a/client/js/models/pool_category.js b/client/js/models/pool_category.js index 4cdb68e6..a77302c2 100644 --- a/client/js/models/pool_category.js +++ b/client/js/models/pool_category.js @@ -17,7 +17,7 @@ class PoolCategory extends events.EventTarget { get name() { return this._name; } get color() { return this._color; } - get poolCount() { return this._poolCount; } + get poolCount() { return this._poolCount; } get isDefault() { return this._isDefault; } get isTransient() { return !this._origName; } diff --git a/server/alembic.ini b/server/alembic.ini index 98ab83d4..6a4e5ff4 100644 --- a/server/alembic.ini +++ b/server/alembic.ini @@ -3,7 +3,6 @@ script_location = szurubooru/migrations # overriden by szurubooru's config sqlalchemy.url = -revision_environment = true [loggers] keys = root,sqlalchemy,alembic diff --git a/server/config.yaml.dist b/server/config.yaml.dist index baf3a34e..37e877f1 100644 --- a/server/config.yaml.dist +++ b/server/config.yaml.dist @@ -4,7 +4,7 @@ # shown in the website title and on the front page name: szurubooru # full url to the homepage of this szurubooru site, with no trailing slash -domain: localhost # example: http://example.com +domain: # example: http://example.com # used to salt the users' password hashes and generate filenames for static content secret: change @@ -49,9 +49,6 @@ enable_safety: yes tag_name_regex: ^\S+$ tag_category_name_regex: ^[^\s%+#/]+$ -pool_name_regex: ^\S+$ -pool_category_name_regex: ^[^\s%+#/]+$ - # don't make these more restrictive unless you want to annoy people; if you do # customize them, make sure to update the instructions in the registration form # template as well. @@ -61,72 +58,72 @@ user_name_regex: '^[a-zA-Z0-9_-]{1,32}$' default_rank: regular privileges: - 'users:create:self': anonymous # Registration permission - 'users:create:any': administrator - 'users:list': regular - 'users:view': regular - 'users:edit:any:name': moderator - 'users:edit:any:pass': moderator - 'users:edit:any:email': moderator - 'users:edit:any:avatar': moderator - 'users:edit:any:rank': moderator - 'users:edit:self:name': regular - 'users:edit:self:pass': regular - 'users:edit:self:email': regular - 'users:edit:self:avatar': regular - 'users:edit:self:rank': moderator # one can't promote themselves or anyone to upper rank than their own. - 'users:delete:any': administrator - 'users:delete:self': regular + 'users:create:self': anonymous # Registration permission + 'users:create:any': administrator + 'users:list': regular + 'users:view': regular + 'users:edit:any:name': moderator + 'users:edit:any:pass': moderator + 'users:edit:any:email': moderator + 'users:edit:any:avatar': moderator + 'users:edit:any:rank': moderator + 'users:edit:self:name': regular + 'users:edit:self:pass': regular + 'users:edit:self:email': regular + 'users:edit:self:avatar': regular + 'users:edit:self:rank': moderator # one can't promote themselves or anyone to upper rank than their own. + 'users:delete:any': administrator + 'users:delete:self': regular - 'user_tokens:list:any': administrator - 'user_tokens:list:self': regular - 'user_tokens:create:any': administrator - 'user_tokens:create:self': regular - 'user_tokens:edit:any': administrator - 'user_tokens:edit:self': regular - 'user_tokens:delete:any': administrator - 'user_tokens:delete:self': regular + 'user_tokens:list:any': administrator + 'user_tokens:list:self': regular + 'user_tokens:create:any': administrator + 'user_tokens:create:self': regular + 'user_tokens:edit:any': administrator + 'user_tokens:edit:self': regular + 'user_tokens:delete:any': administrator + 'user_tokens:delete:self': regular - 'posts:create:anonymous': regular - 'posts:create:identified': regular - 'posts:list': anonymous - 'posts:reverse_search': regular - 'posts:view': anonymous - 'posts:view:featured': anonymous - 'posts:edit:content': power - 'posts:edit:flags': regular - 'posts:edit:notes': regular - 'posts:edit:relations': regular - 'posts:edit:safety': power - 'posts:edit:source': regular - 'posts:edit:tags': regular - 'posts:edit:thumbnail': power - 'posts:feature': moderator - 'posts:delete': moderator - 'posts:score': regular - 'posts:merge': moderator - 'posts:favorite': regular - 'posts:bulk-edit:tags': power - 'posts:bulk-edit:safety': power + 'posts:create:anonymous': regular + 'posts:create:identified': regular + 'posts:list': anonymous + 'posts:reverse_search': regular + 'posts:view': anonymous + 'posts:view:featured': anonymous + 'posts:edit:content': power + 'posts:edit:flags': regular + 'posts:edit:notes': regular + 'posts:edit:relations': regular + 'posts:edit:safety': power + 'posts:edit:source': regular + 'posts:edit:tags': regular + 'posts:edit:thumbnail': power + 'posts:feature': moderator + 'posts:delete': moderator + 'posts:score': regular + 'posts:merge': moderator + 'posts:favorite': regular + 'posts:bulk-edit:tags': power + 'posts:bulk-edit:safety': power - 'tags:create': regular - 'tags:edit:names': power - 'tags:edit:category': power - 'tags:edit:description': power - 'tags:edit:implications': power - 'tags:edit:suggestions': power - 'tags:list': regular - 'tags:view': anonymous - 'tags:merge': moderator - 'tags:delete': moderator + 'tags:create': regular + 'tags:edit:names': power + 'tags:edit:category': power + 'tags:edit:description': power + 'tags:edit:implications': power + 'tags:edit:suggestions': power + 'tags:list': regular + 'tags:view': anonymous + 'tags:merge': moderator + 'tags:delete': moderator - 'tag_categories:create': moderator - 'tag_categories:edit:name': moderator - 'tag_categories:edit:color': moderator - 'tag_categories:list': anonymous - 'tag_categories:view': anonymous - 'tag_categories:delete': moderator - 'tag_categories:set_default': moderator + 'tag_categories:create': moderator + 'tag_categories:edit:name': moderator + 'tag_categories:edit:color': moderator + 'tag_categories:list': anonymous + 'tag_categories:view': anonymous + 'tag_categories:delete': moderator + 'tag_categories:set_default': moderator 'pools:create': regular 'pools:edit:names': power @@ -146,19 +143,19 @@ privileges: 'pool_categories:delete': moderator 'pool_categories:set_default': moderator - 'comments:create': regular - 'comments:delete:any': moderator - 'comments:delete:own': regular - 'comments:edit:any': moderator - 'comments:edit:own': regular - 'comments:list': regular - 'comments:view': regular - 'comments:score': regular + 'comments:create': regular + 'comments:delete:any': moderator + 'comments:delete:own': regular + 'comments:edit:any': moderator + 'comments:edit:own': regular + 'comments:list': regular + 'comments:view': regular + 'comments:score': regular - 'snapshots:list': power + 'snapshots:list': power - 'uploads:create': regular - 'uploads:use_downloader': power + 'uploads:create': regular + 'uploads:use_downloader': power ## ONLY SET THESE IF DEPLOYING OUTSIDE OF DOCKER #debug: 0 # generate server logs? diff --git a/server/requirements.txt b/server/requirements.txt index 8a337f9e..810452e0 100644 --- a/server/requirements.txt +++ b/server/requirements.txt @@ -9,4 +9,3 @@ pillow>=4.3.0 pynacl>=1.2.1 pytz>=2018.3 pyRFC3339>=1.0 -youtube_dl>=2020.5.3 diff --git a/server/szurubooru/db.py b/server/szurubooru/db.py index bd300420..561b7484 100644 --- a/server/szurubooru/db.py +++ b/server/szurubooru/db.py @@ -34,22 +34,3 @@ def _bump_query_count() -> None: sa.event.listen(_engine, 'after_execute', lambda *args: _bump_query_count()) - -import time -import logging - -logger = logging.getLogger("myapp.sqltime") -logger.setLevel(logging.INFO) - -def before_cursor_execute(conn, cursor, statement, - parameters, context, executemany): - conn.info.setdefault('query_start_time', []).append(time.time()) - logger.info("Start Query: %s" % statement) - -def after_cursor_execute(conn, cursor, statement, - parameters, context, executemany): - total = time.time() - conn.info['query_start_time'].pop(-1) - logger.info("Total Time: %f" % total) - -sa.event.listen(_engine, "before_cursor_execute", before_cursor_execute) -sa.event.listen(_engine, "after_cursor_execute", after_cursor_execute) diff --git a/server/szurubooru/func/pool_categories.py b/server/szurubooru/func/pool_categories.py index eca934a9..83305de0 100644 --- a/server/szurubooru/func/pool_categories.py +++ b/server/szurubooru/func/pool_categories.py @@ -195,5 +195,5 @@ def delete_category(category: model.PoolCategory) -> None: if (category.pool_count or 0) > 0: raise PoolCategoryIsInUseError( 'Pool category has some usages and cannot be deleted. ' + - 'Please remove this category from relevant pools first..') + 'Please remove this category from relevant pools first.') db.session.delete(category) diff --git a/server/szurubooru/func/pools.py b/server/szurubooru/func/pools.py index 1d279296..90dede22 100644 --- a/server/szurubooru/func/pools.py +++ b/server/szurubooru/func/pools.py @@ -77,6 +77,7 @@ def _duplicates(a: List[int]) -> List[int]: dupes.append(x) return dupes + def sort_pools(pools: List[model.Pool]) -> List[model.Pool]: default_category_name = pool_categories.get_default_category_name() return sorted( @@ -131,8 +132,7 @@ class PoolSerializer(serialization.BaseSerializer): def serialize_posts(self) -> Any: return [post for post in - [posts.serialize_micro_post(rel, None) - for rel in self.pool.posts]] + [posts.serialize_micro_post(rel, None) for rel in self.pool.posts]] def serialize_pool( @@ -221,7 +221,7 @@ def merge_pools(source_pool: model.Pool, target_pool: model.Pool) -> None: if source_pool.pool_id == target_pool.pool_id: raise InvalidPoolRelationError('Cannot merge pool with itself.') - def merge_posts(source_pool_id: int, target_pool_id: int) -> None: + def merge_pool_posts(source_pool_id: int, target_pool_id: int) -> None: alias1 = model.PoolPost alias2 = sa.orm.util.aliased(model.PoolPost) update_stmt = ( @@ -236,7 +236,7 @@ def merge_pools(source_pool: model.Pool, target_pool: model.Pool) -> None: update_stmt = update_stmt.values(pool_id=target_pool_id) db.session.execute(update_stmt) - merge_posts(source_pool.pool_id, target_pool.pool_id) + merge_pool_posts(source_pool.pool_id, target_pool.pool_id) delete(source_pool) @@ -304,8 +304,6 @@ def update_pool_posts(pool: model.Pool, post_ids: List[int]) -> None: assert pool dupes = _duplicates(post_ids) if len(dupes) > 0: - print(str(dupes)) - print(str(post_ids)) dupes = ', '.join(list(str(x) for x in dupes)) raise InvalidPoolDuplicateError('Duplicate post(s) in pool: ' + dupes) ret = posts.get_posts_by_ids(post_ids) diff --git a/server/szurubooru/func/posts.py b/server/szurubooru/func/posts.py index 723a4668..62458d8e 100644 --- a/server/szurubooru/func/posts.py +++ b/server/szurubooru/func/posts.py @@ -300,7 +300,7 @@ class PostSerializer(serialization.BaseSerializer): self.post.comments, key=lambda comment: comment.creation_time)] - def serialize_pools(self) -> Any: + def serialize_pools(self) -> List[Any]: return [ pools.serialize_pool(pool) for pool in sorted( @@ -343,7 +343,7 @@ def get_post_by_id(post_id: int) -> model.Post: return post -def get_posts_by_ids(ids: List[int]) -> List[model.Pool]: +def get_posts_by_ids(ids: List[int]) -> List[model.Post]: if len(ids) == 0: return [] posts = (