Skip to content

Commit

Permalink
Merge pull request #120 from indera/develop
Browse files Browse the repository at this point in the history
Add doi link
  • Loading branch information
indera committed Jan 21, 2016
2 parents 4224d61 + 9d38aa0 commit 0df598f
Show file tree
Hide file tree
Showing 14 changed files with 93 additions and 168 deletions.
7 changes: 2 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
# @unittest.skip("Unconditional skipping")
# @unittest.skipIf(os.getenv('CONTINUOUS_INTEGRATION', '') > '', reason='Travis VM')

# The redidropper/startup/initializer.py does not need the env variable anymore
#env: REDIDROPPER_CONFIG=~/build/ctsit/redi-dropper-client/app/deploy/application.conf

# http://docs.travis-ci.com/user/migrating-from-legacy/
sudo: false
language: python
Expand Down Expand Up @@ -48,8 +45,8 @@ script:
- pushd app
- echo $TRAVIS_BUILD_DIR
- ls -al deploy/
# put config file in the place expected by config.py
- cp deploy/sample.settings.conf deploy/settings.conf
# link the settings file to make it visible in config.py
- cp deploy/sample.vagrant.settings.conf deploy/settings.conf
- python setup.py nosetests
- popd

Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# RediDropper
# REDI-Dropper

