Skip to content
This repository was archived by the owner on Oct 5, 2020. It is now read-only.

Commit 0a88ac3

Browse files
committed
Fixed permissions, improved init-local
1 parent 69e8b60 commit 0a88ac3

File tree

4 files changed

+364
-45
lines changed

4 files changed

+364
-45
lines changed
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
#
2+
# Put your custom functions in this class in order to keep the files under lib untainted
3+
#
4+
# This class has access to all of the private variables in deploy/lib/server_config.rb
5+
#
6+
# any public method you create here can be called from the command line. See
7+
# the examples below for more information.
8+
#
9+
class ServerConfig
10+
11+
#
12+
# You can easily "override" existing methods with your own implementations.
13+
# In ruby this is called monkey patching
14+
#
15+
# first you would rename the original method
16+
# alias_method :original_deploy_modules, :deploy_modules
17+
18+
# then you would define your new method
19+
# def deploy_modules
20+
# # do your stuff here
21+
# # ...
22+
23+
# # you can optionally call the original
24+
# original_deploy_modules
25+
# end
26+
27+
#
28+
# you can define your own methods and call them from the command line
29+
# just like other roxy commands
30+
# ml local my_custom_method
31+
#
32+
# def my_custom_method()
33+
# # since we are monkey patching we have access to the private methods
34+
# # in ServerConfig
35+
# @logger.info(@properties["ml.content-db"])
36+
# end
37+
38+
#
39+
# to create a method that doesn't require an environment (local, prod, etc)
40+
# you woudl define a class method
41+
# ml my_static_method
42+
#
43+
# def self.my_static_method()
44+
# # This method is static and thus cannot access private variables
45+
# # but it can be called without an environment
46+
# end
47+
48+
# Show-casing some useful overrides, as well as fixing some module doc permissions
49+
alias_method :original_deploy_modules, :deploy_modules
50+
alias_method :original_deploy_rest, :deploy_rest
51+
alias_method :original_clean, :clean
52+
53+
def deploy_modules
54+
# Uncomment deploy_packages if you would like to use MLPM to deploy MLPM packages.
55+
# You can also move mlpm.json into src/ext/ and deploy plain modules (not REST extensions) that way.
56+
#deploy_packages
57+
original_deploy_modules
58+
end
59+
60+
def deploy_packages
61+
password_prompt
62+
system %Q!mlpm deploy -u #{ @ml_username } \
63+
-p #{ @ml_password } \
64+
-H #{ @properties['ml.server'] } \
65+
-P #{ @properties['ml.app-port'] }!
66+
fix_permissions(@properties["ml.modules-db"])
67+
end
68+
69+
def deploy_rest
70+
original_deploy_rest
71+
fix_permissions(@properties["ml.modules-db"])
72+
end
73+
74+
def fix_permissions(where)
75+
logger.info "Fixing permissions in #{where} for documents:"
76+
if where.include? "content"
77+
# This is useful to make sure alert configuration is accessible
78+
r = execute_query(
79+
%Q{
80+
xquery version "1.0-ml";
81+
82+
for $uri in cts:uri-match("*alert*")
83+
return (
84+
$uri,
85+
xdmp:document-set-permissions($uri, (
86+
xdmp:permission("#{@properties["ml.app-name"]}-role", "read"),
87+
xdmp:permission("#{@properties["ml.app-name"]}-role", "update"),
88+
xdmp:permission("#{@properties["ml.app-name"]}-role", "execute")
89+
))
90+
)
91+
},
92+
{ :db_name => where }
93+
)
94+
else
95+
r = execute_query(
96+
%Q{
97+
xquery version "1.0-ml";
98+
99+
for $uri in cts:uris()
100+
where not(ends-with($uri, "/"))
101+
return (
102+
$uri,
103+
xdmp:document-set-permissions($uri, (
104+
xdmp:permission("#{@properties["ml.app-name"]}-role", "read"),
105+
xdmp:permission("#{@properties["ml.app-name"]}-role", "update"),
106+
xdmp:permission("#{@properties["ml.app-name"]}-role", "execute")
107+
))
108+
)
109+
},
110+
{ :db_name => where }
111+
)
112+
end
113+
114+
r.body = parse_json r.body
115+
logger.info r.body
116+
logger.info ""
117+
end
118+
119+
def clean
120+
what = ARGV.shift
121+
122+
case what
123+
when 'collections'
124+
clean_collections
125+
else
126+
ARGV.unshift what
127+
original_clean
128+
end
129+
end
130+
131+
def clean_collections()
132+
what = ARGV.shift
133+
r = execute_query(
134+
%Q{
135+
xquery version "1.0-ml";
136+
137+
for $collection in fn:tokenize("#{what}", ",")
138+
where fn:exists(fn:collection($collection)[1])
139+
return (
140+
xdmp:collection-delete($collection),
141+
"Cleaned collection " || $collection
142+
)
143+
},
144+
{ :db_name => @properties["ml.content-db"]}
145+
)
146+
r.body = parse_json r.body
147+
logger.info r.body
148+
end
149+
150+
end
151+
152+
#
153+
# Uncomment, and adjust below code to get help about your app_specific
154+
# commands included into Roxy help. (ml -h)
155+
#
156+
157+
#class Help
158+
# def self.app_specific
159+
# <<-DOC.strip_heredoc
160+
#
161+
# App-specific commands:
162+
# example Installs app-specific alerting
163+
# DOC
164+
# end
165+
#
166+
# def self.example
167+
# <<-DOC.strip_heredoc
168+
# Usage: ml {env} example [args] [options]
169+
#
170+
# Runs a special example task against given environment.
171+
#
172+
# Arguments:
173+
# this Do this
174+
# that Do that
175+
#
176+
# Options:
177+
# --whatever=value
178+
# DOC
179+
# end
180+
#end

