Skip to content

Commit

Permalink
Merge pull request #827 from WildMeOrg/revert-scout-mission-tasks
Browse files Browse the repository at this point in the history
Revert PRs for Scout MissionTasks
  • Loading branch information
bluemellophone authored Oct 7, 2022
2 parents 4c9cc75 + 588dc1a commit ded4053
Show file tree
Hide file tree
Showing 14 changed files with 116 additions and 335 deletions.
2 changes: 1 addition & 1 deletion _frontend.mws
41 changes: 3 additions & 38 deletions app/modules/missions/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,21 +366,11 @@ class MissionTaskUserAssignment(db.Model, HoustonModel):

user_guid = db.Column(db.GUID, db.ForeignKey('user.guid'), primary_key=True)

assigner_guid = db.Column(
db.GUID, db.ForeignKey('user.guid'), primary_key=True, nullable=False
)

mission_task = db.relationship('MissionTask', back_populates='user_assignments')

user = db.relationship(
'User',
backref=db.backref('mission_task_assignments', cascade='all, delete-orphan'),
foreign_keys=[user_guid],
)

assigner = db.relationship(
'User',
foreign_keys=[assigner_guid],
)


Expand Down Expand Up @@ -479,7 +469,6 @@ class MissionTask(db.Model, HoustonModel, Timestamp):
)

notes = db.Column(db.UnicodeText, nullable=True)
is_complete = db.Column(db.Boolean, default=False, nullable=False)

__table_args__ = (db.UniqueConstraint(mission_guid, title),)

Expand Down Expand Up @@ -549,31 +538,17 @@ def user_is_assigned(self, user):
def get_assigned_users(self):
return [assignment.user for assignment in self.user_assignments]

def get_assigned_users_with_assigner_json(self):
# dont really like schemas from within code, but this seemed the shortest
# route to basically adding this `assigner` user _within_ a normal user schema
from app.modules.users.schemas import BaseUserSchema # NOQA

schema = BaseUserSchema()
json = []
for assignment in self.user_assignments:
udata = schema.dump(assignment.user).data
udata['assigner'] = schema.dump(assignment.assigner).data
json.append(udata)
return json

def get_members(self):
return list(set([self.owner] + self.get_assigned_users()))

def add_user(self, user, assigner):
def add_user(self, user):
with db.session.begin(subtransactions=True):
self.add_user_in_context(user, assigner)
self.add_user_in_context(user)

def add_user_in_context(self, user, assigner):
def add_user_in_context(self, user):
assignment = MissionTaskUserAssignment(
mission_task=self,
user=user,
assigner=assigner,
)

db.session.add(assignment)
Expand All @@ -585,16 +560,6 @@ def remove_user_in_context(self, user):
db.session.delete(assignment)
break

# based on current_user
@property
def assigner(self):
from flask_login import current_user

for assignment in self.user_assignments:
if assignment.user == current_user:
return assignment.assigner
return None

def get_assets(self):
return [participation.asset for participation in self.asset_participations]

Expand Down
20 changes: 3 additions & 17 deletions app/modules/missions/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,6 @@ class CreateMissionTaskParameters(SetOperationsJSONParameters):
'collections',
'tasks',
'assets',
# these are for identity op (passthru)
'users',
'title',
]

PATH_CHOICES = tuple('/%s' % field for field in VALID_FIELDS)
Expand Down Expand Up @@ -280,7 +277,6 @@ class PatchMissionTaskDetailsParameters(PatchJSONParametersWithPassword):
'user',
'asset',
MissionTask.title.key,
MissionTask.is_complete.key,
]

SENSITIVE_FIELDS = ('owner',)
Expand Down Expand Up @@ -315,16 +311,13 @@ def add(cls, obj, field, value, state):
# Only task owners or privileged users can add users
user = User.query.get(value)
if rules.owner_or_privileged(current_user, obj) and user:
obj.add_user_in_context(user, current_user)
obj.add_user_in_context(user)
ret_val = True
elif field == 'asset':
asset = Asset.query.get(value)
if rules.owner_or_privileged(current_user, obj) and user:
obj.add_asset_in_context(asset)
ret_val = True
elif field == MissionTask.is_complete.key and isinstance(value, bool):
obj.is_complete = value
ret_val = True
return ret_val

