Ejemplo n.º 1
0
class Widget(XMLPresentable):
    '''GUI element.
    Provides a shared instance to its subclasses: "SomeWidget.instance".
    '''
    instance: ClassVar[SharedInstance] = SharedInstance()

    widgetId: Optional[str] = None
    '''Unique ID string that identifies this widget, or None.
    Corresponds to the "id" attribute in XML.
    '''
    autoUpdate = False
    '''Automatically update the presentation of this widget in pages using
    JavaScript? False by default.
    '''

    @staticmethod
    def joinStyles(styles: Iterable[str]) -> Optional[str]:
        '''Returns a single string containing all the given CSS styles separated
        by spaces, or None if there were no styles given.
        '''
        assert iterable(styles), type(styles)
        return ' '.join(styles) or None

    def present(self, **kwargs: object) -> XMLContent:
        '''Presents this widget in XHTML using data from the given processor.
        Returns an XML tree.
        '''
        raise NotImplementedError
Ejemplo n.º 2
0
class HTTPAuthPage(Authenticator):
    '''Authenticator that performs HTTP authentication.
    '''

    instance: ClassVar[SharedInstance] = SharedInstance()
    userDB: ClassVar[UserDB]

    def authenticate(self, req: Request) -> Deferred:
        # To avoid cross-site request forgery, we must authenticate every API
        # call and not use session cookies. Since API calls are not made using
        # web browsers, most likely the client is not using session cookies
        # anyway.
        #   http://en.wikipedia.org/wiki/Cross-site_request_forgery
        try:
            credentials = req.getCredentials()
        except UnicodeDecodeError as ex:
            return fail(LoginFailed(ex))

        if credentials.name:
            return ensureDeferred(authenticateUser(self.userDB, credentials))
        elif self.project.anonguest:
            return succeed(AnonGuestUser())
        else:
            return fail(LoginFailed())

    def askForAuthentication(self,
                             req: Request,
                             message: Optional[str] = None) -> Responder:
        return HTTPAuthenticator('SoftFab', message)
Ejemplo n.º 3
0
class Base(ABC):

    instance = SharedInstance()

    def __init__(self):
        self.value = BASE_VALUE

    def get_value(self):
        return self.value
Ejemplo n.º 4
0
class NoAuthPage(Authenticator):
    '''Authenticator that performs no authentication and returns
    a non-privileged user.
    '''

    instance: ClassVar[SharedInstance] = SharedInstance()

    def authenticate(self, req: Request) -> Deferred:
        return succeed(UnknownUser())

    def askForAuthentication(self,
                             req: Request,
                             message: Optional[str] = None) -> Responder:
        raise InternalError(
            'Authentication requested for page that does not require it.')
Ejemplo n.º 5
0
class DisabledAuthPage(Authenticator):
    '''Authenticator that forces no authentication and returns
    a user with all privileges when not logged in.
    This is for ease of development, not recommended for production.
    '''

    instance: ClassVar[SharedInstance] = SharedInstance()

    def authenticate(self, req: Request) -> Deferred:
        user = req.loggedInUser()
        if user is None:
            return succeed(SuperUser())
        else:
            # Use logged-in user.
            return succeed(user)

    def askForAuthentication(self,
                             req: Request,
                             message: Optional[str] = None) -> Responder:
        raise InternalError(
            'Authentication requested while authentication is disabled.')
Ejemplo n.º 6
0
class LoginAuthPage(Authenticator):
    '''Authenticator that performs authentication using a login page and
    a session cookie.
    '''

    instance: ClassVar[SharedInstance] = SharedInstance()

    def authenticate(self, req: Request) -> Deferred:
        user = req.loggedInUser()
        if user is not None:
            # User has already authenticated.
            return succeed(user)
        elif self.project.anonguest:
            return succeed(AnonGuestUser())
        else:
            # User must log in.
            return fail(LoginFailed())

    def askForAuthentication(self,
                             req: Request,
                             message: Optional[str] = None) -> Responder:
        return Redirector(loginURL(req))
