def add_user_to_metadata(type, user_info, record_id, submissions):
    if user_info:
        submissions[record_id]["metadata"][type] = {
            'name': user_info['full_name'],
            'email': user_info['email']}
    else:
        submissions[record_id]["metadata"][type] = {
            'name': 'No primary ' + type} def create_record_for_dashboard(record_id, submissions, user, coordinator=None, user_role=None,
                                status="todo"):
    if user_role is None:
        user_role = []

    publication_record = get_record_by_id(int(record_id))

    if publication_record is not None:
        if record_id not in submissions:

            hepdata_submission_record = get_latest_hepsubmission(publication_recid=record_id)

            submissions[record_id] = {}
            submissions[record_id]["metadata"] = {"recid": record_id,
                                                  "role": user_role,
                                                  "start_date": hepdata_submission_record.created,
                                                  "last_updated": hepdata_submission_record.last_updated}

            submissions[record_id]["metadata"][
                "versions"] = hepdata_submission_record.version
            submissions[record_id]["status"] = status
            submissions[record_id]["stats"] = {"passed": 0, "attention": 0,
                                               "todo": 0}

            if coordinator:
                submissions[record_id]["metadata"]["coordinator"] = {
                    'id': coordinator.id, 'name': coordinator.email,
                    'email': coordinator.email}
                if int(user.get_id()) == coordinator.id:
                    submissions[record_id]["metadata"]["show_coord_view"] = True
                    if 'coordinator' not in submissions[record_id]["metadata"]["role"]:
                        submissions[record_id]["metadata"]["role"].append("coordinator")
                else:
                    submissions[record_id]["metadata"]["show_coord_view"] = False
            else:
                submissions[record_id]["metadata"]["coordinator"] = {
                    'name': 'No coordinator'}

            if "title" in publication_record:
                submissions[record_id]["metadata"]["title"] = \
                    publication_record['title']

            if "inspire_id" not in publication_record or publication_record["inspire_id"] is None:
                submissions[record_id]["metadata"][
                    "requires_inspire_id"] = True
        else:
            # if it is, it's because the user has two roles for that
            # submission. So we should show them!
            if user_role not in submissions[record_id]["metadata"]["role"]:
                submissions[record_id]["metadata"]["role"].append(user_role) def prepare_submissions(user, items_per_page=25, current_page=1, record_id=None):
    """
    Finds all the relevant submissions for a user, or all submissions if the logged in user is a 'super admin'.

    :param current_user: User obj
    :param items_per_page: maximum number of items to return
    :param current_page: page of current set of results (starting at 1)
    :return: OrderedDict of submissions
    """
    submissions = OrderedDict()

    query = _prepare_submission_query(user)

    if record_id:
        query = query.filter(HEPSubmission.publication_recid == record_id)

    offset = (current_page - 1) * items_per_page

    hepdata_submission_records = query.order_by(
        HEPSubmission.last_updated.desc()
    ).limit(items_per_page).offset(offset).all()

    for hepdata_submission in hepdata_submission_records:

        if str(hepdata_submission.publication_recid) not in submissions:

            coordinator = User.query.get(hepdata_submission.coordinator)

            participants = get_submission_participants_for_record(
                hepdata_submission.publication_recid,
                user_account=user.id
            )

            if participants:
                user_roles = []

                for participant in participants:
                    user_roles.append(participant.role)

                create_record_for_dashboard(
                    str(hepdata_submission.publication_recid), submissions,
                    user,
                    coordinator=coordinator,
                    user_role=user_roles,
                    status=hepdata_submission.overall_status)
            else:
                create_record_for_dashboard(
                    str(hepdata_submission.publication_recid), submissions,
                    user,
                    coordinator=coordinator,
                    status=hepdata_submission.overall_status)

            # we update the counts for the number of data tables in various
            # states of review
            statuses = ["todo", "attention", "passed"]
            for status in statuses:
                status_count = DataReview.query.filter_by(
                    publication_recid=hepdata_submission.publication_recid,
                    status=status,
                    version=hepdata_submission.version).count()
                if str(hepdata_submission.publication_recid) in submissions:
                    submissions[str(hepdata_submission.publication_recid)][
                        "stats"][status] += status_count

    return submissions def get_pending_invitations_for_user(user):
    """
    Returns pending invites for upload or review of records.

    :param user: User object
    :return: array of pending invites
    """
    pending_invites = SubmissionParticipant.query.filter(
        func.lower(SubmissionParticipant.email) == func.lower(user.email),
        or_(SubmissionParticipant.role == 'reviewer',
            SubmissionParticipant.role == 'uploader'),
        SubmissionParticipant.status == 'primary',
        SubmissionParticipant.user_account == None
    ).all()

    result = []

    for invite in pending_invites:
        publication_record = get_record_by_id(invite.publication_recid)
        hepsubmission = get_latest_hepsubmission(publication_recid=invite.publication_recid)

        coordinator = get_user_from_id(hepsubmission.coordinator)
        result.append(
            {'title': decode_string(publication_record['title']),
             'invitation_cookie': invite.invitation_cookie,
             'role': invite.role, 'coordinator': coordinator})

    return result def get_submission_count(user):
    query = _prepare_submission_query(user)
    return query.count() def list_submission_titles(current_user):
    user = get_dashboard_current_user(current_user)
    query = _prepare_submission_query(user)

    hepdata_submission_records = query.order_by(
        HEPSubmission.last_updated.desc()
    ).all()

    titles = []
    for hepsubmission in hepdata_submission_records:
        publication_record = get_record_by_id(int(hepsubmission.publication_recid))
        if publication_record:
            titles.append({
                'id': int(hepsubmission.publication_recid),
                'title': publication_record['title']
            })

    return titles def get_dashboard_current_user(current_user):
    """Gets the user to display in the dashboard.

    For non-admin users this will just return the current user.
    For admin users, if they have chosen to view the dashboard as another user,
    this will return that user.

    :param invenio_accounts.models.User current_user: Currently logged-in user, e.g. flask_login.current_user
    :return: User to display in the dashboard
    :rtype: invenio_accounts.models.User

    """
    user = None

    if has_role(current_user, 'admin'):
        user_id = get_session_item(VIEW_AS_USER_ID_KEY)
        if user_id and user_id != current_user.id:
            user = User.query.filter_by(id=user_id).first()

    if not user:
        user = current_user

    return user def set_dashboard_current_user(user):
    set_session_item(VIEW_AS_USER_ID_KEY, user.id) VIEW_AS_USER_ID_KEY = 'dashboard_view_as_user_id' class SubmissionParticipant(db.Model):

    """
    This table stores information about the reviewers and
    uploaders of a HEPData submission.
    """
    __tablename__ = "submissionparticipant"

    id = db.Column(db.Integer, primary_key=True,
                   nullable=False, autoincrement=True)

    publication_recid = db.Column(db.Integer)

    full_name = db.Column(db.String(128))
    email = db.Column(db.String(128))
    affiliation = db.Column(db.String(128))
    invitation_cookie = db.Column(UUIDType, default=uuid.uuid4)

    # when the user logs in with their cookie,
    # this user_account should be updated.
    user_account = db.Column(db.Integer, db.ForeignKey(User.id))

    # e.g., reviewer or uploader
    role = db.Column(db.String(32), default='')
    # e.g. primary or reserve reviewer/uploader
    status = db.Column(db.String(32), default='reserve')
    action_date = db.Column(db.DateTime, default=datetime.utcnow, nullable=True, index=True) @blueprint.route(
    '/manage/<int:recid>/<string:action>/<string:status_action>/<int:participant_id>')
