Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

api team list #8

Merged
merged 14 commits into from
Jan 2, 2024
17 changes: 16 additions & 1 deletion server/app.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import logging
import os

from flask import Flask, session
from flask import Flask, jsonify
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy

Expand All @@ -13,6 +13,21 @@
app, allow_headers=["Authorization", "X-Requested-With"], supports_credentials=True
)


@app.errorhandler(404)
def page_not_found(error):
response = jsonify({"code": -1, "msg": error.description})
response.status_code = 404
return response


@app.errorhandler(400)
def bad_request(error):
response = jsonify({"code": -1, "msg": error.description})
response.status_code = 400
return response


gunicorn_logger = logging.getLogger("gunicorn.error")
app.logger.handlers = gunicorn_logger.handlers
app.logger.setLevel(gunicorn_logger.level)
16 changes: 16 additions & 0 deletions server/model/schema.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import json
import logging
from datetime import datetime
from time import time

import bson
import click
from app import app, db
from flask.cli import with_appcontext
from flask.json.provider import DefaultJSONProvider
from sqlalchemy import BINARY, ForeignKey, String, text


Expand Down Expand Up @@ -318,6 +320,20 @@ class ChatGroup(Base):
)


class CustomJsonProvider(DefaultJSONProvider):
@staticmethod
def default(value):
if isinstance(value, db.Model):
return value.__dict__
elif isinstance(value, datetime):
return value.strftime("%Y-%m-%d %H:%M:%S")
return str(value)


app.json_provider_class = CustomJsonProvider
app.json = CustomJsonProvider(app)


# create command function
@click.command(name="create")
@with_appcontext
Expand Down
109 changes: 109 additions & 0 deletions server/model/team.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
from flask import abort
from sqlalchemy import and_, or_
from utils.utils import query_one_page

from .schema import Team, TeamMember, db


def get_team_list_by_user_id(user_id, page=1, size=100):
query = db.session.query(Team).filter(
or_(
Team.user_id == user_id, # 管理员
and_(
TeamMember.team_id == Team.id,
TeamMember.code_user_id == user_id, # 属于某个team的员工
TeamMember.status == 0,
),
),
Team.status == 0,
)
total = query.count()
if total == 0:
return [], 0
return query_one_page(query, page, size), total


def is_team_admin(team_id, user_id):
return (
True
if db.session.query(Team.id)
.filter(
Team.user_id == user_id,
Team.status == 0,
)
.limit(1)
.scalar()
else False
)


def get_team_by_id(team_id, user_id):
team = (
db.session.query(Team)
.filter(
or_(
Team.user_id == user_id, # 管理员
and_(
TeamMember.team_id == Team.id,
TeamMember.code_user_id == user_id, # 属于某个team的员工
TeamMember.status == 0,
),
),
Team.status == 0,
)
.first()
)
if not team:
return abort(404, "can not found team by id")
return team


def get_platform_info_by_team_id(team_id):
# TODO
return None, None


def get_team_member(team_id, user_id, page=1, size=20):
query = db.session.query(TeamMember).filter(
TeamMember.team_id == team_id,
TeamMember.status == 0,
)
# admin can get all users in current_team
if not is_team_admin(team_id, user_id):
query = query.filter(
TeamMember.code_user_id == user_id,
)
total = query.count()
if total == 0:
return [], 0
return query_one_page(query, page, size), total


def get_im_user_by_team_id(team_id, page=1, size=20):
query = (
db.session.query(BindUser)
.join(
IMPlatform,
IMPlatform.id == BindUser.platform_id,
)
.filter(
IMPlatform.team_id == team_id,
IMPlatform.status == 0,
BindUser.status == 0,
)
)
total = query.count()
if total == 0:
return [], 0
return query_one_page(query, page, size), total

data, total = get_im_user_by_team_id(team_id, page, size)


def set_team_member(team_id, code_user_id, im_user_id):
db.session.query(TeamMember).filter(
TeamMember.team_id == team_id,
TeamMember.code_user_id == code_user_id,
TeamMember.status == 0,
).update(dict(im_user_id=im_user_id))
db.session.commit()
14 changes: 14 additions & 0 deletions server/model/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from sqlalchemy import and_, or_

from .schema import User, db


def get_user_by_id(user_id):
return (
db.session.query(User)
.filter(
User.id == user_id,
User.status == 0,
)
.first()
)
1 change: 1 addition & 0 deletions server/routes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .github import *
from .lark import *
from .team import *
from .user import *
4 changes: 2 additions & 2 deletions server/routes/lark.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import logging
import os

