Ejemplo n.º 1
0
 def get_session(self, url, stypes):
     sessions = self.db.openid_session.filter(None, {'url': url})
     for session_id in sessions:
         # Match may not have been exact
         if self.db.openid_session.get(session_id, 'url') != url:
             continue
         expires = self.db.openid_session.get(session_id, 'expires')
         if expires > date.Date('.') + date.Interval("1:00"):
             # valid for another hour
             return self.db.openid_session.getnode(session_id)
     now = date.Date('.')
     session_data = openid2rp.associate(stypes, url)
     # check whether a session has expired a day ago
     sessions = self.db.openid_session.filter(None, {'expires': 'to -1d'})
     if sessions:
         session = self.db.openid_session.getnode(sessions[0])
         session.assoc_handle = session_data['assoc_handle']
     else:
         session_id = self.db.openid_session.create(
             assoc_handle=session_data['assoc_handle'])
         session = self.db.openid_session.getnode(session_id)
     session.url = url
     session.mac_key = session_data['mac_key']
     session.expires = now + date.Interval(int(session_data['expires_in']))
     self.db.commit()
     return session
Ejemplo n.º 2
0
    def confirm_registration(self, otk):
        props = self.getOTKManager().getall(otk)
        for propname, proptype in self.user.getprops().items():
            value = props.get(propname, None)
            if value is None:
                pass
            elif isinstance(proptype, hyperdb.Date):
                props[propname] = date.Date(value)
            elif isinstance(proptype, hyperdb.Interval):
                props[propname] = date.Interval(value)
            elif isinstance(proptype, hyperdb.Password):
                props[propname] = password.Password(encrypted=value)

        # tag new user creation with 'admin'
        self.journaltag = 'admin'

        # create the new user
        cl = self.user

        props['roles'] = self.config.NEW_WEB_USER_ROLES
        userid = cl.create(**props)
        # clear the props from the otk database
        self.getOTKManager().destroy(otk)
        self.commit()

        return userid
Ejemplo n.º 3
0
def totalTimeSpent(times):
    ''' Call me with a list of timelog items (which have an
        Interval "period" property)
    '''
    total = date.Interval('0d')
    for time in times:
        total += time.period._value
    return total
Ejemplo n.º 4
0
    def __init__ (self, opt) :
        self.opt = opt
        tracker  = instance.open (opt.dir)
        self.db  = tracker.open ('admin')

        now = date.Date ('.')
        exp = now + date.Interval ('%s days' % opt.days)
        wps = self.db.time_wp.filter \
            ( None
            , dict (time_end = '.;%s' % exp.pretty ('%Y-%m-%d'))
            , sort=[('+', 'responsible')]
            )
        self.wps = [self.db.time_wp.getnode (i) for i in wps]
        self.messages = {}
        self.build_mails ()
Ejemplo n.º 5
0
 def pending_approval (db, userid, itemid) :
     """ Users are allowed to edit message if a pending
         approval from them is linked to the PR.
     """
     if not linked_pr (db, userid, itemid) :
         return False
     if open_or_approving (db, userid, itemid) :
         return True
     # Also allow for reject because message is tried to attach twice
     # We allow this only for some time (5 min after last change)
     st_reject = db.pr_status.lookup ('rejected')
     pr        = db.purchase_request.getnode (itemid)
     if pr.status != st_reject :
         return False
     now = date.Date ('.')
     if pr.activity + date.Interval ('00:05:00') > now :
         return True
     return False
Ejemplo n.º 6
0
    def confirm_registration(self, otk):
        props = self.getOTKManager().getall(otk)
        for propname, proptype in self.user.getprops().items():
            value = props.get(propname, None)
            if value is None:
                pass
            elif isinstance(proptype, hyperdb.Date):
                props[propname] = date.Date(value)
            elif isinstance(proptype, hyperdb.Interval):
                props[propname] = date.Interval(value)
            elif isinstance(proptype, hyperdb.Password):
                props[propname] = password.Password(encrypted=value)

        # tag new user creation with 'admin'
        self.journaltag = 'admin'

        # create the new user
        cl = self.user

        props['roles'] = self.config.NEW_WEB_USER_ROLES
        try:
            # ASSUME:: ValueError raised during create due to key value
            # conflict. I an use message in exception to determine
            # when I should intercept the exception with a more
            # friendly error message. If i18n is used to translate
            # original exception message this will fail and translated
            # text (probably unfriendly) will be used.
            userid = cl.create(**props)
        except ValueError as e:
            username = props['username']
            # Try to make error message less cryptic to the user.
            if str(e) == 'node with key "%s" exists' % username:
                raise ValueError(_("Username '%s' already exists." % username))
            else:
                raise

            # clear the props from the otk database
        self.getOTKManager().destroy(otk)
        # commit cl.create (and otk changes)
        self.commit()

        return userid