@login_required
def manage_participant_status(recid, action, status_action,
                              participant_id):
    """
    Can promote or demote a participant to/from primary reviewer/uploader, or
    remove the participant from the record.

    :param recid: record id that the user will be promoted or demoted for
    :param action: upload or review
    :param status_action: demote, promote or remove
    :param participant_id: id of user from the SubmissionParticipant table.
    :return:
    """
    try:
        participant = SubmissionParticipant.query.filter_by(
            id=participant_id).one()

        if status_action == 'remove':
            db.session.delete(participant)
        else:
            status = 'reserve'
            if status_action == 'promote':
                status = 'primary'

            participant.status = status
            db.session.add(participant)

        db.session.commit()

        record = get_record_by_id(recid)

        # now send the email telling the user of their new status!
        if status_action == 'promote':
            hepsubmission = get_latest_hepsubmission(publication_recid=recid)
            send_cookie_email(participant, record, version=hepsubmission.version)
        elif status_action == 'demote':
            send_reserve_email(participant, record)

        return json.dumps({"success": True, "recid": recid})
    except Exception as e:
        error_str = f"Unable to {status_action} participant id {participant_id} for record {recid}"
        log.error(f"{error_str}: {str(e)}")
        return json.dumps(
            {"success": False, "recid": recid, "message": f"{error_str}. Please refresh the page and try again."}) def create_record(ctx):
    """
    Creates the record in the database.

    :param ctx: The record metadata as a dictionary.
    :return: the recid and the uuid
    """
    record_information = create_data_structure(ctx)
    record_id = uuid.uuid4()
    pid = recid_minter(record_id, record_information)
    record_information['recid'] = int(pid.pid_value)
    record_information['uuid'] = str(record_id)

    Record.create(record_information, id_=record_id)
    db.session.commit()

    return record_information
