Example #1
0
        async def process(self, req: Request['UserList_POST.Arguments'],
                          user: User) -> None:
            # Find user record.
            userName = req.args.user
            try:
                subject = self.userDB[userName]
            except KeyError:
                raise PresentableError(
                    xhtml.p(class_='notice')
                    [f'There is no user named "{userName}"'])

            # Parse and check all changes.
            requestUserName = user.name
            newRoles = uiRoleToSet(req.args.role)
            if (userName == requestUserName
                    and not rolesGrantPrivilege(newRoles, 'u/m')):
                # Prevent user from revoking their own 'u/m' privilege.
                raise PresentableError(xhtml[xhtml.p(
                    class_='notice'
                )['Revoking your own privileges could lead to '
                  'a situation from which recovery is impossible.'], xhtml.p[
                      f'If you want to change the role of user "{userName}", '
                      f'please log in as another user with operator '
                      f'privileges.'], ])

            # Changes are OK, commit them.
            subject.roles = newRoles

            raise Redirect(
                pageURL('UserList', UserList_GET.Arguments.subset(req.args)))
Example #2
0
 def presentFeed(self, proc: Processor, ccURL: str) -> XMLContent:
     projectName = proc.project.name
     yield atom.title[f'{projectName} SoftFab - Recent Jobs']
     yield atom.subtitle[
         f'The most recent jobs running in the {projectName} SoftFab']
     yield atom.id[f'{rootURL}jobs']
     yield atom.updated[self.presentTime(getTime())]
     yield atom.generator(uri=HOMEPAGE, version=VERSION)['SoftFab']
     # TODO: Akregator for KDE4 won't show the icon, no matter what I try.
     #       Might be related to Konqueror often losing the icon.
     yield atom.icon[ccURL + 'styles/SoftFabIcon.png']
     #yield atom.link(
     #rel = 'shortcut icon',
     #href = ccURL + 'styles/SoftFabIcon.png',
     #type = 'image/png',
     #)
     # Link to the Control Center.
     yield atom.link(
         rel='alternate',
         href=ccURL + 'Home',
         type='text/html',
     )
     # Link to the feed itself.
     yield atom.link(
         rel='self',
         href=ccURL + pageURL(self.name, proc.args),
         type='application/atom+xml',
     )
     for job, jobTable in zip(proc.jobs, proc.tables):
         yield atom.entry[self.presentJob(proc, ccURL, job, jobTable)]
Example #3
0
def createJobsURL(jobIDs: Sequence[str]) -> str:
    '''Returns a URL of a page that contains details about the given jobs.
    '''
    if len(jobIDs) == 1:
        return createJobURL(jobIDs[0])
    else:
        # Note: This also works fine for zero jobs.
        return pageURL('ShowJobs', JobIdSetArgs(jobId=jobIDs))
Example #4
0
def createRunURL(run: TaskRun, report: Optional[str] = 'overview') -> str:
    """Return a URL of a page showing details of a task run."""
    jobId = run.getJob().getId()
    taskName = run.getName()
    return pageURL(
        'Task',
        TaskReportArgs(jobId=jobId, taskName=taskName, report=report)
        )
Example #5
0
 def makeURL(taskName: str, beginTime: int, endTime: int) -> str:
     if taskName is None:
         # TODO: The links which match all tasks are currently disabled,
         #       but are also no longer accepted by ReportTasks.
         taskName = '*'
     return pageURL(
         'ReportTasks',
         ReportTaskArgs(task=[taskName],
                        ctabove=beginTime,
                        ctbelow=endTime))
