Compare commits

...

3 Commits

Author SHA1 Message Date
xue jiahao
43ad0f5dd8 show domain page for all user
1. show ドメイン管理
2. hide ドメイン適用
2024-11-11 17:50:13 +08:00
方 柏
f5b5607297 Merged PR 2: APP バージョン 履歴管理
- python3.12.4
- add app table
- flow domainid->domainurl add app flowhistory
2024-11-11 07:03:49 +00:00
dd814993f1 flow domainid->domainurl add app flowhistory 2024-11-09 15:56:13 +09:00
9 changed files with 110 additions and 83 deletions

View File

@@ -1,4 +1,5 @@
from fastapi import Query, Request,Depends, APIRouter, UploadFile,HTTPException,File from fastapi import Query, Request,Depends, APIRouter, UploadFile,HTTPException,File
from app.core.operation import log_operation
from app.db import Base,engine from app.db import Base,engine
from app.db.session import get_db from app.db.session import get_db
from app.db.crud import * from app.db.crud import *
@@ -7,6 +8,9 @@ from typing import List, Optional
from app.core.auth import get_current_active_user,get_current_user from app.core.auth import get_current_active_user,get_current_user
from app.core.apiexception import APIException from app.core.apiexception import APIException
import httpx
import app.core.config as config
platform_router = r = APIRouter() platform_router = r = APIRouter()
@@ -17,11 +21,40 @@ platform_router = r = APIRouter()
) )
async def apps_list( async def apps_list(
request: Request, request: Request,
user = Depends(get_current_user),
db=Depends(get_db), db=Depends(get_db),
): ):
try: try:
app = get_apps(db) platformapps = get_apps(db)
return app domain = get_activedomain(db, user.id)
kintoneevn = config.KINTONE_ENV(domain)
headers={config.API_V1_AUTH_KEY:kintoneevn.API_V1_AUTH_VALUE}
url = f"{kintoneevn.BASE_URL}{config.API_V1_STR}/apps.json"
offset = 0
limit = 100
all_apps = []
while True:
r = httpx.get(f"{url}?limit={limit}&offset={offset}", headers=headers)
json_data = r.json()
apps = json_data.get("apps",[])
all_apps.extend(apps)
if len(apps)<limit:
break
offset += limit
tempapps = platformapps.copy()
for papp in tempapps:
exist = False
for kapp in all_apps:
if kapp['appId'] == papp.appid:
exist = True
break
if not exist:
platformapps.remove(papp)
return platformapps
except Exception as e: except Exception as e:
raise APIException('platform:apps',request.url._url,f"Error occurred while get apps:",e) raise APIException('platform:apps',request.url._url,f"Error occurred while get apps:",e)
@@ -158,7 +191,7 @@ async def flow_list(
try: try:
domain = get_activedomain(db, user.id) domain = get_activedomain(db, user.id)
print("domain=>",domain) print("domain=>",domain)
flows = get_flows_by_app(db, domain.id, appid) flows = get_flows_by_app(db, domain.url, appid)
return flows return flows
except Exception as e: except Exception as e:
raise APIException('platform:flow',request.url._url,f"Error occurred while get flow by appid:",e) raise APIException('platform:flow',request.url._url,f"Error occurred while get flow by appid:",e)
@@ -173,7 +206,7 @@ async def flow_create(
): ):
try: try:
domain = get_activedomain(db, user.id) domain = get_activedomain(db, user.id)
return create_flow(db, domain.id, flow) return create_flow(db, domain.url, flow)
except Exception as e: except Exception as e:
raise APIException('platform:flow',request.url._url,f"Error occurred while create flow:",e) raise APIException('platform:flow',request.url._url,f"Error occurred while create flow:",e)

View File

@@ -5,7 +5,7 @@ import base64
PROJECT_NAME = "KintoneAppBuilder" PROJECT_NAME = "KintoneAppBuilder"
#SQLALCHEMY_DATABASE_URI = "postgres://kabAdmin:P@ssw0rd!@kintonetooldb.postgres.database.azure.com/dev" #SQLALCHEMY_DATABASE_URI = "postgres://kabAdmin:P@ssw0rd!@kintonetooldb.postgres.database.azure.com/dev"
SQLALCHEMY_DATABASE_URI = f"postgresql+psycopg2://kabAdmin:P%40ssw0rd!@kintonetooldb.postgres.database.azure.com/postgres" SQLALCHEMY_DATABASE_URI = f"postgresql+psycopg2://kabAdmin:P%40ssw0rd!@kintonetooldb.postgres.database.azure.com/dev_v2"
#SQLALCHEMY_DATABASE_URI = "postgres://kabAdmin:P@ssw0rd!@kintonetooldb.postgres.database.azure.com/test" #SQLALCHEMY_DATABASE_URI = "postgres://kabAdmin:P@ssw0rd!@kintonetooldb.postgres.database.azure.com/test"
#SQLALCHEMY_DATABASE_URI = "postgres://kabAdmin:P@ssw0rd!@ktune-prod-db.postgres.database.azure.com/postgres" #SQLALCHEMY_DATABASE_URI = "postgres://kabAdmin:P@ssw0rd!@ktune-prod-db.postgres.database.azure.com/postgres"
API_V1_STR = "/k/v1" API_V1_STR = "/k/v1"

