Example #1
0
def dyn_user_chpass_wizard(request):
	sess = DBSession()
	loc = get_localizer(request)
	model = ExtModel(User)
	user = request.user
	wiz = Wizard(
		Step(
			ExtJSWizardField({
				'xtype'      : 'passwordfield',
				'name'       : 'oldpass',
				'allowBlank' : False,
				'triggers'   : None,
				'fieldLabel' : loc.translate(_('Old password')),
				'maxLength'  : 255,
				'value'      : '',
				'emptyValue' : ''
			}),
			ExtJSWizardField({
				'xtype'      : 'passwordfield',
				'name'       : 'newpass1',
				'allowBlank' : False,
				'triggers'   : None,
				'fieldLabel' : loc.translate(_('New password')),
				'maxLength'  : 255,
				'value'      : '',
				'emptyValue' : ''
			}),
			ExtJSWizardField({
				'xtype'      : 'passwordfield',
				'name'       : 'newpass2',
				'allowBlank' : False,
				'triggers'   : None,
				'fieldLabel' : loc.translate(_('Repeat password')),
				'maxLength'  : 255,
				'value'      : '',
				'emptyValue' : ''
			})
		),
		validator='ChangePassword'
	)
	return {
		'success' : True,
		'fields'  : wiz.get_cfg(model, request, use_defaults=True),
		'title'   : loc.translate(_('Change your password'))
	}
Example #2
0
class Host(Base):
    """
	Host object.
	"""
    __tablename__ = 'hosts_def'
    __table_args__ = (Comment('Hosts'),
                      Index('hosts_def_u_hostname',
                            'domainid',
                            'name',
                            unique=True), Index('hosts_def_i_hgid', 'hgid'),
                      Index('hosts_def_i_entityid',
                            'entityid'), Index('hosts_def_i_aliasid',
                                               'aliasid'),
                      Index('hosts_def_i_cby',
                            'cby'), Index('hosts_def_i_mby', 'mby'),
                      Trigger('before', 'insert', 't_hosts_def_bi'),
                      Trigger('before', 'update', 't_hosts_def_bu'),
                      Trigger('after', 'insert', 't_hosts_def_ai'),
                      Trigger('after', 'update', 't_hosts_def_au'),
                      Trigger('after', 'delete', 't_hosts_def_ad'), {
                          'mysql_engine': 'InnoDB',
                          'mysql_charset': 'utf8',
                          'info': {
                              'cap_menu':
                              'BASE_HOSTS',
                              'cap_read':
                              'HOSTS_LIST',
                              'cap_create':
                              'HOSTS_CREATE',
                              'cap_edit':
                              'HOSTS_EDIT',
                              'cap_delete':
                              'HOSTS_DELETE',
                              'menu_name':
                              _('Hosts'),
                              'show_in_menu':
                              'modules',
                              'menu_main':
                              True,
                              'default_sort': ({
                                  'property': 'name',
                                  'direction': 'ASC'
                              }, ),
                              'grid_view':
                              ('hostid',
                               MarkupColumn(name='name',
                                            header_string=_('Name'),
                                            template='{__str__}',
                                            column_flex=3,
                                            sortable=True), 'domain', 'group',
                               'entity'),
                              'grid_hidden': ('hostid', 'domain'),
                              'form_view':
                              ('name', 'domain', 'group', 'entity', 'original',
                               'aliastype', 'descr', 'ctime', 'cby', 'mtime',
                               'mby'),
                              'easy_search': ('name', ),
                              'detail_pane':
                              ('netprofile_core.views', 'dpane_simple'),
                              'create_wizard':
                              Wizard(Step('name',
                                          'domain',
                                          'entity',
                                          title=_('New host data')),
                                     Step('group',
                                          'original',
                                          'aliastype',
                                          'descr',
                                          title=_('New host details')),
                                     title=_('Add new host'))
                          }
                      })
    id = Column('hostid',
                UInt32(),
                Sequence('hosts_def_hostid_seq'),
                Comment('Host ID'),
                primary_key=True,
                nullable=False,
                info={'header_string': _('ID')})
    group_id = Column('hgid',
                      UInt32(),
                      ForeignKey('hosts_groups.hgid',
                                 name='hosts_def_fk_hgid',
                                 onupdate='CASCADE'),
                      Comment('Host group ID'),
                      nullable=False,
                      info={
                          'header_string': _('Group'),
                          'filter_type': 'nplist',
                          'column_flex': 1
                      })
    entity_id = Column('entityid',
                       UInt32(),
                       ForeignKey('entities_def.entityid',
                                  name='hosts_def_fk_entityid',
                                  onupdate='CASCADE',
                                  ondelete='CASCADE'),
                       Comment('Entity ID'),
                       nullable=False,
                       info={
                           'header_string': _('Entity'),
                           'filter_type': 'none',
                           'column_flex': 1
                       })
    domain_id = Column('domainid',
                       UInt32(),
                       ForeignKey('domains_def.domainid',
                                  name='hosts_def_fk_domainid',
                                  onupdate='CASCADE'),
                       Comment('Domain ID'),
                       nullable=False,
                       info={
                           'header_string': _('Domain'),
                           'filter_type': 'nplist',
                           'column_flex': 2
                       })
    name = Column(Unicode(255),
                  Comment('Host Name'),
                  nullable=False,
                  info={'header_string': _('Name')})
    original_id = Column('aliasid',
                         UInt32(),
                         ForeignKey('hosts_def.hostid',
                                    name='hosts_def_fk_aliasid',
                                    ondelete='CASCADE',
                                    onupdate='CASCADE'),
                         Comment('Aliased host ID'),
                         nullable=True,
                         default=None,
                         server_default=text('NULL'),
                         info={
                             'header_string': _('Aliased'),
                             'filter_type': 'nplist'
                         })
    alias_type = Column('aliastype',
                        HostAliasType.db_type(),
                        Comment('Host alias type'),
                        nullable=False,
                        default=HostAliasType.symbolic,
                        server_default=HostAliasType.symbolic,
                        info={'header_string': _('Alias Type')})
    creation_time = Column('ctime',
                           TIMESTAMP(),
                           Comment('Time of creation'),
                           nullable=True,
                           default=None,
                           server_default=FetchedValue(),
                           info={
                               'header_string': _('Created'),
                               'read_only': True
                           })
    modification_time = Column('mtime',
                               TIMESTAMP(),
                               Comment('Time of last modification'),
                               CurrentTimestampDefault(on_update=True),
                               nullable=False,
                               info={
                                   'header_string': _('Modified'),
                                   'read_only': True
                               })
    created_by_id = Column('cby',
                           UInt32(),
                           ForeignKey('users.uid',
                                      name='hosts_def_fk_cby',
                                      ondelete='SET NULL',
                                      onupdate='CASCADE'),
                           Comment('Created by'),
                           nullable=True,
                           default=None,
                           server_default=text('NULL'),
                           info={
                               'header_string': _('Created'),
                               'read_only': True
                           })
    modified_by_id = Column('mby',
                            UInt32(),
                            ForeignKey('users.uid',
                                       name='hosts_def_fk_mby',
                                       ondelete='SET NULL',
                                       onupdate='CASCADE'),
                            Comment('Last modified by'),
                            nullable=True,
                            default=None,
                            server_default=text('NULL'),
                            info={
                                'header_string': _('Modified'),
                                'read_only': True
                            })
    description = Column('descr',
                         UnicodeText(),
                         Comment('Host description'),
                         nullable=True,
                         default=None,
                         server_default=text('NULL'),
                         info={'header_string': _('Description')})

    group = relationship('HostGroup', innerjoin=True, backref='hosts')
    entity = relationship('Entity',
                          innerjoin=True,
                          backref=backref('hosts',
                                          cascade='all, delete-orphan',
                                          passive_deletes=True))
    domain = relationship('Domain', innerjoin=True, backref='hosts')
    original = relationship('Host',
                            backref=backref('aliases',
                                            cascade='all, delete-orphan',
                                            passive_deletes=True),
                            remote_side=[id])
    created_by = relationship('User',
                              foreign_keys=created_by_id,
                              backref=backref('created_hosts',
                                              passive_deletes=True))
    modified_by = relationship('User',
                               foreign_keys=modified_by_id,
                               backref=backref('modified_hosts',
                                               passive_deletes=True))
    services = relationship('Service',
                            backref=backref('host', innerjoin=True),
                            cascade='all, delete-orphan',
                            passive_deletes=True)

    @property
    def real(self):
        if not self.original:
            return self
        h = self
        while h.original:
            h = h.original
        return h

    def __str__(self):
        if self.domain:
            return '%s.%s' % (str(self.name), str(self.domain))
        return str(self.name)

    @classmethod
    def resolve(cls, name, domain_aliases=True):
        parts = name.strip('.').split('.')
        num_parts = len(parts)
        if num_parts == 1:
            # TODO: support specifying default domain
            raise ValueError('Hostname must be fully qualified')
        variants = list(('.'.join(parts[:i]), '.'.join(parts[i:]))
                        for i in range(1, num_parts))
        sess = DBSession()
        for host_part, domain_part in variants:
            domain = Domain.resolve(domain_part, domain_aliases=domain_aliases)
            if domain is None:
                continue
            try:
                return sess.query(Host).filter(Host.domain == domain,
                                               Host.name == host_part).one()
            except NoResultFound:
                pass