Example #6
0
    def processSelection(self) -> None:
        db = self.db
        args = self.args
        tagCache = self.tagCache
        action = args.action
        selected = {recordId for recordId in args.sel if recordId in db}

        if action == 'remove':
            selected -= args.bsk
        else:
            for value, label_, page in self.iterActions():
                if action == value:
                    raise Redirect(pageURL(page, SelectArgs(sel=selected)))

        # Determine tag key to filter by.
        # Empty string as key shows all records (all-pass filter).
        tagKey = args.tagkey
        tagKeys = tagCache.getKeys()
        if tagKey and tagKey not in tagKeys:
            # Drop non-existing key.
            tagKey = None
        if tagKey is None and tagKeys:
            # Pick default key.
            tagKey = tagKeys[0]

        # Determine tag value to filter by.
        # Empty string as value shows records that are not tagged
        # with the given tag key.
        if tagKey:
            tagValue = args.tagvalue
            if tagValue:
                if not tagCache.hasValue(tagKey, tagValue):
                    # Unknown tag; drop non-existing value.
                    tagValue = None
            if tagValue is None:
                # Pick default value.
                # If nothing is tagged with this key, show untagged.
                tagValue = min(tagCache.getValues(tagKey), default='')
        else:
            # A value only has meaning if we have a key.
            tagValue = None

        if (selected != args.sel or tagKey != args.tagkey
                or tagValue != args.tagvalue):
            raise ArgsCorrected(args,
                                sel=selected,
                                tagkey=tagKey,
                                tagvalue=tagValue)

        filteredRecords = self.__filterRecords(tagKey, tagValue)

        self.selected = selected
        self.selectedRecords = [db[recordId] for recordId in selected]
        self.filtered = {record.getId() for record in filteredRecords}
        self.filteredRecords = filteredRecords
Example #7
0
    def getPageURL(cls, page: str, args: Optional[ArgsT]) -> Optional[str]:
        '''Gets the URL of another page, relative to this page.
        This URL includes in its query part the arguments shared between
        this page and the other page.
        If the other page requires arguments not present in this page,
        None is returned.
        '''
        otherArgClass = cls.getPageInfo(page)['pageClass'].Arguments
        if args is None:
            # No arguments available.
            try:
                emptyArgs = otherArgClass()
            except KeyError:
                # Other page has mandatory arguments.
                return None
            else:
                return pageURL(page, emptyArgs)

        # Only gather shared arguments that are mandatory in at least one
        # of the pages. In practice this preserves the arguments we want
        # to share across pages, such as selected names, while dropping
        # arguments such as sort order.
        ourArgClass = args.__class__
        sharedArgs = {}
        for name in otherArgClass.iterMandatoryArgs():
            if hasattr(args, name) and args.isArgument(name):
                if getattr(ourArgClass, name) == getattr(otherArgClass, name):
                    sharedArgs[name] = getattr(args, name)
                else:
                    # We share a name with a mandatory argument, but it's not
                    # the same argument.
                    return None
            else:
                # Mandatory argument missing.
                return None
        for name in args.iterMandatoryArgs():
            if hasattr(otherArgClass, name) and otherArgClass.isArgument(name):
                if getattr(ourArgClass, name) == getattr(otherArgClass, name):
                    sharedArgs[name] = getattr(args, name)

        return pageURL(page, otherArgClass(sharedArgs))
Example #8
0
        async def process(self, req: Request['ChangePassword_POST.Arguments'],
                          user: User) -> None:
            # pylint: disable=attribute-defined-outside-init

            if req.args.action is Actions.CANCEL:
                page = cast(ChangePassword_POST, self.page)
                raise Redirect(page.getCancelURL(req.args))
            elif req.args.action is Actions.CHANGE:
                userDB = self.userDB

                userName = user.name  # get current logged-in user
                if userName is None:
                    self.retry = False
                    raise PresentableError(
                        xhtml["Anonymous user has no password."])

                # Perform sanity checks on new password.
                password = req.args.password
                newCredentials = Credentials(userName, password)
                if password == req.args.password2:
                    quality = passwordQuality(newCredentials)
                else:
                    quality = PasswordMessage.MISMATCH
                if quality is not PasswordMessage.SUCCESS:
                    self.retry = True
                    raise PresentableError(xhtml[passwordStr[quality]])

                oldCredentials = Credentials(userName, req.args.loginpass)
                try:
                    user_ = await authenticateUser(userDB, oldCredentials)
                except LoginFailed as ex:
                    self.retry = True
                    raise PresentableError(
                        xhtml["Verification of old password failed",
                              f": {ex.args[0]}" if ex.args else None, "."])

                # Apply changes.
                try:
                    setPassword(userDB, newCredentials)
                except ValueError as ex:
                    self.retry = True
                    raise PresentableError(xhtml[ex.args[0]])
                else:
                    # Successfully changed password
                    raise Redirect(
                        pageURL(
                            'ChangePassword',
                            ChangePassword_GET.Arguments(
                                user=userName, msg=PasswordMessage.SUCCESS)))
            else:
                assert False, req.args.action
