示例#1
0
    def setup_class(cls):
        UserLog.query().delete()
        Session().commit()

        def strptime(val):
            fmt = '%Y-%m-%d %H:%M:%S'
            if '.' not in val:
                return datetime.datetime.strptime(val, fmt)

            nofrag, frag = val.split(".")
            date = datetime.datetime.strptime(nofrag, fmt)

            frag = frag[:6]  # truncate to microseconds
            frag += (6 - len(frag)) * '0'  # add 0s
            return date.replace(microsecond=int(frag))

        with open(os.path.join(FIXTURES, 'journal_dump.csv')) as f:
            for row in csv.DictReader(f):
                ul = UserLog()
                for k, v in row.items():
                    if k == 'action_date':
                        v = strptime(v)
                    if k in ['user_id', 'repository_id']:
                        # nullable due to FK problems
                        v = None
                    setattr(ul, k, v)
                Session().add(ul)
            Session().commit()
示例#2
0
    def setup_class(cls):
        UserLog.query().delete()
        Session().commit()

        def strptime(val):
            fmt = '%Y-%m-%d %H:%M:%S'
            if '.' not in val:
                return datetime.datetime.strptime(val, fmt)

            nofrag, frag = val.split(".")
            date = datetime.datetime.strptime(nofrag, fmt)

            frag = frag[:6]  # truncate to microseconds
            frag += (6 - len(frag)) * '0'  # add 0s
            return date.replace(microsecond=int(frag))

        with open(os.path.join(FIXTURES, 'journal_dump.csv')) as f:
            for row in csv.DictReader(f):
                ul = UserLog()
                for k, v in row.iteritems():
                    v = safe_unicode(v)
                    if k == 'action_date':
                        v = strptime(v)
                    if k in ['user_id', 'repository_id']:
                        # nullable due to FK problems
                        v = None
                    setattr(ul, k, v)
                Session().add(ul)
            Session().commit()
    def test_push_with_readonly_credentials(self, webserver, vt):
        UserLog.query().delete()
        Session().commit()

        dest_dir = _get_tmp_dir()
        clone_url = vt.repo_url_param(webserver,
                                      vt.repo_name,
                                      username=base.TEST_USER_REGULAR_LOGIN,
                                      password=base.TEST_USER_REGULAR_PASS)
        stdout, stderr = Command(base.TESTS_TMP_PATH).execute(
            vt.repo_type, 'clone', clone_url, dest_dir)

        stdout, stderr = _add_files_and_push(webserver,
                                             vt,
                                             dest_dir,
                                             ignoreReturnCode=True,
                                             clone_url=clone_url)

        if vt.repo_type == 'git':
            assert 'The requested URL returned error: 403' in stderr or 'abort: Push access to %r denied' % str(
                vt.repo_name) in stderr
        elif vt.repo_type == 'hg':
            assert 'abort: HTTP Error 403: Forbidden' in stderr or 'abort: push failed on remote' in stderr and 'remote: Push access to %r denied' % str(
                vt.repo_name) in stdout

        action_parts = [
            ul.action.split(':', 1)
            for ul in UserLog.query().order_by(UserLog.user_log_id)
        ]
        assert [(t[0], (t[1].count(',') + 1) if len(t) == 2 else 0) for t in action_parts] == \
            [('pull', 0)]
    def test_push_new_file(self, webserver, testfork, vt):
        UserLog.query().delete()
        Session().commit()

        dest_dir = _get_tmp_dir()
        clone_url = vt.repo_url_param(webserver, vt.repo_name)
        stdout, stderr = Command(base.TESTS_TMP_PATH).execute(
            vt.repo_type, 'clone', clone_url, dest_dir)

        clone_url = vt.repo_url_param(webserver, testfork[vt.repo_type])
        stdout, stderr = _add_files_and_push(webserver,
                                             vt,
                                             dest_dir,
                                             clone_url=clone_url)

        if vt.repo_type == 'git':
            _check_proper_git_push(stdout, stderr)
        elif vt.repo_type == 'hg':
            assert 'pushing to' in stdout
            assert 'Repository size' in stdout
            assert 'Last revision is now' in stdout

        action_parts = [
            ul.action.split(':', 1)
            for ul in UserLog.query().order_by(UserLog.user_log_id)
        ]
        assert [(t[0], (t[1].count(',') + 1) if len(t) == 2 else 0) for t in action_parts] == \
            [('pull', 0), ('push', 3)]
    def test_pull(self, webserver, testfork, vt):
        UserLog.query().delete()
        Session().commit()

        dest_dir = _get_tmp_dir()
        stdout, stderr = Command(base.TESTS_TMP_PATH).execute(
            vt.repo_type, 'init', dest_dir)

        clone_url = vt.repo_url_param(webserver, vt.repo_name)
        stdout, stderr = Command(dest_dir).execute(vt.repo_type, 'pull',
                                                   clone_url)

        if vt.repo_type == 'git':
            assert 'FETCH_HEAD' in stderr
        elif vt.repo_type == 'hg':
            assert 'new changesets' in stdout

        action_parts = [
            ul.action for ul in UserLog.query().order_by(UserLog.user_log_id)
        ]
        assert action_parts == ['pull']

        # Test handling of URLs with extra '/' around repo_name
        stdout, stderr = Command(dest_dir).execute(
            vt.repo_type,
            'pull',
            clone_url.replace('/' + vt.repo_name, '/./%s/' % vt.repo_name),
            ignoreReturnCode=True)
        if issubclass(vt, HttpVcsTest):
            if vt.repo_type == 'git':
                # NOTE: when pulling from http://hostname/./vcs_test_git/ , the git client will normalize that and issue an HTTP request to /vcs_test_git/info/refs
                assert 'Already up to date.' in stdout
            else:
                assert vt.repo_type == 'hg'
                assert "abort: HTTP Error 404: Not Found" in stderr
        else:
            assert issubclass(vt, SshVcsTest)
            if vt.repo_type == 'git':
                assert "abort: Access to './%s' denied" % vt.repo_name in stderr
            else:
                assert "abort: Access to './%s' denied" % vt.repo_name in stdout

        stdout, stderr = Command(dest_dir).execute(vt.repo_type,
                                                   'pull',
                                                   clone_url.replace(
                                                       '/' + vt.repo_name,
                                                       '/%s/' % vt.repo_name),
                                                   ignoreReturnCode=True)
        if vt.repo_type == 'git':
            assert 'Already up to date.' in stdout
        else:
            assert vt.repo_type == 'hg'
            assert "no changes found" in stdout
        assert "denied" not in stderr
        assert "denied" not in stdout
        assert "404" not in stdout