from flask import session
from flask_login import current_user, login_user
from invenio_db import db
from hepdata.modules.dashboard.api import add_user_to_metadata, \
    create_record_for_dashboard, prepare_submissions, \
    get_pending_invitations_for_user, get_submission_count, \
    list_submission_titles, get_dashboard_current_user, \
    set_dashboard_current_user, VIEW_AS_USER_ID_KEY
from hepdata.modules.permissions.models import SubmissionParticipant
from hepdata.modules.permissions.views import manage_participant_status
from hepdata.modules.records.utils.common import get_record_by_id
from hepdata.modules.records.utils.submission import get_or_create_hepsubmission
from hepdata.modules.records.utils.workflow import create_record
from invenio_accounts.models import User, Role
from pytest_mock import mocker
from . import conftest
import pytest
        }
    }
    add_user_to_metadata('test_type', None, '123456', test_submissions)
    assert(test_submissions == {
        '123456': {
            "metadata": {
                'test_type': {
                    'name': 'No primary test_type'
                }
            }
        }
    })


def test_create_record_for_dashboard(app):
    with app.app_context():
        record_information = create_record({'journal_info': 'Phys. Letts', 'title': 'My Journal Paper', 'inspire_id': '1487726'})
        hepsubmission = get_or_create_hepsubmission(record_information['recid'])
        record = get_record_by_id(record_information['recid'])
        user = User(email='test@test.com', password='hello1', active=True,
                    id=101)

        test_submissions = {}
        create_record_for_dashboard(record['recid'], test_submissions, user)
        assert(test_submissions == {
            record_information['recid']: {
                'metadata': {
                    'coordinator': {'name': 'No coordinator'},
                    'recid': record_information['recid'],
                    'role': [],
                    'start_date': hepsubmission.created,
                    'last_updated': hepsubmission.last_updated,
                    'title': u'My Journal Paper',
                    'versions': 1
                },
                'stats': {'attention': 0, 'passed': 0, 'todo': 0},
                'status': 'todo'
            }
        })

        test_submissions = {
            record_information['recid']: {
                "metadata": {"role": []}
            }
        }

        create_record_for_dashboard(record['recid'], test_submissions, user)
        assert(test_submissions == {
            record_information['recid']: {
                "metadata": {"role": [[]]}
            }
        })


def test_submissions_empty(app):
    with app.app_context():
        user = User(email='test@test.com', password='hello1', active=True, id=101)
        assert(get_submission_count(user) == 0)
        assert(list_submission_titles(user) == [])
        assert(prepare_submissions(user) == {})


def test_submissions_admin(app, load_submission):
    with app.app_context():
        record_information = create_record({
            'journal_info': 'Phys. Letts',
            'title': 'My Journal Paper',
            'inspire_id': '1487726'
        })
        hepsubmission = get_or_create_hepsubmission(record_information['recid'])

        role = Role(name='admin')
        user = User(email='test@test.com', password='hello1', active=True,
                    id=101, roles=[role])

        assert(get_submission_count(user) == 1)
        assert(list_submission_titles(user) == [{
            'id': record_information['recid'],
            'title': 'My Journal Paper'
        }])

        submissions = prepare_submissions(user)
        assert(len(submissions) == 1)
        assert(submissions[str(record_information['recid'])] == {
            'metadata': {
                'coordinator': {'email': u'test@hepdata.net',
                                'name': u'test@hepdata.net',
                                'id': 1},
                'recid': str(record_information['recid']),
                'role': [],
                'show_coord_view': False,
                'start_date': hepsubmission.created,
                'last_updated': hepsubmission.last_updated,
                'title': u'My Journal Paper',
                'versions': 1
            },
            'stats': {'attention': 0, 'passed': 0, 'todo': 0},
            'status': u'todo'
        })


def test_submissions_participant(app, load_submission):
    with app.app_context():
        record_information = create_record({
            'journal_info': 'Phys. Letts',
            'title': 'My Journal Paper',
            'inspire_id': '1487726'
        })
        hepsubmission = get_or_create_hepsubmission(record_information['recid'])
        db.session.add(hepsubmission)

        user = User(email='test@test.com', password='hello1', active=True)
        db.session.add(user)
        db.session.commit()

        # Check the user doesn't see the record before they are a participant
        assert(get_submission_count(user) == 0)
        assert(list_submission_titles(user) == [])

        # Add the user as a participant

        participant = SubmissionParticipant(