mirror of
https://github.com/capricornxl/ad-password-self-service.git
synced 2025-08-11 15:46:13 +08:00
### 2021/05/19 -- 更新:
+ 添加了企业微信支持,修改pwdselfservice/local_settings.py中的SCAN_CODE_TYPE = 'DING'或SCAN_CODE_TYPE = 'WEWORK',区分使用哪个应用扫码验证 + 添加Reids缓存Token支持,如果不配置Redis则使用MemoryStorage缓存到内存中
This commit is contained in:
@@ -46,7 +46,7 @@ class AdOps(object):
|
||||
self.authentication = authentication
|
||||
self.auto_bind = auto_bind
|
||||
|
||||
server = Server(host='%s' % AD_HOST, use_ssl=self.use_ssl, port=port, get_info=ALL)
|
||||
server = Server(host='%s' % AD_HOST, connect_timeout=1, use_ssl=self.use_ssl, port=port, get_info=ALL)
|
||||
try:
|
||||
self.conn = Connection(server, auto_bind=self.auto_bind, user=r'{}\{}'.format(self.domain, self.user), password=self.password,
|
||||
authentication=self.authentication, raise_exceptions=True)
|
||||
@@ -115,7 +115,7 @@ class AdOps(object):
|
||||
|
||||
def ad_get_user_dn_by_account(self, username):
|
||||
"""
|
||||
通过mail查询某个用户的完整DN
|
||||
通过username查询某个用户的完整DN
|
||||
:param username:
|
||||
:return: DN
|
||||
"""
|
||||
@@ -179,7 +179,7 @@ class AdOps(object):
|
||||
|
||||
def ad_get_user_locked_status_by_account(self, username):
|
||||
"""
|
||||
通过mail获取某个用户账号是否被锁定
|
||||
通过username获取某个用户账号是否被锁定
|
||||
:param username:
|
||||
:return: 如果结果是1601-01-01说明账号未锁定,返回0
|
||||
"""
|
||||
|
@@ -9,47 +9,31 @@ from urllib.parse import quote
|
||||
|
||||
import requests
|
||||
from dingtalk.client import AppKeyClient
|
||||
from pwdselfservice import cache_storage
|
||||
|
||||
from pwdselfservice.local_settings import DING_APP_KEY, DING_APP_SECRET, DING_CORP_ID, DING_URL, DING_MO_APP_ID, DING_MO_APP_SECRET
|
||||
|
||||
|
||||
class DingDingOps(object):
|
||||
def __init__(self, corp_id=DING_CORP_ID, app_key=DING_APP_KEY, app_secret=DING_APP_SECRET, mo_app_id=DING_MO_APP_ID, mo_app_secret=DING_MO_APP_SECRET):
|
||||
def __init__(self, corp_id=DING_CORP_ID, app_key=DING_APP_KEY, app_secret=DING_APP_SECRET, mo_app_id=DING_MO_APP_ID, mo_app_secret=DING_MO_APP_SECRET, storage=cache_storage):
|
||||
self.corp_id = corp_id
|
||||
self.app_key = app_key
|
||||
self.app_secret = app_secret
|
||||
self.mo_app_id = mo_app_id
|
||||
self.mo_app_secret = mo_app_secret
|
||||
self.storage = storage
|
||||
|
||||
@property
|
||||
def ding_client_connect(self):
|
||||
def _client_connect(self):
|
||||
"""
|
||||
钉钉连接器
|
||||
:return:
|
||||
"""
|
||||
return AppKeyClient(corp_id=self.corp_id, app_key=self.app_key, app_secret=self.app_secret)
|
||||
|
||||
@property
|
||||
def ding_get_access_token(self):
|
||||
def get_union_id_by_code(self, code):
|
||||
"""
|
||||
获取企业内部应用的access_token
|
||||
:return:
|
||||
"""
|
||||
return self.ding_client_connect.access_token
|
||||
|
||||
def ding_get_dept_user_list_detail(self, dept_id, offset, size):
|
||||
"""
|
||||
获取部门中的用户列表详细清单
|
||||
:param dept_id: 部门ID
|
||||
:param offset: 偏移量(可理解为步进量)
|
||||
:param size: 一次查询多少个
|
||||
:return:
|
||||
"""
|
||||
return self.ding_client_connect.user.list(department_id=dept_id, offset=offset, size=size)
|
||||
|
||||
def ding_get_union_id_by_code(self, code):
|
||||
"""
|
||||
通过移动应用接入扫码返回的临时授权码,获取用户的unionid
|
||||
通过移动应用接入扫码返回的临时授权码,使用临时授权码换取用户的unionid
|
||||
:param code:
|
||||
:return:
|
||||
"""
|
||||
@@ -68,57 +52,36 @@ class DingDingOps(object):
|
||||
json=dict(tmp_auth_code=code),
|
||||
)
|
||||
resp = resp.json()
|
||||
print(resp)
|
||||
try:
|
||||
if resp['errcode'] != 0:
|
||||
return False, 'ding_get_union_id_by_code: %s' % str(resp)
|
||||
return False, 'get_union_id_by_code: %s' % str(resp)
|
||||
else:
|
||||
return True, resp["user_info"]["unionid"]
|
||||
except Exception:
|
||||
return False, 'ding_get_union_id_by_code: %s' % str(resp)
|
||||
return False, 'get_union_id_by_code: %s' % str(resp)
|
||||
|
||||
def ding_get_userid_by_union_id(self, union_id):
|
||||
def get_user_id_by_code(self, code):
|
||||
"""
|
||||
通过unionid获取用户的userid
|
||||
:param union_id: 用户在当前钉钉开放平台账号范围内的唯一标识
|
||||
通过code获取用户的userid
|
||||
:param id: 用户在当前钉钉开放平台账号范围内的唯一标识
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
return True, self.ding_client_connect.user.get_userid_by_unionid(union_id)['userid']
|
||||
except Exception as e:
|
||||
return False, 'ding_get_union_id_by_code: %s' % str(e)
|
||||
_status, union_id = self.get_union_id_by_code(code)
|
||||
if _status:
|
||||
return True, self._client_connect.user.get_userid_by_unionid(union_id).get('userid')
|
||||
else:
|
||||
return False, 'get_user_id_by_code: %s' % str(union_id)
|
||||
|
||||
except (KeyError, IndexError) as k_error:
|
||||
return False, 'ding_get_union_id_by_code: %s' % str(k_error)
|
||||
|
||||
@property
|
||||
def ding_get_org_user_count(self):
|
||||
"""
|
||||
企业员工数量
|
||||
only_active – 是否包含未激活钉钉的人员数量
|
||||
:return:
|
||||
"""
|
||||
return self.ding_client_connect.user.get_org_user_count('only_active')
|
||||
|
||||
def ding_get_userinfo_detail(self, user_id):
|
||||
def get_user_detail_by_user_id(self, user_id):
|
||||
"""
|
||||
通过user_id 获取用户详细信息
|
||||
user_id – 用户ID
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
return True, self.ding_client_connect.user.get(user_id)
|
||||
return True, self._client_connect.user.get(user_id)
|
||||
except Exception as e:
|
||||
return False, 'ding_get_union_id_by_code: %s' % str(e)
|
||||
return False, 'get_user_detail_by_user_id: %s' % str(e)
|
||||
|
||||
except (KeyError, IndexError) as k_error:
|
||||
return False, 'ding_get_union_id_by_code: %s' % str(k_error)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start = time.time()
|
||||
d = DingDingOps().ding_client_connect
|
||||
unicode = ''
|
||||
# print(d.)
|
||||
end = time.time()
|
||||
print("running:" + str(round((end - start), 3)))
|
||||
return False, 'get_user_detail_by_user_id: %s' % str(k_error)
|
||||
|
@@ -24,12 +24,22 @@ def format2username(account):
|
||||
elif re.fullmatch(domain_compile, account):
|
||||
return re.fullmatch(domain_compile, account).group(2)
|
||||
else:
|
||||
return account
|
||||
return account.lower()
|
||||
else:
|
||||
raise NameError("输入的账号不能为空..")
|
||||
|
||||
|
||||
def get_user_is_active(user_info):
|
||||
try:
|
||||
return True, user_info.get('active') or user_info.get('status')
|
||||
except Exception as e:
|
||||
return False, 'get_user_is_active: %s' % str(e)
|
||||
|
||||
except (KeyError, IndexError) as k_error:
|
||||
return False, 'get_user_is_active: %s' % str(k_error)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
user = 'aaa\jf.com'
|
||||
user = 'jf.com\XiangLe'
|
||||
username = format2username(user)
|
||||
print(username)
|
||||
|
23
utils/storage/__init__.py
Normal file
23
utils/storage/__init__.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
|
||||
class BaseStorage(object):
|
||||
|
||||
def get(self, key, default=None):
|
||||
raise NotImplementedError()
|
||||
|
||||
def set(self, key, value, ttl=None):
|
||||
raise NotImplementedError()
|
||||
|
||||
def delete(self, key):
|
||||
raise NotImplementedError()
|
||||
|
||||
def __getitem__(self, key):
|
||||
self.get(key)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self.set(key, value)
|
||||
|
||||
def __delitem__(self, key):
|
||||
self.delete(key)
|
58
utils/storage/cache.py
Normal file
58
utils/storage/cache.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import inspect
|
||||
|
||||
from utils.storage import BaseStorage
|
||||
|
||||
|
||||
def _is_cache_item(obj):
|
||||
return isinstance(obj, CacheItem)
|
||||
|
||||
|
||||
class CacheItem(object):
|
||||
|
||||
def __init__(self, cache=None, name=None):
|
||||
self.cache = cache
|
||||
self.name = name
|
||||
|
||||
def key_name(self, key):
|
||||
if isinstance(key, (tuple, list)):
|
||||
key = ':'.join(key)
|
||||
|
||||
k = '{0}:{1}'.format(self.cache.prefix, self.name)
|
||||
if key is not None:
|
||||
k = '{0}:{1}'.format(k, key)
|
||||
return k
|
||||
|
||||
def get(self, key=None, default=None):
|
||||
return self.cache.storage.get(self.key_name(key), default)
|
||||
|
||||
def set(self, key=None, value=None, ttl=None):
|
||||
return self.cache.storage.set(self.key_name(key), value, ttl)
|
||||
|
||||
def delete(self, key=None):
|
||||
return self.cache.storage.delete(self.key_name(key))
|
||||
|
||||
|
||||
class BaseCache(object):
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
self = super(BaseCache, cls).__new__(cls)
|
||||
api_endpoints = inspect.getmembers(self, _is_cache_item)
|
||||
for name, api in api_endpoints:
|
||||
api_cls = type(api)
|
||||
api = api_cls(self, name)
|
||||
setattr(self, name, api)
|
||||
return self
|
||||
|
||||
def __init__(self, storage, prefix='client'):
|
||||
assert isinstance(storage, BaseStorage)
|
||||
self.storage = storage
|
||||
self.prefix = prefix
|
||||
|
||||
|
||||
class WeWorkCache(BaseCache):
|
||||
access_token = CacheItem()
|
||||
|
||||
|
37
utils/storage/kvstorage.py
Normal file
37
utils/storage/kvstorage.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import json
|
||||
|
||||
from dingtalk.core.utils import to_text
|
||||
from utils.storage import BaseStorage
|
||||
|
||||
|
||||
class KvStorage(BaseStorage):
|
||||
|
||||
def __init__(self, kvdb, prefix='wework'):
|
||||
for method_name in ('get', 'set', 'delete'):
|
||||
assert hasattr(kvdb, method_name)
|
||||
self.kvdb = kvdb
|
||||
self.prefix = prefix
|
||||
|
||||
def key_name(self, key):
|
||||
return '{0}:{1}'.format(self.prefix, key)
|
||||
|
||||
def get(self, key, default=None):
|
||||
key = self.key_name(key)
|
||||
value = self.kvdb.get(key)
|
||||
if value is None:
|
||||
return default
|
||||
return json.loads(to_text(value))
|
||||
|
||||
def set(self, key, value, ttl=None):
|
||||
if value is None:
|
||||
return
|
||||
key = self.key_name(key)
|
||||
value = json.dumps(value)
|
||||
self.kvdb.set(key, value, ttl)
|
||||
|
||||
def delete(self, key):
|
||||
key = self.key_name(key)
|
||||
self.kvdb.delete(key)
|
32
utils/storage/memorystorage.py
Normal file
32
utils/storage/memorystorage.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import time
|
||||
|
||||
from utils.storage import BaseStorage
|
||||
|
||||
|
||||
class MemoryStorage(BaseStorage):
|
||||
|
||||
def __init__(self):
|
||||
self._data = {}
|
||||
|
||||
def get(self, key, default=None):
|
||||
ret = self._data.get(key, None)
|
||||
if ret is None or len(ret) != 2:
|
||||
return default
|
||||
else:
|
||||
value = ret[0]
|
||||
expires_at = ret[1]
|
||||
if expires_at is None or expires_at > time.time():
|
||||
return value
|
||||
else:
|
||||
return default
|
||||
|
||||
def set(self, key, value, ttl=None):
|
||||
if value is None:
|
||||
return
|
||||
self._data[key] = (value, int(time.time()) + ttl)
|
||||
|
||||
def delete(self, key):
|
||||
self._data.pop(key, None)
|
113
utils/wework_api/AbstractApi.py
Normal file
113
utils/wework_api/AbstractApi.py
Normal file
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding:utf-8 -*-
|
||||
|
||||
import json
|
||||
|
||||
import requests
|
||||
|
||||
DEBUG = False
|
||||
|
||||
|
||||
class ApiException(Exception):
|
||||
def __init__(self, errCode, errMsg):
|
||||
self.errCode = errCode
|
||||
self.errMsg = errMsg
|
||||
|
||||
|
||||
class AbstractApi(object):
|
||||
def __init__(self):
|
||||
return
|
||||
|
||||
def access_token(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def http_call(self, url_type, args=None):
|
||||
short_url = url_type[0]
|
||||
method = url_type[1]
|
||||
response = {}
|
||||
for retryCnt in range(0, 3):
|
||||
if 'POST' == method:
|
||||
url = self.__make_url(short_url)
|
||||
response = self.__http_post(url, args)
|
||||
elif 'GET' == method:
|
||||
url = self.__make_url(short_url)
|
||||
url = self.__append_args(url, args)
|
||||
response = self.__http_get(url)
|
||||
else:
|
||||
raise ApiException(-1, "unknown method type")
|
||||
|
||||
# check if token expired
|
||||
if self.__token_expired(response.get('errcode')):
|
||||
self.__refresh_token(short_url)
|
||||
retryCnt += 1
|
||||
continue
|
||||
else:
|
||||
break
|
||||
|
||||
return self.__check_response(response)
|
||||
|
||||
@staticmethod
|
||||
def __append_args(url, args):
|
||||
if args is None:
|
||||
return url
|
||||
|
||||
for key, value in args.items():
|
||||
if '?' in url:
|
||||
url += ('&' + key + '=' + value)
|
||||
else:
|
||||
url += ('?' + key + '=' + value)
|
||||
return url
|
||||
|
||||
@staticmethod
|
||||
def __make_url(short_url):
|
||||
base = "https://qyapi.weixin.qq.com"
|
||||
if short_url[0] == '/':
|
||||
return base + short_url
|
||||
else:
|
||||
return base + '/' + short_url
|
||||
|
||||
def __append_token(self, url):
|
||||
if 'ACCESS_TOKEN' in url:
|
||||
return url.replace('ACCESS_TOKEN', self.access_token())
|
||||
else:
|
||||
return url
|
||||
|
||||
def __http_post(self, url, args):
|
||||
real_url = self.__append_token(url)
|
||||
|
||||
if DEBUG is True:
|
||||
print(real_url, args)
|
||||
|
||||
return requests.post(real_url, data=json.dumps(args, ensure_ascii=False).encode('utf-8')).json()
|
||||
|
||||
def __http_get(self, url):
|
||||
real_url = self.__append_token(url)
|
||||
|
||||
if DEBUG is True:
|
||||
print(real_url)
|
||||
|
||||
return requests.get(real_url).json()
|
||||
|
||||
def __post_file(self, url, media_file):
|
||||
return requests.post(url, file=media_file).json()
|
||||
|
||||
@staticmethod
|
||||
def __check_response(response):
|
||||
errCode = response.get('errcode')
|
||||
errMsg = response.get('errmsg')
|
||||
|
||||
if errCode == 0:
|
||||
return response
|
||||
else:
|
||||
raise ApiException(errCode, errMsg)
|
||||
|
||||
@staticmethod
|
||||
def __token_expired(errCode):
|
||||
if errCode == 40014 or errCode == 42001 or errCode == 42007 or errCode == 42009:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def __refresh_token(self, url):
|
||||
if 'ACCESS_TOKEN' in url:
|
||||
self.access_token()
|
140
utils/wework_ops.py
Normal file
140
utils/wework_ops.py
Normal file
@@ -0,0 +1,140 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# @FileName: WEWORK_ops.py
|
||||
# @Software:
|
||||
# @Author: Leven Xiang
|
||||
# @Mail: xiangle0109@outlook.com
|
||||
# @Date: 2021/5/18 16:55
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from pwdselfservice import cache_storage
|
||||
|
||||
from pwdselfservice.local_settings import *
|
||||
from utils.storage.cache import WeWorkCache
|
||||
from utils.wework_api.AbstractApi import *
|
||||
|
||||
CORP_API_TYPE = {
|
||||
'GET_ACCESS_TOKEN': ['/cgi-bin/gettoken', 'GET'],
|
||||
'USER_CREATE': ['/cgi-bin/user/create?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'USER_GET': ['/cgi-bin/user/get?access_token=ACCESS_TOKEN', 'GET'],
|
||||
'USER_UPDATE': ['/cgi-bin/user/update?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'USER_DELETE': ['/cgi-bin/user/delete?access_token=ACCESS_TOKEN', 'GET'],
|
||||
'USER_BATCH_DELETE': ['/cgi-bin/user/batchdelete?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'USER_SIMPLE_LIST': ['/cgi-bin/user/simplelist?access_token=ACCESS_TOKEN', 'GET'],
|
||||
'USER_LIST': ['/cgi-bin/user/list?access_token=ACCESS_TOKEN', 'GET'],
|
||||
'USERID_TO_OPENID': ['/cgi-bin/user/convert_to_openid?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'OPENID_TO_USERID': ['/cgi-bin/user/convert_to_userid?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'USER_AUTH_SUCCESS': ['/cgi-bin/user/authsucc?access_token=ACCESS_TOKEN', 'GET'],
|
||||
|
||||
'DEPARTMENT_CREATE': ['/cgi-bin/department/create?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'DEPARTMENT_UPDATE': ['/cgi-bin/department/update?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'DEPARTMENT_DELETE': ['/cgi-bin/department/delete?access_token=ACCESS_TOKEN', 'GET'],
|
||||
'DEPARTMENT_LIST': ['/cgi-bin/department/list?access_token=ACCESS_TOKEN', 'GET'],
|
||||
|
||||
'TAG_CREATE': ['/cgi-bin/tag/create?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'TAG_UPDATE': ['/cgi-bin/tag/update?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'TAG_DELETE': ['/cgi-bin/tag/delete?access_token=ACCESS_TOKEN', 'GET'],
|
||||
'TAG_GET_USER': ['/cgi-bin/tag/get?access_token=ACCESS_TOKEN', 'GET'],
|
||||
'TAG_ADD_USER': ['/cgi-bin/tag/addtagusers?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'TAG_DELETE_USER': ['/cgi-bin/tag/deltagusers?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'TAG_GET_LIST': ['/cgi-bin/tag/list?access_token=ACCESS_TOKEN', 'GET'],
|
||||
|
||||
'BATCH_JOB_GET_RESULT': ['/cgi-bin/batch/getresult?access_token=ACCESS_TOKEN', 'GET'],
|
||||
|
||||
'BATCH_INVITE': ['/cgi-bin/batch/invite?access_token=ACCESS_TOKEN', 'POST'],
|
||||
|
||||
'AGENT_GET': ['/cgi-bin/agent/get?access_token=ACCESS_TOKEN', 'GET'],
|
||||
'AGENT_SET': ['/cgi-bin/agent/set?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'AGENT_GET_LIST': ['/cgi-bin/agent/list?access_token=ACCESS_TOKEN', 'GET'],
|
||||
|
||||
'MENU_CREATE': ['/cgi-bin/menu/create?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'MENU_GET': ['/cgi-bin/menu/get?access_token=ACCESS_TOKEN', 'GET'],
|
||||
'MENU_DELETE': ['/cgi-bin/menu/delete?access_token=ACCESS_TOKEN', 'GET'],
|
||||
|
||||
'MESSAGE_SEND': ['/cgi-bin/message/send?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'MESSAGE_REVOKE': ['/cgi-bin/message/revoke?access_token=ACCESS_TOKEN', 'POST'],
|
||||
|
||||
'MEDIA_GET': ['/cgi-bin/media/get?access_token=ACCESS_TOKEN', 'GET'],
|
||||
|
||||
'GET_USER_INFO_BY_CODE': ['/cgi-bin/user/getuserinfo?access_token=ACCESS_TOKEN', 'GET'],
|
||||
'GET_USER_DETAIL': ['/cgi-bin/user/getuserdetail?access_token=ACCESS_TOKEN', 'POST'],
|
||||
|
||||
'GET_TICKET': ['/cgi-bin/ticket/get?access_token=ACCESS_TOKEN', 'GET'],
|
||||
'GET_JSAPI_TICKET': ['/cgi-bin/get_jsapi_ticket?access_token=ACCESS_TOKEN', 'GET'],
|
||||
|
||||
'GET_CHECKIN_OPTION': ['/cgi-bin/checkin/getcheckinoption?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'GET_CHECKIN_DATA': ['/cgi-bin/checkin/getcheckindata?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'GET_APPROVAL_DATA': ['/cgi-bin/corp/getapprovaldata?access_token=ACCESS_TOKEN', 'POST'],
|
||||
|
||||
'GET_INVOICE_INFO': ['/cgi-bin/card/invoice/reimburse/getinvoiceinfo?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'UPDATE_INVOICE_STATUS':
|
||||
['/cgi-bin/card/invoice/reimburse/updateinvoicestatus?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'BATCH_UPDATE_INVOICE_STATUS':
|
||||
['/cgi-bin/card/invoice/reimburse/updatestatusbatch?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'BATCH_GET_INVOICE_INFO':
|
||||
['/cgi-bin/card/invoice/reimburse/getinvoiceinfobatch?access_token=ACCESS_TOKEN', 'POST'],
|
||||
|
||||
'APP_CHAT_CREATE': ['/cgi-bin/appchat/create?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'APP_CHAT_GET': ['/cgi-bin/appchat/get?access_token=ACCESS_TOKEN', 'GET'],
|
||||
'APP_CHAT_UPDATE': ['/cgi-bin/appchat/update?access_token=ACCESS_TOKEN', 'POST'],
|
||||
'APP_CHAT_SEND': ['/cgi-bin/appchat/send?access_token=ACCESS_TOKEN', 'POST'],
|
||||
|
||||
'MINIPROGRAM_CODE_TO_SESSION_KEY': ['/cgi-bin/miniprogram/jscode2session?access_token=ACCESS_TOKEN', 'GET'],
|
||||
}
|
||||
|
||||
|
||||
class WeWorkOps(AbstractApi):
|
||||
def __init__(self, corp_id=WEWORK_CORP_ID, agent_id=WEWORK_AGENT_ID, agent_secret=WEWORK_AGNET_SECRET, storage=cache_storage, prefix='wework'):
|
||||
super().__init__()
|
||||
self.corp_id = corp_id
|
||||
self.agent_id = agent_id
|
||||
self.agent_secret = agent_secret
|
||||
self.storage = storage
|
||||
self.cache = WeWorkCache(self.storage, "%s:%s" % (prefix, "corp_id:%s" % self.corp_id))
|
||||
|
||||
def access_token(self):
|
||||
access_token = self.cache.access_token.get()
|
||||
if access_token is None:
|
||||
ret = self.get_access_token()
|
||||
access_token = ret['access_token']
|
||||
expires_in = ret.get('expires_in', 7200)
|
||||
self.cache.access_token.set(value=access_token, ttl=expires_in)
|
||||
return access_token
|
||||
|
||||
def get_access_token(self):
|
||||
return self.http_call(
|
||||
CORP_API_TYPE['GET_ACCESS_TOKEN'],
|
||||
{
|
||||
'corpid': self.corp_id,
|
||||
'corpsecret': self.agent_secret,
|
||||
})
|
||||
|
||||
def get_user_id_by_code(self, code):
|
||||
try:
|
||||
return True, self.http_call(
|
||||
CORP_API_TYPE['GET_USER_INFO_BY_CODE'],
|
||||
{
|
||||
'code': code,
|
||||
}).get('UserId')
|
||||
except ApiException as e:
|
||||
return False, "get_user_id_by_code: {}-{}" .format(e.errCode, e.errMsg)
|
||||
except Exception as e:
|
||||
return False, "get_user_id_by_code: {}".format(e)
|
||||
|
||||
def get_user_detail_by_user_id(self, user_id):
|
||||
try:
|
||||
return True, self.http_call(
|
||||
CORP_API_TYPE['USER_GET'],
|
||||
{
|
||||
'userid': user_id,
|
||||
})
|
||||
except ApiException as e:
|
||||
return False, "get_user_detail_by_user_id: {}-{}" .format(e.errCode, e.errMsg)
|
||||
except Exception as e:
|
||||
return False, "get_user_detail_by_user_id: {}".format(e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
wx = WeWorkOps()
|
||||
print(wx.get_user_detail_by_user_id('XiangLe'))
|
||||
|
Reference in New Issue
Block a user