Skip to content

Commit

Permalink
Bamboo sdk base api class (#97)
Browse files Browse the repository at this point in the history
* bambbo sdk base api class

* minor change

* minor changes

* comment resolve

* resolved comments

* added new methods

* added 201 status code

* class to sync employees from bamboo hr (#98)

* class to sync employees from bamboo hr

* bug fix

* minor changes

* comment resolved

* minor changes

* Bamboo sdk class (#99)

* bamboo sdk class

* comment resolved

* Webhook create and delete API  (#108)

* webhook api added

* indentation fixed

* indentaion fixed

* minor fix

* Fields get API (#109)

* Fields get API

* added timeoff instead of fields and tested
  • Loading branch information
Ashutosh619-sudo authored Dec 20, 2023
1 parent 73ff29e commit 6fd47e9
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 0 deletions.
Empty file added bamboosdk/__init__.py
Empty file.
Empty file added bamboosdk/api/__init__.py
Empty file.
133 changes: 133 additions & 0 deletions bamboosdk/api/api_base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import requests
import base64
import json
from bamboosdk.exceptions import *

class ApiBase:
"""
Base class for all API classes
"""
API_BASE_URL = 'https://api.bamboohr.com/api/gateway.php/{}'

def __init__(self) -> None:
self.__api_token = None
self.__sub_domain = None
self.headers = None

def _get_request(self, module_api_path):
"""
HTTP get method get data from BambooHR API URL
Parameters:
module_api_path (str): URL of BambooHR API
"""

url = self.API_BASE_URL.format(self.__sub_domain) + module_api_path
response = requests.get(url=url, headers=self.headers)
if response.status_code == 200:
result = json.loads(response.text)
return result

if response.status_code == 403:
error_msg = json.loads(response.text)
raise NoPrivilegeError('Forbidden, the user has insufficient privilege', error_msg)

if response.status_code == 404:
error_msg = json.loads(response.text)
raise NotFoundItemError('Not found item with ID', error_msg)

if response.status_code == 401:
error_msg = 'The api token is invalid'
raise InvalidTokenError('Invalid token, try to refresh it', error_msg)

else:
error_msg = json.loads(response.text)
raise BambooHrSDKError('Status code {0}'.format(response.status_code), error_msg)


def _post_request(self, module_api_path, payload):
"""
HTTP post method to send data to BambooHR API URL
Parameters:
payload (dict): Data to be sent to Bamboo API
module_api_path (str): URL of BambooHR API
"""

url= self.API_BASE_URL.format(self.__sub_domain) + module_api_path
response = requests.post(url=url, json=payload, headers=self.headers)
if response.status_code == 200:
result = json.loads(response.text)
return result

if response.status_code == 201:
result = json.loads(response.text)
return result

if response.status_code == 403:
error_msg = json.loads(response.text)
raise NoPrivilegeError('Forbidden, the user has insufficient privilege', error_msg)

if response.status_code == 404:
error_msg = json.loads(response.text)
raise NotFoundItemError('Not found item with ID', error_msg)

if response.status_code == 401:
error_msg = 'The api token is invalid'
raise InvalidTokenError('Invalid token, try to refresh it', error_msg)

else:
error_msg = json.loads(response.text)
raise BambooHrSDKError('Status code {0}'.format(response.status_code), error_msg)

def _delete_request(self, module_api_path):
"""
HTTP delete method to delete resource on BambooHR
Parameters:
module_api_path (str): URL of BambooHR API
"""
url= self.API_BASE_URL.format(self.__sub_domain) + module_api_path
response = requests.delete(url=url, headers=self.headers)
if response.status_code == 200:
result = json.loads(response.text)
return result

if response.status_code == 403:
error_msg = json.loads(response.text)
raise NoPrivilegeError('Forbidden, the user has insufficient privilege', error_msg)

if response.status_code == 404:
error_msg = json.loads(response.text)
raise NotFoundItemError('Not found item with ID', error_msg)

if response.status_code == 401:
error_msg = 'The api token is invalid'
raise InvalidTokenError('Invalid token, try to refresh it', error_msg)

else:
error_msg = json.loads(response.text)
raise BambooHrSDKError('Status code {0}'.format(response.status_code), error_msg)

def __encode_username_password(self):
"""
Utility method to be used in the header for authorization
converts the api token and password to base64
"""

payload = f'{self.__api_token}:a'
payload = payload.encode()

return base64.b64encode(payload).decode()

def set_api_token(self, api_token):
self.__api_token = api_token

self.headers = {
'Accept': 'application/json',
'content-type': 'application/json',
'authorization': f'Basic {self.__encode_username_password()}'
}

def set_sub_domain(self, sub_domain):
self.__sub_domain = sub_domain
14 changes: 14 additions & 0 deletions bamboosdk/api/employee.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from .api_base import ApiBase


class Employee(ApiBase):

GET_EMPLOYEE_REPORT = '/v1/reports/custom?format=JSON&onlyCurrent=false'
payload = { "fields": ["displayName", "firstName", "lastName", "department", "workEmail", "supervisorEmail", "status"] }

def get_all(self):
"""Get the list of employees from bambooHr
Returns:
List with dicts in Employee schema.
"""
return self._post_request(self.GET_EMPLOYEE_REPORT, payload=self.payload)
12 changes: 12 additions & 0 deletions bamboosdk/api/time_off.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from .api_base import ApiBase

class TimeOff(ApiBase):
CHECK_URL = '/v1/meta/time_off/types/'

def get(self):
"""
Get method to get the different fields,
used here for checking connection.
Returns:
"""
return self._get_request(self.CHECK_URL)
22 changes: 22 additions & 0 deletions bamboosdk/api/webhook.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from .api_base import ApiBase


class Webhook(ApiBase):
""" Class for webhook APIs for bamboohr """

POST_WEBHOOK = '/v1/webhooks/'
DELETE_WEBHOOK = '/v1/webhooks/{}'

def post(self, payload):
"""
Post webhook url to bamboohr for employee update or create
Returns:
"""
return self._post_request(self.POST_WEBHOOK, payload)

def delete(self, id):
"""
Delete Webhook
Returns:
"""
return self._delete_request(self.DELETE_WEBHOOK.format(id))
39 changes: 39 additions & 0 deletions bamboosdk/bamboohrsdk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from .api.employee import Employee
from .api.webhook import Webhook
from .api.time_off import TimeOff

class BambooHrSDK:
"""
Creates connection with BambooHr APIs
Parameters:
api_token (str): API token for BambooHr
sub_domain (str): Sub domain of the user in BambooHr
"""

def __init__(self, api_token: str, sub_domain: str):
self.__api_token = api_token
self.__sub_domain = sub_domain

self.employees = Employee()
self.webhook = Webhook()
self.time_off = TimeOff()

self.set_api_token()
self.set_sub_domain()

def set_api_token(self):
"""
Set the api token for all the APIs
"""
self.employees.set_api_token(self.__api_token)
self.webhook.set_api_token(self.__api_token)
self.time_off.set_api_token(self.__api_token)

def set_sub_domain(self):
"""
Set sub domain for all the APIs
"""
self.employees.set_sub_domain(self.__sub_domain)
self.webhook.set_sub_domain(self.__sub_domain)
self.time_off.set_sub_domain(self.__sub_domain)
30 changes: 30 additions & 0 deletions bamboosdk/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""
BambooHR SDK exceptions
"""


class BambooHrSDKError(Exception):
"""
The base exception class for BambooHR SDK
"""

def __init__(self, msg, response=None):
super(BambooHrSDKError, self).__init__(msg)
self.message = msg
self.response = response

def __str__(self):
return repr(self.message)


class NoPrivilegeError(BambooHrSDKError):
"""The user has insufficient privilege, 403 error."""

class NotFoundItemError(BambooHrSDKError):
"""Not found the item from URL, 404 error."""

class InvalidTokenError(BambooHrSDKError):
"""Invalid or non-existing access token, 401 error"""

class InternalServerError(BambooHrSDKError):
"""Internal server error, 500 error"""

0 comments on commit 6fd47e9

Please sign in to comment.