jsharmony-cms 1.5.3 → 1.5.7
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/clientjs/jsHarmonyCMS.ComponentManager.js +1 -1
- package/doc/deployment_target.json +7 -1
- package/jsHarmonyCMSConfig.js +1 -1
- package/models/Publish_Add_Release.json +1 -1
- package/models/Site_Deployment_Target_Role.json +4 -1
- package/models/Site_Deployment_Target_Role_Base.json +3 -0
- package/models/_funcs.branch.js +26 -0
- package/models/_funcs.deploy.js +19 -25
- package/models/sql/_functions.json +22 -0
- package/models/sql/objects/deployment.json +16 -5
- package/models/sql/scripts/upgrade/1-5-7.01.sql +3 -0
- package/package.json +2 -2
- package/public/js/jsHarmonyCMS.js +17279 -17279
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
//"ACL": "public-read",
|
|
83
83
|
//More parameters can be found at:
|
|
84
84
|
//https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property
|
|
85
|
-
}
|
|
85
|
+
},
|
|
86
86
|
},
|
|
87
87
|
|
|
88
88
|
//Git deployment settings
|
|
@@ -101,6 +101,12 @@
|
|
|
101
101
|
"onDeploy": true, //true (all), false (none), or array of items, ex: ["page","media"]
|
|
102
102
|
"onDeploy_PostBuild": true, //true (all), false (none), or array of items, ex: ["page","media"]
|
|
103
103
|
},
|
|
104
|
+
//Remote folders or files to ignore when deleting excess files on publish
|
|
105
|
+
//Use with FTP, FTPS, SFTP, S3, and Local File System deployments
|
|
106
|
+
"ignore_remote": [
|
|
107
|
+
"path/to/folder",
|
|
108
|
+
"path/to/file"
|
|
109
|
+
]
|
|
104
110
|
}
|
|
105
111
|
|
|
106
112
|
//Template Variables
|
package/jsHarmonyCMSConfig.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
{"name":"site_id","control":"dropdown","caption":"Site","validate":["Required"],"readonly":true,
|
|
22
22
|
"lov":{"sql":"select site_id code_val, site_name code_txt from {schema}.site where site_sts='ACTIVE' and site_id={schema}.my_current_site_id()"}},
|
|
23
23
|
{"name":"deployment_target_id","control":"dropdown","caption":"Deployment Target","validate":["Required"],
|
|
24
|
-
"lov":{"parent":"site_id" ,"sql2":"select site_id code_parent, deployment_target_id code_val, deployment_target_name code_txt from {schema}.v_my_deployment_target where deployment_target_can_publish = 1 and deployment_target_sts='ACTIVE' and site_id={schema}.my_current_site_id() order by site_id,deployment_target_name"}},
|
|
24
|
+
"lov":{"parent":"site_id" ,"sql2":"select site_id code_parent, deployment_target_id code_val, deployment_target_name code_txt from {schema}.v_my_deployment_target where ((deployment_target_can_publish = 1) or (deployment_target_can_publish_release = 1)) and deployment_target_sts='ACTIVE' and site_id={schema}.my_current_site_id() order by site_id,deployment_target_name"}},
|
|
25
25
|
{"control":"html","value":[
|
|
26
26
|
"<% if(jsh.globalparams.isWebmaster){ %>",
|
|
27
27
|
"<a href='#' onclick='<%=jsh._instance%>.XExt.popupForm(\"{namespace}Site_Tabs\",\"update\",{site_id:<%=jsh._instance%>.globalparams.site_id}); return false;'>Configure Deployment Targets</a>",
|
|
@@ -11,7 +11,10 @@
|
|
|
11
11
|
{"control":"subform","caption":"Preview / Editor","target":"Site_Deployment_Target_Role_Editor","bindings":{"deployment_target_id":"deployment_target_id","deployment_target_role_type":"'EDITOR'"},
|
|
12
12
|
"controlstyle":"display:inline-block; margin-right:15px;"
|
|
13
13
|
},
|
|
14
|
-
{"control":"subform","caption":"Publish","target":"Site_Deployment_Target_Role_Publish","bindings":{"deployment_target_id":"deployment_target_id","deployment_target_role_type":"'PUBLISH'"},
|
|
14
|
+
{"control":"subform","caption":"Publish (Any Branch)","target":"Site_Deployment_Target_Role_Publish","bindings":{"deployment_target_id":"deployment_target_id","deployment_target_role_type":"'PUBLISH'"},
|
|
15
|
+
"controlstyle":"display:inline-block;"
|
|
16
|
+
},
|
|
17
|
+
{"control":"subform","caption":"Publish Release","target":"Site_Deployment_Target_Role_Publish_Release","bindings":{"deployment_target_id":"deployment_target_id","deployment_target_role_type":"'PUBLISH_RELEASE'"},
|
|
15
18
|
"controlstyle":"display:inline-block;"
|
|
16
19
|
},
|
|
17
20
|
]
|
package/models/_funcs.branch.js
CHANGED
|
@@ -546,6 +546,19 @@ module.exports = exports = function(module, funcs){
|
|
|
546
546
|
|
|
547
547
|
branchData.page_mapping = {};
|
|
548
548
|
|
|
549
|
+
//Sort folders first, then by path length
|
|
550
|
+
branchItems = (branchItems||[]).sort(function(a,b){
|
|
551
|
+
a = a || {};
|
|
552
|
+
b = b || {};
|
|
553
|
+
if(!(a.page_is_folder) && (b.page_is_folder)) return 1;
|
|
554
|
+
if((a.page_is_folder) && !(b.page_is_folder)) return -1;
|
|
555
|
+
var apath = (a.page_path||'').toString();
|
|
556
|
+
var bpath = (b.page_path||'').toString();
|
|
557
|
+
if(apath.length > bpath.length) return 1;
|
|
558
|
+
if(apath.length < bpath.length) return -1;
|
|
559
|
+
return 0;
|
|
560
|
+
});
|
|
561
|
+
|
|
549
562
|
_.each(branchItems, function(item){
|
|
550
563
|
//Create mapping
|
|
551
564
|
branchData.page_mapping[item.page_key] = item;
|
|
@@ -680,6 +693,19 @@ module.exports = exports = function(module, funcs){
|
|
|
680
693
|
|
|
681
694
|
branchData.media_mapping = {};
|
|
682
695
|
|
|
696
|
+
//Sort folders first, then by path length
|
|
697
|
+
branchItems = (branchItems||[]).sort(function(a,b){
|
|
698
|
+
a = a || {};
|
|
699
|
+
b = b || {};
|
|
700
|
+
if(!(a.media_is_folder) && (b.media_is_folder)) return 1;
|
|
701
|
+
if((a.media_is_folder) && !(b.media_is_folder)) return -1;
|
|
702
|
+
var apath = (a.media_path||'').toString();
|
|
703
|
+
var bpath = (b.media_path||'').toString();
|
|
704
|
+
if(apath.length > bpath.length) return 1;
|
|
705
|
+
if(apath.length < bpath.length) return -1;
|
|
706
|
+
return 0;
|
|
707
|
+
});
|
|
708
|
+
|
|
683
709
|
async.waterfall([
|
|
684
710
|
function(cb){
|
|
685
711
|
//Get all media from current database
|
package/models/_funcs.deploy.js
CHANGED
|
@@ -514,7 +514,10 @@ module.exports = exports = function(module, funcs){
|
|
|
514
514
|
var cms = module;
|
|
515
515
|
var git_path = cms.Config.git.bin_path || 'git';
|
|
516
516
|
return funcs.shellExec(git_path, repo_path, params, function(err, rslt, stderr){
|
|
517
|
-
if(err)
|
|
517
|
+
if(err){
|
|
518
|
+
if(err && (err.code == 'ENOENT')) err = new Error('Git executable not found using command: "'+git_path+'". Please install git, or set the git.bin_path config parameter');
|
|
519
|
+
return cb(new Error('Git Error: ' + err.toString() + ' ' + (stderr||'')), rslt);
|
|
520
|
+
}
|
|
518
521
|
return cb(err, rslt);
|
|
519
522
|
}, exec_options);
|
|
520
523
|
}
|
|
@@ -1801,7 +1804,7 @@ module.exports = exports = function(module, funcs){
|
|
|
1801
1804
|
appsrv.ExecRecordset('deployment', sql, sql_ptypes, sql_params, function (err, rslt) {
|
|
1802
1805
|
if (err != null) { err.sql = sql; return cb(err); }
|
|
1803
1806
|
if(!rslt || !rslt.length || !rslt[0]){ return cb(new Error('Error loading deployment media')); }
|
|
1804
|
-
async.
|
|
1807
|
+
async.eachLimit(rslt[0], 10, function(media, item_cb){
|
|
1805
1808
|
var srcpath = funcs.getMediaFilename(media.media_file_id, media.media_ext);
|
|
1806
1809
|
var media_fpath = '';
|
|
1807
1810
|
async.waterfall([
|
|
@@ -1833,7 +1836,7 @@ module.exports = exports = function(module, funcs){
|
|
|
1833
1836
|
},
|
|
1834
1837
|
//Export thumbnails
|
|
1835
1838
|
function(generate_cb){
|
|
1836
|
-
async.
|
|
1839
|
+
async.eachOf(branchData.site_config.media_thumbnails, function(thumbnail_config, thumbnail_id, thumbnail_cb){
|
|
1837
1840
|
if(!thumbnail_config || !thumbnail_config.export) return thumbnail_cb();
|
|
1838
1841
|
if(!_.includes(['.jpg','.jpeg','.tif','.tiff','.png','.gif','.svg'], media.media_ext)) return thumbnail_cb();
|
|
1839
1842
|
|
|
@@ -2011,27 +2014,16 @@ module.exports = exports = function(module, funcs){
|
|
|
2011
2014
|
|
|
2012
2015
|
exports.deploy_ignore_remote = function(publish_params, fpath){
|
|
2013
2016
|
if(fpath=='.git') return true;
|
|
2014
|
-
return false;
|
|
2015
|
-
/*
|
|
2016
2017
|
if(!publish_params || !publish_params.ignore_remote) return false;
|
|
2017
|
-
var origpath = fpath;
|
|
2018
2018
|
fpath = HelperFS.convertWindowsToPosix(fpath);
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
else {
|
|
2026
|
-
if(ignore_expr == fpath) return true;
|
|
2027
|
-
}
|
|
2028
|
-
}
|
|
2029
|
-
fpath = path.dirname(fpath);
|
|
2030
|
-
if(fpath=='.') fpath = '';
|
|
2031
|
-
if(fpath=='..') fpath = '';
|
|
2019
|
+
for(var i=0;i<publish_params.ignore_remote.length;i++){
|
|
2020
|
+
var ignore_expr = publish_params.ignore_remote[i];
|
|
2021
|
+
if(!ignore_expr) continue;
|
|
2022
|
+
var ignore_path = HelperFS.convertWindowsToPosix(ignore_expr.toString());
|
|
2023
|
+
if(ignore_path == fpath) return true;
|
|
2024
|
+
if(fpath.indexOf(ignore_path+'/')==0) return true;
|
|
2032
2025
|
}
|
|
2033
|
-
return
|
|
2034
|
-
*/
|
|
2026
|
+
return false;
|
|
2035
2027
|
}
|
|
2036
2028
|
|
|
2037
2029
|
exports.deploy_fs = function(deployment, publish_path, deploy_path, site_files, cb){
|
|
@@ -2578,6 +2570,7 @@ module.exports = exports = function(module, funcs){
|
|
|
2578
2570
|
if(bucket_prefix){
|
|
2579
2571
|
if(!bucket_prefix || (bucket_prefix[bucket_prefix.length-1]!='/')) bucket_prefix += '/';
|
|
2580
2572
|
}
|
|
2573
|
+
var S3_THREADS = 10;
|
|
2581
2574
|
|
|
2582
2575
|
var s3_files = {};
|
|
2583
2576
|
var s3_upload = [];
|
|
@@ -2613,7 +2606,9 @@ module.exports = exports = function(module, funcs){
|
|
|
2613
2606
|
if(site_md5 != s3_md5) s3_upload.push(fname);
|
|
2614
2607
|
}
|
|
2615
2608
|
else {
|
|
2616
|
-
|
|
2609
|
+
if(!funcs.deploy_ignore_remote(deployment.publish_params, fname)){
|
|
2610
|
+
s3_delete.push(fname);
|
|
2611
|
+
}
|
|
2617
2612
|
}
|
|
2618
2613
|
}
|
|
2619
2614
|
for(var fname in site_files){
|
|
@@ -2625,7 +2620,7 @@ module.exports = exports = function(module, funcs){
|
|
|
2625
2620
|
|
|
2626
2621
|
//Upload new files to S3
|
|
2627
2622
|
function(s3_cb){
|
|
2628
|
-
async.
|
|
2623
|
+
async.eachLimit(s3_upload, S3_THREADS, function(page_path, page_cb){
|
|
2629
2624
|
var page_bpath = bucket_prefix + page_path;
|
|
2630
2625
|
var page_fpath = path.join(publish_path, page_path);
|
|
2631
2626
|
var fstream = fs.createReadStream(page_fpath);
|
|
@@ -2635,7 +2630,6 @@ module.exports = exports = function(module, funcs){
|
|
|
2635
2630
|
Bucket: bucket,
|
|
2636
2631
|
Key: page_bpath,
|
|
2637
2632
|
Body: fstream,
|
|
2638
|
-
ACL: 'public-read'
|
|
2639
2633
|
};
|
|
2640
2634
|
var contentType = HelperFS.getMimeType(page_bpath);
|
|
2641
2635
|
if(contentType) uploadParams.ContentType = contentType;
|
|
@@ -2648,7 +2642,7 @@ module.exports = exports = function(module, funcs){
|
|
|
2648
2642
|
|
|
2649
2643
|
//Delete removed files from S3
|
|
2650
2644
|
function(s3_cb){
|
|
2651
|
-
async.
|
|
2645
|
+
async.eachLimit(s3_delete, S3_THREADS, function(page_path, page_cb){
|
|
2652
2646
|
var page_bpath = bucket_prefix + page_path;
|
|
2653
2647
|
funcs.deploy_log_info(deployment_id, 'Deleting: '+page_path);
|
|
2654
2648
|
funcs.deploy_log_change(deployment_id, 'Deleting file: '+page_path);
|
|
@@ -199,6 +199,28 @@
|
|
|
199
199
|
"\")",
|
|
200
200
|
]
|
|
201
201
|
},
|
|
202
|
+
"{schema}.can_publish":{
|
|
203
|
+
"params": ["BRANCH_ID","DEPLOYMENT_TARGET_ID"],
|
|
204
|
+
"sql": [
|
|
205
|
+
"(case when exists(",
|
|
206
|
+
" select * from {schema}.v_my_deployment_target where deployment_target_id=%%%DEPLOYMENT_TARGET_ID%%% and (",
|
|
207
|
+
" (deployment_target_can_publish=1) or",
|
|
208
|
+
" (deployment_target_can_publish_release=1 and exists(select branch_child.branch_id from {schema}.branch branch_child where branch_child.branch_id=%%%BRANCH_ID%%% and branch_child.branch_type='PUBLIC'))",
|
|
209
|
+
" )",
|
|
210
|
+
") then 1 else 0 end)"
|
|
211
|
+
]
|
|
212
|
+
},
|
|
213
|
+
"{schema}.could_have_published":{
|
|
214
|
+
"params": ["BRANCH_ID","DEPLOYMENT_TARGET_ID"],
|
|
215
|
+
"sql": [
|
|
216
|
+
"(case when exists(",
|
|
217
|
+
" select * from {schema}.v_my_deployment_target where deployment_target_id=%%%DEPLOYMENT_TARGET_ID%%% and (",
|
|
218
|
+
" (deployment_target_can_publish=1) or",
|
|
219
|
+
" (deployment_target_can_publish_release=1 and exists(select branch_child.branch_id from {schema}.branch branch_child inner join {schema}.branch branch_parent on branch_parent.branch_id = branch_child.branch_parent_id where branch_child.branch_id=%%%BRANCH_ID%%% and branch_parent.branch_type='PUBLIC'))",
|
|
220
|
+
" )",
|
|
221
|
+
") then 1 else 0 end)"
|
|
222
|
+
]
|
|
223
|
+
},
|
|
202
224
|
"{schema}.insert_token": {
|
|
203
225
|
"params": ["sys_user_token_hash","sys_user_token_ext","sys_user_token_keys"],
|
|
204
226
|
"sql": [
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
"caption": "Deployment Target Role Type",
|
|
5
5
|
"init_data": [
|
|
6
6
|
{ "code_val": "PUBLISH", "code_txt": "Publish", "code_seq": 1 },
|
|
7
|
-
{ "code_val": "
|
|
7
|
+
{ "code_val": "PUBLISH_RELEASE", "code_txt": "Publish Release", "code_seq": 2 },
|
|
8
|
+
{ "code_val": "EDITOR", "code_txt": "Preview / Editor", "code_seq": 3 }
|
|
8
9
|
]
|
|
9
10
|
},
|
|
10
11
|
|
|
@@ -153,6 +154,16 @@
|
|
|
153
154
|
" when exists(select * from deployment_target_role dtr inner join {schema}.sys_user_site r on r.sys_user_site_access = dtr.sys_role_name and r.sys_user_id = jsharmony.my_sys_user_id() and r.site_id = deployment_target.site_id and dtr.deployment_target_role_type='PUBLISH' and dtr.deployment_target_id = deployment_target.deployment_target_id) then 1",
|
|
154
155
|
" else 0 end"
|
|
155
156
|
]
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"name":"deployment_target_can_publish_release", "type": "int",
|
|
160
|
+
"sqlselect": [
|
|
161
|
+
"case ",
|
|
162
|
+
" when {schema}.my_user_is_publisher(deployment_target.site_id) = 0 then 0",
|
|
163
|
+
" when exists(select * from deployment_target_role dtr inner join jsharmony.sys_user_role r on r.sys_role_name = dtr.sys_role_name and r.sys_user_id = jsharmony.my_sys_user_id() and dtr.deployment_target_role_type='PUBLISH_RELEASE' and dtr.deployment_target_id = deployment_target.deployment_target_id) then 1",
|
|
164
|
+
" when exists(select * from deployment_target_role dtr inner join {schema}.sys_user_site r on r.sys_user_site_access = dtr.sys_role_name and r.sys_user_id = jsharmony.my_sys_user_id() and r.site_id = deployment_target.site_id and dtr.deployment_target_role_type='PUBLISH_RELEASE' and dtr.deployment_target_id = deployment_target.deployment_target_id) then 1",
|
|
165
|
+
" else 0 end"
|
|
166
|
+
]
|
|
156
167
|
}
|
|
157
168
|
]
|
|
158
169
|
}
|
|
@@ -181,7 +192,7 @@
|
|
|
181
192
|
"deployment_etstmp",
|
|
182
193
|
"deployment_euser",
|
|
183
194
|
"deployment_mtstmp",
|
|
184
|
-
"deployment_muser"
|
|
195
|
+
"deployment_muser",
|
|
185
196
|
]
|
|
186
197
|
},
|
|
187
198
|
"v_my_deployment_target": {
|
|
@@ -191,14 +202,14 @@
|
|
|
191
202
|
"join_type": "inner",
|
|
192
203
|
"join_columns": {
|
|
193
204
|
"deployment.deployment_target_id": "v_my_deployment_target.deployment_target_id",
|
|
194
|
-
"
|
|
205
|
+
"{schema}.could_have_published(deployment.branch_id, deployment.deployment_target_id)": "1"
|
|
195
206
|
}
|
|
196
207
|
}
|
|
197
208
|
},
|
|
198
209
|
"triggers": [
|
|
199
210
|
{"on": ["insert"], "exec": [
|
|
200
211
|
//Verify access
|
|
201
|
-
"errorif(
|
|
212
|
+
"errorif($ifnull({schema}.can_publish(inserted(branch_id), inserted(deployment_target_id)),0)<>1,'No access to publish to this deployment target.');",
|
|
202
213
|
//Verify non-duplicate tag name
|
|
203
214
|
"errorif(exists(select 1 from {schema}.deployment inner join {schema}.branch on {schema}.branch.branch_id={schema}.deployment.branch_id where deployment_tag=inserted(deployment_tag) and site_id=inserted(site_id)),'Deployment Tag must be unique for the site.');",
|
|
204
215
|
"errorif(exists(select 1 from {schema}.deployment inner join {schema}.deployment_target on {schema}.deployment_target.deployment_target_id={schema}.deployment.deployment_target_id where deployment_tag=inserted(deployment_tag) and site_id=(select site_id from deployment_target where deployment_target_id=inserted(deployment_target_id))),'Deployment Tag must be unique for the site.');",
|
|
@@ -218,7 +229,7 @@
|
|
|
218
229
|
},
|
|
219
230
|
{"on": ["update"], "exec": [
|
|
220
231
|
//Verify access
|
|
221
|
-
"errorif(
|
|
232
|
+
"errorif($ifnull({schema}.could_have_published((select branch_id from {schema}.deployment where deployment_id = deleted(deployment_id)), (select deployment_target_id from {schema}.deployment where deployment_id = deleted(deployment_id))),0)<>1,'No access to cancel this deployment.');",
|
|
222
233
|
"update {schema}.deployment set deployment_sts = 'CANCEL' where deployment_id = deleted(deployment_id)"
|
|
223
234
|
]
|
|
224
235
|
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
jsharmony.version_increment('jsHarmonyCMS',1,5,7,0);
|
|
2
|
+
update {schema}.code_deployment_target_role_type set code_seq=3 where code_val='EDITOR';
|
|
3
|
+
insert into {schema}.code_deployment_target_role_type(code_val, code_txt, code_seq) values ('PUBLISH_RELEASE','Publish Release',2);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jsharmony-cms",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.7",
|
|
4
4
|
"description": "jsHarmony CMS",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"diff2html": "3.4.1",
|
|
31
31
|
"ejs": "2.7.4",
|
|
32
32
|
"js-beautify": "^1.11.0",
|
|
33
|
-
"jsharmony": "^1.
|
|
33
|
+
"jsharmony": "^1.5.2",
|
|
34
34
|
"jsharmony-factory": "^1.2.0",
|
|
35
35
|
"lodash": "^4.17.19",
|
|
36
36
|
"node-forge": "^0.10.0",
|