View File

@@ -79,7 +79,9 @@ def update_appversion(db: Session, appedit: schemas.AppVersion,userid:int):
if app: if app:
app.version = app.version + 1 app.version = app.version + 1
db_app = app db_app = app
appver = app.version
else: else:
appver = 1
db_app = models.App( db_app = models.App(
domainurl = appedit.domainurl, domainurl = appedit.domainurl,
appid=appedit.appid, appid=appedit.appid,
@@ -89,6 +91,21 @@ def update_appversion(db: Session, appedit: schemas.AppVersion,userid:int):
) )
db.add(db_app) db.add(db_app)
flows = db.query(models.Flow).filter(and_(models.Flow.domainurl == appedit.domainurl,models.App.appid == appedit.appid))
for flow in flows:
db_flowhistory = models.FlowHistory(
flowid = flow.flowid,
appid = flow.appid,
eventid = flow.eventid,
domainurl = flow.domainurl,
name = flow.name,
content = flow.content,
createuser = userid,
version = appver
)
db.add(db_flowhistory)
db.commit() db.commit()
db.refresh(db_app) db.refresh(db_app)
return db_app return db_app
@@ -148,12 +165,12 @@ def get_actions(db: Session):
return actions return actions
def create_flow(db: Session, domainid: int, flow: schemas.FlowBase): def create_flow(db: Session, domainurl: str, flow: schemas.FlowBase):
db_flow = models.Flow( db_flow = models.Flow(
flowid=flow.flowid, flowid=flow.flowid,
appid=flow.appid, appid=flow.appid,
eventid=flow.eventid, eventid=flow.eventid,
domainid=domainid, domainurl=domainurl,
name=flow.name, name=flow.name,
content=flow.content content=flow.content
) )
@@ -200,8 +217,8 @@ def get_flow(db: Session, flowid: str):
raise HTTPException(status_code=404, detail="Data not found") raise HTTPException(status_code=404, detail="Data not found")
return flow return flow
def get_flows_by_app(db: Session, domainid: int, appid: str): def get_flows_by_app(db: Session,domainurl: str, appid: str):
flows = db.query(models.Flow).filter(and_(models.Flow.domainid == domainid,models.Flow.appid == appid)).all() flows = db.query(models.Flow).filter(and_(models.Flow.domainurl == domainurl,models.Flow.appid == appid)).all()
if not flows: if not flows:
raise Exception("Data not found") raise Exception("Data not found")
return flows return flows

View File

@@ -62,10 +62,22 @@ class Flow(Base):
flowid = Column(String(100), index=True, nullable=False) flowid = Column(String(100), index=True, nullable=False)
appid = Column(String(100), index=True, nullable=False) appid = Column(String(100), index=True, nullable=False)
eventid = Column(String(100), index=True, nullable=False) eventid = Column(String(100), index=True, nullable=False)
domainid = Column(Integer,ForeignKey("domain.id")) domainurl = Column(String(200))
name = Column(String(200)) name = Column(String(200))
content = Column(String) content = Column(String)
class FlowHistory(Base):
__tablename__ = "flowhistory"
flowid = Column(String(100), index=True, nullable=False)
appid = Column(String(100), index=True, nullable=False)
eventid = Column(String(100), index=True, nullable=False)
domainurl = Column(String(200))
name = Column(String(200))
content = Column(String)
createuser = Column(Integer,ForeignKey("user.id"))
version = Column(Integer)
class Tenant(Base): class Tenant(Base):
__tablename__ = "tenant" __tablename__ = "tenant"
@@ -119,6 +131,17 @@ class ErrorLog(Base):
location = Column(String(500)) location = Column(String(500))
content = Column(String(5000)) content = Column(String(5000))
class OperationLog(Base):
__tablename__ = "operationlog"
tenantid = Column(String(100))
domainurl = Column(String(200))
userid = Column(Integer,ForeignKey("user.id"))
operation = Column(String(200))
function = Column(String(200))
detail = Column(String(200))
user = relationship('User')
class KintoneFormat(Base): class KintoneFormat(Base):
__tablename__ = "kintoneformat" __tablename__ = "kintoneformat"

View File

@@ -118,7 +118,7 @@ class Flow(Base):
flowid: str flowid: str
appid: str appid: str
eventid: str eventid: str
domainid: int domainurl: str
name: str = None name: str = None
content: str = None content: str = None

View File

