Compare commits

..

1 Commits

Author SHA1 Message Date
xue jiahao
e362c80e98 show domain page for all user
1. show ドメイン管理
2. hide ドメイン適用
3. force redirect to domain page if user no domain exist
2024-11-06 21:56:14 +08:00
11 changed files with 48 additions and 159 deletions

4
.gitignore vendored
View File

@@ -1,7 +1,3 @@
.vscode .vscode
.mypy_cache .mypy_cache
docker-stack.yml docker-stack.yml
backend/pyvenv.cfg
backend/Include/
backend/Scripts/

View File

@@ -9,35 +9,6 @@ from app.core.apiexception import APIException
platform_router = r = APIRouter() platform_router = r = APIRouter()
@r.get(
"/apps",
response_model=List[AppList],
response_model_exclude_none=True,
)
async def apps_list(
request: Request,
db=Depends(get_db),
):
try:
app = get_apps(db)
return app
except Exception as e:
raise APIException('platform:apps',request.url._url,f"Error occurred while get apps:",e)
@r.post("/apps", response_model=AppList, response_model_exclude_none=True)
async def apps_update(
request: Request,
app: AppVersion,
user=Depends(get_current_user),
db=Depends(get_db),
):
try:
return update_appversion(db, app,user.id)
except Exception as e:
raise APIException('platform:apps',request.url._url,f"Error occurred while get create app :",e)
@r.get( @r.get(
"/appsettings/{id}", "/appsettings/{id}",
response_model=App, response_model=App,

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 = "postgres://kabAdmin:P@ssw0rd!@kintonetooldb.postgres.database.azure.com/postgres"
#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

@@ -69,29 +69,6 @@ def edit_user(
db.refresh(db_user) db.refresh(db_user)
return db_user return db_user
def get_apps(
db: Session
) -> t.List[schemas.AppList]:
return db.query(models.App).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
else:
db_app = models.App(
domainurl = appedit.domainurl,
appid=appedit.appid,
appname=appedit.appname,
version = 1,
updateuser= userid
)
db.add(db_app)
db.commit()
db.refresh(db_app)
return db_app
def get_appsetting(db: Session, id: int): def get_appsetting(db: Session, id: int):
app = db.query(models.AppSetting).get(id) app = db.query(models.AppSetting).get(id)

View File

@@ -1,6 +1,5 @@
from sqlalchemy import Boolean, Column, Integer, String, DateTime,ForeignKey from sqlalchemy import Boolean, Column, Integer, String, DateTime,ForeignKey
from sqlalchemy.ext.declarative import as_declarative from sqlalchemy.ext.declarative import as_declarative
from sqlalchemy.orm import relationship
from datetime import datetime from datetime import datetime
from app.core.security import chacha20Decrypt from app.core.security import chacha20Decrypt
@@ -21,16 +20,6 @@ class User(Base):
is_active = Column(Boolean, default=True) is_active = Column(Boolean, default=True)
is_superuser = Column(Boolean, default=False) is_superuser = Column(Boolean, default=False)
class App(Base):
__tablename__ = "app"
domainurl = Column(String(200), nullable=False)
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')
class AppSetting(Base): class AppSetting(Base):
__tablename__ = "appsetting" __tablename__ = "appsetting"

View File

@@ -28,21 +28,21 @@ class UserCreate(UserBase):
is_active:bool is_active:bool
is_superuser:bool is_superuser:bool
class ConfigDict: class Config:
orm_mode = True orm_mode = True
class UserEdit(UserBase): class UserEdit(UserBase):
password: t.Optional[str] = None password: t.Optional[str] = None
class ConfigDict: class Config:
orm_mode = True orm_mode = True
class User(UserBase): class User(UserBase):
id: int id: int
class ConfigDict: class Config:
orm_mode = True orm_mode = True
@@ -50,17 +50,6 @@ class Token(BaseModel):
access_token: str access_token: str
token_type: str token_type: str
class AppList(Base):
domainurl: str
appname: str
appid:str
version:int
user:UserOut
class AppVersion(BaseModel):
domainurl: str
appname: str
appid:str
class TokenData(BaseModel): class TokenData(BaseModel):
id:int = 0 id:int = 0
@@ -79,7 +68,7 @@ class AppBase(BaseModel):
class App(AppBase): class App(AppBase):
id: int id: int
class ConfigDict: class Config:
orm_mode = True orm_mode = True
@@ -90,7 +79,7 @@ class Kintone(BaseModel):
desc: str = None desc: str = None
content: str = None content: str = None
class ConfigDict: class Config:
orm_mode = True orm_mode = True
class Action(BaseModel): class Action(BaseModel):
@@ -103,7 +92,7 @@ class Action(BaseModel):
categoryid: int = None categoryid: int = None
nosort: int nosort: int
categoryname : str =None categoryname : str =None
class ConfigDict: class Config:
orm_mode = True orm_mode = True
class FlowBase(BaseModel): class FlowBase(BaseModel):
@@ -122,7 +111,7 @@ class Flow(Base):
name: str = None name: str = None
content: str = None content: str = None
class ConfigDict: class Config:
orm_mode = True orm_mode = True
class DomainBase(BaseModel): class DomainBase(BaseModel):
@@ -144,7 +133,7 @@ class Domain(Base):
url: str url: str
kintoneuser: str kintoneuser: str
kintonepwd: str kintonepwd: str
class ConfigDict: class Config:
orm_mode = True orm_mode = True
class Event(Base): class Event(Base):
@@ -156,7 +145,7 @@ class Event(Base):
mobile: bool mobile: bool
eventgroup: bool eventgroup: bool
class ConfigDict: class Config:
orm_mode = True orm_mode = True
class ErrorCreate(BaseModel): class ErrorCreate(BaseModel):

Binary file not shown.

View File

@@ -4,6 +4,7 @@
tag="a" tag="a"
:target="target?target:'_blank'" :target="target?target:'_blank'"
:href="link" :href="link"
:disable="disable"
v-if="!isSeparator" v-if="!isSeparator"
> >
<q-item-section <q-item-section
@@ -33,6 +34,7 @@ export interface EssentialLinkProps {
icon?: string; icon?: string;
isSeparator?: boolean; isSeparator?: boolean;
target?:string; target?:string;
disable?:boolean;
} }
withDefaults(defineProps<EssentialLinkProps>(), { withDefaults(defineProps<EssentialLinkProps>(), {
caption: '', caption: '',

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>
@@ -32,7 +34,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted } from 'vue'; import { onMounted, computed } from 'vue';
import EssentialLink, { EssentialLinkProps } from 'components/EssentialLink.vue'; import EssentialLink, { EssentialLinkProps } from 'components/EssentialLink.vue';
import DomainSelector from 'components/DomainSelector.vue'; import DomainSelector from 'components/DomainSelector.vue';
import { useAuthStore } from 'stores/useAuthStore'; import { useAuthStore } from 'stores/useAuthStore';
@@ -45,14 +47,16 @@ const essentialLinks: EssentialLinkProps[] = [
caption: '設計書から導入する', caption: '設計書から導入する',
icon: 'home', icon: 'home',
link: '/', link: '/',
target: '_self' target: '_self',
disable: !authStore.hasDomain,
}, },
{ {
title: 'フローエディター', title: 'フローエディター',
caption: 'イベントを設定する', caption: 'イベントを設定する',
icon: 'account_tree', icon: 'account_tree',
link: '/#/FlowChart', link: '/#/FlowChart',
target: '_self' target: '_self',
disable: !authStore.hasDomain,
}, },
// { // {
// title: '条件エディター', // title: '条件エディター',
@@ -83,58 +87,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 +114,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

@@ -47,6 +47,13 @@ export default route(function (/* { store, ssrContext } */) {
authStore.returnUrl = to.fullPath; authStore.returnUrl = to.fullPath;
return '/login'; return '/login';
} }
// redirect to domain setting page if no domain exist
const domainPages = [...publicPages, '/domain'];
if (!authStore.hasDomain && !domainPages.includes(to.path)) {
authStore.returnUrl = to.fullPath;
return '/domain';
}
}); });
return routerInstance; return routerInstance;
}); });

View File

@@ -33,6 +33,9 @@ export const useAuthStore = defineStore('auth', {
toggleLeftDrawer(): boolean { toggleLeftDrawer(): boolean {
return this.LeftDrawer; return this.LeftDrawer;
}, },
hasDomain(): boolean {
return this.currentDomain.id === null;
}
}, },
actions: { actions: {
toggleLeftMenu() { toggleLeftMenu() {
@@ -60,11 +63,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[]> {