示例#1
0
def getDbConfig():
    """Get the database configuration values from the cherrypy config."""
    cfg = config.getConfig()
    if 'database' in cfg:
        return cfg['database']
    else:
        return {}
示例#2
0
def configureServer(mode=None, plugins=None, curConfig=None):
    """
    Function to setup the cherrypy server. It configures it, but does
    not actually start it.

    :param mode: The server mode to start in.
    :type mode: string
    :param plugins: If you wish to start the server with a custom set of
        plugins, pass this as a list of plugins to load. Otherwise,
        all installed plugins will be loaded.
    :param curConfig: The configuration dictionary to update.
    """
    if curConfig is None:
        curConfig = config.getConfig()

    appconf = {
        '/': {
            'request.dispatch': cherrypy.dispatch.MethodDispatcher(),
            'request.show_tracebacks': mode == ServerMode.TESTING,
            'request.methods_with_bodies': ('POST', 'PUT', 'PATCH'),
            'response.headers.server': 'Girder %s' % __version__,
            'error_page.default': _errorDefault
        }
    }
    # Add MIME types for serving Fontello files from staticdir;
    # these may be missing or incorrect in the OS
    mimetypes.add_type('application/vnd.ms-fontobject', '.eot')
    mimetypes.add_type('application/x-font-ttf', '.ttf')
    mimetypes.add_type('application/font-woff', '.woff')

    curConfig.update(appconf)
    if mode:
        curConfig['server']['mode'] = mode

    logprint.info('Running in mode: ' + curConfig['server']['mode'])
    cherrypy.config['engine.autoreload.on'] = mode in [ServerMode.DEVELOPMENT]

    _setupCache()

    # Don't import this until after the configs have been read; some module
    # initialization code requires the configuration to be set up.
    from girderformindlogger.api import api_main

    root = webroot.Webroot()
    api_main.addApiToNode(root)

    girderformindlogger.events.setupDaemon()

    routeTable = loadRouteTable()
    info = {
        'config': appconf,
        'serverRoot': root,
        'serverRootPath': routeTable[constants.GIRDER_ROUTE_ID],
        'apiRoot': root.api.v1,
    }

    plugin._loadPlugins(info, plugins)
    root, appconf = info['serverRoot'], info['config']

    return root, appconf
示例#3
0
def getApiUrl(url=None, preferReferer=False):
    """
    In a request thread, call this to get the path to the root of the REST API.
    The returned path does *not* end in a forward slash.

    :param url: URL from which to extract the base URL. If not specified, uses
        the server root system setting. If that is not specified, uses `cherrypy.url()`
    :param preferReferer: if no url is specified, this is true, and this is in
        a cherrypy request that has a referer header that contains the api
        string, use that referer as the url.
    """
    apiStr = config.getConfig()['server']['api_root']

    if not url:
        if preferReferer and apiStr in cherrypy.request.headers.get('referer', ''):
            url = cherrypy.request.headers['referer']
        else:
            root = Setting().get(SettingKey.SERVER_ROOT)
            if root:
                return posixpath.join(root, apiStr.lstrip('/'))

    url = url or cherrypy.url()
    idx = url.find(apiStr)

    if idx < 0:
        raise GirderException('Could not determine API root in %s.' % url)

    return url[:idx + len(apiStr)]
def _setupCache():
    """
    Setup caching based on configuration file.

    Cache backends are forcibly replaced because Girder initially configures
    the regions with the null backends.
    """
    curConfig = config.getConfig()

    if curConfig['cache']['enabled']:
        # Replace existing backend, this is necessary
        # because they're initially configured with the null backend
        cacheConfig = {
            'cache.global.replace_existing_backend': True,
            'cache.request.replace_existing_backend': True
        }

        curConfig['cache'].update(cacheConfig)

        cache.configure_from_config(curConfig['cache'], 'cache.global.')
        requestCache.configure_from_config(curConfig['cache'],
                                           'cache.request.')
    else:
        # Reset caches back to null cache (in the case of server teardown)
        cache.configure(backend='dogpile.cache.null',
                        replace_existing_backend=True)
        requestCache.configure(backend='dogpile.cache.null',
                               replace_existing_backend=True)

    # Although the rateLimitBuffer has no pre-existing backend, this method may be called multiple
    # times in testing (where caches were already configured)
    rateLimitBuffer.configure(backend='dogpile.cache.memory',
                              replace_existing_backend=True)
