Skip to content

Commit

Permalink
add readme_en, add getting started, switch user register from sync to…
Browse files Browse the repository at this point in the history
… async🎈
  • Loading branch information
wuranxu committed Jan 2, 2022
1 parent 8c41659 commit 1ad19ee
Show file tree
Hide file tree
Showing 9 changed files with 176 additions and 33 deletions.
48 changes: 44 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,44 @@
## 项目地址 🖕
[English](https://github.com/wuranxu/pity/blob/main/README_EN.md)

## 快速开始

1. 拉取代码

```bash
$ git clone https://github.com/wuranxu/pity
$ cd pity
```

2. 安装依赖

```bash
# 可换豆瓣源或者清华源安装依赖
$ pip install -r requirements.txt
```

3. 安装并启动redis

4. 安装并启动mysql

5. 修改配置config.py

修改mysql和redis连接信息。

6. 启动服务

```bash
$ python main.py
```

7. 注册用户

第一个注册的用户会成为`超级管理员`,拥有一切权限。

![](https://gitee.com/woodywrx/picture/raw/master/2022-1-2/1641092636428-image.png)

登录后就可以开启pity之旅啦!

## 相关地址 🖕

[官方文档 🍚](http://pity.readthedocs.org/)

Expand All @@ -8,9 +48,9 @@

pity是一款专注于api自动化的工具,采用`Python`+`FastApi`+`React`开发,目前还不能作为生产级别的工具,作者正在努力之中。

这个项目叫pity, 一个从0开始写的自动化测试平台(基于FastApi),旨在总结自己最近几年的工作经验,也顺便帮助大家进步。目前还在火热更新中,基本上每周都会更新几篇吧,前期以教学+编码为主,后期以实现功能为主。希望大家能够喜欢!~
这个项目叫pity,一个从0开始写的自动化测试平台(基于FastApi),旨在总结自己最近几年的工作经验,也顺便帮助大家进步。目前还在火热更新中,基本上每周都会更新几篇吧,前期以教学+编码为主,后期以实现功能为主。希望大家能够喜欢!~

项目起源是本人很期待的某家头部公司🐧拒绝了我,觉得特别遗憾吧😅。加上这一年`浑浑噩噩`的,也没有什么产出,做的东西不如18,19年多。所以打算把自己18-19的项目重写出来,给大家一些参考。最重点的是@我去热饭,饭佬的持续更新让我觉得我也得努力一把了。
项目起源是本人很期待的某家头部公司🐧拒绝了我,觉得特别遗憾吧😅。加上这一年`浑浑噩噩`的,也没有什么产出,做的东西不如18,19年多。所以打算把自己18-19的项目重写出来,给大家一些参考。

### 作者介绍 📞

Expand All @@ -20,7 +60,7 @@

个人技术公众号: `米洛的测开日记`,欢迎大家关注我,掌握最新测试开发知识。

![](https://gitee.com/woodywrx/picture/raw/master/2021-12-11/1639202623437-qrcode_for_gh_f52fb2135f68_258.jpg)
![](https://gitee.com/woodywrx/picture/raw/master/2022-1-1/1641020334827-qrcode_for_gh_f52fb2135f68_430.jpg)

### 平台初心❤️

Expand Down
84 changes: 84 additions & 0 deletions README_EN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
[中文文档](https://github.com/wuranxu/pity/blob/main/README.md)

## Getting Started

1. clone code

```bash
$ git clone https://github.com/wuranxu/pity
$ cd pity
```

2. install dependencies

```bash
# 可换豆瓣源或者清华源安装依赖
$ pip install -r requirements.txt
```

3. install and start redis

4. install and start mysql

5. edit config.py

edit connection info about redis and mysql

6. start server

```bash
$ python main.py
```

7. registry

Fisrt people will be `ADMIN`

![](https://gitee.com/woodywrx/picture/raw/master/2022-1-2/1641092636428-image.png)

Sign in and enjoy `pity`

## Overview 🖕

[Documents 🍚](http://pity.readthedocs.org/)

[Demo 🍍](http://121.5.2.74/)

### About pity 😢

pity is an auto test tool based on `Python`+`FastApi`+`React` for api test. It's not an absolute production right now.

### Heart ❤️

I hope pity can help someone still uses robotframework or writes script for apitest.pity can help you a lot.

### Features😊

+ [x] 🔥 absolute auth rule, support login with github

- [x] 🀄 absolute project management

* [x] 🚴 fast with FastApi

- [x] 📝 many options for data dependencies, you can make and use data so easy
- [x] 🎨 online http request like postman
- [x] 🍷 global variable for you
- [x] 🐍 redis online
- [x] 🐎 test plan
- [x] 🙈 online database manager
- [x] 📰 beautiful email notification
- [x] 😹 cronjob for case
- [x] 🐧 beautiful test report

## Comming soon 🙋

- [ ] 🐘 Micro Services
- [ ] 🐄 DataFactory for developing data
- [ ] 🐸 support har/jmx to pity case
- [ ] 👍 CI/CD,like pipeline, provide openapi
- [ ] 🌼 notification
- [ ] 🌛 support dubbo/grpc
- [ ] 🐛 yapi
- [ ] 🌽 and so on

You can open issues to communicate with me, if you like the project, give a star will make me happy.
9 changes: 6 additions & 3 deletions app/core/ws_connection_manager.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# import abc
from typing import TypeVar

from fastapi import WebSocket

from app.utils.logger import Log
from typing import TypeVar

MsgType = TypeVar('MsgType', str, dict, bytes)

Expand All @@ -23,6 +25,7 @@
class ConnectionManager:
def __init__(self):
self.active_connections: dict[str, WebSocket] = {}
self.log = Log("websocket")

async def connect(self, websocket: WebSocket, client_id: str):
await websocket.accept()
Expand All @@ -32,10 +35,10 @@ async def connect(self, websocket: WebSocket, client_id: str):
self.active_connections[client_id]: str = websocket
else:
self.active_connections[client_id]: str = websocket
Log().info(F"websocket{client_id}: 建立连接成功!")
self.log.info(F"websocket{client_id}: 建立连接成功!")

def disconnect(self, client_id: str):
Log().info(F"websocket{self.active_connections.pop(client_id)}: 已安全断开!")
self.log.info(F"websocket{self.active_connections.pop(client_id)}: 已安全断开!")

@staticmethod
async def pusher(sender: WebSocket, message: MsgType):
Expand Down
29 changes: 16 additions & 13 deletions app/crud/auth/UserDao.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import random
from datetime import datetime

from sqlalchemy import or_, select
from sqlalchemy import or_, select, func

from app.middleware.Jwt import UserToken
from app.middleware.RedisManager import RedisHelper
Expand Down Expand Up @@ -90,7 +90,7 @@ async def register_for_github(username, name, email, avatar):
raise Exception("登录失败")

@staticmethod
def register_user(username, name, password, email):
async def register_user(username: str, name: str, password: str, email: str):
"""
:param username: 用户名
Expand All @@ -100,19 +100,22 @@ def register_user(username, name, password, email):
:return:
"""
try:
with Session() as session:
users = session.query(User).filter(or_(User.username == username, User.email == email)).all()
if users:
raise Exception("用户名或邮箱已存在")
# 注册的时候给密码加盐
pwd = UserToken.add_salt(password)
user = User(username, name, pwd, email)
session.add(user)
session.commit()
async with async_session() as session:
async with session.begin():
users = await session.execute(select(User).where(or_(User.username == username, User.email == email)))
counts = await session.execute(select(func.count(User.id)))
if users.scalars().first():
raise Exception("用户名或邮箱已存在")
# 注册的时候给密码加盐
pwd = UserToken.add_salt(password)
user = User(username, name, pwd, email)
# 如果用户数量为0 则注册为超管
if counts.scalars().first() == 0:
user.role = Config.ADMIN
session.add(user)
except Exception as e:
UserDao.log.error(f"用户注册失败: {str(e)}")
return str(e)
return None
raise Exception("注册失败")

@staticmethod
async def login(username, password):
Expand Down
12 changes: 9 additions & 3 deletions app/models/schema/user.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
from pydantic import BaseModel

from pydantic import BaseModel, validator

# 都可以为空,为空则不进行更改
from app.models.schema.base import PityModel


class UserUpdateForm(BaseModel):
id: int = None
id: int
name: str = None
email: str = None
role: int = None
is_valid: bool = None

@validator('id')
def id_not_empty(cls, v):
return PityModel.not_empty(v)
10 changes: 5 additions & 5 deletions app/routers/auth/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@
# router注册的函数都会自带/auth,所以url是/auth/register
@router.post("/register")
async def register(user: UserDto):
err = UserDao.register_user(**user.dict())
if err is not None:
return dict(code=110, msg=err)
return dict(code=0, msg="注册成功")
try:
await UserDao.register_user(**user.dict())
return PityResponse.success(msg="注册成功, 请登录")
except Exception as e:
return PityResponse.failed(e)


@router.post("/login")
Expand Down Expand Up @@ -80,4 +81,3 @@ async def delete_user(id: int, user=Depends(Permission(Config.ADMIN))):
return PityResponse.success(PityResponse.model_to_dict(user))
except Exception as e:
return PityResponse.failed(e)

5 changes: 5 additions & 0 deletions app/utils/logger.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import os

import logbook

from config import Config
Expand All @@ -13,6 +15,9 @@ def __init__(self, name='pity', filename=Config.LOG_NAME): # Logger标识默认
:param name: 业务名称
:param filename: 文件名称
"""
# 如果目录不存在则创建
if not os.path.exists(Config.LOG_DIR):
os.mkdir(Config.LOG_DIR)
self.handler = logbook.FileHandler(filename, encoding='utf-8')
logbook.set_datetime_format("local") # 将日志时间设置为本地时间
self.logger = logbook.Logger(name)
Expand Down
8 changes: 5 additions & 3 deletions config.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# 基础配置类
import os
from enum import IntEnum


class Config(object):
ROOT = os.path.dirname(os.path.abspath(__file__))
LOG_NAME = os.path.join(ROOT, 'logs', 'pity.log')
LOG_DIR = os.path.join(ROOT, 'logs')
LOG_NAME = os.path.join(LOG_DIR, 'pity.log')
# JSON_AS_ASCII = False # Flask jsonify编码问题

# MySQL连接信息
Expand All @@ -14,7 +16,7 @@ class Config(object):
MYSQL_PWD = "wuranxu@33"
DBNAME = "pity"

REDIS_HOST = "127.0.0.1"
REDIS_HOST = "121.5.2.74"
REDIS_PORT = 7788
REDIS_DB = 0
REDIS_PASSWORD = "woodywu123"
Expand Down Expand Up @@ -73,7 +75,7 @@ class Config(object):
IGNORE_FIELDS = ('created_at', "updated_at", "deleted_at", "create_user", "update_user")

# 请求类型
class BodyType:
class BodyType(IntEnum):
none = 0
json = 1
form = 2
Expand Down
4 changes: 2 additions & 2 deletions templates/report.html
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,10 @@ <h1 id="cTMail-title" style="font-size: 20px; line-height: 36px; margin: 0px 0px
</p>

<p id="cTMail-rights" style="max-width: 100%; margin:auto;font-size:12px;color:#999;text-align:center;line-height:22px;">
<img border="0" src="https://gitee.com/woodywrx/picture/raw/master/2021-8-7/1628267097936-qrcode_for_gh_554fe7a74955_258.jpg"
<img border="0" src="https://gitee.com/woodywrx/picture/raw/master/2022-1-1/1641020334827-qrcode_for_gh_f52fb2135f68_430.jpg"
style="width:84px; height:84px; margin:0 auto;">
<br>
关注测试开发坑货,了解pity更多内容
关注米洛的测开日记,了解pity更多内容
<br>
</p>
</td>
Expand Down

0 comments on commit 1ad19ee

Please sign in to comment.