Ejemplo n.º 1
0
    def nameEmail(self, user=None):
        """Provide a string representation of the name and email of the user.

        !!! note
            Care will be taken that to unauthenticated users only
            limited information about users will be shown.

        Parameters
        ----------
        user: dict, optional `None`
            The user whose identity must be represented.
            If absent, the currently logged in user will be taken.

        Returns
        -------
        string
        """

        if user is None:
            user = self.user

        name = G(user, N.name) or E
        if not name:
            firstName = G(user, N.firstName) or E
            lastName = G(user, N.lastName) or E
            name = firstName + (BLANK if firstName and lastName else E) + lastName
        group = self.groupRep(user=user)
        isAuth = group != UNAUTH
        email = (G(user, N.email) or E) if isAuth else E
        return (name, email)
Ejemplo n.º 2
0
    def icon(icon, asChar=False, **atts):
        """icon.

        Pseudo element for an icon.

        !!! warning
            The `icon` names must be listed in the web.yaml config file
            under the key `icons`. The icon itself is a Unicode character.

        Parameters
        ----------
        icon: string
            Name of the icon.
        asChar: boolean, optional, `False`
            If `True`, just output the icon character.
            Otherwise, wrap it in a `<span>` with all
            attributes that might have been passed.

        Returns
        -------
        string(html)
        """

        iconChar = G(ICONS, icon, default=ICONS[N.noicon])
        if asChar:
            return G(ICONS, icon, default=ICONS[N.noicon])
        addClass = f"{N.symbol} i-{icon} "
        return HtmlElement(N.span).wrap(iconChar, addClass=addClass, **atts)
Ejemplo n.º 3
0
    def getValueIds(self, valueTable, constrain):
        """Fetch a set of ids from a value table.

        The ids are taken from the value reocrds that satisfy a constraint.
        but with members restricted by a constraint.

        Parameters
        ----------
        valueTable: string
            The table that contains the records.
        constrain: 2-tuple, optional `None`
            A custom constraint. If present, it should be a tuple `(fieldName, value)`.
            Only records with that value in that field will be delivered.

        Returns
        -------
        set of ObjectId
        """

        records = (
            r
            for r in getattr(self, valueTable, {}).values()
            if G(r, constrain[0]) == constrain[1]
        )
        return {G(r, N._id) for r in records}
Ejemplo n.º 4
0
    def getWf(self, table, kind=None):
        """Select a source of attributes within a workflow item.

        Parameters
        ----------
        table: string
            We must specify the kind of record for which we want the attributes:
            contrib, assessment, or review.
        kind: string {`expert`, `final`}, optional `None`
            Only if we want review attributes

        Returns
        -------
        dict
        """

        data = self.data
        if table == N.contrib:
            return data

        data = G(data, N.assessment)
        if table in {N.assessment, N.criteriaEntry}:
            return data

        if table in {N.review, N.reviewEntry}:
            data = G(G(data, N.reviews), kind)
            return data

        return None
Ejemplo n.º 5
0
def main():
    client = MongoClient()
    sys.stdout.write(f"ADD TEST USERS to DATABASE {DATABASE} ... ")
    db = client[DATABASE]

    idFromIso = {
        G(record, N.iso): G(record, N._id)
        for record in db.country.find()
    }
    idFromGroup = {
        G(record, N.rep): G(record, N._id)
        for record in db.permissionGroup.find()
    }

    users = []
    for user in USER:
        u = dict(x for x in user.items())
        u[N.group] = idFromGroup[u[N.group]]
        if N.country in u:
            u[N.country] = idFromIso[u[N.country]]
        users.append(u)

    db.user.insert_many(users)

    sys.stdout.write("DONE\n")
