@simitgroup/simpleapp-generator 1.0.59 → 1.0.61

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.
Files changed (97) hide show
  1. package/dist/buildinschemas/branch.d.ts.map +1 -1
  2. package/dist/buildinschemas/branch.js +1 -0
  3. package/dist/buildinschemas/branch.js.map +1 -1
  4. package/dist/buildinschemas/organization.d.ts.map +1 -1
  5. package/dist/buildinschemas/organization.js +1 -0
  6. package/dist/buildinschemas/organization.js.map +1 -1
  7. package/dist/buildinschemas/permission.js +1 -1
  8. package/dist/buildinschemas/permission.js.map +1 -1
  9. package/dist/buildinschemas/user.d.ts.map +1 -1
  10. package/dist/buildinschemas/user.js +4 -1
  11. package/dist/buildinschemas/user.js.map +1 -1
  12. package/dist/framework.js +1 -1
  13. package/dist/framework.js.map +1 -1
  14. package/dist/generate.js +11 -6
  15. package/dist/generate.js.map +1 -1
  16. package/dist/type.d.ts +1 -0
  17. package/dist/type.d.ts.map +1 -1
  18. package/docs/jsonschema.md +1 -0
  19. package/package.json +1 -1
  20. package/src/buildinschemas/branch.ts +1 -0
  21. package/src/buildinschemas/organization.ts +1 -0
  22. package/src/buildinschemas/permission.ts +1 -1
  23. package/src/buildinschemas/user.ts +4 -1
  24. package/src/framework.ts +1 -1
  25. package/src/generate.ts +15 -7
  26. package/src/type.ts +1 -0
  27. package/templates/basic/nest/controller.ts.eta +5 -3
  28. package/templates/basic/nest/model.ts.eta +32 -7
  29. package/templates/basic/nuxt/pages.[id].vue.eta +2 -2
  30. package/templates/basic/nuxt/pages.crud.vue.eta +79 -40
  31. package/templates/basic/nuxt/pages.landing.vue.eta +82 -0
  32. package/templates/nest/.env._eta +1 -0
  33. package/templates/nest/src/simpleapp/generate/commons/exceptions/SimpleAppExceptionFilter.ts.eta +1 -1
  34. package/templates/nest/src/simpleapp/generate/commons/roles/roles.group.ts.eta +1 -1
  35. package/templates/nest/src/simpleapp/generate/commons/user.context.ts.eta +127 -22
  36. package/templates/nest/src/simpleapp/generate/processors/simpleapp.processor.ts.eta +1 -1
  37. package/templates/nest/src/simpleapp/profile/profile.controller.ts.eta +25 -2
  38. package/templates/nest/src/simpleapp/profile/profile.service.ts.eta +20 -2
  39. package/templates/nest/src/simpleapp/services/branch.service.ts.eta +41 -40
  40. package/templates/nest/src/simpleapp/services/user.service.ts.eta +10 -9
  41. package/templates/nuxt/app.vue.eta +2 -1
  42. package/templates/nuxt/assets/css/style.css._eta +3 -12
  43. package/templates/nuxt/assets/primevue/passthrough.ts._eta +24 -20
  44. package/templates/nuxt/components/ButtonCreateTenant.vue.eta +30 -23
  45. package/templates/nuxt/components/ButtonHome.vue.eta +15 -2
  46. package/templates/nuxt/components/ButtonMenuPicker.vue.eta +5 -20
  47. package/templates/nuxt/components/ButtonPermissionInfo.vue.eta +5 -7
  48. package/templates/nuxt/components/ButtonProfile.vue.eta +42 -25
  49. package/templates/nuxt/components/CrudSimple.vue.eta +1 -1
  50. package/templates/nuxt/components/EventDecision.vue.eta +115 -0
  51. package/templates/nuxt/components/EventNotification.vue.eta +157 -0
  52. package/templates/nuxt/components/HeaderBar.vue.eta +2 -2
  53. package/templates/nuxt/components/Invitation.vue.eta +3 -3
  54. package/templates/nuxt/components/SelectBranch.vue.eta +5 -2
  55. package/templates/nuxt/components/SimpleAppDatatable.vue.eta +151 -5
  56. package/templates/nuxt/components/TenantPicker.vue.eta +75 -0
  57. package/templates/nuxt/components/UserProfileListItem.vue.eta +65 -0
  58. package/templates/nuxt/components/renderers/BooleanRender.vue.eta +7 -0
  59. package/templates/nuxt/components/renderers/DateRender.vue.eta +6 -0
  60. package/templates/nuxt/components/renderers/ForeignKeyRender.vue.eta +10 -0
  61. package/templates/nuxt/components/renderers/MoneyRender.vue.eta +7 -0
  62. package/templates/nuxt/components/renderers/MultiTextRender.vue.eta +11 -0
  63. package/templates/nuxt/composables/getDocument.generate.ts.eta +4 -0
  64. package/templates/nuxt/composables/getMenus.generate.ts.eta +35 -31
  65. package/templates/nuxt/composables/getUserStore.generate.ts.eta +6 -1
  66. package/templates/nuxt/composables/goTo.generate.ts.eta +15 -0
  67. package/templates/nuxt/composables/notifications.generate.ts.eta +21 -0
  68. package/templates/nuxt/composables/stringHelper.generate.ts.eta +11 -1
  69. package/templates/nuxt/error.vue._eta +20 -5
  70. package/templates/nuxt/layouts/documentlist.vue.eta +166 -0
  71. package/templates/nuxt/middleware/30.acl.global.ts.eta +4 -1
  72. package/templates/nuxt/pages/[xorg]/organization/index.vue.eta +4 -4
  73. package/templates/nuxt/pages/[xorg]/profile.vue.eta +6 -0
  74. package/templates/nuxt/pages/[xorg]/user/[id].vue.eta +6 -0
  75. package/templates/nuxt/pages/[xorg]/user/index.vue.eta +211 -377
  76. package/templates/nuxt/pages/[xorg]/user.vue.eta +197 -0
  77. package/templates/nuxt/pages/index.vue._eta +101 -0
  78. package/templates/nuxt/pages/profile.vue.eta +94 -0
  79. package/templates/nuxt/plugins/10.simpleapp-event.ts.eta +4 -4
  80. package/templates/nuxt/plugins/20.simpleapp-userstore.ts.eta +11 -10
  81. package/templates/nuxt/simpleapp/generate/clients/SimpleAppClient.ts.eta +69 -17
  82. package/templates/nuxt/simpleapp/generate/commons/documents.ts.eta +6 -3
  83. package/templates/nuxt/tailwind.config.ts._eta +10 -0
  84. package/templates/nuxt/types/documentlist.ts.eta +9 -0
  85. package/templates/nuxt/types/events.ts.eta +20 -0
  86. package/templates/nuxt/types/index.ts.eta +6 -79
  87. package/templates/nuxt/types/notifications.ts.eta +16 -0
  88. package/templates/nuxt/types/others.ts.eta +42 -0
  89. package/templates/nuxt/types/user.ts.eta +44 -0
  90. package/tsconfig.tsbuildinfo +1 -1
  91. package/templates/nest/src/simpleapp/generate/models/perm.model.ts.eta +0 -52
  92. package/templates/nest/src/simpleapp/generate/models/tenant.model.ts.eta +0 -43
  93. package/templates/nest/src/simpleapp/generate/models/user.model.ts.eta +0 -56
  94. package/templates/nuxt/components/EventMonitor.vue.eta +0 -85
  95. package/templates/nuxt/pages/[xorg]/tenant/index.vue.eta +0 -89
  96. package/templates/nuxt/pages/index.vue.eta +0 -116
  97. package/templates/nuxt/simpleapp/generate/commons/events.ts.eta +0 -11