示例#5
0
    def __init__(self, templatePath=None):
        if not templatePath:
            templatePath = os.path.join(constants.PACKAGE_DIR, 'api',
                                        'api_docs.mako')
        super(ApiDocs, self).__init__(templatePath)

        curConfig = config.getConfig()
        self.vars['mode'] = curConfig['server'].get('mode', '')
示例#6
0
    def getConfigurationOption(self, section, key, params):
        configSection = config.getConfig().get(section)

        if configSection is None:
            raise ResourcePathNotFound('No section with that name exists.')
        elif key not in configSection:
            raise ResourcePathNotFound('No key with that name exists.')
        else:
            return configSection.get(key)
示例#7
0
def getRedisConnection():
    global _redisClient

    from redis import Redis, ConnectionPool

    if _redisClient:
        return _redisClient

    cfg = config.getConfig()
    pool = ConnectionPool(**cfg['redis'])
    _redisClient = Redis(connection_pool=pool)
    return _redisClient
def getLogPaths():
    """
    Return the paths to the error and info log files. These are returned as
    a dict with "error" and "info" keys that point to the respective file,
    as well as a "root" key pointing to the log root directory.
    """
    cfg = config.getConfig()
    logCfg = cfg.get('logging', {})
    root = os.path.expanduser(logCfg.get('log_root', LOG_ROOT))

    return {
        'root': root,
        'error': logCfg.get('error_log_file', os.path.join(root, 'error.log')),
        'info': logCfg.get('info_log_file', os.path.join(root, 'info.log'))
    }
示例#9
0
    def setPassword(self, user, password, save=True):
        """
        Change a user's password.

        :param user: The user whose password to change.
        :param password: The new password. If set to None, no password will
                         be stored for this user. This should be done in cases
                         where an external system is responsible for
                         authenticating the user.
        """
        if password is None:
            user['salt'] = None
        else:
            cur_config = config.getConfig()

            # Normally this would go in validate() but password is a special case.
            if not re.match(cur_config['users']['password_regex'], password):
                raise ValidationException(cur_config['users']['password_description'], 'password')

            user['salt'] = self._cryptContext.hash(password)

        if save:
            self.save(user)
示例#10
0
def createCipher(applet, appletAssignments, user):
    thisUser = getCurrentUser()
    cUser = None
    try:
        cUser = UserModel().load(user, level=AccessType.NONE, user=thisUser)
    except:
        cur_config = config.getConfig()
        if not re.match(cur_config['users']['email_regex'], user):
            raise ValidationException('Invalid email address.', 'user')
    newCipher = FolderModel().createFolder(parent=applet,
                                           name=nextCipher(appletAssignments),
                                           parentType='folder',
                                           public=False,
                                           creator=thisUser,
                                           reuseExisting=True)
    if cUser is None:
        try:
            appletName = FolderModel().preferredName(FolderModel().load(
                applet['meta']['applet']['@id'],
                level=AccessType.NONE,
                user=thisUser)['name'])
        except:
            raise ValidationException('Invalid assignment folder.', 'applet')
        try:
            cUser = UserModel().createUser(login="******".join(
                [appletName.replace(' ', ''),
                 str(newCipher['name'])]),
                                           password=str(uuid.uuid4()),
                                           firstName=appletName,
                                           email=user,
                                           admin=False,
                                           public=False,
                                           currentUser=thisUser)
        except:
            cUser = UserModel().createUser(login="******".join([
                appletName.replace(' ', ''),
                str(applet['meta']['applet']['@id']),
                str(FolderModel().preferredName(newCipher))
            ]),
                                           password=str(uuid.uuid4()),
                                           firstName=appletName,
                                           email=user,
                                           admin=False,
                                           public=False,
                                           currentUser=thisUser)
    newSecretCipher = FolderModel().setMetadata(
        FolderModel().createFolder(parent=newCipher,
                                   name='userID',
                                   parentType='folder',
                                   public=False,
                                   creator=thisUser,
                                   reuseExisting=True),
        {'user': {
            '@id': str(cUser['_id'])
        }})
    FolderModel().setAccessList(doc=newSecretCipher,
                                access={
                                    'users': [],
                                    'groups': []
                                },
                                save=True,
                                user=thisUser,
                                force=True)
    for u in [thisUser, cUser]:
        FolderModel().setUserAccess(doc=newSecretCipher,
                                    user=u,
                                    level=None,
                                    save=True,
                                    currentUser=thisUser,
                                    force=True)
    for u in [thisUser, cUser]:
        FolderModel().setUserAccess(doc=newSecretCipher,
                                    user=u,
                                    level=AccessType.READ,
                                    save=True,
                                    currentUser=thisUser,
                                    force=True)
    return (newCipher)