Ejemplo n.º 6
0
    def getValueInv(self, valueTable, constrain):
        """Fetch a mapping from values to ids from a value table.

        The mapping is like the *valueTable*`Inv` attribute of `Db`,
        but with members restricted by a constraint.

        !!! caution
            This only works properly if the valueTable has a field `rep`.

        Parameters
        ----------
        valueTable: string
            The table that contains the records.
        constrain: 2-tuple, optional `None`
            A custom constraint. If present, it should be a tuple `(fieldName, value)`.
            Only records with that value in that field will be delivered.

        Returns
        -------
        dict
            Keyed by values, valued by ids.
        """

        records = (
            r
            for r in getattr(self, valueTable, {}).values()
            if G(r, constrain[0]) == constrain[1]
        )
        eids = {G(r, N._id) for r in records}
        return {
            value: eid
            for (value, eid) in getattr(self, f"""{valueTable}Inv""", {}).items()
            if eid in eids
        }
Ejemplo n.º 7
0
    def myReviewerKind(self, reviewer=None):
        """Determine whether the current user is `expert` or `final`.

        Parameters
        ----------
        reviewer: dict, optional `None`
            If absent, the assessment in the workflow info will be inspected
            to get a dict of its reviewers by kind.
            Otherwise, it should be a dict of user ids keyed by `expert` and
            `final`.

        Returns
        -------
        string {`expert`, `final`} | `None`
            Depending on whether the current user is such a reviewer of the
            assessment of this contribution. Or `None` if (s)he is not a reviewer
            at all.
        """
        uid = self.uid

        if reviewer is None:
            reviewer = G(self.getWf(N.assessment), N.reviewer)

        return (N.expert if G(reviewer, N.expert) == uid else
                N.final if G(reviewer, N.final) == uid else None)
Ejemplo n.º 8
0
def execute(context, task, eid):
    """Executes a workflow task.

    First a table object is constructed, based on the `table` property
    of the task, using `context`.

    Then a record object is constructed in that table, based on the `eid`
    parameter.

    If that all succeeds, all information is at hand to verify permissions
    and perform the task.

    Parameters
    ----------
    context: object
        A `control.context.Context` singleton
    task: string
        The name of the task
    eid: string(objectId)
        The id of the relevant record
    """

    taskInfo = G(TASKS, task)
    acro = G(taskInfo, N.acro)
    table = G(taskInfo, N.table)
    if table not in ALL_TABLES:
        flash(f"""Workflow {acro} operates on wrong table: "{table or E}""",
              "error")
        return (False, None)
    return mkTable(context, table).record(eid=eid).task(task)
Ejemplo n.º 9
0
 def assertIt(cl, exp):
     assertModifyField(cl, CONTRIB, eid, TITLE, TITLE2, exp[CONTRIB])
     assertModifyField(cl, ASSESS, aId, TITLE, TITLE_A2, exp[ASSESS])
     reviewerFId = G(users, FINAL)
     reviewerEId = G(users, EXPERT)
     assertModifyField(cl, ASSESS, aId, REVIEWER_E, (reviewerFId, FINAL),
                       exp["assign"])
     assertModifyField(cl, ASSESS, aId, REVIEWER_E, (reviewerEId, EXPERT),
                       exp["assign"])
     assertModifyField(
         cl,
         CRITERIA_ENTRY,
         cIdFirst,
         EVIDENCE,
         ([EVIDENCE1], EVIDENCE1),
         exp[CRITERIA_ENTRY],
     )
     for (rId, remarks, kind) in (
         (rExpertId, REMARKS_E, EXPERT),
         (rFinalId, REMARKS_F, FINAL),
     ):
         assertModifyField(cl, REVIEW, rId, REMARKS, ([remarks], remarks),
                           exp[f"{REVIEW}_{kind}"])
     for (kind, reid) in renId.items():
         comments = COMMENTS_E if kind == EXPERT else COMMENTS_F
         assertModifyField(
             cl,
             REVIEW_ENTRY,
             reid,
             COMMENTS,
             ([comments], comments),
             exp[f"{REVIEW_ENTRY}_{kind}"],
         )
    def bodyCompact(self, **kwargs):
        critId = self.critId
        critRecord = self.critRecord
        perm = self.perm

        critData = critRecord.record
        actual = G(critData, N.actual, default=False)
        msg = E if actual else G(MESSAGES, N.legacyCriterion)

        critKey = f"""{N.criteria}/{critId}/help"""
        (infoShow, infoHide, infoBody) = H.detailx(
            (N.info, N.dismiss),
            critRecord.wrapHelp(),
            critKey,
            openAtts=dict(cls="button small",
                          title="Explanation and scoring guide"),
            closeAtts=dict(cls="button small",
                           title="Hide criteria explanation"),
        )

        score = H.div(self.field(N.score).wrap(asEdit=G(perm, N.isEdit)))
        evidence = H.div(self.field(N.evidence).wrap(asEdit=G(perm, N.isEdit)))
        entry = H.div([
            H.div(H.he(msg), cls="heavy") if msg else E,
            infoShow,
            infoHide,
            infoBody,
            score,
            evidence,
        ], )

        return entry