app/templates/gulpfile.js

Lines changed: 141 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ var _ = require('lodash');
1616
var $ = require('gulp-load-plugins')({lazy: true});
1717
/* jshint ignore:end */
1818

19+
var _s = require('underscore.string');
20+
1921
/**
2022
* yargs variables can be passed in to alter the behavior, when present.
2123
* Example: gulp serve-dev
@@ -203,31 +205,24 @@ gulp.task('inject', ['wiredep', 'styles', 'templatecache'], function() {
203205
});
204206

205207
/**
206-
* Creates a sample local.json; can be used as model for dev.json and prod.json
208+
* Initialize config files for local environment
207209
*/
208-
gulp.task('init-local', function() {
209-
//copy from slushfile - config gulp - with modifications to use config instead
210-
log('Creating local.json sample document with values drawn from gulp.config.js');
211-
try {
212-
var configJSON = {};
213-
configJSON['ml-version'] = config.marklogic.version;
214-
configJSON['ml-host'] = config.marklogic.host;
215-
configJSON['ml-admin-user'] = config.marklogic.username;
216-
configJSON['ml-admin-pass'] = config.marklogic.password;
217-
configJSON['ml-app-user'] = config.marklogic.username;
218-
configJSON['ml-app-pass'] = config.marklogic.password;
219-
configJSON['ml-http-port'] = config.marklogic.httpPort;
220-
configJSON['node-port'] = config.defaultPort;
221-
222-
if (config.marklogic.version < 8) {
223-
configJSON['ml-xcc-port'] = config.marklogic.xccPort;
224-
}
210+
gulp.task('init-local', function(done) {
211+
init('local', done);
212+
});
225213

226-
var configString = JSON.stringify(configJSON, null, 2) + '\n';
227-
fs.writeFileSync('local.json', configString, { encoding: 'utf8' });
228-
} catch (e) {
229-
log('failed to write local.json: ' + e.message);
230-
}
214+
/**
215+
* Initialize config files for dev environment
216+
*/
217+
gulp.task('init-dev', function(done) {
218+
init('dev', done);
219+
});
220+
221+
/**
222+
* Initialize config files for prod environment
223+
*/
224+
gulp.task('init-prod', function(done) {
225+
init('prod', done);
231226
});
232227

233228
/**
@@ -518,6 +513,129 @@ function clean(files) {
518513
});
519514
}
520515

516+
/**
517+
* Initialize config files for given env
518+
* @param {String} env The environment name (local, dev, prod)
519+
* @param {Function} done - callback when complete
520+
*/
521+
function init(env, done) {
522+
if (fs.existsSync(env + '.json')) {
523+
log(env + '.json already exists!');
524+
done();
525+
} else {
526+
//copy from slushfile - config gulp - with modifications to use config instead
527+
var inquirer = require('inquirer');
528+
529+
var properties = fs.readFileSync('deploy/build.properties', { encoding: 'utf8' });
530+
531+
// capture app-name entered earlier
532+
var appNameMatch = /^app\-name=(.*)$/m;
533+
var matches = appNameMatch.exec(properties);
534+
var appName = matches[1];
535+
536+
var prompts = [
537+
{type: 'list', name: 'mlVersion', message: 'MarkLogic version?', choices: ['8','7', '6', '5'], default: 0},
538+
{type: 'input', name: 'marklogicHost', message: 'MarkLogic Host?', default: 'localhost'},
539+
{type: 'input', name: 'marklogicAdminUser', message: 'MarkLogic Admin User?', default: 'admin'},
540+
{type: 'input', name: 'marklogicAdminPass', message: 'Note: consider keeping the following blank, ' +
541+
'you will be asked to enter it at appropriate commands.\n? MarkLogic Admin Password?', default: ''},
542+
{type: 'input', name: 'appPort', message: 'MarkLogic App/Rest port?', default: 8040},
543+
{type: 'input', name: 'xccPort', message: 'XCC port?', default:8041, when: function(answers) {
544+
return answers.mlVersion < 8;
545+
}},
546+
{type: 'input', name: 'nodePort', message: 'Node app port?', default: 9070},
547+
{type: 'input', name: 'guestAccess', message: 'Allow anonymous users to search data?', default: 'false'},
548+
{type: 'input', name: 'readOnlyAccess', message: 'Disallow proxying update requests?', default: 'false'},
549+
{type: 'input', name: 'appUsersOnly', message: 'Only allow access to users created for this app? Disallows admin users.', default: 'false'}
550+
];
551+
552+
if (typeof appName === 'undefined') {
553+
prompts.unshift(
554+
{type: 'input', name: 'name', message: 'Name for the app?'});
555+
}
556+
557+
inquirer.prompt(prompts, function (settings) {
558+
if (typeof appName === 'undefined') {
559+
settings.nameDashed = _s.slugify(settings.name);
560+
} else {
561+
settings.nameDashed = _s.slugify(appName);
562+
}
563+
564+
try {
565+
var configJSON = {};
566+
configJSON['app-name'] = settings.nameDashed;
567+
configJSON['ml-version'] = settings.mlVersion;
568+
configJSON['ml-host'] = settings.marklogicHost;
569+
configJSON['ml-admin-user'] = settings.marklogicAdminUser;
570+
configJSON['ml-admin-pass'] = settings.marklogicAdminPass;
571+
configJSON['ml-app-user'] = settings.nameDashed + '-user';
572+
configJSON['ml-app-pass'] = settings.appuserPassword;
573+
configJSON['ml-http-port'] = settings.appPort;
574+
575+
if (settings.mlVersion < 8) {
576+
configJSON['ml-xcc-port'] = settings.xccPort;
577+
}
578+
579+
configJSON['node-port'] = settings.nodePort;
580+
configJSON['guest-access'] = settings.guestAccess;
581+
configJSON['readonly-access'] = settings.readOnlyAccess;
582+
configJSON['appusers-only'] = settings.appUsersOnly;
583+
584+
var configString = JSON.stringify(configJSON, null, 2) + '\n';
585+
fs.writeFileSync(env + '.json', configString, { encoding: 'utf8' });
586+
log('Created ' + env + '.json.');
587+
588+
if (fs.existsSync('deploy/' + env + '.properties')) {
589+
log('deploy/' + env + '.properties already exists!');
590+
} else {
591+
var envProperties = '#################################################################\n' +
592+
'# This file contains overrides to values in build.properties\n' +
593+
'# These only affect your local environment and should not be checked in\n' +
594+
'#################################################################\n' +
595+
'\n' +
596+
'server-version=' + settings.mlVersion + '\n' +
597+
'\n' +
598+
'#\n' +
599+
'# The ports used by your application\n' +
600+
'#\n' +
601+
'app-port=' + settings.appPort + '\n';
602+
if (settings.mlVersion < 8) {
603+
envProperties += 'xcc-port=' + settings.xccPort + '\n';
604+
}
605+
else
606+
{
607+
envProperties += '# Taking advantage of not needing a XCC Port for ML8\n' +
608+
'xcc-port=${app-port}\n' +
609+
'install-xcc=false\n';
610+
}
611+
612+
envProperties += '\n' +
613+
'#\n' +
614+
'# the uris or IP addresses of your servers\n' +
615+
'# WARNING: if you are running these scripts on WINDOWS you may need to change localhost to 127.0.0.1\n' +
616+
'# There have been reported issues with dns resolution when localhost wasn\'t in the hosts file.\n' +
617+
'#\n' +
618+
env + '-server=' + settings.marklogicHost + '\n' +
619+
'content-forests-per-host=3\n' +
620+
'\n' +
621+
'#\n' +
622+
'# Admin username/password that will exist on the local/dev/prod servers\n' +
623+
'#\n' +
624+
'user=' + settings.marklogicAdminUser + '\n' +
625+
'password=' + settings.marklogicAdminPass + '\n';
626+
627+
fs.writeFileSync('deploy/' + env + '.properties', envProperties, {encoding: 'utf8'});
628+
log('Created deploy/' + env + '.properties.');
629+
}
630+
done();
631+
} catch (e) {
632+
log('Failed to write ' + env + ' config files: ' + e.message);
633+
done();
634+
}
635+
});
636+
}
637+
}
638+
521639
/**
522640
* Inject files in a sorted sequence at a specified inject label
523641
* @param {Array} src glob pattern for source files

app/templates/node-server/utils/options.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ module.exports = function(){
1717
defaultUser: process.env.ML_APP_USER || envJson['ml-app-user'] || config.marklogic.user,
1818
defaultPass: process.env.ML_APP_PASS || envJson['ml-app-pass'] || config.marklogic.password,
1919
guestAccess: bool(process.env.GUEST_ACCESS || envJson['guest-access'] || config.marklogic.guestAccess || false),
20-
readOnlyAccess: bool(process.env.READ_ONLY_ACCESS || envJson['read-only-access'] || config.marklogic.readOnlyAccess || false),
21-
appUsersOnly: bool(process.env.APP_USERS_ONLY || envJson['app-users-only'] || config.marklogic.appUsersOnly || false)
20+
readOnlyAccess: bool(process.env.READ_ONLY_ACCESS || envJson['readonly-access'] || config.marklogic.readOnlyAccess || false),
21+
appUsersOnly: bool(process.env.APP_USERS_ONLY || envJson['appusers-only'] || config.marklogic.appUsersOnly || false)
2222
};
2323

2424
return options;

0 commit comments

Comments
 (0)