示例#11
0
_originalStdErr = sys.stderr
auditLogger = logging.getLogger('girder_audit')
auditLogger.setLevel(logging.INFO)
logger = logging.getLogger('girderformindlogger')
logger.setLevel(
    logging.DEBUG)  # Pass everything; let filters handle level-based filtering
config.loadConfig()  # Populate the config info at import time

# Initialize sentry logging
env = os.environ.get('HTTP_HOST', 'localhost')
sentry_logging = LoggingIntegration(
    level=logging.INFO,  # Capture info and above as breadcrumbs
    event_level=logging.CRITICAL  # Send errors as events
)
if env is not 'localhost':
    sentry_sdk.init(dsn=config.getConfig()['sentry']['backend_dsn'],
                    environment=env,
                    integrations=[sentry_logging])


class LogLevelFilter(object):
    """
    Filter log records based on whether they are between a min and max level.
    """
    def __init__(self, min, max):
        self.minLevel = min
        self.maxLevel = max

    def filter(self, logRecord):
        level = logRecord.levelno
        return self.maxLevel >= level >= self.minLevel
def _attachFileLogHandlers():
    """
    Sets up the Girder logger.
    """
    global _quiet

    cfg = config.getConfig()
    logCfg = cfg.get('logging', {})

    # If we are asked to be quiet, set a global flag so that logprint doesn't
    # have to get the configuration settings every time it is used.
    if logCfg.get('log_quiet') is True:
        _quiet = True

    logPaths = getLogPaths()
    # Ensure log paths are valid
    logDirs = [
        logPaths['root'],
        os.path.dirname(logPaths['info']),
        os.path.dirname(logPaths['error'])
    ]
    for logDir in logDirs:
        mkdir(logDir)

    # Allow minimum log level to be set via config file
    level = logging.INFO
    if logCfg.get('log_level') and isinstance(
            getattr(logging, logCfg['log_level'], None), int):
        level = getattr(logging, logCfg['log_level'])

    logSize = MAX_LOG_SIZE
    if logCfg.get('log_max_size'):
        sizeValue = logCfg['log_max_size']
        sizeUnits = {'kb': 1024, 'Mb': 1024**2, 'Gb': 1024**3}
        if sizeValue[-2:] in sizeUnits:
            logSize = int(sizeValue[:-2].strip()) * sizeUnits[sizeValue[-2:]]
        else:
            logSize = int(sizeValue)
    backupCount = int(logCfg.get('log_backup_count', LOG_BACKUP_COUNT))

    fmt = LogFormatter('[%(asctime)s] %(levelname)s: %(message)s')
    infoMaxLevel = logging.INFO
    # Create log handlers
    if logPaths['error'] != logPaths['info']:
        eh = logging.handlers.RotatingFileHandler(logPaths['error'],
                                                  maxBytes=logSize,
                                                  backupCount=backupCount)
        eh.setLevel(level)
        eh.addFilter(LogLevelFilter(min=logging.WARNING, max=logging.CRITICAL))
        eh._girderLogHandler = 'error'
        eh.setFormatter(fmt)
        logger.addHandler(eh)
        # Record cherrypy errors in our logs, too
        cherrypy.log.error_log.addHandler(eh)
    else:
        infoMaxLevel = logging.CRITICAL

    if isinstance(getattr(logging, logCfg.get('log_max_info_level', ''), None),
                  int):
        infoMaxLevel = getattr(logging, logCfg['log_max_info_level'])
    ih = logging.handlers.RotatingFileHandler(logPaths['info'],
                                              maxBytes=logSize,
                                              backupCount=backupCount)
    ih.setLevel(level)
    ih.addFilter(LogLevelFilter(min=logging.DEBUG, max=infoMaxLevel))
    ih._girderLogHandler = 'info'
    ih.setFormatter(fmt)
    logger.addHandler(ih)
    # Record cherrypy errors in our logs, too
    cherrypy.log.error_log.addHandler(ih)

    # Log http accesses to the screen and/or the info log.
    accessLog = logCfg.get('log_access', 'screen')
    if not isinstance(accessLog, (tuple, list, set)):
        accessLog = [accessLog]
    if _quiet or ('screen' not in accessLog and 'stdout' not in accessLog):
        cherrypy.config.update({'log.screen': False})
    if 'info' in accessLog:
        cherrypy.log.access_log.addHandler(ih)

    return logger