Ejemplo n.º 11
0
def test_addAssessment2(clientOwner):
    recordId = startInfo["recordId"]
    recordInfo = startInfo["recordInfo"]
    ids = startInfo["ids"]

    eid = G(recordId, CONTRIB)
    aId = G(recordId, ASSESS)

    assessInfo = getItem(clientOwner, ASSESS, aId)
    recordInfo[ASSESS] = assessInfo
    fields = assessInfo["fields"]

    aTitle = G(fields, TITLE)
    assertModifyField(clientOwner, CONTRIB, eid, TYPE, (ids["TYPE2"], TYPE2),
                      True)
    assessInfo = getItem(clientOwner, ASSESS, aId)
    text = assessInfo["text"]
    assert checkWarning(text, aTitle)

    assertStartTask(clientOwner, START_ASSESSMENT, eid, True)
    aIds = getEid(clientOwner, ASSESS, multiple=True)
    assert len(aIds) == 2

    newAId = [i for i in aIds if i != aId][0]
    assertDelItem(clientOwner, ASSESS, newAId, True)

    assertModifyField(clientOwner, CONTRIB, eid, TYPE, (ids["TYPE1"], TYPE1),
                      True)
    assessInfo = getItem(clientOwner, ASSESS, aId)
    text = assessInfo["text"]
    assert not checkWarning(text, aTitle)
Ejemplo n.º 12
0
def test_reviewEntries(clients):
    recordId = startInfo["recordId"]

    cIds = recordId[CRITERIA_ENTRY]
    reviewId = G(recordId, REVIEW)
    rEid = G(reviewId, EXPERT)
    rFid = G(reviewId, FINAL)
    assert rEid is not None
    assert rFid is not None

    def assertIt(cl, exp):
        user = cl.user
        for crId in cIds:
            criteriaEntryInfo = getItem(cl, CRITERIA_ENTRY, crId)
            text = criteriaEntryInfo["text"]
            reviewEntries = findReviewEntries(text)
            if exp:
                if user in {EXPERT, FINAL}:
                    assert user in reviewEntries
                    assert COMMENTS in reviewEntries[user][1]
                    assert reviewEntries[user][1][COMMENTS] == E
                else:
                    assert EXPERT in reviewEntries
                    assert FINAL in reviewEntries

    expect = {user: False for user in USERS}
    expect.update({user: True for user in POWER_USERS | {EXPERT, FINAL}})
    forall(clients, expect, assertIt)
Ejemplo n.º 13
0
    def countryRep(self, user=None):
        """Provide a short representation of the country of a user.

        Parameters
        ----------
        user: dict, optional `None`
            The user whose country must be represented.
            If absent, the currently logged in user will be taken.

        Returns
        -------
        string
            The representation consists of the 2-letter country code plus
            a derived two letter unicode character combination that will
            be turned into a flag of that country.
        """

        db = self.db
        country = db.country

        if user is None:
            user = self.user

        countryId = G(user, N.country)
        countryInfo = G(country, countryId)
        iso = G(countryInfo, N.iso, default=E)
        flag = shiftRegional(iso) if iso else Qc
        countryShort = iso + flag
        return countryShort
