Beispiel #1
0
def action_logger(user, action, repo, ipaddr='', commit=False):
    """
    Action logger for various actions made by users

    :param user: user that made this action, can be a unique username string or
        object containing user_id attribute
    :param action: action to log, should be on of predefined unique actions for
        easy translations
    :param repo: string name of repository or object containing repo_id,
        that action was made on
    :param ipaddr: optional IP address from what the action was made

    """

    # if we don't get explicit IP address try to get one from registered user
    # in tmpl context var
    if not ipaddr:
        ipaddr = getattr(get_current_authuser(), 'ip_addr', '')

    if getattr(user, 'user_id', None):
        user_obj = User.get(user.user_id)
    elif isinstance(user, str):
        user_obj = User.get_by_username(user)
    else:
        raise Exception('You have to provide a user object or a username')

    if getattr(repo, 'repo_id', None):
        repo_obj = Repository.get(repo.repo_id)
        repo_name = repo_obj.repo_name
    elif isinstance(repo, str):
        repo_name = repo.lstrip('/')
        repo_obj = Repository.get_by_repo_name(repo_name)
    else:
        repo_obj = None
        repo_name = ''

    user_log = UserLog()
    user_log.user_id = user_obj.user_id
    user_log.username = user_obj.username
    user_log.action = action

    user_log.repository = repo_obj
    user_log.repository_name = repo_name

    user_log.action_date = datetime.datetime.now()
    user_log.user_ip = ipaddr
    meta.Session().add(user_log)

    log.info('Logging action:%s on %s by user:%s ip:%s', action, repo,
             user_obj, ipaddr)
    if commit:
        meta.Session().commit()
Beispiel #2
0
def make_ui(read_from='file', path=None, checkpaths=True, clear_session=True):
    """
    A function that will read python rc files or database
    and make an mercurial ui object from read options

    :param path: path to mercurial config file
    :param checkpaths: check the path
    :param read_from: read from 'file' or 'db'
    """

    baseui = ui.ui()

    # clean the baseui object
    baseui._ocfg = config.config()
    baseui._ucfg = config.config()
    baseui._tcfg = config.config()

    if read_from == 'file':
        if not os.path.isfile(path):
            log.debug('hgrc file is not present at %s, skipping...' % path)
            return False
        log.debug('reading hgrc from %s' % path)
        cfg = config.config()
        cfg.read(path)
        for section in ui_sections:
            for k, v in cfg.items(section):
                log.debug('settings ui from file: [%s] %s=%s' %
                          (section, k, v))
                baseui.setconfig(safe_str(section), safe_str(k), safe_str(v))

    elif read_from == 'db':
        sa = meta.Session()
        ret = sa.query(Ui).all()

        hg_ui = ret
        for ui_ in hg_ui:
            if ui_.ui_active:
                ui_val = safe_str(ui_.ui_value)
                if ui_.ui_section == 'hooks' and BRAND != 'kallithea' and ui_val.startswith(
                        'python:' + BRAND + '.lib.hooks.'):
                    ui_val = ui_val.replace('python:' + BRAND + '.lib.hooks.',
                                            'python:kallithea.lib.hooks.')
                log.debug('settings ui from db: [%s] %s=%s', ui_.ui_section,
                          ui_.ui_key, ui_val)
                baseui.setconfig(safe_str(ui_.ui_section),
                                 safe_str(ui_.ui_key), ui_val)
            if ui_.ui_key == 'push_ssl':
                # force set push_ssl requirement to False, kallithea
                # handles that
                baseui.setconfig(safe_str(ui_.ui_section),
                                 safe_str(ui_.ui_key), False)
        if clear_session:
            meta.Session.remove()

        # prevent interactive questions for ssh password / passphrase
        ssh = baseui.config('ui', 'ssh', default='ssh')
        baseui.setconfig('ui', 'ssh',
                         '%s -oBatchMode=yes -oIdentitiesOnly=yes' % ssh)

    return baseui
