调用禅道api创建新用户
使用禅道API是一件非常麻烦的事,因为它没有详细的API文档。
官方在网站内嵌的API文档极其简略,根本不知道需要传递什么参数。
如何知道该如何使用它提供的API呢?
你必须去看他在网页端发送的请求。
举例:用户创建的请求
需要在浏览器中调用一边,而 API 接口,就出将请求地址中的
.html
改为.json
,需要传递的参数是一样的。
获取 session id
想要使用禅道的 API 必须先获取一个 session id。
请求地址:
/zentao/api-getsessionid.json
请求会返回一个 JSON 数据,而这个 JSON 数据并不能拿来直接使用,需要将结果中的data
数据进行二次解包,才是我们需要的内容。
{
"status": "success",
"data": "{\"title\":\"\",\"sessionName\":\"zentaosid\",\"sessionID\":\"2bfd242rshnpcge5m1fakbsi33\",\"rand\":3088,\"pager\":null}",
"md5": "74daf72bba02d4c1bdbedc7246204c4a"
}
这个接口我们需要用到是 sessionName
和 sessionID
。
在之后的请求中我们都需要在请求的参数中加上 zentaosid=2bfd242rshnpcge5m1fakbsi33
。
使用 session id 登陆
只有 session_id 是不够的,我们还需要使用这个 session_id 成功登陆以后,才能用它请求其他接口。
请求地址:
zentao/user-login.json
使用 post 请求发送用户名和密码
创建新用户
创建新用户是最麻烦的地方。
请求地址:
/zentao/user-create.json
首先需要知道要传递的参数。通过浏览器的抓包,知道了需要传递的参数。
其中有一个参数 verifyPassword
并不像登陆时一样可以直接使用明文密码,也不是单纯的md5后的结果。
打开页面 /zentao/user-create-0.html
, 在网页源码中搜索这个参数名,能找到以下 js 代码。
可以知道 verifyPassword
的构成是 md5(md5(password) + rand
。
这里的 rand 随机数,需要在页面中的'input#verifyRand'
获取。
翻了API文档,并没有看到获取他的地方。
那就只能通过获取整个页面,在拿到对应的值了。
def _get_verify_rand(self):
path = '/zentao/user-create.html'
html = requests.get(self.host + path, params=self.params).text
soup = BeautifulSoup(html, 'html.parser')
value = soup.select_one('input#verifyRand').attrs['value']
return value
老实说,为啥不用ldap呢?
完整的代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
from hashlib import md5
import json
import datetime
from bs4 import BeautifulSoup
"""
官方示例中提示需要解包两次json
$result = file_get_contents('http://pms.zentao.net/project-task-8.json');
$result = json_decode($result);
if($result->status == 'success' and md5($result->data) == $result->md5)
{
$data = json_decode($result->data);
print_r($data);
}
"""
class Zentao(object):
def __init__(self, host, account, password):
self.host = host
self.session_id = ''
self.params = {}
self.account = account
self.password = password
self._get_session_id()
self.login()
def _get_session_id(self):
api_path = "/zentao/api-getsessionid.json"
response = requests.get(self.host + api_path)
result = self._get_zentao_result(response.json())
self.session_id = result['sessionID']
self.params[result['sessionName']] = self.session_id
def login(self):
api_path = '/zentao/user-login.json'
data = {
'account': self.account,
'password': self.password,
}
result = requests.post(self.host + api_path, data=data, params=self.params).json()
if result['status'] == 'success':
print('zentao 登陆成功')
else:
print(result)
@staticmethod
def _get_zentao_result(result):
if result['status'] == 'success' and md5(result['data'].encode()).hexdigest() == result['md5']:
data = json.loads(result['data'])
return data
return result
def zentao_get(self, api_path):
response = requests.get(self.host + api_path, self.params)
# print(response.content)
result = response.json()
# print(result)
return self._get_zentao_result(result)
def zentao_post(self, api_path, data=None, json_data=None):
response = requests.post(self.host + api_path, data=data, json=json_data, params=self.params)
return self._get_zentao_result(response.json())
def get_dept_list(self):
"""
获取部门列表
:return:
"""
api_path = "/zentao/dept-browse-.json"
data = self.zentao_get(api_path)
return data['sons']
def create_user(self, account: str, password: str, realname: str, deptid: int = 7, email: str = ""):
"""
创建用户
:param account: 账号
:param password: 密码
:param realname: 真实姓名
:param deptid: 部门编号
:param email: 邮箱
:return:
"""
api_path = "/zentao/user-create.json".format(deptid)
data = {
"dept": deptid,
"account": account,
"password1": password,
"password2": password,
"realname": realname,
"join": str(datetime.date.today()),
"role": "dev",
"group": 2,
"email": email,
"commiter": "",
"gender": "m",
"verifyPassword": md5((md5(self.password.encode()).hexdigest() + self._get_verify_rand()).encode(
)).hexdigest(),
}
response = requests.post(self.host + api_path, data=data, params=self.params)
if response.status_code == 200:
result = response.json()
return result
return response.text
def _get_verify_rand(self):
path = '/zentao/user-create.html'
html = requests.get(self.host + path, params=self.params).text
soup = BeautifulSoup(html, 'html.parser')
value = soup.select_one('input#verifyRand').attrs['value']
return value
def delete_user():
"""
user-delete-[userid].json
verifyPassword: md5(md5(pass)+rand)
:return:
"""
pass
if __name__ == '__main__':
# json_print(dept_browse())
# print(get_verifyRand())
# print(create_user("test2", "testABC123", "测试用户"))
from config import *
zentao = Zentao(zentao_host, zentao_account, zentao_password)
print(zentao.get_dept_list())