Ejemplo n.º 14
0
    def makeCrit(self, mainTable, conditions):
        """Translate conditons into a MongoDb criterion.

        The conditions come from the options on the interface:
        whether to constrain to items that have assessments and or reviews.

        The result can be fed into an other Mongo query.
        It can also be used to filter a list of record that has already been fetched.

        !!! hint
            `{'assessment': '1'}` means: only those things that have an assessment.

            `'-1'`: means: not having an assessment.

            `'0'`: means: don't care.

        !!! hint
            See also `Db.getList`.

        Parameters
        ----------
        mainTable: string
            The name of the table that is being filtered.
        conditions: dict
            keyed by a table name (such as assessment or review)
            and valued by -1, 0 or 1 (as strings).

        Result
        ------
        dict
            keyed by the same table name as `conditions` and valued by a set of
            mongo ids of items that satisfy the criterion.
            Only for the criteria that do care!
        """
        activeOptions = {
            G(G(OPTIONS, cond), N.table): crit == ONE
            for (cond, crit) in conditions.items()
            if crit in {ONE, MINONE}
        }
        if None in activeOptions:
            del activeOptions[None]

        criterion = {}
        for (table, crit) in activeOptions.items():
            eids = {
                G(record, mainTable)
                for record in self.mongoCmd(
                    N.makeCrit,
                    table,
                    N.find,
                    {mainTable: {M_EX: True}},
                    {mainTable: True},
                )
            }
            if crit in criterion:
                criterion[crit] |= eids
            else:
                criterion[crit] = eids
        return criterion
Ejemplo n.º 15
0
def test_assignReviewers(clients, field, user):
    valueTables = startInfo["valueTables"]
    recordId = startInfo["recordId"]

    aId = G(recordId, ASSESS)
    users = G(valueTables, USER)
    expect = {user: False for user in USERS}
    assignReviewers(clients, users, aId, field, user, True, expect)
Ejemplo n.º 16
0
 def titleStr(self, record):
     """The title string is a suitable icon plus the participle field."""
     decision = G(record, N.participle)
     if decision is None:
         return Qq
     sign = G(record, N.sign)
     decision = f"""{sign}{NBSP}{decision}"""
     return decision
Ejemplo n.º 17
0
    def startAssign():
        aId = recordId[ASSESS]
        users = G(valueTables, USER)
        for (field, user) in ((REVIEWER_E, EXPERT), (REVIEWER_F, FINAL)):
            value = G(users, user)
            assertModifyField(clientOffice, ASSESS, aId, field, (value, user), True)

        if review:
            startReviews()
Ejemplo n.º 18
0
    def titleStr(self, record):
        """Put the score and the level in the title."""

        score = G(record, N.score)
        if score is None:
            return Qq
        score = H.he(score)
        level = H.he(G(record, N.level)) or Qq
        return f"""{score} - {level}"""
Ejemplo n.º 19
0
 def assertIt(cl, exp):
     user = cl.user
     for kind in [EXPERT, FINAL]:
         rId = G(reviewId, kind)
         expStatus = kind == user if exp else exp
         for decision in [REJECT, REVISE, ACCEPT, REVOKE]:
             decisionStr = G(G(REVIEW_DECISION, decision), kind)
             url = f"/api/task/{decisionStr}/{rId}"
             assertStatus(cl, url, expStatus)
