diff --git a/api.py b/api.py index e51679a68b2902f6a79e07737f096f850e30c5fe..ab2695647530bd37255b4e7d1f4231e5fece241a 100755 --- a/api.py +++ b/api.py @@ -3,7 +3,11 @@ # @author: Gunnar Schaefer, Kevin S. Hahn import logging -import logging.config +logging.basicConfig( + format='%(asctime)s %(name)16.16s:%(levelname)4.4s %(message)s', + datefmt='%Y-%m-%d %H:%M:%S', + level=logging.DEBUG, + ) log = logging.getLogger('scitran.api') logging.getLogger('scitran.data').setLevel(logging.WARNING) # silence scitran.data logging logging.getLogger('MARKDOWN').setLevel(logging.WARNING) # silence Markdown library logging @@ -90,16 +94,6 @@ def dispatcher(router, request, response): app = webapp2.WSGIApplication(routes) app.router.set_dispatcher(dispatcher) -app.config = { - 'data_path': 'nims', - 'quarantine_path': 'quarantine', - 'site_id': 'local', - 'site_name': 'Local', - 'ssl_cert': None, - 'insecure': False, - 'log_path': None, - 'demo': False, - } if __name__ == '__main__': @@ -108,39 +102,29 @@ if __name__ == '__main__': import paste.httpserver arg_parser = argparse.ArgumentParser() - arg_parser.add_argument('--host', default='127.0.0.1', help='IP address to bind to') - arg_parser.add_argument('--port', default='8080', help='TCP port to listen on') - arg_parser.add_argument('--db_uri', help='NIMS DB URI', required=True) + arg_parser.add_argument('--host', default='127.0.0.1', help='IP address to bind to [127.0.0.1]') + arg_parser.add_argument('--port', default='8080', help='TCP port to listen on [8080]') + arg_parser.add_argument('--db_uri', help='SciTran DB URI', default='mongodb://localhost/scitran') arg_parser.add_argument('--data_path', help='path to storage area', required=True) - arg_parser.add_argument('--log_path', help='path to API log file', required=True) + arg_parser.add_argument('--log_level', help='log level [info]', default='info') arg_parser.add_argument('--ssl_cert', help='path to SSL certificate file, containing private key and certificate chain', required=True) - arg_parser.add_argument('--site_id', help='site ID for Scitran Central') - arg_parser.add_argument('--site_name', help='site name for Scitran Central', nargs='+') + arg_parser.add_argument('--site_id', help='site ID for Scitran Central [local]', default='local') arg_parser.add_argument('--oauth2_id_endpoint', help='OAuth2 provider ID endpoint', default='https://www.googleapis.com/plus/v1/people/me/openIdConnect') - arg_parser.add_argument('--demo', help='demo mode, enables auto user creation', action='store_true', default=False) - arg_parser.add_argument('--insecure', help='insecure mode, allow user info as urlencoded param', action='store_true', default=False) - arg_parser.add_argument('--log_level', help='log level [info]', default='info') + arg_parser.add_argument('--demo', help='enable automatic user creation', action='store_true', default=False) + arg_parser.add_argument('--insecure', help='allow user info as urlencoded param', action='store_true', default=False) args = arg_parser.parse_args() - args.site_name = ' '.join(args.site_name) if args.site_name else None # site_name as string - logging.basicConfig() + args.data_path = os.path.join(args.data_path, 'scitran') + args.quarantine_path = os.path.join(args.data_path, 'quarantine') + app.config = vars(args) + logging.getLogger('paste.httpserver').setLevel(logging.INFO) # silence paste logging log.setLevel(getattr(logging, args.log_level.upper())) - app.config['site_id'] = args.site_id - app.config['site_name'] = args.site_name - app.config['data_path'] = os.path.join(args.data_path, 'nims') - app.config['quarantine_path'] = os.path.join(args.data_path, 'quarantine') - app.config['log_path'] = args.log_path - app.config['oauth2_id_endpoint'] = args.oauth2_id_endpoint - app.config['insecure'] = args.insecure - app.config['ssl_cert'] = args.ssl_cert - app.config['demo'] = args.demo - if not app.config['ssl_cert']: - log.warning('SSL certificate not specified, scitran central functionality disabled') - elif not app.config['site_id']: - log.warning('site_id not configured, scitran central functionality disabled') + log.warning('SSL certificate not specified, SciTran Central functionality disabled') + if app.config['site_id'] == 'local': + log.warning('site_id not configured, SciTran Central functionality disabled') if not os.path.exists(app.config['data_path']): os.makedirs(app.config['data_path']) diff --git a/api.wsgi b/api.wsgi index 3743b69eac241bfe94dd21f2def5777f833341e7..08caff2aae9c63c74f75d926d2a41bae6733f5f6 100644 --- a/api.wsgi +++ b/api.wsgi @@ -14,35 +14,28 @@ os.environ['PYTHON_EGG_CACHE'] = '/tmp/python_egg_cache' os.umask(0o022) ap = argparse.ArgumentParser() -ap.add_argument('--db_uri', help='mongodb uri', required=True) -ap.add_argument('--data_path', help='path to data', required=True) -ap.add_argument('--log_path', help='path to log', required=True) # for SHOWING the log, not where to write -ap.add_argument('--ssl_cert', help='path to ssl cert in pem format, key+cert', required=True) +ap.add_argument('--db_uri', help='SciTran DB URI', required=True) +ap.add_argument('--data_path', help='path to storage area', required=True) +ap.add_argument('--ssl_cert', help='path to SSL certificate file, containing private key and certificate chain', required=True) ap.add_argument('--api_uri', help='api uri, with https:// prefix') -ap.add_argument('--site_id', help='site id') -ap.add_argument('--site_name', help='site name', nargs='+') -ap.add_argument('--oauth2_id_endpoint', help='oauth2 id endpoint url', default='https://www.googleapis.com/plus/v1/people/me/openIdConnect') -ap.add_argument('--demo', help='demo mode, enables auto user creation', action='store_true', default=False) -ap.add_argument('--insecure', help='insecure mode', action='store_true', default=False) +ap.add_argument('--site_id', help='site ID for Scitran Central [local]', default='local') +ap.add_argument('--site_name', help='site name') +ap.add_argument('--oauth2_id_endpoint', help='OAuth2 provider ID endpoint', default='https://www.googleapis.com/plus/v1/people/me/openIdConnect') +ap.add_argument('--demo', help='enable automatic user creation', action='store_true', default=False) +ap.add_argument('--insecure', help='allow user info as urlencoded param', action='store_true', default=False) ap.add_argument('--central_uri', help='scitran central api', default='https://sdmc.scitran.io/api') ap.add_argument('--log_level', help='log level [info]', default='info') args = ap.parse_args() -args.site_name = ' '.join(args.site_name) if args.site_name else None # site_name as string -logging.basicConfig(level=getattr(logging, args.log_level.upper())) +args.data_path = os.path.join(args.data_path, 'scitran') +args.quarantine_path = os.path.join(args.data_path, 'quarantine') + +logging.basicConfig(level=getattr(logging, args.log_level.upper())) #FIXME probably not necessary, because done in api.py log = logging.getLogger('nimsapi') # configure uwsgi application application = api.app -application.config['site_id'] = args.site_id -application.config['site_name'] = args.site_name -application.config['data_path'] = os.path.join(args.data_path, 'nims') -application.config['quarantine_path'] = os.path.join(args.data_path, 'quarantine') -application.config['log_path'] = args.log_path -application.config['ssl_cert'] = args.ssl_cert -application.config['oauth2_id_endpoint'] = args.oauth2_id_endpoint -application.config['insecure'] = args.insecure -application.config['demo'] = args.demo +application.config = vars(args) if not os.path.exists(application.config['data_path']): os.makedirs(application.config['data_path']) diff --git a/base.py b/base.py index d46a7a68913249b5c1c068660c8005a003d48a13..da3d5f06998ef947a4960b837ff40f13d14b7c52 100644 --- a/base.py +++ b/base.py @@ -14,8 +14,6 @@ import requests class RequestHandler(webapp2.RequestHandler): - """fetches pubkey from own self.db.remotes. needs to be aware of OWN site uid""" - json_schema = None def __init__(self, request=None, response=None): @@ -54,7 +52,7 @@ class RequestHandler(webapp2.RequestHandler): if self.request.environ['SSL_CLIENT_VERIFY'] != 'SUCCESS': self.abort(401, 'no valid SSL client certificate') remote_instance = self.request.user_agent.replace('NIMS Instance', '').strip() - if not self.app.db.remotes.find_one({'_id': remote_instance}): + if not self.app.db.sites.find_one({'_id': remote_instance}): self.abort(402, remote_instance + ' is not authorized') self.public_request = not bool(self.uid) if self.public_request or self.source_site: @@ -88,7 +86,7 @@ class RequestHandler(webapp2.RequestHandler): self.abort(500, 'api site_id is not configured') if not self.app.config['ssl_cert']: self.abort(500, 'api ssl_cert is not configured') - target = self.app.db.remotes.find_one({'_id': target_site}, ['api_uri']) + target = self.app.db.sites.find_one({'_id': target_site}, ['api_uri']) if not target: self.abort(402, 'remote host ' + target_site + ' is not an authorized remote') # adjust headers diff --git a/centralclient.py b/centralclient.py index 54dea35b048d39c3b6fced9599a08855f3f72650..0168d4455d92c5322a4fded586a19bc9901fec26 100755 --- a/centralclient.py +++ b/centralclient.py @@ -51,8 +51,8 @@ def update(db, api_uri, site_name, site_id, ssl_cert, central_url): for _id, remotes in response['users'].iteritems(): db.users.update({'_id': _id}, {'$set': {'remotes': remotes}}) if sites: - db.remotes.remove({'_id': {'$nin': [site['_id'] for site in response['sites']]}}) - [db.remotes.update({'_id': site['_id']}, site, upsert=True) for site in sites] + db.sites.remove({'_id': {'$nin': [site['_id'] for site in response['sites']]}}) + [db.sites.update({'_id': site['_id']}, site, upsert=True) for site in sites] db.users.update( # clean users who no longer have remotes {'remotes': {'$exists': True}, '_id': {'$nin': users.keys()}}, {'$unset': {'remotes': ''}}, @@ -60,7 +60,7 @@ def update(db, api_uri, site_name, site_id, ssl_cert, central_url): ) log.info('%3d users with remote data, %3d remotes' % ( len([u['_id'] for u in db.users.find({'remotes': {'$exists': True}}, {'_id': True})]), - len([s['_id'] for s in db.remotes.find({}, {'_id': True})]) + len([s['_id'] for s in db.sites.find({}, {'_id': True})]) )) return True else: @@ -76,9 +76,9 @@ def update(db, api_uri, site_name, site_id, ssl_cert, central_url): def clean_remotes(db): - """Remove db.remotes, and removes remotes field from all db.users.""" + """Remove db.sites, and removes remotes field from all db.users.""" log.debug('removing remotes from users, and remotes collection') - db.remotes.remove({}) + db.sites.remove({}) db.users.update({'remotes': {'$exists': True}}, {'$unset': {'remotes': ''}}, multi=True) diff --git a/collections_.py b/collections_.py index 6e75a922aa13da0c461f91b3d42dd0085b77a692..2d6955cae9eaebb457958c7d05f2dfabe3ba76bd 100644 --- a/collections_.py +++ b/collections_.py @@ -145,10 +145,6 @@ COLLECTION_SCHEMA = { 'site': { 'type': 'string', }, - 'site_name': { - 'title': 'Site', - 'type': 'string', - }, 'permissions': { 'title': 'Permissions', 'type': 'array', diff --git a/core.py b/core.py index 14699dcd599c8e8e3e8bbf584d5d54b9bdaf9527..fded44f9e27ea55a480bf38a562ae0c856cd8280 100644 --- a/core.py +++ b/core.py @@ -186,28 +186,14 @@ class Core(base.RequestHandler): def sites(self): """Return local and remote sites.""" + if self.app.config['site_id'] == 'local': + return [{'_id': 'local', 'name': 'Local', 'onload': True}] if self.public_request or self.request.get('all').lower() in ('1', 'true'): - sites = list(self.app.db.remotes.find(None, ['name'])) + sites = list(self.app.db.sites.find(None, ['name'])) else: - sites = (self.app.db.users.find_one({'_id': self.uid}, ['remotes']) or {}).get('remotes', []) - return sites + [{'_id': self.app.config['site_id'], 'name': self.app.config['site_name'], 'onload': True}] - - def log(self): - """Return logs.""" - try: - logs = open(self.app.config['log_path']).readlines() - except IOError as e: - if 'Permission denied' in e: - body_template = '${explanation}<br /><br />${detail}<br /><br />${comment}' - comment = 'To fix permissions, run the following command: chmod o+r ' + self.app.config['log_path'] - self.abort(500, detail=str(e), comment=comment, body_template=body_template) - else: # file does not exist - self.abort(500, 'log_path variable misconfigured or not set') - try: - n = int(self.request.get('n', 10000)) - except: - self.abort(400, 'n must be an integer') - return [line.strip() for line in reversed(logs) if re.match('[-:0-9 ]{18} +api:(?!.*[/a-z]*/log )', line)][:n] + remote_ids = (self.app.db.users.find_one({'_id': self.uid}, ['remotes']) or {}).get('remotes', []) + [self.app.config['site_id']] + sites = list(self.app.db.sites.find({'_id': {'$in': remote_ids}}, ['name'])) + return sites search_schema = { 'title': 'Search', diff --git a/projects.py b/projects.py index c8d2ebeb46df865794a71d73e11549d6e0c9b290..b1c0b21e3e251463a0a7105a73470802729ec2de 100644 --- a/projects.py +++ b/projects.py @@ -103,13 +103,6 @@ class Project(containers.Container): 'properties': { '_id': { }, - 'site': { - 'type': 'string', - }, - 'site_name': { - 'title': 'Site', - 'type': 'string', - }, 'permissions': { 'title': 'Permissions', 'type': 'object', @@ -138,8 +131,6 @@ class Project(containers.Container): """Return one Project, conditionally with details.""" _id = bson.ObjectId(pid) proj, _ = self._get(_id) - proj['site'] = self.app.config['site_id'] - proj['site_name'] = self.app.config['site_name'] if self.debug: proj['sessions'] = self.uri_for('sessions', pid, _full=True) + '?' + self.request.query_string return proj