Package: onlyuserclient
onlyuserclient统一认证服务Onlyuser客户端开发包,配合Onlyuser在微服务中实现：角色权限控制，包括数据记录和字段权限控制。计费相关功能依赖包django >= 2.0.0djangorestframework >= 3.10.0发布包pythonsetup.pybdist_wheel
twineupload-utangdyy-pTdy741013./dist/*安装源码包安装pythonsetup.pyinstallpip安装pipinstallonlyuserclient# 升级pipinstall-Uonlyuserclient快速开始1.修改配置文件settings.py1.1.添加中间件到配置中MIDDLEWARE=['....',# 角色权限中间件'onlyuserclient.middleware.RoleMiddleware',# 计费控制中间件'onlyuserclient.middleware.BillingMiddleware',]1.2.添加onlyuserclient配置ONLYUSERCLIENT={'API_ROOT_URL':'http://dev.onlyuser','API_TIMEOUT':5,'API_HEADERS':{},'APIKEY_HEADER':'apikey','APIKEY':'','CACHE_API':False,'CACHE_TTL':60,}API_ROOT_URLonlyuser服务的根URL, 根据实际部署环境正确配置。API_TIMEOUTonlyuser的API接口访问超时(秒), 默认30秒。API_HEADERS需要附加到访问onlyuser的请求中的http header,  是一个健值对，KEY就header名，VALUE是header值。APIKEY_HEADER如果从集群外访问onlyuser，访问接口要求用key-auth方式鉴权，此配置项指定携带KEY的http header名称，默认是apikey，实际名称要与onlyuser服务端配置一致。APIKEYkey-auth的KEY，由onlyuser服务端提供。如果为None，表示不需要认证，默认是None。CACHE_API是否在本地缓存API访问结果，默认是False。onlyuserclient是使用Django内建的缓存功能，当你开启此项时，还需要同时配置settings.py中的CACHES。CACHE_TTL缓存有效时间，默认60秒。1.3.添加计费配配置项BILLINGCLIENT={# 计费服务器Restful接口URL'API_ROOT_URL':'http://dev.billing',# API URL前缀'API_PFX':None,# 计费服务器Restful接口超时(秒)'API_TIMEOUT':5,# 缓存远程接口'CACHE_API':False,# 缓存存活时间(秒)'CACHE_TTL':60,# 属于应用服务'APPLICATION_SERVICE':True,# 此项目提供的服务项目列表'SERVICE_ITEMS':{'insurance':('b6b962b2-198d-490d-bab1-14765212bbbe','汽车保险算价服务  ',None),},# 缓存引擎'CACHE_ENGINE':'cache',# 本地模式,如果允许，将不会访问远程服务器'LOCAL':False}API_ROOT_URL计费服务器API接口的根URLAPI_PFXURL前缀API_TIMEOUT计费服务器Restful接口超时(秒)CACHE_API是否缓存远程接口访问数据，默认是False。缓存接口访问数据可以大幅减少接口重复访问，极大提高后端性能，生产环境应当开启。CACHE_TTL接口缓存数据的生命期，默认60秒。此值大小需要权衡性能和数据更新及时性。APPLICATION_SERVICE此项目是否属于应用服务, 默认False。属于应用服务是指此项目提供的功能是应用程序的基础服务，计费上将受应用程序类服务项目的控制，比如：名单管理是车险营销管理系统的基础功能，不单独计费，名单管理微服务项目的配置项APPLICATION_SERVICE应当设为True。在视图类中可以设置类属性application_service配置视图类是否属于应用服务。在视图类方法的计费装饰器apiview_charge的初始化参数中可以设置参数application_service，配置视图类方法是否属于应用服务。这三个配置项的优先级：配置项APPLICATION_SERVICE> 类属性application_service>  装饰器apiview_charge参数application_serviceSERVICE_ITEMS此项目提供的服务项目的计费配置，dict类型。格式如下：{'key':('计费服务项目的label','服务项目名称','计费处理类'),'insurance':('b6b962b2-198d-490d-bab1-14765212bbbe','汽车保险算价服务  ',None),}CACHE_ENGINE缓存引擎，django配置项CACHES的key值。生产环境建议用数据库、membercache等高性能缓存引擎。LOCAL本地模式，如果允许，将不会访问远程服务器，用于代码编程阶段，不便于链接计费服务器时，默认是False。2.确定字段权限控制方案，定义序列化类确定要控制字段显示和字段修改权限的场景，并分别定义多个序列化类，每个场景对应一个序列化类，并定义一个标签。例如:  序列化类有三个字段name，mobile，address。第一种情况允许用户修改所有字段并完整显示全部字段, 用标签all代表；第二种情况用户不能修改mobile字段，并且隐藏mobile字段中间4位，用*号代替, 用标签part代表；第三种情况全部字段都只能查看不能修改，并且隐藏address字段, 用*号代替, 用标签readonly代表；定义三个序列化类fromrest_frameworkimportserializersfrom.modelsimportDemofromonlyuserclient.serializersimportHideCharFieldclassAllDemoSerializer(serializers.ModelSerializer):classMeta:model=Demofields="__all__"classPartDemoSerializer(serializers.ModelSerializer):mobile=HideCharField(max_length=11,hide_start=3,hide_end=7,fill_char='*')classMeta:model=Demofields="__all__"read_only_fields=['mobile']classReadonlyDemoSerializer(serializers.ModelSerializer):address=HideCharField(max_length=11,hide_start=0,hide_end=-1,fill_char='*')classMeta:model=Demofields="__all__"read_only_fields=['name','mobile','address']3.定义视图集类从onlyuserclient.viewsets.RoleModelViewSet继承。这个类默认实现了按组织机构控制的数据记录权限控制,定义了五个标签:all可以访问全部记录owner可以访问用户自已拥有的记录department可以访问本部门的全部用户的记录branch可以访问本部门及下属机构全部用户的记录organization可以操作所在组织整个组织机构树下全部用户的记录视图类除了ModelViewSet的标准属性外，需要定义以下属性：queryset必须定义，是Model的QuerySet对象。user_relate_field必须定义，Model中关联User的字段名，此字段保存User对象的ID值，类型为CHAR(24)。serializer_classs必须定义，dict类型，key是tag, value是序列化类。org_relate_field可选，保存Organization对象ID，默认是关联到根组织。allow_not_auth可选，是否允许未鉴权访问，默认False。createrv1.0.10 增加。可选，记录创建者字段名，如果有这个属性，将根据登录用户自动填充创建者和创建时间字段。属性值：True, 默认字段名creater、create_time。list对象，自定义字段名，第一个元素是创建者字段名，第二个是创建时间字段名。reviserv1.0.10 增加。可选，记录修改者字段名，如果有这个属性，将根据登录用户自动填充修改者和修改时间字段。属性值：True, 默认字段名reviser、modify_time。list对象，自定义字段名，第一个元素是修改者字段名，第二个是修改时间字段名。fromonlyuserclient.viewsetsimportRoleModelViewSetfrom.serializersimportDefaultDemoSerializer,CompleteDemoSerializer,HideDemoSerializerfrom.modelsimportRoleDemoclassRoleViewSet(RoleModelViewSet):queryset=RoleDemo.objects.all()user_relate_field='owner'serializer_classs={'default':DefaultDemoSerializer,'complete':CompleteDemoSerializer,'part':HideDemoSerializer}4.相关序列化字段参考HideCharField可以部分隐藏的字符串字段，除了标准属性外，有以下属性：fill_char隐藏部分的填充字符，默认是*。hide_start隐藏开始位置，从0开始。hide_end隐藏结束位置，如果-1，表示到结尾。RemotePkRelatedField主键远程关联字段，本地保存的字段值是远程资源的主键，有以下属性：resource远程资源名action查询资源对象的方法，默认就retrieve。fields序列化的资源字段列表remote_api一个simple_rest_client.api.API对象，访问远程资源，只能在子类中定义，默认是onlyuserapi。UserRelatedFieldonlyuser的User关联字段OrganizationRelatedFieldonlyuser的Organization关联字段SummaryRelatedField关联字段摘要信息字段ApplicationRelatedFieldonlyuser的Application关联字段SelecterField选项字段，在序列化类中定义属性serializer_choice_field，值等于SelecterField。5.ChoicesModelMixin类为模型视图类混入选项字段的选项列表查询方法。classResourceViewSet(RoleModelViewSet,ChoicesModelMixin):pass查询选项列表URLGETresources/choices返回结果格式{"field1":[["value1","label1"],["value2","label2"]],"field2":[["value1","label1"],["value2","label2"]]}6.实现API接口计费方法参照上面1.3.配置，并在SERVICE_ITEMS中添加计费服务项目配置。修改需要计费的视图类方法，添加装饰器apiview_charge。注意：如有多个装饰器，apiview_charge应当放到最下面。fromonlyuserclient.decoratorimportapiview_chargeclassDemoViewSet(viewsets.ViewSet):# 参见1.3.中说明application_service=False@action(detail=True,methods=['post'],url_name='bill-postpay',url_path='bill-postpay')@apiview_charge(# 配置项 `SERVICE_ITEMS` 中的KEYservice_key='insurance',# 方法调用前需要计费检查before=True,# 方法调用后需要提交计费结果after=True,# 方法调用前的计费检查只检查服务可用否，`before` 是 `True` 时有效usable=True,# 参见1.3.中说明application_service=False)defbill_postpay(self,request,pk=None):data={'code':1,'result':'this is demo bill_postpay.'}returnResponse(data)API 参考onlyuserclient.api.onlyuserapi实例对象onlyuserapi是simple_rest_client.api.API的实例对象，将一系列 onlyuser api 接口封装为实例方法。1.onlyuserapi.apply_application(application, user, organization=None)计费相关接口方法，检查用户是否可以访问应用程序。即：用户或用户所在组织关联的计费账号开通了相关应用程序服务项目，项目在启用状态，计费账户状态符合条件。参数：application应用程序IDuser登录用户IDorganization当前组织ID返回值：(code, detail)code数值类型，是 0 表示可以使用，其他值不允许使用；detail字符串，结果的详细说明。2.onlyuserclient.get_organization_billaccount(organization_id)计费相关接口方法，查询组织绑定的计费账号参数：organization_id组织机构的ID返回值：计费账号，字符串 或None。3.onlyuserclient.get_application_info(application_id)查询应用程序的详细信息参数：application_id应用程序的ID返回值：应用程序信息详细信息，dict或None。4.onlyuserclient.get_organization_info(organization_id)查询组织的详细信息参数：organization_id组织的ID返回值：组织的详细信息，dict或None。5.onlyuserclient.get_user_info(user_id)查询用户的详细信息参数：user_id用户的ID返回值：用户的详细信息，dict或None。onlyuserclient.api.billingapi实例对象billingapi是simple_rest_client.api.API的实例对象，将一系列 wellbill api 接口封装为实例方法。1.billingapi.get_account_by_user(userid)检查用户的计费账号。参数：userid登录用户ID返回值：计费账号，字符串。
异常：
计费账号不存在时，产生异常：onlyuserclient.api.billing.BillAccountNotExist。onlyuserclient.grpc.billing.counter模块1.2.0 增加服务程序计费 gRpc 接口。CounterClient对象CounterClient对象提供服务程序与计费系统通信的接口方法。class CounterClient(server=None, max_retres=None, max_backoff=None, dns_timeout=None)参数：server计费系统 grpc 服务器地址，默认localhost:50051。max_retres最大重连次数 2-5， 0 不重连，默认 5。max_backoff最长退出时间，默认5秒，格式 '5s'。CounterClient.create_account(owner, kind, name)创建计费帐户。此方法通常由`onlyuser`调用。参数：owner绑定计费帐户的用户ID。kind帐户类别， 0 个人帐户，1 公司帐户。name帐户名称。返回值：Response对象，包含属性：idaccnonamebalancecreditwarningstatekindCounterClient.query_account(userid, applicationid, organizationid)查询用户或者组织绑定的计费帐户。参数：userid用户ID。applicationid应用程序ID。organizationid组组ID。注意：参数需要提供userid或者applicationid和organizationid。返回值：Response对象，包含属性：idaccnonamebalancecreditwarningstatekindCounterClient.usable_service(accno, label, count=1)检查服务是否可用。返回结果 `False` 或者发生异常，表示服务不可用，服务提供者应当中止服务。参数：accno计费帐号。label服务项目标签。count准备使用的服务资源数量。默认值1。返回值：布尔类型，True服务可用，False服务不可用。CounterClient.start_service(accno, label, providerno, start_time=None, count=1, summary=None, application=None, organization=None, expire=None, usable=False)开始服务项目计费。参数：accno计费帐号。label服务项目标签。providerno服务提供者序列号。用于唯一标识服务记录，可以使用objectid，freeswitch 话单的 uuid 等。start_time服务计费开始时间，带UTC时区的datetime对象。如果是None，默认是接口调用时间。count服务资源数量。默认值1。summary服务摘要。对服务记录的简要描述，应当包括一些关键词，以便于理解服务内容。默认值None。application应用程序ID。默认值None。organization组织ID。默认值None。expire计费保持超时间间，带UTC时区的datetime对象，超过此时间计费服务器强制结束服务计费，如果None不进行超时检查。 默认值None。usable是否只检查服务可用。默认值False。返回值：Response对象，包含属性：svcnoexpireCounterClient.end_service(accno, label, providerno, start_time, svcno=None, finish_time=None, count=1, summary=None, application=None，organization=None)结束服务计费。具备服务端断线重试功能。参数：accno计费帐号。label服务项目标签。providerno服务提供者序列号。用于唯一标识服务记录，可以使用objectid，freeswitch 话单的 uuid 等。start_time服务计费开始时间，带UTC时区的datetime对象。svcno服务流水号。默认值None。finish_time服务计费结束时间，带UTC时区的datetime对象。如果是None，默认是接口调用时间。count服务资源数量。默认值1。summary服务摘要。对服务记录的简要描述，应当包括一些关键词，以便于理解服务内容。默认值None。application应用程序ID。默认值None。organization组织ID。默认值None。返回值：Response对象，包含属性：svcnostart_timefinish_timecountcostCounterClient.increase_resource(accno, label, count=1, total=None):申请增加服务项目的资源占用。如果发生异常，申请失败；返回 Response 对象，申请成功。参数：accno计费帐号。label服务项目标签。count申请增加占用的服务资源数量。默认值1。total增加占用的服务资源后，计费帐户占用的资源总数。默认None，由计费服务器计算。返回值：usagelimitsCounterClient.reduce_resource(accno, label, count=1, total=None):申请减少服务项目的资源占用。如果发生异常，申请失败；返回 Response 对象，申请成功。参数：accno计费帐号。label服务项目标签。count申请减少占用的服务资源数量。默认值1。total减少占用的服务资源后，计费帐户占用的资源总数。默认None，由计费服务器计算。返回值：usagelimitsCounterClient.query_subaccounts(parent, label=None):计费子帐户查询。    
如果 label 是 None, 返回结果是主帐户下全部子帐户帐号列表。
如果 label 不是 None, 返回结果是开通服务项目的 主帐户及子帐户 帐号列表。参数：parent主帐户帐号。label服务项目标签。返回值：帐号列表,list类型使用 gRPC 接口实现服务功能按次计费示例代码：fromonlyuserclient.grpc.billingimportcounterclient=counter.CounterClient()# 检查计费帐户是否可以使用该服务项目ifclient.usable_service(accno,label,count=1):# 功能代码调用fun()# 调用成功，结束服务计费。client.end_service(accno,svcno,label,providerno,start_time,finish_time,count,summary,application，organization)