class ProductSchema(BaseSchema): productID = EmqString(dump_only=True) productName = EmqString(required=True) description = EmqString(allow_none=True, len_max=300) cloudProtocol = EmqInteger(required=True, validate=OneOf(range(1, 8))) gatewayProtocol = EmqInteger(allow_none=True, validate=OneOf(range(1, 8))) productType = EmqInteger(required=True, validate=OneOf([1, 2])) @validates('productName') def is_exist(self, value): if self._validate_obj('productName', value): return product_name = db.session.query(Product.productName) \ .filter_tenant(tenant_uid=g.tenant_uid) \ .filter(Product.productName == value).first() if product_name: raise DataExisted(field='productName') @pre_load def product_load(self, data): product_type = data.get('productType') if not product_type: data['productType'] = 1 gateway_protocol = data.get('gatewayProtocol') if data['productType'] == 2 and not gateway_protocol: raise FormInvalid(field='gatewayProtocol') if data['productType'] == 1 and gateway_protocol: data['gatewayProtocol'] = None return data
class CertSchema(BaseSchema): certName = EmqString(required=True) enable = EmqInteger(allow_none=True) CN = EmqString(dump_only=True) key = EmqString(dump_only=True) cert = EmqString(dump_only=True) root = EmqString(dump_only=True) @validates('certName') def name_is_exist(self, value): if self._validate_obj('certName', value): return query = db.session.query(Cert.certName) \ .filter_tenant(tenant_uid=g.tenant_uid) \ .filter(Cert.certName == value).first() if query: raise DataExisted(field='certName') @post_dump def dump_root(self, data): certs_path = current_app.config.get('CERTS_PATH') root_ca_path = os.path.join(certs_path, 'actorcloud/root_ca.crt') with open(root_ca_path, 'r') as root_crt_file: st_root_cert = root_crt_file.read() data['root'] = st_root_cert return data
class CodeRunSchema(BaseSchema): productID = EmqString(required=True) code = EmqString(required=True, len_max=100000) topic = EmqString(required=True) input = EmqString(required=True, len_max=100000) analogType = EmqInteger(required=True, validate=OneOf([1, 2])) # 1:decode,2:encode
class ApplicationSchema(BaseSchema): """ application management """ appID = EmqString(dump_only=True) appName = EmqString(required=True) appToken = EmqString(dump_only=True) expiredAt = EmqDateTime(allow_none=True) # expired time description = EmqString(allow_none=True, len_max=300) appStatus = EmqInteger(required=True, validate=OneOf([0, 1])) userIntID = EmqInteger(allow_none=True) roleIntID = EmqInteger(required=True) # app role id groups = EmqList(allow_none=True, list_type=str, load_only=True) # product uid @validates('appName') def validate_app_name(self, value): if self._validate_obj('appName', value): return app = Application.query \ .filter_tenant(tenant_uid=g.tenant_uid) \ .filter(Application.appName == value).first() if app: raise DataExisted(field='appName') @post_load def handle_app_groups(self, in_data): groups_uid = in_data.get('groups') if not groups_uid: return in_data groups = Group.query \ .filter_tenant(tenant_uid=g.tenant_uid) \ .filter(Group.groupID.in_(set(groups_uid))).all() if len(groups_uid) != len(groups): raise DataNotFound(field='groups') in_data['groups'] = groups return in_data
class FromTopicSchema(BaseSchema): productID = EmqString(required=True) deviceID = EmqString(required=True) topic = EmqString(required=True) @validates_schema def validate_from(self, data): product_uid = data.get('productID') product = db.session \ .query(Product.cloudProtocol) \ .filter_tenant(tenant_uid=g.tenant_uid) \ .filter(Product.productID == product_uid) \ .first() if not product: raise DataNotFound(field='productID') device_uid = data.get('deviceID') # device_uid can be '+' or deviceID of device if device_uid != '+': device = db.session \ .query(Device.id) \ .filter_tenant(tenant_uid=g.tenant_uid) \ .filter(Device.productID == product_uid, Device.deviceID == device_uid) \ .first() if not device: raise DataNotFound(field='deviceID') topic = data.get('topic') # If the protocol is LwM2M,the fixed value of topic is 'ad/#' if product.cloudProtocol == 3 and topic != 'ad/#': raise DataNotFound(field='topic') else: data_stream = db.session \ .query(DataStream.topic) \ .filter_tenant(tenant_uid=g.tenant_uid) \ .filter(DataStream.productID == product_uid, DataStream.topic == topic) \ .first() if not data_stream: raise DataNotFound(field='topic') @post_dump def query_name(self, data): product_uid = data.get('productID') product = db.session \ .query(Product.productName) \ .filter_tenant(tenant_uid=g.tenant_uid) \ .filter(Product.productID == product_uid) \ .first() data['productName'] = product.productName if product else None device_uid = data.get('deviceID') if device_uid != '+': device = db.session \ .query(Device.deviceName) \ .filter_tenant(tenant_uid=g.tenant_uid) \ .filter(Device.productID == product_uid, Device.deviceID == device_uid) \ .first() data['deviceName'] = device.deviceName if device else None return data
class ImportDeviceSchema(Schema, BaseDeviceSchema): deviceType = EmqInteger(allow_none=True) productID = EmqString(allow_none=True, len_max=6) # devices import upLinkSystem = EmqInteger(required=True, validate=OneOf([1, 3])) # 1:cloud, 3:gateway product = EmqString(required=True) # product name gateway = EmqString(allow_none=True) # gateway name
class LoRaABPSchema(BaseSchema): is_private = True region = EmqString(required=True) nwkSKey = EmqString(required=True, validate=validate.Length(equal=32)) appSKey = EmqString(required=True, validate=validate.Length(equal=32)) fcntUp = EmqInteger(required=True) fcntDown = EmqInteger(required=True) fcntCheck = EmqInteger(required=True)
class EmailActionSchema(BaseSchema): title = EmqString(required=True) content = EmqString(required=True) emails = EmqList(required=True) @validates('emails') def validate_email(self, value): for email in value: validate.Email()(email)
class DataPointSchema(BaseSchema): dataPointName = EmqString(required=True) dataPointID = EmqString(required=True) dataTransType = EmqInteger( required=True) # message 1: Up, 2: Down, 3 UpAndDown pointDataType = EmqInteger( required=True) # 1:num, 2:str, 3:Boolean, 4:datetime, 5:location extendTypeAttr = EmqDict( allow_none=True) # extension attribute for point data type isLocationType = EmqInteger(allow_none=True) # 1:yes, 2:no locationType = EmqInteger( allow_none=True) # 1: longitude, 2: latitude, 3: altitude description = EmqString(allow_none=True, len_max=300) enum = EmqList(allow_none=True) # enum of string or integer productID = EmqString(required=True) # product uid cloudProtocol = EmqInteger(load_only=True) # product cloudProtocol @validates('dataPointName') def name_is_exist(self, value): if self._validate_obj('dataPointName', value): return product_uid = self.get_request_data('productID') point_name = db.session.query(DataPoint.dataPointName) \ .filter(DataPoint.productID == product_uid, DataPoint.dataPointName == value).first() if point_name: raise DataExisted(field='dataPointName') @validates('dataPointID') def validate_point_uid(self, value): if not value or self._validate_obj('dataPointID', value): return if not re.match(r"^[0-9A-Za-z_\-]*$", value): raise FormInvalid(field='dataPointID') product_uid = self.get_request_data('productID') data_point_uid = db.session.query(DataPoint.dataPointID) \ .filter(DataPoint.productID == product_uid, DataPoint.dataPointID == value).first() if data_point_uid: raise DataExisted(field='dataPointID') @pre_load def handle_load_data(self, data): product_uid: str = data.get('productID') if not isinstance(product_uid, str): raise FormInvalid(field='productID') product = Product.query. \ filter_tenant(tenant_uid=g.tenant_uid) \ .filter(Product.productID == product_uid).first() if not product: raise DataNotFound(field='productID') data['productID'] = product.productID data['cloudProtocol'] = product.cloudProtocol data = handle_extend_type_attr(data) return data
class DeviceEventSchema(BaseSchema): class Meta: additional = ('deviceID', ) msgTime = EmqDateTime(allow_none=True) streamID = EmqString(required=True) topic = EmqString(required=True) dataType = EmqInteger(required=True) data = EmqString(required=True) responseResult = EmqString(required=True)
class DataStreamSchema(BaseSchema): streamName = EmqString(required=True) streamID = EmqString(required=True) # data stream identifier streamType = EmqInteger(required=True, validate=OneOf([1, 2])) topic = EmqString(required=True, len_max=500) productID = EmqString(required=True) description = EmqString(allow_none=True, len_max=300) cloudProtocol = EmqInteger(load_only=True) # product cloud protocol productType = EmqInteger(load_only=True) # 1: device, 2: gateway @validates('streamName') def stream_name_is_exist(self, value): if self._validate_obj('streamName', value): return product_uid = self.get_request_data('productID') stream_name = db.session.query(DataStream.streamName) \ .filter(DataStream.productID == product_uid, DataStream.streamName == value).first() if stream_name: raise DataExisted(field='dataPointName') @validates('streamID') def stream_id_is_exist(self, value): if self._validate_obj('streamID', value): return if not re.match(r"^[a-zA-Z]\w{3,}$", value): raise FormInvalid(field='streamID') product_uid = self.get_request_data('productID') stream_name = db.session.query(DataStream.streamID) \ .filter(DataStream.productID == product_uid, DataStream.streamID == value).first() if stream_name: raise DataExisted(field='streamID') @validates('topic') def validate_topic(self, value): if not value or self._validate_obj('topic', value): return if not re.match(r"^[0-9A-Za-z_\-/]*$", value): raise FormInvalid(field='topic') @pre_load def handle_load_data(self, data): product_uid: str = data.get('productID') if not isinstance(product_uid, str): raise FormInvalid(field='productID') product = Product.query. \ filter_tenant(tenant_uid=g.tenant_uid) \ .filter(Product.productID == product_uid).first() if not product: raise DataNotFound(field='productID') data['productID'] = product.productID data['cloudProtocol'] = product.cloudProtocol data['productType'] = product.productType return data
class CurrentAlertSchema(BaseSchema): class Meta: additional = ( 'alertName', 'alertContent', 'alertDetail', 'alertSeverity', 'startTime' ) tenantID = EmqString(required=True) deviceID = EmqString(required=True) ruleIntID = EmqInteger(required=True) alertTimes = EmqInteger(missing=1) @validates_schema def validate_data(self, in_data): tenant_uid = in_data.get('tenantID') rule = db.session.query(Rule.id) \ .filter(Rule.id == in_data.get('ruleIntID'), Rule.tenantID == tenant_uid) \ .first() if not rule: raise DataNotFound(field='ruleIntID') device = db.session.query(Device.id) \ .filter(Device.tenantID == tenant_uid, Device.deviceID == in_data.get('deviceID')) \ .first() if not device: raise DataNotFound(field='deviceID') @pre_load def handle_data(self, data): action = data.get('action') values = data.get('values') result = {} if isinstance(values, list) and len(values) > 0: result = values[0] in_data = { **action, 'alertDetail': result, "startTime": datetime.now() } topic = result.get('topic') # /$protocol/$tenant_id/$product_id/$device_id/$topic if topic: topic_info = re.split(r'/', topic[1:], 4) if len(topic_info) != 5: raise APIException() _, tenant_uid, _, device_uid, _ = topic_info in_data['tenantID'] = tenant_uid in_data['deviceID'] = device_uid return in_data @post_load def add_tenant_info(self, data): return data
class GroupSchema(BaseSchema): groupID = EmqString(dump_only=True) groupName = EmqString(required=True) description = EmqString(allow_none=True, len_max=300) @validates('groupName') def group_name_is_exist(self, value): if self._validate_obj('groupName', value): return query = db.session.query(Group.groupName) \ .filter_tenant(tenant_uid=g.tenant_uid) \ .filter(Group.groupName == value).first() if query: raise DataExisted(field='groupName')
class ScopeDataSchema(BaseSchema): devices = EmqList(required=True, list_type=str) scope = EmqString(required=True, len_max=1000) scopeType = EmqInteger() @validates('devices') def validate_devices(self, value): devices_count = Device.query \ .filter_tenant(tenant_uid=g.tenant_uid) \ .filter(Device.deviceID.in_(set(value))) \ .count() if devices_count != len(value): raise DataNotFound(field='devices') @post_dump def query_devices(self, data): devices_uid = data.get('devices') devices_result = Device.query \ .filter(Device.deviceID.in_(set(devices_uid))) \ .with_entities(Device.id, Device.deviceID, Device.deviceName) \ .many() devices = [] for device in devices_result: device_record = { key: getattr(device, key) for key in device.keys() } devices.append(device_record) data['devices'] = devices return data
class UpdateUserSchema(BaseSchema): roleIntID = EmqInteger(required=True) enable = EmqInteger(required=True) expiresAt = EmqDateTime(allow_none=True) phone = EmqString(allow_none=True, len_max=15) userAuthType = EmqInteger(allow_none=True) groups = EmqList(allow_none=True, list_type=str, load_only=True) @post_load def handle_user_auth_type(self, data): if 'user_id' not in g: data['userAuthType'] = 1 groups_uid = self.get_request_data(key='groups') auth_type = data.get('userAuthType') if auth_type not in (1, 2): raise FormInvalid(field='userAuthType') if auth_type == 2 and groups_uid: groups = Group.query \ .filter_tenant(tenant_uid=g.tenant_uid) \ .filter(Group.groupID.in_(set(groups_uid))).all() if len(groups_uid) != len(groups): raise DataNotFound(field='groups') data['groups'] = groups else: data.pop('groups', None) return data
class WebhookActionSchema(BaseSchema): url = fields.Url(required=True, len_max=100) token = EmqString(required=True, len_min=6) @validates_schema def validate_webhook(self, data): url = data.get('url') token = data.get('token') if not all([url, token]): return timestamp = int(time.time()) nonce = generate_uuid(size=10) hash_str = f"{token}{timestamp}{nonce}".encode('utf-8') signature = hashlib.sha1(hash_str).hexdigest() validate_status = True params = dict(signature=signature, timestamp=timestamp, nonce=nonce) with SyncHttp() as sync_http: response = sync_http.get(url=url, params=params) if response.responseCode != 200: validate_status = False try: response_dict = json.loads(response.responseContent) if response_dict.get('nonce') != params.get('nonce'): validate_status = False except Exception: validate_status = False if not validate_status: raise FormInvalid(field='Webhook url')
class RuleSchema(BaseSchema): ruleName = EmqString(required=True) sql = EmqString(required=True, len_max=1000) fromTopics = fields.Nested(FromTopicSchema, allow_none=True, many=True) scopeData = fields.Nested(ScopeDataSchema) ruleType = EmqInteger(required=True, validate=OneOf([1, 2])) remark = EmqString(allow_none=True) enable = EmqInteger(allow_none=True, validate=OneOf([0, 1])) actions = fields.Nested(ActionSchema, only='id', required=True, many=True, dump_only=True) userIntID = EmqInteger(dump_only=True) tenantID = EmqString(dump_only=True) @validates('ruleName') def name_is_exist(self, value): if self._validate_obj('ruleName', value): return query = Rule.query \ .filter_tenant(tenant_uid=g.tenant_uid) \ .filter(Rule.ruleName == value) \ .first() if query: raise DataExisted(field='ruleName') @validates_schema def validate_rule_meta(self, data): rule_type = data.get('ruleType') # fromTopics is required when ruleType=1 if rule_type == 1 and not data.get('fromTopics'): raise ValidationError( fields.Field.default_error_messages['required'], ['fromTopics']) # scopeData is required when ruleType=2 elif rule_type == 2 and not data.get('scopeData'): raise ValidationError( fields.Field.default_error_messages['required'], ['scopeData']) @pre_load() def remove_from_topics(self, data): if data.get('ruleType') == 1: data.pop('scopeData', None) elif data.get('ruleType') == 2: data.pop('fromTopics', None)
class UpdateDataStreamSchema(DataStreamSchema): productID = EmqString(dump_only=True) topic = EmqString(dump_only=True, len_max=500) dataPoints = EmqList(allow_none=True, load_only=True, list_type=int) @post_load def handle_data_points(self, data): product_uid = self.get_origin_obj('productID') data_point_ids = data.get('dataPoints') if not data_point_ids: return data data_points = DataPoint.query \ .filter(DataPoint.productID == product_uid, DataPoint.id.in_(set(data_point_ids))).all() if len(data_points) != len(data_point_ids): raise DataNotFound(field='dataPoints') data['data_points'] = data_points return data
class Lwm2mItemSchema(BaseSchema): itemName = EmqString(required=True) itemID = EmqInteger(required=True) description = EmqString() itemType = EmqString(required=True) itemOperations = EmqString(required=True) # R/W/RW/E itemUnit = EmqString(required=True) rangeEnumeration = EmqString() mandatory = EmqString() # mandatory: Optional,Mandatory multipleInstance = EmqString(required=True) objectID = EmqInteger(required=True)
class TimerPublishSchema(BaseSchema): taskName = EmqString(required=True) deviceID = EmqString(required=True) topic = EmqString(required=True, len_max=500) # publish topic payload = EmqString(required=True, len_max=10000) # publish payload timerType = EmqInteger(required=True, validate=OneOf([1, 2])) intervalTime = EmqDict(allow_none=True) crontabTime = EmqDateTime(allow_none=True) deviceIntID = EmqInteger(allow_none=True) # client index id taskStatus = EmqInteger(dump_only=True) @post_load def handle_data(self, data): data['taskStatus'] = 2 data = self.validate_timer_format(data) result = PublishSchema().load({**data}).data data['deviceIntID'] = result['deviceIntID'] data['payload'] = result['payload'] data['topic'] = result['topic'] if result.get('topic') else None data['payload'] = json.loads(data['payload']) return data @staticmethod def validate_timer_format(data): timer_type = data.get('timerType') interval_time = data.get('intervalTime') crontab_time = data.get('crontabTime') if timer_type == 1 and crontab_time and not interval_time: date_now = arrow.now(tz=current_app.config['TIMEZONE']).shift( minutes=+2) try: crontab_time = arrow.get(crontab_time) except ParserError: raise FormInvalid(field='crontabTime') if crontab_time < date_now: FormInvalid(field='crontabTime') elif timer_type == 2 and interval_time and not crontab_time: check_status = check_interval_time(interval_time) if not check_status: raise FormInvalid(field='intervalTime') else: raise FormInvalid(field='timerType') return data
class TenantUpdateSchema(BaseSchema): company = EmqString(allow_none=True) contactPerson = EmqString(allow_none=True) contactPhone = EmqString(allow_none=True) contactEmail = EmqEmail(allow_none=True) logo = EmqInteger() logoDark = EmqInteger() @validates('company') def company_is_exist(self, value): if value == '': raise FormInvalid(field='company') if Tenant.query.filter_by(company=value).first(): raise DataExisted(field='company') @post_load def handle_logo(self, data): logo = data.get('logo') logo_dark = data.get('logoDark') if logo is not None: if logo < 1: data.pop('logo') else: upload_info = UploadInfo.query \ .join(User, User.id == UploadInfo.userIntID) \ .filter(UploadInfo.id == logo, User.tenantID == g.tenant_uid) \ .first() if not upload_info: raise DataNotFound(field='logo') if logo_dark is not None: if logo_dark < 1: data.pop('logoDark') else: upload_info = UploadInfo.query \ .join(User, User.id == UploadInfo.userIntID) \ .filter(UploadInfo.id == logo_dark, User.tenantID == g.tenant_uid) \ .first() if not upload_info: raise DataNotFound(field='logoDark')
class CodecSchema(BaseSchema): productID = EmqString(required=True) code = EmqString(required=True, len_max=100000) codeStatus = EmqInteger(dump_only=True) reviewOpinion = EmqString(dump_only=True) @validates('productID') def validate_product(self, value): if self._validate_obj('productID', value): return product = db.session.query(Product.id) \ .filter(Product.userIntID == g.user_id, Product.productID == value) \ .first() if not product: raise DataNotFound(field='productID') codec = db.session.query(Codec.id) \ .filter(Codec.tenantID == g.tenant_uid, Codec.productID == value) \ .first() if codec: raise DataExisted(field='productID')
class RoleSchema(BaseSchema): roleName = EmqString(required=True) description = EmqString(allow_none=True, len_max=300) permissions = EmqList(required=True, list_type=int) isShare = EmqInteger(dump_only=True) tenantID = EmqString(dump_only=True) @validates('permissions') def is_empty_list(self, value): if not value: raise FormInvalid('permissions') @validates('roleName') def role_name_is_exist(self, value): if self._validate_obj('roleName', value): return role = Role.query \ .join(Tenant, Role.tenantID == Tenant.tenantID) \ .filter(Role.roleName == value) \ .filter(Tenant.tenantID == g.tenant_uid).all() if role: raise DataExisted(field='roleName')
class Lwm2mObjectSchema(BaseSchema): objectName = EmqString(required=True) objectID = EmqInteger(required=True) description = EmqString() objectURN = EmqString() objectVersion = EmqString() multipleInstance = EmqString(required=True) mandatory = EmqString() # mandatory: Optional,Mandatory
class LoRaOTTASchema(BaseSchema): is_private = True region = EmqString(required=True) appEUI = EmqString(required=True, validate=validate.Length(equal=16)) appKey = EmqString(required=True, validate=validate.Length(equal=32)) fcntCheck = EmqInteger(required=True) canJoin = EmqInteger(required=True) @validates('region') def validate_region(self, value): if value is None: return cache = Cache() dict_code_cache = cache.dict_code region_cache = dict_code_cache['region'] if value not in region_cache.keys(): raise DataNotFound(field='region') @post_dump def dump_can_join(self, data): # bool to 0/1 data['canJoin'] = 1 if data.get('canJoin') else 0 return data
class ActionSchema(BaseSchema): actionName = EmqString(required=True) actionType = EmqInteger(required=True, validate=OneOf([1, 2, 3, 4, 5])) config = EmqDict(required=True) description = EmqString(allow_none=True) userIntID = EmqInteger(dump_only=True) tenantID = EmqString(dump_only=True) @validates('actionName') def name_is_exist(self, value): if self._validate_obj('actionName', value): return query = db.session.query(Action.actionName) \ .filter(Action.tenantID == g.tenant_uid, Action.actionName == value).first() if query: raise DataExisted(field='actionName') @pre_load def restore_config(self, data): action_type = data.get('actionType') config_dict = data.get('config') if config_dict is None: return data if action_type == 1: AlertActionSchema().validate(config_dict) if action_type == 2: EmailActionSchema().validate(config_dict) elif action_type == 3: WebhookActionSchema().validate(config_dict) elif action_type == 4: # We need the config data after load data['config'] = PublishActionSchema().load(config_dict).data elif action_type == 5: MqttActionSchema().validate(config_dict) return data
class LoRaDeviceSchema(BaseSchema): is_private = True type = EmqString(required=True, validate=lambda x: x in ['otaa', 'abp']) region = EmqString(allow_none=True) fcntCheck = EmqInteger(allow_none=True) ottaInfo = EmqDict(load_only=True) # lora otta type info abpInfo = EmqDict(load_only=True) # lora abp type info @validates('fcntCheck') def validate_fcnt_check(self, value): if value is None: return cache = Cache() dict_code_cache = cache.dict_code fcnt_check_cache = dict_code_cache['fcntCheck'] if value not in fcnt_check_cache.keys(): raise DataNotFound(field='fcntCheck') @pre_load def handle_origin_data(self, data): lora_type = data['type'] if lora_type == 'otaa': data['ottaInfo'] = LoRaOTTASchema().load(data).data elif lora_type == 'abp': data['abpInfo'] = LoRaABPSchema().load(data).data return data @post_load def handle_validated_data(self, data): lora_type = data['type'] if lora_type == 'otaa': otta_info = data.pop('ottaInfo') data.update(otta_info) elif lora_type == 'abp': abp_info = data.pop('abpInfo') data.update(abp_info) return data
class TenantSchema(BaseSchema): tenantType = EmqInteger(required=True, validate=OneOf([1, 2])) tenantID = EmqString(allow_none=True, len_max=9) company = EmqString(allow_none=True) companySize = EmqString(allow_none=True) companyAddress = EmqString(allow_none=True) contactPerson = EmqString(allow_none=True) contactPhone = EmqString(allow_none=True) contactEmail = EmqEmail(allow_none=True) enable = EmqInteger(dump_only=True) tenantBalance = EmqFloat(dump_only=True) invoiceBalance = EmqFloat(dump_only=True) logo = EmqInteger() logoDark = EmqInteger() @validates('company') def company_is_exist(self, value): tenant_type = request.get_json().get('tenantType') if value == '': raise APIException() if tenant_type == 2 and Tenant.query.filter_by(company=value).first(): raise DataExisted(field='company') @post_dump def convert_image(self, data): api_version = current_app.config['ACTORCLOUD_API'] logo_id = data.get('logo') logo_dark_id = data.get('logoDark') logo = UploadInfo.query.filter(UploadInfo.id == logo_id).first() logo_dark = UploadInfo.query.filter(UploadInfo.id == logo_dark_id).first() if logo: logo_light_info = { 'name': logo.displayName, 'uploadID': logo.id, 'url': f'{api_version}/download?fileType=image&filename={logo.fileName}' } else: logo_light_info = { 'name': 'logo.png', 'uploadID': 0, 'url': f'{api_version}/backend_static?fileType=image&filename=logo.png' } if logo_dark: logo_dark_info = { 'name': logo_dark.displayName, 'uploadID': logo_dark.id, 'url': f'{api_version}/download?fileType=image&filename={logo_dark.fileName}' } else: logo_dark_info = { 'name': 'logo-dark.png', 'uploadID': 0, 'url': f'{api_version}/backend_static?fileType=image&filename=logo-dark.png' } data['logo'] = logo_light_info data['logoDark'] = logo_dark_info return data
class InvitationSchema(BaseSchema): userIntID = EmqInteger(allow_none=True) inviteEmail = EmqEmail(required=True) roleIntID = EmqInteger(required=True) tenantID = EmqString(allow_none=True, len_max=9) inviteStatus = EmqInteger(allow_none=True, validate=OneOf([0, 1])) @validates('inviteEmail') def validate_invite_email(self, value): email = Invitation.query \ .filter_tenant(tenant_uid=g.tenant_uid)\ .filter(Invitation.inviteEmail == value).first() if email: raise DataExisted(field='inviteEmail') email = User.query.filter(User.email == value).first() if email: raise DataExisted(field='email')
class UserSchema(BaseSchema): username = EmqString(required=True) email = EmqEmail(required=True) password = EmqString(required=True, len_min=6, len_max=100, load_only=True) enable = EmqInteger(allow_none=True) nickname = EmqString(allow_none=True) phone = EmqString(allow_none=True, len_max=15) department = EmqString(allow_none=True) lastRequestTime = EmqDateTime(allow_none=True) loginTime = EmqDateTime(allow_none=True) expiresAt = EmqDateTime(allow_none=True) roleIntID = EmqInteger(allow_none=True) userAuthType = EmqInteger(allow_none=True, validate=OneOf([1, 2])) groups = EmqList(allow_none=True, list_type=str, load_only=True) tenantID = EmqString(dump_only=True) @validates('username') def validate_username(self, value): if value in current_app.config.get('RESERVED'): raise FormInvalid(field='username') @validates('email') def email_is_exist(self, value): try: split_email = value.split('@')[0] if split_email in current_app.config.get('RESERVED'): raise FormInvalid(field='email') except Exception: raise FormInvalid(field='email') email = User.query.filter(User.email == value).first() if email: raise DataExisted(field='email') @post_load def handle_user_auth_type(self, data): if 'user_id' not in g: data['userAuthType'] = 1 groups_uid = self.get_request_data(key='groups') auth_type = data.get('userAuthType') if auth_type not in (1, 2): raise FormInvalid(field='userAuthType') if auth_type == 2 and groups_uid: groups = Group.query \ .filter_tenant(tenant_uid=g.tenant_uid) \ .filter(Group.groupID.in_(set(groups_uid))).all() if len(groups_uid) != len(groups): raise DataNotFound(field='groups') data['groups'] = groups else: data.pop('groups', None) return data