@@ -22,6 +22,8 @@
<div v-if="isAdmin()"> <div v-if="isAdmin()">
<EssentialLink v-for="link in adminLinks" :key="link.title" v-bind="link" /> <EssentialLink v-for="link in adminLinks" :key="link.title" v-bind="link" />
</div> </div>
<EssentialLink v-for="link in domainLinks" :key="link.title" v-bind="link" />
</q-list> </q-list>
</q-drawer> </q-drawer>
@@ -83,58 +85,23 @@ const essentialLinks: EssentialLinkProps[] = [
// link:'https://cybozu.dev/ja/kintone/docs/', // link:'https://cybozu.dev/ja/kintone/docs/',
// icon:'help_outline' // icon:'help_outline'
// }, // },
];
const domainLinks: EssentialLinkProps[] = [
{
title: 'ドメイン管理',
caption: 'kintoneのドメイン設定',
icon: 'domain',
link: '/#/domain',
target: '_self'
},
// { // {
// title:'', // title: 'ドメイン適用',
// isSeparator:true // caption: 'ユーザー使用可能なドメインの設定',
// icon: 'assignment_ind',
// link: '/#/userDomain',
// target: '_self'
// }, // },
// {
// title: 'Docs',
// caption: 'quasar.dev',
// icon: 'school',
// link: 'https://quasar.dev'
// },
// {
// title: 'Icons',
// caption: 'Material Icons',
// icon: 'insert_emoticon',
// link: 'https://fonts.google.com/icons?selected=Material+Icons:insert_emoticon:'
// },
// {
// title: 'Github',
// caption: 'github.com/quasarframework',
// icon: 'code',
// link: 'https://github.com/quasarframework'
// },
// {
// title: 'Discord Chat Channel',
// caption: 'chat.quasar.dev',
// icon: 'chat',
// link: 'https://chat.quasar.dev'
// },
// {
// title: 'Forum',
// caption: 'forum.quasar.dev',
// icon: 'record_voice_over',
// link: 'https://forum.quasar.dev'
// },
// {
// title: 'Twitter',
// caption: '@quasarframework',
// icon: 'rss_feed',
// link: 'https://twitter.quasar.dev'
// },
// {
// title: 'Facebook',
// caption: '@QuasarFramework',
// icon: 'public',
// link: 'https://facebook.quasar.dev'
// },
// {
// title: 'Quasar Awesome',
// caption: 'Community Quasar projects',
// icon: 'favorite',
// link: 'https://awesome.quasar.dev'
// }
]; ];
const adminLinks: EssentialLinkProps[] = [ const adminLinks: EssentialLinkProps[] = [
@@ -145,20 +112,6 @@ const adminLinks: EssentialLinkProps[] = [
link: '/#/user', link: '/#/user',
target: '_self' target: '_self'
}, },
{
title: 'ドメイン管理',
caption: 'kintoneのドメイン設定',
icon: 'domain',
link: '/#/domain',
target: '_self'
},
{
title: 'ドメイン適用',
caption: 'ユーザー使用可能なドメインの設定',
icon: 'assignment_ind',
link: '/#/userDomain',
target: '_self'
},
] ]
const version = process.env.version; const version = process.env.version;

View File

@@ -155,7 +155,8 @@ let editId = ref(0);
const getDomain = async () => { const getDomain = async () => {
loading.value = true; loading.value = true;
const result = await api.get(`api/domains/1`); const userId = authStore.userId;
const result = await api.get(`api/domain?userId=${userId}`);
rows.value = result.data.map((item) => { rows.value = result.data.map((item) => {
return { id: item.id, tenantid: item.tenantid, name: item.name, url: item.url, user: item.kintoneuser, password: item.kintonepwd } return { id: item.id, tenantid: item.tenantid, name: item.name, url: item.url, user: item.kintoneuser, password: item.kintonepwd }
}); });

View File

@@ -25,7 +25,7 @@ const routes: RouteRecordRaw[] = [
// { path: 'FlowChart', component: () => import('pages/FlowChart.vue') }, // { path: 'FlowChart', component: () => import('pages/FlowChart.vue') },
{ path: 'right', component: () => import('pages/testRight.vue') }, { path: 'right', component: () => import('pages/testRight.vue') },
{ path: 'domain', component: () => import('pages/TenantDomain.vue') }, { path: 'domain', component: () => import('pages/TenantDomain.vue') },
{ path: 'userdomain', component: () => import('pages/UserDomain.vue')}, // { path: 'userdomain', component: () => import('pages/UserDomain.vue')},
{ path: 'user', component: () => import('pages/UserManagement.vue')}, { path: 'user', component: () => import('pages/UserManagement.vue')},
{ path: 'condition', component: () => import('pages/conditionPage.vue') } { path: 'condition', component: () => import('pages/conditionPage.vue') }
], ],

View File

@@ -60,11 +60,11 @@ export const useAuthStore = defineStore('auth', {
} }
}, },
async getCurrentDomain(): Promise<IDomainInfo> { async getCurrentDomain(): Promise<IDomainInfo> {
const activedomain = await api.get(`api/activedomain`); const activedomain = (await api.get(`api/activedomain`))?.data;
return { return {
id: activedomain.data.id, id: activedomain?.id,
domainName: activedomain.data.name, domainName: activedomain?.name,
kintoneUrl: activedomain.data.url, kintoneUrl: activedomain?.url,
}; };
}, },
async getUserDomains(): Promise<IDomainInfo[]> { async getUserDomains(): Promise<IDomainInfo[]> {