Example #3
0
class PDNSTemplate(Base):
    """
    PDNS Association table for both template and field types
    """
    __tablename__ = 'pdns_templates'
    __table_args__ = (
        Comment('PowerDNS Template-Field Association Table'),
        {
            'mysql_engine': 'InnoDB',
            'mysql_charset': 'utf8',
            'info': {
                'cap_menu':
                'BASE_DOMAINS',
                # 'cap_read'      : 'DOMAINS_LIST',
                # 'cap_create'    : 'DOMAINS_CREATE',
                # 'cap_edit'      : 'DOMAINS_EDIT',
                # 'cap_delete'    : 'DOMAINS_DELETE',
                'show_in_menu':
                'admin',
                'menu_name':
                _('PDNS Templates'),
                'menu_order':
                50,
                'grid_view': ('template', 'field', 'defaultvalues'),
                'form_view': ('template', 'field', 'defaultvalues'),
                'easy_search': ('template', ),
                'detail_pane': ('netprofile_core.views', 'dpane_simple'),
                'create_wizard':
                Wizard(Step(
                    'template',
                    'field',
                    id='generic',
                    title=_('Add new template'),
                    on_submit=_wizcb_pdnstemplate_submit('PDNSTemplate')),
                       title=_('New domain template'),
                       validator='CreateDomainTemplate')
            }
        })
    id = Column('relationid',
                UInt32(),
                Sequence('pdns_templates_relationid_seq'),
                Comment('ID'),
                primary_key=True,
                nullable=False,
                info={'header_string': _('ID')})
    templateid = Column('templ_id',
                        UInt32(),
                        ForeignKey('pdns_templatetypes.id'),
                        info={'header_string': _('Template')})
    fieldid = Column('field_id',
                     UInt32(),
                     ForeignKey('pdns_recordtypes.id'),
                     info={
                         'header_string': _('Record'),
                         'editor_xtype': 'gridfield'
                     })
    defaultvalues = Column('defvalues',
                           Unicode(255),
                           Comment('Default Values'),
                           nullable=True,
                           default=None,
                           info={'header_string': _('Default Values')})
    template = relationship("PDNSTemplateType",
                            backref=backref('template_fields',
                                            cascade="all, delete-orphan"))
    field = relationship("PDNSFieldType")

    def __str__(self):
        return '%s %s Record' % (self.template.name, self.field.name)
Example #4
0
def dyn_ticket_uwiz(params, request):
    tid = int(params['ticketid'])
    sess = DBSession()
    loc = request.localizer
    trans = [{
        'name':
        'ttrid',
        'boxLabel':
        '<div class="np-xradiolabel"><div class="title">%s</div>%s</div>' %
        (html_escape(loc.translate(_('No changes')), True),
         html_escape(loc.translate(_('Do not change ticket state.')), True)),
        'inputValue':
        '',
        'checked':
        True
    }]
    ticket = sess.query(Ticket).get(tid)
    if ticket is None:
        raise KeyError('Invalid ticket ID')
    model = ExtModel(Ticket)
    ch_model = ExtModel(TicketChange)
    fields = []
    if request.has_permission('ENTITIES_LIST'):
        fields.append(
            ExternalWizardField(
                model,
                'entity',
                value=ticket.entity,
                extra_config={
                    'readOnly':
                    not bool(request.has_permission('TICKETS_CHANGE_ENTITY'))
                }))
    if request.has_permission('TICKETS_CHANGE_STATE'):
        for tr in ticket.state.transitionmap_to:
            label = '<div class="np-xradiolabel"><div class="title">%s</div>%s</div>' % (
                html_escape(tr.name, True),
                html_escape((tr.description if tr.description else ''), True))
            trans.append({
                'name': 'ttrid',
                'boxLabel': label,
                'inputValue': tr.id
            })
        fields.append(
            ExtJSWizardField({
                'xtype': 'radiogroup',
                'fieldLabel': loc.translate(_('Transition')),
                'vertical': True,
                'columns': 1,
                'items': trans
            }))
    if request.has_permission('TICKETS_CHANGE_FLAGS'):
        fields.append(ExternalWizardField(model, 'flags', value=ticket.flags))
    if request.has_permission('USERS_LIST'):
        fields.append(
            ExternalWizardField(
                model,
                'assigned_user',
                value=ticket.assigned_user,
                extra_config={
                    'readOnly':
                    not bool(request.has_permission('TICKETS_CHANGE_UID'))
                }))
    if request.has_permission('GROUPS_LIST'):
        fields.append(
            ExternalWizardField(
                model,
                'assigned_group',
                value=ticket.assigned_group,
                extra_config={
                    'readOnly':
                    not bool(request.has_permission('TICKETS_CHANGE_GID'))
                }))
    fields.extend(
        (ExternalWizardField(model, 'ticketid', value=ticket.id),
         CompositeWizardField(
             ExternalWizardField(
                 model,
                 'assigned_time',
                 value=ticket.assigned_time,
                 extra_config={
                     'readOnly':
                     not bool(request.has_permission('TICKETS_CHANGE_DATE'))
                 }),
             ExtJSWizardField({
                 'xtype': 'button',
                 'text': 'Schedule',
                 'iconCls': 'ico-schedule',
                 'margin': '0 0 0 2',
                 'itemId': 'btn_sched'
             })),
         ExternalWizardField(
             model,
             'archived',
             value=ticket.archived,
             extra_config={
                 'readOnly':
                 not bool(request.has_permission('TICKETS_ARCHIVAL'))
             }), ExternalWizardField(ch_model, 'show_client', value=False)))
    if request.has_permission('TICKETS_COMMENT'):
        fields.append(ExternalWizardField(ch_model, 'comments'))
    wiz = Wizard(Step(*fields), title=_('Update ticket'))
    ret = {
        'success': True,
        'fields': wiz.get_cfg(model, request, use_defaults=True)
    }
    return ret