Ejemplo n.º 7
0
def add_milestones(db, cl, nodeid, new_values):
    """auditor on release.create

    XXX: not sure if this should be in an auditor ???

    - creates the milestones and attaches them to the newly created release.
    - set release's `status` to M000
    """
    milestones = \
        [ ("M000", "+     0d", "Release Planning has started")
        , ("M100", "+ 2m 15d", "Release Planning completed, Feature Freeze")
        , ("M200", "+ 3m 20d", "Design completed")
        , ("M210", "+ 3m 30d", "Check for Customer Appslications to be "
                               "used as Testcases")
        , ("M300", "+ 6m 20d", "Implementation completed")
        , ("M310", "+ 7m    ", "TC Spec & TC Implementation completed")
        , ("M400", "+ 8m 15d", "Integration Test completed; Beta Release")
        , ("M410", "+ 8m 20d", "Documentation Completed")
        , ("M490", "+ 9m    ", "Bugfixing completed")
        , ("M500", "+ 9m 10d", "Test by Services completed; Production "
                               "Release")
        , ("M600", "+10m"    , "Shipment completed")
        ]
    order = 1
    ms_ids = []
    today = date.Date(".").pretty(format="%Y-%m-%d")
    today = date.Date(today)  # to start today at 00:00 and not somewhere in
    # the day
    for name, interval, desc in milestones:
        planned = today + date.Interval(interval)
        ms = db.milestone.create(name=name,
                                 description=desc,
                                 order=order,
                                 planned=planned,
                                 release=nodeid)
        ms_ids.append(ms)
        order += 1
    new_values["milestones"] = ms_ids
    # set status to M0
    new_values["status"] = ms_ids[0]
Ejemplo n.º 8
0
    def handle(self):
        """Performs an edit of all of a class' items in one go.

        The "rows" CGI var defines the CSV-formatted entries for the class. New
        nodes are identified by the ID 'X' (or any other non-existent ID) and
        removed lines are retired.

        """
        cl = self.db.classes[self.classname]
        idlessprops = cl.getprops(protected=0).keys()
        idlessprops.sort()
        props = ['id'] + idlessprops

        # do the edit
        rows = StringIO.StringIO(self.form['rows'].value)
        reader = csv.reader(rows)
        found = {}
        line = 0
        for values in reader:
            line += 1
            if line == 1: continue
            # skip property names header
            if values == props:
                continue

            # extract the nodeid
            nodeid, values = values[0], values[1:]
            found[nodeid] = 1

            # see if the node exists
            if nodeid in ('x', 'X') or not cl.hasnode(nodeid):
                exists = 0
            else:
                exists = 1

            # confirm correct weight
            if len(idlessprops) != len(values):
                self.client.error_message.append(
                    self._('Not enough values on line %(line)s') %
                    {'line': line})
                return

            # extract the new values
            d = {}
            for name, value in zip(idlessprops, values):
                prop = cl.properties[name]
                value = value.strip()
                # only add the property if it has a value
                if value:
                    # if it's a multilink, split it
                    if isinstance(prop, hyperdb.Multilink):
                        value = value.split(':')
                    elif isinstance(prop, hyperdb.Password):
                        value = password.Password(value)
                    elif isinstance(prop, hyperdb.Interval):
                        value = date.Interval(value)
                    elif isinstance(prop, hyperdb.Date):
                        value = date.Date(value)
                    elif isinstance(prop, hyperdb.Boolean):
                        value = value.lower() in ('yes', 'true', 'on', '1')
                    elif isinstance(prop, hyperdb.Number):
                        value = float(value)
                    d[name] = value
                elif exists:
                    # nuke the existing value
                    if isinstance(prop, hyperdb.Multilink):
                        d[name] = []
                    else:
                        d[name] = None

            # perform the edit
            if exists:
                # edit existing
                cl.set(nodeid, **d)
            else:
                # new node
                found[cl.create(**d)] = 1

        # retire the removed entries
        for nodeid in cl.list():
            if not found.has_key(nodeid):
                cl.retire(nodeid)

        # all OK
        self.db.commit()

        self.client.ok_message.append(self._('Items edited OK'))