示例#6
0
def action_logger(user, action, repo, ipaddr='', sa=None, 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
    :param sa: optional sqlalchemy session

    """

    if not sa:
        sa = meta.Session()
    # 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, basestring):
        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, basestring):
        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 = safe_unicode(action)

    user_log.repository = repo_obj
    user_log.repository_name = repo_name

    user_log.action_date = datetime.datetime.now()
    user_log.user_ip = ipaddr
    sa.add(user_log)

    log.info('Logging action:%s on %s by user:%s ip:%s' %
             (action, safe_unicode(repo), user_obj, ipaddr))
    if commit:
        sa.commit()
示例#7
0
    def index(self):
        users_log = UserLog.query() \
                .options(joinedload(UserLog.user)) \
                .options(joinedload(UserLog.repository))

        #FILTERING
        c.search_term = request.GET.get('filter')
        users_log = _journal_filter(users_log, c.search_term)

        users_log = users_log.order_by(UserLog.action_date.desc())

        p = safe_int(request.GET.get('page'), 1)

        def url_generator(**kw):
            return url.current(filter=c.search_term, **kw)

        c.users_log = Page(users_log,
                           page=p,
                           items_per_page=10,
                           url=url_generator)

        if request.environ.get('HTTP_X_PARTIAL_XHR'):
            return render('admin/admin_log.html')

        return render('admin/admin.html')
示例#8
0
    def _get_journal_data(self, following_repos):
        repo_ids = [x.follows_repository_id for x in following_repos
                    if x.follows_repository_id is not None]
        user_ids = [x.follows_user_id for x in following_repos
                    if x.follows_user_id is not None]

        filtering_criterion = None

        if repo_ids and user_ids:
            filtering_criterion = or_(UserLog.repository_id.in_(repo_ids),
                        UserLog.user_id.in_(user_ids))
        if repo_ids and not user_ids:
            filtering_criterion = UserLog.repository_id.in_(repo_ids)
        if not repo_ids and user_ids:
            filtering_criterion = UserLog.user_id.in_(user_ids)
        if filtering_criterion is not None:
            journal = UserLog.query() \
                .options(joinedload(UserLog.user)) \
                .options(joinedload(UserLog.repository))
            #filter
            journal = _journal_filter(journal, c.search_term)
            journal = journal.filter(filtering_criterion) \
                        .order_by(UserLog.action_date.desc())
        else:
            journal = []

        return journal
示例#9
0
def action_logger(user, action, repo, ipaddr='', sa=None, 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
    :param sa: optional sqlalchemy session

    """

    if not sa:
        sa = meta.Session()
    # 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, basestring):
        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, basestring):
        repo_name = repo.lstrip('/')
        repo_obj = Repository.get_by_repo_name(repo_name)
    else:
        repo_obj = None
        repo_name = u''

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

    user_log.repository = repo_obj
    user_log.repository_name = repo_name

    user_log.action_date = datetime.datetime.now()
    user_log.user_ip = ipaddr
    sa.add(user_log)

    log.info('Logging action:%s on %s by user:%s ip:%s',
             action, safe_unicode(repo), user_obj, ipaddr)
    if commit:
        sa.commit()