Example #5
0
class StashIO(Base):
	"""
	Stash I/O operation object.
	"""
	__tablename__ = 'stashes_io_def'
	__table_args__ = (
		Comment('Stashes input/output operations'),
		Index('stashes_io_def_i_siotypeid', 'siotypeid'),
		Index('stashes_io_def_i_stashid', 'stashid'),
		Index('stashes_io_def_i_currid', 'currid'),
		Index('stashes_io_def_i_uid', 'uid'),
		Index('stashes_io_def_i_entityid', 'entityid'),
		Index('stashes_io_def_i_ts', 'ts'),
		Trigger('before', 'insert', 't_stashes_io_def_bi'),
		Trigger('after', 'insert', 't_stashes_io_def_ai'),
		{
			'mysql_engine'  : 'InnoDB',
			'mysql_charset' : 'utf8',
			'info'          : {
				'cap_menu'      : 'BASE_STASHES',
				'cap_read'      : 'STASHES_IO',
				'cap_create'    : 'STASHES_IO',
				'cap_edit'      : '__NOPRIV__',
				'cap_delete'    : '__NOPRIV__',
				'menu_name'     : _('Operations'),
				'show_in_menu'  : 'modules',
				'default_sort'  : ({ 'property': 'ts', 'direction': 'DESC' },),
				'grid_view'     : ('sioid', 'type', 'stash', 'entity', 'user', 'ts', 'currency', 'diff'),
				'grid_hidden'   : ('sioid', 'currency'),
				'form_view'     : ('type', 'stash', 'currency', 'entity', 'user', 'ts', 'diff', 'descr'),
				'extra_data'    : ('formatted_difference',),
				'detail_pane'   : ('netprofile_core.views', 'dpane_simple'),

				'create_wizard' : Wizard(
					Step(
						'stash', 'type', 'diff', 'descr',
						id='generic',
						on_submit=_wizcb_stashio_submit
					),
					title=_('Add new operation')
				)
			}
		}
	)
	id = Column(
		'sioid',
		UInt32(),
		Sequence('stashes_io_def_sioid_seq'),
		Comment('Stash I/O ID'),
		primary_key=True,
		nullable=False,
		info={
			'header_string' : _('ID')
		}
	)
	type_id = Column(
		'siotypeid',
		UInt32(),
		Comment('Stash I/O type ID'),
		ForeignKey('stashes_io_types.siotypeid', name='stashes_io_def_fk_siotypeid', ondelete='CASCADE', onupdate='CASCADE'),
		nullable=False,
		info={
			'header_string' : _('Type'),
			'filter_type'   : 'nplist',
			'editor_xtype'  : 'simplemodelselect',
			'editor_config' : {
				'extraParams' : { '__ffilter' : [{
					'property' : 'oper_visible',
					'operator' : 'eq',
					'value'    : True
				}]}
			},
			'column_flex'   : 2
		}
	)
	stash_id = Column(
		'stashid',
		UInt32(),
		Comment('Stash ID'),
		ForeignKey('stashes_def.stashid', name='stashes_io_def_fk_stashid', ondelete='CASCADE', onupdate='CASCADE'),
		nullable=False,
		info={
			'header_string' : _('Stash'),
			'filter_type'   : 'none',
			'column_flex'   : 2
		}
	)
	currency_id = Column(
		'currid',
		UInt32(),
		Comment('Currency ID'),
		ForeignKey('currencies_def.currid', name='stashes_io_def_fk_currid', onupdate='CASCADE'), # ondelete=RESTRICT
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Currency'),
			'editor_xtype'  : 'simplemodelselect',
			'editor_config' : {
				'extraParams' : { '__ffilter' : [{
					'property' : 'oper_visible',
					'operator' : 'eq',
					'value'    : True
				}]}
			},
			'filter_type'   : 'nplist'
		}
	)
	user_id = Column(
		'uid',
		UInt32(),
		Comment('User ID'),
		ForeignKey('users.uid', name='stashes_io_def_fk_uid', ondelete='SET NULL', onupdate='CASCADE'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Operator'),
			'filter_type'   : 'nplist'
		}
	)
	entity_id = Column(
		'entityid',
		UInt32(),
		Comment('Related entity ID'),
		ForeignKey('entities_def.entityid', name='stashes_io_def_fk_entityid', ondelete='SET NULL', onupdate='CASCADE'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Entity'),
			'filter_type'   : 'none',
			'column_flex'   : 1
		}
	)
	timestamp = Column(
		'ts',
		TIMESTAMP(),
		Comment('Time stamp of operation'),
		CurrentTimestampDefault(),
		nullable=False,
		info={
			'header_string' : _('Date'),
			'column_flex'   : 1
		}
	)
	difference = Column(
		'diff',
		Money(),
		Comment('Operation result'),
		nullable=False,
		info={
			'header_string' : _('Change'),
			'column_xtype'  : 'templatecolumn',
			'template'      : '{formatted_difference}'
		}
	)
	description = Column(
		'descr',
		UnicodeText(),
		Comment('Description'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Description')
		}
	)

	type = relationship(
		'StashIOType',
		innerjoin=True,
		lazy='joined',
		backref=backref(
			'ios',
			cascade='all, delete-orphan',
			passive_deletes=True
		)
	)
	stash = relationship(
		'Stash',
		innerjoin=True,
		backref=backref(
			'ios',
			cascade='all, delete-orphan',
			passive_deletes=True
		)
	)
	currency = relationship(
		'Currency',
		lazy='joined',
		backref=backref(
			'ios',
			passive_deletes='all'
		)
	)
	user = relationship(
		'User',
		backref=backref(
			'stash_ios',
			passive_deletes=True
		)
	)
	entity = relationship(
		'Entity',
		backref=backref(
			'stash_ios',
			passive_deletes=True
		)
	)

	def __str__(self):
		return '%s: %s' % (
			str(self.stash),
			str(self.type)
		)

	def formatted_difference(self, req):
		return money_format(req, self.difference, currency=self.currency)