Ejemplo n.º 7
0
class Column:
    instance: ClassVar[SharedInstance] = SharedInstance()

    label: XMLContent = None
    colSpan = 1
    cellStyle: Optional[str] = None

    @staticmethod
    def adapt(obj: Union['Column', XMLContent]) -> 'Column':
        '''Returns `obj` if it is a column, otherwise returns a new column
        with `obj` as its label.
        '''
        return obj if isinstance(obj, Column) else Column(obj)

    def __init__(self,
            label: XMLContent = None,
            colSpan: int = 1,
            cellStyle: Optional[str] = None
            ):
        super().__init__()
        if label is not None:
            self.label = label
        if colSpan != 1:
            self.colSpan = colSpan
        if cellStyle is not None:
            self.cellStyle = cellStyle

    def presentHeader(self, **kwargs: object) -> XMLNode: # pylint: disable=unused-argument
        """Presents the header tag without content."""
        colSpan = self.colSpan
        return xhtml.th(
            scope='col',
            colspan=None if colSpan == 1 else colSpan,
            class_=self.cellStyle
            )

    def presentHeaderContent(self, **kwargs: object) -> XMLContent: # pylint: disable=unused-argument
        """Presents the content for the header tag."""
        return self.label
Ejemplo n.º 8
0
class ReportFilterForm:
    instance: ClassVar = SharedInstance()
    objectName: ClassVar[str] = abstract

    def present(self, **kwargs: object) -> XMLContent:
        yield makeForm(method='get',
                       formId='filters',
                       onsubmit='return checkFilters()')[xhtml.table(
                           class_='filters')[xhtml.tbody[self.presentRows(
                               **kwargs)]]].present(**kwargs)
        yield self.dateCheckScript.present(**kwargs)

    def presentRows(self, **kwargs: object) -> XMLContent:
        proc = cast(ReportProcessor, kwargs['proc'])
        numListItems = cast(int, kwargs['numListItems'])

        targets = proc.uiTargets
        owners = proc.uiOwners
        showOwners = proc.userDB.showOwners
        objectName = self.objectName

        def columns1() -> XMLContent:
            yield xhtml.td(
                colspan=4)[f'Select {objectName} to display reports for:']
            if len(targets) > 1:
                yield xhtml.td['Targets:']
            if len(owners) > 1 and showOwners:
                yield xhtml.td['Owners:']

        yield xhtml.tr[columns1()]

        def columns2() -> XMLContent:
            yield self.presentCustomBox(**kwargs)
            if len(targets) > 1:
                yield xhtml.td(
                    rowspan=4, style='vertical-align:top')[selectionList(
                        name='target', size=numListItems,
                        style='width: 18ex')[(target or noneOption
                                              for target in sorted(targets))]]
            if len(owners) > 1 and showOwners:
                yield xhtml.td(
                    rowspan=4, style='vertical-align:top')[selectionList(
                        name='owner', size=numListItems,
                        style='width: 18ex')[(owner or noneOption
                                              for owner in sorted(owners))]]

        yield xhtml.tr[columns2()]

        yield xhtml.tr[xhtml.td['Created after:'],
                       xhtml.td[textInput(name='ctabove',
                                          value=timeValue(proc.args.ctabove),
                                          style='width:20ex')],
                       xhtml.td['Created before:'],
                       xhtml.td[textInput(name='ctbelow',
                                          value=timeValue(proc.args.ctbelow),
                                          style='width:20ex')]]

        yield xhtml.tr[xhtml.td['Execution state:'],
                       xhtml.td(colspan=3)[executionStateBox(objectName)]]

        yield xhtml.tr[xhtml.td(
            colspan=4, style='text-align:center')[submitButton['Apply'], ' ',
                                                  resetButton, ' ',
                                                  clearButton]]

    def presentCustomBox(self, **kwargs: object) -> XMLContent:
        raise NotImplementedError

    dateCheckScript = script[r'''
var numOfDays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
function checkMatch(match) {
    if (match == null)
        return false;
    var day = parseInt(match[4], 10);
    if (day > 28) {
        var month = parseInt(match[3], 10);
        if (day > numOfDays[month]) {
            if ((month != 2) || (day > 29))
                return false;
            if ((parseInt(match[1], 10) % 4) > 0)
                return false;
        }
    }
    return true;
}
function checkFilters() {
    if (RegExp) {
        var ctabove = document.forms.filters.elements.ctabove.value;
        var ctbelow = document.forms.filters.elements.ctbelow.value;
        if ((ctabove.length > 0) || (ctbelow.length > 0)) {
            var re = new RegExp('^\\s*((?:20)?\\d\\d)([-./])(0?[1-9]|1[0-2])\\2(0?[1-9]|[12]\\d|3[01])(?:\\s+(?:[01]?\\d|2[0-3])[:.][0-5]\\d)?\\s*$');
            if (ctabove.length > 0) {
                if (!checkMatch(re.exec(ctabove))) {
                    alert('Invalid date/time: ' + ctabove);
                    return false;
                }
            }
            if (ctbelow.length > 0) {
                if (!checkMatch(re.exec(ctbelow))) {
                    alert('Invalid date/time: ' + ctbelow);
                    return false;
                }
            }
        }
    }
    return true;
}
''']