示例#13
0
def setupDaemon():
    global daemon
    if config.getConfig()['server'].get('disable_event_daemon', False):
        daemon = ForegroundEventsDaemon()
    else:
        daemon = AsyncEventsThread()
示例#14
0
def getStaticPublicPath():
    return config.getConfig()['server']['static_public_path']
示例#15
0
def getApiRoot():
    return config.getConfig()['server']['api_root']
示例#16
0
    def __init__(self, templatePath):
        self.vars = {}
        self.config = config.getConfig()

        self._templateDirs = []
        self.setTemplatePath(templatePath)
示例#17
0
def mountServer(path,
                database=None,
                fuseOptions=None,
                quiet=False,
                plugins=None):
    """
    Perform the mount.

    :param path: the mount location.
    :param database: a database connection URI, if it contains '://'.
        Otherwise, the default database is used.
    :param fuseOptions: a comma-separated string of options to pass to the FUSE
        mount.  A key without a value is taken as True.  Boolean values are
        case insensitive.  For instance, 'foreground' or 'foreground=True' will
        keep this program running until the SIGTERM or unmounted.
    :param quiet: if True, suppress Girder logs.
    :param plugins: an optional list of plugins to enable.  If None, use the
        plugins that are configured.
    """
    if quiet:
        curConfig = config.getConfig()
        curConfig.setdefault('logging', {})['log_quiet'] = True
        curConfig.setdefault('logging', {})['log_level'] = 'FATAL'
        girderformindlogger._attachFileLogHandlers()
    if database and '://' in database:
        cherrypy.config['database']['uri'] = database
    if plugins is not None:
        plugins = plugins.split(',')
    webroot, appconf = configureServer(plugins=plugins)
    girderformindlogger._setupCache()

    opClass = ServerFuse(stat=os.stat(path))
    options = {
        # By default, we run in the background so the mount command returns
        # immediately.  If we run in the foreground, a SIGTERM will shut it
        # down
        'foreground': False,
        # Cache files if their size and timestamp haven't changed.
        # This lets the OS buffer files efficiently.
        'auto_cache': True,
        # We aren't specifying our own inos
        'use_ino': False,
        # read-only file system
        'ro': True,
    }
    if sys.platform != 'darwin':
        # Automatically unmount when we try to mount again
        options['auto_unmount'] = True
    if fuseOptions:
        for opt in fuseOptions.split(','):
            if '=' in opt:
                key, value = opt.split('=', 1)
                value = (False if value.lower() == 'false' else
                         True if value.lower() == 'true' else value)
            else:
                key, value = opt, True
            if key in ('use_ino', 'ro', 'rw') and options.get(key) != value:
                logprint.warning('Ignoring the %s=%r option' % (key, value))
                continue
            options[key] = value
    Setting().set(SettingKey.GIRDER_MOUNT_INFORMATION, {
        'path': path,
        'mounttime': time.time()
    })
    FUSELogError(opClass, path, **options)