Example #6
0
class FuturePayment(Base):
	"""
	Future payment object.
	"""
	__tablename__ = 'futures_def'
	__table_args__ = (
		Comment('Future payments'),
		Index('futures_def_i_futures', 'state', 'ptime'),
		Index('futures_def_i_entityid', 'entityid'),
		Index('futures_def_i_stashid', 'stashid'),
		Index('futures_def_i_cby', 'cby'),
		Index('futures_def_i_mby', 'mby'),
		Index('futures_def_i_pby', 'pby'),
		Trigger('before', 'insert', 't_futures_def_bi'),
		Trigger('before', 'update', 't_futures_def_bu'),
		Trigger('after', 'insert', 't_futures_def_ai'),
		Trigger('after', 'update', 't_futures_def_au'),
		Trigger('after', 'delete', 't_futures_def_ad'),
		{
			'mysql_engine'  : 'InnoDB',
			'mysql_charset' : 'utf8',
			'info'          : {
				'cap_menu'      : 'BASE_FUTURES',
				'cap_read'      : 'FUTURES_LIST',
				'cap_create'    : 'FUTURES_CREATE',
				'cap_edit'      : 'FUTURES_EDIT',
				'cap_delete'    : '__NOPRIV__',
				# TODO: APPROVE/CANCEL
				'menu_name'     : _('Promised Payments'),
				'default_sort'  : ({ 'property': 'ctime', 'direction': 'DESC' },),
				'grid_view'     : ('futureid', 'entity', 'stash', 'diff', 'state', 'ctime'),
				'grid_hidden'   : ('futureid',),
				'form_view'     : (
					'entity', 'stash', 'diff',
					'state', 'origin',
					'ctime', 'created_by',
					'mtime', 'modified_by',
					'ptime', 'paid_by'
				),
				'detail_pane'   : ('netprofile_core.views', 'dpane_simple'),
				'create_wizard' : Wizard(
					Step(
						'entity', 'stash', 'diff', 'descr',
						id='generic',
						on_submit=_wizcb_future_submit
					),
					title=_('Add new promised payment')
				)
			}
		}
	)
	id = Column(
		'futureid',
		UInt32(),
		Sequence('futures_def_futureid_seq'),
		Comment('Future payment ID'),
		primary_key=True,
		nullable=False,
		info={
			'header_string': _('ID')
		}
	)
	entity_id = Column(
		'entityid',
		UInt32(),
		Comment('Entity ID'),
		ForeignKey('entities_def.entityid', name='futures_def_fk_entityid', onupdate='CASCADE', ondelete='SET NULL'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Entity'),
			'filter_type'   : 'none',
			'column_flex'   : 2
		}
	)
	stash_id = Column(
		'stashid',
		UInt32(),
		Comment('Stash ID'),
		ForeignKey('stashes_def.stashid', name='futures_def_fk_stashid', ondelete='CASCADE', onupdate='CASCADE'),
		nullable=False,
		info={
			'header_string' : _('Stash'),
			'filter_type'   : 'none',
			'column_flex'   : 2
		}
	)
	difference = Column(
		'diff',
		Money(),
		Comment('Payment result'),
		nullable=False,
		default=0.0,
		server_default=text('0.0'),
		info={
			'header_string' : _('Change')
		}
	)
	state = Column(
		FuturePaymentState.db_type(),
		Comment('Active / Paid / Cancelled'),
		nullable=False,
		default=FuturePaymentState.active,
		server_default=FuturePaymentState.active,
		info={
			'header_string' : _('State')
		}
	)
	origin = Column(
		FuturePaymentOrigin.db_type(),
		Comment('Origin of payment'),
		nullable=False,
		default=FuturePaymentOrigin.operator,
		server_default=FuturePaymentOrigin.operator,
		info={
			'header_string' : _('Origin')
		}
	)
	creation_time = Column(
		'ctime',
		TIMESTAMP(),
		Comment('Creation timestamp'),
		nullable=True,
		default=None,
		server_default=FetchedValue(),
		info={
			'header_string' : _('Created'),
			'read_only'     : True
		}
	)
	modification_time = Column(
		'mtime',
		TIMESTAMP(),
		Comment('Last modification timestamp'),
		CurrentTimestampDefault(on_update=True),
		nullable=False,
		info={
			'header_string' : _('Modified'),
			'read_only'     : True
		}
	)
	payment_time = Column(
		'ptime',
		TIMESTAMP(),
		Comment('Payment timestamp'),
		nullable=True,
		default=None,
		server_default=FetchedValue(),
		info={
			'header_string' : _('Confirmed'),
			'read_only'     : True
		}
	)
	created_by_id = Column(
		'cby',
		UInt32(),
		ForeignKey('users.uid', name='futures_def_fk_cby', ondelete='SET NULL', onupdate='CASCADE'),
		Comment('Created by'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Created'),
			'read_only'     : True
		}
	)
	modified_by_id = Column(
		'mby',
		UInt32(),
		ForeignKey('users.uid', name='futures_def_fk_mby', ondelete='SET NULL', onupdate='CASCADE'),
		Comment('Modified by'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Modified'),
			'read_only'     : True
		}
	)
	paid_by_id = Column(
		'pby',
		UInt32(),
		ForeignKey('users.uid', name='futures_def_fk_pby', ondelete='SET NULL', onupdate='CASCADE'),
		Comment('Payment confirmed by'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Confirmed'),
			'read_only'     : True
		}
	)
	description = Column(
		'descr',
		UnicodeText(),
		Comment('Description'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Description')
		}
	)

	stash = relationship(
		'Stash',
		innerjoin=True,
		backref=backref(
			'futures',
			cascade='all, delete-orphan',
			passive_deletes=True
		)
	)
	entity = relationship(
		'Entity',
		backref=backref(
			'stash_futures',
			passive_deletes=True
		)
	)
	created_by = relationship(
		'User',
		foreign_keys=created_by_id,
		backref=backref(
			'created_futures',
			passive_deletes=True
		)
	)
	modified_by = relationship(
		'User',
		foreign_keys=modified_by_id,
		backref=backref(
			'modified_futures',
			passive_deletes=True
		)
	)
	paid_by = relationship(
		'User',
		foreign_keys=paid_by_id,
		backref=backref(
			'paid_futures',
			passive_deletes=True
		)
	)

	def __str__(self):
		return '%s: %s' % (
			str(self.stash),
			str(self.difference)
		)