from app import app, session
from app import app
from connectai.lark.oauth import Server as OauthServerBase
from connectai.lark.sdk import Bot, MarketBot
from connectai.lark.webhook import LarkServer as LarkServerBase
from flask import session
from model.lark import get_bot_by_app_id


Expand Down
91 changes: 87 additions & 4 deletions server/routes/team.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import logging

from app import app
from flask import Blueprint, abort, jsonify, redirect, request
from flask import Blueprint, abort, jsonify, redirect, request, session
from model.team import (
get_im_user_by_team_id,
get_platform_info_by_team_id,
get_team_by_id,
get_team_list_by_user_id,
get_team_member,
is_team_admin,
set_team_member,
)
from utils.auth import authenticated

bp = Blueprint("team", __name__, url_prefix="/api/team")
Expand All @@ -14,7 +21,83 @@ def get_team_list():
get team list
TODO
"""
return jsonify({"code": 0, "msg": "success", "data": [], "total": 0})
data, total = get_team_list_by_user_id(session["user_id"])
return jsonify({"code": 0, "msg": "success", "data": data, "total": total})


@bp.route("/<team_id>", methods=["GET"])
@authenticated
def get_team_detail(team_id):
team = get_team_by_id(team_id, session["user_id"])
code_platform, im_platform = get_platform_info_by_team_id(team_id)
return jsonify(
{
"code": 0,
"msg": "success",
"data": {
"team": team,
"code_platform": code_platform,
"im_platform": im_platform,
},
}
)


@bp.route("/<team_id>/member", methods=["GET"])
@authenticated
def get_team_member_by_team_id(team_id):
page = request.args.get("page", default=1, type=int)
size = request.args.get("size", default=20, type=int)

current_user = session["user_id"]
data, total = get_team_member(team_id, current_user, page, size)
return jsonify({"code": 0, "msg": "success", "data": data, "total": total})


@bp.route("/<team_id>/<platform>/user", methods=["GET"])
@authenticated
def get_im_user_by_team_id_and_platform(team_id, platform):
page = request.args.get("page", default=1, type=int)
size = request.args.get("size", default=20, type=int)

if platform not in ["lark"]: # TODO lark/slack...
return abort(400, "params error")

current_user = session["user_id"]
data, total = get_im_user_by_team_id(team_id, page, size)
return jsonify(
{
"code": 0,
"msg": "success",
"data": [
{
"value": i.user_id,
"label": i.name or i.email,
"email": i.email,
"avatar": i.avatar,
}
for i in data
],
"total": total,
}
)


@bp.route("/<team_id>/member", methods=["POST"])
@authenticated
def save_team_member_by_team_id(team_id):
code_user_id = request.json.get("code_user_id")
im_user_id = request.json.get("im_user_id")
if not code_user_id or not im_user_id:
return abort(400, "params error")

current_user = session["user_id"]
is_admin = is_team_admin(team_id, current_user)
if current_user != code_user_id and not is_admin:
return abort(400, "permission error")

set_team_member(team_id, code_user_id, im_user_id)
return jsonify({"code": 0, "msg": "success"})


app.register_blueprint(bp)
33 changes: 33 additions & 0 deletions server/routes/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from app import app
from flask import Blueprint, jsonify, session
from model.team import get_team_list_by_user_id, is_team_admin
from model.user import get_user_by_id
from utils.auth import authenticated

bp = Blueprint("user", __name__, url_prefix="/api")


@bp.route("/account", methods=["GET"])
@authenticated
def get_account():
current_user = session["user_id"]
user = get_user_by_id(current_user)
teams, _ = get_team_list_by_user_id(current_user)
current_team = session.get("team_id")
if not current_team and len(teams) > 0:
current_team = teams[0].id
is_admin = is_team_admin(current_team, current_user) if current_team else False
return jsonify(
{
"code": 0,
"msg": "success",
"data": {
"user": user,
"current_team": current_team,
"is_team_admin": is_admin,
},
}
)


app.register_blueprint(bp)
2 changes: 1 addition & 1 deletion server/utils/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
def authenticated(func):
@wraps(func)
def wrapper(*args, **kwargs):
if "user_id" not in session:
if not session.get("user_id"):
return abort(401)
return func(*args, **kwargs)

Expand Down
2 changes: 1 addition & 1 deletion server/utils/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def register(code: str) -> str | None:
)

db.session.add(new_user)
db.session.commit()
db.session.flush()

new_bind_user = BindUser(
id=ObjID.new_id(),
Expand Down
5 changes: 5 additions & 0 deletions server/utils/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
def query_one_page(query, page, size):
offset = (page - 1) * int(size)
return (
query.offset(offset if offset > 0 else 0).limit(size if size > 0 else 0).all()
)