forked from TencentBlueKing/bk-user
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature: 企业微信用户同步 TencentBlueKing#118
- Loading branch information
richardlu
committed
Nov 2, 2021
1 parent
8c633e0
commit b23c281
Showing
12 changed files
with
982 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# 创建插件目录 | ||
本地创建插件 | ||
对应的插件名称为 wecom | ||
domian 根据实际需要设置 | ||
```bash | ||
python manage.py create_pluggable_category --name 企业微信 --domain some-domain.com --plugin wecom | ||
``` | ||
默认地,以上步骤会创建一个 key 为 `wecom` 的 `Setting` 绑定到该目录。 | ||
|
||
|
||
# DB 初始化 | ||
配置同步所需的corpId和Secret | ||
category_id: step1创建的目录的ID | ||
settingmeta_wecom_corpid_id: settingmeta 表中key为wecom_corpid 的ID | ||
settingmeta_wecom_secret_id: settingmeta 表中key为wecom_secret 的ID | ||
```bash | ||
insert into user_settings_setting(create_time,update_time,value,enabled,category_id,meta_id) values(now(),now(),"",0,{category_id},${settingmeta_wecom_corpid_id}); | ||
insert into user_settings_setting(create_time,update_time,value,enabled,category_id,meta_id) values(now(),now(),"",0,{category_id},${settingmeta_wecom_secret_id}); | ||
``` | ||
|
||
# 其他 | ||
企业微信接口频率限制 | ||
https://work.weixin.qq.com/api/doc/90000/90139/90312 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-用户管理(Bk-User) available. | ||
Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. All rights reserved. | ||
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at http://opensource.org/licenses/MIT | ||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
specific language governing permissions and limitations under the License. | ||
""" | ||
from bkuser_core.categories.plugins.plugin import DataSourcePlugin | ||
|
||
from .login import LoginHandler | ||
from .syncer import WeComSyncer | ||
|
||
DataSourcePlugin( | ||
name="wecom", | ||
syncer_cls=WeComSyncer, | ||
login_handler_cls=LoginHandler, | ||
allow_client_write=True, | ||
category_type="pluggable", | ||
).register() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-用户管理(Bk-User) available. | ||
Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. All rights reserved. | ||
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at http://opensource.org/licenses/MIT | ||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
specific language governing permissions and limitations under the License. | ||
""" | ||
|
||
import requests | ||
import json | ||
import logging | ||
|
||
from dataclasses import dataclass | ||
from typing import TYPE_CHECKING | ||
|
||
from . import exceptions as local_exceptions | ||
from .constants import ACCESS_TOKEN_URL, DEPARTMENT_LIST_URL, USER_LIST_DETAIL | ||
|
||
|
||
if TYPE_CHECKING: | ||
from bkuser_core.user_settings.loader import ConfigProvider | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
@dataclass | ||
class WeComClient: | ||
|
||
config_provider: "ConfigProvider" | ||
|
||
def __post_init__(self): | ||
self.corpid = self.config_provider.get("wecom_corpid").get("wecom_corpid") | ||
self.secret = self.config_provider.get("wecom_secret").get("wecom_secret") | ||
self.access_token = "" | ||
|
||
@staticmethod | ||
def __request_get(url: str) -> dict: | ||
""" | ||
request get 请求 | ||
:param url: | ||
:return: | ||
""" | ||
try: | ||
response = requests.get(url) | ||
except Exception as e: | ||
logger.exception("request wecom api failed,url={}, error={}".format(url, e)) | ||
raise local_exceptions.WeComAPIRequestFailed | ||
if response.status_code != 200: | ||
logger.error("request wecom api failed,url={},status_code={}".format(url, response.status_code)) | ||
raise local_exceptions.WeComAPIRequestStatusCodeError | ||
else: | ||
try: | ||
result = json.loads(response.content) | ||
except Exception as e: | ||
logger.exception("json loads wecom api return fail, error={}".format(e)) | ||
raise local_exceptions.WeComAPIRequestJsonLoadError | ||
return result | ||
|
||
def __get_access_token(self) -> str: | ||
""" | ||
获取访问企业微信的access_token | ||
:return: | ||
""" | ||
if self.access_token: | ||
return self.access_token | ||
url = ACCESS_TOKEN_URL.format(self.corpid, self.secret) | ||
res = self.__request_get(url) | ||
if res.get('errcode') == 0: | ||
access_token = res.get('access_token', '') | ||
else: | ||
logger.error("get access_token failed, res={}".format(res)) | ||
raise local_exceptions.WeComAPIGetAccessTokenError | ||
self.access_token = access_token | ||
return access_token | ||
|
||
def get_departments(self) -> list: | ||
""" | ||
获取部门列表 | ||
:return: | ||
""" | ||
url = DEPARTMENT_LIST_URL.format(self.__get_access_token()) | ||
res = self.__request_get(url) | ||
if res.get('errcode') == 0: | ||
departments = res.get('department', []) | ||
else: | ||
logger.error("get departments failed, res={}".format(res)) | ||
raise local_exceptions.WeComAPIGetDepartmentError | ||
return departments | ||
|
||
def get_user_info(self, departments: list) -> list: | ||
""" | ||
获取用户列表 | ||
:param departments: 部门列表 | ||
:return: | ||
""" | ||
user_list = [] | ||
for department in departments: | ||
url = USER_LIST_DETAIL.format(self.__get_access_token(), department['id'], 0) | ||
res = self.__request_get(url) | ||
if res.get('errcode') == 0: | ||
user_list.extend(res.get('userlist', [])) | ||
else: | ||
logger.error("get user list failed, res={}".format(res)) | ||
raise local_exceptions.WeComAPIGetDepartmentError | ||
# 去重 | ||
new_user_list = self.__uniq_user_info(user_list) | ||
return new_user_list | ||
|
||
@staticmethod | ||
def __uniq_user_info(user_list: list) -> list: | ||
""" | ||
将从企业微信获取的用户去重 | ||
:param user_list: | ||
:return: | ||
""" | ||
user_ids = [] | ||
new_user_list = [] | ||
for user in user_list: | ||
if user.get("userid") not in user_ids: | ||
user_ids.append(user.get("userid")) | ||
new_user_list.append(user) | ||
return new_user_list | ||
|
||
def check(self, corpid, secret): | ||
# todo check corpid and secret | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-用户管理(Bk-User) available. | ||
Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. All rights reserved. | ||
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at http://opensource.org/licenses/MIT | ||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
specific language governing permissions and limitations under the License. | ||
""" | ||
ACCESS_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={}&corpsecret={}" | ||
DEPARTMENT_LIST_URL = "https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token={}" | ||
USER_LIST_URL = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token={}&department_id={}&fetch_child=1" | ||
USER_LIST_DETAIL = "https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token={}&department_id={}&fetch_child={}" | ||
# USER_LIST_DETAIL = "https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token={}&department_id={}&fetch_child=1" | ||
|
||
|
||
class WeComStatus: | ||
"""WeCom用户状态类型 | ||
1=已激活,2=已禁用,4=未激活,5=退出企业。 | ||
""" | ||
ACTIVE = 1 | ||
DISABLED = 2 | ||
INACTIVE = 4 | ||
EXIT_ENTERPRISE = 5 | ||
|
||
|
||
class WeComEnabled: | ||
ENABLE = 1 | ||
DISABLE = 0 |
46 changes: 46 additions & 0 deletions
46
src/api/bkuser_core/categories/plugins/wecom/exceptions.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-用户管理(Bk-User) available. | ||
Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. All rights reserved. | ||
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at http://opensource.org/licenses/MIT | ||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
specific language governing permissions and limitations under the License. | ||
""" | ||
|
||
|
||
class NoKeyItemAvailable(Exception): | ||
"""没有可找到的对象""" | ||
|
||
|
||
class CustomAPIRequestFailed(Exception): | ||
"""拉取自定义 API 失败""" | ||
|
||
|
||
class WeComAPIRequestFailed(Exception): | ||
"""WeCom API 失败""" | ||
|
||
|
||
class WeComAPIRequestStatusCodeError(Exception): | ||
"""WeCom API 返回码非200""" | ||
|
||
|
||
class WeComAPIRequestJsonLoadError(Exception): | ||
"""WeCom API json load 失败""" | ||
|
||
|
||
class WeComAPIGetAccessTokenError(Exception): | ||
"""WeCom API 获取 accesstoken 失败""" | ||
|
||
|
||
class WeComAPIGetDepartmentError(Exception): | ||
"""WeCom API 获取部门信息失败""" | ||
|
||
|
||
class WeComAPIGetUserListError(Exception): | ||
"""WeCom API 获取用户信息失败""" | ||
|
||
|
||
class WeComLoginError(Exception): | ||
"""WeCom 登录直接返回""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# -*- coding: utf-8 -*- | ||
""" | ||
TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-用户管理(Bk-User) available. | ||
Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. All rights reserved. | ||
Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at http://opensource.org/licenses/MIT | ||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
specific language governing permissions and limitations under the License. | ||
""" | ||
|
||
from dataclasses import dataclass | ||
|
||
from bkuser_core.categories.plugins.wecom.exceptions import WeComLoginError | ||
|
||
|
||
@dataclass | ||
class LoginHandler: | ||
def check(self, profile, password): | ||
raise WeComLoginError |
Oops, something went wrong.