Example #7
0
class House(Base):
	"""
	House object. Used for anything with an exact address.
	"""

	@classmethod
	def _filter_hgroup(cls, query, value):
		if not isinstance(value, list):
			value = [value]
		return query.filter(House.id.in_(
			DBSession().query(HouseGroupMapping.house_id)\
				.filter(HouseGroupMapping.group_id.in_(value))
		))

	@classmethod
	def _filter_address(cls, query, value):
		if not isinstance(value, dict):
			return query
		if 'streetid' in value:
			val = int(value['streetid'])
			if val > 0:
				query = query.filter(House.street_id == val)
		elif 'districtid' in value:
			val = int(value['districtid'])
			if val > 0:
				query = query.join(House.street).filter(or_(
					Street.district_id == val,
					House.district_id == val
				))
		elif 'cityid' in value:
			val = int(value['cityid'])
			if val > 0:
				query = query.join(House.street).filter(Street.city_id == val)
		return query

	__tablename__ = 'addr_houses'
	__table_args__ = (
		Comment('Houses'),
		Index('addr_houses_u_house', 'streetid', 'number', 'num_slash', 'num_suffix', 'building', unique=True),
		Index('addr_houses_i_districtid', 'districtid'),
		{
			'mysql_engine'  : 'InnoDB',
			'mysql_charset' : 'utf8',
			'info'          : {
				'cap_menu'      : 'BASE_GEO',
				'cap_read'      : 'GEO_LIST',
				'cap_create'    : 'GEO_CREATE',
				'cap_edit'      : 'GEO_EDIT',
				'cap_delete'    : 'GEO_DELETE',

				'show_in_menu'  : 'admin',
				'menu_name'     : _('Houses'),
				'default_sort'  : (
					{ 'property' : 'streetid', 'direction' : 'ASC' },
					{ 'property' : 'number', 'direction' : 'ASC' },
					{ 'property' : 'num_slash', 'direction' : 'ASC' },
					{ 'property' : 'num_suffix', 'direction' : 'ASC' },
					{ 'property' : 'building', 'direction' : 'ASC' }
				),
				'grid_view'     : (
					'houseid',
					'street', 'number', 'num_slash', 'num_suffix', 'building',
					'entrnum', 'postindex'
				),
				'grid_hidden'   : ('houseid',),
				'form_view'     : (
					'street', 'number', 'num_slash', 'num_suffix', 'building',
					'district', 'house_groups', 'entrnum', 'postindex', 'descr'
				),
				'easy_search'   : ('number',),
				'detail_pane'   : ('netprofile_core.views', 'dpane_simple'),
				'extra_search'  : (
					CheckboxGroupFilter('hg', _filter_hgroup,
						title=_('House Group'),
						data='NetProfile.store.geo.HouseGroup',
						value_field='ahgid',
						display_field='name'
					),
					AddressFilter('address', _filter_address,
						title=_('Address'),
						show_houses=False
					)
				),

				'create_wizard' : Wizard(
					Step('street', 'number', 'num_slash', 'num_suffix', 'building', title=_('Basic house data')),
					Step('house_groups', 'entrnum', 'postindex', title=_('Additional house data')),
					title=_('Add new house')
				)
			}
		}
	)
	id = Column(
		'houseid',
		UInt32(),
		Sequence('addr_houses_houseid_seq'),
		Comment('House ID'),
		primary_key=True,
		nullable=False,
		info={
			'header_string' : _('ID')
		}
	)
	street_id = Column(
		'streetid',
		UInt32(),
		ForeignKey('addr_streets.streetid', name='addr_houses_fk_streetid', ondelete='CASCADE', onupdate='CASCADE'),
		Comment('Street ID'),
		nullable=False,
		info={
			'header_string' : _('Street'),
			'filter_type'   : 'nplist',
			'column_flex'   : 1
		}
	)
	district_id = Column(
		'districtid',
		UInt32(),
		ForeignKey('addr_districts.districtid', name='addr_houses_fk_districtid', ondelete='SET NULL', onupdate='CASCADE'),
		Comment('District ID'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('District'),
			'filter_type'   : 'nplist',
			'column_flex'   : 1
		}
	)
	number = Column(
		UInt16(),
		Comment('House number'),
		nullable=False,
		default=0,
		server_default=text('0'),
		info={
			'header_string' : _('Number')
		}
	)
	building = Column(
		UInt16(),
		Comment('House building'),
		nullable=False,
		default=0,
		server_default=text('0'),
		info={
			'header_string' : _('Building')
		}
	)
	second_number = Column(
		'num_slash',
		UInt16(),
		Comment('Second house number'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Second Num.')
		}
	)
	number_suffix = Column(
		'num_suffix',
		Unicode(32),
		Comment('House number suffix'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Num. Suffix')
		}
	)
	entrances = Column(
		'entrnum',
		UInt8(),
		Comment('Number of entrances'),
		nullable=False,
		default=1,
		server_default=text('1'),
		info={
			'header_string' : _('Entr. #')
		}
	)
	postal_code = Column(
		'postindex',
		Unicode(8),
		Comment('Postal code'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Postal Code')
		}
	)
	description = Column(
		'descr',
		UnicodeText(),
		Comment('House description'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Description')
		}
	)

	places = relationship(
		'Place',
		backref=backref('house', innerjoin=True),
		cascade='all, delete-orphan',
		passive_deletes=True
	)
	house_groupmap = relationship(
		'HouseGroupMapping',
		backref=backref('house', innerjoin=True),
		cascade='all, delete-orphan',
		passive_deletes=True
	)
	user_locations = relationship(
		'UserLocation',
		backref='house',
		cascade='all, delete-orphan',
		passive_deletes=True
	)

	house_groups = association_proxy(
		'house_groupmap',
		'group',
		creator=lambda v: HouseGroupMapping(group=v)
	)

	@classmethod
	def __augment_query__(cls, sess, query, params, req):
		flist = []
		if '__filter' in params:
			flist.extend(params['__filter'])
		if '__ffilter' in params:
			flist.extend(params['__ffilter'])
		for flt in flist:
			prop = flt.get('property', None)
			oper = flt.get('operator', None)
			value = flt.get('value', None)
			if prop == 'xdistrictid':
				if oper in ('eq', '=', '==', '==='):
					query = query.join(House.street).options(contains_eager(House.street))
					query = query.filter(or_(
						House.district_id == int(value),
						Street.district_id == int(value)
					))
			if prop == 'cityid':
				if oper in ('eq', '=', '==', '==='):
					query = query.join(House.street).options(contains_eager(House.street))
					query = query.filter(Street.city_id == int(value))
		return query

	@classmethod
	def __augment_result__(cls, sess, res, params, req):
		populate_related_list(
			res, 'id', 'house_groupmap', HouseGroupMapping,
			sess.query(HouseGroupMapping),
			None, 'house_id'
		)
		return res

	def __str__(self):
		loc = str
		req = getattr(self, '__req__', None)
		if req:
			loc = req.localizer.translate

		l = [str(self.street), str(self.number)]
		if self.number_suffix:
			l.append(self.number_suffix)
		if self.second_number:
			l.append('/' + str(self.second_number))
		if self.building:
			l.append(loc(_('bld.')))
			l.append(str(self.building))
		return ' '.join(l)
