2009-06-29 07:06:01 -05:00
|
|
|
# ------------------------------------------------------------------------------
|
2013-09-18 05:06:07 -05:00
|
|
|
# This file is part of Appy, a framework for building applications in the Python
|
|
|
|
# language. Copyright (C) 2007 Gaetan Delannay
|
|
|
|
|
|
|
|
# Appy is free software; you can redistribute it and/or modify it under the
|
|
|
|
# terms of the GNU General Public License as published by the Free Software
|
|
|
|
# Foundation; either version 3 of the License, or (at your option) any later
|
|
|
|
# version.
|
|
|
|
|
|
|
|
# Appy is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
|
|
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
# You should have received a copy of the GNU General Public License along with
|
|
|
|
# Appy. If not, see <http://www.gnu.org/licenses/>.
|
2009-06-29 07:06:01 -05:00
|
|
|
|
2013-07-08 16:39:16 -05:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
# Import stuff from appy.fields (and from a few other places too).
|
|
|
|
# This way, when an app gets "from appy.gen import *", everything is available.
|
2013-09-18 05:06:07 -05:00
|
|
|
from appy import Object
|
|
|
|
from appy.px import Px
|
2013-08-21 06:54:56 -05:00
|
|
|
from appy.fields import Field
|
2013-07-08 16:39:16 -05:00
|
|
|
from appy.fields.action import Action
|
|
|
|
from appy.fields.boolean import Boolean
|
|
|
|
from appy.fields.computed import Computed
|
|
|
|
from appy.fields.date import Date
|
|
|
|
from appy.fields.file import File
|
|
|
|
from appy.fields.float import Float
|
|
|
|
from appy.fields.info import Info
|
|
|
|
from appy.fields.integer import Integer
|
|
|
|
from appy.fields.list import List
|
|
|
|
from appy.fields.pod import Pod
|
|
|
|
from appy.fields.ref import Ref, autoref
|
|
|
|
from appy.fields.string import String, Selection
|
2013-08-21 06:54:56 -05:00
|
|
|
from appy.fields.search import Search, UiSearch
|
|
|
|
from appy.fields.group import Group, Column
|
|
|
|
from appy.fields.page import Page
|
|
|
|
from appy.fields.phase import Phase
|
2013-09-18 05:06:07 -05:00
|
|
|
from appy.fields.workflow import *
|
2013-07-08 16:39:16 -05:00
|
|
|
from appy.gen.layout import Table
|
2013-09-18 05:06:07 -05:00
|
|
|
from appy.gen.utils import No
|
2010-08-05 11:23:17 -05:00
|
|
|
|
2014-02-26 16:40:27 -06:00
|
|
|
# Make the following classes available here: people may need to monkey-patch
|
|
|
|
# some PXs on thoses classes.
|
|
|
|
from appy.gen.wrappers import AbstractWrapper as BaseObject
|
|
|
|
from appy.gen.wrappers.ToolWrapper import ToolWrapper as BaseTool
|
|
|
|
|
2009-10-20 09:57:00 -05:00
|
|
|
class Import:
|
|
|
|
'''Used for describing the place where to find the data to use for creating
|
|
|
|
an object.'''
|
2010-01-06 11:36:16 -06:00
|
|
|
def __init__(self, path, onElement=None, headers=(), sort=None):
|
2009-10-20 09:57:00 -05:00
|
|
|
self.id = 'import'
|
|
|
|
self.path = path
|
2010-01-06 11:36:16 -06:00
|
|
|
# p_onElement hereafter must be a function (or a static method) that
|
|
|
|
# will be called every time an element to import is found. It takes a
|
|
|
|
# single arg that is the absolute filen name of the file to import,
|
|
|
|
# within p_path. It must return a list of info about the element, or
|
|
|
|
# None if the element must be ignored. The list will be used to display
|
|
|
|
# information about the element in a tabular form.
|
|
|
|
self.onElement = onElement
|
|
|
|
# The following attribute must contain the names of the column headers
|
|
|
|
# of the table that will display elements to import (retrieved from
|
|
|
|
# calls to self.onElement). Every not-None element retrieved from
|
|
|
|
# self.onElement must have the same length as self.headers.
|
|
|
|
self.headers = headers
|
|
|
|
# The following attribute must store a function or static method that
|
|
|
|
# will be used to sort elements to import. It will be called with a
|
|
|
|
# single param containing the list of all not-None elements as retrieved
|
|
|
|
# by calls to self.onElement (but with one additional first element in
|
|
|
|
# every list, which is the absolute file name of the element to import)
|
|
|
|
# and must return a similar, sorted, list.
|
|
|
|
self.sort = sort
|
2009-10-20 09:57:00 -05:00
|
|
|
|
2009-06-29 07:06:01 -05:00
|
|
|
# ------------------------------------------------------------------------------
|
2010-09-02 09:16:08 -05:00
|
|
|
class Model: pass
|
|
|
|
class Tool(Model):
|
[gen] Added param Search.default allowing to define a default Search. The default search, if present, will be triggered when clicking on the main link for a class, instead of the query that collects all instances of this class; appy.gen.Type: removed 3 obsolete params: 'index', 'editDefault' and 'optional'. For achieving the same result than using 'editDefault', one may define 'by hand' an attribute on the Tool for storing the editable default value, and define, on the appropriate field in param 'default', a method that returns the value of the tool attribute; Added Type.defaultForSearch, allowing, for some sub-types, to define a default value when displaying the corresponding widget on the search screen; added a default 'state' field allowing to include workflow state among search criteria in the search screens; removed obsolete test applications.
2012-10-31 07:20:25 -05:00
|
|
|
'''If you want to extend or modify the Tool class, subclass me.'''
|
2010-09-02 09:16:08 -05:00
|
|
|
class User(Model):
|
|
|
|
'''If you want to extend or modify the User class, subclass me.'''
|
2009-06-29 07:06:01 -05:00
|
|
|
|
2013-07-24 08:53:19 -05:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
class LdapConfig:
|
2013-09-06 09:19:56 -05:00
|
|
|
'''Parameters for authenticating users to an LDAP server.'''
|
|
|
|
ldapAttributes = { 'loginAttribute':None, 'emailAttribute':'email',
|
|
|
|
'fullNameAttribute':'title',
|
|
|
|
'firstNameAttribute':'firstName',
|
|
|
|
'lastNameAttribute':'name' }
|
|
|
|
|
2013-09-05 03:42:19 -05:00
|
|
|
def __init__(self):
|
|
|
|
self.server = '' # Name of the LDAP server
|
|
|
|
self.port = None # Port for this server.
|
|
|
|
# Login and password of the technical power user that the Appy
|
|
|
|
# application will use to connect to the LDAP.
|
|
|
|
self.adminLogin = ''
|
|
|
|
self.adminPassword = ''
|
|
|
|
# LDAP attribute to use as login for authenticating users.
|
|
|
|
self.loginAttribute = 'dn' # Can also be "mail", "sAMAccountName", "cn"
|
2013-09-06 09:19:56 -05:00
|
|
|
# LDAP attributes for storing email
|
|
|
|
self.emailAttribute = None
|
|
|
|
# LDAP attribute for storing full name (first + last name)
|
|
|
|
self.fullNameAttribute = None
|
|
|
|
# Alternately, LDAP attributes for storing 1st & last names separately.
|
|
|
|
self.firstNameAttribute = None
|
|
|
|
self.lastNameAttribute = None
|
|
|
|
# LDAP classes defining the users stored in the LDAP.
|
|
|
|
self.userClasses = ('top', 'person')
|
|
|
|
self.baseDn = '' # Base DN where to find users in the LDAP.
|
|
|
|
self.scope = 'SUBTREE' # Scope of the search within self.baseDn
|
2013-09-05 03:42:19 -05:00
|
|
|
|
|
|
|
def getServerUri(self):
|
|
|
|
'''Returns the complete URI for accessing the LDAP, ie
|
|
|
|
"ldap://some.ldap.server:389".'''
|
|
|
|
port = self.port or 389
|
|
|
|
return 'ldap://%s:%d' % (self.server, port)
|
2013-07-24 08:53:19 -05:00
|
|
|
|
2013-09-06 09:19:56 -05:00
|
|
|
def getUserFilterValues(self, login):
|
|
|
|
'''Gets the filter values required to perform a query for finding user
|
|
|
|
corresponding to p_login in the LDAP.'''
|
|
|
|
res = [(self.loginAttribute, login)]
|
|
|
|
for userClass in self.userClasses:
|
|
|
|
res.append( ('objectClass', userClass) )
|
|
|
|
return res
|
|
|
|
|
|
|
|
def getUserAttributes(self):
|
|
|
|
'''Gets the attributes we want to get from the LDAP for characterizing
|
|
|
|
a user.'''
|
2013-09-09 16:14:50 -05:00
|
|
|
res = []
|
2013-09-06 09:19:56 -05:00
|
|
|
for name in self.ldapAttributes.iterkeys():
|
|
|
|
if getattr(self, name):
|
|
|
|
res.append(getattr(self, name))
|
|
|
|
return res
|
|
|
|
|
|
|
|
def getUserParams(self, ldapData):
|
|
|
|
'''Formats the user-related p_ldapData retrieved from the ldap, as a
|
|
|
|
dict of params usable for creating or updating the corresponding
|
|
|
|
Appy user.'''
|
|
|
|
res = {}
|
|
|
|
for name, appyName in self.ldapAttributes.iteritems():
|
|
|
|
if not appyName: continue
|
|
|
|
# Get the name of the attribute as known in the LDAP.
|
|
|
|
ldapName = getattr(self, name)
|
|
|
|
if not ldapName: continue
|
|
|
|
if ldapData.has_key(ldapName) and ldapData[ldapName]:
|
2013-09-09 16:14:50 -05:00
|
|
|
value = ldapData[ldapName]
|
|
|
|
if isinstance(value, list): value = value[0]
|
|
|
|
res[appyName] = value
|
2013-09-06 09:19:56 -05:00
|
|
|
return res
|
|
|
|
|
2009-06-29 07:06:01 -05:00
|
|
|
# ------------------------------------------------------------------------------
|
|
|
|
class Config:
|
|
|
|
'''If you want to specify some configuration parameters for appy.gen and
|
2013-07-24 08:53:19 -05:00
|
|
|
your application, please create a class named "Config" in the __init__.py
|
|
|
|
file of your application and override some of the attributes defined
|
|
|
|
here, ie:
|
|
|
|
|
|
|
|
import appy.gen
|
|
|
|
class Config(appy.gen.Config):
|
|
|
|
langages = ('en', 'fr')
|
|
|
|
'''
|
2014-01-20 09:30:14 -06:00
|
|
|
# What skin to use for the web interface? Appy has 2 skins: the default
|
|
|
|
# one (with a fixed width) and the "wide" skin (takes the whole page width).
|
|
|
|
skin = None # None means: the default one. Could be "wide".
|
2013-07-24 08:53:19 -05:00
|
|
|
# For every language code that you specify in this list, appy.gen will
|
|
|
|
# produce and maintain translation files.
|
|
|
|
languages = ['en']
|
|
|
|
# If languageSelector is True, on every page, a language selector will
|
|
|
|
# allow to switch between languages defined in self.languages. Else,
|
|
|
|
# the browser-defined language will be used for choosing the language
|
|
|
|
# of returned pages.
|
|
|
|
languageSelector = False
|
|
|
|
# People having one of these roles will be able to create instances
|
|
|
|
# of classes defined in your application.
|
2013-08-23 11:57:27 -05:00
|
|
|
defaultCreators = ['Manager']
|
2014-03-03 11:54:21 -06:00
|
|
|
# The "root" classes are those that will get their menu in the user
|
|
|
|
# interface. Put their names in the list below.
|
|
|
|
rootClasses = []
|
2013-07-24 08:53:19 -05:00
|
|
|
# Number of translations for every page on a Translation object
|
|
|
|
translationsPerPage = 30
|
|
|
|
# Language that will be used as a basis for translating to other
|
|
|
|
# languages.
|
|
|
|
sourceLanguage = 'en'
|
|
|
|
# Activate or not the button on home page for asking a new password
|
|
|
|
activateForgotPassword = True
|
|
|
|
# Enable session timeout?
|
|
|
|
enableSessionTimeout = False
|
|
|
|
# If the following field is True, the login/password widget will be
|
|
|
|
# discreet. This is for sites where authentication is not foreseen for
|
|
|
|
# the majority of visitors (just for some administrators).
|
|
|
|
discreetLogin = False
|
|
|
|
# When using Ogone, place an instance of appy.gen.ogone.OgoneConfig in
|
|
|
|
# the field below.
|
|
|
|
ogone = None
|
|
|
|
# When using Google analytics, specify here the Analytics ID
|
|
|
|
googleAnalyticsId = None
|
|
|
|
# Create a group for every global role?
|
|
|
|
groupsForGlobalRoles = False
|
|
|
|
# When using a LDAP for authenticating users, place an instance of class
|
|
|
|
# LdapConfig above in the field below.
|
|
|
|
ldap = None
|
2009-06-29 07:06:01 -05:00
|
|
|
# ------------------------------------------------------------------------------
|