@@ -1,3 +1,4 @@
1
+ <% const skipcolumns = ['_id','createdby','created','updatedby','updated','orgId','branchId','tenantId','doctype'] %>
1
2
  <script setup lang="ts">
2
3
  /**
3
4
  * This file was automatically generated by simpleapp everytime regenerate code.
@@ -6,44 +7,86 @@
6
7
  * last change 2023-09-09
7
8
  * author: Ks Tan
8
9
  */
9
- <% let skipcolumns = ['_id','createdby','created','updatedby','updated','orgId','branchId','tenantId','doctype'] %>
10
- //import {InputTableColumnType,InputTableColumn} from "~/components/type";
11
- import Column from "primevue/column";
12
- const {$<%= it.typename %>Doc } = useNuxtApp();
10
+ import ConfirmPopup from 'primevue/confirmpopup';
11
+ import { useConfirm } from "primevue/useconfirm";
12
+ const confirm = useConfirm();
13
+
14
+ const {$<%= it.typename %>Doc,$event } = useNuxtApp();
13
15
  const doc = $<%= it.typename %>Doc()
14
16
  const data = doc.getReactiveData();
15
- const columns = [
16
- <%Object.keys(it.jsonschema.properties).forEach(function(key) { %>
17
- <%let obj=it.jsonschema.properties[key] %>
18
- <%if(skipcolumns.indexOf(key)>=0){%>/* skip system columns <%=key%>*/
19
- <%} else if(['string','number','integer'].indexOf(obj.type)>=0){%>'<%=key%>',<%}%>
20
- <%})%>
21
- ]
22
- //prepare subtable if exists
23
- /*
24
- <%Object.keys(it.jsonschema.properties).forEach(function(key) { %>
25
- <% let obj=it.jsonschema.properties[key] %>
17
+
18
+ const fetchRecord = async (id:string) =>{
19
+ await doc.getById(id)
20
+ }
21
+ onMounted(()=>{
22
+ const id = String(useRoute().params.id);
23
+ fetchRecord(id);
24
+ })
25
+ const disabled = computed(()=>{
26
+ return false
27
+ })
28
+
29
+ const createData = async () => {
30
+ // disabled.value=true
31
+
32
+ doc.create().then((res)=>{
33
+ //refresh()
34
+ goTo(doc.getDocName(),res.data._id)
35
+ }).catch(err=>{
36
+ console.error(err)
37
+ })
38
+
39
+ };
40
+ const updateData = async () => {
41
+
42
+
43
+ doc.update().then(()=>{
44
+ // visible.value=false
45
+ refresh()
46
+ }).catch(err=>{
47
+ console.error(err)
48
+ })
49
+
50
+ };
51
+ const deleteData = (event:Event) => {
26
52
 
27
- <% if(obj.type=='array' && obj.items.type=='object' && obj.items['properties']){ %>
28
- <%let tablefields = Object.keys(obj.items.properties) %>
29
- const <%=it.name%>_<%=key%> :InputTableColumn[] = [
30
- <% for(let a=0;a<tablefields.length;a++){%>
31
- {type:InputTableColumnType.field, field:'<%= tablefields[a] %>',style:'width:10%'},
32
- <%}%>
33
- ]
34
- <%}%>
35
- <%})%>
36
- */
37
- //end
53
+ confirm.require({
54
+ target: event.currentTarget as HTMLElement,
55
+ message:'Delete?',
56
+ icon: 'pi pi-exclamation-triangle',
57
+ acceptClass: 'p-button-danger',
58
+ accept: ()=>{
59
+ // disabled.value=true
60
+ doc.delete(data.value._id ?? "").then((res) => {
61
+ refresh();
62
+ goTo(doc.getDocName())
63
+ });
64
+ },
65
+ reject: () => {
66
+ console.log("Cancel delete")
67
+ }
68
+ })
69
+ };
70
+ const newData = ()=>{
71
+ goTo(doc.getDocName(),'new')
72
+ }
73
+ const refresh = ()=>{
74
+ $event('RefreshDocumentList',{documentName:doc.getDocName()})
75
+ }
38
76
  </script>