Example #8
0
def dyn_ticket_uwiz(params, request):
	tid = int(params['ticketid'])
	sess = DBSession()
	loc = request.localizer
	trans = [{
		'name'       : 'ttrid',
		'boxLabel'   : '<div class="np-xradiolabel"><div class="title">%s</div>%s</div>' % (
			html_escape(loc.translate(_('No changes')), True),
			html_escape(loc.translate(_('Do not change ticket state.')), True)
		),
		'inputValue' : '',
		'checked'    : True
	}]
	ticket = sess.query(Ticket).get(tid)
	if ticket is None:
		raise KeyError('Invalid ticket ID')
	model = ExtModel(Ticket)
	ch_model = ExtModel(TicketChange)
	fields = []
	if request.has_permission('ENTITIES_LIST'):
		fields.append(ExternalWizardField(
			model, 'entity',
			value=ticket.entity,
			extra_config={
				'readOnly' : not bool(request.has_permission('TICKETS_CHANGE_ENTITY'))
			}
		))
	if request.has_permission('TICKETS_CHANGE_STATE'):
		for tr in ticket.state.transitionmap_to:
			label = '<div class="np-xradiolabel"><div class="title">%s</div>%s</div>' % (
				html_escape(tr.name, True),
				html_escape((tr.description if tr.description else ''), True)
			)
			trans.append({
				'name'       : 'ttrid',
				'boxLabel'   : label,
				'inputValue' : tr.id
			})
		fields.append(ExtJSWizardField({
			'xtype'      : 'radiogroup',
			'fieldLabel' : loc.translate(_('Transition')),
			'vertical'   : True,
			'columns'    : 1,
			'items'      : trans
		}))
	if request.has_permission('TICKETS_CHANGE_FLAGS'):
		fields.append(ExternalWizardField(
			model, 'flags',
			value=ticket.flags
		))
	if request.has_permission('USERS_LIST'):
		fields.append(ExternalWizardField(
			model, 'assigned_user',
			value=ticket.assigned_user,
			extra_config={
				'readOnly' : not bool(request.has_permission('TICKETS_CHANGE_UID'))
			}
		))
	if request.has_permission('GROUPS_LIST'):
		fields.append(ExternalWizardField(
			model, 'assigned_group',
			value=ticket.assigned_group,
			extra_config={
				'readOnly' : not bool(request.has_permission('TICKETS_CHANGE_GID'))
			}
		))
	fields.extend((
		ExternalWizardField(
			model, 'ticketid',
			value=ticket.id
		),
		CompositeWizardField(
			ExternalWizardField(
				model, 'assigned_time',
				value=ticket.assigned_time,
				extra_config={
					'readOnly' : not bool(request.has_permission('TICKETS_CHANGE_DATE'))
				}
			),
			ExtJSWizardField({
				'xtype'   : 'button',
				'text'    : 'Schedule',
				'iconCls' : 'ico-schedule',
				'margin'  : '0 0 0 2',
				'itemId'  : 'btn_sched'
			})
		),
		ExternalWizardField(
			model, 'archived',
			value=ticket.archived,
			extra_config={
				'readOnly' : not bool(request.has_permission('TICKETS_ARCHIVAL'))
			}
		),
		ExternalWizardField(ch_model, 'show_client', value=False)
	))
	if request.has_permission('TICKETS_COMMENT'):
		fields.append(ExternalWizardField(ch_model, 'comments'))
	wiz = Wizard(Step(*fields), title=_('Update ticket'))
	ret = {
		'success' : True,
		'fields'  : wiz.get_cfg(model, request, use_defaults=True)
	}
	return ret
