def sec(): pi = cherrypy.request.path_info if pi[-1] == '/': pi_n = pi[:-1] # w/o slash else: pi_n = pi rcr = cpu.get_class_ref() #pyDumps not works here! if pi_n not in grantAccessRefs and not is_static_resource(pi): if cpu.getUserVar('uid') is None: return cpu.goToIndex(mes=_('Сессия утеряна!')) #print "entered pi_n=", pi_n, cpu.getUserVar('granted_system_refs') if rcr not in cpu.getUserVar('granted_system_refs') \ and not (rcr.startswith('/ENGINE/METRICS') and '/ENGINE/METRICS' in cpu.getUserVar('granted_system_refs')) \ and not pi_n.endswith('/exception') and not cpu.getUserVar('is_superadmin'): #print "blocked pi_n=", pi_n return cpu.goToError( _('У Вас нет прав на доступ к ресурсу либо ресурс отсутствует' )) #print "passed pi_n=", pi_n #если отключаем систему, то при каждом запросе смотрим поле ENGINE_SYSTEMS.DISABLED #print "pi_n=", pi_n, "rcr=", rcr if hc.get_disabled() and not pi_n.endswith('/exception'): #если disabled непуст, то смотрим детально sysinfo = si.get_mapped_sysinfo(rcr) if len(sysinfo) and hc.get_disabled(sysinfo['id_system']): return cpu.goToError( _('Подсистема временно недоступна.' ))
def get_th_store(self, thread_id, key, layer_id=None): """Возвращает КОПИИ данных по потоку, слою и ключу внутри слоя. Потокозащищенный метод для использования вне класса. Если thread_id is None, используется текущий поток, если layer_id is None - текущий слой. Если запрошена отсутствующая структура, она создаётся. """ #self.Lock.acquire() #try: # return self._dic(thread_id=thread_id, layer_id=layer_id).get(key) # обезопасиваем чтение данных по ключам другого потока #finally: # self.Lock.release() if layer_id is None: layer_id = cpu.getUserVar('layer_id') if layer_id is None: layer_id = -1 self.Lock.acquire() try: th_all = self._get_th_all(thread_id) try: tss = th_all[layer_id] except KeyError: tss = th_all[layer_id] = {} val_copy = copy.copy(tss.get(key)) #deepcopy не копирует объекты kinterbasdb finally: self.Lock.release() return val_copy
def _dic(self, thread_id=None, layer_id=None): # def _dic(_get_ident=thread.get_ident) make thread.get_ident a local var """Возвращает ссылку на словарик данных, определяемый потоком и слоем ДЛЯ ВНУТРЕННЕГО ИСПОЛЬЗОВАНИЯ (непотокобезопасный) в виде: {'db': {}, 'tr_cnt': {}, 'id_top_system': {}, 'cnt_reconnects': ..., 'in_trans': ..., 'last_sql': ..., 'trans_start': ..., 'trans_end': ...} Методы-писатели, а также читатели данных других потоков обрамоляют его блокировкой. Если thread_id is None, используется текущий поток, если layer_id is None - текущий слой. Если пользователь не авторизовался и запрошен текущий слой - используется слой -1. Если запрошена отсутствующая структура по потоку или слою, она создаётся. при коннектах/реконнектах заполняются th_dic['db'] ={id_top_system1: connect1, id_top_system2: connect2} # словарь открытых потоком соединенией по топ-системам th_dic['tr_cnt'] ={id_top_system1: count1, id_top_system2: count2} # количество транзакций, стартованных потоком с момента последнего коннекта/реконнекта, по базам данных топ-систем th_dic['id_top_system']={id_system1: id_top_system1, id_system2: id_top_system2} # топ-система для каждой подсистемы - храним в каждом потоке, чтоб не защищать блокировками читателей, и в каждом слое, если в будущем можно будет NO_MAP подсистем по слоям th_dic['cnt_reconnects']=cnt_reconnects # к-во реконнектов к базе DBKURS, совершённых данным потоком в данном слое при обработке транзакций заполняются th_dic['in_trans']=0 или 1 - пишут также Direct-ф-ции (по любым базам, кроме DBENGINE) th_dic['last_sql']='select * from ...' - пишут также Direct-ф-ции (по любым базам, кроме DBENGINE) th_dic['trans_start']=time_beg - пишут также Direct-ф-ции (по любым базам, кроме DBENGINE) th_dic['trans_end']=time_end - пишут также Direct-ф-ции (по любым базам, кроме DBENGINE) """ if layer_id is None: layer_id = cpu.getUserVar('layer_id') if layer_id is None: layer_id = -1 th_all = self._get_th_all(thread_id) try: tss = th_all[layer_id] except KeyError: tss = th_all[layer_id] = {} return tss
def index(self, filepath): "корневой метод для маппинга дерева подсистем (нельзя вызывать явно)" path, fname = os.path.split(filepath) # fname= fname.encode('windows-1251') # path= path.encode('windows-1251') # блок безопасности # проверим, что скачивание привязано к сессии (т.е. юзер хотя бы залогинен) uid = getUserVar('uid') if not uid: return goToError(error_code[0] % fname) # теперь проверим, пренадлежит ли файл этой учетной записи # получим uid-префикс из имени файла fuid = self.split_path_to_uid(path) # если он не пустой, но не равен сессионному -валим эксепшн (если же пустой, значит загрузка общая и не привязана к сессии) if fuid and str(uid) != str(fuid): return goToError(error_code[1] % fname) # проверка на доступность файла для скачивания if not os.path.isfile(filepath): return goToError(error_code[2] % fname) return serve_file(filepath, "application/x-download", "attachment")
def saveprofileaddon(self, **kwargs): "сохранение дополнительной информации профиля (кроме темы и паролей)" if self.profileaddon == 1: if cpu.getUserVar('uid') is None: return cpu.goToIndex(mes=_('Сессия утеряна!')) # импорт модуля доп. параметров регистрации from systems.ADDONS.PROFILEADDON.profileaddon import ProfileAddon ProfileAddon = ProfileAddon() return ProfileAddon.saveprofileaddon(**kwargs)
def info(self): "дополнительная информация профиля" if self.profileaddon == 1: if cpu.getUserVar('uid') is None: return cpu.goToIndex(mes=_('Сессия утеряна!')) # импорт модуля доп. параметров регистрации from systems.ADDONS.PROFILEADDON.profileaddon import ProfileAddon ProfileAddon = ProfileAddon() return ProfileAddon.index()
def check_login_uniq(self, login): "проверяет логин на уникальность в БД, не учитывая текущего пользователя" res = 1 fields = {} # resdb = db.dbExec(sql="select * FROM ENGINE_USER_LOGIN_CHECK(?)", # params=(login,), fetch='one', id_system=-1) # if resdb['IS_VALID'] == 0: if not adm.userCheckLoginUnique(login, id_user=cpu.getUserVar('uid')): res = 0 fields = {'name': 'login', 'errmes': adm.errmsgUserExistsLogin} return res, fields
def get_user_systems(uid, higher=None, recurse=1, systems_order=None, spaces_per_level=24, use_layers=None, conEngine=None): u"""Дерево замапленных систем пользователя. Без учета прав его ролей в текущем тарифе организации пользователя, если используются слои, либо с учетом прав его ролей без использования тарифов, если слои не используются. Принимает: :param uid: ID пользователя (если None, используется uid текущего пользователя) :type uid: int :param higher: ID родительской системы, если нужно отфильтровать только какую-то ветку. None - все ветки. :type higher: int :param recurse: рекурсивный поиск дочерних узлов (любое число кроме 0 и None) либо возвращать лишь 1-й уровень вложенности (0, None) :type recurse: int :param systems_order: сортировка систем в дереве: 0 - по полям ORDERBY, SHOW_NAME таблицы ENGINE_SYSTEMS; 1 - по полю SHOW_NAME. None - значение по умолчанию из конфигурационного файла :type systems_order: int :param spaces_per_level: количество пробелов-отступов на 1 уровень :type spaces_per_level: int :param use_layers: использовать ли слои. None - использовать параметр конфигурационого файла. True - использовать слои и тарифы. False - не использовать слои и тарифы (возвращается всё дерево прав, в том числе и прав ролей) :type use_layers: int :param conEngine: объект соединения с БД Engine. Если передан, то доступ к ней происходит в его контексте и без commit'а в конце :type conEngine: объект соединения kinterbasdb Возвращает: Cписок прав, в виде: {'datalist': [{'ID_SYSTEM': ID_SYSTEM, 'HIGHER_OUT': HIGHER_OUT, 'SPACES': SPACES, 'FULL_REF_NAME': FULL_REF_NAME, 'SHOW_NAME': SHOW_NAME, 'LEVEL_OUT': LEVEL_OUT}, ... {'ID_SYSTEM': ID_SYSTEM, 'HIGHER_OUT': HIGHER_OUT, 'SPACES': SPACES, 'FULL_REF_NAME': FULL_REF_NAME, 'SHOW_NAME': SHOW_NAME, 'LEVEL_OUT': LEVEL_OUT}]}, где ID_SYSTEM - ID системы HIGHER_OUT - ID родительской системы SPACES - отступы: html-символы неразрывного пробела в количестве LEVEL_OUT*spaces_per_level FULL_REF_NAME - внутренняя полная ссылка на систему SHOW_NAME - название системы LEVEL_OUT - уровень вложенности, начиная с 0 """ if uid is None: uid = cpu.getUserVar('uid') if systems_order is None: systems_order = cfg.systems_order if use_layers is None: use_layers = layers.layersIsUse() if use_layers: return db.dbExec(sql="""select ID_SYSTEM, HIGHER_OUT, FULL_REF_NAME, FULL_FOLDER_NAME, SHOW_NAME, LEVEL_OUT, LASTDATE, lpad('', %d*level_out, ' ') SPACES from TAR_USER_SYSTEMS_GET(?,?,?,?,?)""" % spaces_per_level, params=[uid, higher, recurse, None, systems_order], fetch='all', id_system=-1, conEngine=conEngine) else: return db.dbExec(sql="""select ID_SYSTEM, HIGHER_OUT, FULL_REF_NAME, FULL_FOLDER_NAME, SHOW_NAME, LEVEL_OUT, lpad('', %d*level_out, ' ') SPACES from ENGINE_USER_GET_SYSTEMS(?,?,?,?,?)""" % spaces_per_level, params=[uid, higher, recurse, None, systems_order], fetch='all', id_system=-1, conEngine=conEngine)
def check_email_uniq(self, email): "проверяет email на уникальность, не учитывая текущего пользователя" res = 1 fields = {} # resdb = db.dbExec(sql="select * FROM ENGINE_USER_EMAIL_CHECK(?)", # params=(email,), fetch='one', id_system=-1) # if resdb['IS_VALID'] == 0: if not adm.userCheckEmailUnique(email, id_user=cpu.getUserVar('uid')): res = 0 fields = {'name': 'email', 'errmes': adm.errmsgUserExistsEmail} # ,'uid' : resdb['ID_USER']} return res, fields
def drawTemplate(templ='index', data=None, draw_wo_login=False, module=None, path='templates'): u"""Возвращает cheetah-обработанное html-представление шаблона. Если в качестве шаблона templ используется строка с его именем, то происходит динамический импорт из пути, указанном в параметре path. При динамическом импорте импортированный файл не включается в sys.modules, что позволяет не рестартовать движок при изменении этого файла, даже если сервер настроен на рестарт при изменении модулей. :param templ: Rласс шаблона или строка - имя файла шаблона (без расширения tmpl) :type templ: str :param data: Передаваемые в шаблон данные :type data: list :param draw_wo_login: прорисовывать ли шаблон для неавторизованных пользователей или переводить на страницу с отказом доступа :type draw_wo_login: bool :param path: Относительный путь импорта. Используется, если templ задан как строка. Подкаталоги разделяются прямым слэшем (/). Если путь начинается на прямой слэш, он считается относительно корневого каталога движка, иначе - относительно каталога текущей системы. Допускаются спецсимволы пути: точка (.) - текущий каталог, две точки (..) - родительский каталог. :type path: str :returns: отрендеренный html-код Пример:: import ch_utils as chu # статический импорт файла index из подкаталога systems/system1/templates корневого каталога движка def static(): from systems.system1.templates.index import index return chu.drawTemplate(templ=index) # динамический импорт файла index из подкаталога templates текущей системы def from_default1(): return chu.drawTemplate() # динамический импорт файла index из подкаталога templates текущей системы (идентичен предыдущему) def from_default2(): index = chu.import_tmpl('index') return chu.drawTemplate(templ=index) # динамический импорт файла main из подкаталога templates/dir1 текущей системы def from_current_system(): return chu.drawTemplate(templ='main', path='templates/dir1') # динамический импорт файла main из подкаталога templates/dir1 родительской системы def from_parent_system(): return chu.drawTemplate(templ='main', path='../templates/dir1') # динамический импорт файла main из подкаталога /systems/ENGINE/ADMINPANEL/templates корневого каталога движка def from_root(): return chu.drawTemplate(templ='main', path='/systems/ENGINE/ADMINPANEL/templates') """ if type(templ) == types.StringType: templ = import_tmpl(tmpl_name=templ, path=path) import cp_utils as cpu if data is None: data = [] if not hasattr(cherrypy, 'session'): return str(templ(searchList=data, filtersLib=filters)) #cherrypy.session.acquire_lock() try: if not cherrypy.session.loaded: cherrypy.session.load() finally: pass #cherrypy.session.release_lock() if cfg.trace_session: print "=" * 52 print "drawTemplate: templ=", templ cpu.printSession() if not draw_wo_login and cpu.getUserVar('uid') is None: return cpu.goToIndex() else: user_init_class = cpu.getSesVar('user_init_class') if user_init_class: for (key, val) in user_init_class.__dict__.items(): data.append({key: val}) if cfg.TEST_MESSAGE: data.append({'test_message': cfg.TEST_MESSAGE}) id_system = si.get_id_system(level=1, none_if_not_found=True) if id_system: if si.systems_params.has_key(id_system): system_folder = si.systems_params[id_system]['system_folder'] data.append({'sp': system_folder}) data.append({'sp_img': system_folder + '/images'}) data.append({'sp_css': system_folder + '/css'}) data.append({'sp_js': system_folder + '/js'}) data.append({'sp_forms': system_folder + '/forms'}) data.append({'sp_reports': system_folder + '/reports'}) data.append({'system_name': si.systems_params[id_system]['system_name']}) data.append({'system_full_ref': si.systems_params[id_system]['system_full_ref']}) data.append({'top_system_name': si.systems_params[id_system]['top_system_name']}) data.append({'top_system_ref': si.systems_params[id_system]['top_system_ref']}) #else: # #для прорисовки шаблона, в котором используется getSesVar для получения локали из ф-ции обработки ошибок data.append({'getSesVar': cpu.getSesVar}) data.append({'eng_img': '/ENGINE/images'}) data.append({'eng_css': '/ENGINE/css'}) data.append({'eng_js': '/ENGINE/js'}) data.append({'eng_forms': '/ENGINE/forms'}) data.append({'eng_reports': '/ENGINE/reports'}) sps_name = {} sps_img = {} sps_css = {} sps_js = {} sps_forms = {} sps_reports = {} for s in si.systems_params.keys(): if s != -1: s_folder = si.systems_params[s]['system_folder'] s_ref = si.systems_params[s]['system_ref'] sps_name[s_ref] = s_folder sps_img[s_ref] = s_folder + '/images' sps_css[s_ref] = s_folder + '/css' sps_js[s_ref] = s_folder + '/js' sps_forms[s_ref] = s_folder + '/forms' sps_reports[s_ref] = s_folder + '/reports' data.append({'sps_name': sps_name}) data.append({'sps_img': sps_img}) data.append({'sps_css': sps_css}) data.append({'sps_js': sps_js}) data.append({'sps_forms': sps_forms}) data.append({'sps_reports': sps_reports}) data.append({'eng_name': si.eng_name}) data.append({'is_terminal': cpu.getSesVar('is_terminal')}) return str(templ(searchList=data, filtersLib=filters))
def getUserVar(self, var): return cpu.getUserVar(var)
def logWrite(code, ext_params=None, level=0): "direct write into log (code required max 20 chars)" def get_params_for_log(): type_caller, self, f, f_cum_name = find_base_caller(level = level + 2) if type_caller == 'b': cls = self.__class__ str_cls = str(cls) id_system = int(self.id_system) #int(self.getIfaceVar('id_system')) #or nested function not in class (self is none), or class is borned not from BasePage system_name = si.systems_params[id_system]['system_name'] f_doc = f.__doc__ elif type_caller in ['f', 'n']: #try: cls = f.__module__ str_cls = "m " + str(f.__module__) id_system = -1 system_name = 'SYSTEM' f_doc = f.__doc__ #except: elif type_caller == 't': cls = None str_cls = None id_system = None system_name = None f_doc = None #print 'Top level' #raise Exception('Класс не порождён от BasePage') else:# type_caller == 'o': cls = None str_cls = None id_system = None system_name = None f_doc = None #print 'Class not borned from BasePage' #raise Exception('Класс не порождён от BasePage') return type_caller == 'b', f_cum_name, cls, str_cls, id_system, system_name, f_doc is_class, f_name, cls, str_cls, id_system, system_name, f_doc = get_params_for_log() res = db.dbExec(sql='select id_system from ENGINE_FIND_SYSTEM_BY_FULL_REF(?)', params=['/LOG'], fetch='one', id_system=-1) if not res: cpu.cherrypylog('system LOG not found') return log_system = res['id_system'] #print is_class #print f_name #try: # print f.__name__ #except: # pass if not f_doc: raise LogException('Doc string of %s %s.%s not found' % (iif(is_class, 'method', 'function'), cls, f_name)) tb_frame = sys._getframe(level+1) #simple args and arg-argument args_new = [] #simple argument for local in tb_frame.f_locals.keys(): vl = tb_frame.f_locals[local] if is_simple_argument(local, tb_frame): args_new.append(format(obj=vl, add_utf_str=True, add_unicode_str=True)) #arg-argument for local in tb_frame.f_locals.keys(): vl = tb_frame.f_locals[local] if is_args(local, tb_frame): args_new.extend(format(obj=vl, add_utf_str=True, add_unicode_str=True)) #kwargs and ext_params kwargs_new = {} for local in tb_frame.f_locals.keys(): vl = tb_frame.f_locals[local] #kwarg-argument or is arg if is_kwargs(local, tb_frame): if ext_params: vlcopy = vl.copy() vlcopy.update(ext_params) kwargs_new = format(obj=vlcopy, add_utf_str=True, add_unicode_str=True) break #only once if kwargs_new == {}: kwargs_new = format(obj=ext_params, add_utf_str=True, add_unicode_str=True) sargs = '' skwargs = '' #args_1251 = format(obj=args_new, add_utf_str=True, add_unicode_str=True) #already in this coding #kwargs_1251 = format(obj=kwargs_new, add_utf_str=True, add_unicode_str=True) #args #del self-links #if is_class or is_nested: if len(args_new): for i in xrange(len(args_new)): if isinstance(args_new[i], BasePage): del args_new[i] break #args for arg in args_new: sargs += '%s, ' % iif(arg is None, 'null', iif(type(arg)==str, decodeXStr('"%s"'%(str(arg).replace('"', '\\"'))), decodeXStr('%s'%(str(arg).replace('"', '\\"'))))) #str() need, else error "AttributeError: 'int' object has no attribute 'replace'" if sargs: sargs = '"args": [%s]' % sargs[:-2] #kwargs for name, val in kwargs_new.items(): skwargs += '%s: %s, ' % (iif(type(name)==str, decodeXStr('"%s"'%(str(name).replace('"', '\\"'))), decodeXStr('%s'%(str(name).replace('"', '\\"')))), iif(val is None, 'null', iif(type(val)==str, decodeXStr('"%s"'%(str(val).replace('"', '\\"'))), decodeXStr('%s'%(str(val).replace('"', '\\"')))))) #str() need, else error "AttributeError: 'int' object has no attribute 'replace'" if skwargs: skwargs = '"kwargs": {%s}' % skwargs[:-2] #sallargs = '; '.join((sargs, skwargs)) #ne katit #sallargs = str(sargs + skwargs).strip() sallargs = sargs if sallargs: if skwargs: sallargs += ', ' + skwargs else: sallargs = skwargs sallargs = '{%s}' % sallargs table_name = logGetTableName(cls) conv_f_doc = convDocString(f_doc) db.dbExec(sql='execute procedure prepare_metadata(?)', params=[table_name], fetch='none', id_system=log_system) db.dbExec(sql='execute procedure log_insert(?,?,?,?,?,?,?,?,?,?)', params=( table_name, id_system, system_name, str_cls, #str(cls), #str(args[0].__class__), #.split('.')[-1], f_name, #f.__name__ для wrapped-функций возвращает имя wrapped-функции code[:20], conv_f_doc, iif(cpu.getUserVar('uid'), cpu.getUserVar('uid'), '-1'), iif(cpu.getUserVar('userfio'), cpu.getUserVar('userfio'), 'SYSTEM'), #cpu.getUserVar('userfio') sallargs ), fetch='none', id_system=log_system)