Ejemplo n.º 9
0
    def add_new_columns_v2(self):
        '''While we're adding the actor column, we need to update the
        tables to have the correct datatypes.'''
        for klass in self.classes.values():
            cn = klass.classname
            properties = klass.getprops()
            old_spec = self.database_schema['tables'][cn]

            # figure the non-Multilink properties to copy over
            propnames = ['activity', 'creation', 'creator']

            # figure actions based on data type
            for name, s_prop in old_spec[1]:
                # s_prop is a repr() string of a hyperdb type object
                if s_prop.find('Multilink') == -1:
                    if name in properties:
                        propnames.append(name)
                    continue
                tn = '%s_%s'%(cn, name)

                if name in properties:
                    # grabe the current values
                    sql = 'select linkid, nodeid from %s'%tn
                    self.sql(sql)
                    rows = self.cursor.fetchall()

                # drop the old table
                self.drop_multilink_table_indexes(cn, name)
                sql = 'drop table %s'%tn
                self.sql(sql)

                if name in properties:
                    # re-create and populate the new table
                    self.create_multilink_table(klass, name)
                    sql = '''insert into %s (linkid, nodeid) values
                        (%s, %s)'''%(tn, self.arg, self.arg)
                    for linkid, nodeid in rows:
                        self.sql(sql, (int(linkid), int(nodeid)))

            # figure the column names to fetch
            fetch = ['_%s'%name for name in propnames]

            # select the data out of the old table
            fetch.append('id')
            fetch.append('__retired__')
            fetchcols = ','.join(fetch)
            sql = 'select %s from _%s'%(fetchcols, cn)
            self.sql(sql)

            # unserialise the old data
            olddata = []
            propnames = propnames + ['id', '__retired__']
            cols = []
            first = 1
            for entry in self.cursor.fetchall():
                l = []
                olddata.append(l)
                for i in range(len(propnames)):
                    name = propnames[i]
                    v = entry[i]

                    if name in ('id', '__retired__'):
                        if first:
                            cols.append(name)
                        l.append(int(v))
                        continue
                    if first:
                        cols.append('_' + name)
                    prop = properties[name]
                    if isinstance(prop, hyperdb.Date) and v is not None:
                        v = date.Date(v)
                    elif isinstance(prop, hyperdb.Interval) and v is not None:
                        v = date.Interval(v)
                    elif isinstance(prop, hyperdb.Password) and v is not None:
                        v = password.Password(encrypted=v)
                    elif isinstance(prop, hyperdb.Integer) and v is not None:
                        v = int(v)
                    elif (isinstance(prop, hyperdb.Boolean) or
                            isinstance(prop, hyperdb.Number)) and v is not None:
                        v = float(v)

                    # convert to new MySQL data type
                    prop = properties[name]
                    if v is not None:
                        e = self.to_sql_value(prop.__class__)(v)
                    else:
                        e = None
                    l.append(e)

                    # Intervals store the seconds value too
                    if isinstance(prop, hyperdb.Interval):
                        if first:
                            cols.append('__' + name + '_int__')
                        if v is not None:
                            l.append(v.as_seconds())
                        else:
                            l.append(e)
                first = 0

            self.drop_class_table_indexes(cn, old_spec[0])

            # drop the old table
            self.sql('drop table _%s'%cn)

            # create the new table
            self.create_class_table(klass)

            # do the insert of the old data
            args = ','.join([self.arg for x in cols])
            cols = ','.join(cols)
            sql = 'insert into _%s (%s) values (%s)'%(cn, cols, args)
            for entry in olddata:
                self.sql(sql, tuple(entry))

            # now load up the old journal data to migrate it
            cols = ','.join('nodeid date tag action params'.split())
            sql = 'select %s from %s__journal'%(cols, cn)
            self.sql(sql)

            # data conversions
            olddata = []
            for nodeid, journaldate, journaltag, action, params in \
                    self.cursor.fetchall():
                #nodeid = int(nodeid)
                journaldate = date.Date(journaldate)
                #params = eval(params)
                olddata.append((nodeid, journaldate, journaltag, action,
                    params))

            # drop journal table and indexes
            self.drop_journal_table_indexes(cn)
            sql = 'drop table %s__journal'%cn
            self.sql(sql)

            # re-create journal table
            self.create_journal_table(klass)
            dc = self.to_sql_value(hyperdb.Date)
            for nodeid, journaldate, journaltag, action, params in olddata:
                self.save_journal(cn, cols, nodeid, dc(journaldate),
                    journaltag, action, params)

            # make sure the normal schema update code doesn't try to
            # change things
            self.database_schema['tables'][cn] = klass.schema()