Example #9
0
class Domain(Base):
	"""
	Domain object.
	"""
	__tablename__ = 'domains_def'
	__table_args__ = (
		Comment('Domains'),
		Index('domains_def_u_domain', 'parentid', 'name', unique=True),
		Trigger('after', 'insert', 't_domains_def_ai'),
		Trigger('after', 'update', 't_domains_def_au'),
		Trigger('after', 'delete', 't_domains_def_ad'),
		{
			'mysql_engine'  : 'InnoDB',
			'mysql_charset' : 'utf8',
			'info'          : {
				'cap_menu'      : 'BASE_DOMAINS',
				'cap_read'      : 'DOMAINS_LIST',
				'cap_create'    : 'DOMAINS_CREATE',
				'cap_edit'      : 'DOMAINS_EDIT',
				'cap_delete'    : 'DOMAINS_DELETE',

				'show_in_menu'  : 'modules',
				'menu_name'     : _('Domains'),
				'menu_main'     : True,
				'default_sort'  : ({ 'property': 'name' ,'direction': 'ASC' },),
				'grid_view'     : (
					'domainid',
					MarkupColumn(
						name='name',
						header_string=_('Name'),
						template='{__str__}',
						column_flex=1,
						sortable=True
					),
					'parent',
					MarkupColumn(
						name='state',
						header_string=_('State'),
						template=TemplateObject('netprofile_domains:templates/domain_icons.mak'),
						cell_class='np-nopad',
						column_width=60,
						column_resizable=False
					)
				),
				'grid_hidden'   : ('domainid',),
				'form_view'		: (
					'name', 'parent',
					'enabled', 'public', 'signed',
					'soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum',
					'spf_gen', 'spf_rule', 'spf_errmsg',
					'dkim_name', 'dkim_data', 'dkim_test', 'dkim_subdomains', 'dkim_strict',
					'dmarc_trailer',
					'descr'
				),
				'easy_search'   : ('name', 'descr'),
				'detail_pane'   : ('netprofile_core.views', 'dpane_simple'),

				'create_wizard' : Wizard(
					Step('name', 'parent', 'enabled', 'public', 'signed', 'descr', title=_('Domain info')),
					Step('soa_refresh', 'soa_retry', 'soa_expire', 'soa_minimum', 'dkim_name', 'dkim_data', title=_('DNS options')),
					title=_('Add new domain')
				)
			}
		}
	)
	id = Column(
		'domainid',
		UInt32(),
		Sequence('domains_def_domainid_seq'),
		Comment('Domain ID'),
		primary_key=True,
		nullable=False,
		info={
			'header_string' : _('ID')
		}
	)
	parent_id = Column(
		'parentid',
		UInt32(),
		ForeignKey('domains_def.domainid', name='domains_def_fk_parentid', onupdate='CASCADE'),
		Comment('Parent domain ID'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Parent'),
			'column_flex'   : 1
		}
	)
	name = Column(
		Unicode(255),
		Comment('Domain name'),
		nullable=False,
		info={
			'header_string' : _('Name')
		}
	)
	enabled = Column(
		NPBoolean(),
		Comment('Is domain enabled?'),
		nullable=False,
		default=True,
		server_default=npbool(True),
		info={
			'header_string' : _('Enabled')
		}
	)
	public = Column(
		NPBoolean(),
		Comment('Is domain visible to outsiders?'),
		nullable=False,
		default=False,
		server_default=npbool(False),
		info={
			'header_string' : _('Public')
		}
	)
	signed = Column(
		NPBoolean(),
		Comment('Needs DNSSEC signing?'),
		nullable=False,
		default=False,
		server_default=npbool(False),
		info={
			'header_string' : _('Signed')
		}
	)
	soa_refresh = Column(
		UInt32(),
		Comment('SOA refresh field'),
		nullable=False,
		default=3600,
		info={
			'header_string' : _('SOA Refresh')
		}
	)
	soa_retry = Column(
		UInt32(),
		Comment('SOA retry field'),
		nullable=False,
		default=300,
		info={
			'header_string' : _('SOA Retry')
		}
	)
	soa_expire = Column(
		UInt32(),
		Comment('SOA expire field'),
		nullable=False,
		default=1814400,
		info={
			'header_string' : _('SOA Expire')
		}
	)
	soa_minimum = Column(
		UInt32(),
		Comment('SOA minimum field'),
		nullable=False,
		default=3600,
		info={
			'header_string' : _('SOA Minimum')
		}
	)
	serial_date = Column(
		Date(),
		Comment('Domain serial date'),
		nullable=False,
		info={
			'header_string' : _('Serial Date'),
			'secret_value'  : True
		}
	)
	serial_revision = Column(
		'serial_rev',
		UInt8(),
		Comment('Domain serial revision'),
		nullable=False,
		default=1,
		info={
			'header_string' : _('Serial Revision'),
			'secret_value'  : True
		}
	)
	dkim_name = Column(
		ASCIIString(255),
		Comment('DKIM public key name'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('DKIM Name')
		}
	)
	dkim_data = Column(
		ASCIIText(),
		Comment('DKIM public key body'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('DKIM Key')
		}
	)
	dkim_test = Column(
		NPBoolean(),
		Comment('Use DKIM in test mode'),
		nullable=False,
		default=False,
		server_default=npbool(False),
		info={
			'header_string' : _('DKIM Test')
		}
	)
	dkim_subdomains = Column(
		NPBoolean(),
		Comment('Propagate DKIM rules to subdomains'),
		nullable=False,
		default=False,
		server_default=npbool(False),
		info={
			'header_string' : _('DKIM in Subdomains')
		}
	)
	dkim_strict = Column(
		NPBoolean(),
		Comment('Use DKIM strict check and discard'),
		nullable=False,
		default=False,
		server_default=npbool(False),
		info={
			'header_string' : _('DKIM Strict')
		}
	)
	spf_generate = Column(
		'spf_gen',
		NPBoolean(),
		Comment('Generate SPF record'),
		nullable=False,
		default=True,
		server_default=npbool(True),
		info={
			'header_string' : _('Use SPF')
		}
	)
	spf_rule = Column(
		ASCIIText(),
		Comment('Custom SPF rule'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Custom SPF Rule')
		}
	)
	spf_error_message = Column(
		'spf_errmsg',
		UnicodeText(),
		Comment('Custom SPF error explanation string'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('SPF Error')
		}
	)
	dmarc_trailer = Column(
		ASCIIString(255),
		Comment('DMARC record trailer'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('DMARC Trailer')
		}
	)
	description = Column(
		'descr',
		UnicodeText(),
		Comment('Domain description'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Description')
		}
	)

	children = relationship(
		'Domain',
		backref=backref('parent', remote_side=[id])
	)

	@property
	def serial(self):
		if not self.serial_date:
			return str(self.serial_revision % 100)
		return '%s%02d' % (
			self.serial_date.strftime('%Y%m%d'),
			(self.serial_revision % 100)
		)

	def __str__(self):
		if self.parent:
			return '%s.%s' % (
				str(self.name),
				str(self.parent)
			)
		return str(self.name)

	@classmethod
	def resolve(cls, name, domain_aliases=True):
		name = name.strip('.')
		sess = DBSession()
		candidates = [(None, domain_candidates(name), None)]

		while len(candidates) > 0:
			old_candidates = candidates
			candidates = []
			domain_cond = []
			da_cond = []
			for domain, names, suffix in old_candidates:
				if domain is None or isinstance(domain, Domain):
					domain_cond.append(and_(
						Domain.parent_id == (domain.id if domain else None),
						Domain.name.in_(names)
					))
				if not domain_aliases:
					continue
				if domain is None or isinstance(domain, DomainAlias):
					da_cond.append(and_(
						DomainAlias.parent_id == (domain.id if domain else None),
						DomainAlias.name.in_(names)
					))
			if len(domain_cond) > 0:
				for domain in sess.query(Domain).filter(or_(*domain_cond)):
					if suffix is None:
						domain_name = str(domain)
					else:
						domain_name = '.'.join((domain.name, suffix))
					if name == domain_name:
						return domain
					offset = name.find('.' + domain_name)
					if offset > 0:
						left_part = name[:offset]
						candidates.append((domain, domain_candidates(left_part), domain_name))
			if domain_aliases and len(da_cond) > 0:
				for da in sess.query(DomainAlias).filter(or_(*da_cond)):
					if suffix is None:
						domain_name = str(da)
					else:
						domain_name = '.'.join((da.name, suffix))
					if name == domain_name:
						return da.domain
					offset = name.find('.' + domain_name)
					if offset > 0:
						left_part = name[:offset]
						dc = domain_candidates(left_part)
						candidates.extend((
							(da, dc, domain_name),
							(da.domain, dc, domain_name)
						))
