############################################################################## # # Copyright (c) 2004 TINY SPRL. (http://tiny.be) All Rights Reserved. # Fabien Pinckaers # # WARNING: This program as such is intended to be used by professional # programmers who take the whole responsability of assessing all potential # consequences resulting from its eventual inadequacies and bugs # End users who are looking for a ready-to-use solution with commercial # garantees and support are strongly adviced to contract a Free Software # Service Company # # This program 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 2 # of the License, or (at your option) any later version. # # This program 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 this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # ############################################################################## import base64, os, string import netsvc import sql_db, security, ir, tools import logging logging.basicConfig() #TODO: use translation system def _(str): return str class common(netsvc.Service): def __init__(self,name="common"): netsvc.Service.__init__(self,name) self.joinGroup("web-services") self.exportMethod(self.ir_get) self.exportMethod(self.ir_set) self.exportMethod(self.ir_del) # self.exportMethod(self.convert) self.exportMethod(self.about) self.exportMethod(self.login) def ir_set(self, uid, password, keys, args, name, value, replace=True, isobject=False): security.check(uid, password) cr = sql_db.db.cursor() res = ir.ir_set(cr,uid, keys, args, name, value, replace, isobject) cr.commit() cr.close() return res def ir_del(self, uid, password, id): security.check(uid, password) cr = sql_db.db.cursor() res = ir.ir_del(cr,uid, id) cr.commit() cr.close() return res def ir_get(self, uid, password, keys, args=[], meta=None, context={}): security.check(uid, password) cr = sql_db.db.cursor() res = ir.ir_get(cr,uid, keys, args, meta, context) cr.commit() cr.close() return res def convert(self, uid, password): security.check(uid, password) cr = sql_db.db.cursor() cr.execute('delete from ir_values') cr.execute('select * from ir_utils_key_value order by id') result = cr.dictfetchall() cr.commit() cr.close() for r in result: if r['res_id']: args = [('res_id',r['res_id'])] else: args = [] self.ir_set(uid, password, [('action',r['key']),('res_model',r['res_model'])], args, r['name'], r['val_model']+','+str(r['val_id']), replace=False, isobject=True) return True # def key_value_get(self, uid, password, key, limit=1, *args): # security.check(uid, password) # cr = sql_db.db.cursor() # fields = ['res_id', 'res_model', 'arg_int', 'arg_char'] # fields_type = ['%d', '%s', '%d', '%s'] # qu1 = ['key=%s'] # qu2 = [uid, key] # for x in range(len(args)): # if args[x]: # qu1.append(fields[x]+'='+fields_type[x]) # qu2.append(args[x]) # else: # qu1.append(fields[x]+' is null') # qu2.append(limit) # cr.execute('select val_model, val_id, name from ir_utils_key_value where (user_id=%d or user_id is null) and '+string.join(qu1,' and ')+' order by priority desc limit %d', qu2) # d = [] # service = netsvc.LocalService("object_proxy") # res=cr.fetchone() # while res: # values = service.execute(uid, res[0], 'read', [res[1]]) # if len(values): # d.append( values[0] ) # res=cr.fetchone() # cr.close() # if args[0] and not(len(d)): # new_args = list(args) # new_args[0]=False # return self.key_value_get(uid,password, key, limit, *new_args) # return d # # def key_value_set(self, *args): # return True def login(self, login, password): logger = netsvc.Logger() cr = sql_db.db.cursor() #FIXME: this is a temporary fix for the crash on login/password with non ASCII chars. #We should fix this in a better way (ie somewhere else) cr.execute('select id from res_users where login=%s and password=%s', (login.encode('utf-8'), password.encode('utf-8'))) res = cr.fetchone() if res: logger.notifyChannel("web-service", netsvc.LOG_INFO, 'successful login from %s' % (login,)) else: logger.notifyChannel("web-service", netsvc.LOG_INFO, 'bad login or password from %s' % (login,)) cr.close() return (res and res[0]) or False def about(self): return tools.version_string + _(''' Tiny ERP is an ERP+CRM program for small and medium businesses. The whole source code is distributed under the terms of the GNU Public Licence. (c) 2003-TODAY, Fabien Pinckaers - Tiny sprl''') common() class objects_proxy(netsvc.Service): def __init__(self,name="object"): netsvc.Service.__init__(self,name) self.joinGroup('web-services') self.exportMethod(self.execute) self.exportMethod(self.exec_workflow) self.exportMethod(self.obj_list) def exec_workflow(self, uid, passwd, object, method, id): security.check(uid, passwd) service = netsvc.LocalService("object_proxy") res = service.exec_workflow(uid, object, method, id) return res def execute(self, uid, passwd, object, method, *args): security.check(uid, passwd) service = netsvc.LocalService("object_proxy") res = service.execute(uid, object, method, *args) return res def obj_list(self, uid, passwd): security.check(uid, passwd) service = netsvc.LocalService("object_proxy") res = service.obj_list() return res objects_proxy() # # Wizard ID: 1 # - None = end of wizard # # Wizard Type: 'form' # - form # - print # # Wizard datas: {} # TODO: change local request to OSE request/reply pattern # class wizard(netsvc.Service): def __init__(self, name='wizard'): netsvc.Service.__init__(self,name) self.joinGroup('web-services') self.exportMethod(self.execute) self.exportMethod(self.create) self.id = 0 self.wiz_datas = {} self.wiz_name = {} self.wiz_uid = {} def _execute(self, uid, wiz_id, datas, action): self.wiz_datas[wiz_id].update(datas) wiz = netsvc.LocalService('wizard.'+self.wiz_name[wiz_id]) return wiz.execute(uid, self.wiz_datas[wiz_id], action) def create(self, uid, passwd, wiz_name, datas={}): security.check(uid, passwd) self.id += 1 self.wiz_datas[self.id] = {} self.wiz_name[self.id] = wiz_name self.wiz_uid[self.id] = uid return self.id def execute(self, uid, passwd, wiz_id, datas, action='init'): security.check(uid, passwd) if self.wiz_uid[wiz_id] == uid: return self._execute(uid, wiz_id, datas, action) else: raise 'AccessDenied' wizard() # # TODO: set a maximum report number per user to avoid DOS attacks # # Report Status: # unknown -> wait +-> done # +-> abort # class report_spool(netsvc.Service): def __init__(self, name='report'): netsvc.Service.__init__(self,name) self.joinGroup('web-services') self.exportMethod(self.report) self.exportMethod(self.report_get) self.exportMethod(self.report_check) self._reports = {} self._requests = {} self._results = {} def report(self, uid, passwd, object, ids, datas={}, context={}): security.check(uid, passwd) try: obj = self.serviceEndPoint('report.'+object) id = obj.create(uid, ids, datas, context) self._reports[id] = {'uid' : uid, 'obj' : obj} self.processFailure(self._report_fail,id) return id except netsvc.ServiceUnavailable: raise 'ServiceUnavailable' def _report_fail(self, id, *args): fail = self.currentFailure() print fail.details(), fail.error(), fail.description(), fail.origin() def _rep_get_ok(self, id, result, *args): req = self._requests[id] self._results[req] = result del self._requests[id] self.resumeResponse(req) def _rep_get_fail(self, id, error,description,origin,details): req = self._requests[id] del self._requests[id] #fail = self.currentFailure() self.cancelResponse(req, error, description, origin, details) def _rep_sus_check(self, req): result = self._results[req] del self._results[req] return result[0] def _rep_sus(self, req): result = self._results[req] del self._results[req] res={'state':result[0]} if res['state']: if tools.config['reportgz']: import zlib res['result']=base64.encodestring(zlib.compress(result[1])) res['code']='zlib' else: res2 = result[1] if type(result[1])==type(u''): res2 = result[1].encode('latin1','replace') res['result']=base64.encodestring(res2) res['format']=result[2] return res def report_check(self, uid, passwd, report_id, format='normal'): #CHECKME: faudrait pas rajouter un security.check(uid, passwd) ici? value = '' if report_id in self._reports: if self._reports[report_id]['uid'] != uid: raise 'AccessDenied' else: id = self._reports[report_id]['obj'].result() self.processResponse(self._rep_get_ok,id) self.processFailure(self._rep_get_fail,id) self._requests[id] = id self.suspendResponse(self._rep_sus_check) else: raise 'ReportNotFound' def report_get(self, uid, passwd, report_id, format='normal'): #CHECKME: faudrait pas rajouter un security.check(uid, passwd) ici? value = '' if report_id in self._reports: if self._reports[report_id]['uid'] != uid: raise 'AccessDenied' else: id = self._reports[report_id]['obj'].result() self.processResponse(self._rep_get_ok,id) self.processFailure(self._rep_get_fail,id) self._requests[id] = id self.suspendResponse(self._rep_sus) else: raise 'ReportNotFound' report_spool() # vim:noexpandtab