diff --git a/CTFd/utils/csv/__init__.py b/CTFd/utils/csv/__init__.py index 3f1ef924..553a45f1 100644 --- a/CTFd/utils/csv/__init__.py +++ b/CTFd/utils/csv/__init__.py @@ -216,6 +216,66 @@ def dump_teams_with_fields_csv(): return output +def dump_teams_with_members_fields_csv(): + temp = StringIO() + writer = csv.writer(temp) + + team_fields = TeamFields.query.all() + team_field_ids = [f.id for f in team_fields] + team_field_names = [f.name for f in team_fields] + + user_fields = UserFields.query.all() + user_field_ids = [f.id for f in user_fields] + user_field_names = [f.name for f in user_fields] + + user_header = [ + f"member_{column.name}" for column in Users.__mapper__.columns + ] + user_field_names + + header = ( + [column.name for column in Teams.__mapper__.columns] + + team_field_names + + user_header + ) + writer.writerow(header) + + responses = Teams.query.all() + + for curr in responses: + team_field_entries = {f.field_id: f.value for f in curr.field_entries} + team_field_values = [ + team_field_entries.get(f_id, "") for f_id in team_field_ids + ] + + team_row = [ + getattr(curr, column.name) for column in Teams.__mapper__.columns + ] + team_field_values + + writer.writerow(team_row) + + for member in curr.members: + padding = [""] * len(team_row) + + user_field_entries = {f.field_id: f.value for f in member.field_entries} + user_field_values = [ + user_field_entries.get(f_id, "") for f_id in user_field_ids + ] + user_row = [ + getattr(member, column.name) for column in Users.__mapper__.columns + ] + user_field_values + writer.writerow(padding + user_row) + + temp.seek(0) + + # In Python 3 send_file requires bytes + output = BytesIO() + output.write(temp.getvalue().encode("utf-8")) + output.seek(0) + temp.close() + + return output + + def dump_database_table(tablename): # TODO: It might make sense to limit dumpable tables. Config could potentially leak sensitive information. model = get_class_by_tablename(tablename) @@ -334,4 +394,5 @@ CSV_KEYS = { "scoreboard": dump_scoreboard_csv, "users+fields": dump_users_with_fields_csv, "teams+fields": dump_teams_with_fields_csv, + "teams+members+fields": dump_teams_with_members_fields_csv, }