22# author: 63720750@qq.com
33# website: http://appnxt.com
44
5+ import odoo
56from odoo import api , http , SUPERUSER_ID , _
6- from odoo .modules .registry import RegistryManager
77from odoo .http import Root
88import werkzeug
99import base64
1010import time
1111import json
1212import logging
13+ import pdb
1314
1415_logger = logging .getLogger (__name__ )
1516
1920# Odoo Nxt Restful API Method.
2021#
2122###############################
23+ import _ast
24+ import re
25+ import csv
26+ try : # Python 3
27+ import configparser
28+ from threading import current_thread
29+ from xmlrpc .client import Fault , ServerProxy , MININT , MAXINT
30+ PY2 = False
31+ except ImportError : # Python 2
32+ import ConfigParser as configparser
33+ from threading import currentThread as current_thread
34+ from xmlrpclib import Fault , ServerProxy , MININT , MAXINT
35+ PY2 = True
36+
37+ DOMAIN_OPERATORS = frozenset ('!|&' )
38+ _term_re = re .compile (
39+ '([\w._]+)\s*' '(=(?:like|ilike|\?)|[<>]=?|!?=(?!=)'
40+ '|(?<= )(?:like|ilike|in|not like|not ilike|not in|child_of))' '\s*(.*)' )
41+ # Simplified ast.literal_eval which does not parse operators
42+ def _convert (node , _consts = {'None' : None , 'True' : True , 'False' : False }):
43+ if isinstance (node , _ast .Str ):
44+ return node .s
45+ if isinstance (node , _ast .Num ):
46+ return node .n
47+ if isinstance (node , _ast .Tuple ):
48+ return tuple (map (_convert , node .elts ))
49+ if isinstance (node , _ast .List ):
50+ return list (map (_convert , node .elts ))
51+ if isinstance (node , _ast .Dict ):
52+ return dict ([(_convert (k ), _convert (v ))
53+ for (k , v ) in zip (node .keys , node .values )])
54+ if hasattr (node , 'value' ) and str (node .value ) in _consts :
55+ return node .value # Python 3.4+
56+ if isinstance (node , _ast .Name ) and node .id in _consts :
57+ return _consts [node .id ] # Python <= 3.3
58+ raise ValueError ('malformed or disallowed expression' )
59+
60+ if PY2 :
61+ int_types = int , long
62+
63+ class _DictWriter (csv .DictWriter ):
64+ """Unicode CSV Writer, which encodes output to UTF-8."""
65+
66+ def writeheader (self ):
67+ # Method 'writeheader' does not exist in Python 2.6
68+ header = dict (zip (self .fieldnames , self .fieldnames ))
69+ self .writerow (header )
70+
71+ def _dict_to_list (self , rowdict ):
72+ rowlst = csv .DictWriter ._dict_to_list (self , rowdict )
73+ return [cell .encode ('utf-8' ) if hasattr (cell , 'encode' ) else cell
74+ for cell in rowlst ]
75+ else : # Python 3
76+ basestring = str
77+ int_types = int
78+ _DictWriter = csv .DictWriter
79+
80+ def literal_eval (expression , _octal_digits = frozenset ('01234567' )):
81+ node = compile (expression , '<unknown>' , 'eval' , _ast .PyCF_ONLY_AST )
82+ if expression [:1 ] == '0' and expression [1 :2 ] in _octal_digits :
83+ raise SyntaxError ('unsupported octal notation' )
84+ value = _convert (node .body )
85+ if isinstance (value , int_types ) and not MININT <= value <= MAXINT :
86+ raise ValueError ('overflow, int exceeds XML-RPC limits' )
87+ return value
88+
89+ def searchargs (params , kwargs = None , context = None ):
90+ """Compute the 'search' parameters."""
91+
92+ if not params :
93+ return ([],)
94+ domain = params [0 ]
95+ if not isinstance (domain , list ):
96+ return params
97+ for (idx , term ) in enumerate (domain ):
98+ if isinstance (term , basestring ) and term not in DOMAIN_OPERATORS :
99+ m = _term_re .match (term .strip ())
100+ if not m :
101+ raise ValueError ('Cannot parse term %r' % term )
102+ (field , operator , value ) = m .groups ()
103+ try :
104+ value = literal_eval (value )
105+ except Exception :
106+ # Interpret the value as a string
107+ pass
108+ domain [idx ] = (field , operator , value )
109+ return domain
110+
111+ def issearchdomain (arg ):
112+ """Check if the argument is a search domain.
113+
114+ Examples:
115+ - ``[('name', '=', 'mushroom'), ('state', '!=', 'draft')]``
116+ - ``['name = mushroom', 'state != draft']``
117+ - ``[]``
118+ """
119+ return isinstance (arg , list ) and not (arg and (
120+ # Not a list of ids: [1, 2, 3]
121+ isinstance (arg [0 ], int_types ) or
122+ # Not a list of ids as str: ['1', '2', '3']
123+ (isinstance (arg [0 ], basestring ) and arg [0 ].isdigit ())))
22124
23125def no_token ():
24126 rp = {'result' : '' ,'success' : False ,'message' :'invalid token!' }
25127 return json_response (rp )
26128
27129def json_response (rp ):
28130 headers = {"Access-Control-Allow-Origin" : "*" }
29- return werkzeug .wrappers .Response (json .dumps (rp ,ensure_ascii = False ), mimetype = 'application/json' ,headers = headers )
131+ return werkzeug .wrappers .Response (json .dumps (rp ,ensure_ascii = False ), mimetype = 'application/json' ,headers = headers )
30132
31133def authenticate (token ):
32134 try :
33135 a = 4 - len (token ) % 4
34136 if a != 0 :
35137 token += '==' if a == 2 else '='
36- SERVER ,db ,login ,uid ,ts = base64 .urlsafe_b64decode (str (token )).split (',' )
138+ SERVER ,db ,login ,uid ,ts = base64 .urlsafe_b64decode (str (token ). encode ()). decode ( ).split (',' )
37139 if int (ts ) + 60 * 60 * 24 * 7 * 10 < time .time ():
38140 return False
39- registry = RegistryManager .get (db )
40- cr = registry .cursor ()
141+ # todo verify
142+ # registry = RegistryManager.get(db)
143+ odoo .registry (db ).check_signaling ()
144+ cr = odoo .registry (db ).cursor ()
41145 env = api .Environment (cr , int (uid ), {})
42- except Exception , e :
146+ except Exception as e :
43147 return str (e )
44148 return env
45149
46150class NxtRestfulApi (http .Controller ):
47151 @http .route ([
48152 '/api/v1.0/get_token' ,
49153 ], type = 'http' , auth = "none" , csrf = False , methods = ['POST' ,'GET' ])
50- def get_token (self ,serv = 'http://d10.appnxt.com' , a = None , s = 'admin' , d = 'd10' , sid = None , success = True , message = '' ,** kw ):
154+ def get_token (self ,serv = 'http://d10.appnxt.com' , login = None , password = 'admin' , db = 'd10' , sid = None , success = True , message = '' ,** kw ):
51155 """ service, app(user/login),secret(password) """
52156 try :
53- uid = http .request .session .authenticate (d , a , s )
54- except Exception , e :
157+ uid = http .request .session .authenticate (db , login , password )
158+ except Exception as e :
55159 rp = {'token' : '' ,'success' :False ,'message' :str (e )}
56160 return json_response (rp )
57161 if not uid :
58162 rp = {'token' : '' ,'success' :False ,'message' :'you are unauthenticated' }
59163 return json_response (rp )
60- e = base64 .urlsafe_b64encode (',' .join ([serv ,d , a ,str (uid ),str (int (time .time ()))]))
61- rp = {'token' : e .replace ('=' ,'' ),'success' :success ,'message' :message }
164+ e = base64 .urlsafe_b64encode (',' .join ([serv ,db , login ,str (uid ),str (int (time .time ()))]). encode ( ))
165+ rp = {'token' : e .decode (). replace ('=' ,'' ),'success' :success ,'message' :message }
62166 return json_response (rp )
63167
64168 @http .route ([
@@ -77,6 +181,8 @@ def read_objects(self, model=None, ids=None, **kw):
77181 limit = int (kw .get ('per_page' ,'80' ))
78182 order = kw .get ('order' ,'id' )
79183
184+ # domain = searchargs(domain)
185+
80186 if ids :
81187 ids = map (int ,ids .split (',' ))
82188 domain += [('id' ,'in' ,ids )]
@@ -91,9 +197,11 @@ def read_objects(self, model=None, ids=None, **kw):
91197 r [f ] = {'id' : r [f ][0 ],'display_name' :r [f ][1 ]}
92198 else :
93199 r [f ] = ''
200+ if model_fields [f ]['type' ] == 'binary' and r [f ]:
201+ r [f ] = r [f ].decode ()
94202 if ids and result and len (ids ) == 1 :
95203 result = result [0 ]
96- except Exception , e :
204+ except Exception as e :
97205 result ,success ,message = '' ,False ,str (e )
98206 rp = {'success' : success ,'message' :message , 'result' : result ,'total' :count ,'page' : offset + 1 , 'per_page' : limit }
99207 return json_response (rp )
@@ -108,7 +216,7 @@ def create_objects(self, model=None, success=True, message='', **kw):
108216 return no_token ()
109217 try :
110218 result = env [model ].create (kw ).id
111- except Exception , e :
219+ except Exception as e :
112220 result ,success ,message = '' ,False ,str (e )
113221 env .cr .commit ()
114222 env .cr .close ()
@@ -126,7 +234,7 @@ def update_objects(self, model=None, ids=None, success=True, message='', **kw):
126234 ids = map (int ,ids .split (',' ))
127235 try :
128236 result = env [model ].browse (ids ).write (kw )
129- except Exception , e :
237+ except Exception as e :
130238 result ,success ,message = '' ,False ,str (e )
131239 env .cr .commit ()
132240 env .cr .close ()
@@ -144,7 +252,7 @@ def unlink_objects(self, model=None, ids=None, success=True, message='', **kw):
144252 ids = map (int ,ids .split (',' ))
145253 try :
146254 result = env [model ].browse (ids ).unlink ()
147- except Exception , e :
255+ except Exception as e :
148256 result ,success ,message = '' ,False ,str (e )
149257 env .cr .commit ()
150258 env .cr .close ()
@@ -161,7 +269,7 @@ def call_method(self, model=None, method=None, success=True, message='', **kw):
161269 return no_token ()
162270 try :
163271 result = eval ('env[model].' + method )(kw )
164- except Exception , e :
272+ except Exception as e :
165273 result ,success ,message = '' ,False ,str (e )
166274 env .cr .commit ()
167275 env .cr .close ()
0 commit comments