@simitgroup/simpleapp-generator 1.0.24 → 1.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/framework.js +22 -12
- package/dist/framework.js.map +1 -1
- package/package.json +1 -1
- package/src/framework.ts +23 -14
- package/templates/basic/model.eta +2 -1
- package/templates/nest/TenantMiddleware.eta +28 -19
- package/templates/nest/User.eta +106 -71
- package/templates/nest/app.module.eta +36 -2
- package/templates/nest/nest.env.eta +15 -1
- package/templates/nest/nest.main.eta +13 -4
- package/templates/nest/oauth2-redirect.eta +79 -0
- package/templates/nuxt/components.crudsimple.vue.eta +1 -2
- package/templates/nuxt/composables.getautocomplete.ts.eta +12 -7
- package/templates/nuxt/composables.getmenus.ts.eta +21 -10
- package/templates/nuxt/env.eta +11 -1
- package/templates/nuxt/nuxt.config.ts.eta +9 -8
- package/templates/nuxt/pages.[xorg].index.vue.eta +19 -0
- package/templates/nuxt/pages.index.vue.eta +9 -1
- package/templates/nuxt/pages.login.vue.eta +20 -0
- package/templates/nuxt/plugins.simpleapp.ts.eta +2 -3
- package/templates/nuxt/server.api.auth.logout.ts.eta +12 -0
- package/templates/nuxt/server.api.auth[...].ts.eta +233 -0
- package/templates/nuxt/server.api.ts.eta +19 -14
package/dist/framework.js
CHANGED
|
@@ -41,6 +41,14 @@ let config = {
|
|
|
41
41
|
"frontendFolder": "./myfrontend",
|
|
42
42
|
"frontendPort": "8080",
|
|
43
43
|
"openapi3Yaml": "../openapi.yaml",
|
|
44
|
+
"keycloaksetting": {
|
|
45
|
+
"OAUTH2_BASEURL": "https://keycloak-server-url/",
|
|
46
|
+
"OAUTH2_REALM": "realm-name",
|
|
47
|
+
"OAUTH2_CONFIGURL": "https://keycloak-server-url/realms/realm-name",
|
|
48
|
+
"OAUTH2_CLIENTID": "client-id",
|
|
49
|
+
"OAUTH2_CLIENTSECRET": "client-secret-value",
|
|
50
|
+
"AUTH_SECRET_KEY": "my-secret",
|
|
51
|
+
}
|
|
44
52
|
};
|
|
45
53
|
const setConfiguration = (paraconfig) => {
|
|
46
54
|
config = paraconfig;
|
|
@@ -81,18 +89,18 @@ const prepareNest = (callback) => {
|
|
|
81
89
|
const targetfolder = config.backendFolder;
|
|
82
90
|
log.info(`creating backend project ${targetfolder}`);
|
|
83
91
|
if (!fs_1.default.existsSync(`${targetfolder}/.env`)) {
|
|
84
|
-
(0, child_process_1.exec)(`cd ${targetfolder};pnpm install --save axios @darkwolf/base64url json-schema @wearenova/mongoose-tenant @nestjs/swagger @nestjs/mongoose mongoose ajv ajv-formats @nestjs/config`, async (error, stdout, stderr) => {
|
|
92
|
+
(0, child_process_1.exec)(`cd ${targetfolder};pnpm install --save nest-keycloak-connect keycloak-connect @nestjs/serve-static jsonwebtoken axios @darkwolf/base64url json-schema @wearenova/mongoose-tenant @nestjs/swagger @nestjs/mongoose mongoose ajv ajv-formats @nestjs/config`, async (error, stdout, stderr) => {
|
|
85
93
|
// log.info(`dependency installed`)
|
|
86
94
|
if (!error) {
|
|
95
|
+
fs_1.default.mkdirSync(`${targetfolder}/public_html`, { recursive: true });
|
|
87
96
|
const eta = new eta_1.Eta({ views: constants.templatedir });
|
|
88
|
-
const variables =
|
|
89
|
-
backendPort: config.backendPort,
|
|
90
|
-
mongoConnectStr: config.mongoConnectStr
|
|
91
|
-
};
|
|
97
|
+
const variables = config;
|
|
92
98
|
const txtEnv = eta.render('./nest/nest.env.eta', variables);
|
|
93
99
|
const txtMain = eta.render('./nest/nest.main.eta', variables);
|
|
100
|
+
const txtRedirectHtml = eta.render('./nest/oauth2-redirect.eta', variables);
|
|
94
101
|
fs_1.default.writeFileSync(`${targetfolder}/.env`, txtEnv);
|
|
95
102
|
fs_1.default.writeFileSync(`${targetfolder}/src/main.ts`, txtMain);
|
|
103
|
+
fs_1.default.writeFileSync(`${targetfolder}/public_html/oauth2-redirect.html`, txtRedirectHtml);
|
|
96
104
|
const tsconfigpath = process.cwd() + '/' + `${targetfolder}/tsconfig.json`;
|
|
97
105
|
const tsconfig = require(tsconfigpath);
|
|
98
106
|
tsconfig.compilerOptions.esModuleInterop = true;
|
|
@@ -118,22 +126,20 @@ const prepareNuxt = (callback) => {
|
|
|
118
126
|
const targetfolder = config.frontendFolder;
|
|
119
127
|
if (!fs_1.default.existsSync(`${targetfolder}/.env`)) {
|
|
120
128
|
//asume no environment. prepare now
|
|
121
|
-
(0, child_process_1.exec)(`cd ${targetfolder};pnpm install;pnpm install -D @nuxt/ui @types/node @vueuse/nuxt @sidebase/nuxt-auth @vueuse/core nuxt-security prettier `, (error, stdout, stderr) => {
|
|
129
|
+
(0, child_process_1.exec)(`cd ${targetfolder};pnpm install;pnpm install -D @sidebase/nuxt-auth @nuxt/ui @types/node @vueuse/nuxt @sidebase/nuxt-auth @vueuse/core nuxt-security prettier `, (error, stdout, stderr) => {
|
|
122
130
|
//;pnpm install
|
|
123
131
|
console.log(error, stdout, stderr);
|
|
124
|
-
(0, child_process_1.exec)(`cd ${targetfolder};pnpm install --save
|
|
132
|
+
(0, child_process_1.exec)(`cd ${targetfolder};pnpm install --save next-auth@4.21.1 @darkwolf/base64url @nuxt/ui ajv dotenv @fullcalendar/core @fullcalendar/vue3 quill uuid ajv-formats primeflex primeicons prettier primevue axios json-schema mitt @simitgroup/simpleapp-vue-component@latest`, (error, stdout, stderr) => {
|
|
125
133
|
console.log(error, stdout, stderr);
|
|
126
134
|
fs_1.default.mkdirSync(`${targetfolder}/assets/css/`, { recursive: true });
|
|
127
135
|
fs_1.default.mkdirSync(`${targetfolder}/layouts`, { recursive: true });
|
|
128
136
|
fs_1.default.mkdirSync(`${targetfolder}/components`, { recursive: true });
|
|
129
137
|
fs_1.default.mkdirSync(`${targetfolder}/server/api/[xorg]`, { recursive: true });
|
|
130
|
-
fs_1.default.mkdirSync(`${targetfolder}/
|
|
138
|
+
fs_1.default.mkdirSync(`${targetfolder}/server/api/auth`, { recursive: true });
|
|
139
|
+
fs_1.default.mkdirSync(`${targetfolder}/pages/[xorg]`, { recursive: true });
|
|
131
140
|
fs_1.default.mkdirSync(`${targetfolder}/plugins`, { recursive: true });
|
|
132
141
|
const eta = new eta_1.Eta({ views: `${constants.templatedir}/nuxt` });
|
|
133
|
-
const variables =
|
|
134
|
-
backendPort: config.backendPort,
|
|
135
|
-
frontendPort: config.frontendPort
|
|
136
|
-
};
|
|
142
|
+
const variables = config;
|
|
137
143
|
const writes = {
|
|
138
144
|
'./app.vue.eta': 'app.vue',
|
|
139
145
|
'./components.eventmonitor.vue.eta': 'components/EventMonitor.vue',
|
|
@@ -142,8 +148,12 @@ const prepareNuxt = (callback) => {
|
|
|
142
148
|
'./components.debugdocdata.vue.eta': 'components/DebugDocumentData.vue',
|
|
143
149
|
'./layouts.default.vue.eta': 'layouts/default.vue',
|
|
144
150
|
'./server.api.ts.eta': 'server/api/[xorg]/[...].ts',
|
|
151
|
+
'./server.api.auth.logout.ts.eta': 'server/api/auth/logout.ts',
|
|
152
|
+
'./server.api.auth[...].ts.eta': 'server/api/auth/[...].ts',
|
|
145
153
|
'./nuxt.config.ts.eta': 'nuxt.config.ts',
|
|
146
154
|
'./pages.index.vue.eta': 'pages/index.vue',
|
|
155
|
+
'./pages.[xorg].index.vue.eta': 'pages/[xorg]/index.vue',
|
|
156
|
+
'./pages.login.vue.eta': 'pages/login.vue',
|
|
147
157
|
'./plugins.simpleapp.ts.eta': 'plugins/simpleapp.ts',
|
|
148
158
|
'./tailwind.config.ts.eta': 'tailwind.config.ts',
|
|
149
159
|
'./tailwind.css.eta': 'assets/css/tailwind.css',
|
package/dist/framework.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"framework.js","sourceRoot":"","sources":["../src/framework.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4CAAmB;AACnB,iDAAwC;AACxC,iCAAwC;AACxC,sDAAuC;AACvC,6BAA0B;AAC1B,MAAM,GAAG,GAAoB,IAAI,cAAM,EAAE,CAAC;AAE1C,IAAI,MAAM,GAAG;IACT,mBAAmB,EAAC,eAAe;IACnC,eAAe,EAAC,aAAa;IAC7B,aAAa,EAAC,MAAM;IACpB,iBAAiB,EAAC,kEAAkE;IACpF,gBAAgB,EAAC,cAAc;IAC/B,cAAc,EAAC,MAAM;IACrB,cAAc,EAAC,iBAAiB;
|
|
1
|
+
{"version":3,"file":"framework.js","sourceRoot":"","sources":["../src/framework.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/framework.ts
CHANGED
|
@@ -13,6 +13,14 @@ let config = {
|
|
|
13
13
|
"frontendFolder":"./myfrontend",
|
|
14
14
|
"frontendPort":"8080",
|
|
15
15
|
"openapi3Yaml":"../openapi.yaml",
|
|
16
|
+
"keycloaksetting":{
|
|
17
|
+
"OAUTH2_BASEURL":"https://keycloak-server-url/",
|
|
18
|
+
"OAUTH2_REALM":"realm-name",
|
|
19
|
+
"OAUTH2_CONFIGURL":"https://keycloak-server-url/realms/realm-name",
|
|
20
|
+
"OAUTH2_CLIENTID":"client-id",
|
|
21
|
+
"OAUTH2_CLIENTSECRET":"client-secret-value",
|
|
22
|
+
"AUTH_SECRET_KEY":"my-secret",
|
|
23
|
+
}
|
|
16
24
|
}
|
|
17
25
|
|
|
18
26
|
export const setConfiguration=(paraconfig)=>{
|
|
@@ -53,20 +61,19 @@ export const prepareNest = (callback:Function)=>{
|
|
|
53
61
|
if(!fs.existsSync(`${targetfolder}/.env`)){
|
|
54
62
|
|
|
55
63
|
|
|
56
|
-
exec(`cd ${targetfolder};pnpm install --save axios @darkwolf/base64url json-schema @wearenova/mongoose-tenant @nestjs/swagger @nestjs/mongoose mongoose ajv ajv-formats @nestjs/config`,async (error, stdout, stderr)=>{
|
|
64
|
+
exec(`cd ${targetfolder};pnpm install --save nest-keycloak-connect keycloak-connect @nestjs/serve-static jsonwebtoken axios @darkwolf/base64url json-schema @wearenova/mongoose-tenant @nestjs/swagger @nestjs/mongoose mongoose ajv ajv-formats @nestjs/config`,async (error, stdout, stderr)=>{
|
|
57
65
|
// log.info(`dependency installed`)
|
|
58
66
|
if(!error){
|
|
59
|
-
|
|
67
|
+
fs.mkdirSync(`${targetfolder}/public_html`,{recursive:true})
|
|
60
68
|
const eta = new Eta({views: constants.templatedir});
|
|
61
|
-
const variables=
|
|
62
|
-
backendPort:config.backendPort,
|
|
63
|
-
mongoConnectStr:config.mongoConnectStr
|
|
64
|
-
}
|
|
69
|
+
const variables=config
|
|
65
70
|
const txtEnv = eta.render('./nest/nest.env.eta', variables);
|
|
66
71
|
const txtMain = eta.render('./nest/nest.main.eta', variables);
|
|
72
|
+
const txtRedirectHtml = eta.render('./nest/oauth2-redirect.eta', variables);
|
|
67
73
|
|
|
68
74
|
fs.writeFileSync(`${targetfolder}/.env`, txtEnv);
|
|
69
75
|
fs.writeFileSync(`${targetfolder}/src/main.ts`, txtMain);
|
|
76
|
+
fs.writeFileSync(`${targetfolder}/public_html/oauth2-redirect.html`, txtRedirectHtml);
|
|
70
77
|
const tsconfigpath = process.cwd()+'/'+`${targetfolder}/tsconfig.json`
|
|
71
78
|
const tsconfig = require(tsconfigpath)
|
|
72
79
|
tsconfig.compilerOptions.esModuleInterop=true
|
|
@@ -91,23 +98,21 @@ export const prepareNuxt = (callback:Function)=>{
|
|
|
91
98
|
const targetfolder = config.frontendFolder
|
|
92
99
|
if(!fs.existsSync(`${targetfolder}/.env`)){
|
|
93
100
|
//asume no environment. prepare now
|
|
94
|
-
exec(`cd ${targetfolder};pnpm install;pnpm install -D @nuxt/ui @types/node @vueuse/nuxt @sidebase/nuxt-auth @vueuse/core nuxt-security prettier `, (error, stdout, stderr)=>{
|
|
101
|
+
exec(`cd ${targetfolder};pnpm install;pnpm install -D @sidebase/nuxt-auth @nuxt/ui @types/node @vueuse/nuxt @sidebase/nuxt-auth @vueuse/core nuxt-security prettier `, (error, stdout, stderr)=>{
|
|
95
102
|
//;pnpm install
|
|
96
103
|
console.log(error, stdout, stderr)
|
|
97
|
-
exec(`cd ${targetfolder};pnpm install --save
|
|
104
|
+
exec(`cd ${targetfolder};pnpm install --save next-auth@4.21.1 @darkwolf/base64url @nuxt/ui ajv dotenv @fullcalendar/core @fullcalendar/vue3 quill uuid ajv-formats primeflex primeicons prettier primevue axios json-schema mitt @simitgroup/simpleapp-vue-component@latest`, (error, stdout, stderr)=>{
|
|
98
105
|
console.log(error, stdout, stderr)
|
|
99
106
|
|
|
100
107
|
fs.mkdirSync(`${targetfolder}/assets/css/`,{recursive:true})
|
|
101
108
|
fs.mkdirSync(`${targetfolder}/layouts`,{recursive:true})
|
|
102
109
|
fs.mkdirSync(`${targetfolder}/components`,{recursive:true})
|
|
103
110
|
fs.mkdirSync(`${targetfolder}/server/api/[xorg]`,{recursive:true})
|
|
104
|
-
fs.mkdirSync(`${targetfolder}/
|
|
111
|
+
fs.mkdirSync(`${targetfolder}/server/api/auth`,{recursive:true})
|
|
112
|
+
fs.mkdirSync(`${targetfolder}/pages/[xorg]`,{recursive:true})
|
|
105
113
|
fs.mkdirSync(`${targetfolder}/plugins`,{recursive:true})
|
|
106
114
|
const eta = new Eta({views: `${constants.templatedir}/nuxt`});
|
|
107
|
-
const variables=
|
|
108
|
-
backendPort:config.backendPort,
|
|
109
|
-
frontendPort:config.frontendPort
|
|
110
|
-
}
|
|
115
|
+
const variables=config
|
|
111
116
|
const writes = {
|
|
112
117
|
'./app.vue.eta':'app.vue',
|
|
113
118
|
'./components.eventmonitor.vue.eta':'components/EventMonitor.vue',
|
|
@@ -116,11 +121,15 @@ export const prepareNuxt = (callback:Function)=>{
|
|
|
116
121
|
'./components.debugdocdata.vue.eta':'components/DebugDocumentData.vue',
|
|
117
122
|
'./layouts.default.vue.eta':'layouts/default.vue',
|
|
118
123
|
'./server.api.ts.eta':'server/api/[xorg]/[...].ts',
|
|
124
|
+
'./server.api.auth.logout.ts.eta':'server/api/auth/logout.ts',
|
|
125
|
+
'./server.api.auth[...].ts.eta':'server/api/auth/[...].ts',
|
|
119
126
|
'./nuxt.config.ts.eta':'nuxt.config.ts',
|
|
120
127
|
'./pages.index.vue.eta':'pages/index.vue',
|
|
128
|
+
'./pages.[xorg].index.vue.eta':'pages/[xorg]/index.vue',
|
|
129
|
+
'./pages.login.vue.eta':'pages/login.vue',
|
|
121
130
|
'./plugins.simpleapp.ts.eta':'plugins/simpleapp.ts',
|
|
122
131
|
'./tailwind.config.ts.eta':'tailwind.config.ts',
|
|
123
|
-
'./tailwind.css.eta':'assets/css/tailwind.css',
|
|
132
|
+
'./tailwind.css.eta':'assets/css/tailwind.css',
|
|
124
133
|
'./env.eta':'.env',
|
|
125
134
|
}
|
|
126
135
|
|
|
@@ -23,9 +23,10 @@ const schemasetting = {
|
|
|
23
23
|
<% }else if( schema[key].type == 'array'){%>
|
|
24
24
|
<%= key %>: [{type: <%= schema[key].item.type %>, required:false}] //basic array
|
|
25
25
|
<% }else{%>
|
|
26
|
-
<%= key %>: {type: <%= capitalizeFirstLetter(schema[key].type) %>, required:false}, //field
|
|
26
|
+
<%= key %>: {type: <%= capitalizeFirstLetter(schema[key].type) %>, required: <% if(key==it.autocompletecode || key==it.autocompletename){%>true<%}else{%>false<%}%>}, //field
|
|
27
27
|
<% } %>
|
|
28
28
|
<%}) %>
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
export const <%= it.doctype %>MongoSchema = new Schema(schemasetting,{collection: '<%= it.name %>'})
|
|
32
|
+
.index({<%=it.autocompletecode%>:1,orgId:1},{unique:true});
|
|
@@ -1,30 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
import { Injectable, NestMiddleware,Scope } from '@nestjs/common';
|
|
1
|
+
import { Injectable, NestMiddleware, Scope } from '@nestjs/common';
|
|
3
2
|
import { Request, Response, NextFunction } from 'express';
|
|
4
|
-
import
|
|
3
|
+
// import * as jwt from 'nestjs-jwt'
|
|
4
|
+
|
|
5
5
|
|
|
6
|
+
import { User } from './User';
|
|
7
|
+
// import {KeycloakConfigService} from "../keycloak/keycloak.service"
|
|
6
8
|
@Injectable({
|
|
7
|
-
|
|
9
|
+
scope: Scope.REQUEST,
|
|
8
10
|
})
|
|
11
|
+
|
|
9
12
|
export class TenantMiddleware implements NestMiddleware {
|
|
10
13
|
use(req: Request, res: Response, next: NextFunction) {
|
|
11
|
-
req.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
}else{
|
|
25
|
-
return res.status(401).send("undefine header string x-org")
|
|
14
|
+
if (req.baseUrl == '/oauth2-redirect.html') {
|
|
15
|
+
next();
|
|
16
|
+
return ;
|
|
17
|
+
}
|
|
18
|
+
if(!req.headers['authorization']){
|
|
19
|
+
return res.status(401).send('Undefine bearer token');
|
|
20
|
+
}
|
|
21
|
+
if (!req.headers['x-org']){
|
|
22
|
+
return res.status(401).send('undefine header string x-org');
|
|
23
|
+
}
|
|
24
|
+
const u = User.getInstance();
|
|
26
25
|
|
|
26
|
+
try {
|
|
27
|
+
u.setXorg(req.headers['x-org'].toString());
|
|
28
|
+
let tokenstr:string = req.headers['authorization']
|
|
29
|
+
tokenstr = tokenstr.replace("Bearer ",'')
|
|
30
|
+
u.setUserToken(tokenstr);
|
|
31
|
+
next();
|
|
32
|
+
} catch {
|
|
33
|
+
return res.status(401).send('Invalid x-org or user info');
|
|
27
34
|
}
|
|
35
|
+
|
|
36
|
+
|
|
28
37
|
|
|
29
38
|
}
|
|
30
39
|
}
|
package/templates/nest/User.eta
CHANGED
|
@@ -1,80 +1,115 @@
|
|
|
1
1
|
import { Injectable, Scope } from '@nestjs/common';
|
|
2
|
-
import Base64URL from '@darkwolf/base64url'
|
|
2
|
+
import Base64URL from '@darkwolf/base64url';
|
|
3
|
+
import * as jwt from 'jsonwebtoken'
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
3
8
|
|
|
4
9
|
@Injectable({
|
|
5
|
-
|
|
10
|
+
scope: Scope.REQUEST,
|
|
6
11
|
})
|
|
7
12
|
export class User {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
User.getInstance().uid=uid
|
|
25
|
-
}
|
|
26
|
-
getInfo=()=>{
|
|
27
|
-
return User.getInstance()
|
|
28
|
-
}
|
|
29
|
-
getBranchFilter=()=>{
|
|
30
|
-
return {
|
|
31
|
-
tenantId:User.getInstance().tenantId,
|
|
32
|
-
orgId: User.getInstance().orgId,
|
|
33
|
-
branchId:User.getInstance().branchId
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
getTenantFilter=()=>{
|
|
37
|
-
return {tenantId:User.getInstance().tenantId}
|
|
38
|
-
}
|
|
39
|
-
getOrgFilter=()=>{
|
|
40
|
-
return {tenantId:User.getInstance().tenantId,orgId: User.getInstance().orgId}
|
|
13
|
+
private static instance: User;
|
|
14
|
+
protected uid: string = '';
|
|
15
|
+
protected uname: string = '';
|
|
16
|
+
protected email: string = '';
|
|
17
|
+
protected fullname:string=''
|
|
18
|
+
protected xOrg: string = '';
|
|
19
|
+
protected tenantId: number = 0;
|
|
20
|
+
protected orgId: number = 0;
|
|
21
|
+
protected branchId: number = 0;
|
|
22
|
+
protected accessrights:any = {}
|
|
23
|
+
protected token:string = ''
|
|
24
|
+
protected refreshtoken:string = ''
|
|
25
|
+
constructor() {}
|
|
26
|
+
public static getInstance(): User {
|
|
27
|
+
if (!User.instance) {
|
|
28
|
+
User.instance = new User();
|
|
41
29
|
}
|
|
30
|
+
return User.instance;
|
|
31
|
+
}
|
|
32
|
+
setUserToken = (tokenstr: string) => {
|
|
33
|
+
const tokeninfo = jwt.decode(tokenstr)
|
|
34
|
+
// realm_access: {
|
|
35
|
+
// roles: [
|
|
36
|
+
// 'default-roles-simitdeveloper',
|
|
37
|
+
// 'offline_access',
|
|
38
|
+
// 'uma_authorization'
|
|
39
|
+
// ]
|
|
40
|
+
// },
|
|
41
|
+
// resource_access: { account: { roles: [Array] } },
|
|
42
|
+
// scope: 'openid email profile',
|
|
43
|
+
// sid: '53192f53-d4af-413b-b8d7-1e186419fe53',
|
|
44
|
+
// email_verified: false,
|
|
45
|
+
// name: 'kstan kstan',
|
|
46
|
+
// preferred_username: 'kstan',
|
|
47
|
+
// given_name: 'kstan',
|
|
48
|
+
// family_name: 'kstan',
|
|
49
|
+
// email: 'kstan@simitgroup.com'
|
|
50
|
+
|
|
51
|
+
const u = User.getInstance()
|
|
52
|
+
u.token = tokenstr
|
|
53
|
+
u.uid = tokeninfo.sid;
|
|
54
|
+
u.email = tokeninfo.email
|
|
55
|
+
u.uname = tokeninfo.preferred_username
|
|
56
|
+
u.fullname = tokeninfo.name
|
|
57
|
+
u.accessrights = tokeninfo.resource_access
|
|
58
|
+
};
|
|
59
|
+
getInfo = () => {
|
|
60
|
+
return User.getInstance();
|
|
61
|
+
};
|
|
62
|
+
getBranchFilter = () => {
|
|
63
|
+
return {
|
|
64
|
+
tenantId: User.getInstance().tenantId,
|
|
65
|
+
orgId: User.getInstance().orgId,
|
|
66
|
+
branchId: User.getInstance().branchId,
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
getTenantFilter = () => {
|
|
70
|
+
return { tenantId: User.getInstance().tenantId };
|
|
71
|
+
};
|
|
72
|
+
getOrgFilter = () => {
|
|
73
|
+
return {
|
|
74
|
+
tenantId: User.getInstance().tenantId,
|
|
75
|
+
orgId: User.getInstance().orgId,
|
|
76
|
+
};
|
|
77
|
+
};
|
|
42
78
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
+
getCreateFilter = () => {
|
|
80
|
+
const u = User.getInstance();
|
|
81
|
+
return {
|
|
82
|
+
tenantId: u.tenantId,
|
|
83
|
+
orgId: u.orgId,
|
|
84
|
+
branchId: u.branchId,
|
|
85
|
+
createdby: u.uid,
|
|
86
|
+
updatedby: u.uid,
|
|
87
|
+
created: new Date().getTime().toString(),
|
|
88
|
+
updated: new Date().getTime().toString(),
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
getUpdateFilter = () => {
|
|
92
|
+
const u = User.getInstance();
|
|
93
|
+
return {
|
|
94
|
+
updatedby: u.uid,
|
|
95
|
+
updated: new Date().getTime().toString(),
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
setXorg = (xorg) => {
|
|
99
|
+
try {
|
|
100
|
+
const decodedText: string = Base64URL.decodeText(xorg);
|
|
101
|
+
const arrXorg = decodedText.split('-');
|
|
102
|
+
|
|
103
|
+
if (arrXorg.length == 3) {
|
|
104
|
+
const u = User.getInstance();
|
|
105
|
+
u.tenantId = Number(arrXorg[0]);
|
|
106
|
+
u.orgId = Number(arrXorg[1]);
|
|
107
|
+
u.branchId = Number(arrXorg[2]);
|
|
108
|
+
} else {
|
|
109
|
+
throw 'invalid x-org';
|
|
110
|
+
}
|
|
111
|
+
} catch (err) {
|
|
112
|
+
throw err;
|
|
79
113
|
}
|
|
114
|
+
};
|
|
80
115
|
}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { Module,MiddlewareConsumer,NestModule } from '@nestjs/common';
|
|
2
2
|
import { MongooseModule } from '@nestjs/mongoose';
|
|
3
|
+
import { APP_GUARD } from '@nestjs/core';
|
|
4
|
+
import {
|
|
5
|
+
AuthGuard, KeycloakConnectModule,
|
|
6
|
+
ResourceGuard,TokenValidation,
|
|
7
|
+
RoleGuard,PolicyEnforcementMode
|
|
8
|
+
} from 'nest-keycloak-connect';
|
|
3
9
|
import { ConfigModule } from '@nestjs/config';
|
|
10
|
+
import { ServeStaticModule } from '@nestjs/serve-static';
|
|
11
|
+
import { join } from 'path';
|
|
4
12
|
import {TenantMiddleware} from './class/TenantMiddleware'
|
|
5
13
|
<% for(let i=0;i<it.length; i++){ %>
|
|
6
14
|
import {<%= it[i].docname %>Module} from './docs/<%= it[i].doctype %>/<%= it[i].doctype %>.module'
|
|
@@ -8,9 +16,35 @@ import {<%= it[i].docname %>Module} from './docs/<%= it[i].doctype %>/<%= it[i].
|
|
|
8
16
|
|
|
9
17
|
@Module({
|
|
10
18
|
//define environment variables: MONGODB_URL='mongodb://<user>:<pass>@<host>:<port>/<db>?authMechanism=DEFAULT'
|
|
11
|
-
imports: [
|
|
19
|
+
imports: [
|
|
20
|
+
ConfigModule.forRoot(),
|
|
21
|
+
MongooseModule.forRoot(process.env.MONGODB_URL),
|
|
22
|
+
ServeStaticModule.forRoot({
|
|
23
|
+
rootPath: join(__dirname, '..', 'public_html'),
|
|
24
|
+
exclude: ['/api/(.*)'],
|
|
25
|
+
}),
|
|
26
|
+
KeycloakConnectModule.register({
|
|
27
|
+
authServerUrl: process.env.OAUTH2_BASEURL,
|
|
28
|
+
realm: process.env.OAUTH2_REALM,
|
|
29
|
+
clientId: process.env.OAUTH2_CLIENTID,
|
|
30
|
+
secret: process.env.OAUTH2_CLIENTSECRET,
|
|
31
|
+
policyEnforcement: PolicyEnforcementMode.PERMISSIVE,
|
|
32
|
+
tokenValidation: TokenValidation.ONLINE,
|
|
33
|
+
}),
|
|
34
|
+
<% for(let i=0;i<it.length; i++){ %><%= it[i].docname %>Module,<%}%>],
|
|
12
35
|
controllers: [],
|
|
13
|
-
providers: [
|
|
36
|
+
providers: [ {
|
|
37
|
+
provide: APP_GUARD,
|
|
38
|
+
useClass: AuthGuard,
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
provide: APP_GUARD,
|
|
42
|
+
useClass: ResourceGuard,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
provide: APP_GUARD,
|
|
46
|
+
useClass: RoleGuard,
|
|
47
|
+
},],
|
|
14
48
|
})
|
|
15
49
|
export class AppModule implements NestModule{
|
|
16
50
|
configure(consumer: MiddlewareConsumer) {
|
|
@@ -4,4 +4,18 @@ HTTP_PORT=<%=it.backendPort%>
|
|
|
4
4
|
|
|
5
5
|
PROJECT_NAME=SimpleApp Demo1
|
|
6
6
|
PROJECT_DESCRIPTION=Try CRUD
|
|
7
|
-
PROJECT_Version=1.0.0
|
|
7
|
+
PROJECT_Version=1.0.0
|
|
8
|
+
|
|
9
|
+
OAUTH2_BASEURL=<%=it.keycloaksetting.OAUTH2_BASEURL%>
|
|
10
|
+
|
|
11
|
+
OAUTH2_REALM=<%=it.keycloaksetting.OAUTH2_REALM%>
|
|
12
|
+
|
|
13
|
+
OAUTH2_CONFIGURL=<%=it.keycloaksetting.OAUTH2_CONFIGURL%>
|
|
14
|
+
|
|
15
|
+
OAUTH2_CLIENTID=<%=it.keycloaksetting.OAUTH2_CLIENTID%>
|
|
16
|
+
|
|
17
|
+
OAUTH2_CLIENTSECRET=<%=it.keycloaksetting.OAUTH2_CLIENTSECRET%>
|
|
18
|
+
|
|
19
|
+
AUTH_SECRET_KEY=<%=it.keycloaksetting.AUTH_SECRET_KEY%>
|
|
20
|
+
|
|
21
|
+
AUTH_ORIGIN=http://localhost:8080
|
|
@@ -9,14 +9,23 @@ async function bootstrap() {
|
|
|
9
9
|
.setTitle(process.env.PROJECT_NAME)
|
|
10
10
|
.setDescription(process.env.PROJECT_DESCRIPTION)
|
|
11
11
|
.setVersion(process.env.PROJECT_VERSION)
|
|
12
|
-
.addApiKey({
|
|
12
|
+
.addApiKey({
|
|
13
|
+
in: 'header',name: 'x-org',type: 'apiKey',description: 'base 64 url encode. example: MS0xLTE',
|
|
14
|
+
},'x-org',)
|
|
15
|
+
.addOAuth2({
|
|
16
|
+
name:'oauth2',in:'header',type:'oauth2',flows:{
|
|
17
|
+
implicit:{
|
|
18
|
+
authorizationUrl: `${process.env.OAUTH2_CONFIGURL}/protocol/openid-connect/auth`,
|
|
19
|
+
scopes:[],
|
|
20
|
+
}}},'oauth2')
|
|
13
21
|
.addSecurityRequirements('x-org')
|
|
22
|
+
.addSecurityRequirements('oauth2')
|
|
14
23
|
.build();
|
|
15
24
|
const document = SwaggerModule.createDocument(app, config);
|
|
16
25
|
SwaggerModule.setup('api', app, document, {
|
|
17
|
-
swaggerOptions: { showExtensions: true },
|
|
26
|
+
swaggerOptions: { showExtensions: true, persistAuthorization: true },
|
|
18
27
|
});
|
|
19
28
|
|
|
20
|
-
await app.listen(process.env.HTTP_PORT ??
|
|
29
|
+
await app.listen(process.env.HTTP_PORT ?? 8000); //listen which port
|
|
21
30
|
}
|
|
22
|
-
bootstrap();
|
|
31
|
+
bootstrap();
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en-US">
|
|
3
|
+
<head>
|
|
4
|
+
<title>Swagger UI: OAuth2 Redirect</title>
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<script>
|
|
8
|
+
'use strict';
|
|
9
|
+
function run () {
|
|
10
|
+
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
|
11
|
+
var sentState = oauth2.state;
|
|
12
|
+
var redirectUrl = oauth2.redirectUrl;
|
|
13
|
+
var isValid, qp, arr;
|
|
14
|
+
|
|
15
|
+
if (/code|token|error/.test(window.location.hash)) {
|
|
16
|
+
qp = window.location.hash.substring(1).replace('?', '&');
|
|
17
|
+
} else {
|
|
18
|
+
qp = location.search.substring(1);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
arr = qp.split("&");
|
|
22
|
+
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
|
|
23
|
+
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
|
24
|
+
function (key, value) {
|
|
25
|
+
return key === "" ? value : decodeURIComponent(value);
|
|
26
|
+
}
|
|
27
|
+
) : {};
|
|
28
|
+
|
|
29
|
+
isValid = qp.state === sentState;
|
|
30
|
+
|
|
31
|
+
if ((
|
|
32
|
+
oauth2.auth.schema.get("flow") === "accessCode" ||
|
|
33
|
+
oauth2.auth.schema.get("flow") === "authorizationCode" ||
|
|
34
|
+
oauth2.auth.schema.get("flow") === "authorization_code"
|
|
35
|
+
) && !oauth2.auth.code) {
|
|
36
|
+
if (!isValid) {
|
|
37
|
+
oauth2.errCb({
|
|
38
|
+
authId: oauth2.auth.name,
|
|
39
|
+
source: "auth",
|
|
40
|
+
level: "warning",
|
|
41
|
+
message: "Authorization may be unsafe, passed state was changed in server. The passed state wasn't returned from auth server."
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (qp.code) {
|
|
46
|
+
delete oauth2.state;
|
|
47
|
+
oauth2.auth.code = qp.code;
|
|
48
|
+
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
|
49
|
+
} else {
|
|
50
|
+
let oauthErrorMsg;
|
|
51
|
+
if (qp.error) {
|
|
52
|
+
oauthErrorMsg = "["+qp.error+"]: " +
|
|
53
|
+
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
|
|
54
|
+
(qp.error_uri ? "More info: "+qp.error_uri : "");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
oauth2.errCb({
|
|
58
|
+
authId: oauth2.auth.name,
|
|
59
|
+
source: "auth",
|
|
60
|
+
level: "error",
|
|
61
|
+
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server."
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
|
66
|
+
}
|
|
67
|
+
window.close();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (document.readyState !== 'loading') {
|
|
71
|
+
run();
|
|
72
|
+
} else {
|
|
73
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
74
|
+
run();
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
</script>
|
|
78
|
+
</body>
|
|
79
|
+
</html>
|
|
@@ -47,7 +47,6 @@ const newData = () => {
|
|
|
47
47
|
|
|
48
48
|
const triggerEdit = (event: any) => {
|
|
49
49
|
let id = event.data._id.toString()
|
|
50
|
-
editRecord(event.data._id);
|
|
51
50
|
router.push({ path: `${props.path}/${id}` })
|
|
52
51
|
};
|
|
53
52
|
const editRecord = (id:string) => {
|
|
@@ -95,7 +94,7 @@ refresh();
|
|
|
95
94
|
<button class="bg-primary" @click="newData" v-tooltip="'Add new(ctrl+i)'" >New</button>
|
|
96
95
|
<SimpleAppDatatable
|
|
97
96
|
@row-dblclick="triggerEdit"
|
|
98
|
-
v-model="recordlist"
|
|
97
|
+
v-model="recordlist"
|
|
99
98
|
:setting="{}"
|
|
100
99
|
:columns="listColumns"
|
|
101
100
|
>
|
|
@@ -6,18 +6,23 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import * as o from "../simpleapp/openapi";
|
|
9
|
-
|
|
9
|
+
import axios from 'axios'
|
|
10
10
|
const getAutoComplete = (apiname: string): any => {
|
|
11
|
+
const { csrf } = useCsrf()
|
|
12
|
+
axios.defaults.headers.common = {"CSRF-TOKEN": csrf};
|
|
13
|
+
const route = useRoute();
|
|
14
|
+
|
|
11
15
|
const config: o.Configuration = {
|
|
12
|
-
basePath: useRuntimeConfig().public.APP_URL
|
|
16
|
+
basePath: `${useRuntimeConfig().public.APP_URL}/api/${route.params.xorg}`,
|
|
13
17
|
isJsonMime: () => true,
|
|
14
18
|
};
|
|
15
19
|
const docsOpenapi: any = {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
'category' : new o.CATApi(config),
|
|
21
|
+
'leadtype' : new o.LEADTApi(config),
|
|
22
|
+
'level' : new o.LVLApi(config),
|
|
23
|
+
'product' : new o.PRDApi(config),
|
|
24
|
+
'studentgroup' : new o.STGApi(config),
|
|
25
|
+
};
|
|
21
26
|
if (!docsOpenapi[apiname]) {
|
|
22
27
|
console.error(
|
|
23
28
|
`api for '${apiname}' does not exists, most probably define wrong x-foreignkey`,
|
|
@@ -4,13 +4,24 @@
|
|
|
4
4
|
* last change 2023-09-10
|
|
5
5
|
* author: Ks Tan
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
|
-
export const getMenus =(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
|
|
8
|
+
export const getMenus =()=>{
|
|
9
|
+
|
|
10
|
+
const route = useRoute();
|
|
11
|
+
const xorg = route.params.xorg
|
|
12
|
+
let data =[];
|
|
13
|
+
if(xorg){
|
|
14
|
+
data =[
|
|
15
|
+
{label: 'Home',icon: 'pi pi-fw pi-home', url:'/'},
|
|
16
|
+
{label: 'Cruds',icon: 'pi pi-fw pi-pencil',items:[
|
|
17
|
+
<% for(let i=0;i<it.length; i++){ %>
|
|
18
|
+
<% let obj = it[i]%>
|
|
19
|
+
{label: '<%=obj.docname.toLowerCase()%>', to:`/${xorg}/<%=obj.docname.toLowerCase()%>`},
|
|
20
|
+
<%}%>
|
|
21
|
+
]},
|
|
22
|
+
]
|
|
23
|
+
}else{
|
|
24
|
+
data= [{label: 'Home',icon: 'pi pi-fw pi-home', url:'/'},]
|
|
25
|
+
}
|
|
26
|
+
return data
|
|
27
|
+
}
|
package/templates/nuxt/env.eta
CHANGED
|
@@ -4,4 +4,14 @@ SIMPLEAPP_BACKEND_URL=http://localhost:<%=it.backendPort%>
|
|
|
4
4
|
|
|
5
5
|
APP_URL=http://localhost:<%=it.frontendPort%>
|
|
6
6
|
|
|
7
|
-
DEBUGDATA=1
|
|
7
|
+
DEBUGDATA=1
|
|
8
|
+
|
|
9
|
+
OAUTH2_CONFIGURL=<%=it.keycloaksetting.OAUTH2_CONFIGURL%>
|
|
10
|
+
|
|
11
|
+
OAUTH2_CLIENTID=<%=it.keycloaksetting.OAUTH2_CLIENTID%>
|
|
12
|
+
|
|
13
|
+
OAUTH2_CLIENTSECRET=<%=it.keycloaksetting.OAUTH2_CLIENTSECRET%>
|
|
14
|
+
|
|
15
|
+
AUTH_SECRET_KEY=<%=it.keycloaksetting.AUTH_SECRET_KEY%>
|
|
16
|
+
|
|
17
|
+
AUTH_ORIGIN=http://localhost:<%=it.frontendPort%>
|
|
@@ -19,19 +19,19 @@ tailwindcss: {
|
|
|
19
19
|
// Options
|
|
20
20
|
},
|
|
21
21
|
modules: [
|
|
22
|
-
|
|
23
|
-
"nuxt-security",
|
|
24
|
-
|
|
22
|
+
'@sidebase/nuxt-auth',
|
|
23
|
+
"nuxt-security",
|
|
25
24
|
'@vueuse/nuxt',
|
|
26
25
|
'@nuxt/ui'
|
|
27
|
-
//'@nuxtjs/tailwindcss', //use @nuxt/ui own tailwind
|
|
28
|
-
// '@nuxtjs/color-mode'
|
|
29
|
-
|
|
30
26
|
],
|
|
31
|
-
|
|
27
|
+
auth: {
|
|
28
|
+
globalAppMiddleware: true
|
|
29
|
+
},
|
|
32
30
|
security: {
|
|
33
|
-
csrf: true,
|
|
31
|
+
//csrf: true, // been force to off csrf cash it crash with nuxt-auth
|
|
34
32
|
},
|
|
33
|
+
ssr: true,
|
|
34
|
+
|
|
35
35
|
css: [
|
|
36
36
|
"primevue/resources/themes/lara-light-blue/theme.css",
|
|
37
37
|
'primeicons/primeicons.css'
|
|
@@ -41,5 +41,6 @@ tailwindcss: {
|
|
|
41
41
|
transpile: ["primevue"]
|
|
42
42
|
},
|
|
43
43
|
|
|
44
|
+
|
|
44
45
|
|
|
45
46
|
})
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
/**
|
|
3
|
+
* This file was automatically generated by simpleapp generator during initialization.
|
|
4
|
+
* You may modify it for your need
|
|
5
|
+
* last change 2023-09-09
|
|
6
|
+
* author: Ks Tan
|
|
7
|
+
*/
|
|
8
|
+
</script>
|
|
9
|
+
<template>
|
|
10
|
+
<div>
|
|
11
|
+
<h1>index page</h1>
|
|
12
|
+
<ul>
|
|
13
|
+
<li><NuxtLink :external="true" to="/MS0xLTE" >MS0xLTE (1-1-1)</NuxtLink></li>
|
|
14
|
+
<li><NuxtLink :external="true" to="/Mi0yLTI" >Mi0yLTI (2-2-2)</NuxtLink></li>
|
|
15
|
+
</ul>
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
</template>
|
|
@@ -7,5 +7,13 @@
|
|
|
7
7
|
*/
|
|
8
8
|
</script>
|
|
9
9
|
<template>
|
|
10
|
-
<div>
|
|
10
|
+
<div>
|
|
11
|
+
<h1>index page</h1>
|
|
12
|
+
<ul>
|
|
13
|
+
<li><NuxtLink :external="true" to="/MS0xLTE" >MS0xLTE (1-1-1)</NuxtLink></li>
|
|
14
|
+
<li><NuxtLink :external="true" to="/Mi0yLTI" >Mi0yLTI (2-2-2)</NuxtLink></li>
|
|
15
|
+
</ul>
|
|
16
|
+
|
|
17
|
+
</div>
|
|
18
|
+
|
|
11
19
|
</template>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<NuxtPage />
|
|
3
|
+
</template>
|
|
4
|
+
<script setup lang="ts">
|
|
5
|
+
definePageMeta({
|
|
6
|
+
name: 'Login',
|
|
7
|
+
auth: false,
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
// const route = useRoute();
|
|
11
|
+
const { signIn } = useAuth()
|
|
12
|
+
onMounted(async () => {
|
|
13
|
+
let callbackUrl = '/';
|
|
14
|
+
// if(route.params.redirect) {
|
|
15
|
+
// callbackUrl = <string>route.params.redirect;
|
|
16
|
+
// }
|
|
17
|
+
await signIn('keycloak', { callbackUrl: callbackUrl })
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
</script>
|
|
@@ -40,9 +40,8 @@ const emitter = mitt()
|
|
|
40
40
|
|
|
41
41
|
|
|
42
42
|
export default defineNuxtPlugin((nuxtApp) => {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
const { csrf } = useCsrf()
|
|
44
|
+
axios.defaults.headers.common = {"CSRF-TOKEN": csrf};
|
|
46
45
|
nuxtApp.vueApp.use(PrimeVue, { ripple: true });
|
|
47
46
|
nuxtApp.vueApp
|
|
48
47
|
.component("SimpleAppAutocomplete",SimpleAppAutocomplete)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// give keycloak for
|
|
2
|
+
export default defineEventHandler(async (event) => {
|
|
3
|
+
const path = `${
|
|
4
|
+
process.env.OAUTH2_CONFIGURL
|
|
5
|
+
}/protocol/openid-connect/logout?redirect_uri=${encodeURIComponent(
|
|
6
|
+
process.env.AUTH_ORIGIN ?? ""
|
|
7
|
+
)}`;
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
path: path
|
|
11
|
+
}
|
|
12
|
+
});
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { NuxtAuthHandler } from "#auth";
|
|
2
|
+
import KeycloakProvider from "next-auth/providers/keycloak";
|
|
3
|
+
import type { JWT } from "next-auth/jwt";
|
|
4
|
+
// import GithubProvider from "next-auth/providers/github";
|
|
5
|
+
|
|
6
|
+
export default NuxtAuthHandler({
|
|
7
|
+
secret: process.env.AUTH_SECRET_KEY,
|
|
8
|
+
jwt: {
|
|
9
|
+
maxAge: 60 * 60 * 24 * 30,
|
|
10
|
+
},
|
|
11
|
+
providers: [
|
|
12
|
+
// GithubProvider.default({
|
|
13
|
+
// clientId: process.env.GITHUB_ID ?? '',
|
|
14
|
+
// clientSecret: process.env.GITHUB_SECRET ?? '',
|
|
15
|
+
// }),
|
|
16
|
+
// @ts-expect-error
|
|
17
|
+
KeycloakProvider.default({
|
|
18
|
+
clientId: process.env.OAUTH2_CLIENTID ?? "",
|
|
19
|
+
clientSecret: process.env.OAUTH2_CLIENTSECRET ?? "",
|
|
20
|
+
issuer: process.env.OAUTH2_CONFIGURL,
|
|
21
|
+
idToken: true,
|
|
22
|
+
scheme: "oauth2",
|
|
23
|
+
endpoints: {
|
|
24
|
+
authorization: `${process.env.OAUTH2_CONFIGURL}/protocol/openid-connect/auth`,
|
|
25
|
+
userInfo: `${process.env.OAUTH2_CONFIGURL}/protocol/openid-connect/userinfo`,
|
|
26
|
+
token: `${process.env.OAUTH2_CONFIGURL}/protocol/openid-connect/token`,
|
|
27
|
+
logout:
|
|
28
|
+
`${process.env.OAUTH2_CONFIGURL}/protocol/openid-connect/logout?redirect_uri=` +
|
|
29
|
+
encodeURIComponent(String(process.env.APP_URL)),
|
|
30
|
+
},
|
|
31
|
+
// accessTokenUrl: `${process.env.OAUTH2_CONFIGURL}/protocol/openid-connect/token`,
|
|
32
|
+
// requestTokenUrl: `${process.env.OAUTH2_CONFIGURL}/protocol/openid-connect/token`,
|
|
33
|
+
// profileUrl: `${process.env.OAUTH2_CONFIGURL}/protocol/openid-connect/userinfo`,
|
|
34
|
+
token: {
|
|
35
|
+
property: "access_token",
|
|
36
|
+
type: "Bearer",
|
|
37
|
+
name: "Authorization",
|
|
38
|
+
maxAge: 60 * 60 * 24,
|
|
39
|
+
},
|
|
40
|
+
refreshToken: {
|
|
41
|
+
property: "refresh_token",
|
|
42
|
+
maxAge: 60 * 60 * 24 * 30,
|
|
43
|
+
},
|
|
44
|
+
responseType: "code",
|
|
45
|
+
grantType: "authorization_code",
|
|
46
|
+
scope: ["openid", "profile", "email"],
|
|
47
|
+
codeChallengeMethod: "S256",
|
|
48
|
+
redirect: {
|
|
49
|
+
logout: "/",
|
|
50
|
+
callback: "/",
|
|
51
|
+
home: "/",
|
|
52
|
+
},
|
|
53
|
+
}),
|
|
54
|
+
],
|
|
55
|
+
pages: {
|
|
56
|
+
signIn: "/login",
|
|
57
|
+
},
|
|
58
|
+
callbacks: {
|
|
59
|
+
// async redirect({ url, baseUrl }) {
|
|
60
|
+
|
|
61
|
+
// console.log(url, baseUrl)
|
|
62
|
+
// return baseUrl
|
|
63
|
+
// },
|
|
64
|
+
async jwt({ token, account }) {
|
|
65
|
+
// Persist the OAuth access_token to the token right after signin
|
|
66
|
+
if (account) {
|
|
67
|
+
token.accessToken = account.access_token;
|
|
68
|
+
}
|
|
69
|
+
return token;
|
|
70
|
+
},
|
|
71
|
+
async session({ session, token, user }) {
|
|
72
|
+
// console.log("session", session);
|
|
73
|
+
// Send properties to the client, like an access_token from a provider.
|
|
74
|
+
session.accessToken = <string>token.accessToken;
|
|
75
|
+
return session;
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
/*async jwt({ token, account, user }) {
|
|
79
|
+
// Persist the OAuth access_token to the token right after signin
|
|
80
|
+
console.log("token", token);
|
|
81
|
+
console.log("account", account);
|
|
82
|
+
console.log("user", user);
|
|
83
|
+
|
|
84
|
+
// Initial sign in
|
|
85
|
+
if (account && user) {
|
|
86
|
+
// Add access_token, refresh_token and expirations to the token right after signin
|
|
87
|
+
token.accessToken = account.accessToken;
|
|
88
|
+
token.refreshToken = account.refreshToken;
|
|
89
|
+
token.accessTokenExpired =
|
|
90
|
+
Date.now() + (account.expires_in - 15) * 1000;
|
|
91
|
+
token.refreshTokenExpired =
|
|
92
|
+
Date.now() + (account.refresh_expires_in - 15) * 1000;
|
|
93
|
+
token.user = user;
|
|
94
|
+
return token;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Return previous token if the access token has not expired yet
|
|
98
|
+
if (Date.now() < token.accessTokenExpired) return token;
|
|
99
|
+
|
|
100
|
+
// Access token has expired, try to update it
|
|
101
|
+
return refreshAccessToken(token);
|
|
102
|
+
|
|
103
|
+
// if (account) {
|
|
104
|
+
// // Save the access token and refresh token in the JWT on the initial login
|
|
105
|
+
// token.accessToken = account.access_token;
|
|
106
|
+
// return {
|
|
107
|
+
// access_token: account.access_token,
|
|
108
|
+
// expires_at: Math.floor(
|
|
109
|
+
// Date.now() / 1000 + account.expires_in
|
|
110
|
+
// ),
|
|
111
|
+
// refresh_token: account.refresh_token,
|
|
112
|
+
// };
|
|
113
|
+
// } else if (Date.now() < token.expires_at * 1000) {
|
|
114
|
+
// // If the access token has not expired yet, return it
|
|
115
|
+
// return token;
|
|
116
|
+
// } else {
|
|
117
|
+
// // If the access token has expired, try to refresh it
|
|
118
|
+
// try {
|
|
119
|
+
// // ${process.env.OAUTH2_CONFIGURL}/.well-known/openid-configuration
|
|
120
|
+
// // We need the `token_endpoint`.
|
|
121
|
+
// const response = await fetch(
|
|
122
|
+
// `${process.env.OAUTH2_CONFIGURL}/protocol/openid-connect/token`,
|
|
123
|
+
// {
|
|
124
|
+
// headers: {
|
|
125
|
+
// "Content-Type":
|
|
126
|
+
// "application/x-www-form-urlencoded;charset=UTF-8",
|
|
127
|
+
// },
|
|
128
|
+
// body: new URLSearchParams({
|
|
129
|
+
// client_id: process.env.OAUTH2_CLIENTID ?? "",
|
|
130
|
+
// client_secret:
|
|
131
|
+
// process.env.OAUTH2_CLIENTSECRET ?? "",
|
|
132
|
+
// grant_type: "refresh_token",
|
|
133
|
+
// refresh_token: <string>token.refresh_token,
|
|
134
|
+
// }),
|
|
135
|
+
// method: "POST",
|
|
136
|
+
// }
|
|
137
|
+
// );
|
|
138
|
+
|
|
139
|
+
// const tokens: any = await response.json();
|
|
140
|
+
|
|
141
|
+
// if (!response.ok) throw tokens;
|
|
142
|
+
|
|
143
|
+
// return {
|
|
144
|
+
// ...token, // Keep the previous token properties
|
|
145
|
+
// access_token: tokens.access_token,
|
|
146
|
+
// expires_at: Math.floor(
|
|
147
|
+
// Date.now() / 1000 + tokens.expires_in
|
|
148
|
+
// ),
|
|
149
|
+
// // Fall back to old refresh token, but note that
|
|
150
|
+
// // many providers may only allow using a refresh token once.
|
|
151
|
+
// refresh_token:
|
|
152
|
+
// tokens.refresh_token ?? token.refresh_token,
|
|
153
|
+
// };
|
|
154
|
+
// } catch (error) {
|
|
155
|
+
// console.error("Error refreshing access token", error);
|
|
156
|
+
// // The error property will be used client-side to handle the refresh token error
|
|
157
|
+
// return {
|
|
158
|
+
// ...token,
|
|
159
|
+
// error: "RefreshAccessTokenError" as const,
|
|
160
|
+
// };
|
|
161
|
+
// }
|
|
162
|
+
// }
|
|
163
|
+
return token;
|
|
164
|
+
},
|
|
165
|
+
async session({ session, token, user }) {
|
|
166
|
+
if (token) {
|
|
167
|
+
session.error = <string>token.error;
|
|
168
|
+
session.accessToken = <string>token.accessToken;
|
|
169
|
+
}
|
|
170
|
+
return session;
|
|
171
|
+
}, */
|
|
172
|
+
},
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
/* const refreshAccessToken = async (token: JWT) => {
|
|
176
|
+
try {
|
|
177
|
+
if (Date.now() > token.refreshTokenExpired) throw Error;
|
|
178
|
+
const details = {
|
|
179
|
+
client_id: process.env.OAUTH2_CLIENTID,
|
|
180
|
+
client_secret: process.env.OAUTH2_CLIENTSECRET,
|
|
181
|
+
grant_type: ["refresh_token"],
|
|
182
|
+
refresh_token: token.refreshToken,
|
|
183
|
+
};
|
|
184
|
+
const formBody: string[] = [];
|
|
185
|
+
Object.entries(details).forEach(([key, value]: [string, any]) => {
|
|
186
|
+
const encodedKey = encodeURIComponent(key);
|
|
187
|
+
const encodedValue = encodeURIComponent(value);
|
|
188
|
+
formBody.push(encodedKey + "=" + encodedValue);
|
|
189
|
+
});
|
|
190
|
+
const formData = formBody.join("&");
|
|
191
|
+
const url = `${process.env.OAUTH2_CONFIGURL}/protocol/openid-connect/token`;
|
|
192
|
+
const response = await fetch(url, {
|
|
193
|
+
method: "POST",
|
|
194
|
+
headers: {
|
|
195
|
+
"Content-Type":
|
|
196
|
+
"application/x-www-form-urlencoded;charset=UTF-8",
|
|
197
|
+
},
|
|
198
|
+
body: formData,
|
|
199
|
+
});
|
|
200
|
+
const refreshedTokens = await response.json();
|
|
201
|
+
if (!response.ok) throw refreshedTokens;
|
|
202
|
+
return {
|
|
203
|
+
...token,
|
|
204
|
+
accessToken: refreshedTokens.access_token,
|
|
205
|
+
accessTokenExpired:
|
|
206
|
+
Date.now() + (refreshedTokens.expires_in - 15) * 1000,
|
|
207
|
+
refreshToken: refreshedTokens.refresh_token ?? token.refreshToken,
|
|
208
|
+
refreshTokenExpired:
|
|
209
|
+
Date.now() + (refreshedTokens.refresh_expires_in - 15) * 1000,
|
|
210
|
+
};
|
|
211
|
+
} catch (error) {
|
|
212
|
+
console.log('receive', error)
|
|
213
|
+
|
|
214
|
+
return {
|
|
215
|
+
...token,
|
|
216
|
+
error: "RefreshAccessTokenError",
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}; */
|
|
220
|
+
|
|
221
|
+
// import NextAuth from "next-auth"
|
|
222
|
+
// import KeycloakProvider from 'next-auth/providers/keycloak'
|
|
223
|
+
// export const authOptions = {
|
|
224
|
+
// // Configure one or more authentication providers
|
|
225
|
+
// providers: [
|
|
226
|
+
// KeycloakProvider({
|
|
227
|
+
// clientId: process.env.OAUTH2_CLIENTID,
|
|
228
|
+
// clientSecret: process.env.OAUTH2_CLIENTSECRET,
|
|
229
|
+
// issuer: process.env.OAUTH2_CONFIGURL,
|
|
230
|
+
// }),
|
|
231
|
+
// ],
|
|
232
|
+
// }
|
|
233
|
+
// export default NextAuth(authOptions)
|
|
@@ -7,22 +7,27 @@
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
import axios from 'axios';
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
import { getServerSession } from '#auth'
|
|
11
|
+
import type { Session } from 'next-auth';
|
|
12
12
|
|
|
13
13
|
export default defineEventHandler(async (event) => {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
14
|
+
type additionalprops = {accessToken?:string}
|
|
15
|
+
let session:any=null
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
session = await getServerSession(event)
|
|
20
|
+
|
|
21
|
+
} catch (error) {
|
|
22
|
+
return sendRedirect(event, '/login', 401)
|
|
23
|
+
}
|
|
20
24
|
|
|
21
25
|
return new Promise<any>(async (resolve, reject) => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
if(!session) {
|
|
27
|
+
//if(!session || !session.accessToken) {
|
|
28
|
+
reject({ statusMessage: 'Unauthorized', statusCode: 401 });
|
|
29
|
+
throw createError({ statusMessage: 'Unauthorized', statusCode: 401 })
|
|
30
|
+
}
|
|
26
31
|
// console.log("------hihi------")
|
|
27
32
|
const seperateSymbol = '.';
|
|
28
33
|
// const seperateSymbol = '&';
|
|
@@ -32,7 +37,7 @@ export default defineEventHandler(async (event) => {
|
|
|
32
37
|
|
|
33
38
|
|
|
34
39
|
// console.error("event.context???",event.context)
|
|
35
|
-
|
|
40
|
+
const accessToken = session?.accessToken;
|
|
36
41
|
|
|
37
42
|
// const allowPlatform = ['report-api', 'cloudapi'];
|
|
38
43
|
// if(!key || !platform || !allowPlatform.includes(platform) || !accessToken) {
|
|
@@ -75,7 +80,7 @@ export default defineEventHandler(async (event) => {
|
|
|
75
80
|
method: req.method,
|
|
76
81
|
url: url,
|
|
77
82
|
headers: {
|
|
78
|
-
|
|
83
|
+
Authorization: `Bearer ${accessToken}`,
|
|
79
84
|
'X-Org': xOrg,
|
|
80
85
|
},
|
|
81
86
|
data: forwardData,
|