Beispiel #3
0
def upgrade(migrate_engine):
    """
    Upgrade operations go here.
    Don't create your own engine; bind migrate_engine to your metadata
    """
    _reset_base(migrate_engine)
    from kallithea.lib.dbmigrate.schema import db_1_5_0
    #==========================================================================
    # USER LOGS
    #==========================================================================

    tbl = db_1_5_0.UserLog.__table__
    username = Column("username",
                      String(255, convert_unicode=False, assert_unicode=None),
                      nullable=True,
                      unique=None,
                      default=None)
    # create username column
    username.create(table=tbl)

    _Session = meta.Session()
    ## after adding that column fix all usernames
    users_log = _Session.query(db_1_5_0.UserLog)\
            .options(joinedload(db_1_5_0.UserLog.user))\
            .options(joinedload(db_1_5_0.UserLog.repository)).all()

    for entry in users_log:
        entry.username = entry.user.username
        _Session.add(entry)
    _Session.commit()

    #alter username to not null
    tbl_name = db_1_5_0.UserLog.__tablename__
    tbl = Table(tbl_name,
                MetaData(bind=migrate_engine),
                autoload=True,
                autoload_with=migrate_engine)
    col = tbl.columns.username

    # remove nullability from revision field
    col.alter(nullable=False)

    # issue fixups
    fixups(db_1_5_0, meta.Session)
Beispiel #4
0
def make_ui(repo_path=None):
    """
    Create an Mercurial 'ui' object based on database Ui settings, possibly
    augmenting with content from a hgrc file.
    """
    baseui = mercurial.ui.ui()

    # clean the baseui object
    baseui._ocfg = mercurial.config.config()
    baseui._ucfg = mercurial.config.config()
    baseui._tcfg = mercurial.config.config()

    sa = meta.Session()
    for ui_ in sa.query(Ui).order_by(Ui.ui_section, Ui.ui_key):
        if ui_.ui_active:
            log.debug('config from db: [%s] %s=%r', ui_.ui_section, ui_.ui_key,
                      ui_.ui_value)
            baseui.setconfig(
                ascii_bytes(ui_.ui_section), ascii_bytes(ui_.ui_key),
                b'' if ui_.ui_value is None else safe_bytes(ui_.ui_value))

    # force set push_ssl requirement to False, Kallithea handles that
    baseui.setconfig(b'web', b'push_ssl', False)
    baseui.setconfig(b'web', b'allow_push', b'*')
    # prevent interactive questions for ssh password / passphrase
    ssh = baseui.config(b'ui', b'ssh', default=b'ssh')
    baseui.setconfig(b'ui', b'ssh',
                     b'%s -oBatchMode=yes -oIdentitiesOnly=yes' % ssh)
    # push / pull hooks
    baseui.setconfig(b'hooks', b'changegroup.kallithea_log_push_action',
                     b'python:kallithea.lib.hooks.log_push_action')
    baseui.setconfig(b'hooks', b'outgoing.kallithea_log_pull_action',
                     b'python:kallithea.lib.hooks.log_pull_action')

    if repo_path is not None:
        # Note: MercurialRepository / mercurial.localrepo.instance will do this too, so it will always be possible to override db settings or what is hardcoded above
        baseui.readconfig(repo_path)

    assert baseui.plain(
    )  # set by hgcompat.monkey_do (invoked from import of vcs.backends.hg) to minimize potential impact of loading config files
    return baseui
Beispiel #5
0
def log_in_user(user, remember, is_external_auth, ip_addr):
    """
    Log a `User` in and update session and cookies. If `remember` is True,
    the session cookie is set to expire in a year; otherwise, it expires at
    the end of the browser session.

    Returns populated `AuthUser` object.
    """
    # It should not be possible to explicitly log in as the default user.
    assert not user.is_default_user, user

    auth_user = AuthUser.make(dbuser=user,
                              is_external_auth=is_external_auth,
                              ip_addr=ip_addr)
    if auth_user is None:
        return None

    user.update_lastlogin()
    meta.Session().commit()

    # Start new session to prevent session fixation attacks.
    session.invalidate()
    session['authuser'] = cookie = auth_user.to_cookie()

    # If they want to be remembered, update the cookie.
    # NOTE: Assumes that beaker defaults to browser session cookie.
    if remember:
        t = datetime.datetime.now() + datetime.timedelta(days=365)
        session._set_cookie_expires(t)

    session.save()

    log.info(
        'user %s is now authenticated and stored in '
        'session, session attrs %s', user.username, cookie)

    # dumps session attrs back to cookie
    session._update_cookie_out()

    return auth_user
