def commits(self, pid=None, tid=None, cid=None, gid=None, start=0, limit=10, dfrom=None, dto=None, inc_merge_commit=None, inc_repos=None, metadata=None, exc_groups=None, inc_groups=None): c = Commits(index.Connector()) projects_index = Projects() idents = Contributors() query_kwargs = utils.resolv_filters( projects_index, idents, pid, tid, cid, gid, dfrom, dto, inc_repos, inc_merge_commit, metadata, exc_groups, inc_groups) query_kwargs.update( {'start': start, 'limit': limit}) resp = c.get_commits(**query_kwargs) for cmt in resp[2]: # Get extra metadata keys extra = set(cmt.keys()) - set(PROPERTIES.keys()) cmt['metadata'] = list(extra) cmt['repos'] = [r for r in cmt['repos'] if not r.startswith('meta_ref: ')] # Compute link to access commit diff based on the # URL template provided in projects.yaml cmt['gitwebs'] = [ projects_index.get_gitweb_link(r) % {'sha': cmt['sha']} for r in cmt['repos']] cmt['projects'] = utils.get_projects_from_references( projects_index, cmt['repos']) # Also remove the URI part cmt['repos'] = [":".join(p.split(':')[-2:]) for p in cmt['repos']] # Request the ident index to fetch author/committer name/email for elm in ('author', 'committer'): ident = list(idents.get_idents_by_emails( cmt['%s_email' % elm]).values())[0] cmt['%s_email' % elm] = ident['default-email'] if ident['name']: cmt['%s_name' % elm] = ident['name'] # Convert the TTL to something human readable cmt['ttl'] = str((datetime.fromtimestamp(cmt['ttl']) - datetime.fromtimestamp(0))) cmt['author_gravatar'] = \ hashlib.md5(cmt['author_email'].encode( errors='ignore')).hexdigest() cmt['committer_gravatar'] = \ hashlib.md5(cmt['committer_email'].encode( errors='ignore')).hexdigest() if len(cmt['commit_msg']) > 80: cmt['commit_msg'] = cmt['commit_msg'][0:76] + '...' # Add cid and ccid cmt['cid'] = utils.encrypt(xorkey, cmt['author_email']) cmt['ccid'] = utils.encrypt(xorkey, cmt['committer_email']) # Remove email details del cmt['author_email'] del cmt['committer_email'] return resp
def test_users_crud_admin(self): headers = { 'REMOTE_USER': '******', 'ADMIN_TOKEN': '12345'} # User should not exist response = self.app.get( '/api/v1/users/admin', headers=headers, status="*") self.assertEqual(response.status_int, 404) # Push user details data = { 'uid': 'admin', 'name': 'saboten', 'default-email': 'saboten@domain1', 'emails': [ {'email': 'saboten@domain1', 'groups': [ {'group': 'ugroup2', 'begin-date': '1410456005', 'end-date': '1410476005'} ]} ]} response = self.app.put_json( '/api/v1/users/admin', data, headers=headers, status="*") self.assertEqual(response.status_int, 201) # Get admin user details response = self.app.get( '/api/v1/users/admin', headers=headers, status="*") self.assertEqual(response.status_int, 200) rdata = copy.deepcopy(data) rdata['cid'] = utils.encrypt(xorkey, 'saboten@domain1') self.assertDictEqual(response.json, rdata) # Update admin user details data['name'] = 'sabosan' response = self.app.post_json( '/api/v1/users/admin', data, headers=headers, status="*") self.assertEqual(response.status_int, 200) # Get admin user details response = self.app.get( '/api/v1/users/admin', headers=headers, status="*") self.assertEqual(response.status_int, 200) rdata = copy.deepcopy(data) rdata['cid'] = utils.encrypt(xorkey, 'saboten@domain1') self.assertDictEqual(response.json, rdata) # Get admin user details w/o admin_token headers = {'REMOTE_USER': '******'} response = self.app.get( '/api/v1/users/admin', headers=headers, status="*") self.assertEqual(response.status_int, 200) rdata = copy.deepcopy(data) rdata['cid'] = utils.encrypt(xorkey, 'saboten@domain1') self.assertDictEqual(response.json, rdata)
def top_authors_sanitize( self, idents, authors, commits, top, resolv_name=True, clean_email=True): sanitized = utils.authors_sanitize(idents, authors) top_authors_s = [] for email, v in sanitized.items(): top_authors_s.append( {'cid': utils.encrypt(xorkey, v[2]), 'email': email, 'gravatar': hashlib.md5( email.encode(errors='ignore')).hexdigest(), 'amount': int(v[0]), 'name': v[1]}) top_authors_s_sorted = sorted(top_authors_s, key=lambda k: k['amount'], reverse=True) if top is None: top = 10 else: top = int(top) # If top set to a negative value all results will be returned if top >= 0: top_authors_s_sorted = top_authors_s_sorted[:int(top)] if resolv_name: self.resolv_name(commits, top_authors_s_sorted) return top_authors_s_sorted
def search_authors(self, query=""): ret_limit = 100 c = Commits(index.Connector()) ret = c.es.search(index=c.index, q=query, df="author_name", size=10000, default_operator="AND", _source_includes=["author_name", "author_email"]) ret = ret['hits']['hits'] if not len(ret): return {} idents = Contributors() authors = dict([(d['_source']['author_email'], d['_source']['author_name']) for d in ret]) result = {} _idents = idents.get_idents_by_emails(list(authors.keys())[:ret_limit]) for iid, ident in _idents.items(): email = ident['default-email'] name = ident['name'] or authors[email] result[utils.encrypt(xorkey, iid)] = { 'name': name, 'gravatar': hashlib.md5(email.encode(errors='ignore')).hexdigest() } result = OrderedDict( sorted(list(result.items()), key=lambda t: t[1]['name'])) return result
def search_authors(self, query=""): ret_limit = 100 c = Commits(index.Connector()) ret = c.es.search( index=c.index, doc_type=c.dbname, q=query, df="author_name", size=10000, default_operator="AND", _source_include=["author_name", "author_email"]) ret = ret['hits']['hits'] if not len(ret): return {} idents = Contributors() authors = dict([(d['_source']['author_email'], d['_source']['author_name']) for d in ret]) result = {} _idents = idents.get_idents_by_emails(list(authors.keys())[:ret_limit]) for iid, ident in _idents.items(): email = ident['default-email'] name = ident['name'] or authors[email] result[utils.encrypt(xorkey, iid)] = { 'name': name, 'gravatar': hashlib.md5( email.encode(errors='ignore')).hexdigest()} result = OrderedDict( sorted(list(result.items()), key=lambda t: t[1]['name'])) return result
def top_authors_sanitize( self, idents, authors, commits, top, resolv_name=True, clean_email=True): sanitized = utils.authors_sanitize(idents, authors) top_authors_s = [] for email, v in sanitized.items(): top_authors_s.append( {'cid': utils.encrypt(xorkey, v[2]), 'email': email, 'gravatar': hashlib.md5(email.encode('utf-8')).hexdigest(), 'amount': int(v[0]), 'name': v[1]}) top_authors_s_sorted = sorted(top_authors_s, key=lambda k: k['amount'], reverse=True) if top is None: top = 10 else: top = int(top) # If top set to a negative value all results will be returned if top >= 0: top_authors_s_sorted = top_authors_s_sorted[:int(top)] if resolv_name: self.resolv_name(commits, top_authors_s_sorted) return top_authors_s_sorted
def index(self, prefix=None, nameonly='false', withstats='false'): ci = Commits(index.Connector()) contributors_index = Contributors() groups = contributors_index.get_groups() if nameonly == 'true': ret = dict([(k, None) for k in groups.keys()]) if prefix: ret = dict([(k, None) for k in ret.keys() if k.lower().startswith(prefix)]) return ret ret_groups = {} for group, data in groups.items(): if prefix and not group.lower().startswith(prefix.lower()): continue rg = {'members': {}, 'description': data['description'], 'domains': data.get('domains', [])} emails = data['emails'].keys() members = contributors_index.get_idents_by_emails(emails) for id, member in members.items(): member['gravatar'] = hashlib.md5( member['default-email']).hexdigest() # TODO(fbo): bounces should be a list of bounce # Let's deactivate that for now # member['bounces'] = bounces del member['emails'] if not member['name']: # Try to find it among commits suggested = ci.get_commits_author_name_by_emails( [member['default-email']]) name = suggested.get(member['default-email'], 'Unknown name') member['name'] = name del member['default-email'] rg['members'][utils.encrypt(xorkey, id)] = member if withstats == 'true': # TODO(fbo): This endpoint needs to handle some filters like # dates bounces to return more accurate stats # Fetch the number of projects and repos contributed to p_filter = {} query_kwargs = { 'mails': data['emails'], 'merge_commit': False, 'repos': p_filter, } projects = Projects() tops_ctl = tops.TopProjectsController() top_projects = tops_ctl.gbycommits( ci, projects, query_kwargs, False) top_repos = tops_ctl.gbycommits( ci, projects, query_kwargs, True) rg['projects_amount'] = len(top_projects) rg['repos_amount'] = len(top_repos) ret_groups[group] = rg return ret_groups
def test_search_authors(self): root.search.indexname = 'repoxplorertest' response = self.app.get('/api/v1/search/search_authors?query=jean') cid = utils.encrypt(xorkey, '*****@*****.**') expected = { cid: {'name': 'Jean Paul', 'gravatar': 'c184ebe163aa66b25668757000116849'}} self.assertDictEqual(response.json, expected)
def get(self, uid): self._authorize(uid) _users = users.Users(index.Connector(index_suffix='users')) u = _users.get(uid) if not u: abort(404) u['cid'] = utils.encrypt(xorkey, u['default-email']) return u
def get(self, uid): self._authorize(uid) _users = users.Users( index.Connector(index_suffix='users')) u = _users.get(uid) if not u: abort(404) u['cid'] = utils.encrypt(xorkey, u['default-email']) return u
def index(self, prefix=None, nameonly='false', withstats='false', pid=None, dfrom=None, dto=None, inc_merge_commit=None): ci = Commits(index.Connector()) contributors_index = Contributors() groups = contributors_index.get_groups() if withstats == 'true': projects_index = Projects() if nameonly == 'true': ret = dict([(k, None) for k in groups.keys()]) if prefix: ret = dict([(k, None) for k in ret.keys() if k.lower().startswith(prefix)]) return ret ret_groups = {} for group, data in groups.items(): if prefix and not group.lower().startswith(prefix.lower()): continue rg = {'members': {}, 'description': data.get('description', ''), 'domains': data.get('domains', [])} emails = list(data['emails'].keys()) members = contributors_index.get_idents_by_emails(emails) for id, member in members.items(): member['gravatar'] = hashlib.md5( member['default-email'].encode( errors='ignore')).hexdigest() # TODO(fbo): bounces should be a list of bounce # Let's deactivate that for now # member['bounces'] = bounces del member['emails'] if not member['name']: # Try to find it among commits suggested = ci.get_commits_author_name_by_emails( [member['default-email']]) name = suggested.get(member['default-email'], 'Unnamed') member['name'] = name del member['default-email'] rg['members'][utils.encrypt(xorkey, id)] = member if withstats == 'true': # Fetch the number of projects and repos contributed to query_kwargs = utils.resolv_filters( projects_index, contributors_index, pid, None, None, group, dfrom, dto, None, inc_merge_commit, None, None, None) repos = [r for r in ci.get_repos(**query_kwargs)[1] if not r.startswith('meta_ref: ')] projects = utils.get_projects_from_references( projects_index, repos) rg['repos_amount'] = len(repos) rg['projects_amount'] = len(projects) ret_groups[group] = rg return ret_groups
def test_get_infos_contributor(self): expected = { 'name': 'Nakata Daisuke', 'mails_amount': 1, 'gravatar': '505dcbea438008f24001e2928cdc0678', } cid = utils.encrypt(xorkey, '*****@*****.**') response = self.app.get('/api/v1/infos/contributor', {'cid': cid}) self.assertEqual(response.status_int, 200) self.assertDictEqual(response.json, expected)
def test_get_tops_authors_bycommits(self): with patch.object(root.projects.Projects, 'get_projects') as m: expected_top1 = { 'gravatar': 'c184ebe163aa66b25668757000116849', 'amount': 3, 'name': 'Jean Paul', 'cid': utils.encrypt(xorkey, '*****@*****.**'), } expected_top2 = { 'gravatar': '505dcbea438008f24001e2928cdc0678', 'amount': 1, 'name': 'Nakata Daisuke', 'cid': utils.encrypt(xorkey, '*****@*****.**'), } m.return_value = self.projects root.tops.indexname = 'repoxplorertest' response = self.app.get( '/api/v1/tops/authors/bycommits?pid=test&inc_merge_commit=on') assert response.status_int == 200 self.assertDictEqual(response.json[0], expected_top1) self.assertDictEqual(response.json[1], expected_top2) self.assertEqual(len(response.json), 2) # Same request but with a limit set to 1 response = self.app.get('/api/v1/tops/authors/bycommits?pid=test' '&inc_merge_commit=on&limit=1') assert response.status_int == 200 self.assertDictEqual(response.json[0], expected_top1) self.assertEqual(len(response.json), 1) # Validate the CSV endpoint mode # First convert all expected dict values to str expected_top1 = dict((k, str(v)) for k, v in expected_top1.items()) expected_top2 = dict((k, str(v)) for k, v in expected_top2.items()) response = self.app.get( '/api/v1/tops/authors/bycommits?' 'pid=test&inc_merge_commit=on', headers={'Accept': 'text/csv'}) assert response.status_int == 200 csvret = build_dict_from_csv(response.body) self.assertDictEqual(csvret[0], expected_top1) self.assertDictEqual(csvret[1], expected_top2) self.assertEqual(len(csvret), 2)
def test_get_infos_contributor(self): expected = { 'name': 'Nakata Daisuke', 'mails_amount': 1, 'gravatar': '505dcbea438008f24001e2928cdc0678', } cid = utils.encrypt(xorkey, '*****@*****.**') response = self.app.get( '/api/v1/infos/contributor', {'cid': cid}) self.assertEqual(response.status_int, 200) self.assertDictEqual(response.json, expected)
def test_get_tops_projects_bylchanged(self): cid = utils.encrypt(xorkey, '*****@*****.**') response = self.app.get( '/api/v1/tops/projects/bylchanged?cid=%s' % cid) expected_top1 = { 'amount': 19, 'name': 'test' } assert response.status_int == 200 self.assertDictEqual(response.json[0], expected_top1) self.assertEqual(len(response.json), 1) # Ask repo details response = self.app.get( '/api/v1/tops/projects/bylchanged?cid=' '%s&inc_repos_detail=true' % cid) expected_top1_d = { 'amount': 19, 'name': 'monkey:master', 'projects': ['test'] } assert response.status_int == 200 self.assertDictEqual(response.json[0], expected_top1_d) self.assertEqual(len(response.json), 1) # Check the limit attribute response = self.app.get( '/api/v1/tops/projects/bylchanged?cid=%s&limit=0' % cid) assert response.status_int == 200 self.assertEqual(len(response.json), 0) # Validate the CSV endpoint mode # First convert all expected dict values to str expected_top1 = dict((k, str(v)) for k, v in expected_top1.items()) for k, v in expected_top1_d.items(): if isinstance(v, list): # A list, that will be semi column separated, can be return # when inc_repos_detail is passed to this endpoint expected_top1_d[k] = ";".join(v) else: expected_top1_d[k] = str(v) response = self.app.get( '/api/v1/tops/projects/bylchanged?' 'cid=%s' % cid, headers={'Accept': 'text/csv'}) assert response.status_int == 200 csvret = build_dict_from_csv(response.body) self.assertDictEqual(csvret[0], expected_top1) response = self.app.get( '/api/v1/tops/projects/bylchanged?' 'cid=%s&inc_repos_detail=true' % cid, headers={'Accept': 'text/csv'}) assert response.status_int == 200 csvret = build_dict_from_csv(response.body) self.assertDictEqual(csvret[0], expected_top1_d)
def test_get_tops_authors_bycommits(self): expected_top1 = { 'gravatar': 'c184ebe163aa66b25668757000116849', 'amount': 3, 'name': 'Jean Paul', 'cid': utils.encrypt(xorkey, '*****@*****.**'), } expected_top2 = { 'gravatar': '505dcbea438008f24001e2928cdc0678', 'amount': 1, 'name': 'Nakata Daisuke', 'cid': utils.encrypt(xorkey, '*****@*****.**'), } response = self.app.get( '/api/v1/tops/authors/bycommits?pid=test&inc_merge_commit=on') assert response.status_int == 200 self.assertDictEqual(response.json[0], expected_top1) self.assertDictEqual(response.json[1], expected_top2) self.assertEqual(len(response.json), 2) # Same request but with a limit set to 1 response = self.app.get( '/api/v1/tops/authors/bycommits?pid=test' '&inc_merge_commit=on&limit=1') assert response.status_int == 200 self.assertDictEqual(response.json[0], expected_top1) self.assertEqual(len(response.json), 1) # Validate the CSV endpoint mode # First convert all expected dict values to str expected_top1 = dict((k, str(v)) for k, v in expected_top1.items()) expected_top2 = dict((k, str(v)) for k, v in expected_top2.items()) response = self.app.get( '/api/v1/tops/authors/bycommits?' 'pid=test&inc_merge_commit=on', headers={'Accept': 'text/csv'}) assert response.status_int == 200 csvret = build_dict_from_csv(response.body) self.assertDictEqual(csvret[0], expected_top1) self.assertDictEqual(csvret[1], expected_top2) self.assertEqual(len(csvret), 2)
def test_get_tops_authors_bylchanged(self): expected_top1 = { 'amount': 19, 'gravatar': 'c184ebe163aa66b25668757000116849', 'cid': utils.encrypt(xorkey, '*****@*****.**'), 'name': 'Jean Paul' } expected_top2 = { 'amount': 10, 'gravatar': '505dcbea438008f24001e2928cdc0678', 'cid': utils.encrypt(xorkey, '*****@*****.**'), 'name': 'Nakata Daisuke' } response = self.app.get('/api/v1/tops/authors/bylchanged?pid=test') assert response.status_int == 200 self.assertDictEqual(response.json[0], expected_top1) self.assertDictEqual(response.json[1], expected_top2) self.assertEqual(len(response.json), 2) # Same request but with a limit set to 1 response = self.app.get( '/api/v1/tops/authors/bylchanged?pid=test&limit=1') assert response.status_int == 200 self.assertDictEqual(response.json[0], expected_top1) self.assertEqual(len(response.json), 1) # Validate the CSV endpoint mode # First convert all expected dict values to str expected_top1 = dict((k, str(v)) for k, v in expected_top1.items()) expected_top2 = dict((k, str(v)) for k, v in expected_top2.items()) response = self.app.get( '/api/v1/tops/authors/bylchanged?pid=test', headers={'Accept': 'text/csv'}) assert response.status_int == 200 csvret = build_dict_from_csv(response.body) self.assertDictEqual(csvret[0], expected_top1) self.assertDictEqual(csvret[1], expected_top2) self.assertEqual(len(csvret), 2)
def test_get_tops_authors_diff(self): # with patch.object(root.projects.Projects, 'get_projects') as m: expected_diff = { 'gravatar': '505dcbea438008f24001e2928cdc0678', 'amount': 1, 'name': 'Nakata Daisuke', 'cid': utils.encrypt(xorkey, '*****@*****.**'), } response = self.app.get( '/api/v1/tops/authors/diff?pid=test&dfromref=2014-01-01' '&dtoref=2014-09-03&dfrom=2014-09-04&dto=2017-01-01' '&inc_merge_commit=on&limit=1') assert response.status_int == 200 self.assertDictEqual(response.json[0], expected_diff) self.assertEqual(len(response.json), 1)
def test_get_infos_contributor(self): expected = { 'repos_amount': 1, 'name': 'Nakata Daisuke', 'mails_amount': 1, 'gravatar': '505dcbea438008f24001e2928cdc0678', 'projects_amount': 1 } cid = utils.encrypt(xorkey, '*****@*****.**') with patch.object(root.projects.Projects, 'get_projects') as m: root.infos.indexname = 'repoxplorertest' m.return_value = self.projects response = self.app.get('/api/v1/infos/contributor?cid=%s' % cid) self.assertEqual(response.status_int, 200) self.assertDictEqual(response.json, expected)
def test_get_infos(self): expected = { 'first': 1393860653, 'last': 1410456005, 'commits_amount': 3, 'authors_amount': 2, 'line_modifieds_amount': 29, 'duration': 16595352, 'ttl_average': 0, 'projects_amount': 1, 'repos_amount': 1, } response = self.app.get('/api/v1/infos/infos?pid=test') self.assertEqual(response.status_int, 200) self.assertDictEqual(response.json, expected) # Check endpoint CSV mode response = self.app.get('/api/v1/infos/infos?pid=test', headers={'Accept': 'text/csv'}) self.assertEqual(response.status_int, 200) csvret = build_dict_from_csv(response.body) # Convert all dict values to str expected = dict((k, str(v)) for k, v in expected.items()) self.assertDictEqual(csvret[0], expected) self.assertEqual(len(csvret), 1) # Make an attempt by setting meta ref to True new_projects_file = """ project-templates: default: uri: https://github.com/nakata/%(name)s.git branches: - master projects: test: meta-ref: true repos: monkey: template: default """ self.db = set_projects_definition(self.conp, new_projects_file) expected = { 'first': 1393860653, 'last': 1410456005, 'commits_amount': 2, 'authors_amount': 2, 'line_modifieds_amount': 18, 'duration': 16595352, 'ttl_average': 0, 'projects_amount': 1, 'repos_amount': 1, } response = self.app.get('/api/v1/infos/infos?pid=test') self.assertEqual(response.status_int, 200) self.assertDictEqual(response.json, expected) # Test with a cid expected = { 'projects_amount': 1, 'first': 1410456005, 'line_modifieds_amount': 10, 'duration': 0, 'commits_amount': 1, 'ttl_average': 0, 'last': 1410456005, 'authors_amount': 1, 'repos_amount': 1 } cid = utils.encrypt(xorkey, '*****@*****.**') response = self.app.get('/api/v1/infos/infos', {'cid': cid}) self.assertEqual(response.status_int, 200) self.assertDictEqual(response.json, expected)
def test_users_crud_user(self): # First set a user as admin data = { 'uid': 'saboten', 'name': 'Cactus Saboten', 'default-email': 'saboten@domain1', 'emails': [{ 'email': 'saboten@domain1', 'groups': [{ 'group': 'ugroup2', 'begin-date': '1410456005', 'end-date': '1410476005' }] }] } headers = {'REMOTE_USER': '******', 'ADMIN_TOKEN': '12345'} self.app.put_json('/api/v1/users/saboten', data, headers=headers, status="*") # Change user headers = {'REMOTE_USER': '******'} response = self.app.get('/api/v1/users/saboten', headers=headers, status="*") self.assertEqual(response.status_int, 200) rdata = copy.deepcopy(data) rdata['cid'] = utils.encrypt(xorkey, 'saboten@domain1') self.assertDictEqual(response.json, rdata) # User is not authorized to change protected fields ndata = copy.deepcopy(data) ndata['default-email'] = 'saboten@domain2' response = self.app.post_json('/api/v1/users/saboten', ndata, headers=headers, status="*") self.assertEqual(response.status_int, 403) # User is not authorized to change protected fields ndata = copy.deepcopy(data) ndata['emails'].append({'emails': '*****@*****.**'}) response = self.app.post_json('/api/v1/users/saboten', ndata, headers=headers, status="*") self.assertEqual(response.status_int, 400) # Authorized to change its full name data['name'] = 'John Doe' response = self.app.post_json('/api/v1/users/saboten', data, headers=headers, status="*") self.assertEqual(response.status_int, 200) # Not authorized to change its full name if > 100 chars ndata = copy.deepcopy(data) ndata['name'] = 'a' * 101 response = self.app.post_json('/api/v1/users/saboten', ndata, headers=headers, status="*") self.assertEqual(response.status_int, 400) # Authorized to change its emails memberships email = [e for e in data['emails'] if e['email'] == 'saboten@domain1'][0] email['groups'][0]['group'] = 'ugroup3' response = self.app.post_json('/api/v1/users/saboten', data, headers=headers, status="*") self.assertEqual(response.status_int, 200) # Change user headers = {'REMOTE_USER': '******'} # Another user not authorized to get response = self.app.get('/api/v1/users/saboten', headers=headers, status="*") self.assertEqual(response.status_int, 401) # Another user not authorized to change data['name'] = 'John Doe' response = self.app.post_json('/api/v1/users/saboten', data, headers=headers, status="*") self.assertEqual(response.status_int, 401) # Another user not authorized to delete response = self.app.delete('/api/v1/users/saboten', headers=headers, status="*") self.assertEqual(response.status_int, 401) # Change user headers = {'REMOTE_USER': '******'} # User authorized to delete itself response = self.app.delete('/api/v1/users/saboten', headers=headers, status="*") self.assertEqual(response.status_int, 200)
def index(self, prefix=None, nameonly='false', withstats='false', pid=None, dfrom=None, dto=None, inc_merge_commit=None): ci = Commits(index.Connector()) contributors_index = Contributors() groups = contributors_index.get_groups() if withstats == 'true': projects_index = Projects() if nameonly == 'true': ret = dict([(k, None) for k in groups.keys()]) if prefix: ret = dict([(k, None) for k in ret.keys() if k.lower().startswith(prefix)]) return ret ret_groups = {} for group, data in groups.items(): if prefix and not group.lower().startswith(prefix.lower()): continue rg = { 'members': {}, 'description': data.get('description', ''), 'domains': data.get('domains', []) } emails = list(data['emails'].keys()) members = contributors_index.get_idents_by_emails(emails) for id, member in members.items(): member['gravatar'] = hashlib.md5( member['default-email'].encode( errors='ignore')).hexdigest() # TODO(fbo): bounces should be a list of bounce # Let's deactivate that for now # member['bounces'] = bounces del member['emails'] if not member['name']: # Try to find it among commits suggested = ci.get_commits_author_name_by_emails( [member['default-email']]) name = suggested.get(member['default-email'], 'Unnamed') member['name'] = name del member['default-email'] rg['members'][utils.encrypt(xorkey, id)] = member if withstats == 'true': # Fetch the number of projects and repos contributed to query_kwargs = utils.resolv_filters( projects_index, contributors_index, pid, None, None, group, dfrom, dto, None, inc_merge_commit, None, None, None) repos = [ r for r in ci.get_repos(**query_kwargs)[1] if not r.startswith('meta_ref: ') ] projects = utils.get_projects_from_references( projects_index, repos) rg['repos_amount'] = len(repos) rg['projects_amount'] = len(projects) ret_groups[group] = rg return ret_groups
def test_users_crud_user(self): # First set a user as admin data = { 'uid': 'saboten', 'name': 'Cactus Saboten', 'default-email': 'saboten@domain1', 'emails': [ {'email': 'saboten@domain1', 'groups': [ {'group': 'ugroup2', 'begin-date': '1410456005', 'end-date': '1410476005'} ] } ] } headers = { 'REMOTE_USER': '******', 'ADMIN_TOKEN': '12345'} self.app.put_json( '/api/v1/users/saboten', data, headers=headers, status="*") # Change user headers = {'REMOTE_USER': '******'} response = self.app.get( '/api/v1/users/saboten', headers=headers, status="*") self.assertEqual(response.status_int, 200) rdata = copy.deepcopy(data) rdata['cid'] = utils.encrypt(xorkey, 'saboten@domain1') self.assertDictEqual(response.json, rdata) # User is not authorized to change protected fields ndata = copy.deepcopy(data) ndata['default-email'] = 'saboten@domain2' response = self.app.post_json( '/api/v1/users/saboten', ndata, headers=headers, status="*") self.assertEqual(response.status_int, 403) # User is not authorized to change protected fields ndata = copy.deepcopy(data) ndata['emails'].append({'emails': '*****@*****.**'}) response = self.app.post_json( '/api/v1/users/saboten', ndata, headers=headers, status="*") self.assertEqual(response.status_int, 400) # Authorized to change its full name data['name'] = 'John Doe' response = self.app.post_json( '/api/v1/users/saboten', data, headers=headers, status="*") self.assertEqual(response.status_int, 200) # Not authorized to change its full name if > 100 chars ndata = copy.deepcopy(data) ndata['name'] = 'a'*101 response = self.app.post_json( '/api/v1/users/saboten', ndata, headers=headers, status="*") self.assertEqual(response.status_int, 400) # Authorized to change its emails memberships email = [e for e in data['emails'] if e['email'] == 'saboten@domain1'][0] email['groups'][0]['group'] = 'ugroup3' response = self.app.post_json( '/api/v1/users/saboten', data, headers=headers, status="*") self.assertEqual(response.status_int, 200) # Change user headers = {'REMOTE_USER': '******'} # Another user not authorized to get response = self.app.get( '/api/v1/users/saboten', headers=headers, status="*") self.assertEqual(response.status_int, 401) # Another user not authorized to change data['name'] = 'John Doe' response = self.app.post_json( '/api/v1/users/saboten', data, headers=headers, status="*") self.assertEqual(response.status_int, 401) # Another user not authorized to delete response = self.app.delete( '/api/v1/users/saboten', headers=headers, status="*") self.assertEqual(response.status_int, 401) # Change user headers = {'REMOTE_USER': '******'} # User authorized to delete itself response = self.app.delete( '/api/v1/users/saboten', headers=headers, status="*") self.assertEqual(response.status_int, 200)
def test_get_infos(self): expected = { 'first': 1393860653, 'last': 1410456005, 'commits_amount': 3, 'authors_amount': 2, 'line_modifieds_amount': 29, 'duration': 16595352, 'ttl_average': 0, 'projects_amount': 1, 'repos_amount': 1, } response = self.app.get('/api/v1/infos/infos?pid=test') self.assertEqual(response.status_int, 200) self.assertDictEqual(response.json, expected) # Check endpoint CSV mode response = self.app.get( '/api/v1/infos/infos?pid=test', headers={'Accept': 'text/csv'}) self.assertEqual(response.status_int, 200) csvret = build_dict_from_csv(response.body) # Convert all dict values to str expected = dict((k, str(v)) for k, v in expected.items()) self.assertDictEqual(csvret[0], expected) self.assertEqual(len(csvret), 1) # Make an attempt by setting meta ref to True new_projects_file = """ project-templates: default: uri: https://github.com/nakata/%(name)s.git branches: - master projects: test: meta-ref: true repos: monkey: template: default """ self.db = set_projects_definition(self.conp, new_projects_file) expected = { 'first': 1393860653, 'last': 1410456005, 'commits_amount': 2, 'authors_amount': 2, 'line_modifieds_amount': 18, 'duration': 16595352, 'ttl_average': 0, 'projects_amount': 1, 'repos_amount': 1, } response = self.app.get('/api/v1/infos/infos?pid=test') self.assertEqual(response.status_int, 200) self.assertDictEqual(response.json, expected) # Test with a cid expected = { 'projects_amount': 1, 'first': 1410456005, 'line_modifieds_amount': 10, 'duration': 0, 'commits_amount': 1, 'ttl_average': 0, 'last': 1410456005, 'authors_amount': 1, 'repos_amount': 1 } cid = utils.encrypt(xorkey, '*****@*****.**') response = self.app.get('/api/v1/infos/infos', {'cid': cid}) self.assertEqual(response.status_int, 200) self.assertDictEqual(response.json, expected)