def get(self, id): """Get all data, getall """ # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(field_inputs_wrap.keys()) requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 # one to many # 1. parsing reqest try: for k, v in field_inputs.items(): field_inputs[k]['required'] = False orgArgs, self.args = GetRequestArgs( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value # print(self.args, 'self.args', resource_fields_wrap) self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[__heads__] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 if not hasattr(g, 'user'): return omitError('CE_NOT_EXIST', 'not login yet'), 400 r = g.user if r is None: return omitError('CE_NOT_EXIST'), 400 # 1.1 check permission if r.id != id: return omitError('CE_UNAUTHORIZED', 'id not match'), 400 # 2. export to user _r = dict((col, getattr(r, col)) for col in r.__table__.columns.keys()) self.args[field_inputs_wrap_head] = _r _resource_fields = resource_fields.copy() _resource_fields_wrap = resource_fields_wrap.copy() for col in resource_fields_wrap: if col not in ['type', 'subtype']: _resource_fields_wrap.pop(col, None) _resource_fields.pop('access_token', None) _resource_fields_wrap[field_inputs_wrap_head] = ( fields.Nested(_resource_fields)) self.args['type'] = "system" self.args['subtype'] = "regist" return marshal(self.args, _resource_fields_wrap), 200
def get(self): """Get all data """ # one to many # 1. parsing reqest try: # FIXME: # when i assign field_inputs['name']['required'] to True, # it could through below error: # ValueError: [name]: (name Valid Error) Missing required parameter # in dataDict # but i have no idea what it happen. if os.environ.get('EVN'): # in unit test field_inputs['name']['required'] = False logger.warning('now we are in unit test mode, turn off'\ ' field_inputs[\'name\'][\'required\']'\ ' but 1st run is ok :(') self.args = GetRequest( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[__heads__] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(grp, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') r = grp.query.order_by(isDesc()) _r = r.all() self.args['total'] = len(_r) if itemsPerPage is not 0: _r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() r = _r # 2. export to user data, field = SerialGroupOutput(r, resource_fields=resource_fields, omitKeys=['id', 'name']) self.args[__heads__] = data _resource_fields_wrap = resource_fields_wrap.copy() _resource_fields_wrap[__heads__] = fields.List(fields.Nested(field)) return marshal(self.args, _resource_fields_wrap), 200
def get(self, id): """Get all data, getall """ # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(field_inputs_wrap.keys()) requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 # one to many # 1. parsing reqest try: for k, v in field_inputs.items(): field_inputs[k]['required'] = False orgArgs, self.args = GetRequestArgs( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value # print(self.args, 'self.args', resource_fields_wrap) self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[__heads__] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 r = obj.query.filter(obj.id == id, obj.isdel == False).scalar() if r is None: return omitError('CE_NOT_EXIST', 'id {} not found'.format(id)), 400 # 2. export to user _r = dict((col, getattr(r, col)) for col in r.__table__.columns.keys()) self.args[field_inputs_wrap_head] = _r _resource_fields = resource_fields.copy() _resource_fields_wrap = resource_fields_wrap.copy() for col in resource_fields_wrap: if col not in ['type', 'subtype']: _resource_fields_wrap.pop(col, None) _resource_fields_wrap[field_inputs_wrap_head] = ( fields.Nested(_resource_fields)) self.args['type'] = "business" self.args['subtype'] = "rate" return marshal(self.args, _resource_fields_wrap), 200
def get(self): # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(__heads__, 'refBy') requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 try: self.args = _reqparse.parse_args() self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[__heads__] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError('CE_INVALID_PARAM', repr(error)), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(obj, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') # .order_by(User.login.desc()) r = obj.query.order_by(isDesc()) if itemsPerPage is 0: r = r.all() else: r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() for _r in r: __r = dict( (col, getattr(_r, col)) for col in _r.__table__.columns.keys()) self.args[__heads__].append(__r) self.args['total'] = len(r) _resource_fields_wrap[__heads__] = {} _resource_fields_wrap[__heads__] = fields.List( fields.Nested(resource_fields)) return marshal(self.args, _resource_fields_wrap), 200
def output(self, key, obj): value = get_value(key if self.attribute is None else self.attribute, obj) if value is None: if self.allow_null: return None elif self.default is not None: return self.default return marshal(value, self.nested)
def output(self, key, data): value = get_value(key if self.attribute is None else self.attribute, data) # we cannot really test for external dict behavior if is_indexable_but_not_string(value) and not isinstance(value, dict): return self.format(value) if value is None: return self.default return [marshal(value, self.container.nested)]
def post(self): logger.debug('request.header: \n%s', request.headers) login = request.headers.get('login') passHash = request.headers.get('passHash') Authentication = request.headers.get('Authentication') if not login or not passHash or not Authentication: return omitError(ErrorMsg=\ 'Not Found: login(%s)/passHash(%s)/Authentication(%s)' % ( login, passHash, Authentication) ), 400 elif ('SAGITTARIUS' not in Authentication): return omitError(ErrorMsg='SAGITTARIUS not in Authentication header(%s)'\ % Authentication), 400 user = Users.get_by_loginpass(login, passHash) if not user: logger.debug("user %s not found with password %s", login, passHash) #return omitError(ErrorMsg='not Authentication ), 401 abort(401) #elif not Users.sign(user.id, login, passHash): # logger.debug("Users.sign fail") # return omitError(ErrorMsg='not Authentication ), 401 else: if user.passHash == "": # no passHash, not use email to login logger.debug( "user %s not found with password %s, use non email login", login, passHash) abort(401) self.args, _resource_fields_wrap = signin(user) # g.user = user # _resource_fields = {} # _resource_fields_wrap = resource_fields_wrap.copy() # for col in resource_fields_wrap: # if col not in ['type', 'subtype']: # _resource_fields_wrap.pop(col, None) # # _resource_fields_wrap[field_inputs_wrap_head] = fields.Nested(resource_fields) # # self.args = {} # self.args[field_inputs_wrap_head] = dict((col, getattr(user, col)) for col in user.__table__.columns.keys()) # #self.args[field_inputs_wrap_head]['sid'] = session['sid'] # token = user.generate_auth_token() # self.args[field_inputs_wrap_head]['access_token'] = token.decode('ascii') # self.args[field_inputs_wrap_head]['clientIp'] = request.environ['REMOTE_ADDR'] # # logger.debug("self.args[field_inputs_wrap_head]: %s", self.args[field_inputs_wrap_head]) # self.args['type'] = "admin" # self.args['subtype'] = "login" return marshal(self.args, _resource_fields_wrap), 200
def get(self, id): """ retreive one record """ r = grp.query.filter(grp.id == id).scalar() if r is None: return omitError('CE_NOT_EXIST', 'id {} not found'.format(id)), 400 data, field = SerialGroupOutput(r, resource_fields=resource_fields, omitKeys=['id', 'name']) return marshal(data, field), 200
def put(self, id): requestArgsSet = set((col) for col in request.args) if not ExtraParamsIsValid(requestArgsSet): return omitError(ErrorMsg=repr(set( (col) for col in request.args))), 400 try: self.dataDict = request.get_json() request.dataDict = self.dataDict[__head__] add_argument(_reqparse, field_inputs) self.args = _reqparse.parse_args() except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) if error == type(BadRequest): return omitError(ErrorMsg='maybe json format error'), 400 return omitError(ErrorMsg='{}'.format(repr(error.args))), 400 try: checkInputIsValid(self.args) except Exception as error: return error.args r = obj.query.filter(obj.id == id).scalar() for k, v in self.args.items(): if v != None: setattr(r, k, v) db.session.add(r) try: db.session.flush() db.session.commit() except Exception as error: db.session.rollback() logger.warning('session commit error(%s)', error) if exc.IntegrityError == type(error): return omitError('CE_NAME_CONFLICT', repr(error)), 400 return omitError(ErrorMsg=repr(error)), 400 self.args[__head__] = {} _resource_fields_wrap = {} _resource_fields_wrap[__head__] = fields.Nested(resource_fields) for col in r.__table__.columns.keys(): self.args[__head__][col] = getattr(r, col) return marshal(self.args, _resource_fields_wrap), 200
def post(self): """Create new """ # 1. parsing reqest try: self.args = GetRequest(__head__, field_inputs) except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 # 2. validate follows spec if db.session.query(grp.id).count() > max: return omitError('CE_EXCEED_LIMIT', 'limit is {}'.format(max)), 400 if len(self.args[__obj__heads__]) > childrenMax: return omitError('CE_EXCEED_LIMIT', 'limit is {}'.format(childrenMax)), 400 # 3. assign request data to orm r = grp() try: r = PrepareGroupORM(r, obj, mapping, __obj__heads__, self.args.items()) except Exception as error: return omitError(ErrorMsg=repr(error)), 400 # 4. commit to save try: db.session.add(r) db.session.flush() db.session.commit() except Exception as error: db.session.rollback() logger.warning('session commit error(%s)', error) if exc.IntegrityError == type(error): return omitError('CE_NAME_CONFLICT', repr(error)), 400 return omitError(ErrorMsg=repr(error)), 400 # 5. return all data to user data, field = SerialGroupOutput(r, resource_fields=resource_fields) return marshal(data, field), 200
def put(self, id): """ update one record """ # 1. parsing reqest try: self.args = GetRequest(__head__, field_inputs) except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 # 2. get orm from db r = grp.query.filter(grp.id == id).scalar() if r is None: return omitError('CE_NOT_EXIST', 'id {} not found'.format(id)), 400 # 3. assign request data to orm try: r = PrepareGroupORM(r, obj, mapping, __obj__heads__, self.args.items()) except Exception as error: return omitError(ErrorMsg=repr(error)), 400 # 4. commit to save try: db.session.merge(r) db.session.flush() db.session.commit() except Exception as error: db.session.rollback() logger.warning('session commit error(%s)', error) if exc.IntegrityError == type(error): return omitError('CE_NAME_CONFLICT', repr(error)), 400 return omitError(ErrorMsg=repr(error)), 400 # 5. return all data to user data, field = SerialGroupOutput(r, resource_fields=resource_fields) return marshal(data, field), 200
def get(self, id): requestArgsSet = set((col) for col in request.args) if not ExtraParamsIsValid(requestArgsSet): return omitError(ErrorMsg=repr(set( (col) for col in request.args))), 400 r = obj.query.filter(obj.id == id).scalar() if r is None: return omitError('CE_NOT_EXIST', 'user id {} not found'.format(id)), 400 self.args = {} self.args[__head__] = {} _resource_fields_wrap = {} _resource_fields_wrap[__head__] = fields.Nested(resource_fields) for col in r.__table__.columns.keys(): self.args[__head__][col] = getattr(r, col) return marshal(self.args, _resource_fields_wrap), 200
def _put(self, id): #task = filter(lambda t: t['id'] == id, admins) #data = request.data #dataDict = json.loads(data) #parser = reqparse.RequestParser() #parser.add_argument('login', required=True, type=str, location=['json', 'form', 'values'], help='Rate cannot be converted') #args = parser.parse_args() #print(data, 'xxx', 'dataDict', self.dataDict, 'xxx', args) #print(self.dataDict, 'xxx') #if len(task) == 0: # abort(404) try: args = _reqparse.parse_args() except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) message['message'] = ' '.join(error.args) return message, 400 #task = {} #print(args, 'xxxx') #r = User.query.filter( # User.id == id).options(lazyload('AdminGroup').first() # one to many r = UsersMAdminGroup.query.filter(UsersMAdminGroup.user_id == id).all() #print(_r.user_obj.login, 'xxxx') #r = User.query.filter( # User.id == id).first() #rr = UsersMAdminGroup.query.filter( # UsersMAdminGroup.user_id == id).all() if len(r) is 0: message['message'] = 'user id {} not found'.format(id) return message, 400 else: for k, v in args.items(): if v != None: if k == 'admingroup': continue #print(k, v, 'v', type(v) is dict, type(v)) setattr(r[0].user_obj, k, v) #data = json.loads(repr(v)) db.session.add(r[0].user_obj) # update foreign table # delete all mapping if args['admingroup']: #print("args['admingroup']", # json.loads(args['admingroup'][1].replace('\'', '"'))) try: for _r in r: # 1. delete all db.session.delete(_r) db.session.flush() for entity in args['admingroup']: # 2. re-add it rr = UsersMAdminGroup() rr.admingroup_id = json.loads( (entity.replace('\'', '"'))).get('id') rr.user_id = id db.session.add(rr) #print(json.loads(args['admingroup'].replace('\'', '"'))) #print(set((col) for col in json.loads(args['admingroup'].replace('\'', '"')).get('id'))) #for admingroup_id in json.loads(args['admingroup'].replace('\'', '"')).get('id') #rr = UsersMAdminGroup() #rr.admingroup_id = admingroup_id #rr.user_id = id #db.session.add(rr) #j = repr(args['admingroup']) #j = re.sub(r"{\s*(\w)", r'{"\1', j) #j = re.sub(r",\s*(\w)", r',"\1', j) #j = re.sub(r"(\w):", r'\1":', j) #admingroup = json.loads(j) #admingroup = json.loads(args['admingroup'].replace('\'', '"')) #admingroup = json.loads(repr(args['admingroup'])) #admingroup = json.loads(('{"id": "1"}')) #print('rr', type(args['admingroup']), type(admingroup), repr(args['admingroup'])) #admingroup_id = admingroup[0].get('id') # JSON requires double quotes for its strings. #admingroup_id = json.loads(args['admingroup'].replace('\'', '"')).get('id') #if admingroup_id: # #print(rr, 'rr', admingroup_id) # if rr is None: # rr = UsersMAdminGroup() # rr.admingroup_id = admingroup_id # rr.user_id = id # db.session.add(rr) # #print(json.loads(repr(args['admingroup'])).get('id'), 'd') # #setattr(rr, 'user_id', json.loads(repr(args['admingroup'])).get('id')) except Exception as error: # for ambiguous #(TypeError, ValueError) as err: logger.debug('impossible that parsing json %s error(%s)', args['admingroup'], error) pass #return message, 400 #db.session.commit() try: db.session.commit() except Exception as error: logger.warning('session commit error(%s)', error) db.session.rollback() return message, 400 #print(dict((k, v['type']) for k,v in field_inputs.items())) # http://stackoverflow.com/questions/7389759/memory-efficient-built-in-sqlalchemy-iterator-generator #args['admingroup'] = dict(('id', getattr(_r,'id')) for _r in rr) #r = UsersMAdminGroup.query.filter(UsersMAdminGroup.user_id == id) \ # .with_entities(UsersMAdminGroup.admingroup_id).all() #r = UsersMAdminGroup.query.filter( # UsersMAdminGroup.user_id == id).with_entities(UsersMAdminGroup.user_id, # UsersMAdminGroup.admingroup_id).all() r = UsersMAdminGroup.query.filter(UsersMAdminGroup.user_id == id).all() for col in r[0].user_obj.__table__.columns.keys(): args[col] = getattr(r[0].user_obj, col) args['admingroup'] = [] for _r in r: args['admingroup'].append({'id': getattr(_r, 'admingroup_id')}) # http://stackoverflow.com/questions/15261149/sqlalchemy-how-is-it-that-a-comma-determines-if-a-query-returns-a-string-or-a-t #for _r, in r: # args['admingroup'].append({'id': _r}) #args['admingroup'].append( \ # dict((col, getattr(_r, col)) # for col in _r.__table__.columns.keys() if col is not 'id')) #print(dict((col, getattr(_r, col)) for col in _r.__table__.columns.keys())) #print(dict((col, getattr(_r, col)) for col in _r.__table__.columns.keys() if col is not 'id')) #return {'task': 'Hello world'}, 201, {'Etag': 'some-opaque-string'} #return message, 200 return marshal(args, resource_fields), 200
def get(self): """Get all data, getall @api {get} /rest/objects/ipaddrs Read IP Addresses @apiVersion 0.0.1 @apiName GetIpAddrs @apiVersion 0.0.1 @apiGroup objects @apiPermission registered user @apiDescription todo validation @apiParam {Number=0, 25, 50, 100} [itemsPerPage=25] items for each request. @apiParam {Number} [page=1] page you want to request from, start with 1. @apiParam {String="name", "description"} [orderBy=name] the items order by column you specified. @apiParam {String="true", "false"} [desc=false] the items order by descending or asceding order. @apiExample Example usage: curl -i http://localhost/rest/objects/ipaddrs?itemsPerPage=50&page=1&orderBy=name&desc=true @apiSuccess {Number} total total items for pagination. @apiSuccess {String} orderBy the items order by column you specified. @apiSuccess {Number} page page you want to request from, start with 1. @apiSuccess {Number} itemsPerPage items for each request. @apiSuccess {String} desc the items order by descending or asceding order. @apiSuccess {Object[]} ipaddrs List of IP Addresses. @apiSuccess {String} ipaddrs.addr1 1st IP Address. @apiSuccess {String} ipaddrs.addr2 2ed IP Address. @apiSuccess {String} ipaddrs.description this items's description. @apiSuccess {Number} ipaddrs.id index in database. @apiSuccess {String} ipaddrs.ipVersion IP Address version. @apiSuccess {String} ipaddrs.name items uniq name for record. @apiSuccess {String} ipaddrs.type IP Address type, the possible values are 'Single', 'Range', 'Subnet'. @apiError CE_INVALID_PARAM invalid parameter @api {get} /rest/objects/ipaddrs @apiErrorExample {json} we use invalid parameter pages curl -i http://localhost/rest/objects/ipaddrs?pages=1 ================================================ HTTP/1.0 400 BAD REQUEST { "errorId": 2001, "message": "{'pages'}" } """ # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(field_inputs_wrap.keys()) requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 # one to many # 1. parsing reqest try: # FIXME: # when i assign field_inputs['name']['required'] to True, # it could through below error: # ValueError: [name]: (name Valid Error) Missing required parameter # in dataDict # but i have no idea what it happen. if os.environ.get('EVN'): # in unit test field_inputs['name']['required'] = False logger.warning('now we are in unit test mode, turn off'\ ' field_inputs[\'name\'][\'required\']'\ ' but 1st run is ok :(') orgArgs, self.args = GetRequestArgs( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value # print(self.args, 'self.args', resource_fields_wrap) self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[__heads__] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(obj, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') r = obj.query.order_by(isDesc()) _r = r.all() self.args['total'] = len(_r) if itemsPerPage is not 0: _r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() r = _r # 2. export to user for _r in r: __r = dict( (col, getattr(_r, col)) for col in _r.__table__.columns.keys()) self.args[__heads__].append(__r) resource_fields_wrap[__heads__] = fields.List( fields.Nested(resource_fields)) return marshal(self.args, resource_fields_wrap), 200
def get(self, id): """ @api {get} /rest/objects/ipaddr/:id get one IP address item. @apiName GetIpAddr @apiVersion 0.0.1 @apiGroup objects @apiPermission registered user @apiDescription todo validation @apiParam {Number} id IP Address item id. @apiExample Example usage: curl -i http://localhost/rest/objects/ipaddr/7 @apiSuccess {Object[]} ipaddrs List of IP Addresses. @apiSuccess {String} ipaddrs.addr1 1st IP Address. @apiSuccess {String} ipaddrs.addr2 2ed IP Address. @apiSuccess {String} ipaddrs.description this items's description. @apiSuccess {Number} ipaddrs.id index in database. @apiSuccess {String} ipaddrs.ipVersion IP Address version. @apiSuccess {String} ipaddrs.name items uniq name for record. @apiSuccess {String} ipaddrs.type IP Address type, the possible values are 'Single', 'Range', 'Subnet'. @apiError CE_INVALID_PARAM invalid parameter @api {get} /rest/objects/ipaddr/:id @apiErrorExample {json} we use invalid parameter pages curl -X GET -H "mTag: xx" -H "Content-Type:application/json" -d "${BODY}" http://localhost/rest/objects/ipaddr/7?pages=1 ================================================ HTTP/1.0 400 BAD REQUEST { "errorId": 2001, "message": "{'pages'}" } @apiError CE_NOT_EXIST item not found @api {get} /rest/objects/ipaddr/:id @apiErrorExample {json} we use not exist id curl -X GET -H "mTag: xx" -H "Content-Type:application/json" -d "${BODY}" http://localhost/rest/objects/ipaddr/17 ================================================ HTTP/1.0 400 BAD REQUEST { "errorId": 2003, "message": "id 17 not found" } """ requestArgsSet = set((col) for col in request.args) if not ExtraParamsIsValid(requestArgsSet): return omitError(ErrorMsg=repr(set( (col) for col in request.args))), 400 r = obj.query.filter(obj.id == id).scalar() if r is None: return omitError('CE_NOT_EXIST', 'id {} not found'.format(id)), 400 self.args = {} self.args[__head__] = {} _resource_fields_wrap = {} _resource_fields_wrap[__head__] = fields.Nested(resource_fields) for col in r.__table__.columns.keys(): self.args[__head__][col] = getattr(r, col) return marshal(self.args, _resource_fields_wrap), 200
def post(self): try: self.dataDict = request.get_json() request.dataDict = self.dataDict[__head__] add_argument(_reqparse, field_inputs) args = _reqparse.parse_args() except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) if error == type(BadRequest): return omitError(ErrorMsg='maybe json format error'), 400 return omitError(ErrorMsg='{}'.format(error.args)), 400 if db.session.query(obj.id).count() > limit['max']: return omitError('CE_EXCEED_LIMIT', 'limit is {}'.format(limit['max'])), 400 try: # now we only support IPv4/IPv6 args['addr1'] = inputs.is_ipv4_ipv6(args['addr1'], argument=args['ipVersion']) except socket.error as error: # Not legal logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError( 'CE_INVALID_PARAM', '`{}/{}`: {}'.format(args['addr1'], args['ipVersion'], error.args)), 400 ip = args['addr1'] ver = args['ipVersion'] pre = args['addr2'] try: if args['type'] == 'Single': # TODO: maybe we limit that could not pass anything in attribute 'addr2' pass elif args['type'] == 'Range': # do the same as below pre = inputs.is_ipv4_ipv6(pre, argument=ver) # legal elif args['type'] == 'Subnet': # do the same as below if 'IPv4' == ver: #NOTICE: maybe correct user's input? try: ip = inputs.is_cidr(ip, argument=pre) except Exception as error: pre = inputs.is_netmask(pre) elif 'IPv6' == ver: pre = inputs.is_ipv6_prefix(ip, argument=pre) # legal except Exception as error: # Not legal logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError('CE_INVALID_PARAM', '`{}/{}({})`: {}'.\ format(ip, pre, ver, error.args)), 400 r = obj() for k, v in args.items(): if v != None: setattr(r, k, v) db.session.add(r) try: db.session.flush() db.session.commit() except Exception as error: db.session.rollback() logger.warning('session commit error(%s)', error) if exc.IntegrityError == type(error): return omitError('CE_NAME_CONFLICT', repr(error)), 400 return omitError(ErrorMsg=repr(error)), 400 # get id immediately after call commit for col in r.__table__.columns.keys(): args[col] = getattr(r, col) args[__head__] = args _resource_fields = {} _resource_fields[__head__] = fields.Nested(resource_fields) return marshal(args, _resource_fields), 200
def get(self): """Get all data, getall @api {get} /rest/customer/businesses list business @apiName GetAllCustomerBusinesses @apiVersion 0.0.3 @apiGroup business @apiPermission registered user @apiDescription modified: change category type from string to number.<br/> modified: add name attribute.<br /> modified: change deal type from string to number.<br/> todo validation<br/> query string <br /> todo error / success return code in api <br /> @apiParam {Number=0, 25, 50, 100} [itemsPerPage=25] items for each request. @apiParam {Number} [page=1] page you want to request from, start with 1. @apiParam {String="name", "description"} [orderBy=name] the items order by column you specified. @apiParam {String="true", "false"} [desc=false] the items order by descending or asceding order. @apiExample {curl} Example usage: curl -X GET -H "mTag: xx" -H "Content-Type:application/json" -i http://localhost/rest/customer/businesses?itemsPerPage=50&page=1&orderBy=name&desc=true { "page":1, "type":"business", "orderBy":"name", "desc":0, "total":1, "itemsPerPage":25, "subtype":"list", "data":[ { "lat":120.678, "id":1, "deal":200, "name":"Starbucks Coffee 31", "image_url":"", "long":23.5383, "cat":1, "description":"early Bird Special: Get off." } ] } @apiSuccess {Number} total total items for pagination @apiSuccess {String} orderBy the items order by column you specified @apiSuccess {Number} page page you want to request from, start with 1 @apiSuccess {Number} itemsPerPage items for each request @apiSuccess {String} desc the items order by descending or asceding order @apiSuccess {String} type request's type @apiSuccess {String} subtype request's subtype @apiSuccess {Object} business object of business. @apiSuccess {Number} business.id item's uniq id. @apiSuccess {String} business.name item's name. @apiSuccess {Number} business.cat item's business industry category. @apiSuccess {float} business.lat item's entered latitude. @apiSuccess {float} business.long item's entered longitude. @apiSuccess {String} business.address item's address @apiSuccess {String} business.description item's description. @apiSuccess {Number} business.deal item's deal. @apiSuccess {String} business.image_url items's image url. @apiError CE_INVALID_PARAM invalid parameter HTTP/1.0 400 BAD REQUEST { "errorId": 2001, "message": "{'pages'}" } """ # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(field_inputs_wrap.keys()) requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 # one to many # 1. parsing reqest try: for k, v in field_inputs.items(): field_inputs[k]['required'] = False orgArgs, self.args = GetRequestArgs( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value # print(self.args, 'self.args', resource_fields_wrap) self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[field_inputs_wrap_head] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(obj, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') r = obj.query.filter(obj.isdel == False).order_by(isDesc()) _r = r.all() self.args['total'] = len(_r) if itemsPerPage is not 0: _r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() r = _r # 2. export to user for _r in r: __r = dict( (col, getattr(_r, col)) for col in _r.__table__.columns.keys()) #__r['description'] = getattr(_r.detail, 'description') # (1, 'icon'), (2, 'bg'), (3, 'gallery') ___r = pics.query.filter(pics.business_id == _r.id, pics.type == 1).scalar() __r['image_url'] = getattr(___r, 'path', "") self.args[field_inputs_wrap_head].append(__r) resource_fields_wrap[field_inputs_wrap_head] = fields.List( fields.Nested(resource_fields)) self.args['type'] = "business" self.args['subtype'] = "list" return marshal(self.args, resource_fields_wrap), 200
def get(self, id): """Get all data, getall """ """get pics by business id @api {get} /rest/pic/gallery/:id get pictures list with business id @apiVersion 0.0.5 @apiName ListPicsUnderBusiness @apiGroup business @apiPermission registered user @apiDescription todo certificate with cookies / oauth 2.0<br /> todo long/lat validation<br /> todo metadata for counter of registerd devices<br /> todo error / success return code in api @apiParam {Number} id business id @apiExample {curl} Example usage: curl -X GET -H "mTag: xx" -H "Content-Type:application/json" http://localhost/rest/pic/gallery/1 { "orderBy":"id", "itemsPerPage":25, "subtype":"gallery", "desc":0, "data":[ { "path":"/img/customer/1/BYTPH2_20160618_6615.jpg", "id":5, "width":1024, "height":1365 }, { "path":"/img/customer/1/ZS0LII_10473.jpg", "id":6, "width":1024, "height":1365 }, { "path":"/img/customer/1/G30SLL_20160618_6615.jpg", "id":9, "width":1024, "height":1365 } ], "type":"pic", "total":3, "page":1 } @apiSuccess {Number} total total items in one business @apiSuccess {String} orderBy the items order by column you specified @apiSuccess {Number} page page you want to request from, start with 1 @apiSuccess {Number} itemsPerPage items for each request @apiSuccess {String} type request's type @apiSuccess {String} subtype request's subtype @apiSuccess {Object[]} data object @apiSuccess {Number} data.id image's id @apiSuccess {Number} data.path image's url that you could directly access @apiSuccess {Number} data.height image's height(px) @apiSuccess {Number} data.width image's width(px) """ # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(field_inputs_wrap.keys()) requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 # one to many # 1. parsing reqest try: for k, v in field_inputs.items(): field_inputs[k]['required'] = False orgArgs, self.args = GetRequestArgs( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value # print(self.args, 'self.args', resource_fields_wrap) self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[__heads__] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) #return omitError(ErrorMsg=repr(error)), 400 return omitError('CE_INVALID_PARAM', 'not found'), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(obj, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') # FIXME: use mapping table r = obj.query.filter(obj.type == 3, obj.business_id == id, obj.isdel == False).order_by(isDesc()) _r = r.all() self.args['total'] = len(_r) if itemsPerPage is not 0: _r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() r = _r # 2. export to user self.args[field_inputs_wrap_head] = [] for _r in r: __r = dict( (col, getattr(_r, col)) for col in _r.__table__.columns.keys()) # FIXME: use mapping table if __r['type'] == 3: rest_pic_prefix = os.path.join(REST_PIC_PREFIX, 'customer', str(__r['business_id'])) __r['path'] = os.path.join(rest_pic_prefix, __r['path']) self.args[field_inputs_wrap_head].append(__r) _resource_fields_wrap = resource_fields_wrap.copy() _resource_fields_wrap.pop('gallery_nr', None) _resource_fields_wrap[field_inputs_wrap_head] = fields.List( fields.Nested(resource_fields_post)) self.args['type'] = "pic" self.args['subtype'] = "gallery" return marshal(self.args, _resource_fields_wrap), 200
def get(self, id): """get all devices info by business id @api {get} /rest/pushno/reg/:id registed devices under business id @apiVersion 0.0.4 @apiName GetAllDeviceByBusinessId @apiGroup pushno @apiPermission registered user @apiParam {Number} id business id, you can get from GetAllCustomerBusinesses. @apiDescription todo certificate with cookies / oauth 2.0<br /> todo long/lat validation<br /> todo metadata for counter of registerd devices<br /> todo error / success return code in api @apiExample {curl} Example usage: curl -X GET -H "mTag: xx" -H "Content-Type:application/json" http://localhost/rest/pushno/reg/1 { "orderBy":"user_id", "desc":0, "subtype":"reg", "itemsPerPage":25, "page":1, "data":[ { "dev_id":"eh2AM5l18K8:APA91bFsjAU_FmdkdTeErJ_BRSiz7_Iipi_r12QTscHciTVJmj1gcSK_p9l6BfgYtudntv0Ht7JNiyCe8lS-WdrL8zHOwCdGFdRutEDglPV1I9EeROVbhwVX0rcd_PS_jdCTQZ22inFq", "id":4, "user_id":1, "business_id":1, "type":1 }, { "dev_id":"eh2AM5l18K8:APA91bFsjAU_FmdkdTeErJ_BRSiz7_Iipi_r12QTscHciTVJmj1gcSK_p9l6BfgYtudntv0Ht7JNiyCe8lS-WdrL8zHOwCdGFdRutEDglPV1I9EeROVbhwVX0rcd_PS_jdCTQZ22inFq", "id":5, "user_id":1, "business_id":1, "type":1 }, { "dev_id":"eh2AM5l18K8:APA91bFsjAU_FmdkdTeErJ_BRSiz7_Iipi_r12QTscHciTVJmj1gcSK_p9l6BfgYtudntv0Ht7JNiyCe8lS-WdrL8zHOwCdGFdRutEDglPV1I9EeROVbhwVX0rcd_PS_jdCTQZ22inFq", "id":6, "user_id":1, "business_id":1, "type":1 } ], "total":3, "type":"pushno" } @apiSuccess {Number} total total items for pagination @apiSuccess {String} orderBy the items order by column you specified @apiSuccess {Number} page page you want to request from, start with 1 @apiSuccess {Number} itemsPerPage items for each request @apiSuccess {String} desc the items order by descending or asceding order @apiSuccess {String} type request's type @apiSuccess {Object[]} devices object of devices @apiSuccess {Number} devices.id device's uniq id @apiSuccess {Number} devices.user_id registered user id @apiSuccess {Number=1, 2}devices.type device's type, 1 for andriod, 2 for ios @apiSuccess {String{..254}} devices.dev_id device's id """ # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(field_inputs_wrap.keys()) requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 # one to many # 1. parsing reqest try: for k, v in field_inputs.items(): field_inputs[k]['required'] = False orgArgs, self.args = GetRequestArgs( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value # print(self.args, 'self.args', resource_fields_wrap) self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[field_inputs_wrap_head] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(obj, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') r = obj.query.filter(obj.business_id == id, obj.isdel == False).order_by(isDesc()) _r = r.all() self.args['total'] = len(_r) if itemsPerPage is not 0: _r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() r = _r # 2. export to user for _r in r: __r = dict( (col, getattr(_r, col)) for col in _r.__table__.columns.keys()) self.args[field_inputs_wrap_head].append(__r) _resource_fields = resource_fields.copy() _resource_fields_wrap = resource_fields_wrap.copy() _resource_fields_wrap[field_inputs_wrap_head] = fields.List( fields.Nested(_resource_fields)) self.args['type'] = "pushno" self.args['subtype'] = "reg" return marshal(self.args, _resource_fields_wrap), 200
def get(self): """google / fb """ # fix route hardcode _request = request.args.get('q', None) code = request.args.get('code', None) access_token = request.args.get('access_token', None) logger.debug("login code %s, q=%s access_token=%s", code, _request, access_token) if 1: # for debug if not access_token: return omitError('CE_UNAUTHORIZED', 'no route, permission deny'), 400 if _request == 'google' or request.path == '/rest/admin/login/google': oauth = OAuthSignIn.get_provider('google') userinfo = oauth.get_session(access_token=access_token) user = Users.regist_by_google(userinfo) #log the user in--> #HERE YOU LOG THE USER IN, OR ANYTHING ELSE YOU WANT #THEN REDIRECT TO PROTECTED PAGE self.args, _resource_fields_wrap = signin(user) return marshal(self.args, _resource_fields_wrap), 200 elif _request == 'facebook' or request.path == '/rest/admin/login/facebook': resp = urllib.request.Request( settings.FACEBOOK_OAUTH2_USERINFO_SCOPE + "&access_token={accessToken}".format( accessToken=access_token)) #this gets the facebook profile!! content = None try: with urllib.request.urlopen(resp) as _resp: content = _resp.read() except urllib.error.URLError as e: logger.debug( 'path %s, %s encounter urllib.error.URLError.reason %s', resp.get_full_url(), resp, e.reason) return omitError('CE_UNAUTHORIZED', ',, permission deny'), 400 facebook_profile = json.loads(content.decode('utf-8')) print("facebook_profile =", facebook_profile) userinfo = facebook_profile user = Users.regist_by_facebook(userinfo) #log the user in--> #HERE YOU LOG THE USER IN, OR ANYTHING ELSE YOU WANT #THEN REDIRECT TO PROTECTED PAGE self.args, _resource_fields_wrap = signin(user) return marshal(self.args, _resource_fields_wrap), 200 return omitError('CE_UNAUTHORIZED', 'no route, permission deny'), 400 else: # # the folloing are auto login without get access_token # if _request == 'google' or request.path == '/rest/admin/login/google': if code is None: # request auth # TODO: use OAuthSignIn.get_provider logger.debug("login with google") token_request_uri = settings.GOOGLE_OAUTH2_OAUTH2_URL response_type = "code" client_id = settings.GOOGLE_API_CLIENT_ID redirect_uri = urllib.parse.urljoin( request.url_root, '/rest/admin/login/google') scope = settings.GOOGLE_API_SCOPE url = "{token_request_uri}?response_type={response_type}&client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}".format( token_request_uri=token_request_uri, response_type=response_type, client_id=client_id, redirect_uri=redirect_uri, scope=scope) return redirect(url) else: #validate login_failed_url = '/' if 'error' in request.args or 'code' not in request.args: logger.debug( "'error' in request.args or 'code' not in request.args" ) return omitError('CE_UNAUTHORIZED', 'permission deny'), 400 access_token_uri = settings.GOOGLE_OAUTH2_TOKEN_URL redirect_uri = urllib.parse.urljoin( request.url_root, '/rest/admin/login/google') #redirect_uri = request.url_root + '/rest/admin/login?q=google' params = urllib.parse.urlencode({ 'code': code, 'redirect_uri': redirect_uri, 'client_id': settings.GOOGLE_API_CLIENT_ID, 'client_secret': settings.GOOGLE_API_CLIENT_SECRET, 'grant_type': 'authorization_code' }) print("params=", params) params = params.encode('ascii') # params should be bytes headers = { 'content-type': 'application/x-www-form-urlencoded' } resp = urllib.request.Request(access_token_uri, method='POST', data=params, headers=headers) content = None try: with urllib.request.urlopen(resp) as _resp: content = _resp.read() except urllib.error.URLError as e: logger.debug( '%s encounter urllib.error.URLError.reason %s', resp, e.reason) return omitError('CE_UNAUTHORIZED', ', permission deny'), 400 token_data = json.loads(content.decode('utf-8')) print("token_data=", token_data, ", content =", content) #session['access_token'] = token_data['access_token'] resp = urllib.request.Request( settings.GOOGLE_OAUTH2_USERINFO + "?access_token={accessToken}".format( accessToken=token_data['access_token'])) try: with urllib.request.urlopen(resp) as _resp: content = _resp.read() except urllib.error.URLError as e: logger.debug( '%s encounter urllib.error.URLError.reason %s', resp, e.reason) return omitError('CE_UNAUTHORIZED', ',, permission deny'), 400 #this gets the google profile!! google_profile = json.loads(content.decode('utf-8')) print("google_profile =", google_profile) oauth = OAuthSignIn.get_provider('google') #session['access_token'] = 'ya29.Ci8VA43OwblUKzf7diCatoDGGuOn4untNZTKJNJ4VLkcj6wbA266u-eQd6qrRx3xWQ' userinfo = oauth.get_session( access_token=token_data['access_token']) user = Users.regist_by_google(userinfo) #log the user in--> #HERE YOU LOG THE USER IN, OR ANYTHING ELSE YOU WANT #THEN REDIRECT TO PROTECTED PAGE self.args, _resource_fields_wrap = signin(user) return marshal(self.args, _resource_fields_wrap), 200 elif _request == 'facebook' or request.path == '/rest/admin/login/facebook': if code is None: # request auth # TODO: use OAuthSignIn.get_provider logger.debug("login with facebook") token_request_uri = settings.FACEBOOK_OAUTH2_OAUTH2_URL client_id = settings.FACEBOOK_API_CLIENT_ID redirect_uri = urllib.parse.urljoin( request.url_root, '/rest/admin/login/facebook') scope = settings.FACEBOOK_API_SCOPE response_type = "code" url = "{token_request_uri}?response_type={response_type}&client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}".format( token_request_uri=token_request_uri, response_type=response_type, client_id=client_id, redirect_uri=redirect_uri, scope=scope) print("redirect url=", url) return redirect(url) else: #validate login_failed_url = '/' if 'error' in request.args or 'code' not in request.args: logger.debug( "'error' in request.args or 'code' not in request.args" ) return omitError('CE_UNAUTHORIZED', 'permission deny'), 400 access_token_uri = settings.FACEBOOK_OAUTH2_TOKEN_URL redirect_uri = urllib.parse.urljoin( request.url_root, '/rest/admin/login/facebook') #redirect_uri = request.url_root + '/rest/admin/login?q=facebook' params = urllib.parse.urlencode({ 'code': code, 'redirect_uri': redirect_uri, 'client_id': settings.FACEBOOK_API_CLIENT_ID, 'client_secret': settings.FACEBOOK_API_CLIENT_SECRET, 'grant_type': 'authorization_code' }) print("params=", params) params = params.encode('ascii') # params should be bytes headers = { 'content-type': 'application/x-www-form-urlencoded' } resp = urllib.request.Request(access_token_uri, method='POST', data=params, headers=headers) content = None try: with urllib.request.urlopen(resp) as _resp: content = _resp.read() except urllib.error.URLError as e: logger.debug( '%s encounter urllib.error.URLError.reason %s', resp, e.reason) return omitError('CE_UNAUTHORIZED', ', permission deny'), 400 print(", content =", content) token_data = json.loads(content.decode('utf-8')) print("token_data=", token_data, ", content =", content) #session['access_token'] = token_data['access_token'] resp = urllib.request.Request( settings.FACEBOOK_OAUTH2_USERINFO_SCOPE + "&access_token={accessToken}".format( accessToken=token_data['access_token'])) #this gets the facebook profile!! try: with urllib.request.urlopen(resp) as _resp: content = _resp.read() except urllib.error.URLError as e: logger.debug( 'path %s, %s encounter urllib.error.URLError.reason %s', resp.get_full_url(), resp, e.reason) return omitError('CE_UNAUTHORIZED', ',, permission deny'), 400 facebook_profile = json.loads(content.decode('utf-8')) print("facebook_profile =", facebook_profile) #oauth = OAuthSignIn.get_provider('facebook') ##session['access_token'] = 'ya29.Ci8VA43OwblUKzf7diCatoDGGuOn4untNZTKJNJ4VLkcj6wbA266u-eQd6qrRx3xWQ' #userinfo = oauth.get_session(access_token=token_data['access_token'] ) userinfo = facebook_profile user = Users.regist_by_facebook(userinfo) #log the user in--> #HERE YOU LOG THE USER IN, OR ANYTHING ELSE YOU WANT #THEN REDIRECT TO PROTECTED PAGE self.args, _resource_fields_wrap = signin(user) return marshal(self.args, _resource_fields_wrap), 200 return omitError('CE_UNAUTHORIZED', 'no route, permission deny'), 400
def get(self): """Get all data, getall @api {get} /rest/customer/comments list all comments @apiName GetAllCustomerComments @apiVersion 0.0.5 @apiGroup campaign @apiPermission registered user @apiDescription todo validation<br/> todo query target<br/> @apiParam {Number=0, 25, 50, 100} [itemsPerPage=25] items for each request. @apiParam {Number} [page=1] page you want to request from, start with 1. @apiParam {String} [orderBy=mtime] the items order by column you specified. @apiParam {String="true", "false"} [desc=false] the items order by descending or asceding order. @apiParam {String={..254}} [q] query string for pre-defined columns. @apiExample {curl} Example usage: curl -X GET -H "mTag: xx" -H "Content-Type:application/json" http://localhost/rest/customer/comments HTTP/1.0 200 OK { "page":1, "orderBy":"mtime", "desc":0, "total":2, "subtype":"comment", "type":"business", "itemsPerPage":25, "data":[ { "id":1, "business_id":1, "mtime":"2016-08-31 00:14:56.215613", "content":"Starbucks were all over Singapore and the quality ", "rate":2, "user":{ "id":2, "avatar_url":"" } }, { "id":2, "business_id":1, "mtime":"2016-08-31 04:23:15.682219", "content":"Starbucks were all over Singapore and the quality ", "rate":2, "user":{ "id":2, "avatar_url":"" } } ] } @apiSuccess {Number} total total items for pagination. @apiSuccess {String} orderBy the items order by column you specified. @apiSuccess {Number} page page you want to request from, start with 1. @apiSuccess {Number} itemsPerPage items for each request. @apiSuccess {String} desc the items order by descending or asceding order. @apiSuccess {Object[]} data List of business's comments. @apiSuccess {Number} data.id item's uniq id. @apiSuccess {String} data.content item's comment content @apiSuccess {Number} data.rate item's rate for business item @apiSuccess {Number} data.mtime items's latest modified time with ISO 8601 format @apiSuccess {Object} data.user item's author infomation @apiSuccess {Number} data.user.id item's author id @apiSuccess {String} data.user.avatar_url item's author avatar @apiError CE_INVALID_PARAM invalid parameter HTTP/1.0 400 BAD REQUEST { "errorId": 2001, "message": "{'pages'}" } @apiError CE_NOT_EXIST item not found HTTP/1.0 400 BAD REQUEST { "errorId": 2003, "message": "id 1 not found" } """ # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(field_inputs_wrap.keys()) requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 # one to many # 1. parsing reqest try: for k, v in field_inputs.items(): field_inputs[k]['required'] = False orgArgs, self.args = GetRequestArgs( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value # print(self.args, 'self.args', resource_fields_wrap) self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[field_inputs_wrap_head] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(obj, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') r = obj.query.filter(obj.isdel == False).order_by(isDesc()) _r = r.all() self.args['total'] = len(_r) if itemsPerPage is not 0: _r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() r = _r # 2. export to user for _r in r: __r = dict( (col, getattr(_r, col)) for col in _r.__table__.columns.keys()) ___r = db.session.query(Users).\ filter(_r.user_id == Users.id).scalar() __r['user'] = {'id': ___r.id, 'avatar_url': ___r.avatar_url} ___r = db.session.query(rates).\ filter(_r.user_id == rates.user_id, _r.business_id == rates.business_id).scalar() if ___r is not None: __r['rate'] = ___r.rate self.args[field_inputs_wrap_head].append(__r) _resource_fields = resource_fields.copy() _resource_fields_wrap = resource_fields_wrap.copy() _resource_fields['user'] = fields.Nested(resource_fields_user) _resource_fields_wrap[field_inputs_wrap_head] = fields.List( fields.Nested(_resource_fields)) self.args['type'] = "business" self.args['subtype'] = "comment" return marshal(self.args, _resource_fields_wrap), 200
def get(self, id): """get one item @api {get} /rest/customer/business/:id get one business @apiName GetCustomerBusiness @apiVersion 0.0.4 @apiGroup customer @apiPermission registered user @apiDescription todo validation<br /> todo query target<br/> @apiParam {Number} id business id, you can get from GetAllCustomerBusinesses. @apiExample Example usage: HTTP/1.0 200 OK { "id": 1, "name": "Starbucks Coffee", "image_url": "/business/1/icon", "cat": 1, "deal": 200, "lat": 120.678469, "long": 23.538302, "description": "Early Bird Special: Get $2 off.", "detail": { "rate": 4.3, "rates": [ {"u_id": 1, "avatar_url": "/user/1/avater"}, {"u_id": 2, "avatar_url": "/user/2/avater"} ], "deals": [ {"title": "morning", "description": "for every one"} ], "open": "0600", "close": "2100", "dist": 12333333, "address": "CA", "images_url": { "bg": "/business/1/bg", "icon": "/business/1/icon" } } } @apiSuccess {Object} business object of business. @apiSuccess {Number} business.id item's uniq id. @apiSuccess {String} business.name item's name. @apiSuccess {Number} business.cat item's business industry category. @apiSuccess {float} business.lat item's entered latitude. @apiSuccess {float} business.long item's entered longitude. @apiSuccess {String} business.address item's address @apiSuccess {String} business.description item's description. @apiSuccess {Number} business.deal item's deal. @apiSuccess {String} business.image_url items's image url. @apiSuccess {Object} business.detail item's detail @apiSuccess {Float} business.detail.rate item's rate, average from each comments @apiSuccess {Object[]} business.detail.rates item's brief comments @apiSuccess {Number} business.detail.rates.u_id comment's author id @apiSuccess {String} business.detail.rates.avatar_url comment's author avatar url path @apiSuccess {Object[]} business.detail.deals item's deals @apiSuccess {String} business.detail.deals.title item's deal title @apiSuccess {String} business.detail.deals.description item's deal description @apiSuccess {String} business.detail.open item open time with 24h format @apiSuccess {String} business.detail.open item close time with 24h format @apiSuccess {Number} business.detail.dist item's distance farward with your current location, the unit is meter @apiSuccess {Object} business.detail.images_url item images' path @apiSuccess {String} business.detail.images_url.bg item backgound images' path @apiSuccess {String} business.detail.images_url.icon item icon images' path @apiError CE_INVALID_PARAM invalid parameter HTTP/1.0 400 BAD REQUEST { "errorId": 2001, "message": "{'pages'}" } @apiError CE_NOT_EXIST item not found HTTP/1.0 400 BAD REQUEST { "errorId": 2003, "message": "id 17 not found" } """ requestArgsSet = set((col) for col in request.args) if not ExtraParamsIsValid(requestArgsSet): return omitError(ErrorMsg=repr(set( (col) for col in request.args))), 400 r = detail.query.filter(detail.business_id == id, detail.isdel == False).scalar() if r is None: return omitError('CE_NOT_EXIST', 'id {} not found'.format(id)), 400 self.args = {} self.args[field_inputs_wrap_head] = {} #self.args[field_inputs_wrap_head][__head_detail__] = {} _resource_fields_wrap = resource_fields_wrap.copy() for col in resource_fields_wrap: if col not in ['type', 'subtype']: _resource_fields_wrap.pop(col, None) #_resource_fields_detail_wrap = {} #resource_fields_detail[__head_detail_rates__] = \ # fields.List(fields.Nested(resource_fields_detail_rates)) resource_fields_detail[__head_detail_deals__] = \ fields.List(fields.Nested(resource_fields_detail_deals)) _resource_fields_detail_rates = {} #_resource_fields_detail_rates['user'] = fields.Nested(resource_fields_detail_rates) _resource_fields_detail_rates = resource_fields_detail_rates.copy() resource_fields_detail['users'] = \ fields.List(fields.Nested(_resource_fields_detail_rates)) #resource_fields.update(resource_fields_detail) resource_fields_detail[__head_detail_images_url__] = \ fields.Nested(resource_fields_detail_images_url) #resource_fields[__head_detail__] = fields.Nested(_resource_fields_detail_wrap) #_resource_fields_wrap[field_inputs_wrap_head] = fields.Nested(resource_fields) _resource_fields_wrap[field_inputs_wrap_head] = fields.Nested( resource_fields_detail) #print('_resource_fields_wrap ', resource_fields) _r = r #for col in resource_fields.keys(): # self.args[field_inputs_wrap_head][col] = getattr(_r, col) #for col in resource_fields.keys(): for col in _r.__table__.columns.keys(): self.args[field_inputs_wrap_head][col] = getattr(_r, col) self.args[field_inputs_wrap_head]['name'] = getattr(_r.meta, 'name') rate = 0 self.args[field_inputs_wrap_head]['rate'] = rate self.args[field_inputs_wrap_head]['users'] = [] self.args[field_inputs_wrap_head][__head_detail_deals__] = [] self.args[field_inputs_wrap_head]['images_url'] = {} __r = db.session.query(rates).\ filter(rates.business_id == id).all() r_len = len(__r) self.args[field_inputs_wrap_head]['rate_nr'] = r_len if r_len > 0: for ___r in __r: rate += ___r.rate self.args[field_inputs_wrap_head]['rate'] = int(rate / r_len) # FIXME: hard code __r = db.session.query(comment).\ filter(comment.business_id == id).order_by(comment.mtime.desc()).offset(0).limit(5).all() r_len = len(__r) self.args[field_inputs_wrap_head]['user_nr'] = r_len if r_len > 0: for __r in __r: ___r = db.session.query(Users).\ filter(__r.user_id == Users.id).scalar() self.args[field_inputs_wrap_head]['users'].append( #{'user': { 'id': ___r.id, 'avatar_url': ___r.avatar_url } #} ) # TODO: get favorite by User id from session _r = deals.query.filter(deals.business_id == id).all() r_len = len(_r) if r_len: for __r in _r: self.args[field_inputs_wrap_head][ __head_detail_deals__].append({ 'title': __r.title, 'description': __r.description }) _r = pics.query.filter(pics.business_id == id).all() # (1, 'icon'), (2, 'bg'), (3, 'gallery') r_len = len(_r) if r_len > 0: # TODO: mapping table for __r in _r: if getattr(__r, 'type') == 1: self.args[field_inputs_wrap_head]['images_url']['icon'] = \ getattr(__r, 'path') r_len -= 1 elif getattr(__r, 'type') == 2: self.args[field_inputs_wrap_head]['images_url']['bg'] = \ getattr(__r, 'path') r_len -= 1 self.args[field_inputs_wrap_head]['gallery_nr'] = r_len self.args[field_inputs_wrap_head]['id'] = id self.args['type'] = "business" self.args['subtype'] = "overview" #print('self.args= ', self.args, '_resource_fields_wrap', _resource_fields_wrap) return marshal(self.args, _resource_fields_wrap), 200
def get(self): """Get all data, getall """ # check the request is validtion, # ex: we not allow request arg 'itemsPerPage1' validSet = set(field_inputs_wrap.keys()) requestArgsSet = set(request.dataDictWrap.keys()) if not ExtraParamsIsValid(requestArgsSet, validSet): return omitError( ErrorMsg=repr(requestArgsSet.difference(validSet))), 400 # one to many # 1. parsing reqest try: for k, v in field_inputs.items(): field_inputs[k]['required'] = False orgArgs, self.args = GetRequestArgs( None, field_inputs_wrap, dict((col, request.args.get(col)) for col in request.args)) # get default value # print(self.args, 'self.args', resource_fields_wrap) self.response = dict( marshal(self.args, resource_fields_wrap).items()) self.args[field_inputs_wrap_head] = [] except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError(ErrorMsg=repr(error)), 400 itemsPerPage = self.response['itemsPerPage'] page = self.response['page'] orderBy = getattr(obj, self.response['orderBy']) isDesc = getattr(orderBy, 'desc' if self.response['desc'] else 'asc') r = obj.query.filter(obj.isdel == False).order_by(isDesc()) _r = r.all() self.args['total'] = len(_r) if itemsPerPage is not 0: _r = r.offset(itemsPerPage * (page-1))\ .limit(itemsPerPage)\ .all() r = _r # 2. export to user for _r in r: __r = dict( (col, getattr(_r, col)) for col in _r.__table__.columns.keys()) self.args[field_inputs_wrap_head].append(__r) _resource_fields = resource_fields.copy() _resource_fields_wrap = resource_fields_wrap.copy() _resource_fields_wrap[field_inputs_wrap_head] = fields.List( fields.Nested(_resource_fields)) self.args['type'] = "business" self.args['subtype'] = "rate" return marshal(self.args, _resource_fields_wrap), 200
def post(self): """upload pics to business @api {post} /rest/pic/gallery upload multiple pictures to business @apiVersion 0.0.5 @apiName UploadPicsToBusiness @apiGroup business @apiPermission registered user @apiDescription todo certificate with cookies / oauth 2.0<br /> todo long/lat validation<br /> todo metadata for counter of registerd devices<br /> todo error / success return code in api @apiHeader {String} file[] upload file path @apiHeader {Number} business_id upload to business @apiHeader {String={customer}} type upload type @apiExample {curl} Example usage: curl -v -i -X POST -H "Content-Type: multipart/form-data" -F "file[]=@20160618_6615.jpg" -F "business_id=1" -F type="customer" -F "file[][email protected]" http://localhost/rest/pic/gallery { "type":"pic", "data":[ { "id":9, "path":"/img/customer/1/G30SLL_20160618_6615.jpg", "height":1365, "width":1024 }, { "id":10, "path":"/img/customer/1/3AZGA4_10473.jpg", "height":1365, "width":1024 } ], "page":1, "subtype":"gallery", "gallery_nr":2, "total":6 } @apiSuccess {Number} total total items in one business @apiSuccess {String} orderBy the items order by column you specified @apiSuccess {Number} page page you want to request from, start with 1 @apiSuccess {Number} gallery_nr current upload files number @apiSuccess {String} type request's type @apiSuccess {String} subtype request's subtype @apiSuccess {Object[]} data object @apiSuccess {Number} data.id image's id @apiSuccess {Number} data.path image's url that you could directly access @apiSuccess {Number} data.height image's height(px) @apiSuccess {Number} data.width image's width(px) """ try: orgArgs, self.args = GetTwoLayerRequestArgs( None, field_inputs, request.form) except Exception as error: logger.debug('traceback.format_exc(%s)', traceback.format_exc()) return omitError('CE_INVALID_PARAM', 'not found'), 400 id = self.args['business_id'] type = self.args['type'] #print(self.args, 'self.args', id, type) #self.args = {} #id = request.form.get('business_id') #type = request.form.get('type') #if type not in PIC_ALLOWED_TYPE: # logger.debug('%s not in PIC_ALLOWED_TYPE', type) # type = None #if not id or not type: # return omitError('CE_INVALID_PARAM', 'id {} not found'.format(id)), 400 print("galleryed_files", request.files, "form data=", request.form) # 1. check id exist r = business.query.filter(business.id == id, business.isdel == False).scalar() if r is None: return omitError('CE_NOT_EXIST', 'id {} not found'.format(id)), 400 # if dir not exist, create it # /img/business/1/ pic_dir = os.path.join(STATIC_ROOT, PIC_PREFIX, type, str(id)) rest_pic_prefix = os.path.join(REST_PIC_PREFIX, type, str(id)) if not os.path.exists(pic_dir): os.makedirs(pic_dir) # TODO: review trigger time # 2. check last status that records are same with local _pics = [] count = 0 filenames = next(os.walk(pic_dir))[2] _filenames = filenames.copy() print("filenames=", _filenames) ps = obj.query.filter(obj.business_id == id).all() for v in ps: #print("filenames=", filenames, "v.path=", v.path) if v.path in filenames: count += 1 _filenames.remove(v.path) else: # prepare remove _pics.append(v) # TODO: need check duplicate record? # 2.1. commit to delete not relationship records try: for v in _pics: db.session.delete(v) db.session.flush() db.session.commit() except Exception as error: db.session.rollback() logger.warning('session commit error(%s)', error) return omitError(ErrorMsg=repr(error)), 400 # remove not exist db's file for v in _filenames: os.remove(os.path.join(pic_dir, v)) # 3. validate follows spec if count > max: return omitError('CE_EXCEED_LIMIT', 'limit is {}'.format(max)), 400 # 4. check pic name _pics = [] filenames = [] galleryed_files = request.files.getlist("file[]") print("galleryed_files file[]= ", galleryed_files) if len(galleryed_files) == 0: galleryed_files = request.files.getlist("customer") # for ios print("galleryed_files customer= ", galleryed_files) for file in galleryed_files: # Check if the file is one of the allowed types/extensions if file and self.allowed_file(file.filename): # Make the filename safe, remove unsupported chars filename = secure_filename(file.filename) print("file.filename=", file.filename, "filename=", filename) # Move the file form the temporal folder to the gallery # folder we setup p = obj() rs = ''.join( random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(6)) # 5FATMM_35e4183b.jpg.png -> 5FATMM_35e4183b.png extend = os.path.splitext(filename)[1] #print("self.remove_extend(filename)=", self.remove_extend(filename)) p.path = '_'.join([rs, self.remove_extend(filename)]) + extend p.business_id = id # (1, 'icon'), (2, 'bg'), (3, 'gallery') p.type = 3 _pics.append(p) filenames.append(filename) # 4. move to pic dir # FIXME: check file exist if abnormal error that db record save but pic not exist self.args[field_inputs_wrap_head] = [] path = [] _filenames = [] for k, v in enumerate(_pics): filename = os.path.join(pic_dir, filenames[k]) n_filename = os.path.join(pic_dir, v.path) try: # FIXME: handle <FileStorage: '35e4183b.jpg.png' ('application/octet-stream')>) galleryed_files[k].save(filename) #import shutil #shutil.copy(filename, n_filename) os.rename(filename, n_filename) _filenames.append(n_filename) print("n_filename = ", n_filename, "filename=", filename) img = Image.open(n_filename) s = img.size ratio = 0 v.width = s[0] v.height = s[1] if s[0] > MAXWIDTH: ratio = MAXWIDTH / s[0] v.width = MAXWIDTH v.height = int(round(s[1] * ratio)) img.thumbnail((v.width, v.height), Image.ANTIALIAS) print("img = ", img, "n_filenam=", n_filename, "format:", img.format, "width:", MAXWIDTH, ", height: ", int(round(s[1] * ratio)), "orgsize:", s) #img.save(n_filename, img.format) # FIXME: open 35e4183b.jpg.png error img.save(n_filename) except IOError: #for v in _filenames: # os.remove(v) return omitError('CE_IMAGE_RESIZE', 'image resize {} error'.format( filenames[k])), 400 # 5. commit to save try: for v in _pics: db.session.add(v) db.session.flush() db.session.refresh(r) for v in _pics: _pic = dict((col, getattr(v, col)) for col in v.__table__.columns.keys()) print("_pic:", _pic) _pic['path'] = os.path.join(rest_pic_prefix, v.path) self.args[field_inputs_wrap_head].append(_pic) db.session.commit() except Exception as error: db.session.rollback() logger.warning('session commit error(%s)', error) return omitError(ErrorMsg=repr(error)), 400 #output = {"type": "pic", "subtype": "gallery", # "imgs": {"total": count, "gallery_nr": len(_pics), "path": (path)}} for v in ['itemsPerPage', 'desc', 'orderBy']: resource_fields_wrap.pop(v, None) _resource_fields = {} resource_fields_wrap[field_inputs_wrap_head] = fields.List( fields.Nested(resource_fields_post)) self.args['total'] = len( obj.query.filter(obj.business_id == id, obj.isdel == False).all()) self.args['gallery_nr'] = len(_pics) self.args['type'] = "pic" self.args['subtype'] = "gallery" return marshal(self.args, resource_fields_wrap), 200