Example #10
0
class AccessEntity(Entity):
	"""
	Access entity object.
	"""
	DN_ATTR = 'uid'
	__tablename__ = 'entities_access'
	__table_args__ = (
		Comment('Access entities'),
		Index('entities_access_i_stashid', 'stashid'),
		Index('entities_access_i_rateid', 'rateid'),
		Index('entities_access_i_aliasid', 'aliasid'),
		Index('entities_access_i_ipaddrid', 'ipaddrid'),
		Index('entities_access_i_ip6addrid', 'ip6addrid'),
		Index('entities_access_i_nextrateid', 'nextrateid'),
		Trigger('before', 'insert', 't_entities_access_bi'),
		Trigger('before', 'update', 't_entities_access_bu'),
		Trigger('after', 'update', 't_entities_access_au'),
		Trigger('after', 'delete', 't_entities_access_ad'),
		{
			'mysql_engine'  : 'InnoDB',
			'mysql_charset' : 'utf8',
			'info'          : {
				'cap_menu'     : 'BASE_ENTITIES',
				'cap_read'     : 'ENTITIES_LIST',
				'cap_create'   : 'ENTITIES_CREATE',
				'cap_edit'     : 'ENTITIES_EDIT',
				'cap_delete'   : 'ENTITIES_DELETE',

				'show_in_menu' : 'modules',
				'menu_name'    : _('Access Entities'),
				'menu_parent'  : 'entities',
				'default_sort' : ({ 'property': 'nick' ,'direction': 'ASC' },),
				'grid_view'    : (
					MarkupColumn(
						name='icon',
						header_string='&nbsp;',
						help_text=_('Entity icon'),
						column_width=22,
						column_name=_('Icon'),
						column_resizable=False,
						cell_class='np-nopad',
						template='<img class="np-block-img" src="{grid_icon}" />'
					),
					'entityid',
					'nick', 'stash', 'rate'
				),
				'grid_hidden'  : ('entityid',),
				'form_view'    : (
					'nick', 'parent', 'state', 'flags',
					'password', 'stash', 'rate', 'next_rate', #'alias_of',
					'ipv4_address', 'ipv6_address',
					'ut_ingress', 'ut_egress', 'u_sec',
					'qpend', 'access_state',
					'pol_ingress', 'pol_egress',
					'bcheck', 'pcheck',
					'descr'
				),
				'easy_search'  : ('nick',),
				'extra_data'    : ('grid_icon',),
				'detail_pane'  : ('netprofile_core.views', 'dpane_simple'),
				'create_wizard' : Wizard(
					Step(
						'nick', 'parent', 'state', 
						'flags', 'descr',
						id='generic', title=_('Generic entity properties'),
					),
					Step(
						'password', 'stash', 'rate',
						id='ent_access1', title=_('Access entity properties'),
					),
					title=_('Add new access entity'), validator='CreateAccessEntity'
				)
			}
		}
	)
	__mapper_args__ = {
		'polymorphic_identity' : 5
	}
	id = Column(
		'entityid',
		UInt32(),
		ForeignKey('entities_def.entityid', name='entities_access_fk_entityid', ondelete='CASCADE', onupdate='CASCADE'),
		Comment('Entity ID'),
		primary_key=True,
		nullable=False,
		info={
			'header_string' : _('ID')
		}
	)
	password = Column(
		Unicode(255),
		Comment('Cleartext password'),
		nullable=False,
		info={
			'header_string' : _('Password'),
			'secret_value'  : True,
			'editor_xtype'  : 'passwordfield'
		}
	)
	stash_id = Column(
		'stashid',
		UInt32(),
		ForeignKey('stashes_def.stashid', name='entities_access_fk_stashid', onupdate='CASCADE'),
		Comment('Used stash ID'),
		nullable=False,
		info={
			'header_string' : _('Stash'),
			'column_flex'   : 3
		}
	)
	rate_id = Column(
		'rateid',
		UInt32(),
		ForeignKey('rates_def.rateid', name='entities_access_fk_rateid', onupdate='CASCADE'),
		Comment('Used rate ID'),
		nullable=False,
		info={
			'header_string' : _('Rate'),
			'filter_type'   : 'nplist',
			'column_flex'   : 2
		}
	)
	alias_of_id = Column(
		'aliasid',
		UInt32(),
		ForeignKey('entities_access.entityid', name='entities_access_fk_aliasid', ondelete='CASCADE', onupdate='CASCADE'),
		Comment('Aliased access entity ID'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Alias Of'),
			'filter_type'   : 'none'
		}
	)
	next_rate_id = Column(
		'nextrateid',
		UInt32(),
		ForeignKey('rates_def.rateid', name='entities_access_fk_nextrateid', ondelete='SET NULL', onupdate='CASCADE'),
		Comment('Next rate ID'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Next Rate'),
			'filter_type'   : 'nplist'
		}
	)
	ipv4_address_id = Column(
		'ipaddrid',
		UInt32(),
		ForeignKey('ipaddr_def.ipaddrid', name='entities_access_fk_ipaddrid', ondelete='SET NULL', onupdate='CASCADE'),
		Comment('IPv4 address ID'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('IPv4 Address')
		}
	)
	ipv6_address_id = Column(
		'ip6addrid',
		UInt64(),
		ForeignKey('ip6addr_def.ip6addrid', name='entities_access_fk_ip6addrid', ondelete='SET NULL', onupdate='CASCADE'),
		Comment('IPv6 address ID'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('IPv6 Address')
		}
	)
	used_traffic_ingress = Column(
		'ut_ingress',
		Traffic(),
		Comment('Used ingress traffic'),
		nullable=False,
		default=0,
		server_default=text('0'),
		info={
			'header_string' : _('Used Ingress'),
			'read_only'     : True
		}
	)
	used_traffic_egress = Column(
		'ut_egress',
		Traffic(),
		Comment('Used egress traffic'),
		nullable=False,
		default=0,
		server_default=text('0'),
		info={
			'header_string' : _('Used Egress'),
			'read_only'     : True
		}
	)
	used_seconds = Column(
		'u_sec',
		UInt32(),
		Comment('Used seconds'),
		nullable=False,
		default=0,
		server_default=text('0'),
		info={
			'header_string' : _('Used Seconds'),
			'read_only'     : True
		}
	)
	quota_period_end = Column(
		'qpend',
		TIMESTAMP(),
		Comment('End of quota period'),
		nullable=True,
		default=None,
		server_default=FetchedValue(),
		info={
			'header_string' : _('Ends'),
			'read_only'     : True
		}
	)
	access_state = Column(
		'state',
		UInt8(),
		Comment('Access code'),
		nullable=False,
		default=0,
		server_default=text('0'),
		info={
			'header_string' : _('Access Code'),
			'choices'       : AccessState,
			'write_cap'     : 'ENTITIES_ACCOUNTSTATE_EDIT'
		}
	)
	policy_ingress = Column(
		'pol_ingress',
		ASCIIString(255),
		Comment('Ingress traffic policy'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Ingress Policy')
		}
	)
	policy_egress = Column(
		'pol_egress',
		ASCIIString(255),
		Comment('Egress traffic policy'),
		nullable=True,
		default=None,
		server_default=text('NULL'),
		info={
			'header_string' : _('Egress Policy')
		}
	)
	check_block_state = Column(
		'bcheck',
		NPBoolean(),
		Comment('Check block state'),
		nullable=False,
		default=False,
		server_default=npbool(False),
		info={
			'header_string' : _('Check Blocks')
		}
	)
	check_paid_services = Column(
		'pcheck',
		NPBoolean(),
		Comment('Check paid services'),
		nullable=False,
		default=False,
		server_default=npbool(False),
		info={
			'header_string' : _('Check Services')
		}
	)

	stash = relationship(
		'Stash',
		innerjoin=True,
		backref='access_entities'
	)
	rate = relationship(
		'Rate',
		innerjoin=True,
		foreign_keys=rate_id,
		backref='access_entities'
	)
	next_rate = relationship(
		'Rate',
		foreign_keys=next_rate_id,
		backref=backref(
			'pending_access_entities',
			passive_deletes=True
		)
	)
	alias_of = relationship(
		'AccessEntity',
		foreign_keys=alias_of_id,
		remote_side=[id],
		backref='aliases'
	)
	ipv4_address = relationship(
		'IPv4Address',
		backref=backref(
			'access_entities',
			passive_deletes=True
		)
	)
	ipv6_address = relationship(
		'IPv6Address',
		backref=backref(
			'access_entities',
			passive_deletes=True
		)
	)
	blocks = relationship(
		'AccessBlock',
		backref=backref('entity', innerjoin=True),
		cascade='all, delete-orphan',
		passive_deletes=True
	)

	def data(self, req):
		ret = super(AccessEntity, self).data

		if self.rate:
			ret['rate'] = str(self.rate)
		if self.next_rate:
			ret['nextrate'] = str(self.next_rate)
		if self.quota_period_end:
			ret['qpend'] = format_datetime(self.quota_period_end, locale=req.current_locale)

		ret['accessstate'] = self.access_state_string(req)
		if self.access_state == AccessState.ok.value:
			ret['accessimg'] = 'ok'
		elif self.access_state == AccessState.block_auto.value:
			ret['accessimg'] = 'stop'
		elif self.access_state == AccessState.block_manual.value:
			ret['accessimg'] = 'manual'
		else:
			ret['accessimg'] = 'misc'

		return ret

	def access_state_string(self, req):
		if self.access_state is None:
			return None
		return req.localizer.translate(AccessState.from_string(self.access_state).description)

	def grid_icon(self, req):
		return req.static_url('netprofile_access:static/img/access.png')