Example #9
0
        async def process(self, req: Request['ResourceIndex_POST.Arguments'],
                          user: User) -> None:
            args = req.args

            # Get resource record.
            resource = self.getResource(args.resource)

            # Update suspend state.
            resource.setSuspend(args.action is Actions.SUSPEND, user.name
                                or 'anonymous')

            # Show new status, forget commands.
            raise Redirect(
                pageURL('ResourceIndex',
                        ResourceIndex_GET.Arguments.subset(args)))
Example #10
0
 async def process(self, req: Request['ScheduleIndex_POST.Arguments'],
                   user: User) -> None:
     actions = cast(Mapping[str, str], req.args.action)
     for scheduleId, action in actions.items():
         # Toggle suspend.
         scheduled = self.scheduleDB.get(scheduleId)
         # TODO: Report when action is not possible, instead of ignoring.
         if scheduled is not None:
             checkPrivilegeForOwned(user, 's/m', scheduled,
                                    ('suspend/resume this schedule',
                                     'suspend/resume schedules'))
             if not scheduled.isDone():
                 scheduled.setSuspend(action is Actions.SUSPEND)
     raise Redirect(
         pageURL('ScheduleIndex',
                 ScheduleIndex_GET.Arguments.subset(req.args)))
Example #11
0
 def subItemRelURL(self, subPath: str) -> str:
     '''Gets a relative URL to the given item subpath.
     '''
     return pageURL(f'{self.page.name}/{subPath}', self.args)
Example #12
0
def createProductDetailsURL(productDefId: str) -> str:
    return pageURL(
        'ProductDetails',
        ProductDefIdArgs(id = productDefId)
        )
Example #13
0
def createFrameworkDetailsURL(frameworkId: str) -> str:
    return pageURL(
        'FrameworkDetails',
        FrameworkIdArgs(id = frameworkId)
        )
Example #14
0
def logoutURL(req: Request) -> str:
    """Returns a URL of the Logout page, so that it returns to the request's
    URL after the user has logged out.
    """
    return pageURL('Logout', URLArgs(url=req.getURL()))
Example #15
0
def createUserDetailsURL(userId: str) -> str:
    return pageURL('UserDetails', UserIdArgs(user = userId))
Example #16
0
def createScheduleDetailsURL(scheduleId: str) -> str:
    return pageURL('ScheduleDetails', ScheduleIdArgs(id=scheduleId))
Example #17
0
def setPasswordURL(token: Credentials) -> str:
    return rootURL + pageURL('SetPassword',
        PasswordSetArgs(token=token.name, secret=token.password))
Example #18
0
 def linkTab(tab: int, text: str) -> XMLNode:
     return xhtml.td(class_='navother')[xhtml.a(href=pageURL(
         proc.page.name,
         proc.args.override(**{tabOffsetField: tab * recordsPerPage})),
                                                class_='nav')[text]]
Example #19
0
 def loginURL(self, **kwargs: Any) -> str:
     userName = cast(Optional[str], kwargs['proc'].userName)
     return pageURL('Login', LoginNameArgs(loginname=userName))
Example #20
0
def createJobURL(jobId: str) -> str:
    '''Returns a URL of a page that contains details about the given job.
    '''
    return pageURL('ShowReport', JobIdArgs(jobId = jobId))