Ejemplo n.º 20
0
    def __init__(self, regime, test=False):
        """## Initialization

        Pick up the connection to MongoDb.

        !!! note

        Parameters
        ----------
        regime: {"production", "development"}
            See below
        test: boolean
            See below.
        """

        self.regime = regime
        """*string* Whether the app runs in production or in development."""

        self.test = test
        """*boolean* Whether to connect to the test database."""

        database = G(DATABASE, N.test) if test else G(DATABASE, regime)
        self.database = database

        mode = f"""regime = {regime} {"test" if test else E}"""
        if not self.database:
            serverprint(f"""MONGO: no database configured for {mode}""")
            sys.exit(1)

        self.client = None
        """*object* The MongoDb client."""

        self.mongo = None
        """*object* The connection to the MongoDb database.

        The connnection exists before the Db singleton is initialized.
        """

        self.collected = {}
        """*dict* For each value table, the time that this worker last collected it.

        In the database there is a table which holds the last time for each value
        table that a worker updated a value in it.
        """
        self.collect()

        creator = [
            G(record, N._id)
            for record in self.user.values()
            if G(record, N.eppn) == CREATOR
        ]
        if not creator:
            serverprint(f"""DATABASE: no creator user found in {database}.user""")
            sys.exit(1)

        self.creatorId = creator[0]
        """*ObjectId* System user.
Ejemplo n.º 21
0
    def titleStr(self, record):
        """The title is a sequence number plus the short criterion text."""

        context = self.context
        types = context.types

        seq = H.he(G(record, N.seq)) or Qn
        eid = G(record, N.criteria)
        title = Qq if eid is None else types.criteria.title(eid=eid)
        return f"""{seq}. {title}"""
Ejemplo n.º 22
0
    def titleStr(self, record):
        """Put the main type and the sub type in the title."""

        if not record:
            return Qq

        mainType = G(record, N.mainType) or E
        subType = G(record, N.subType) or E
        sep = WHYPHEN if mainType and subType else E
        return H.he(f"""{mainType}{sep}{subType}""")
Ejemplo n.º 23
0
    def __init__(self, db, regime):
        """## Initialization

        Include a handle to `control.db.Db` into the
        attributes.

        Parameters
        ----------
        db: object
            See below.
        """

        self.db = db
        """*object* The `control.db.Db` singleton

        Provides methods to retrieve user
        info from the database and store user info there.
        """

        permissionGroupInv = db.permissionGroupInv

        # determine production or devel
        self.isDevel = regime == N.development
        """*boolean* Whether the server runs in production or in development.

        In production we use the DARIAH Identity provider,
        while in development we use a simple, console-based way of
        logging a few test users in.
        """

        self.authority = N.local if self.isDevel else N.DARIAH
        """*string* The name of the authority that identifies users.

        In production it is "DARIAH", which stands for the DARIAH Identity Provider.
        In development it is "local".
        """

        self.authId = G(permissionGroupInv, AUTH)
        """*string* The groupId of the `auth` permission group.
        """

        self.authUser = {N.group: self.authId}
        """*string* Info of the `auth` permission group.
        """

        self.unauthId = G(permissionGroupInv, UNAUTH)
        """*string* The groupId of the `public` permission group.
        """

        self.unauthUser = {N.group: self.unauthId}
        """*string* Info of the `public` permission group.
        """

        self.user = {}
        """*dict* The attributes of the currently logged in user."""
Ejemplo n.º 24
0
    def tasks(self, table, kind=None):
        """Present the currently available tasks as buttons on the interface.

        !!! hint "easy comments"
            We also include a comment `<!-- task~!taskName:eid -->
            for the ease of testing.

        Parameters
        ----------
        table: string
            We must specify the table for which we want to present the
            tasks: contrib, assessment, or review.
        kind: string {`expert`, `final`}, optional `None`
            Only if we want review attributes

        Returns
        -------
        string(html)
        """

        uid = self.uid

        if not uid or table not in USER_TABLES:
            return E

        eid = list(self.info(table, N._id, kind=kind))[0]
        taskParts = []

        allowedTasks = sorted((task, taskInfo)
                              for (task, taskInfo) in TASKS.items()
                              if G(taskInfo, N.table) == table)
        justNow = now()

        for (task, taskInfo) in allowedTasks:
            permitted = self.permission(task, kind=kind)
            if not permitted:
                continue

            remaining = type(permitted) is timedelta and permitted
            taskUntil = E
            if remaining:
                remainingRep = datetime.toDisplay(justNow + remaining)
                taskUntil = H.span(f""" before {remainingRep}""", cls="datex")
            taskMsg = G(taskInfo, N.msg)
            taskCls = G(taskInfo, N.cls)

            taskPart = (H.a(
                [taskMsg, taskUntil],
                f"""/api/task/{task}/{eid}""",
                cls=f"large task {taskCls}",
            ) + f"""<!-- task!{task}:{eid} -->""")
            taskParts.append(taskPart)

        return H.join(taskParts)
Ejemplo n.º 25
0
    def title(self, *args, **kwargs):
        uid = self.uid
        record = self.record

        creatorId = G(record, N.creator)

        youRep = f""" ({N.you})""" if creatorId == uid else E
        lastModified = G(record, N.modified)
        lastModifiedRep = (self.field(N.modified).value[-1].rsplit(
            DOT, maxsplit=1)[0] if lastModified else Qu)

        return H.span(f"""{lastModifiedRep}{youRep}""", cls=f"rentrytitle")
Ejemplo n.º 26
0
    def insert(self, force=False, masterTable=None, masterId=None):
        mayInsert = force or self.mayInsert
        if not mayInsert:
            return None

        if not masterTable or not masterId:
            return None

        context = self.context
        db = context.db
        uid = self.uid
        eppn = self.eppn
        table = self.table

        masterOid = castObjectId(masterId)
        masterRecord = context.getItem(N.assessment, masterOid)
        contribId = G(masterRecord, N.contrib)
        if not contribId:
            return None

        wfitem = context.getWorkflowItem(contribId)

        if not wfitem.permission(N.startReview):
            return contribId

        (contribType, ) = wfitem.info(N.contrib, N.type)
        (assessmentTitle, ) = wfitem.info(N.assessment, N.title)

        fields = {
            N.contrib: contribId,
            masterTable: masterOid,
            N.reviewType: contribType,
            N.title: f"review of {assessmentTitle}",
        }
        reviewId = db.insertItem(table, uid, eppn, False, **fields)

        criteriaEntries = db.getDetails(
            N.criteriaEntry,
            N.assessment,
            masterOid,
            sortKey=lambda r: G(r, N.seq, default=0),
        )
        records = [{
            N.seq: G(critEntry, N.seq, default=0),
            N.criteria: G(critEntry, N.criteria),
            N.criteriaEntry: G(critEntry, N._id),
            N.assessment: masterOid,
            N.review: reviewId,
        } for critEntry in criteriaEntries]
        db.insertMany(N.reviewEntry, uid, eppn, records)
        self.adjustWorkflow(contribId, new=False)

        return contribId
Ejemplo n.º 27
0
def checkPerm(
    require, perm,
):
    """Verify whether user's credentials match the requirements.

    Parameters
    ----------
    require: string
        The required permission level (see the perm.yaml configuration file under
        the key `roles`).
    perm: dict
        User attributes, in paticular `group` which is the role a user can play on the
        basis of his/her identity.
        But it also contains attributes that links a user to ceertain records, e.g. the
        records of which (s)he is creator/editor, or National Coordinator.

    Returns
    -------
    boolean
    """

    if require == UNAUTH:
        return True

    group = G(perm, N.group)

    if require == NOBODY:
        return False

    if require == AUTH:
        return group != UNAUTH

    isSuper = group in {OFFICE, SYSTEM, ROOT}

    if require == OFFICE:
        return isSuper

    if require == SYSTEM:
        return group in {SYSTEM, ROOT}

    if require == ROOT:
        return group == ROOT

    if require == EDIT:
        return group != UNAUTH and (G(perm, N.isEdit) or isSuper)

    if require == OWN:
        return group != UNAUTH and (G(perm, N.isOwn) or isSuper)

    if require == COORD:
        return group == COORD and G(perm, N.sameCountry) or isSuper
Ejemplo n.º 28
0
    def insertItem(self, table, uid, eppn, onlyIfNew, **fields):
        """Inserts a new record in a table, possibly only if it is new.

        The record will be filled with the specified fields, but also with
        provenance fields.

        The provenance fields are the creation date, the creator,
        and the start of the trail of modifiers.

        Parameters
        ----------
        table: string
            The table in which the record will be inserted.
        uid: ObjectId
            The user that creates the record, typically the logged in user.
        onlyIfNew: boolean
            If `True`, it will be checked whether a record with the specified fields
            already exists. If so, no record will be inserted.
        eppn: string
            The eppn of that same user. This is the unique identifier that comes from
            the DARIAH authentication service.
        **fields: dict
            The field names and their contents to populate the new record with.

        Returns
        -------
        ObjectId
            The id of the newly inserted record, or the id of the first existing
            record found, if `onlyIfNew` is true.
        """

        if onlyIfNew:
            existing = [
                G(rec, N._id)
                for rec in getattr(self, table, {}).values()
                if all(G(rec, k) == v for (k, v) in fields.items())
            ]
            if existing:
                return existing[0]

        justNow = now()
        newRecord = {
            N.dateCreated: justNow,
            N.creator: uid,
            N.modified: [MOD_FMT.format(eppn, justNow)],
            **fields,
        }
        result = self.mongoCmd(N.insertItem, table, N.insert_one, newRecord)
        if table in VALUE_TABLES:
            self.recollect(table)
        return result.inserted_id
Ejemplo n.º 29
0
    def insert(self, force=False, masterTable=None, masterId=None):
        mayInsert = force or self.mayInsert
        if not mayInsert:
            return None

        if not masterTable or not masterId:
            return None

        context = self.context
        db = context.db
        uid = self.uid
        eppn = self.eppn
        table = self.table
        typeCriteria = db.typeCriteria

        masterOid = castObjectId(masterId)

        wfitem = context.getWorkflowItem(masterOid)

        if not wfitem.permission(N.startAssessment):
            return None

        (contribType, contribTitle) = wfitem.info(N.contrib, N.type, N.title)
        if not contribType:
            flash("You cannot assess a contribution without a type", "error")
            return None
        isActual = G(G(db.typeContribution, contribType), N.actual)
        if not isActual:
            flash("You cannot assess a contribution with a legacy type", "error")
            return None

        fields = {
            masterTable: masterOid,
            N.assessmentType: contribType,
            N.title: f"assessment of {contribTitle}",
        }
        criteria = G(typeCriteria, contribType, default=[])
        if not criteria:
            flash("This contribution type has no criteria", "error")
            return None

        assessmentId = db.insertItem(table, uid, eppn, False, **fields)

        records = [
            {N.seq: seq, N.criteria: crit, N.assessment: assessmentId}
            for (seq, crit) in enumerate(criteria)
        ]
        db.insertMany(N.criteriaEntry, uid, eppn, records)
        self.adjustWorkflow(masterOid, new=False)

        return assessmentId
Ejemplo n.º 30
0
    def authenticate(self, login=False):
        """Verify the authenticated status of the current user.

        This function is called for every request that requires authentication.
        Whether a user is authenticated or not depends on whether a session for
        that user is present. And that depends on whether the identity provider
        has sent attributes (eppn and others) to the server.

        The data in the `user` attribute will be cleared if there is
        an authenticated user. Subsequent methods that ask for the uid of
        the currennt user will get nothing if there is no authenticated user.
        If there is an authenticated user, and `login=False`, his/her data
        are not loaded into the `user` attribute.

        Parameters
        ----------
        login: boolean, optional `False`
            Pass `True` in order to verify/update a user that has just logged in.
            The data in the `user` attribute will be updated with his/her
            data. The user table in the database will be updated if the
            identity provider has given updated attributed for that user.

        Returns
        -------
        boolean
            Whether the current user is authenticated.
        """

        user = self.user

        # if login=True we want to log the user in
        # if login=False we only want the current user information

        if login:
            session.pop(N.eppn, None)
            if self.checkLogin():
                # in this case there is an eppn
                session[N.eppn] = G(user, N.eppn)
                return True
            return False

        eppn = G(session, N.eppn)
        if eppn:
            if not self.getUser(eppn, mayCreate=False):
                self.clearUser()
                return False
            return True

        self.clearUser()
        return False