@classmethod
Expand Down Expand Up @@ -376,12 +369,8 @@ def replace(cls, obj, field, value, state):
from app.modules.users.models import User

ret_val = False
# Permissions for all fields (other than is_complete - SCT-367) are the same so have one check
if (
rules.owner_or_privileged(current_user, obj)
or current_user.is_admin
or field == MissionTask.is_complete.key
):
# Permissions for all fields are the same so have one check
if rules.owner_or_privileged(current_user, obj) or current_user.is_admin:
if field == MissionTask.title.key:
obj.title = value
ret_val = True
Expand All @@ -390,7 +379,4 @@ def replace(cls, obj, field, value, state):
if user:
obj.owner = user
ret_val = True
elif field == MissionTask.is_complete.key and isinstance(value, bool):
obj.is_complete = value
ret_val = True
return ret_val
101 changes: 35 additions & 66 deletions app/modules/missions/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,24 +235,8 @@ def post(self, args, mission):
"""
Alias of [POST] /api/v1/missions/<uuid:mission_guid>/collections/
"""
from app.extensions.tus import tus_filepaths_from # NOQA

args['owner'] = current_user
args['mission'] = mission
filepaths, metadatas = tus_filepaths_from(
transaction_id=args.get('transaction_id'),
paths=args.get('paths'),
)
uploaded_filenames = [md.get('filename') for md in metadatas]
dups = []
for asset in mission.get_assets():
if asset.get_original_filename() in uploaded_filenames:
dups.append(asset.get_original_filename())
if dups:
abort(
HTTPStatus.CONFLICT,
f"This Mission already contains files with these names: {', '.join(dups)}",
)
mission_collection, input_filenames = MissionCollection.create_from_tus(**args)
db.session.refresh(mission_collection)

Expand Down Expand Up @@ -381,7 +365,7 @@ def get(self, mission):
@api.response(code=HTTPStatus.CONFLICT)
def post(self, args, mission):
"""
Create a new instance of MissionTask.
Create a new instance of Mission.
"""
from app.modules.assets.models import Asset

Expand All @@ -399,58 +383,43 @@ def post(self, args, mission):
db.session, default_error_message='Failed to create a new MissionTask'
)

# use data (potentially) passed via op=identity
title = identity_dict.get('title')
if title is None:
# Pick a random title with an adjective noun structure (see here: https://github.com/imsky/wordlists)
if USE_GLOBALLY_UNIQUE_MISSION_TASK_NAMES:
current_tasks = MissionTask.query.all()
else:
current_tasks = mission.tasks
titles = [task.title for task in current_tasks]
title = None
while title in titles + [None]:
title = randomname.get_name(
adj=(
'character',
'colors',
'emotions',
'shape',
),
noun=(
'apex_predators',
'birds',
'cats',
'dogs',
'fish',
),
sep=' ',
).title()
title = 'New Task: {}'.format(title)
assert title is not None
assert title not in titles

users_to_assign = {current_user} # always assign current_user
if isinstance(identity_dict.get('users'), list):
from app.modules.users.models import User

for user_guid in identity_dict.get('users'):
user = User.query.get(user_guid)
if not user:
abort(409, message=f'wanting to assign invalid user guid={user_guid}')
users_to_assign.add(user)

task_args = {}
task_args['title'] = title
task_args['owner'] = current_user
task_args['mission'] = mission
mission_task = MissionTask(**task_args)
# Pick a random title with an adjective nown structure (see here: https://github.com/imsky/wordlists)
if USE_GLOBALLY_UNIQUE_MISSION_TASK_NAMES:
current_tasks = MissionTask.query.all()
else:
current_tasks = mission.tasks
titles = [task.title for task in current_tasks]
title = None
while title in titles + [None]:
title = randomname.get_name(
adj=(
'character',
'colors',
'emotions',
'shape',
),
noun=(
'apex_predators',
'birds',
'cats',
'dogs',
'fish',
),
sep=' ',
).title()
title = 'New Task: {}'.format(title)
assert title is not None
assert title not in titles

args = {}
args['title'] = title
args['owner'] = current_user
args['mission'] = mission
mission_task = MissionTask(**args)