Beispiel #6
0
def map_groups(path):
    """
    Given a full path to a repository, create all nested groups that this
    repo is inside. This function creates parent-child relationships between
    groups and creates default perms for all new groups.

    :param paths: full path to repository
    """
    from kallithea.model.repo_group import RepoGroupModel
    sa = meta.Session()
    groups = path.split(db.URL_SEP)
    parent = None
    group = None

    # last element is repo in nested groups structure
    groups = groups[:-1]
    rgm = RepoGroupModel()
    owner = User.get_first_admin()
    for lvl, group_name in enumerate(groups):
        group_name = '/'.join(groups[:lvl] + [group_name])
        group = RepoGroup.get_by_group_name(group_name)
        desc = '%s group' % group_name

        # skip folders that are now removed repos
        if REMOVED_REPO_PAT.match(group_name):
            break

        if group is None:
            log.debug('creating group level: %s group_name: %s', lvl,
                      group_name)
            group = RepoGroup(group_name, parent)
            group.group_description = desc
            group.owner = owner
            sa.add(group)
            rgm._create_default_perms(group)
            sa.flush()

        parent = group
    return group
Beispiel #7
0
def repo2db_mapper(initial_repo_dict,
                   remove_obsolete=False,
                   install_git_hooks=False,
                   user=None,
                   overwrite_git_hooks=False):
    """
    maps all repos given in initial_repo_dict, non existing repositories
    are created, if remove_obsolete is True it also check for db entries
    that are not in initial_repo_dict and removes them.

    :param initial_repo_dict: mapping with repositories found by scanning methods
    :param remove_obsolete: check for obsolete entries in database
    :param install_git_hooks: if this is True, also check and install git hook
        for a repo if missing
    :param overwrite_git_hooks: if this is True, overwrite any existing git hooks
        that may be encountered (even if user-deployed)
    """
    from kallithea.model.repo import RepoModel
    from kallithea.model.scm import ScmModel
    sa = meta.Session()
    repo_model = RepoModel()
    if user is None:
        user = User.get_first_admin()
    added = []

    # creation defaults
    defs = Setting.get_default_repo_settings(strip_prefix=True)
    enable_statistics = defs.get('repo_enable_statistics')
    enable_downloads = defs.get('repo_enable_downloads')
    private = defs.get('repo_private')

    for name, repo in initial_repo_dict.items():
        group = map_groups(name)
        db_repo = repo_model.get_by_repo_name(name)
        # found repo that is on filesystem not in Kallithea database
        if not db_repo:
            log.info('repository %s not found, creating now', name)
            added.append(name)
            desc = (repo.description if repo.description != 'unknown' else
                    '%s repository' % name)

            new_repo = repo_model._create_repo(
                repo_name=name,
                repo_type=repo.alias,
                description=desc,
                repo_group=getattr(group, 'group_id', None),
                owner=user,
                enable_downloads=enable_downloads,
                enable_statistics=enable_statistics,
                private=private,
                state=Repository.STATE_CREATED)
            sa.commit()
            # we added that repo just now, and make sure it has githook
            # installed, and updated server info
            if new_repo.repo_type == 'git':
                git_repo = new_repo.scm_instance
                ScmModel().install_git_hooks(git_repo)
                # update repository server-info
                log.debug('Running update server info')
                git_repo._update_server_info()
            new_repo.update_changeset_cache()
        elif install_git_hooks:
            if db_repo.repo_type == 'git':
                ScmModel().install_git_hooks(db_repo.scm_instance,
                                             force_create=overwrite_git_hooks)

    removed = []
    # remove from database those repositories that are not in the filesystem
    for repo in sa.query(Repository).all():
        if repo.repo_name not in initial_repo_dict:
            if remove_obsolete:
                log.debug("Removing non-existing repository found in db `%s`",
                          repo.repo_name)
                try:
                    RepoModel().delete(repo, forks='detach', fs_remove=False)
                    sa.commit()
                except Exception:
                    #don't hold further removals on error
                    log.error(traceback.format_exc())
                    sa.rollback()
            removed.append(repo.repo_name)
    return added, removed
Beispiel #8
0
def get_session():
    sa = meta.Session()
    return sa
Beispiel #9
0
 def __init__(self, sa=None):
     if sa is not None:
         self.sa = sa
     else:
         self.sa = meta.Session()
Beispiel #10
0
def get_session():
    if CELERY_ON:
        engine = engine_from_config(config, 'sqlalchemy.db1.')
        init_model(engine)
    sa = meta.Session()
    return sa