39
77
  <template>
40
- <div>
41
- <CrudSimple :document="doc" title="<%= it.typename %>"
42
- #default="o"
43
- :path="`/${useRoute().params.xorg}/<%= it.name %>`"
44
- :listColumns="columns">
45
-
46
- <%Object.keys(it.jsonschema.properties).forEach(function(key) { %>
78
+ <SimpleAppForm #default="o" :document="doc">
79
+ <div class="simpleapp-tool-bar col-span-4 text-left gap-4" >
80
+ <Button class="" :disabled="disabled" @click="newData" type="button" v-if="canPerform(doc.getDocName(),'create')">New</Button>
81
+ <Button class="bg-primary-600 hover:bg-primary-400 text-white" :disabled="disabled" @click="createData" type="button" v-if="canPerform(doc.getDocName(),'create') && doc.isNew()">Create</Button>
82
+ <Button class="bg-primary-600 hover:bg-primary-400 text-white" :disabled="disabled" @click="updateData" type="button" v-if="canPerform(doc.getDocName(),'update') && !doc.isNew()">Update</Button>
83
+ <Button class="bg-danger-600 hover:bg-danger-400 text-white" :disabled="disabled" @click="deleteData($event)" type="button" v-if="canPerform(doc.getDocName(),'delete') && !doc.isNew()">Delete</Button>
84
+
85
+
86
+ <ProgressSpinner v-if="disabled==true" style="width: 2rem; height: 2rem" ></ProgressSpinner>
87
+ <ConfirmPopup></ConfirmPopup>
88
+ </div>
89
+ <%Object.keys(it.jsonschema.properties).forEach(function(key) { %>
47
90
 
48
91
  <% let obj=it.jsonschema.properties[key] %>
49
92
  <% if(skipcolumns.indexOf(key)>=0){ %>
@@ -177,10 +220,6 @@
177
220
  <!-- Can auto generate <%=obj.key %> -->
178
221
  <!-- <%~ JSON.stringify(obj) %>-->
179
222
  <%}%>
180
- <%})%>
181
-
182
- </CrudSimple>
183
- </div>
184
- </template>
185
-
186
-
223
+ <%})%>
224
+ </SimpleAppForm>
225
+ </template>
@@ -0,0 +1,82 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * This file was automatically generated by simpleapp everytime regenerate code.
4
+ * delete file "delete-me-for-avoid-override" if you want to modify this file and
5
+ * prevent regenerate code override it.
6
+ * last change 2023-09-09
7
+ * author: Ks Tan
8
+ */
9
+ <% const skipcolumns = ['_id','createdby','created','updatedby','updated','orgId','branchId','tenantId','doctype'] %>
10
+ //import {InputTableColumnType,InputTableColumn} from "~/components/type";
11
+ import Column from "primevue/column";
12
+ import MultiTextRender from '~/components/renderers/MultiTextRender.vue'
13
+ import BooleanRender from '~/components/renderers/BooleanRender.vue'
14
+ import DateRender from '~/components/renderers/DateRender.vue'
15
+ import ForeignKeyRender from '~/components/renderers/ForeignKeyRender.vue'
16
+
17
+ const {$<%= it.typename %>Doc } = useNuxtApp();
18
+ const doc = $<%= it.typename %>Doc()
19
+ const data = doc.getReactiveData();
20
+ const visible = ref(false)
21
+
22
+ definePageMeta({
23
+ name: '<%= it.typename %>',
24
+ layout:'documentlist',
25
+ documentName: '<%= it.typename.toLowerCase() %>',
26
+ columns: [<%Object.keys(it.jsonschema.properties).forEach(function(key) { %>
27
+ <%let obj=it.jsonschema.properties[key] %>
28
+ <%if(skipcolumns.indexOf(key)>=0){%>/* skip system columns <%=key%>*/
29
+ <%} else if(['string','number','integer'].indexOf(obj.type)>=0){%>'<%=key%>',
30
+ <%} else if(obj.type =='object' && obj['x-foreignkey'] ){%>
31
+ {
32
+ title:'<%=capitalizeFirstLetter(key)%>',
33
+ field:'<%=key%>',
34
+ component:ForeignKeyRender,
35
+ componentSetting:{collection:'<%=key%>' }
36
+ },
37
+ <%}%>
38
+ <%})%>],
39
+ sorts:[
40
+ <%if(it.jsonschema['x-simpleapp-config'] && it.jsonschema['x-simpleapp-config']['uniqueKey']){%>
41
+ ['<%=it.jsonschema['x-simpleapp-config']['uniqueKey']%>','asc'],
42
+ <%}%>
43
+
44
+ ]
45
+ });
46
+
47
+ const newData = () => {
48
+ doc.setNew()
49
+ goTo(doc.getDocName(),'new')
50
+ visible.value=true
51
+ };
52
+
53
+
54
+ const exitRecord = ()=>{
55
+ goTo(doc.getDocName())
56
+ console.log("exitRecord")
57
+ }
58
+
59
+ watch(()=> useRoute().fullPath ,(newvalue,oldvalue)=>{
60
+ visible.value = useRoute().params.id ? true : false
61
+ })
62
+
63
+ onNuxtReady(()=>{
64
+ visible.value = useRoute().params.id ? true : false;
65
+ })
66
+ </script>
67
+ <template>
68
+ <div>
69
+ <Button class="bg-primary-600 hover:bg-primary-400 text-white" v-if="canPerform(String(useRoute().meta.name),'create')" @click="newData">New</Button>
70
+ <Dialog v-model:visible="visible"
71
+ :pt="{root:{class:'w-full h-full bg-white'}}"
72
+ modal :header="doc.getDocName()"
73
+ :autoZIndex="false"
74
+ @update:visible="exitRecord"
75
+ >
76
+ <NuxtPage />
77
+ </Dialog>
78
+ <!-- -->
79
+ </div>
80
+ </template>
81
+
82
+
@@ -29,3 +29,4 @@ AUTH_SECRET_KEY=<%=it.configs.oauthSetting.oauthAuthSecretKey%>
29
29
 