[![DOI](https://zenodo.org/badge/doi/10.5281/zenodo.32500.svg)](http://dx.doi.org/10.5281/zenodo.32500)

| Branch | [Travis-CI](https://travis-ci.org/ctsit/redi-dropper-client/builds) | [Coveralls](https://coveralls.io/github/ctsit/redi-dropper-client) |
| :----- | :---------------------------: | :-------: |
Expand Down
24 changes: 2 additions & 22 deletions app/db/002/data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@ SET @end = CONCAT(CURDATE() + interval 6 month, ' 23:59:59');
SET @end2 = CONCAT(CURDATE() - interval 1 month, ' 23:59:59');


-- Note: there is no value inserted in the usrPasswordHash
INSERT INTO User (usrEmail, usrFirst, usrLast, usrAddedAt, usrAccessExpiresAt, usrIsActive, usrEmailConfirmedAt)
VALUES
('asura@ufl.edu', 'Andrei', 'Şérenfaü', NOW(), @end, 1, NOW()),
('kshanson@ufl.edu', 'Kevin', 'Hanson', NOW(), @end, 1, NOW()),
('cpb@ufl.edu', 'Christopher', 'Barnes', NOW(), @end2, 1, NOW()),
('pbc@ufl.edu', 'Philip', 'Chase', NOW(), @end, 0, NOW()),
('keyes@ufl.edu', 'Roy', 'Keyes', NOW(), @end, 0, NOW()),
('taeber@ufl.edu', 'Taeber', 'Rapczak', NOW(), @end, 0, NOW()),
('atloiaco@ufl.edu', 'Alex', 'Loiacono', NOW(), @end, 0, NOW()),
('cavedivr@ufl.edu', 'Erik', 'Schmidt', NOW(), @end, 0, NOW())
('taeber@ufl.edu', 'Taeber', 'Rapczak', NOW(), @end, 0, NOW())
;

INSERT INTO Role (rolName, rolDescription)
Expand All @@ -35,27 +34,8 @@ UNION SELECT usrID, rolID, NOW() FROM User, Role WHERE usrEmail = 'cpb@ufl.edu'
UNION SELECT usrID, rolID, NOW() FROM User, Role WHERE usrEmail = 'pbc@ufl.edu' AND rolName = 'technician'
UNION SELECT usrID, rolID, NOW() FROM User, Role WHERE usrEmail = 'keyes@ufl.edu' AND rolName = 'technician'
UNION SELECT usrID, rolID, NOW() FROM User, Role WHERE usrEmail = 'taeber@ufl.edu' AND rolName = 'technician'
UNION SELECT usrID, rolID, NOW() FROM User, Role WHERE usrEmail = 'atloiaco@ufl.edu' AND rolName = 'technician'
UNION SELECT usrID, rolID, NOW() FROM User, Role WHERE usrEmail = 'cavedivr@ufl.edu' AND rolName = 'technician'
;

-- REDCap Subjects (retrieve from server)
-- INSERT INTO Subject (sbjRedcapID, sbjAddedAt)
-- VALUES
-- ('001', NOW()),
-- ('002', NOW()),
-- ('003', NOW()),
-- ('004', NOW()),
-- ('005', NOW())
-- ;


-- REDCap event (retrieve from server)
-- INSERT INTO Event (evtRedcapArm, evtRedcapEvent, evtAddedAt)
-- SELECT 'Arm 1', 'Event 01', NOW()
-- UNION SELECT 'Arm 1', 'Event 02', NOW()
-- ;


-- Subject Files
-- INSERT INTO SubjectFile (sbjID, evtID, sfFileName, sfFileCheckSum, sfFileSize, sfUploadedAt, usrID)
Expand Down
22 changes: 14 additions & 8 deletions app/deploy/fabfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,16 +136,10 @@ def _is_prod():
return env.environment == 'production'


def _motd():
"""Print the message of the day"""
print(MOTD_PROD if _is_prod() else MOTD_STAG)


def bootstrap(tag='master'):
"""Bootstrap the deployment using the specified branch"""
require('environment', provided_by=[production, staging])
_motd()

print(MOTD_PROD if _is_prod() else MOTD_STAG)
msg = colors.red('\n%(project_path)s exists. '
'Do you want to continue anyway?' % env)

Expand Down Expand Up @@ -351,11 +345,16 @@ def mysql_reset_tables():


def _toggle_apache_site(state):
"""Switch site's status to enabled or disabled"""
"""Switch site's status to enabled or disabled
Note: the `project_name` is used for referencing the config files
"""
action = "Enabling" if state else "Disabling"
print('\n%s site...' % action)
env.apache_command = 'a2ensite' if state else 'a2dissite'
sudo('%(apache_command)s %(project_name)s' % env)

# We have to have the ssl config too because we use the NetScaler
sudo('%(apache_command)s %(project_name)s-ssl' % env)
sudo('service apache2 reload')


Expand Down Expand Up @@ -433,6 +432,13 @@ def update_config(tag='master'):
'group': 'root'
},
2: {
'local': os.path.abspath('%(environment)s/virtualhost-ssl.conf'
% env),
'remote': env.vhost_ssl_file,
'mode': '644',
'group': 'root'
},
3: {
'local': local_settings_file,
'remote': env.settings_file,
'mode': '640'
Expand Down
2 changes: 2 additions & 0 deletions app/deploy/sample.fabric.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ def get_settings(overrides={}):
SETTINGS['server_group'] = 'app-runner'
SETTINGS['vhost_file'] = ('/etc/apache2/sites-available/%(project_name)s' %
SETTINGS)
SETTINGS['vhost_ssl_file'] = ('/etc/apache2/sites-available/%(project_name)s-ssl' %
SETTINGS)
SETTINGS['wsgi_file'] = ('%(project_path)s/dropper.wsgi' %
SETTINGS)
SETTINGS['settings_file'] = ('%(project_path)s/settings.conf' %
Expand Down
File renamed without changes.
102 changes: 26 additions & 76 deletions app/deploy/sample.virtualhost-ssl.conf
Original file line number Diff line number Diff line change
@@ -1,84 +1,34 @@
<IfModule mod_ssl.c>
ServerSignature off
ServerTokens Prod
#
# Apache SSL config
# @see NetScaler: https://www.citrix.com/products/netscaler-application-delivery-controller/overview/what-is-an-adc.html
#

##
## SSL Global Context
##
## All SSL configuration in this context applies both to
## the main server and all SSL-enabled virtual hosts.
##

<VirtualHost _default_:443>
ServerName %(project_url)s:443
UseCanonicalName On




<VirtualHost *:443>
ServerName %(project_url)s
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains"

SSLEngine on
SSLProtocol All -SSLv2 -SSLv3
SSLCipherSuite AES256+EECDH:AES256+EDH:!aNULL:!eNULL
SSLCompression off
SSLCertificateFile /etc/apache2/ssl/%(project_url)s.crt
SSLCertificateKeyFile /etc/apache2/ssl/%(project_url)s.key

# Possible values: debug, info, notice, warn, error, crit, alert, emerg.
LogLevel warn
ServerAdmin webmaster@localhost
ErrorLog %(project_path)s/logs/error.log
CustomLog %(project_path)s/logs/access.log combined

############################################################################
# @see https://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIDaemonProcess
###########################################################################

#ALZ_INSTANCE_BEGIN
WSGIDaemonProcess %(project_name)s processes=2 threads=3 stack-size=1048576 maximum-requests=500 inactivity-timeout=300 display-name=%%{GROUP} python-path=%(env_path)s/lib/%(python)s/site-packages
WSGIProcessGroup %(project_name)s
WSGIScriptAlias /alz %(wsgi_file)s

<Directory "%(project_path)s">
WSGIScriptReloading On
WSGIProcessGroup %(project_name)s
WSGIApplicationGroup %%{GLOBAL}

Order deny,allow
Allow from all
</Directory>

Alias /alz/static %(project_repo_path)s/app/redidropper/static
<Directory "%(project_repo_path)s/app/redidropper/static/">
Order allow,deny
Allow from all
</Directory>
#ALZ_INSTANCE_END

#ONEFL_INSTANCE_BEGIN
WSGIDaemonProcess dropper_onefl user=www-data group=www-data processes=2 threads=3 stack-size=1048576 maximum-requests=500 inactivity-timeout=300 display-name=%%{GROUP} python-path=/srv/apps/dropper-onefl/env/lib/python2.7/site-packages
WSGIProcessGroup dropper_onefl
WSGIScriptAlias /onefl /srv/apps/dropper-onefl/dropper.wsgi

<Directory "/srv/apps/dropper-onefl">
WSGIScriptReloading On
WSGIProcessGroup dropper_onefl
WSGIApplicationGroup %%{GLOBAL}
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW

Order deny,allow
Allow from all
</Directory>
SSLCertificateFile /etc/apache2/ssl/%(project_url)s.crt
SSLCertificateKeyFile /etc/apache2/ssl/%(project_url)s.key

Alias /onefl/static /srv/apps/dropper-onefl/src/current/app/redidropper/static
<Directory "/srv/apps/dropper-onefl/src/current/app/redidropper/static/">
Order allow,deny
Allow from all
</Directory>
#ONEFL_INSTANCE_END
<Files ~ "\.(cgi|shtml|phtml|php3?)$">
SSLOptions +StdEnvVars
</Files>

###########################################################################
<Location />
AuthType shibboleth
ShibRequireSession Off
ShibUseHeaders On
# require valid-user
require shibboleth
</Location>
SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0

Options -Indexes
SetOutputFilter DEFLATE
AddOutputFilterByType DEFLATE text/html text/css text/plain text/xml application/x-javascript
</VirtualHost>
</IfModule>
2 changes: 1 addition & 1 deletion app/deploy/sample.virtualhost.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ ServerSignature off
ServerTokens Prod

<VirtualHost *:80>
ServerName https:// %(project_url)s:443
ServerName https://%(project_url)s:443
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains"

# Possible values: debug, info, notice, warn, error, crit, alert, emerg.
Expand Down
13 changes: 9 additions & 4 deletions app/redidropper/routes/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ def download_file():
@app.route('/api/save_user', methods=['POST'])
@login_required
def api_save_user():
""" Save a new user to the database """
""" Save a new user to the database
TODO: Add support for reading a password field
"""
email = request.form['email']
first = request.form['first']
last = request.form['last']
Expand All @@ -201,19 +203,22 @@ def api_save_user():
return utils.jsonify_error(
{'message': 'Sorry. This email is already taken.'})

# @TODO: fix hardcoded values
# salt, hashed_pass = generate_auth(app.config['SECRET_KEY'], password)
# @TODO: use a non-gatorlink password here
password = email
salt, password_hash = utils.generate_auth(app.config['SECRET_KEY'],
password)
added_date = datetime.today()
access_end_date = utils.get_expiration_date(180)

# Note: we store the salt as a prefix
user = UserEntity.create(email=email,
first=first,
last=last,
minitial=minitial,
added_at=added_date,
modified_at=added_date,
access_expires_at=access_end_date,
password_hash="")
password_hash="{}:{}".format(salt, password_hash))

user_roles = []
try:
Expand Down
12 changes: 9 additions & 3 deletions app/redidropper/routes/pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,14 @@ def render_login_local():
LogEntity.login(uuid, "No such email: {}".format(email))
return redirect(url_for('index'))

# if utils.is_valid_auth(app.config['SECRET_KEY'], auth.uathSalt,
# password, auth.uathPassword):
if '' == user.password_hash:
password_hash = user.password_hash

# @TODO: enforce the `local password` policy
if '' == password_hash or \
utils.is_valid_auth(app.config['SECRET_KEY'],
password_hash[0:16],
password,
password_hash[17:]):
app.logger.info('Log login event for: {}'.format(user))
LogEntity.login(uuid, 'Successful login via email/password')
login_user(user, remember=False, force=False)
Expand All @@ -181,6 +186,7 @@ def render_login_local():
else:
app.logger.info('Incorrect pass for: {}'.format(user))
LogEntity.login_error(uuid, 'Incorrect pass for: {}'.format(user))
utils.flash_error("Incorrect username/password.")

# When sending a GET request render the login form
return render_template('index.html', form=form,
Expand Down
4 changes: 2 additions & 2 deletions app/redidropper/routes/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ def get_user_links():
'logout': ('logout', 'Logout'),
}
role = get_highest_role()
# print "highest role: {}".format(role)

if role is None:
return []

print "highest role: {}".format(role)

if ROLE_ADMIN == role:
links = [pages['admin'],
pages['upload_files'],
Expand Down
4 changes: 2 additions & 2 deletions app/redidropper/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ def generate_auth(pepper, password):
Note: requires a request context.
"""
salt = _create_salt()
hashed_pass = _generate_sha512_hmac(pepper, salt, password)
return (salt, hashed_pass)
password_hash = _generate_sha512_hmac(pepper, salt, password)
return (salt, password_hash)


def is_valid_auth(pepper, salt, candidate_password, correct_hash):
Expand Down
Loading

0 comments on commit 0df598f

Please sign in to comment.