diff --git a/patch-tracking/README.md b/patch-tracking/README.md index 6fb10f624931fc8289368f45deed118a27ccc127..746f3cb079ae0e06c07bef70b7c2baf6cd9b9498 100644 --- a/patch-tracking/README.md +++ b/patch-tracking/README.md @@ -1,24 +1,31 @@ -补丁跟踪 +patch-tracking === -# 一 简介 +# 简介 在 openEuler 发行版开发过程,需要及时更新上游社区各个软件包的最新代码,修改功能 bug 及安全问题,确保发布的 openEuler 发行版尽可能避免缺陷和漏洞。 本工具对软件包进行补丁管理,主动监控上游社区提交,自动生成补丁,并自动提交 issue 给对应的 maintainer,同时自动验证补丁基础功能,减少验证工作量支持 maintainer 快速决策。 -# 二 架构 +# 架构 -### 2.1 CS架构 +## C/S架构 -补丁跟踪采用 C/S 架构,其中服务端(patch-tracking) 负责执行补丁跟踪任务,包括:维护跟踪项,识别上游仓库分支代码变更并形成补丁文件,向 Gitee 提交 issue 及 PR,同时 patch-tracking 提供 RESTful 接口,用于对跟踪项进行增删改查操作。客户端,即命令行工具(patch-tracking-cli),通过调用 patch-tracking 的 RESTful 接口,实现对跟踪项的增删改查操作。 +patch-tracking采用 C/S 架构。 -### 2.2 核心流程 +服务端(patch-tracking) :负责执行补丁跟踪任务,包括:维护跟踪项,识别上游仓库分支代码变更并形成补丁文件,向 Gitee 提交 issue 及 PR,同时 patch-tracking 提供 RESTful 接口,用于对跟踪项进行增删改查操作。 + +客户端:即命令行工具(patch-tracking-cli),通过调用 patch-tracking 的 RESTful 接口,实现对跟踪项的增删改查操作。 +## 软件下载 +rpm包获取地址:https://117.78.1.88/package/show/openEuler:Mainline/patch-tracking + +## 核心流程 * 补丁跟踪服务流程 **主要步骤:** + 1. 命令行工具写入跟踪项。 2. 自动从跟踪项配置的上游仓库(例如Github)获取补丁文件。 3. 创建临时分支,将获取到的补丁文件提交到临时分支。 @@ -34,7 +41,7 @@ ![Maintainer](images/Maintainer.jpg) -### 2.3 数据结构 +## 数据结构 * Tracking表 @@ -57,136 +64,136 @@ | 2 | repo | 包源码在Gitee的仓库地址 | String | - | NO | | 3 | branch | 包源码在Gitee的仓库分支 | String | - | NO | -# 三 部署 +# 工具部署 ->环境已安装 Python >= 3.7 以及 pip3 +## 环境要求 -### 3.1 安装依赖 +>* 安装 Python 3.7及以上版本 +>* 已安装 pip3。 + +## 安装依赖 + +执行如下命令安装依赖包。 ```shell script yum install -y gcc gcc-c++ python3-devel openssl-devel -pip3 install flask flask-sqlalchemy flask-apscheduler requests flask_httpauth pandas +pip3 install flask flask-sqlalchemy flask-apscheduler requests flask_httpauth pandas numpy==1.16.5 pip3 install -I uwsgi ``` +## 安装工具 -### 3.2 安装 - -这里以 `patch-tracking-1.0.0-1.oe1.noarch.rpm` 为例 +以`patch-tracking-1.0.0-1.oe1.noarch.rpm` 为例,执行如下命令安装工具。 ```shell script rpm -ivh patch-tracking-1.0.0-1.oe1.noarch.rpm ``` -### 3.3 生成证书 +## 生成证书 +执行如下命令生成证书。 ```shell script openssl req -x509 -days 3650 -subj "/CN=self-signed" \ -nodes -newkey rsa:4096 -keyout self-signed.key -out self-signed.crt ``` -将 `self-signed.key` 和 `self-signed.crt` 拷贝到 __/etc/patch-tracking__ 目录 +将生成的 `self-signed.key` 和 `self-signed.crt` 文件拷贝到 __/etc/patch-tracking__ 目录 -### 3.4 配置 +## 配置参数 -在配置文件中进行对应参数的配置。 +在配置文件中对相应参数进行配置,配置文件路径为 `/etc/patch-tracking/settings.conf`。 -配置文件路径 `/etc/patch-tracking/settings.conf`。 +1. 配置服务监听地址。 + ``` + LISTEN = "127.0.0.1:5001" + ``` -- 服务监听地址 +2. GitHub Token, 用于访问托管在 GitHub 上游开源软件仓的仓库信息 , 生成 GitHub Token 的方法参考 [Creating a personal access token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) 。 -```python -LISTEN = "127.0.0.1:5001" -``` + ``` + GITHUB_ACCESS_TOKEN = "" + ``` -- GitHub Token,用于访问托管在 GitHub 上游开源软件仓的仓库信息 +3. 对于托管在gitee上的需要跟踪的仓库,配置一个有该仓库权限的gitee的token,用于提交patch文件,提交issue,提交PR等操作。 -生成 GitHub Token 的方法参考 [Creating a personal access token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) + ``` + GITEE_ACCESS_TOKEN = "" + ``` -```python -GITHUB_ACCESS_TOKEN = "" -``` +4. 定时扫描数据库中是否有新增或修改的跟踪项,对扫描到的跟踪项执行获取上游补丁任务,在这里配置扫描的时间间隔,数字单位是秒。 -- 对于托管在gitee上的需要跟踪的仓库,配置一个有该仓库权限的gitee的token,用于提交patch文件,提交issue,提交PR等操作。 + ``` + SCAN_DB_INTERVAL = 3600 + ``` -```python -GITEE_ACCESS_TOKEN = "" -``` +5. 命令行工具运行过程中,POST接口需要填写进行认证的用户名和口令哈希值。 -- 定时扫描数据库中是否有新增或修改的跟踪项,对扫描到的跟踪项执行获取上游补丁任务,在这里配置扫描的时间间隔,数字单位是秒 + ``` + USER = "admin" -```python -SCAN_DB_INTERVAL = 3600 -``` + PASSWORD = "" + ``` -- 命令行工具运行过程中,POST接口需要进行认证的用户名和密码 + > `USER`默认值为`admin`。 -```python -USER = "admin" +​ 执行如下指令,获取口令的哈希值,其中Test@123为设置的口令。 -PASSWORD = "" +``` +[root]# generate_password Test@123 +pbkdf2:sha256:150000$w38eLeRm$ebb5069ba3b4dda39a698bd1d9d7f5f848af3bd93b11e0cde2b28e9e34bfbbae ``` -`USER`默认值为`admin`。 - ->`PASSWORD`口令的复杂度要求: ->* 长度大于等于6个字符 ->* 至少有一个数字 ->* 至少有一个大写字母 ->* 至少有一个小写字母 ->* 至少有一个特殊字符 (~!@#%^*_+=-) - -需要将口令的哈希值通过命令工具生成后将其配置到此处,获取方法为执行命令`generate_password `,例如: - - [root]# generate_password Test@123 - pbkdf2:sha256:150000$w38eLeRm$ebb5069ba3b4dda39a698bd1d9d7f5f848af3bd93b11e0cde2b28e9e34bfbbae +> `口令值`需要满足如下复杂度要求: +> +> * 长度大于等于6个字符 +> * 必须包含大写字母、小写字母、数字、特殊字符(~!@#%^*-_=+) -将`pbkdf2:sha256:150000$w38eLeRm$ebb5069ba3b4dda39a698bd1d9d7f5f848af3bd93b11e0cde2b28e9e34bfbbae`配置到`PASSWORD = ""`引号中。 + 将口令的哈希值`pbkdf2:sha256:150000$w38eLeRm$ebb5069ba3b4dda39a698bd1d9d7f5f848af3bd93b11e0cde2b28e9e34bfbbae`配置到`PASSWORD = ""`引号中。 -### 3.5 启动补丁跟踪服务 +## 启动补丁跟踪服务 -可以使用以下两种方式启动服务: +可以使用以下两种方式启动服务。 -1. 使用 systemd 方式 +* 使用systemd方式。 -```shell script -systemctl start patch-tracking -``` + ``` + systemctl start patch-tracking + ``` -2. 直接执行可执行程序 +* 直接执行可执行程序。 -```shell script -/usr/bin/patch-tracking -``` + ``` + /usr/bin/patch-tracking + ``` -# 四 使用 +# 工具使用 -### 4.1 添加跟踪项 +## 添加跟踪项 -将需要跟踪的软件仓库和分支与其上游开源软件仓库与分支关联起来,有 3 种使用方法。 +将需要跟踪的软件仓库和分支与其上游开源软件仓库与分支关联起来,可以通过以下三种方式实现。 -#### 4.1.1 命令行直接添加 +### 命令行直接添加 参数含义: >--user :POST接口需要进行认证的用户名,同settings.conf中的USER参数 \ --password :POST接口需要进行认证的口令,为settings.conf中的PASSWORD哈希值对应的实际的口令字符串 \ --server :启动Patch Tracking服务的URL,例如:127.0.0.1:5001 \ ---version_control :上游仓库版本的控制工具,只支持github \ ---repo 需要进行跟踪的仓库名称,格式:组织/仓库 \ ---branch 需要进行跟踪的仓库的分支名称 \ ---scm_repo 被跟踪的上游仓库的仓库名称,github格式:组织/仓库 \ ---scm_branch 被跟踪的上游仓库的仓库的分支 \ ---enable 是否自动跟踪该仓库 +--version_control :上游仓库版本的控制工具,只支持github \ +--repo: 需要进行跟踪的仓库名称,格式:组织/仓库 \ +--branch :需要进行跟踪的仓库的分支名称 \ +--scm_repo :被跟踪的上游仓库的仓库名称,github格式:组织/仓库 \ +--scm_branch: 被跟踪的上游仓库的仓库的分支 \ +--enable :是否自动跟踪该仓库 例如: ```shell script patch-tracking-cli add --server 127.0.0.1:5001 --user admin --password Test@123 --version_control github --repo testPatchTrack/testPatch1 --branch master --scm_repo BJMX/testPatch01 --scm_branch test --enable true ``` -#### 4.1.2 指定文件添加 +### 指定文件添加 参数含义: >--server :启动Patch Tracking服务的URL,例如:127.0.0.1:5001 \ @@ -194,14 +201,14 @@ patch-tracking-cli add --server 127.0.0.1:5001 --user admin --password Test@123 --password :POST接口需要进行认证的口令,为settings.conf中的PASSWORD哈希值对应的实际的口令字符串 \ --file :yaml文件路径 -文件内容是仓库、分支、版本管理工具、是否启动监控等信息,将这些写入文件名为xxx.yaml,例如tracking.yaml,文件路径作为`--file`的入参调用命令。 +将仓库、分支、版本管理工具、是否启动监控等信息写入yaml文件(例如tracking.yaml),文件路径作为`--file`的入参调用命令。 例如: ```shell script patch-tracking-cli add --server 127.0.0.1:5001 --user admin --password Test@123 --file tracking.yaml ``` -yaml内容格式如下,冒号左边的内容不可修改,右边内容根据实际情况填写。 +yaml文件内容格式如下,冒号左边的内容不可修改,右边内容根据实际情况填写。 ```shell script version_control: github @@ -212,16 +219,16 @@ branch: master enabled: true ``` ->version_control :上游仓库版本的控制工具,只支持github \ -scm_repo 被跟踪的上游仓库的仓库名称,github格式:组织/仓库 \ -scm_branch 被跟踪的上游仓库的仓库的分支 \ -repo 需要进行跟踪的仓库名称,格式:组织/仓库 \ -branch 需要进行跟踪的仓库的分支名称 \ -enable 是否自动跟踪该仓库 +>version_control :上游仓库版本的控制工具,只支持github \ +scm_repo :被跟踪的上游仓库的仓库名称,github格式:组织/仓库 \ +scm_branch :被跟踪的上游仓库的仓库的分支 \ +repo :需要进行跟踪的仓库名称,格式:组织/仓库 \ +branch :需要进行跟踪的仓库的分支名称 \ +enable :是否自动跟踪该仓库 -#### 4.1.3 指定目录添加 +### 指定目录添加 -在指定的目录,例如`test_yaml`下放入多个`xxx.yaml`文件,执行命令,记录指定目录下所有yaml文件的跟踪项。yaml文件都放在不会读取子目录内文件。, +在指定的目录,例如`test_yaml`下放入多个`xxx.yaml`文件,执行如下命令,记录指定目录下所有yaml文件的跟踪项。 参数含义: >--user :POST接口需要进行认证的用户名,同settings.conf中的USER参数 \ @@ -233,16 +240,13 @@ enable 是否自动跟踪该仓库 patch-tracking-cli add --server 127.0.0.1:5001 --user admin --password Test@123 --dir /home/Work/test_yaml/ ``` -### 4.2 查询跟踪项 +## 查询跟踪项 参数含义: >--server :必选参数,启动Patch Tracking服务的URL,例如:127.0.0.1:5001 \ --table :必选参数,需要查询的表 \ --repo :可选参数,需要查询的repo;如果没有该参数查询表中所有内容 \ ---branch :可选参数,需要查询的branch,必须和--repo同时查询,没有--repo不允许单独查询该参数 - -#### 4.2.1 查询tracking表 - +--branch :可选参数,需要查询的branch ```shell script patch-tracking-cli query --server --table tracking ``` @@ -251,7 +255,7 @@ patch-tracking-cli query --server --table tracking patch-tracking-cli query --server 127.0.0.1:5001 --table tracking ``` -### 4.3 查询生成的 Issue 列表 +## 查询生成的 Issue ```shell script patch-tracking-cli query --server --table issue @@ -261,26 +265,22 @@ patch-tracking-cli query --server --table issue patch-tracking-cli query --server 127.0.0.1:5001 --table issue ``` -### 4.4 删除 Tracking 跟踪项数据 +## 删除跟踪项 ```shell script patch-tracking-cli delete --server SERVER --user USER --password PWD --table TABLE --repo REPO [--branch BRANCH] ``` - -可以删除指定repo和branch的单条数据;也可直接删除指定repo下所有branch的数据。 - - 例如: ```shell script patch-tracking-cli delete --server 127.0.0.1:5001 --user admin --password Test@123 --repo testPatchTrack/testPatch1 --branch master ``` -### 4.5 码云查看 issue 及 PR +> 可以删除指定repo和branch的单条数据;也可直接删除指定repo下所有branch的数据。 + -登录Gitee上进行跟踪的软件项目,在该项目的Issues和Pull Requests页签下,可以查看到名为`[patch tracking] TIME`,例如` [patch tracking] 20200713101548`的条目。 +## 码云查看 issue 及 PR -即是刚生成的补丁文件的issue和对应PR。 +登录Gitee上进行跟踪的软件项目,在该项目的Issues和Pull Requests页签下,可以查看到名为`[patch tracking] TIME`,例如` [patch tracking] 20200713101548`的条目,该条目即是刚生成的补丁文件的issue和对应PR。 -# 五 常见问题与解决方法 diff --git a/patch-tracking/patch-tracking.spec b/patch-tracking/patch-tracking.spec index d2683e1fd520739876c9dda385b95c8d767295e1..7a6d92e86285a460562e3787c38f54072342d8b9 100644 --- a/patch-tracking/patch-tracking.spec +++ b/patch-tracking/patch-tracking.spec @@ -1,6 +1,6 @@ %define name patch-tracking %define version 1.0.0 -%define release 1 +%define release 2 Summary: This is a tool for automatically tracking upstream repository code patches Name: %{name} diff --git a/patch-tracking/patch_tracking/api/auth.py b/patch-tracking/patch_tracking/api/auth.py new file mode 100644 index 0000000000000000000000000000000000000000..6916f9bc358fdf6652ff77087dd48177f640e21e --- /dev/null +++ b/patch-tracking/patch_tracking/api/auth.py @@ -0,0 +1,39 @@ +""" +http basic auth +""" +import logging +from werkzeug.security import check_password_hash +from flask_httpauth import HTTPBasicAuth +from flask import current_app as app + +logger = logging.getLogger(__name__) + +auth = HTTPBasicAuth() + + +@auth.verify_password +def verify_password(username, password): + """ + verify password + """ + try: + if username == app.config["USER"] and \ + check_password_hash(app.config["PASSWORD"], password): + return username + except ValueError as err: + logger.error(err) + return None + logger.error("verify password failed") + return None + + +if __name__ == "__main__": + try: + print( + check_password_hash( + " pbkdf2:sha256:150000$ClAZjafb$ec0718c193c000e70812a0709919596e7523ab581c25ea6883aadba33c2edf0d", + "Test@123" + ) + ) + except ValueError as err: + print(err) diff --git a/patch-tracking/patch_tracking/api/tracking.py b/patch-tracking/patch_tracking/api/tracking.py index 8ecd27f2fdecb49b5ef5e7e4b6e25f627c642f96..4a8a24cf78e244656c4a4b587eb2b00b9ebf4268 100644 --- a/patch-tracking/patch_tracking/api/tracking.py +++ b/patch-tracking/patch_tracking/api/tracking.py @@ -7,7 +7,7 @@ from sqlalchemy.exc import SQLAlchemyError from patch_tracking.database.models import Tracking from patch_tracking.api.business import create_tracking, update_tracking, delete_tracking from patch_tracking.api.constant import ResponseCode -from patch_tracking.util.auth import auth +from patch_tracking.api.auth import auth logger = logging.getLogger(__name__) tracking = Blueprint('tracking', __name__) @@ -36,8 +36,9 @@ def delete(): logger.info('Delete tracking repo: %s, branch: %s', input_params['repo'], input_params['branch']) return ResponseCode.ret_message(code=ResponseCode.SUCCESS) else: - logger.info('Delete tracking repo: %s, branch: %s not found.', input_params['repo'], - input_params['branch']) + logger.info( + 'Delete tracking repo: %s, branch: %s not found.', input_params['repo'], input_params['branch'] + ) return ResponseCode.ret_message(code=ResponseCode.DELETE_DB_NOT_FOUND) else: if Tracking.query.filter(Tracking.repo == input_params['repo']).first(): diff --git a/patch-tracking/patch_tracking/app.py b/patch-tracking/patch_tracking/app.py index 294149c515d589b7ef708021f0b50a70a8e39ead..e39ba4cb2f15f4f35ef927a9e737be0a44ab865c 100644 --- a/patch-tracking/patch_tracking/app.py +++ b/patch-tracking/patch_tracking/app.py @@ -9,6 +9,7 @@ from patch_tracking.api.issue import issue from patch_tracking.api.tracking import tracking from patch_tracking.database import db from patch_tracking.task import task +from patch_tracking.util import github_api, gitee_api logging.config.fileConfig('logging.conf', disable_existing_loggers=False) @@ -16,6 +17,43 @@ app = Flask(__name__) logger = logging.getLogger(__name__) +def check_token(): + """ check gitee/github token """ + gitee_token = app.config['GITEE_ACCESS_TOKEN'] + github_token = app.config['GITHUB_ACCESS_TOKEN'] + token_error = False + github_ret = github_api.get_user_info(github_token) + if github_ret[0] != "success": + logger.error('github token is bad credentials.') + token_error = True + + gitee_ret = gitee_api.get_user_info(gitee_token) + if gitee_ret[0] != "success": + logger.error('gitee token is bad credentials.') + token_error = True + + if token_error: + sys.exit() + + +def check_listen(listen_param): + """ check LISTEN """ + check_ret = True + if ":" in listen_param and listen_param.count(":") == 1: + host, port = listen_param.split(":") + if int(port) > 65535 or int(port) <= 0: + check_ret = False + if "." in host and host.count(".") == 3: + for item in host.split("."): + if int(item) < 0 or int(item) > 255: + check_ret = False + else: + check_ret = False + else: + check_ret = False + return check_ret + + def check_settings_conf(): """ check settings.conf @@ -24,9 +62,21 @@ def check_settings_conf(): required_settings = ['LISTEN', 'GITHUB_ACCESS_TOKEN', 'GITEE_ACCESS_TOKEN', 'SCAN_DB_INTERVAL', 'USER', 'PASSWORD'] for setting in required_settings: if setting in app.config: - if not app.config[setting]: + if app.config[setting] == "": logger.error('%s is empty in settings.conf.', setting) setting_error = True + else: + if setting == "LISTEN" and (not check_listen(app.config[setting])): + logger.error('LISTEN error: illegal param in /etc/patch-tracking/settings.conf.') + setting_error = True + if setting == "SCAN_DB_INTERVAL" and int(app.config[setting]) <= 0: + logger.error( + 'SCAN_DB_INTERVAL error: must be greater than zero in /etc/patch-tracking/settings.conf.' + ) + setting_error = True + if setting == "USER" and len(app.config[setting]) > 32: + logger.error('USER value error: user name too long, USER character should less than 32.') + setting_error = True else: logger.error('%s not configured in settings.conf.', setting) setting_error = True @@ -37,16 +87,10 @@ def check_settings_conf(): settings_file = os.path.join(os.path.abspath(os.curdir), "settings.conf") app.config.from_pyfile(settings_file) check_settings_conf() - -GITHUB_ACCESS_TOKEN = app.config['GITHUB_ACCESS_TOKEN'] -GITEE_ACCESS_TOKEN = app.config['GITEE_ACCESS_TOKEN'] -SCAN_DB_INTERVAL = app.config['SCAN_DB_INTERVAL'] +check_token() app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite?check_same_thread=False' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False -app.config['SWAGGER_UI_DOC_EXPANSION'] = 'list' -app.config['ERROR_404_HELP'] = False -app.config['RESTX_MASK_SWAGGER'] = False app.config['SCHEDULER_EXECUTORS'] = {'default': {'type': 'threadpool', 'max_workers': 100}} app.register_blueprint(issue, url_prefix="/issue") diff --git a/patch-tracking/patch_tracking/cli/generate_password b/patch-tracking/patch_tracking/cli/generate_password index 9cb861b0f5398cc495c84374447087f0d6bb6fd5..f9d91f0c76aa01880769533e0cd0e44f5034e1e1 100644 --- a/patch-tracking/patch_tracking/cli/generate_password +++ b/patch-tracking/patch_tracking/cli/generate_password @@ -8,6 +8,32 @@ import re from werkzeug.security import generate_password_hash +def usage(): + """ usage """ + print( + """usage: generate_password PASSWORD + +Requirements: +1. PASSWORD must be within the 'latin1' character set +2. PASSWORD strength require: + 6 characters or more + at least 1 digit [0-9] + at least 1 alphabet [a-z] + at least 1 alphabet of Upper Case [A-Z] + at least 1 special character from [~!@#%^*_+=-] +""" + ) + + +def password_encode_check(password): + """ check if password within the latin1 character set """ + try: + password.encode("latin1") + except UnicodeEncodeError as err: + return str(err) + return None + + def password_strength_check(password): """ Verify the strength of 'password' @@ -44,21 +70,26 @@ def password_strength_check(password): } -ret = password_strength_check(sys.argv[1]) -if not ret['ok']: - print("Password strength is not satisfied.") - for item in ret['error']: - if ret['error'][item]: - print("{} not satisfied.".format(item)) - print( - """ -password strength require: - 6 characters or more - at least 1 digit [0-9] - at least 1 alphabet [a-z] - at least 1 alphabet of Upper Case [A-Z] - at least 1 special character from [~!@#%^*_+=-] -""" - ) -else: - print(generate_password_hash(sys.argv[1])) +if __name__ == "__main__": + if len(sys.argv) != 2: + usage() + sys.exit(1) + + password_ = sys.argv[1] + + ret = password_encode_check(password_) + if ret: + usage() + print("PASSWORD: only latin1 character set are allowed") + sys.exit(1) + + ret = password_strength_check(password_) + if not ret['ok']: + usage() + print("Password strength is not satisfied:") + for item in ret['error']: + if ret['error'][item]: + print("{} not satisfied.".format(item)) + sys.exit(1) + else: + print(generate_password_hash(password_)) diff --git a/patch-tracking/patch_tracking/cli/patch_tracking_cli.py b/patch-tracking/patch_tracking/cli/patch_tracking_cli.py index 9802788c679e52e52f5b6692d8489da7ee0e3e94..ec712eac22d8436a412cc0f19329d57e17b91633 100755 --- a/patch-tracking/patch_tracking/cli/patch_tracking_cli.py +++ b/patch-tracking/patch_tracking/cli/patch_tracking_cli.py @@ -112,6 +112,15 @@ def repo_branch_check(url): return 'error', ret.text +def latin1_encode(text): + """ latin1 encode """ + try: + text.encode("latin1") + except UnicodeEncodeError as err: + return str(err) + return None + + def params_input_track(params, file_path=None): """ load tracking from command line arguments @@ -132,6 +141,13 @@ def params_input_track(params, file_path=None): user = params['user'] password = params['password'] + err = latin1_encode(user) + if err: + return "error", "ERROR: user: only latin1 character set are allowed." + err = latin1_encode(password) + if err: + return "error", "ERROR: user: only latin1 character set are allowed." + enabled = bool(enabled == 'true') url = '/'.join(['https:/', server, 'tracking']) @@ -165,7 +181,11 @@ def check_add_param(params): miss_params.append(param) success = False if not success: - print("patch_tracking_cli add: error: the following arguments are required: --{}".format(", --".join(miss_params))) + print( + "patch_tracking_cli add: error: the following arguments are required: --{}".format( + ", --".join(miss_params) + ) + ) return success @@ -180,8 +200,8 @@ def add(args): style3 = bool(args.dir) if str([style1, style2, style3]).count('True') >= 2: - print("mix different usage style") - print(add_usage) + print("usage:" + add_usage) + print("patch_tracking_cli add: error: mix different usage style") return if style2: @@ -215,6 +235,15 @@ def delete(args): user = args.user password = args.password + err = latin1_encode(user) + if err: + print("ERROR: user: only latin1 character set are allowed.") + return + err = latin1_encode(password) + if err: + print("ERROR: password: Only latin1 character set are allowed.") + return + url = '/'.join(['https:/', server, 'tracking']) if args.branch: params = {'repo': args.repo, 'branch': args.branch} @@ -310,11 +339,11 @@ authentication_parser.add_argument('--password', required=True, help='authentica # add add_usage = """ - %(prog)s --server SERVER --user USER --password PASSWORD + patch_tracking_cli add --server SERVER --user USER --password PASSWORD --version_control github --scm_repo SCM_REPO --scm_branch SCM_BRANCH --repo REPO --branch BRANCH --enabled True - %(prog)s --server SERVER --user USER --password PASSWORD --file FILE - %(prog)s --server SERVER --user USER --password PASSWORD --dir DIR""" + patch_tracking_cli add --server SERVER --user USER --password PASSWORD --file FILE + patch_tracking_cli add --server SERVER --user USER --password PASSWORD --dir DIR""" parser_add = subparsers.add_parser( 'add', parents=[common_parser, authentication_parser], help="add tracking", usage=add_usage, allow_abbrev=False ) @@ -329,16 +358,14 @@ parser_add.add_argument('--file', help='import patch tracking from file') parser_add.add_argument('--dir', help='import patch tracking from files in directory') # delete -del_usage = """ - %(prog)s --server SERVER --table TABLE --repo REPO [--branch BRANCH]""" -parser_delete = subparsers.add_parser('delete', parents=[common_parser, authentication_parser], help="delete tracking", allow_abbrev=False) +parser_delete = subparsers.add_parser( + 'delete', parents=[common_parser, authentication_parser], help="delete tracking", allow_abbrev=False +) parser_delete.set_defaults(func=delete) parser_delete.add_argument("--repo", required=True, help="source package repository") parser_delete.add_argument("--branch", help="source package branch") # query -query_usage = """ - %(prog)s --server SERVER --table {tracking,issue} [--repo REPO] [--branch BRANCH]""" parser_query = subparsers.add_parser('query', parents=[common_parser], help="query tracking/issue", allow_abbrev=False) parser_query.set_defaults(func=query) parser_query.add_argument("--table", required=True, choices=["tracking", "issue"], help="query tracking or issue") diff --git a/patch-tracking/patch_tracking/patch-tracking b/patch-tracking/patch_tracking/patch-tracking index f0143c040f43d9de78b2d691af20e78a87bb3982..f5961fcee7db8d00d00b36253500ebab73e7d7cf 100755 --- a/patch-tracking/patch_tracking/patch-tracking +++ b/patch-tracking/patch_tracking/patch-tracking @@ -8,4 +8,4 @@ settings_file='/etc/patch-tracking/settings.conf' server=`grep 'LISTEN' $settings_file | awk -F'=' '{print $2}' | sed -e 's/^[ ]"//g' | sed -e 's/"$//g'` -/usr/local/bin/uwsgi --master --https ${server},/etc/patch-tracking/self-signed.crt,/etc/patch-tracking/self-signed.key --wsgi-file ${app_file} --callable app --chdir ${chdir_path} --threads 100 --lazy +/usr/local/bin/uwsgi --master --https "${server},/etc/patch-tracking/self-signed.crt,/etc/patch-tracking/self-signed.key" --wsgi-file "${app_file}" --callable app --chdir "${chdir_path}" --threads 100 --lazy diff --git a/patch-tracking/patch_tracking/util/auth.py b/patch-tracking/patch_tracking/util/auth.py deleted file mode 100644 index df9ed248a0a049f770fc3192741ba9b20cf86bca..0000000000000000000000000000000000000000 --- a/patch-tracking/patch_tracking/util/auth.py +++ /dev/null @@ -1,19 +0,0 @@ -""" -http basic auth -""" -from werkzeug.security import check_password_hash -from flask_httpauth import HTTPBasicAuth -from flask import current_app as app - -auth = HTTPBasicAuth() - - -@auth.verify_password -def verify_password(username, password): - """ - verify password - """ - if username == app.config["USER"] and \ - check_password_hash(app.config["PASSWORD"], password): - return username - return None diff --git a/patch-tracking/patch_tracking/util/gitee_api.py b/patch-tracking/patch_tracking/util/gitee_api.py index cf798b3a06077ef3f802834998d0cfbde5f304ce..53a553f14721f01c96860832e25826865e74e0d7 100644 --- a/patch-tracking/patch_tracking/util/gitee_api.py +++ b/patch-tracking/patch_tracking/util/gitee_api.py @@ -12,6 +12,19 @@ ORG_URL = "https://gitee.com/api/v5/orgs" REPO_URL = "https://gitee.com/api/v5/repos" +def get_user_info(token): + """ + get user info + """ + url = "https://gitee.com/api/v5/user" + gitee_token = token + param = {'access_token': gitee_token} + ret = requests.get(url, params=param) + if ret.status_code == 200: + return "success", ret.text + return "error", ret.json() + + def get_path_content(repo, branch, path): """ get file content diff --git a/patch-tracking/patch_tracking/util/github_api.py b/patch-tracking/patch_tracking/util/github_api.py index c2196c5b669adc38c23f51874efac3e780b896b4..31b533c4ec35d61dd664191031e0890a4012ec89 100644 --- a/patch-tracking/patch_tracking/util/github_api.py +++ b/patch-tracking/patch_tracking/util/github_api.py @@ -10,6 +10,37 @@ from flask import current_app logger = logging.getLogger(__name__) +def get_user_info(token): + """ + get user info + """ + url = "https://api.github.com/user" + count = 30 + token = 'token ' + token + headers = { + 'User-Agent': 'Mozilla/5.0', + 'Authorization': token, + 'Content-Type': 'application/json', + 'Connection': 'close', + 'method': 'GET', + 'Accept': 'application/json' + } + while count > 0: + try: + ret = requests.get(url, headers=headers) + if ret.status_code == 200: + return 'success', ret.text + return 'error', ret.json() + except requests_connectionError as err: + logger.warning(err) + time.sleep(10) + count -= 1 + continue + if count == 0: + logger.error('Fail to connnect to github: %s after retry 30 times.', url) + return 'connect error' + + class GitHubApi: """ Encapsulates GitHub functionality