30
30
  AUTH_ORIGIN=http://localhost:8080
31
31
 
32
+ ADMIN_EMAIL =
@@ -29,7 +29,7 @@ export class SimpleAppExceptionFilter implements ExceptionFilter {
29
29
  const session:ClientSession = request['sessionuser'].getDBSession()
30
30
  if(session.inTransaction())session.abortTransaction()
31
31
  }
32
- console.log('exceptionexception',typeof exception,Object.keys(exception),exception)
32
+ // console.log('exceptionexception',typeof exception,Object.keys(exception),exception)
33
33
  let errordata
34
34
  let finalstatus
35
35
  let msg
@@ -7,7 +7,7 @@
7
7
  import {Role} from './roles.enum'
8
8
 
9
9
  <% Object.getOwnPropertyNames(it.allroles).forEach((key)=>{ %>
10
- export const <%=key%>=[
10
+ export const <%=key%>=()=>[
11
11
  Role.User,
12
12
  <%for(let i=0; i <it.allroles[key].length; i++){%>
13
13
  Role.<%=it.allroles[key][i]%>,
@@ -21,8 +21,10 @@ import { Permission, } from './../types/perm.type';
21
21
  import {ProfileUserBranch , ProfileUserInvites} from '../../profile/profile.types'
22
22
 
23
23
  import {ClientSession} from 'mongoose'
24
- @Injectable()
24
+
25
+ @Injectable({scope:Scope.REQUEST})
25
26
  export class UserContext {
27
+ protected sessionId : string =crypto.randomUUID()
26
28
  protected logger = new Logger()
27
29
  protected uid: string = '';
28
30
  protected _id: string = '';
@@ -42,6 +44,7 @@ export class UserContext {
42
44
  protected orgCode: string = '';
43
45
  protected orgName: string = '';
44
46
  protected branches: any[] = []
47
+ protected lastActivity : string = new Date().toISOString()
45
48
  protected invites: any[] = [] //User + field tenant:Tenant[]
46
49
  protected roles: string[] = [];
47
50
  protected modifiedRecords:ModifiedRecords = {createds:{},updateds:{},deleteds:{}}
@@ -49,7 +52,8 @@ export class UserContext {
49
52
  constructor(
50
53
  private readonly usermodel:Model<User>,
51
54
  private readonly permmodel:Model<Permission>,
52
- private dbsession:ClientSession
55
+ private dbsession:ClientSession,
56
+
53
57
  ) {
54
58
 
55
59
  }
@@ -119,21 +123,19 @@ export class UserContext {
119
123
  */
120
124
  obtainProfileFromDb = async () : Promise<User|undefined>=>{
121
125
  const filter = { $match:{uid:this.uid,tenantId:this.tenantId} }
122
-
123
-
124
-
125
126
 
126
127
  const joinpermission:PipelineStage = {$lookup: {
127
128
  from : 'permission',
128
- localField : 'uid',
129
- foreignField : 'uid',
129
+ localField : '_id',
130
+ foreignField : 'userId',
130
131
  as : 'permissions',
131
132
  pipeline:[
132
- { $match:{
133
- uid:this.uid,
134
- tenantId:this.tenantId,
135
- orgId:this.orgId,
136
- branchId:this.branchId,
133
+ {
134
+ $match:{
135
+ // userId:this.getId(),
136
+ tenantId:this.tenantId,
137
+ orgId:this.orgId,
138
+ branchId:this.branchId,
137
139
  }},
138
140
  {$lookup:{from: 'branch',localField: 'branchId',foreignField:'branchId',as: 'currentbranch'}},
139
141
  {$lookup:{from: 'organization',localField: 'orgId',foreignField:'orgId',as: 'currentorg'}}
@@ -154,22 +156,38 @@ export class UserContext {
154
156
  // console.log("obtainProfileFromDbobtainProfileFromDb ",users)
155
157
  if(users && users.length>0){
156
158
  const userinfo = users[0]
157
- // console.log("userinfouserinfouserinfouserinfouserinfouserinfo ",userinfo)
159
+ console.log("userinfouserinfouserinfouserinfouserinfouserinfo ",userinfo)
158
160
 
159
161
  if(this.tenantId>0){
160
162
  const myperm=userinfo.permissions[0]
161
163
  if(myperm && myperm.group){
162
164
  userinfo.group = myperm.group
163
- userinfo.roles = rolegroups[userinfo.group]
165
+ userinfo.roles = rolegroups[userinfo.group]()
164
166
  userinfo.branchCode = myperm.currentbranch[0].branchCode
165
167
  userinfo.branchName = myperm.currentbranch[0].branchName
166
168
  userinfo.orgCode = myperm.currentorg[0].orgCode
167
169
  userinfo.orgName = myperm.currentorg[0].orgName
170
+
168
171
  }
169
172
  }else{
170
173
  userinfo.group = ''
171
174
  }
175
+ console.log('userinfouserinfouserinfouserinfo',userinfo)
176
+ const currentitme = new Date(this.lastActivity).getTime()
177
+ console.log(" userinfo.lastactivity userinfo.lastactivity userinfo.lastactivity ", userinfo.lastActivity )
178
+ const dblastactivity = userinfo.lastActivity ?? '2000-01-01T00:00:00Z'
179
+ const lastvisit = new Date( dblastactivity).getTime() ?? 0
180
+ // if(currentitme - lastvisit)
181
+ console.log(`${userinfo._id}: ${this.lastActivity}: ${currentitme} - ${dblastactivity}:${lastvisit} = ${currentitme - lastvisit}`)
182
+
183
+ //update last activtity dont too frequent
184
+ if(!dblastactivity || currentitme - lastvisit > 5000 ){
185
+ const newusermodel = await this.usermodel.findById(userinfo._id)
186
+ newusermodel.lastActivity= this.lastActivity
187
+ const result = await newusermodel.save()
188
+ }
172
189
 
190
+ // const result = await this.usermodel.findOneAndUpdate({_id: userinfo._id},{lastActivity: new Date().toISOString})
173
191
  return userinfo
174
192
  }else{
175
193
  return undefined
@@ -200,7 +218,7 @@ export class UserContext {
200
218
  this.orgCode = userinfo['orgCode'] ?? ''
201
219
  this.orgName = userinfo['orgName'] ?? ''
202
220
  this.group = userinfo['group'] ?? ''
203
- this.roles = userinfo['roles'] ?? [Role.Everyone,Role.User,Role.SuperAdmin]
221
+ this.roles = userinfo['roles'] ?? [Role.Everyone,Role.User]
204
222
  }else{
205
223
  this.logger.debug(`Set unknown id of current user`,'setUserToken' )
206
224
  // this.group = ''
@@ -291,6 +309,7 @@ export class UserContext {
291
309
  // obtain basic user info
292
310
  const userinfo = {
293
311
  _id: this.getId() ,
312
+ sessionId:this.sessionId,
294
313
  tenantId: this.getTenantId(),
295
314
  orgId: this.getOrgId(),
296
315
  branchId: this.getBranchId(),
@@ -310,14 +329,17 @@ export class UserContext {
310
329
 
311
330
  if(this.getId()!=''){
312
331
  this.logger.debug(userinfo,"obtain permissions and invitations")
313
- const filter:PipelineStage ={ $match:{uid:this.uid }} as PipelineStage
332
+ const filter:PipelineStage ={ $match:{
333
+ uid:this.uid,
334
+ tenantId :this.tenantId
335
+ }} as PipelineStage
314
336
  const permission:PipelineStage = {$lookup: {
315
337
  from : 'permission',
316
- localField : 'uid',
317
- foreignField : 'uid',
338
+ localField : '_id',
339
+ foreignField : 'userId',
318
340
  as : 'permissions',
319
341
  pipeline:[
320
- {$match:{uid: this.uid,},},
342
+ // {$match:{userId: this.getId(),},},
321
343
  {$lookup:{from : 'branch',localField : 'branchId',foreignField : 'branchId',as : 'branch',}},
322
344
  ]
323
345
  }}
@@ -340,6 +362,7 @@ export class UserContext {
340
362
  this.logger.debug(pipeline,"getUserInfo")
341
363
  // // // const users = await usermodel.find(filter)
342
364
  const users = await this.usermodel.aggregate(pipeline)
365
+ this.logger.debug(users,'users from aggregate')
343
366
 
344
367
 
345
368
  this.invites = users[0].invites
@@ -388,11 +411,13 @@ export class UserContext {
388
411
  const o = this.ssoACL
389
412
  const ssoclient = process.env.OAUTH2_CLIENTID
390
413
  const adminRole = process.env.OAUTH2_ADMINROLE
391
- if( o[ssoclient] && o[ssoclient]['roles'] && o[ssoclient]['roles'] == adminRole ){
392
- //console.log("isadmin")
414
+ // return false
415
+ if(this.getEmail()===process.env.ADMIN_EMAIL){
416
+ return true
417
+ }
418
+ else if( o[ssoclient] && o[ssoclient]['roles'] && o[ssoclient]['roles'] == adminRole ){
393
419
  return true
394
420
  }else{
395
- //console.log("not admin")
396
421
  return false
397
422
  }
398
423
 
@@ -425,4 +450,84 @@ export class UserContext {
425
450
  }
426
451
 
427
452
  }
453
+
454
+
455
+ async getAllTenants (){
456
+ const results = []
457
+ if(this.getId()!=''){
458
+ const filteruser:PipelineStage ={ $match:{
459
+ uid:this.uid,
460
+ tenantId :{'$gt':0}
461
+ }} as PipelineStage
462
+
463
+ const getTenantData:PipelineStage = { $lookup:{
464
+ from : 'tenant',
465
+ localField : 'tenantId',
466
+ foreignField : 'tenantId',
467
+ as : 'tenant',}}
468
+
469
+ const permission:PipelineStage = {$lookup: {
470
+ from : 'permission',
471
+ localField : '_id',
472
+ foreignField : 'userId',
473
+ as : 'permissions',
474
+ pipeline:[
475
+
476
+ {$lookup:{from : 'organization',localField : 'orgId',foreignField : 'orgId',as : 'org',}},
477
+ {$lookup:{from : 'branch',localField : 'branchId',foreignField : 'branchId',as : 'branch',}},
478
+ ]
479
+ }}
480
+
481
+ const pipelines:PipelineStage[] =[filteruser,getTenantData,permission]
482
+ // const users=[]
483
+ this.logger.warn(pipelines,"pipelines")
484
+ const users = await this.usermodel.aggregate(pipelines)
485
+
486
+ if(users){
487
+
488
+
489
+ const activeusers = users.filter((u)=>{
490
+ // console.log(u.active,'===',true, ' && ',u.tenant[0].active,'===',true)
491
+ return u.active===true && u.tenant[0].active===true
492
+ })
493
+ // return activeusers
494
+ activeusers.forEach((u)=>{
495
+
496
+ const permissions = u.permissions.filter((item:any)=>{
497
+ return item.org[0].active && item.branch[0].active
498
+ })
499
+ .map((item:any)=>{
500
+
501
+ return {
502
+ _id: item._id,
503
+ orgId: item.orgId,
504
+ branchId: item.branchId,
505
+ group: item.group,
506
+ orgCode: item.org[0].orgCode,
507
+ orgName: item.org[0].orgName,
508
+ branchCode: item.branch[0].branchCode,
509
+ branchName: item.branch[0].branchName,
510
+ xOrg: this.generateXorg(u.tenantId,item.orgId,item.branchId)
511
+ }
512
+ })
513
+
514
+
515
+
516
+
517
+ results.push({
518
+ _id: u._id,
519
+ fullname : u.fullname,
520
+ tenantId: u.tenantId,
521
+ tenantName: u.tenant[0].tenantName,
522
+ permissions: permissions
523
+ })
524
+ })
525
+
526
+ }
527
+
528
+
529
+
530
+ }
531
+ return results
532
+ }
428
533
  }
@@ -236,7 +236,7 @@ export class SimpleAppService<T extends { _id?: string }> {
236
236
  await this.hook(appuser,HookType.beforeSearch, newfilters);
237
237
  // console.log("before _find",newfilters)
238
238
  // console.log("this.doc",this.doc)
239
- const products = await this.doc.find(newfilters,projection).sort(sort);
239
+ const products = await this.doc.find(newfilters,projection,{session:appuser.getDBSession()}).sort(sort);
240
240
  // console.log("after search",products)
241
241
  const productlist = products.map((p: T) => {
242
242
  return p;
@@ -67,6 +67,31 @@ export class ProfileController {
67
67
  }
68
68
  }
69
69
 
70
+ @Get('/tenants')
71
+ @Roles(Role.Everyone, Role.User)
72
+ @ApiOperation({
73
+ operationId: 'getAllTenants',
74
+ description: 'Get all tenants',
75
+ })
76
+ @ApiResponse({
77
+ status: 200,
78
+ type: () => [MyProfileApiSchema],
79
+ description: 'Success',
80
+ })
81
+ @ApiResponse({ status: 401, type: Object, description: 'Undefine profile' })
82
+ async getAllTenants(@AppUser() appuser: UserContext) {
83
+ this.logger.debug(
84
+ `access getAllTenants API by ${appuser.getUid()},(${appuser.getId()})`,
85
+ );
86
+ const result = await this.profileservice.getAllTenants(appuser);
87
+ this.logger.debug('getProfile result is:');
88
+ this.logger.debug(result);
89
+ if (result) {
90
+ return result;
91
+ } else {
92
+ throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
93
+ }
94
+ }
70
95
 
71
96
  @Post('/tenant')
72
97
  @Roles(Role.Everyone)
@@ -106,10 +131,8 @@ export class ProfileController {
106
131
  decision,
107
132
  );
108
133
  if (result) {
109
- console.log('result', result);
110
134
  return result;
111
135
  } else {
112
- console.log('throw error');
113
136
  throw new HttpException('Forbidden', HttpStatus.FORBIDDEN);
114
137
  }
115
138
  }
@@ -74,7 +74,11 @@ export class ProfileService {
74
74
  active: true,
75
75
  doctype: 'user',
76
76
  } as User;
77
-
77
+ if (appuser.getTenantId() == 0) {
78
+ data.tenantId = 0;
79
+ data.orgId = 0;
80
+ data.branchId = 0;
81
+ }
78
82
  const createresult = await this.usersvc.create(appuser, data);
79
83
  const userinfo = await appuser.getUserInfo();
80
84
  userinfo._id = createresult._id;
@@ -161,7 +165,7 @@ export class ProfileService {
161
165
  orgId: orgResult.orgId,
162
166
  branchId: branchResult.branchId,
163
167
  uid: appuser.getUid(),
164
- user_id: appuser.getId(),
168
+ userId: userRecordId,
165
169
  group: 'admin',
166
170
  };
167
171
  this.logger.log(permdata, 'create Permission data');
@@ -172,6 +176,16 @@ export class ProfileService {
172
176
 
173
177
  this.logger.log(permResult, 'create Permission result');
174
178
 
179
+
180
+ //tenant owner shall map to userId for that tenant
181
+
182
+ const tenantUpdateData = await this.tenantsvc.findById(appuser,tenantResult._id)
183
+ this.logger.log(tenantUpdateData, `update tenant owner(${tenantResult._id})`);
184
+ tenantUpdateData.owner._id = userRecordId
185
+ const updateTenantOwnerResult = await this.tenantsvc.findIdThenUpdate(appuser,tenantResult._id,tenantUpdateData)
186
+ if (!updateTenantOwnerResult) {
187
+ throw new BadRequestException('Update tenant owner failed');
188
+ }
175
189
  const xorg: string = Base64URL.encodeText(
176
190
  `${tenantResult.tenantId}-${orgResult.orgId}-${branchResult.branchId}`,
177
191
  );
@@ -197,4 +211,8 @@ export class ProfileService {
197
211
  async decideInvitation(appuser: UserContext, id: string, decision: string) {
198
212
  return await appuser.decideInvitation(id, decision);
199
213
  }
214
+
215
+ async getAllTenants(appuser: UserContext) {
216
+ return await appuser.getAllTenants();
217
+ }
200
218
  }