Prevent recursive grouping of albums/tags

How did I not catch this before
This commit is contained in:
voussoir 2016-12-20 18:31:09 -08:00
parent b5294431aa
commit e992b76db0
4 changed files with 15 additions and 2 deletions

View file

@ -98,6 +98,7 @@ ERROR_NO_SUCH_TAG = 'Doesn\'t exist'
ERROR_NO_TAG_GIVEN = 'No tag name supplied' ERROR_NO_TAG_GIVEN = 'No tag name supplied'
ERROR_SYNONYM_ITSELF = 'Cant apply synonym to itself' ERROR_SYNONYM_ITSELF = 'Cant apply synonym to itself'
ERROR_TAG_TOO_SHORT = 'Not enough valid chars' ERROR_TAG_TOO_SHORT = 'Not enough valid chars'
ERROR_RECURSIVE_GROUPING = 'Recursive grouping'
WARNING_MINMAX_INVALID = 'Field "{field}": "{value}" is not a valid request. Ignored.' WARNING_MINMAX_INVALID = 'Field "{field}": "{value}" is not a valid request. Ignored.'
WARNING_MINMAX_OOO = 'Field "{field}": minimum "{min}" maximum "{max}" are out of order. Ignored.' WARNING_MINMAX_OOO = 'Field "{field}": minimum "{min}" maximum "{max}" are out of order. Ignored.'
WARNING_NO_SUCH_TAG = 'Tag "{tag}" does not exist. Ignored.' WARNING_NO_SUCH_TAG = 'Tag "{tag}" does not exist. Ignored.'

View file

@ -685,6 +685,8 @@ def post_edit_tags():
response = {'error': constants.ERROR_SYNONYM_ITSELF, 'tagname': tag} response = {'error': constants.ERROR_SYNONYM_ITSELF, 'tagname': tag}
except exceptions.NoSuchTag as e: except exceptions.NoSuchTag as e:
response = {'error': constants.ERROR_NO_SUCH_TAG, 'tagname': tag} response = {'error': constants.ERROR_NO_SUCH_TAG, 'tagname': tag}
except exceptions.RecursiveGrouping as e:
response = {'error': constants.ERROR_RECURSIVE_GROUPING, 'tagname': tag}
except ValueError as e: except ValueError as e:
response = {'error': e.args[0], 'tagname': tag} response = {'error': e.args[0], 'tagname': tag}
else: else:

View file

@ -33,6 +33,9 @@ class UserExists(Exception):
# TAG ERRORS # TAG ERRORS
class RecursiveGrouping(Exception):
pass
class TagTooLong(Exception): class TagTooLong(Exception):
pass pass

View file

@ -43,15 +43,22 @@ class GroupableMixin:
if not isinstance(member, type(self)): if not isinstance(member, type(self)):
raise TypeError('Member must be of type %s' % type(self)) raise TypeError('Member must be of type %s' % type(self))
# Groupables are only allowed to have 1 parent.
# Unlike photos which can exist in multiple albums.
self.photodb.cur.execute('SELECT * FROM tag_group_rel WHERE memberid == ?', [member.id]) self.photodb.cur.execute('SELECT * FROM tag_group_rel WHERE memberid == ?', [member.id])
fetch = self.photodb.cur.fetchone() fetch = self.photodb.cur.fetchone()
if fetch is not None: if fetch is not None:
if fetch[constants.SQL_TAGGROUP['parentid']] == self.id: parent_id = fetch[constants.SQL_TAGGROUP['parentid']]
if parent_id == self.id:
that_group = self that_group = self
else: else:
that_group = self.group_getter(id=fetch[constants.SQL_TAGGROUP['parentid']]) that_group = self.group_getter(id=parent_id)
raise exceptions.GroupExists('%s already in group %s' % (member.name, that_group.name)) raise exceptions.GroupExists('%s already in group %s' % (member.name, that_group.name))
for parent in self.walk_parents():
if parent.id == member.id:
raise exceptions.RecursiveGrouping('%s is an ancestor of %s' % (member.name, self.name))
self.photodb._cached_frozen_children = None self.photodb._cached_frozen_children = None
self.photodb.cur.execute('INSERT INTO tag_group_rel VALUES(?, ?)', [self.id, member.id]) self.photodb.cur.execute('INSERT INTO tag_group_rel VALUES(?, ?)', [self.id, member.id])
if commit: if commit: