From 76457b66675d3338f2796f3ef97e47cf348b7f6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=B9=20=E6=9F=8F?= Date: Mon, 9 Oct 2023 15:55:58 +0900 Subject: [PATCH] UserDomain Add --- backend/app/api/api_v1/routers/platform.py | 48 ++- backend/app/db/crud.py | 45 +++ backend/app/db/models.py | 14 +- backend/app/db/schemas.py | 21 ++ frontend/src/control/auth.ts | 21 ++ frontend/src/layouts/MainLayout.vue | 5 + frontend/src/pages/LoginPage.vue | 100 ++++++ frontend/src/pages/UserDomain.vue | 354 +++++++++++++++++++++ frontend/src/router/index.ts | 63 +++- frontend/src/router/routes.ts | 6 + frontend/src/stores/useAuthStore.ts | 36 +++ 11 files changed, 697 insertions(+), 16 deletions(-) create mode 100644 frontend/src/control/auth.ts create mode 100644 frontend/src/pages/LoginPage.vue create mode 100644 frontend/src/pages/UserDomain.vue create mode 100644 frontend/src/stores/useAuthStore.ts diff --git a/backend/app/api/api_v1/routers/platform.py b/backend/app/api/api_v1/routers/platform.py index d309d72..07ae5f7 100644 --- a/backend/app/api/api_v1/routers/platform.py +++ b/backend/app/api/api_v1/routers/platform.py @@ -137,4 +137,50 @@ async def flow_delete( db=Depends(get_db), ): - return delete_flow(db, flowid) \ No newline at end of file + return delete_flow(db, flowid) + +@r.get( + "/domain/{userid}", + response_model=List[Domain], + response_model_exclude_none=True, +) +async def domain_details( + request: Request, + userid: str, + db=Depends(get_db), +): + domains = get_domain(db, userid) + return domains + + +@r.post("/domain", response_model=Domain, response_model_exclude_none=True) +async def domain_create( + request: Request, + domain: DomainBase, + db=Depends(get_db), +): + return create_domain(db, domain) + + +@r.put( + "/domain", response_model=Domain, response_model_exclude_none=True +) +async def domain_edit( + request: Request, + domain: DomainBase, + db=Depends(get_db), +): + return edit_domain(db, domain) + + +@r.delete( + "/domain/{userid}/{id}", response_model=Domain, response_model_exclude_none=True +) +async def domain_delete( + request: Request, + userid: int, + id: int, + db=Depends(get_db), +): + + return delete_domain(db, userid,id) \ No newline at end of file diff --git a/backend/app/db/crud.py b/backend/app/db/crud.py index b2f39a2..4b5fcdc 100644 --- a/backend/app/db/crud.py +++ b/backend/app/db/crud.py @@ -180,3 +180,48 @@ def get_flows_by_app(db: Session, appid: str): if not flows: raise HTTPException(status_code=404, detail="Data not found") return flows + +def create_domain(db: Session, domain: schemas.DomainBase): + db_domain = models.UserDomain( + userid=domain.userid, + name=domain.name, + url=domain.url, + kintoneuser=domain.kintoneuser, + kintonepwd=domain.kintonepwd + ) + db.add(db_domain) + db.commit() + db.refresh(db_domain) + return db_domain + +def delete_domain(db: Session, userid: int,id: int): + db_domain = db.query(models.UserDomain).get(id) + if not db_domain or db_domain.userid != userid: + raise HTTPException(status.HTTP_404_NOT_FOUND, detail="Domain not found") + db.delete(db_domain) + db.commit() + return db_domain + + +def edit_domain( + db: Session, domain: schemas.DomainBase +) -> schemas.Domain: + db_domain = db.query(models.UserDomain).get(domain.id) + if not db_domain or db_domain.userid != domain.userid: + 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"): + setattr(db_domain, key, value) + + db.add(db_domain) + db.commit() + db.refresh(db_domain) + return db_domain + +def get_domain(db: Session, userid: str): + domains = db.query(models.UserDomain).filter(models.UserDomain.userid == userid).all() + if not domains: + raise HTTPException(status_code=404, detail="Data not found") + return domains \ No newline at end of file diff --git a/backend/app/db/models.py b/backend/app/db/models.py index a88f28c..b22033a 100644 --- a/backend/app/db/models.py +++ b/backend/app/db/models.py @@ -1,4 +1,4 @@ -from sqlalchemy import Boolean, Column, Integer, String, DateTime +from sqlalchemy import Boolean, Column, Integer, String, DateTime,ForeignKey from sqlalchemy.ext.declarative import as_declarative from datetime import datetime @@ -48,4 +48,14 @@ class Flow(Base): appid = Column(String(100), index=True, nullable=False) eventid = Column(String(100), index=True, nullable=False) name = Column(String(200)) - content = Column(String) \ No newline at end of file + content = Column(String) + +class UserDomain(Base): + __tablename__ = "userdomain" + + userid = Column(Integer,ForeignKey("user.id")) + name = Column(String(100), nullable=False) + url = Column(String(200), nullable=False) + kintoneuser = Column(String(100), nullable=False) + kintonepwd = Column(String(100), nullable=False) + active = Column(Boolean, default=False) \ No newline at end of file diff --git a/backend/app/db/schemas.py b/backend/app/db/schemas.py index 02c6483..ef75fe1 100644 --- a/backend/app/db/schemas.py +++ b/backend/app/db/schemas.py @@ -101,5 +101,26 @@ class Flow(Base): name: str = None content: str = None + class Config: + orm_mode = True + +class DomainBase(BaseModel): + id: int + userid: int + name: str + url: str + kintoneuser: str + kintonepwd: str + active:bool = False + +class Domain(Base): + id: int + userid: str + name: str + url: str + kintoneuser: str + kintonepwd: str + active:bool + class Config: orm_mode = True \ No newline at end of file diff --git a/frontend/src/control/auth.ts b/frontend/src/control/auth.ts new file mode 100644 index 0000000..e2ca5e6 --- /dev/null +++ b/frontend/src/control/auth.ts @@ -0,0 +1,21 @@ +import { api } from 'boot/axios'; + +export class Auth +{ + async login(user:string,pwd:string):Promise + { + const params = new URLSearchParams(); + params.append('username', user); + params.append('password', pwd); + try{ + const result = await api.post(`http://127.0.0.1:8000/api/token`,params); + console.info(result); + localStorage.setItem('Token', result.data.access_token); + return true; + }catch(e) + { + console.info(e); + return false; + } + } +} diff --git a/frontend/src/layouts/MainLayout.vue b/frontend/src/layouts/MainLayout.vue index 3c40937..2dffa94 100644 --- a/frontend/src/layouts/MainLayout.vue +++ b/frontend/src/layouts/MainLayout.vue @@ -14,7 +14,9 @@ Kintone App Builder V{{ env.version }} + + import { ref } from 'vue'; import EssentialLink, { EssentialLinkProps } from 'components/EssentialLink.vue'; +import { useAuthStore } from 'stores/useAuthStore'; + +const authStore = useAuthStore(); const essentialLinks: EssentialLinkProps[] = [ { diff --git a/frontend/src/pages/LoginPage.vue b/frontend/src/pages/LoginPage.vue new file mode 100644 index 0000000..e9c174f --- /dev/null +++ b/frontend/src/pages/LoginPage.vue @@ -0,0 +1,100 @@ + + diff --git a/frontend/src/pages/UserDomain.vue b/frontend/src/pages/UserDomain.vue new file mode 100644 index 0000000..fd651be --- /dev/null +++ b/frontend/src/pages/UserDomain.vue @@ -0,0 +1,354 @@ + + + + + + + + + diff --git a/frontend/src/router/index.ts b/frontend/src/router/index.ts index 4531114..53aaa0a 100644 --- a/frontend/src/router/index.ts +++ b/frontend/src/router/index.ts @@ -7,7 +7,7 @@ import { } from 'vue-router'; import routes from './routes'; - +import { useAuthStore } from 'stores/useAuthStore'; /* * If not building with SSR mode, you can * directly export the Router instantiation; @@ -17,20 +17,57 @@ import routes from './routes'; * with the Router instance. */ +// export default route(function (/* { store, ssrContext } */) { +// const createHistory = process.env.SERVER +// ? createMemoryHistory +// : (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory); + +// const Router = createRouter({ +// scrollBehavior: () => ({ left: 0, top: 0 }), +// routes, + +// // Leave this as is and make changes in quasar.conf.js instead! +// // quasar.conf.js -> build -> vueRouterMode +// // quasar.conf.js -> build -> publicPath +// history: createHistory(process.env.VUE_ROUTER_BASE), +// }); + +// return Router; +// }); + + + +const createHistory = process.env.SERVER + ? createMemoryHistory + : (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory); + +export const Router = createRouter({ + scrollBehavior: () => ({ left: 0, top: 0 }), + routes, + + // Leave this as is and make changes in quasar.conf.js instead! + // quasar.conf.js -> build -> vueRouterMode + // quasar.conf.js -> build -> publicPath + history: createHistory(process.env.VUE_ROUTER_BASE), + }); + export default route(function (/* { store, ssrContext } */) { - const createHistory = process.env.SERVER - ? createMemoryHistory - : (process.env.VUE_ROUTER_MODE === 'history' ? createWebHistory : createWebHashHistory); + return Router; + }); - const Router = createRouter({ - scrollBehavior: () => ({ left: 0, top: 0 }), - routes, +Router.beforeEach(async (to) => { + // clear alert on route change + //const alertStore = useAlertStore(); + //alertStore.clear(); - // Leave this as is and make changes in quasar.conf.js instead! - // quasar.conf.js -> build -> vueRouterMode - // quasar.conf.js -> build -> publicPath - history: createHistory(process.env.VUE_ROUTER_BASE), - }); + // redirect to login page if not logged in and trying to access a restricted page + const publicPages = ['/login']; + const authRequired = !publicPages.includes(to.path); + const authStore = useAuthStore(); - return Router; + if (authRequired && !authStore.token) { + authStore.returnUrl = to.fullPath; + return '/login'; + } }); + diff --git a/frontend/src/router/routes.ts b/frontend/src/router/routes.ts index a3eb0e2..9e53020 100644 --- a/frontend/src/router/routes.ts +++ b/frontend/src/router/routes.ts @@ -1,6 +1,11 @@ import { RouteRecordRaw } from 'vue-router'; const routes: RouteRecordRaw[] = [ + { + path: '/login', + component: () => import('pages/LoginPage.vue') + }, + { path: '/', component: () => import('layouts/MainLayout.vue'), @@ -14,6 +19,7 @@ const routes: RouteRecordRaw[] = [ { path: 'flowEditor2', component: () => import('pages/FlowChart.vue') }, { path: 'flowChart2', component: () => import('pages/FlowEditorPage2.vue') }, { path: 'right', component: () => import('pages/testRight.vue') }, + { path: 'domain', component: () => import('pages/UserDomain.vue') } ], }, // Always leave this as last one, diff --git a/frontend/src/stores/useAuthStore.ts b/frontend/src/stores/useAuthStore.ts new file mode 100644 index 0000000..bf59d17 --- /dev/null +++ b/frontend/src/stores/useAuthStore.ts @@ -0,0 +1,36 @@ +import { defineStore } from 'pinia'; +import { api } from 'boot/axios'; +import { Router } from '../router'; + + +export const useAuthStore = defineStore({ + id: 'auth', + state: () => ({ + token: localStorage.getItem('token'), + returnUrl: '' + }), + actions: { + async login(username:string, password:string) { + const params = new URLSearchParams(); + params.append('username', username); + params.append('password', password); + try{ + const result = await api.post(`http://127.0.0.1:8000/api/token`,params); + console.info(result); + this.token =result.data.access_token; + localStorage.setItem('token', result.data.access_token); + Router.push(this.returnUrl || '/'); + return true; + }catch(e) + { + console.info(e); + return false; + } + }, + logout() { + this.token = null; + localStorage.removeItem('token'); + Router.push('/login'); + } + } +});