def test_authenticate_method_setups_auth_token(self): client = HubstaffClient(app_token=os.getenv('HUBSTAFF_APP_TOKEN'), username=os.getenv('HUBSTAFF_USERNAME'), password=os.getenv('HUBSTAFF_PASSWORD')) client.authenticate() self.assertIsNotNone(client._auth_token)
def test_authenticate_method_calls_post_with_right_params(self, m_post): m_post.return_value.status_code = 200 m_post.return_value.json.return_value = { 'user': { 'auth_token': self.auth_token } } client = HubstaffClient(app_token=self.app_token, username='******', password='******') client.authenticate() self.assertEqual(m_post.call_count, 1) call_args, call_kwargs = m_post.call_args self.assertEqual(call_args, ('https://api.hubstaff.com/v1/auth', )) self.assertDictEqual( call_kwargs, { 'headers': { 'App-Token': self.app_token }, 'data': { 'email': '*****@*****.**', 'password': '******' }, })
def test_authenticate_method_raises_error_on_invalid_app_token(self): client = HubstaffClient(app_token='x' * 43, username=os.getenv('HUBSTAFF_USERNAME'), password=os.getenv('HUBSTAFF_PASSWORD')) with self.assertRaises(HubstaffAuthError) as err_ctx: client.authenticate() self.assertEqual(err_ctx.exception.message, 'Invalid app_token')
def _init_client(self): self._hubstaff = HubstaffClient( app_token=self._config.hubstaff_app_token, auth_token=self._config.hubstaff_auth_token, username=self._config.hubstaff_username, password=self._config.hubstaff_password) # set given auth_token to the config self._config.hubstaff_auth_token = self._hubstaff.authenticate()
def test_authenticate_method_raises_error_on_invalid_username(self): client = HubstaffClient(app_token=os.getenv('HUBSTAFF_APP_TOKEN'), username='******', password=os.getenv('HUBSTAFF_PASSWORD')) with self.assertRaises(HubstaffAuthError) as err_ctx: client.authenticate() self.assertEqual(err_ctx.exception.message, 'Invalid email and/or password')
def test_request_method_refreshes_auth_token(self, m_post, m_request): m_post.side_effect = self._auth_endpoint m_request.side_effect = self._users_endpoint client = HubstaffClient(app_token=self.app_token, auth_token='EXPIRED!', username='******', password='******') client._request('get', '/users', params={ 'organization_memberships': False, 'project_memberships': False, 'offset': 0 }) self.assertEqual(m_request.call_count, 2) # The first call uses expired token call_args, call_kwargs = m_request.call_args_list[0] self.assertEqual(call_args, ( 'get', 'https://api.hubstaff.com/v1/users', )) self.assertDictEqual( call_kwargs, { 'headers': { 'App-Token': self.app_token, 'Auth-Token': 'EXPIRED!', }, 'params': { 'organization_memberships': False, 'project_memberships': False, 'offset': 0 }, 'data': None, 'json': None, }) # The second call uses refreshed token call_args, call_kwargs = m_request.call_args_list[1] self.assertEqual(call_args, ( 'get', 'https://api.hubstaff.com/v1/users', )) self.assertDictEqual( call_kwargs, { 'headers': { 'App-Token': self.app_token, 'Auth-Token': self.auth_token, }, 'params': { 'organization_memberships': False, 'project_memberships': False, 'offset': 0 }, 'data': None, 'json': None, })
def test_authenticate_method_raises_error_on_invalid_password(self): client = HubstaffClient(app_token=os.getenv('HUBSTAFF_APP_TOKEN'), username=os.getenv('HUBSTAFF_USERNAME'), password='******' * 16) with self.assertRaises(HubstaffAuthError) as err_ctx: client.authenticate() self.assertEqual(err_ctx.exception.message, 'Invalid email and/or password')
def test_authenticate_method_raises_invalid_app_token_error(self, m_post): m_post.return_value.status_code = 401 m_post.return_value.json.return_value = {'error': 'Invalid app_token'} client = HubstaffClient(app_token='bad_token', username='******', password='******') with self.assertRaises(HubstaffAuthError) as err_ctx: client.authenticate() self.assertEqual(err_ctx.exception.message, 'Invalid app_token')
def test_authenticate_method_returns_auth_token_no_password(self, m_post): m_post.return_value.status_code = 401 m_post.return_value.json.return_value = { 'error': 'Invalid email and/or password' } client = HubstaffClient(app_token=self.app_token, auth_token=self.auth_token) auth_token = client.authenticate() self.assertEqual(auth_token, self.auth_token)
def test_post_method_calls_request_method_with_data(self, m_request): m_request.return_value = {'user': {'id': 123}} client = HubstaffClient(app_token=self.app_token, username='******', password='******') result = client._post('/users', data={'name': 'Johny'}) self.assertDictEqual(result, {'user': {'id': 123}}) m_request.assert_called_once_with('post', '/users', data={'name': 'Johny'}, json=None)
def test_authenticate_method_setups_auth_token(self, m_post): m_post.return_value.status_code = 200 m_post.return_value.json.return_value = { 'user': { 'auth_token': self.auth_token } } client = HubstaffClient(app_token=self.app_token, username='******', password='******') client.authenticate() self.assertEqual(client._auth_token, self.auth_token)
def test_authenticate_method_raises_invalid_password_error(self, m_post): m_post.return_value.status_code = 401 m_post.return_value.json.return_value = { 'error': 'Invalid email and/or password' } client = HubstaffClient(app_token=self.app_token, username='******', password='******' * 16) with self.assertRaises(HubstaffAuthError) as err_ctx: client.authenticate() self.assertEqual(err_ctx.exception.message, 'Invalid email and/or password')
def setUpClass(cls): cls.client = HubstaffClient( app_token=os.getenv('HUBSTAFF_APP_TOKEN'), auth_token=os.getenv('HUBSTAFF_AUTH_TOKEN'), username=os.getenv('HUBSTAFF_USERNAME'), password=os.getenv('HUBSTAFF_PASSWORD')) # save auth_token to prevent auth api throttling if not os.getenv('HUBSTAFF_AUTH_TOKEN'): os.environ['HUBSTAFF_AUTH_TOKEN'] = cls.client.authenticate() # date range cls.date_from = datetime.strptime(os.getenv('HUBSTAFF_TEST_DATE_FROM'), '%Y-%m-%d') cls.date_to = datetime.strptime(os.getenv('HUBSTAFF_TEST_DATE_TO'), '%Y-%m-%d') # save first found user id users_list = cls.client.get_users_list(include_projects=True, include_organizations=True) cls.user_id = users_list[0]['id'] # save first found organization id cls.organization_id = users_list[0]['organizations'][0]['id'] # take the rest of organization members cls.organization_members = set() for user_item in users_list: user_organizations = user_item.get('organizations') or [] user_organization_id_list = [o['id'] for o in user_organizations] if cls.organization_id in user_organization_id_list: cls.organization_members.add(user_item['id']) # save first found project id cls.project_id = users_list[0]['projects'][0]['id']
def test_request_method_returns_json_data(self, m_request): m_request.return_value.status_code = 200 m_request.return_value.json.return_value = {'users': []} client = HubstaffClient(app_token=self.app_token, auth_token=self.auth_token) result = client._request('get', '/users', params={ 'organization_memberships': False, 'project_memberships': False, 'offset': 0 }) self.assertDictEqual(result, {'users': []})
def test_init_raises_error_on_no_auth_token_no_password(self): with self.assertRaises(ValueError) as err_ctx: HubstaffClient(app_token=self.app_token, username='******') self.assertEqual( err_ctx.exception.args[0], 'auth_token or (username, password) pair must be set')
def test_authenticate_method_raises_too_many_requests_error(self, m_post): m_post.return_value.status_code = 429 m_post.return_value.json.return_value = { 'error': 'Rate limit has been reached. ' 'Please wait before making your next request.' } client = HubstaffClient(app_token=self.app_token, username='******', password='******') with self.assertRaises(HubstaffError) as err_ctx: client.authenticate() self.assertEqual( err_ctx.exception.message, 'Rate limit has been reached. ' 'Please wait before making your next request.')
def test_request_method_doesnt_call_authenticate_method( self, m_authenticate, m_request): m_request.return_value.status_code = 200 m_request.return_value.json.return_value = {'users': []} client = HubstaffClient(app_token=self.app_token, auth_token=self.auth_token) client._request('get', '/users', params={ 'organization_memberships': False, 'project_memberships': False, 'offset': 0 }) m_authenticate.assert_not_called()
def setUpClass(cls): cls.client = HubstaffClient( app_token=os.getenv('HUBSTAFF_APP_TOKEN'), auth_token=os.getenv('HUBSTAFF_AUTH_TOKEN'), username=os.getenv('HUBSTAFF_USERNAME'), password=os.getenv('HUBSTAFF_PASSWORD')) # save auth_token to prevent auth api throttling if not os.getenv('HUBSTAFF_AUTH_TOKEN'): os.environ['HUBSTAFF_AUTH_TOKEN'] = cls.client.authenticate()
def setUpClass(cls): cls.client = HubstaffClient( app_token=os.getenv('HUBSTAFF_APP_TOKEN'), auth_token=os.getenv('HUBSTAFF_AUTH_TOKEN'), username=os.getenv('HUBSTAFF_USERNAME'), password=os.getenv('HUBSTAFF_PASSWORD')) # save auth_token to prevent auth api throttling if not os.getenv('HUBSTAFF_AUTH_TOKEN'): os.environ['HUBSTAFF_AUTH_TOKEN'] = cls.client.authenticate() # save the first found project id cls.project_id = cls.client.get_projects_list()[0]['id']
def test_request_method_raises_unauthorized_error(self, _, m_request): m_request.return_value.status_code = 401 m_request.return_value.json.return_value = { 'error': 'Permission denied' } client = HubstaffClient( app_token=self.app_token, auth_token=self.auth_token, # valid but probably expired username='******', password='******') with self.assertRaises(HubstaffAuthError) as err_ctx: client._request('get', '/users', params={ 'organization_memberships': False, 'project_memberships': False, 'offset': 0 }) self.assertEqual(err_ctx.exception.message, 'Permission denied')
def test_request_method_raises_too_many_requests(self, m_request): m_request.return_value.status_code = 429 m_request.return_value.json.return_value = { 'error': 'Rate limit has been reached. ' 'Please wait before making your next request.' } client = HubstaffClient(app_token=self.app_token, auth_token=self.auth_token) with self.assertRaises(HubstaffError) as err_ctx: client._request('get', '/users', params={ 'organization_memberships': False, 'project_memberships': False, 'offset': 0 }) self.assertEqual( err_ctx.exception.message, 'Rate limit has been reached. ' 'Please wait before making your next request.')
def test_get_method_calls_request_method(self, m_request): m_request.return_value = {'users': []} client = HubstaffClient(app_token=self.app_token, username='******', password='******') result = client._get('/users', params={ 'organization_memberships': False, 'project_memberships': False, 'offset': 0 }) self.assertDictEqual(result, {'users': []}) m_request.assert_called_once_with('get', '/users', params={ 'organization_memberships': False, 'project_memberships': False, 'offset': 0 })
def test_request_method_tries_to_to_refresh_the_token( self, m_authenticate, m_request): m_request.return_value.status_code = 401 m_request.return_value.json.return_value = { 'error': 'Permission denied' } client = HubstaffClient( app_token=self.app_token, auth_token=self.auth_token, # valid but probably expired username='******', password='******') with self.assertRaises(HubstaffAuthError): client._request('get', '/users', params={ 'organization_memberships': False, 'project_memberships': False, 'offset': 0 }) m_authenticate.asert_called_once_with()
def test_request_method_calls_api_with_auth_token(self, m_post, m_request): m_post.side_effect = self._auth_endpoint m_request.return_value.status_code = 200 m_request.return_value.json.return_value = {'users': []} client = HubstaffClient(app_token=self.app_token, username='******', password='******') client._request('get', '/users', params={ 'organization_memberships': False, 'project_memberships': False, 'offset': 0 }) self.assertEqual(m_request.call_count, 1) call_args, call_kwargs = m_request.call_args self.assertEqual(call_args, ( 'get', 'https://api.hubstaff.com/v1/users', )) self.assertDictEqual( call_kwargs, { 'headers': { 'App-Token': self.app_token, 'Auth-Token': self.auth_token, }, 'params': { 'organization_memberships': False, 'project_memberships': False, 'offset': 0 }, 'data': None, 'json': None, })
def handle(self, *args, **options): HUBSTAFF_APP_TOKEN = "S-HAXY_8ZU996f1xGEX-OATcWaAwb51HqlnwN6oi4vU" hubstaff = HubstaffClient(app_token=HUBSTAFF_APP_TOKEN, username='******', password='******') os.environ['HUBSTAFF_AUTH_TOKEN'] = hubstaff.authenticate() hubstaff = HubstaffClient(app_token=HUBSTAFF_APP_TOKEN, auth_token=os.getenv('HUBSTAFF_AUTH_TOKEN')) hubstaff.authenticate() users_list = hubstaff.get_users_list(include_projects=True, include_organizations=True) ids = map(lambda user: (user['id'], user['email']), users_list) for user_id in ids: try: user = CustomUser.objects.get(email=user_id[1]) HubstaffUser.objects.get_or_create(user=user, hubstaff_id=user_id[0]) except Exception as e: print("user not found")
def hubStaffAuthentication(): hubstaff = HubstaffClient(app_token=config.HUBSTAFF_APP_TOKEN, username=config.HUBSTAFF_USERNAME, password=config.HUBSTAFF_PASSWORD) hubstaff.authenticate() return hubstaff
def handle(self, *args, **options): month = options['month'] year = options['year'] day = options['day'] HUBSTAFF_APP_TOKEN = "S-HAXY_8ZU996f1xGEX-OATcWaAwb51HqlnwN6oi4vU" #hubstaff = HubstaffClient(app_token=HUBSTAFF_APP_TOKEN,username='******',password='******') #os.environ['HUBSTAFF_AUTH_TOKEN'] = hubstaff.authenticate() #print (os.getenv('HUBSTAFF_AUTH_TOKEN')) os.environ[ 'HUBSTAFF_AUTH_TOKEN'] = "p-XSy3G4v4nkVewG0Z72G4SlDnXe8uljLzo7MJhtQ5g" hubstaff = HubstaffClient(app_token=HUBSTAFF_APP_TOKEN, auth_token=os.getenv('HUBSTAFF_AUTH_TOKEN')) hubstaff.authenticate() if month and year and day: params = { 'start_date': datetime(year=year, month=month, day=day).isoformat(), 'end_date': datetime(year=year, month=month, day=day).isoformat(), } else: params = { 'start_date': datet.today().isoformat(), 'end_date': datet.today().isoformat(), } result = hubstaff._get('/custom/by_date/team', params=params) for data in result['organizations'][0]['dates']: date = datetime.strptime(data['date'], '%Y-%m-%d').date() for user in data['users']: #import pdb;pdb.set_trace() try: wfh = WorkFromHome.objects.get( date=date, hubstaff_id__hubstaff_id=user['id']) if user['projects']: shift = wfh.user.shifts.get(date=date) obj, created = UserAttendanceLog.objects.get_or_create( date=date, user=wfh.user, shift=shift) #import pdb;pdb.set_trace() #time_from = time(11, 30) time_from = shift.shift.time_from for log in user['projects']: time_to = ( datetime.combine(date, time_from) + timedelta(seconds=log['duration'])).time() ctx = { 'attendance_log': obj, 'in_time': time_from, 'out_time': time_to, 'type': 'in', 'duration': timedelta(seconds=log['duration']), 'comment': log['name'] } UserAttendanceLogSummary.objects.get_or_create( **ctx) time_from = time_to except Exception as e: print("work from home not found", e)
class Command: def __init__(self, **opts): self._logger = logging.getLogger(__name__) self._logger.setLevel(logging.WARNING) self._config = Config(**opts) self._hubstaff = None def _load_config(self): self._config.load() def _init_client(self): self._hubstaff = HubstaffClient( app_token=self._config.hubstaff_app_token, auth_token=self._config.hubstaff_auth_token, username=self._config.hubstaff_username, password=self._config.hubstaff_password) # set given auth_token to the config self._config.hubstaff_auth_token = self._hubstaff.authenticate() def _save_config(self): self._config.save() def _get_report_data(self, date_from, date_to): users_list = self._hubstaff.get_users_list(include_projects=True) users_dict = {} projects_dict = {} for user_item in users_list: users_dict[user_item['id']] = { 'id': user_item['id'], 'name': user_item['name'], } for project_item in user_item['projects']: projects_dict[project_item['id']] = { 'id': project_item['id'], 'name': project_item['name'], } activities_list = self._hubstaff.get_activities_list( date_from, date_to) spent_time_dict = defaultdict(lambda: 0) for activity_item in activities_list: spent_time_dict[( activity_item['user_id'], activity_item['project_id'])] += activity_item['tracked'] report_data = { 'date_from': date_from, 'date_to': date_to, 'users': users_dict, 'projects': projects_dict, 'spent_time': spent_time_dict, } return report_data @classmethod def _render_report_to_html(cls, data): template = jinja2.Template('''<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>rt-bot-34 report {{ date_from }} - {{ date_to }}</title> </head> <body> <h1>{{ date_from }} - {{ date_to }}</h1> <table> <thead> <tr> <th> </th> {% for user_id, user in users.items() %} <th>{{ user.name }}</th> {% endfor %} </tr> </thead> <tbody> {% for project_id, project in projects.items() %} <tr> <td>{{ project.name }}</td> {% for user_id, user in users.items() %} <td>{{ spent_time.get((user_id, project_id), 0) }}</td> {% endfor %} </tr> {% endfor %} </tbody> </table> </body> </html> ''') html = template.render(**data) return html @classmethod def _save_report_html_to_file(cls, html, filename): with open(filename, 'w+') as f: f.write(html) def _build_report(self): report_data = self._get_report_data( date_from=self._config.report_date_from, date_to=self._config.report_date_to) report_html = self._render_report_to_html(data=report_data) self._save_report_html_to_file(html=report_html, filename=self._config.report_filename) # here you can add sending report html by email ... def handle(self): try: self._load_config() self._init_client() self._save_config() self._build_report() except HubstaffAuthError: self._logger.error('hubstaff error: authentication failed') except ma.ValidationError as e: self._logger.error('validation error: %s' % e.messages)
def test_authenticate_method_no_password_doesnt_call_api(self, m_post): client = HubstaffClient(app_token=self.app_token, auth_token=self.auth_token) client.authenticate() m_post.assert_not_called()