with context:
db.session.add(mission_task)
log.debug(f'created {mission_task}, assigning: {users_to_assign}')
for user in users_to_assign:
mission_task.add_user_in_context(user, current_user)
mission_task.add_user_in_context(current_user)
for asset in tqdm.tqdm(asset_set, desc='Adding Assets to MissionTask'):
mission_task.add_asset_in_context(asset)

Expand Down
20 changes: 1 addition & 19 deletions app/modules/missions/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ class Meta:
MissionTask.created.key,
MissionTask.guid.key,
MissionTask.title.key,
MissionTask.is_complete.key,
'mission',
'asset_count',
'elasticsearchable',
Expand All @@ -165,36 +164,19 @@ class Meta:
MissionTask.created.key,
MissionTask.guid.key,
MissionTask.title.key,
MissionTask.is_complete.key,
'asset_count',
'elasticsearchable',
MissionTask.indexed.key,
)
dump_only = (MissionTask.guid.key,)


class BaseMissionTaskWithAssignerSchema(BaseMissionTaskSchema):
"""
MissionTask schema, including assigner
"""

assigner = base_fields.Nested('BaseUserSchema', many=False)

class Meta(BaseMissionTaskSchema.Meta):
fields = BaseMissionTaskSchema.Meta.fields + ('assigner',)
dump_only = BaseMissionTaskSchema.Meta.dump_only


class DetailedMissionTaskSchema(BaseMissionTaskSchema):
"""
Detailed MissionTask schema exposes all useful fields.
"""

# assigned_users = base_fields.Nested('BaseUserSchema', many=True)
assigned_users = base_fields.Function(
lambda t: t.get_assigned_users_with_assigner_json()
)
# def get_assigned_users_with_assigner_json(self):
assigned_users = base_fields.Nested('BaseUserSchema', many=True)

assets = base_fields.Nested(
'BaseAssetSchema',
Expand Down
4 changes: 1 addition & 3 deletions app/modules/users/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ class UserListSchema(BaseUserSchema):
owned_missions = base_fields.Nested('BaseMissionSchema', many=True)
owned_mission_tasks = base_fields.Nested('BaseMissionTaskSchema', many=True)
assigned_missions = base_fields.Nested('BaseMissionSchema', many=True)
assigned_mission_tasks = base_fields.Nested(
'BaseMissionTaskWithAssignerSchema', many=True
)
assigned_mission_tasks = base_fields.Nested('BaseMissionTaskSchema', many=True)

class Meta(BaseUserSchema.Meta):
# pylint: disable=missing-docstring
Expand Down
60 changes: 60 additions & 0 deletions migrations/versions/66bbd28297d2_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
"""empty message
Revision ID: 66bbd28297d2
Revises: 4a23a43a395d
Create Date: 2022-10-07 18:12:05.644149
"""
import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects import postgresql

# revision identifiers, used by Alembic.
revision = '66bbd28297d2'
down_revision = '4a23a43a395d'


def upgrade():
"""
Upgrade Semantic Description:
ENTER DESCRIPTION HERE
"""
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('mission_task', schema=None) as batch_op:
batch_op.drop_column('is_complete')

with op.batch_alter_table('mission_task_user_assignment', schema=None) as batch_op:
batch_op.drop_constraint(
'fk_mission_task_user_assignment_assigner_guid_user', type_='foreignkey'
)
batch_op.drop_column('assigner_guid')

# ### end Alembic commands ###


def downgrade():
"""
Downgrade Semantic Description:
ENTER DESCRIPTION HERE
"""
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('mission_task_user_assignment', schema=None) as batch_op:
batch_op.add_column(
sa.Column(
'assigner_guid', postgresql.UUID(), autoincrement=False, nullable=False
)
)
batch_op.create_foreign_key(
'fk_mission_task_user_assignment_assigner_guid_user',
'user',
['assigner_guid'],
['guid'],
)

with op.batch_alter_table('mission_task', schema=None) as batch_op:
batch_op.add_column(
sa.Column('is_complete', sa.BOOLEAN(), autoincrement=False, nullable=False)
)

# ### end Alembic commands ###
Loading

0 comments on commit ded4053

Please sign in to comment.