示例#10
0
    def index(self):
        users_log = UserLog.query()\
                .options(joinedload(UserLog.user))\
                .options(joinedload(UserLog.repository))

        #FILTERING
        c.search_term = request.GET.get('filter')
        users_log = _journal_filter(users_log, c.search_term)

        users_log = users_log.order_by(UserLog.action_date.desc())

        p = safe_int(request.GET.get('page', 1), 1)

        def url_generator(**kw):
            return url.current(filter=c.search_term, **kw)

        c.users_log = Page(users_log, page=p, items_per_page=10, url=url_generator)

        if request.environ.get('HTTP_X_PARTIAL_XHR'):
            return render('admin/admin_log.html')

        return render('admin/admin.html')
示例#11
0
 def teardown_class(cls):
     UserLog.query().delete()
     Session().commit()
示例#12
0
 def teardown_class(cls):
     UserLog.query().delete()
     Session().commit()
示例#13
0
 def get_unread_journal(self):
     return UserLog.query().count()
示例#14
0
    def test_push_new_repo(self, webserver, vt):
        # Clear the log so we know what is added
        UserLog.query().delete()
        Session().commit()

        # Create an empty server repo using the API
        repo_name = 'new_%s_%s' % (vt.repo_type, next(_RandomNameSequence()))
        usr = User.get_by_username(base.TEST_USER_ADMIN_LOGIN)
        params = {
            "id":
            7,
            "api_key":
            usr.api_key,
            "method":
            'create_repo',
            "args":
            dict(repo_name=repo_name,
                 owner=base.TEST_USER_ADMIN_LOGIN,
                 repo_type=vt.repo_type),
        }
        req = urllib.request.Request(
            'http://%s:%s/_admin/api' % webserver.server_address,
            data=ascii_bytes(json.dumps(params)),
            headers={'content-type': 'application/json'})
        response = urllib.request.urlopen(req)
        result = json.loads(response.read())
        # Expect something like:
        # {u'result': {u'msg': u'Created new repository `new_XXX`', u'task': None, u'success': True}, u'id': 7, u'error': None}
        assert result['result']['success']

        # Create local clone of the empty server repo
        local_clone_dir = _get_tmp_dir()
        clone_url = vt.repo_url_param(webserver, repo_name)
        stdout, stderr = Command(base.TESTS_TMP_PATH).execute(
            vt.repo_type, 'clone', clone_url, local_clone_dir)

        # Make 3 commits and push to the empty server repo.
        # The server repo doesn't have any other heads than the
        # refs/heads/master we are pushing, but the `git log` in the push hook
        # should still list the 3 commits.
        stdout, stderr = _add_files_and_push(webserver,
                                             vt,
                                             local_clone_dir,
                                             clone_url=clone_url)
        if vt.repo_type == 'git':
            _check_proper_git_push(stdout, stderr)
        elif vt.repo_type == 'hg':
            assert 'pushing to ' in stdout
            assert 'remote: added ' in stdout

        # Verify that we got the right events in UserLog. Expect something like:
        # <UserLog('id:new_git_XXX:started_following_repo')>
        # <UserLog('id:new_git_XXX:user_created_repo')>
        # <UserLog('id:new_git_XXX:pull')>
        # <UserLog('id:new_git_XXX:push:aed9d4c1732a1927da3be42c47eb9afdc200d427,d38b083a07af10a9f44193486959a96a23db78da,4841ff9a2b385bec995f4679ef649adb3f437622')>
        action_parts = [
            ul.action.split(':', 1)
            for ul in UserLog.query().order_by(UserLog.user_log_id)
        ]
        assert [
            (t[0], (t[1].count(',') + 1) if len(t) == 2 else 0)
            for t in action_parts
        ] == ([
            ('started_following_repo', 0), ('user_created_repo', 0),
            ('pull', 0), ('push', 3)
        ] if vt.repo_type == 'git' else [
            ('started_following_repo', 0),
            ('user_created_repo', 0),
            # (u'pull', 0), # Mercurial outgoing hook is not called for empty clones
            ('push', 3)
        ])