cob-cli 2.8.0 → 2.11.0
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/customizations/dashboard.dash.js +11 -0
- package/customizations/dashboard.js +1 -0
- package/customizations/dashboard.simple.js +1 -1
- package/customizations/dashboard.vue.empty.js +1 -1
- package/customizations/frontend.easy.js +16 -0
- package/lib/task_lists/customize_copy.js +7 -6
- package/package.json +1 -1
- package/templates/{cob-dashboard-html → dashboards/cob-dashboard-html}/demoDashboard.html +0 -0
- package/templates/{cob-dashboard-vue → dashboards/cob-dashboard-vue}/package-lock.json +0 -0
- package/templates/{cob-dashboard-vue → dashboards/cob-dashboard-vue}/package.json +0 -0
- package/templates/{cob-dashboard-vue → dashboards/cob-dashboard-vue}/src/App.vue +0 -0
- package/templates/{cob-dashboard-vue → dashboards/cob-dashboard-vue}/src/dashboard.html +0 -0
- package/templates/{cob-dashboard-vue → dashboards/cob-dashboard-vue}/src/main.js +0 -0
- package/templates/{cob-dashboard-vue → dashboards/cob-dashboard-vue}/src/plugins/cobUiVueComponents.js +0 -0
- package/templates/{cob-dashboard-vue → dashboards/cob-dashboard-vue}/src/plugins/vuetify.js +0 -0
- package/templates/{cob-dashboard-vue → dashboards/cob-dashboard-vue}/vue.config.js +0 -0
- package/templates/dashboards/dash/dist/css/app.3140d0d1.css +8 -0
- package/templates/dashboards/dash/dist/dashboard.html +20 -0
- package/templates/dashboards/dash/dist/fonts/fa-brands-400.a78ffbbe.ttf +0 -0
- package/templates/dashboards/dash/dist/fonts/fa-brands-400.cd2b4095.woff2 +0 -0
- package/templates/dashboards/dash/dist/fonts/fa-regular-400.b1a1bebb.ttf +0 -0
- package/templates/dashboards/dash/dist/fonts/fa-regular-400.e8a1ba41.woff2 +0 -0
- package/templates/dashboards/dash/dist/fonts/fa-solid-900.55b416a8.woff2 +0 -0
- package/templates/dashboards/dash/dist/fonts/fa-solid-900.73820155.ttf +0 -0
- package/templates/dashboards/dash/dist/fonts/fa-v4compatibility.0d6f5f18.ttf +0 -0
- package/templates/dashboards/dash/dist/fonts/fa-v4compatibility.786e6b33.woff2 +0 -0
- package/templates/dashboards/dash/dist/js/app.a65a4c2c.js +188 -0
- package/templates/dashboards/dash/dist/js/app.a65a4c2c.js.map +1 -0
- package/templates/dashboards/dash/package-lock.json +24340 -0
- package/templates/dashboards/dash/package.json +19 -0
- package/templates/dashboards/dash/src/App.vue +257 -0
- package/templates/dashboards/dash/src/Dashboard.vue +46 -0
- package/templates/dashboards/dash/src/assets/css/all.min.css +6 -0
- package/templates/dashboards/dash/src/assets/webfonts/fa-brands-400.ttf +0 -0
- package/templates/dashboards/dash/src/assets/webfonts/fa-brands-400.woff2 +0 -0
- package/templates/dashboards/dash/src/assets/webfonts/fa-regular-400.ttf +0 -0
- package/templates/dashboards/dash/src/assets/webfonts/fa-regular-400.woff2 +0 -0
- package/templates/dashboards/dash/src/assets/webfonts/fa-solid-900.ttf +0 -0
- package/templates/dashboards/dash/src/assets/webfonts/fa-solid-900.woff2 +0 -0
- package/templates/dashboards/dash/src/assets/webfonts/fa-v4compatibility.ttf +0 -0
- package/templates/dashboards/dash/src/assets/webfonts/fa-v4compatibility.woff2 +0 -0
- package/templates/dashboards/dash/src/collector.js +3782 -0
- package/templates/dashboards/dash/src/components/Board.vue +61 -0
- package/templates/dashboards/dash/src/components/BoardsNav.vue +23 -0
- package/templates/dashboards/dash/src/components/BoardsPage.vue +36 -0
- package/templates/dashboards/dash/src/components/Menu.vue +19 -0
- package/templates/dashboards/dash/src/components/Title.vue +13 -0
- package/templates/dashboards/dash/src/components/Totals.vue +53 -0
- package/templates/dashboards/dash/src/components/TotalsBadge.vue +69 -0
- package/templates/dashboards/dash/src/dashboard.html +34 -0
- package/templates/dashboards/dash/src/input.css +9 -0
- package/templates/dashboards/dash/src/main.js +11 -0
- package/templates/dashboards/dash/src/output.css +45836 -0
- package/templates/dashboards/dash/tailwind.config.js +18 -0
- package/templates/dashboards/dash/vue.config.js +104 -0
- package/templates/frontend/common/css/_dashboard.css +7 -0
- package/templates/frontend/common/css/_global.css +3 -1
- package/templates/frontend/easy/css/_easy/googlefonts.css +360 -0
- package/templates/frontend/easy/css/_easy/vuetify.cob-scoped.css +10488 -0
- package/templates/frontend/easy/js/_easy/lib/axios.min.js +9 -0
- package/templates/frontend/easy/js/_easy/lib/marked.min.js +6 -0
- package/templates/frontend/easy/js/_easy/lib/vue.js +11912 -0
- package/templates/frontend/easy/js/_easy/lib/vue.min.js +6 -0
- package/templates/frontend/easy/js/_easy/lib/vuetify.min.js +6 -0
- package/templates/frontend/easy/js/customizations2.__MERGE__.js +22 -0
- package/templates/frontend/easy/webapp/.browserslistrc +2 -0
- package/templates/frontend/easy/webapp/.eslintrc.js +17 -0
- package/templates/frontend/easy/webapp/README.md +60 -0
- package/templates/frontend/easy/webapp/babel.config.js +5 -0
- package/templates/frontend/easy/webapp/dist/css/app.a4fb91f8.css +1 -0
- package/templates/frontend/easy/webapp/dist/dashboard.html +13 -0
- package/templates/frontend/easy/webapp/dist/js/app.63a57dcd.js +2 -0
- package/templates/frontend/easy/webapp/dist/js/app.63a57dcd.js.map +1 -0
- package/templates/frontend/easy/webapp/package-lock.json +32986 -0
- package/templates/frontend/easy/webapp/package.json +32 -0
- package/templates/frontend/easy/webapp/postcss.config.js +5 -0
- package/templates/frontend/easy/webapp/public/dashboard.html +13 -0
- package/templates/frontend/easy/webapp/src/App.vue +181 -0
- package/templates/frontend/easy/webapp/src/assets/logo.png +0 -0
- package/templates/frontend/easy/webapp/src/components/HelloWorld.vue +59 -0
- package/templates/frontend/easy/webapp/src/components/PermBuilder.vue +163 -0
- package/templates/frontend/easy/webapp/src/components/PlanExecutor.vue +225 -0
- package/templates/frontend/easy/webapp/src/components/ProductPermBuilder.vue +95 -0
- package/templates/frontend/easy/webapp/src/components/RmDefinitionChooser.vue +59 -0
- package/templates/frontend/easy/webapp/src/components/RmDomainChooser.vue +60 -0
- package/templates/frontend/easy/webapp/src/components/RoleBuilder.vue +73 -0
- package/templates/frontend/easy/webapp/src/main.js +19 -0
- package/templates/frontend/easy/webapp/src/perm-templates.js +189 -0
- package/templates/frontend/easy/webapp/src/perms.js +197 -0
- package/templates/frontend/easy/webapp/vue.config.js +66 -0
- package/templates/keywords/audit/frontend/js/cob/_audit.js +4 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "userm-easy",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"scripts": {
|
|
6
|
+
"serve": "vue-cli-service serve",
|
|
7
|
+
"build": "vue-cli-service build",
|
|
8
|
+
"lint": "vue-cli-service lint",
|
|
9
|
+
"dist": "rsync -av --delete dist/* -e ssh $npm_package_config_remote_server:/etc/userm/customUI/$npm_package_config_dash_dir/dist/"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@cob/ui-vue-components": "^2.x",
|
|
13
|
+
"core-js": "^2.6.5",
|
|
14
|
+
"vue": "^2.6.10"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@cob/vue-cli-plugin-dashboard": "latest",
|
|
18
|
+
"@vue/cli-plugin-babel": "^3.12.0",
|
|
19
|
+
"@vue/cli-plugin-eslint": "^3.12.0",
|
|
20
|
+
"@vue/cli-service": "^3.12.0",
|
|
21
|
+
"babel-eslint": "^10.0.1",
|
|
22
|
+
"eslint": "^5.16.0",
|
|
23
|
+
"eslint-plugin-vue": "^5.0.0",
|
|
24
|
+
"stylus": "^0.54.0",
|
|
25
|
+
"stylus-loader": "^3.0.0",
|
|
26
|
+
"vue-template-compiler": "^2.6.10"
|
|
27
|
+
},
|
|
28
|
+
"config": {
|
|
29
|
+
"remote_server": "dogfooding.cultofbits.com",
|
|
30
|
+
"dash_dir": "easy"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<% for (var css in htmlWebpackPlugin.files.css) { %>
|
|
2
|
+
<link href="<%= htmlWebpackPlugin.files.css[css] %>" rel="stylesheet">
|
|
3
|
+
<% } %>
|
|
4
|
+
|
|
5
|
+
<div id="userm-easy"></div>
|
|
6
|
+
|
|
7
|
+
<script>
|
|
8
|
+
cob.utils.afterDeps([ 'Vue', 'Vuetify', 'axios', 'marked' ], function() {
|
|
9
|
+
<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
|
|
10
|
+
cob.utils.loadScript('<%=htmlWebpackPlugin.files.chunks[chunk].entry%>');
|
|
11
|
+
<% } %>
|
|
12
|
+
})
|
|
13
|
+
</script>
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-app>
|
|
3
|
+
<v-container fluid grid-list-sm>
|
|
4
|
+
|
|
5
|
+
<v-layout row wrap>
|
|
6
|
+
<v-flex m12 xs12>
|
|
7
|
+
<h3 style="text-align:center;margin-top:10px;">Easy Perms</h3>
|
|
8
|
+
</v-flex>
|
|
9
|
+
|
|
10
|
+
<v-flex md3 sm6 xs12>
|
|
11
|
+
<v-switch v-model="showTemplates" label="Templates" hide-details></v-switch>
|
|
12
|
+
</v-flex>
|
|
13
|
+
<v-flex md3 sm6 xs12>
|
|
14
|
+
<v-switch v-model="showBuilder" label="Builder" hide-details></v-switch>
|
|
15
|
+
</v-flex>
|
|
16
|
+
<v-flex md3 sm6 xs12>
|
|
17
|
+
<v-switch v-model="showPlan" label="Plan" hide-details></v-switch>
|
|
18
|
+
</v-flex>
|
|
19
|
+
<v-flex md3 sm6 xs12>
|
|
20
|
+
<v-switch v-model="debug" label="debug" hide-details></v-switch>
|
|
21
|
+
</v-flex>
|
|
22
|
+
</v-layout>
|
|
23
|
+
|
|
24
|
+
<v-layout v-if="showTemplates" row wrap>
|
|
25
|
+
|
|
26
|
+
<!-- Seleccionar template -->
|
|
27
|
+
<v-flex xs12>
|
|
28
|
+
<v-select :items="permTemplates"
|
|
29
|
+
v-model="selectedTemplate"
|
|
30
|
+
item-text="name" return-object
|
|
31
|
+
label="Escolha um template" clearable dense solo></v-select>
|
|
32
|
+
</v-flex>
|
|
33
|
+
|
|
34
|
+
<!-- Template -->
|
|
35
|
+
<v-layout xs12 column v-if="selectedTemplate">
|
|
36
|
+
<v-flex xs12 v-if="debug">
|
|
37
|
+
{{ selectedTemplate }}
|
|
38
|
+
</v-flex>
|
|
39
|
+
|
|
40
|
+
<v-layout xs12 row wrap align-center
|
|
41
|
+
v-for="tmplVar in selectedTemplate.vars"
|
|
42
|
+
v-bind:key="tmplVar.name">
|
|
43
|
+
<v-flex md2 sm3 xs12>{{ tmplVar.name }} : {{ tmplVar.type }}</v-flex>
|
|
44
|
+
<v-flex md10 sm9 xs12>
|
|
45
|
+
<v-text-field v-if="tmplVar.type === 'simple'"
|
|
46
|
+
v-model="tmplVar.value"></v-text-field>
|
|
47
|
+
<RmDefinitionChooser v-if="tmplVar.type === 'RM-DEF'"
|
|
48
|
+
v-model="tmplVar.value"></RmDefinitionChooser>
|
|
49
|
+
<RmDomainChooser v-if="tmplVar.type === 'RM-DOMAIN-ID'"
|
|
50
|
+
v-model="tmplVar.value"></RmDomainChooser>
|
|
51
|
+
</v-flex>
|
|
52
|
+
</v-layout>
|
|
53
|
+
</v-layout>
|
|
54
|
+
|
|
55
|
+
<v-flex xs12>
|
|
56
|
+
<v-btn color="primary"
|
|
57
|
+
:disabled="selectedTemplate == null"
|
|
58
|
+
v-on:click="applyTemplate">Apply Template</v-btn>
|
|
59
|
+
</v-flex>
|
|
60
|
+
</v-layout>
|
|
61
|
+
|
|
62
|
+
<!-- Builder -->
|
|
63
|
+
<v-flex xs12 v-if="showBuilder">
|
|
64
|
+
<ProductPermBuilder :perms="perms" :debug="debug" v-model="rmPerms"/>
|
|
65
|
+
</v-flex>
|
|
66
|
+
|
|
67
|
+
<v-flex md1 xs12 v-if="showBuilder">
|
|
68
|
+
<v-btn color="primary" v-on:click="plan">Planear</v-btn>
|
|
69
|
+
</v-flex>
|
|
70
|
+
|
|
71
|
+
<!-- Creator -->
|
|
72
|
+
<PlanExecutor v-if="showPlan" :value="rmPerms" :debug="debug"></PlanExecutor>
|
|
73
|
+
</v-container>
|
|
74
|
+
|
|
75
|
+
</v-app>
|
|
76
|
+
</template>
|
|
77
|
+
|
|
78
|
+
<script>
|
|
79
|
+
import ProductPermBuilder from './components/ProductPermBuilder.vue';
|
|
80
|
+
import RmDefinitionChooser from './components/RmDefinitionChooser.vue';
|
|
81
|
+
import RmDomainChooser from './components/RmDomainChooser.vue';
|
|
82
|
+
import PlanExecutor from './components/PlanExecutor.vue';
|
|
83
|
+
|
|
84
|
+
import permTemplates from './perm-templates.js';
|
|
85
|
+
import perms from './perms.js';
|
|
86
|
+
|
|
87
|
+
const applyAllSubstitutions = function(value, subs){
|
|
88
|
+
return subs.reduce(
|
|
89
|
+
(acc, curr) => {
|
|
90
|
+
// verdade para entidades complexas como Defs, Domains, etc...
|
|
91
|
+
if(typeof curr.value === 'object'){
|
|
92
|
+
acc = acc.replace(`$$${curr.name}.ID$$`, curr.value.id)
|
|
93
|
+
acc = acc.replace(`$$${curr.name}.NAME$$`, curr.value.name)
|
|
94
|
+
} else {
|
|
95
|
+
acc = acc.replace(`$$${curr.name}$$`, curr.value)
|
|
96
|
+
}
|
|
97
|
+
return acc;
|
|
98
|
+
} ,
|
|
99
|
+
value
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export default {
|
|
104
|
+
name: 'app',
|
|
105
|
+
components: {
|
|
106
|
+
ProductPermBuilder,
|
|
107
|
+
RmDomainChooser,
|
|
108
|
+
RmDefinitionChooser,
|
|
109
|
+
PlanExecutor
|
|
110
|
+
},
|
|
111
|
+
data() {
|
|
112
|
+
return {
|
|
113
|
+
debug: false,
|
|
114
|
+
showTemplates: false,
|
|
115
|
+
showBuilder: true,
|
|
116
|
+
showPlan: false,
|
|
117
|
+
|
|
118
|
+
permTemplates: permTemplates,
|
|
119
|
+
selectedTemplate: null,
|
|
120
|
+
|
|
121
|
+
perms: perms,
|
|
122
|
+
|
|
123
|
+
rmPerms: {
|
|
124
|
+
product: "recordm",
|
|
125
|
+
perms: [
|
|
126
|
+
{ name: "", description: ''}
|
|
127
|
+
],
|
|
128
|
+
roles: [ ]
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
methods: {
|
|
134
|
+
applyTemplate: function(){
|
|
135
|
+
// todo jone tornar isto num ciclo
|
|
136
|
+
const vars = this.selectedTemplate.vars
|
|
137
|
+
const newPerms = JSON.parse(JSON.stringify(this.selectedTemplate.productPerms[0]))
|
|
138
|
+
|
|
139
|
+
newPerms.perms = newPerms.perms.map(p => ({
|
|
140
|
+
name: applyAllSubstitutions(p.name, vars),
|
|
141
|
+
description: applyAllSubstitutions(p.description, vars)
|
|
142
|
+
}))
|
|
143
|
+
|
|
144
|
+
newPerms.roles = newPerms.roles.map(r => ({
|
|
145
|
+
name: applyAllSubstitutions(r.name, vars),
|
|
146
|
+
description: applyAllSubstitutions(r.description, vars),
|
|
147
|
+
perms: r.perms.map(p => applyAllSubstitutions(p, vars))
|
|
148
|
+
}))
|
|
149
|
+
|
|
150
|
+
this.rmPerms = newPerms
|
|
151
|
+
|
|
152
|
+
this.showTemplates = false;
|
|
153
|
+
this.showBuilder = true;
|
|
154
|
+
},
|
|
155
|
+
|
|
156
|
+
plan() {
|
|
157
|
+
this.showBuilder = false;
|
|
158
|
+
this.showPlan = true;
|
|
159
|
+
},
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
</script>
|
|
163
|
+
|
|
164
|
+
<style>
|
|
165
|
+
#app {
|
|
166
|
+
font-family: 'Avenir', Helvetica, Arial, sans-serif;
|
|
167
|
+
-webkit-font-smoothing: antialiased;
|
|
168
|
+
-moz-osx-font-smoothing: grayscale;
|
|
169
|
+
//text-align: center;
|
|
170
|
+
color: #2c3e50;
|
|
171
|
+
font-size: 1.2em;
|
|
172
|
+
}
|
|
173
|
+
#app .v-input input,
|
|
174
|
+
#app .v-input textarea,
|
|
175
|
+
#app .v-input .v-select__selection {
|
|
176
|
+
font-size: 0.9em;
|
|
177
|
+
min-height: fit-content;
|
|
178
|
+
}
|
|
179
|
+
</style>
|
|
180
|
+
|
|
181
|
+
<!-- vim: set sw=2 ts=2 et : -->
|
|
Binary file
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="hello">
|
|
3
|
+
<h1>{{ msg }}</h1>
|
|
4
|
+
<p>
|
|
5
|
+
For a guide and recipes on how to configure / customize this project,<br>
|
|
6
|
+
check out the
|
|
7
|
+
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
|
8
|
+
</p>
|
|
9
|
+
<h3>Installed CLI Plugins</h3>
|
|
10
|
+
<ul>
|
|
11
|
+
<li><a href="https://www.npmjs.com/package/@cob%2Fvue-cli-plugin-dashboard" target="_blank" rel="noopener">dashboard</a></li>
|
|
12
|
+
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
|
|
13
|
+
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
|
|
14
|
+
</ul>
|
|
15
|
+
<h3>Essential Links</h3>
|
|
16
|
+
<ul>
|
|
17
|
+
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
|
18
|
+
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
|
19
|
+
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
|
20
|
+
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
|
21
|
+
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
|
22
|
+
</ul>
|
|
23
|
+
<h3>Ecosystem</h3>
|
|
24
|
+
<ul>
|
|
25
|
+
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
|
26
|
+
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
|
27
|
+
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
|
28
|
+
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
|
29
|
+
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
|
30
|
+
</ul>
|
|
31
|
+
</div>
|
|
32
|
+
</template>
|
|
33
|
+
|
|
34
|
+
<script>
|
|
35
|
+
export default {
|
|
36
|
+
name: 'HelloWorld',
|
|
37
|
+
props: {
|
|
38
|
+
msg: String
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
44
|
+
<style scoped>
|
|
45
|
+
h3 {
|
|
46
|
+
margin: 40px 0 0;
|
|
47
|
+
}
|
|
48
|
+
ul {
|
|
49
|
+
list-style-type: none;
|
|
50
|
+
padding: 0;
|
|
51
|
+
}
|
|
52
|
+
li {
|
|
53
|
+
display: inline-block;
|
|
54
|
+
margin: 0 10px;
|
|
55
|
+
}
|
|
56
|
+
a {
|
|
57
|
+
color: #42b983;
|
|
58
|
+
}
|
|
59
|
+
</style>
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-layout column>
|
|
3
|
+
<v-layout row wrap>
|
|
4
|
+
|
|
5
|
+
<v-flex sm3 xs12>
|
|
6
|
+
<v-combobox v-model="domain" :items="selectableDomains" @change="actions = []"
|
|
7
|
+
label="Domain" dense clearable></v-combobox>
|
|
8
|
+
</v-flex>
|
|
9
|
+
|
|
10
|
+
<v-flex sm4 xs12>
|
|
11
|
+
<v-combobox v-model="actions" :items="selectableActions" @change="entities = []"
|
|
12
|
+
label="Action" dense multiple clearable></v-combobox>
|
|
13
|
+
</v-flex>
|
|
14
|
+
|
|
15
|
+
<v-flex sm5 xs12>
|
|
16
|
+
<v-combobox v-if="!customEntityType" v-model="entities" :items="selectableEntities"
|
|
17
|
+
label="Entity" dense multiple clearable></v-combobox>
|
|
18
|
+
<RmDomainChooser v-if="customEntityType === 'RM-DOMAIN-ID'"
|
|
19
|
+
v-model="customEntity"></RmDomainChooser>
|
|
20
|
+
<RmDefinitionChooser v-if="customEntityType === 'RM-DEF'"
|
|
21
|
+
v-model="customEntity"></RmDefinitionChooser>
|
|
22
|
+
</v-flex>
|
|
23
|
+
</v-layout>
|
|
24
|
+
|
|
25
|
+
<v-flex xs12>
|
|
26
|
+
<v-textarea md3 v-model="description"
|
|
27
|
+
label="Description" rows="1" auto-grow></v-textarea>
|
|
28
|
+
</v-flex>
|
|
29
|
+
|
|
30
|
+
<v-layout v-if="debug" row wrap>
|
|
31
|
+
<v-flex sm2 xs12>
|
|
32
|
+
domain: {{ domain }}
|
|
33
|
+
</v-flex>
|
|
34
|
+
|
|
35
|
+
<v-flex sm4 xs12 style="background-color: #efe">
|
|
36
|
+
actions: {{ actions }}
|
|
37
|
+
</v-flex>
|
|
38
|
+
|
|
39
|
+
<v-flex sm3 xs12>
|
|
40
|
+
entities: {{ customEntityType ? "custom" : "normal" }} {{ customEntityType ? customEntity : entities }}
|
|
41
|
+
</v-flex>
|
|
42
|
+
|
|
43
|
+
</v-layout>
|
|
44
|
+
|
|
45
|
+
<!-- needed to force de compute and emit of the resulting perm -->
|
|
46
|
+
<span style="display:none">{{ resultingPerm }}</span>
|
|
47
|
+
</v-layout>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<script>
|
|
51
|
+
|
|
52
|
+
import RmDomainChooser from './RmDomainChooser.vue'
|
|
53
|
+
import RmDefinitionChooser from './RmDefinitionChooser.vue'
|
|
54
|
+
|
|
55
|
+
export default {
|
|
56
|
+
name: 'PermBuilder',
|
|
57
|
+
|
|
58
|
+
components: {
|
|
59
|
+
RmDomainChooser, RmDefinitionChooser
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
props: {
|
|
63
|
+
perms: Array,
|
|
64
|
+
value: Object,
|
|
65
|
+
debug: Boolean
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
data() {
|
|
69
|
+
const components = this.value.name.split(":");
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
domain: components[0] || '',
|
|
73
|
+
components: components,
|
|
74
|
+
actions: components.length > 1 ? components[1].split(',') : [],
|
|
75
|
+
entities: components.length > 2 ? components[2].split(',') : []
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
computed: {
|
|
80
|
+
|
|
81
|
+
selectableDomains: function(){
|
|
82
|
+
return this.perms.map(d => d.domain);
|
|
83
|
+
},
|
|
84
|
+
selectableActions: function(){
|
|
85
|
+
const selectedDomain = this.perms.find(d => d.domain === this.domain)
|
|
86
|
+
const domainActions = ( selectedDomain || {} ).actions || [];
|
|
87
|
+
return domainActions.map(a => a.name);
|
|
88
|
+
},
|
|
89
|
+
customEntityType() {
|
|
90
|
+
const selectedDomain = this.perms.find(d => d.domain === this.domain)
|
|
91
|
+
if(typeof selectedDomain === 'undefined' ) return false;
|
|
92
|
+
|
|
93
|
+
const entities = selectedDomain.actions
|
|
94
|
+
.filter(a => this.actions.includes(a.name))
|
|
95
|
+
.flatMap(a => (a.entities || []) )
|
|
96
|
+
|
|
97
|
+
return entities.length > 0 && entities[0].type
|
|
98
|
+
},
|
|
99
|
+
customEntity: {
|
|
100
|
+
get: function(){
|
|
101
|
+
return this.customEntityType && this.components.length > 2 ? { id: this.components[2] } : {id: null}
|
|
102
|
+
},
|
|
103
|
+
set: function(newValue) {
|
|
104
|
+
this.entities = [newValue]
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
selectableEntities: function(){
|
|
108
|
+
const selectedDomain = this.perms.find(d => d.domain === this.domain)
|
|
109
|
+
if(typeof selectedDomain === 'undefined' ) return [];
|
|
110
|
+
|
|
111
|
+
const selectedActions = selectedDomain.actions
|
|
112
|
+
.filter(a => this.actions.includes(a.name))
|
|
113
|
+
const actionEntities = selectedActions.flatMap(a => (a.entities || []) )
|
|
114
|
+
.map(e => e.name);
|
|
115
|
+
|
|
116
|
+
return actionEntities || [ "*" ];
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
description: {
|
|
120
|
+
get: function(){
|
|
121
|
+
return this.value.description
|
|
122
|
+
},
|
|
123
|
+
set: function(newValue){
|
|
124
|
+
this.value.description = newValue;
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
|
|
128
|
+
resultingPerm: function(){
|
|
129
|
+
const result = this.buildName();
|
|
130
|
+
|
|
131
|
+
if(this.value.name !== result){
|
|
132
|
+
this.$emit('input', { name: result, description: this.description });
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
methods: {
|
|
140
|
+
buildName: function(){
|
|
141
|
+
var result = '';
|
|
142
|
+
|
|
143
|
+
if(this.domain && this.domain != '')
|
|
144
|
+
result += this.domain;
|
|
145
|
+
|
|
146
|
+
if(this.actions.length > 0)
|
|
147
|
+
result += ':' + this.actions.join(",");
|
|
148
|
+
|
|
149
|
+
if(this.entities.length > 0){
|
|
150
|
+
if(this.customEntityType)
|
|
151
|
+
result += ':' + this.entities.map(e => e.id || e).join(",");
|
|
152
|
+
else
|
|
153
|
+
result += ':' + this.entities.join(",");
|
|
154
|
+
}
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
</script>
|
|
160
|
+
|
|
161
|
+
<style></style>
|
|
162
|
+
|
|
163
|
+
<!-- vim: set sw=2 ts=2 et : -->
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<v-layout xs12 row wrap align-center>
|
|
3
|
+
<v-flex xs12>
|
|
4
|
+
<h3>Plano</h3>
|
|
5
|
+
</v-flex>
|
|
6
|
+
|
|
7
|
+
<v-flex v-if="debug" xs12 style="text-align:left;">
|
|
8
|
+
<code>{{ value }}</code>
|
|
9
|
+
</v-flex>
|
|
10
|
+
|
|
11
|
+
<v-flex md5 xs12>
|
|
12
|
+
<v-layout column>
|
|
13
|
+
<v-flex xs12 text-center>
|
|
14
|
+
<h4>Permissões</h4>
|
|
15
|
+
</v-flex>
|
|
16
|
+
<v-layout row v-for="perm in perms" v-bind:key="perm.name">
|
|
17
|
+
<v-flex xs3 text-right :class="'state-' + perm.state">
|
|
18
|
+
{{ perm.state }}
|
|
19
|
+
<span v-if="perm.state === 'existing'">
|
|
20
|
+
[<a :href="'#/permission/' + perm.id" target="_blank">{{ perm.id }}</a>]
|
|
21
|
+
</span>
|
|
22
|
+
<span v-if="perm.state === 'error'"><pre>{{ perm.error }}</pre></span>
|
|
23
|
+
</v-flex>
|
|
24
|
+
<v-flex xs12 text-left>
|
|
25
|
+
<code>{{ perm.name }}</code>
|
|
26
|
+
</v-flex>
|
|
27
|
+
</v-layout>
|
|
28
|
+
</v-layout>
|
|
29
|
+
</v-flex>
|
|
30
|
+
|
|
31
|
+
<v-flex md7 xs12>
|
|
32
|
+
<v-layout column>
|
|
33
|
+
<v-flex xs12 text-center>
|
|
34
|
+
<h4>Roles</h4>
|
|
35
|
+
</v-flex>
|
|
36
|
+
<v-layout row align-start fill-height v-for="role in roles" v-bind:key="role.name">
|
|
37
|
+
<v-flex xs2 text-right :class="'state-' + role.state">
|
|
38
|
+
{{ role.state }}
|
|
39
|
+
<span v-if="role.state === 'existing'">
|
|
40
|
+
[<a :href="'#/role/' + role.id" target="_blank">{{ role.id }}</a>]
|
|
41
|
+
</span>
|
|
42
|
+
<span v-if="role.state === 'error'"><pre>{{ role.error }}</pre></span>
|
|
43
|
+
</v-flex>
|
|
44
|
+
<v-flex md4 xs12 text-left>
|
|
45
|
+
<code>{{ role.name }}</code>
|
|
46
|
+
</v-flex>
|
|
47
|
+
<v-flex md6 xs12 text-left>
|
|
48
|
+
com perms: {{ role.perms }}
|
|
49
|
+
</v-flex>
|
|
50
|
+
</v-layout>
|
|
51
|
+
</v-layout>
|
|
52
|
+
</v-flex>
|
|
53
|
+
|
|
54
|
+
<v-flex xs12 style="padding-top:20px">
|
|
55
|
+
<v-btn v-on:click="refresh">Refresh Cache</v-btn>
|
|
56
|
+
<v-btn color="primary" v-on:click="execute">Executar</v-btn>
|
|
57
|
+
</v-flex>
|
|
58
|
+
</v-layout>
|
|
59
|
+
</template>
|
|
60
|
+
|
|
61
|
+
<script>
|
|
62
|
+
import axios from 'axios';
|
|
63
|
+
|
|
64
|
+
export default {
|
|
65
|
+
name: 'PlanExecutor',
|
|
66
|
+
|
|
67
|
+
props: {
|
|
68
|
+
value: Object,
|
|
69
|
+
debug: Boolean
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
data() {
|
|
73
|
+
return {
|
|
74
|
+
waitingToCreateRoles: false
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
computed: {
|
|
79
|
+
plan() {
|
|
80
|
+
return this.value
|
|
81
|
+
},
|
|
82
|
+
perms() {
|
|
83
|
+
this.find('permission', this.plan.perms)
|
|
84
|
+
|
|
85
|
+
return this.plan.perms
|
|
86
|
+
},
|
|
87
|
+
roles() {
|
|
88
|
+
this.find('role', ( this.plan.roles || [] ))
|
|
89
|
+
|
|
90
|
+
return this.plan.roles || []
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
watch: {
|
|
95
|
+
waitingToCreateRoles() {
|
|
96
|
+
if(this.waitingToCreateRoles && this.perms.every(p => p.state !== 'new')){
|
|
97
|
+
this.createRoles();
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
perms() {
|
|
101
|
+
if(this.waitingToCreateRoles && this.perms.every(p => p.state !== 'new')){
|
|
102
|
+
this.createRoles();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
|
|
107
|
+
methods: {
|
|
108
|
+
|
|
109
|
+
find: function(type, entities, force){
|
|
110
|
+
entities.forEach((p, i) => {
|
|
111
|
+
if(!force && p.state) return;
|
|
112
|
+
|
|
113
|
+
axios.get('/userm/userm/' + type + '/product/recordm/name/' + encodeURIComponent(p.name))
|
|
114
|
+
.then((resp) => {
|
|
115
|
+
this.$set(entities[i], 'state', 'existing')
|
|
116
|
+
this.$set(entities[i], 'id', resp.data.id)
|
|
117
|
+
})
|
|
118
|
+
.catch(() => {
|
|
119
|
+
this.$set(entities[i], 'state', 'new')
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
refresh: function(){
|
|
125
|
+
this.find('permission', this.plan.perms, true)
|
|
126
|
+
this.find('role', ( this.plan.roles || [] ), true)
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
execute: function(){
|
|
130
|
+
this.waitingToCreateRoles = true;
|
|
131
|
+
this.createPerms();
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
createPerms: function(){
|
|
135
|
+
const product = this.plan.product;
|
|
136
|
+
const perms = this.perms;
|
|
137
|
+
const uri = 'userm/permission'
|
|
138
|
+
|
|
139
|
+
const newPerms = perms.filter(p => p.state === 'new');
|
|
140
|
+
|
|
141
|
+
newPerms.forEach(p => {
|
|
142
|
+
const body = {
|
|
143
|
+
product: product,
|
|
144
|
+
name: p.name,
|
|
145
|
+
description: p.description
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
axios.post(uri, body)
|
|
149
|
+
.then(function(resp){
|
|
150
|
+
this.$set(p, 'state', 'existing')
|
|
151
|
+
this.$set(p, 'id', resp.data.id)
|
|
152
|
+
}.bind(this))
|
|
153
|
+
|
|
154
|
+
.catch(function(error){
|
|
155
|
+
window.console.error('JN perm', error)
|
|
156
|
+
this.$set(p, 'state', 'error')
|
|
157
|
+
this.$set(p, 'error', error.response.data)
|
|
158
|
+
}.bind(this))
|
|
159
|
+
})
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
createRoles: function(){
|
|
163
|
+
this.waitingToCreateRoles = false;
|
|
164
|
+
|
|
165
|
+
const product = this.plan.product;
|
|
166
|
+
const roles = this.roles;
|
|
167
|
+
const uri = 'userm/role'
|
|
168
|
+
|
|
169
|
+
const newRoles = roles.filter(r => r.state === 'new' || r.state === 'error' );
|
|
170
|
+
|
|
171
|
+
if(newRoles.length === 0){
|
|
172
|
+
roles.forEach(r => this.associateRoles(r.id, r.perms));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
newRoles.forEach(r => {
|
|
176
|
+
const body = {
|
|
177
|
+
product: product,
|
|
178
|
+
name: r.name,
|
|
179
|
+
description: r.description
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
axios.post(uri, body)
|
|
183
|
+
.then(function(resp){
|
|
184
|
+
this.$set(r, 'state', 'existing')
|
|
185
|
+
this.$set(r, 'id', resp.data.id)
|
|
186
|
+
|
|
187
|
+
this.associateRoles(r.id, r.perms);
|
|
188
|
+
|
|
189
|
+
}.bind(this))
|
|
190
|
+
|
|
191
|
+
.catch(function(error){
|
|
192
|
+
window.console.error('JN role', error)
|
|
193
|
+
this.$set(r, 'state', 'error')
|
|
194
|
+
this.$set(r, 'error', error.response.data)
|
|
195
|
+
}.bind(this))
|
|
196
|
+
})
|
|
197
|
+
},
|
|
198
|
+
|
|
199
|
+
associateRoles: function(roleId, permNames){
|
|
200
|
+
const permIds = permNames.map(name => this.perms.find(p => p.name === name).id)
|
|
201
|
+
window.console.debug('JN', 'associate', roleId, permNames, permIds);
|
|
202
|
+
|
|
203
|
+
axios.put('userm/role/' + roleId + '/permissions', permIds)
|
|
204
|
+
.then(resp => {
|
|
205
|
+
window.console.debug('JN', 'associar', resp)
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
</script>
|
|
212
|
+
<style scoped>
|
|
213
|
+
.state-new {
|
|
214
|
+
color: green
|
|
215
|
+
}
|
|
216
|
+
.state-existing {
|
|
217
|
+
color: gray
|
|
218
|
+
}
|
|
219
|
+
.state-error {
|
|
220
|
+
color: red
|
|
221
|
+
}
|
|
222
|
+
div, span, code {
|
|
223
|
+
font-size: 1.0em;
|
|
224
|
+
}
|
|
225
|
+
</style>
|