Compare commits
6 Commits
feature-xj
...
feature-xj
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
055ec1aeaf | ||
|
|
321f14b229 | ||
|
|
1626091e36 | ||
| fa1d3b01b0 | |||
|
|
bf4abe3cad | ||
|
|
3f98e17215 |
@@ -25,11 +25,15 @@ async def login(
|
||||
minutes=security.ACCESS_TOKEN_EXPIRE_MINUTES
|
||||
)
|
||||
if user.is_superuser:
|
||||
permissions = "admin"
|
||||
roles = "super"
|
||||
permissions = "ALL"
|
||||
else:
|
||||
permissions = "user"
|
||||
roles = ";".join(role.name for role in user.roles)
|
||||
perlst = [perm.privilege for role in user.roles for perm in role.permissions]
|
||||
permissions =";".join(list(set(perlst)))
|
||||
|
||||
access_token = security.create_access_token(
|
||||
data={"sub": user.id, "permissions": permissions},
|
||||
data={"sub": user.id, "roles":roles,"permissions": permissions ,},
|
||||
expires_delta=access_token_expires,
|
||||
)
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ platform_router = r = APIRouter()
|
||||
)
|
||||
async def apps_list(
|
||||
request: Request,
|
||||
user = Depends(get_current_user),
|
||||
user = Depends(get_current_active_user),
|
||||
db=Depends(get_db),
|
||||
):
|
||||
try:
|
||||
@@ -60,7 +60,7 @@ async def apps_list(
|
||||
async def apps_update(
|
||||
request: Request,
|
||||
app: AppVersion,
|
||||
user=Depends(get_current_user),
|
||||
user=Depends(get_current_active_user),
|
||||
db=Depends(get_db),
|
||||
):
|
||||
try:
|
||||
@@ -68,7 +68,21 @@ async def apps_update(
|
||||
except Exception as e:
|
||||
raise APIException('platform:apps',request.url._url,f"Error occurred while get create app :",e)
|
||||
|
||||
|
||||
@r.delete(
|
||||
"/apps/{domainurl}/{appid}", response_model_exclude_none=True
|
||||
)
|
||||
async def apps_delete(
|
||||
request: Request,
|
||||
domainurl:str,
|
||||
appid: str,
|
||||
user=Depends(get_current_active_user),
|
||||
db=Depends(get_db),
|
||||
):
|
||||
try:
|
||||
return delete_apps(db, domainurl,appid)
|
||||
except Exception as e:
|
||||
raise APIException('platform:apps',request.url._url,f"Error occurred while delete apps({domainurl}:{appid}):",e)
|
||||
|
||||
@r.get(
|
||||
"/appsettings/{id}",
|
||||
response_model=App,
|
||||
@@ -183,7 +197,7 @@ async def flow_details(
|
||||
async def flow_list(
|
||||
request: Request,
|
||||
appid: str,
|
||||
user=Depends(get_current_user),
|
||||
user=Depends(get_current_active_user),
|
||||
db=Depends(get_db),
|
||||
):
|
||||
try:
|
||||
@@ -198,8 +212,8 @@ async def flow_list(
|
||||
@r.post("/flow", response_model=Flow, response_model_exclude_none=True)
|
||||
async def flow_create(
|
||||
request: Request,
|
||||
flow: FlowBase,
|
||||
user=Depends(get_current_user),
|
||||
flow: FlowIn,
|
||||
user=Depends(get_current_active_user),
|
||||
db=Depends(get_db),
|
||||
):
|
||||
try:
|
||||
@@ -215,13 +229,13 @@ async def flow_create(
|
||||
async def flow_edit(
|
||||
request: Request,
|
||||
flowid: str,
|
||||
flow: FlowBase,
|
||||
user=Depends(get_current_user),
|
||||
flow: FlowIn,
|
||||
user=Depends(get_current_active_user),
|
||||
db=Depends(get_db),
|
||||
):
|
||||
try:
|
||||
domain = get_activedomain(db, user.id)
|
||||
return edit_flow(db,domain.url, flow)
|
||||
return edit_flow(db,domain.url, flow,user.id)
|
||||
except Exception as e:
|
||||
raise APIException('platform:flow',request.url._url,f"Error occurred while edit flow:",e)
|
||||
|
||||
@@ -259,7 +273,7 @@ async def domain_details(
|
||||
async def domain_create(
|
||||
request: Request,
|
||||
domain: DomainBase,
|
||||
user=Depends(get_current_user),
|
||||
user=Depends(get_current_active_user),
|
||||
db=Depends(get_db),
|
||||
):
|
||||
try:
|
||||
@@ -274,10 +288,11 @@ async def domain_create(
|
||||
async def domain_edit(
|
||||
request: Request,
|
||||
domain: DomainBase,
|
||||
user=Depends(get_current_active_user),
|
||||
db=Depends(get_db),
|
||||
):
|
||||
try:
|
||||
return edit_domain(db, domain)
|
||||
return edit_domain(db, domain,user.id)
|
||||
except Exception as e:
|
||||
raise APIException('platform:domain',request.url._url,f"Error occurred while edit domain:",e)
|
||||
|
||||
@@ -303,7 +318,7 @@ async def domain_delete(
|
||||
async def userdomain_details(
|
||||
request: Request,
|
||||
userId: Optional[int] = Query(None, alias="userId"),
|
||||
user=Depends(get_current_user),
|
||||
user=Depends(get_current_active_user),
|
||||
db=Depends(get_db),
|
||||
):
|
||||
try:
|
||||
@@ -351,7 +366,7 @@ async def userdomain_delete(
|
||||
async def get_useractivedomain(
|
||||
request: Request,
|
||||
userId: Optional[int] = Query(None, alias="userId"),
|
||||
user=Depends(get_current_user),
|
||||
user=Depends(get_current_active_user),
|
||||
db=Depends(get_db),
|
||||
):
|
||||
try:
|
||||
@@ -371,7 +386,7 @@ async def update_activeuserdomain(
|
||||
request: Request,
|
||||
domainid:int,
|
||||
userId: Optional[int] = Query(None, alias="userId"),
|
||||
user=Depends(get_current_user),
|
||||
user=Depends(get_current_active_user),
|
||||
db=Depends(get_db),
|
||||
):
|
||||
try:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from fastapi import APIRouter, Request, Depends, Response, encoders
|
||||
from fastapi import APIRouter, Request, Depends, Response, Security, encoders
|
||||
import typing as t
|
||||
|
||||
from app.db.session import get_db
|
||||
@@ -8,9 +8,11 @@ from app.db.crud import (
|
||||
create_user,
|
||||
delete_user,
|
||||
edit_user,
|
||||
assign_userrole,
|
||||
get_roles,
|
||||
)
|
||||
from app.db.schemas import UserCreate, UserEdit, User, UserOut
|
||||
from app.core.auth import get_current_active_user, get_current_active_superuser
|
||||
from app.db.schemas import UserCreate, UserEdit, User, UserOut,Role
|
||||
from app.core.auth import get_current_user,get_current_active_user, get_current_active_superuser
|
||||
|
||||
users_router = r = APIRouter()
|
||||
|
||||
@@ -23,14 +25,14 @@ users_router = r = APIRouter()
|
||||
async def users_list(
|
||||
response: Response,
|
||||
db=Depends(get_db),
|
||||
current_user=Depends(get_current_active_superuser),
|
||||
current_user=Depends(get_current_active_user),
|
||||
):
|
||||
"""
|
||||
Get all users
|
||||
"""
|
||||
users = get_users(db)
|
||||
users = get_users(db,current_user.is_superuser)
|
||||
# This is necessary for react-admin to work
|
||||
response.headers["Content-Range"] = f"0-9/{len(users)}"
|
||||
#response.headers["Content-Range"] = f"0-9/{len(users)}"
|
||||
return users
|
||||
|
||||
|
||||
@@ -105,3 +107,30 @@ async def user_delete(
|
||||
Delete existing user
|
||||
"""
|
||||
return delete_user(db, user_id)
|
||||
|
||||
|
||||
@r.post("/userrole",
|
||||
response_model=User,
|
||||
response_model_exclude_none=True,)
|
||||
async def assign_role(
|
||||
request: Request,
|
||||
userid:int,
|
||||
roles:t.List[int],
|
||||
db=Depends(get_db)
|
||||
):
|
||||
|
||||
return assign_userrole(db,userid,roles)
|
||||
|
||||
|
||||
@r.get(
|
||||
"/roles",
|
||||
response_model=t.List[Role],
|
||||
response_model_exclude_none=True,
|
||||
)
|
||||
async def roles_list(
|
||||
response: Response,
|
||||
db=Depends(get_db),
|
||||
current_user=Security(get_current_active_user, scopes=["role_list"]),
|
||||
):
|
||||
roles = get_roles(db)
|
||||
return roles
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from fastapi.security import SecurityScopes
|
||||
import jwt
|
||||
from fastapi import Depends, HTTPException, status
|
||||
from fastapi import Depends, HTTPException, Request, Security, status
|
||||
from jwt import PyJWTError
|
||||
|
||||
from app.db import models, schemas, session
|
||||
@@ -7,7 +8,7 @@ from app.db.crud import get_user_by_email, create_user,get_user
|
||||
from app.core import security
|
||||
|
||||
|
||||
async def get_current_user(
|
||||
async def get_current_user(security_scopes: SecurityScopes,
|
||||
db=Depends(session.get_db), token: str = Depends(security.oauth2_scheme)
|
||||
):
|
||||
credentials_exception = HTTPException(
|
||||
@@ -16,13 +17,21 @@ async def get_current_user(
|
||||
headers={"WWW-Authenticate": "Bearer"},
|
||||
)
|
||||
try:
|
||||
|
||||
payload = jwt.decode(
|
||||
token, security.SECRET_KEY, algorithms=[security.ALGORITHM]
|
||||
)
|
||||
id: int = payload.get("sub")
|
||||
if id is None:
|
||||
raise credentials_exception
|
||||
|
||||
permissions: str = payload.get("permissions")
|
||||
if not permissions =="ALL":
|
||||
for scope in security_scopes.scopes:
|
||||
if scope not in permissions.split(";"):
|
||||
raise HTTPException(
|
||||
status_code=403, detail="The user doesn't have enough privileges"
|
||||
)
|
||||
token_data = schemas.TokenData(id = id, permissions=permissions)
|
||||
except PyJWTError:
|
||||
raise credentials_exception
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from datetime import datetime
|
||||
from fastapi import HTTPException, status
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy import and_
|
||||
@@ -19,9 +20,12 @@ def get_user_by_email(db: Session, email: str) -> schemas.UserBase:
|
||||
|
||||
|
||||
def get_users(
|
||||
db: Session, skip: int = 0, limit: int = 100
|
||||
db: Session, super:bool
|
||||
) -> t.List[schemas.UserOut]:
|
||||
return db.query(models.User).offset(skip).limit(limit).all()
|
||||
if super:
|
||||
return db.query(models.User).all()
|
||||
else:
|
||||
return db.query(models.User).filter(models.User.is_superuser == False)
|
||||
|
||||
|
||||
def create_user(db: Session, user: schemas.UserCreate):
|
||||
@@ -69,28 +73,48 @@ def edit_user(
|
||||
db.refresh(db_user)
|
||||
return db_user
|
||||
|
||||
|
||||
def get_roles(
|
||||
db: Session
|
||||
) -> t.List[schemas.Role]:
|
||||
return db.query(models.Role).all()
|
||||
|
||||
def assign_userrole( db: Session, user_id: int, roles: t.List[int]):
|
||||
db_user = db.query(models.User).get(user_id)
|
||||
if db_user:
|
||||
for role in db_user.roles:
|
||||
db_user.roles.remove(role)
|
||||
for roleid in roles:
|
||||
role = db.query(models.Role).get(roleid)
|
||||
if role:
|
||||
db_user.roles.append(role)
|
||||
db.commit()
|
||||
db.refresh(db_user)
|
||||
return db_user
|
||||
|
||||
def get_apps(
|
||||
db: Session,
|
||||
domain_url:str
|
||||
domainurl:str
|
||||
) -> t.List[schemas.AppList]:
|
||||
return db.query(models.App).filter(models.App.domainurl == domain_url).all()
|
||||
return db.query(models.App).filter(models.App.domainurl == domainurl).all()
|
||||
|
||||
def update_appversion(db: Session, appedit: schemas.AppVersion,userid:int):
|
||||
app = db.query(models.App).filter(and_(models.App.domainurl == appedit.domainurl,models.App.appid == appedit.appid)).first()
|
||||
if app:
|
||||
app.version = app.version + 1
|
||||
db_app = app
|
||||
appver = app.version
|
||||
else:
|
||||
appver = 1
|
||||
db_app = models.App(
|
||||
db_app = db.query(models.App).filter(and_(models.App.domainurl == appedit.domainurl,models.App.appid == appedit.appid)).first()
|
||||
if not db_app:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, detail="User not found")
|
||||
|
||||
db_app.version = db_app.version + 1
|
||||
appversion = models.AppVersion(
|
||||
domainurl = appedit.domainurl,
|
||||
appid=appedit.appid,
|
||||
appname=appedit.appname,
|
||||
version = 1,
|
||||
updateuser= userid
|
||||
)
|
||||
|
||||
appname=db_app.appname,
|
||||
version = db_app.version,
|
||||
versionname = appedit.versionname,
|
||||
comment = appedit.comment,
|
||||
updateuserid = userid,
|
||||
createuserid = userid
|
||||
)
|
||||
db.add(appversion)
|
||||
db.add(db_app)
|
||||
|
||||
flows = db.query(models.Flow).filter(and_(models.Flow.domainurl == appedit.domainurl,models.App.appid == appedit.appid))
|
||||
@@ -103,7 +127,9 @@ def update_appversion(db: Session, appedit: schemas.AppVersion,userid:int):
|
||||
name = flow.name,
|
||||
content = flow.content,
|
||||
createuser = userid,
|
||||
version = appver
|
||||
version = db_app.version,
|
||||
updateuserid = userid,
|
||||
createuserid = userid
|
||||
)
|
||||
db.add(db_flowhistory)
|
||||
|
||||
@@ -111,6 +137,17 @@ def update_appversion(db: Session, appedit: schemas.AppVersion,userid:int):
|
||||
db.refresh(db_app)
|
||||
return db_app
|
||||
|
||||
def delete_apps(db: Session, domainurl: str,appid: str ):
|
||||
db_app = db.query(models.App).filter(and_(models.App.domainurl == domainurl,models.App.appid ==appid)).first()
|
||||
if not db_app:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, detail="App not found")
|
||||
db.delete(db_app)
|
||||
db_flows = db.query(models.Flow).filter(and_(models.Flow.domainurl == domainurl,models.Flow.appid ==appid))
|
||||
for flow in db_flows:
|
||||
db.delete(flow)
|
||||
db.commit()
|
||||
return db_app
|
||||
|
||||
def get_appsetting(db: Session, id: int):
|
||||
app = db.query(models.AppSetting).get(id)
|
||||
if not app:
|
||||
@@ -166,16 +203,28 @@ def get_actions(db: Session):
|
||||
return actions
|
||||
|
||||
|
||||
def create_flow(db: Session, domainurl: str, flow: schemas.FlowBase):
|
||||
def create_flow(db: Session, domainurl: str, flow: schemas.FlowIn,userid:int):
|
||||
db_flow = models.Flow(
|
||||
flowid=flow.flowid,
|
||||
appid=flow.appid,
|
||||
eventid=flow.eventid,
|
||||
domainurl=domainurl,
|
||||
name=flow.name,
|
||||
content=flow.content
|
||||
content=flow.content,
|
||||
createuserid = userid,
|
||||
updateuserid = userid
|
||||
)
|
||||
db.add(db_flow)
|
||||
db_app = db.query(models.App).filter(and_(models.App.domainurl == domainurl,models.App.appid == flow.appid)).first()
|
||||
if not db_app:
|
||||
db_app = models.App(
|
||||
domainurl = domainurl,
|
||||
appid=flow.appid,
|
||||
appname=flow.appname,
|
||||
version = 0,
|
||||
createuserid= userid,
|
||||
updateuserid = userid
|
||||
)
|
||||
db.commit()
|
||||
db.refresh(db_flow)
|
||||
return db_flow
|
||||
@@ -190,18 +239,20 @@ def delete_flow(db: Session, flowid: str):
|
||||
|
||||
|
||||
def edit_flow(
|
||||
db: Session, domainurl: str, flow: schemas.FlowBase
|
||||
db: Session, domainurl: str, flow: schemas.FlowIn,userid:int
|
||||
) -> schemas.Flow:
|
||||
db_flow = get_flow(db, flow.flowid)
|
||||
if not db_flow:
|
||||
#見つからない時新規作成
|
||||
return create_flow(db,domainurl,flow)
|
||||
return create_flow(db,domainurl,flow,userid)
|
||||
|
||||
db_flow.appid =flow.appid
|
||||
db_flow.eventid=flow.eventid
|
||||
db_flow.domainurl=domainurl
|
||||
db_flow.name=flow.name
|
||||
db_flow.content=flow.content
|
||||
db_flow.updateuserid = userid
|
||||
|
||||
update_data = flow.dict(exclude_unset=True)
|
||||
|
||||
for key, value in update_data.items():
|
||||
setattr(db_flow, key, value)
|
||||
|
||||
db.add(db_flow)
|
||||
db.commit()
|
||||
db.refresh(db_flow)
|
||||
@@ -233,7 +284,9 @@ def create_domain(db: Session, domain: schemas.DomainBase,userid:int):
|
||||
name=domain.name,
|
||||
url=domain.url,
|
||||
kintoneuser=domain.kintoneuser,
|
||||
kintonepwd=domain.kintonepwd
|
||||
kintonepwd=domain.kintonepwd,
|
||||
createuserid = userid,
|
||||
updateuserid = userid
|
||||
)
|
||||
db.add(db_domain)
|
||||
db.flush()
|
||||
@@ -252,18 +305,19 @@ def delete_domain(db: Session,id: int):
|
||||
|
||||
|
||||
def edit_domain(
|
||||
db: Session, domain: schemas.DomainBase
|
||||
db: Session, domain: schemas.DomainBase,userid:int
|
||||
) -> schemas.Domain:
|
||||
domain.encrypt_kintonepwd()
|
||||
db_domain = db.query(models.Domain).get(domain.id)
|
||||
if not db_domain:
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, detail="Domain not found")
|
||||
update_data = domain.dict(exclude_unset=True)
|
||||
|
||||
for key, value in update_data.items():
|
||||
if key != "id" and not (key == "kintonepwd" and (value is None or value == "")):
|
||||
setattr(db_domain, key, value)
|
||||
print(str(db_domain))
|
||||
raise HTTPException(status.HTTP_404_NOT_FOUND, detail="Domain not found")
|
||||
db_domain.tenantid = domain.tenantid
|
||||
db_domain.name=domain.name
|
||||
db_domain.url=domain.url
|
||||
db_domain.kintoneuser=domain.kintoneuser
|
||||
db_domain.kintonepwd = domain.kintonepwd
|
||||
db_domain.updateuserid = userid
|
||||
db_domain.update_time = datetime.now
|
||||
db.add(db_domain)
|
||||
db.commit()
|
||||
db.refresh(db_domain)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from sqlalchemy import Boolean, Column, Integer, String, DateTime,ForeignKey
|
||||
from sqlalchemy import Boolean, Column, Integer, String, DateTime,ForeignKey,Table
|
||||
from sqlalchemy.ext.declarative import as_declarative
|
||||
from sqlalchemy.orm import relationship
|
||||
from datetime import datetime
|
||||
|
||||
from app.db.session import Base
|
||||
from app.core.security import chacha20Decrypt
|
||||
|
||||
@as_declarative()
|
||||
@@ -11,6 +11,21 @@ class Base:
|
||||
create_time = Column(DateTime, default=datetime.now)
|
||||
update_time = Column(DateTime, default=datetime.now, onupdate=datetime.now)
|
||||
|
||||
|
||||
userrole = Table(
|
||||
"userrole",
|
||||
Base.metadata,
|
||||
Column("userid",Integer,ForeignKey("user.id")),
|
||||
Column("roleid",Integer,ForeignKey("role.id")),
|
||||
)
|
||||
|
||||
rolepermission = Table(
|
||||
"rolepermission",
|
||||
Base.metadata,
|
||||
Column("roleid",Integer,ForeignKey("role.id")),
|
||||
Column("permissionid",Integer,ForeignKey("permission.id")),
|
||||
)
|
||||
|
||||
class User(Base):
|
||||
__tablename__ = "user"
|
||||
|
||||
@@ -20,6 +35,25 @@ class User(Base):
|
||||
hashed_password = Column(String(200), nullable=False)
|
||||
is_active = Column(Boolean, default=True)
|
||||
is_superuser = Column(Boolean, default=False)
|
||||
roles = relationship("Role",secondary=userrole,back_populates="users")
|
||||
|
||||
|
||||
class Role(Base):
|
||||
__tablename__ = "role"
|
||||
|
||||
name = Column(String(100))
|
||||
description = Column(String(255))
|
||||
users = relationship("User",secondary=userrole,back_populates="roles")
|
||||
permissions = relationship("Permission",secondary=rolepermission,back_populates="roles")
|
||||
|
||||
class Permission(Base):
|
||||
__tablename__ = "permission"
|
||||
|
||||
menu = Column(String(100))
|
||||
function = Column(String(255))
|
||||
privilege = Column(String(100))
|
||||
roles = relationship("Role",secondary=rolepermission,back_populates="permissions")
|
||||
|
||||
|
||||
class App(Base):
|
||||
__tablename__ = "app"
|
||||
@@ -28,8 +62,25 @@ class App(Base):
|
||||
appname = Column(String(200), nullable=False)
|
||||
appid = Column(String(100), index=True, nullable=False)
|
||||
version = Column(Integer)
|
||||
updateuser = Column(Integer,ForeignKey("user.id"))
|
||||
user = relationship('User')
|
||||
createuserid = Column(Integer,ForeignKey("user.id"))
|
||||
updateuserid = Column(Integer,ForeignKey("user.id"))
|
||||
createuser = relationship('User',foreign_keys=[createuserid])
|
||||
updateuser = relationship('User',foreign_keys=[updateuserid])
|
||||
|
||||
class AppVersion(Base):
|
||||
__tablename__ = "appversion"
|
||||
|
||||
domainurl = Column(String(200), nullable=False)
|
||||
appname = Column(String(200), nullable=False)
|
||||
appid = Column(String(100), index=True, nullable=False)
|
||||
version = Column(Integer)
|
||||
versionname = Column(String(200), nullable=False)
|
||||
comment = Column(String(200), nullable=False)
|
||||
createuserid = Column(Integer,ForeignKey("user.id"))
|
||||
updateuserid = Column(Integer,ForeignKey("user.id"))
|
||||
createuser = relationship('User',foreign_keys=[createuserid])
|
||||
updateuser = relationship('User',foreign_keys=[updateuserid])
|
||||
|
||||
|
||||
class AppSetting(Base):
|
||||
__tablename__ = "appsetting"
|
||||
@@ -64,7 +115,11 @@ class Flow(Base):
|
||||
eventid = Column(String(100), index=True, nullable=False)
|
||||
domainurl = Column(String(200))
|
||||
name = Column(String(200))
|
||||
content = Column(String)
|
||||
content = Column(String)
|
||||
createuserid = Column(Integer,ForeignKey("user.id"))
|
||||
updateuserid = Column(Integer,ForeignKey("user.id"))
|
||||
createuser = relationship('User',foreign_keys=[createuserid])
|
||||
updateuser = relationship('User',foreign_keys=[updateuserid])
|
||||
|
||||
class FlowHistory(Base):
|
||||
__tablename__ = "flowhistory"
|
||||
@@ -75,8 +130,11 @@ class FlowHistory(Base):
|
||||
domainurl = Column(String(200))
|
||||
name = Column(String(200))
|
||||
content = Column(String)
|
||||
createuser = Column(Integer,ForeignKey("user.id"))
|
||||
version = Column(Integer)
|
||||
createuserid = Column(Integer,ForeignKey("user.id"))
|
||||
updateuserid = Column(Integer,ForeignKey("user.id"))
|
||||
createuser = relationship('User',foreign_keys=[createuserid])
|
||||
updateuser = relationship('User',foreign_keys=[updateuserid])
|
||||
|
||||
class Tenant(Base):
|
||||
__tablename__ = "tenant"
|
||||
@@ -98,7 +156,10 @@ class Domain(Base):
|
||||
def decrypt_kintonepwd(self):
|
||||
decrypted_pwd = chacha20Decrypt(self.kintonepwd)
|
||||
return decrypted_pwd
|
||||
|
||||
createuserid = Column(Integer,ForeignKey("user.id"))
|
||||
updateuserid = Column(Integer,ForeignKey("user.id"))
|
||||
createuser = relationship('User',foreign_keys=[createuserid])
|
||||
updateuser = relationship('User',foreign_keys=[updateuserid])
|
||||
|
||||
class UserDomain(Base):
|
||||
__tablename__ = "userdomain"
|
||||
|
||||
@@ -8,13 +8,26 @@ class Base(BaseModel):
|
||||
create_time: datetime
|
||||
update_time: datetime
|
||||
|
||||
|
||||
class Permission(BaseModel):
|
||||
id: int
|
||||
menu:str
|
||||
function:str
|
||||
privilege:str
|
||||
|
||||
class Role(BaseModel):
|
||||
id: int
|
||||
name:str
|
||||
description:str
|
||||
permissions:t.List[Permission] = []
|
||||
|
||||
class UserBase(BaseModel):
|
||||
email: str
|
||||
is_active: bool = True
|
||||
is_superuser: bool = False
|
||||
first_name: str = None
|
||||
last_name: str = None
|
||||
|
||||
roles:t.List[Role] = []
|
||||
|
||||
class UserOut(UserBase):
|
||||
pass
|
||||
@@ -54,13 +67,16 @@ class AppList(Base):
|
||||
domainurl: str
|
||||
appname: str
|
||||
appid:str
|
||||
updateuser: UserOut
|
||||
version:int
|
||||
user:UserOut
|
||||
|
||||
|
||||
class AppVersion(BaseModel):
|
||||
domainurl: str
|
||||
appname: str
|
||||
versionname: str
|
||||
comment:str
|
||||
appid:str
|
||||
|
||||
|
||||
class TokenData(BaseModel):
|
||||
id:int = 0
|
||||
@@ -106,9 +122,11 @@ class Action(BaseModel):
|
||||
class ConfigDict:
|
||||
orm_mode = True
|
||||
|
||||
class FlowBase(BaseModel):
|
||||
class FlowIn(BaseModel):
|
||||
flowid: str
|
||||
# domainurl:str
|
||||
appid: str
|
||||
appname:str
|
||||
eventid: str
|
||||
name: str = None
|
||||
content: str = None
|
||||
|
||||
@@ -17,28 +17,38 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { ref, onMounted, reactive, watchEffect } from 'vue'
|
||||
import { ref, onMounted, reactive, watchEffect, PropType } from 'vue'
|
||||
import { api } from 'boot/axios';
|
||||
|
||||
interface IAppDisplay {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
createdate: string;
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'AppSelectBox',
|
||||
props: {
|
||||
name: String,
|
||||
type: String,
|
||||
filter: String,
|
||||
filterInitRowsFunc: {
|
||||
type: Function as PropType<(app: IAppDisplay) => boolean>,
|
||||
},
|
||||
updateSelectApp: {
|
||||
type: Function
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
const columns = [
|
||||
{ name: 'id', required: true, label: 'ID', align: 'left', field: 'id', sortable: true },
|
||||
{ name: 'id', required: true, label: 'ID', align: 'left', field: 'id', sortable: true, sort: (a: string, b: string) => parseInt(a, 10) - parseInt(b, 10) },
|
||||
{ name: 'name', label: 'アプリ名', field: 'name', sortable: true, align: 'left' },
|
||||
{ name: 'description', label: '概要', field: 'description', align: 'left', sortable: false },
|
||||
{ name: 'createdate', label: '作成日時', field: 'createdate', align: 'left' }
|
||||
]
|
||||
const isLoaded = ref(false);
|
||||
const rows: any[] = reactive([]);
|
||||
const rows = reactive<IAppDisplay[]>([]);
|
||||
const selected = ref([])
|
||||
|
||||
watchEffect(()=>{
|
||||
@@ -49,12 +59,16 @@ export default {
|
||||
onMounted(() => {
|
||||
api.get('api/v1/allapps').then(res => {
|
||||
res.data.apps.forEach((item: any) => {
|
||||
rows.push({
|
||||
const row : IAppDisplay = {
|
||||
id: item.appId,
|
||||
name: item.name,
|
||||
description: item.description,
|
||||
createdate: dateFormat(item.createdAt)
|
||||
});
|
||||
}
|
||||
if (props.filterInitRowsFunc && !props.filterInitRowsFunc(row)) {
|
||||
return;
|
||||
}
|
||||
rows.push(row);
|
||||
});
|
||||
isLoaded.value = true;
|
||||
});
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<slot></slot>
|
||||
</q-card-section>
|
||||
<q-card-actions v-if="!disableBtn" align="right" class="text-primary">
|
||||
<q-btn flat label="確定" v-close-popup @click="CloseDialogue('OK')" />
|
||||
<q-btn flat label="確定" :loading="okBtnLoading" :v-close-popup="okBtnAutoClose" @click="CloseDialogue('OK')" />
|
||||
<q-btn flat label="キャンセル" v-close-popup @click="CloseDialogue('Cancel')" />
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
@@ -30,6 +30,11 @@ export default {
|
||||
height:String,
|
||||
minWidth:String,
|
||||
minHeight:String,
|
||||
okBtnLoading:Boolean,
|
||||
okBtnAutoClose:{
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
disableBtn:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<q-table title="Treats" :rows="rows" :columns="columns" row-key="id" :filter="filter" :loading="loading" :pagination="pagination">
|
||||
|
||||
<template v-slot:top>
|
||||
<q-btn disabled color="primary" :disable="loading" label="新規" @click="addRow" />
|
||||
<q-btn color="primary" :disable="loading" label="新規" @click="showAddAppDialog" />
|
||||
<q-space />
|
||||
<q-input borderless dense filled debounce="300" v-model="filter" placeholder="検索">
|
||||
<template v-slot:append>
|
||||
@@ -26,15 +26,24 @@
|
||||
<template v-slot:body-cell-actions="p">
|
||||
<q-td :props="p">
|
||||
<q-btn-group flat>
|
||||
<q-btn flat color="primary" padding="xs" size="1em" icon="edit_note" @click="editFlow(p.row)" />
|
||||
<q-btn flat color="primary" padding="xs" size="1em" icon="edit_note" @click="toEditFlowPage(p.row)" />
|
||||
<q-btn disabled flat color="primary" padding="xs" size="1em" icon="history" @click="showHistory(p.row)" />
|
||||
<q-btn disabled flat color="negative" padding="xs" size="1em" icon="delete_outline" @click="removeRow(p.row)" />
|
||||
</q-btn-group>
|
||||
</q-td>
|
||||
</template>
|
||||
|
||||
</q-table>
|
||||
|
||||
<show-dialog v-model:visible="showSelectApp" name="アプリ選択" @close="closeSelectAppDialog" min-width="50vw" min-height="50vh" :ok-btn-auto-close="false" :ok-btn-loading="isAdding">
|
||||
<template v-slot:toolbar>
|
||||
<q-input dense debounce="300" v-model="filter" placeholder="検索" clearable>
|
||||
<template v-slot:before>
|
||||
<q-icon name="search" />
|
||||
</template>
|
||||
</q-input>
|
||||
</template>
|
||||
<app-select-box ref="appDialog" name="アプリ" type="single" :filter="filter" :filterInitRowsFunc="filterInitRows" />
|
||||
</show-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -46,9 +55,12 @@ import { useFlowEditorStore } from 'stores/flowEditor';
|
||||
import { router } from 'src/router';
|
||||
import { date } from 'quasar'
|
||||
import { IManagedApp } from 'src/types/AppTypes';
|
||||
import ShowDialog from 'src/components/ShowDialog.vue';
|
||||
import AppSelectBox from 'src/components/AppSelectBox.vue';
|
||||
|
||||
interface IAppDisplay{
|
||||
id:string;
|
||||
sortId: number;
|
||||
name:string;
|
||||
url:string;
|
||||
user:string;
|
||||
@@ -65,7 +77,7 @@ const columns = [
|
||||
{ name: 'url', label: 'URL', field: 'url', align: 'left', sortable: true },
|
||||
{ name: 'user', label: '最後更新者', field: 'user', align: 'left', sortable: true},
|
||||
{ name: 'updatetime', label: '最後更新日', field: 'updatetime', align: 'left', sortable: true},
|
||||
{ name: 'version', label: 'バージョン', field: 'version', align: 'left', sortable: true},
|
||||
{ name: 'version', label: 'バージョン', field: 'version', align: 'left', sortable: true, sort: numberStringSorting },
|
||||
{ name: 'actions', label: '操作', field: 'actions' }
|
||||
];
|
||||
|
||||
@@ -73,21 +85,21 @@ const pagination = ref({ sortBy: 'id', descending: true, rowsPerPage: 20 });
|
||||
const loading = ref(false);
|
||||
const filter = ref('');
|
||||
const rows = ref<IAppDisplay[]>([]);
|
||||
const rowIds = new Set<string>();
|
||||
|
||||
const store = useFlowEditorStore();
|
||||
const appDialog = ref();
|
||||
const showSelectApp=ref(false);
|
||||
const isAdding = ref(false);
|
||||
|
||||
const getApps = async () => {
|
||||
loading.value = true;
|
||||
rowIds.clear();
|
||||
const result = await api.get('api/apps');
|
||||
rows.value = result.data.map((item: IManagedApp) => {
|
||||
return {
|
||||
id: item.appid,
|
||||
name: item.appname,
|
||||
url: `${item.domainurl}/k/${item.appid}`,
|
||||
user: `${item.user.first_name} ${item.user.last_name}` ,
|
||||
updatetime:date.formatDate(item.update_time, 'YYYY/MM/DD HH:mm'),
|
||||
version: Number(item.version)
|
||||
}
|
||||
}).sort((a: IAppDisplay, b: IAppDisplay) => numberStringSorting(a.id, b.id)); // set default order
|
||||
rowIds.add(item.appid);
|
||||
return appToAppDisplay(item)
|
||||
}).sort((a: IAppDisplay, b: IAppDisplay) => a.sortId - b.sortId); // set default order
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
@@ -100,8 +112,22 @@ watch(() => authStore.currentDomain.id, async () => {
|
||||
await getApps();
|
||||
});
|
||||
|
||||
const addRow = () => {
|
||||
return
|
||||
const filterInitRows = (row: {id: string}) => {
|
||||
return !rowIds.has(row.id);
|
||||
}
|
||||
|
||||
const showAddAppDialog = () => {
|
||||
showSelectApp.value = true;
|
||||
}
|
||||
|
||||
const closeSelectAppDialog = async (val: 'OK'|'Cancel') => {
|
||||
showSelectApp.value = true;
|
||||
if (val == 'OK' && appDialog.value.selected[0]) {
|
||||
isAdding.value = true;
|
||||
toEditFlowPage(appDialog.value.selected[0]);
|
||||
}
|
||||
showSelectApp.value = false;
|
||||
isAdding.value = false;
|
||||
}
|
||||
|
||||
const removeRow = (app:IAppDisplay) => {
|
||||
@@ -112,7 +138,19 @@ const showHistory = (app:IAppDisplay) => {
|
||||
return
|
||||
}
|
||||
|
||||
const editFlow = (app:IAppDisplay) => {
|
||||
const appToAppDisplay = (app: IManagedApp) => {
|
||||
return {
|
||||
id: app.appid,
|
||||
sortId: parseInt(app.appid, 10),
|
||||
name: app.appname,
|
||||
url: `${app.domainurl}/k/${app.appid}`,
|
||||
user: `${app.updateuser.first_name} ${app.updateuser.last_name}` ,
|
||||
updatetime:date.formatDate(app.update_time, 'YYYY/MM/DD HH:mm'),
|
||||
version: app.version
|
||||
}
|
||||
}
|
||||
|
||||
const toEditFlowPage = (app:IAppDisplay) => {
|
||||
store.setApp({
|
||||
appId: app.id,
|
||||
name: app.name
|
||||
|
||||
@@ -328,8 +328,22 @@ const fetchData = async () => {
|
||||
}
|
||||
|
||||
const fetchAppById = async(id: string) => {
|
||||
const result = await api.get('api/apps');
|
||||
return result.data.find((item: IManagedApp) => item.appid === id ) as IManagedApp;
|
||||
try {
|
||||
const result = await api.get('api/apps');
|
||||
return result.data.find((item: IManagedApp) => item.appid === id ) as IManagedApp;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
const result = await api.get(`api/v1/app?app=${id}`);
|
||||
const data = result?.data;
|
||||
if (data?.message) {
|
||||
$q.notify({
|
||||
type: 'negative',
|
||||
caption: "エラー",
|
||||
message: data.message
|
||||
});
|
||||
}
|
||||
return { appid: data.appId, appname: data.name };
|
||||
}
|
||||
}
|
||||
|
||||
const onClearFilter=()=>{
|
||||
|
||||
@@ -128,6 +128,7 @@ export const useFlowEditorStore = defineStore('flowEditor', {
|
||||
const jsonData = {
|
||||
flowid: isNew ? flow.createNewId() : flow.id,
|
||||
appid: this.appInfo?.appId,
|
||||
appname: this.appInfo?.name,
|
||||
eventid: root?.name,
|
||||
name: root?.subTitle,
|
||||
content: JSON.stringify(flow),
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
interface IUser {
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
export interface IManagedApp {
|
||||
appid: string;
|
||||
appname: string;
|
||||
domainurl: string;
|
||||
version: string;
|
||||
user: IUser;
|
||||
update_time: string;
|
||||
}
|
||||
interface IUser {
|
||||
first_name: string;
|
||||
last_name: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
export interface IManagedApp {
|
||||
appid: string;
|
||||
appname: string;
|
||||
domainurl: string;
|
||||
version: string;
|
||||
updateuser: IUser;
|
||||
update_time: string;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user