Ejemplo n.º 10
0
    def handle(self):
        """Performs an edit of all of a class' items in one go.

        The "rows" CGI var defines the CSV-formatted entries for the class. New
        nodes are identified by the ID 'X' (or any other non-existent ID) and
        removed lines are retired.
        """
        # ensure modification comes via POST
        if self.client.env['REQUEST_METHOD'] != 'POST':
            raise roundup.exceptions.Reject(self._('Invalid request'))

        # figure the properties list for the class
        cl = self.db.classes[self.classname]
        props_without_id = list(cl.getprops(protected=0))

        # the incoming CSV data will always have the properties in colums
        # sorted and starting with the "id" column
        props_without_id.sort()
        props = ['id'] + props_without_id

        # do the edit
        rows = io_.BytesIO(self.form['rows'].value)
        reader = csv.reader(rows)
        found = {}
        line = 0
        for values in reader:
            line += 1
            if line == 1: continue
            # skip property names header
            if values == props:
                continue

            # extract the itemid
            itemid, values = values[0], values[1:]
            found[itemid] = 1

            # see if the node exists
            if itemid in ('x', 'X') or not cl.hasnode(itemid):
                exists = 0

                # check permission to create this item
                if not self.hasPermission('Create', classname=self.classname):
                    raise exceptions.Unauthorised(
                        self._(
                            'You do not have permission to create %(class)s') %
                        {'class': self.classname})
            elif cl.hasnode(itemid) and cl.is_retired(itemid):
                # If a CSV line just mentions an id and the corresponding
                # item is retired, then the item is restored.
                cl.restore(itemid)
                continue
            else:
                exists = 1

            # confirm correct weight
            if len(props_without_id) != len(values):
                self.client.add_error_message(
                    self._('Not enough values on line %(line)s') %
                    {'line': line})
                return

            # extract the new values
            d = {}
            for name, value in zip(props_without_id, values):
                # check permission to edit this property on this item
                if exists and not self.hasPermission('Edit',
                                                     itemid=itemid,
                                                     classname=self.classname,
                                                     property=name):
                    raise exceptions.Unauthorised(
                        self._('You do not have permission to edit %(class)s')
                        % {'class': self.classname})

                prop = cl.properties[name]
                value = value.strip()
                # only add the property if it has a value
                if value:
                    # if it's a multilink, split it
                    if isinstance(prop, hyperdb.Multilink):
                        value = value.split(':')
                    elif isinstance(prop, hyperdb.Password):
                        value = password.Password(value, config=self.db.config)
                    elif isinstance(prop, hyperdb.Interval):
                        value = date.Interval(value)
                    elif isinstance(prop, hyperdb.Date):
                        value = date.Date(value)
                    elif isinstance(prop, hyperdb.Boolean):
                        value = value.lower() in ('yes', 'true', 'on', '1')
                    elif isinstance(prop, hyperdb.Number):
                        value = float(value)
                    d[name] = value
                elif exists:
                    # nuke the existing value
                    if isinstance(prop, hyperdb.Multilink):
                        d[name] = []
                    else:
                        d[name] = None

            # perform the edit
            if exists:
                # edit existing
                cl.set(itemid, **d)
            else:
                # new node
                found[cl.create(**d)] = 1

        # retire the removed entries
        for itemid in cl.list():
            if itemid not in found:
                # check permission to retire this item
                if not self.hasPermission(
                        'Retire', itemid=itemid, classname=self.classname):
                    raise exceptions.Unauthorised(
                        self._(
                            'You do not have permission to retire %(class)s') %
                        {'class': self.classname})
                cl.retire(itemid)

        # all OK
        self.db.commit()

        self.client.add_ok_message(self._('Items edited OK'))