Initial working version
still a lot to do
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
config.ini
|
||||||
|
.venv/
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# system libs
|
||||||
|
import json
|
||||||
|
|
||||||
|
# 3rd party libs
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
class ACAuthenticator:
|
||||||
|
|
||||||
|
user = None
|
||||||
|
accounts = None
|
||||||
|
|
||||||
|
# FIXME: put into config
|
||||||
|
# This is only for cloud instance!
|
||||||
|
base_url = 'https://activecollab.com/api/v1/external/login'
|
||||||
|
|
||||||
|
def headers(self):
|
||||||
|
return {
|
||||||
|
'Content-Type': 'application/json; charset=utf8',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'User-Agent': 'Active Collab API Wrapper; v3.0.0'
|
||||||
|
}
|
||||||
|
|
||||||
|
def login(self, email, password):
|
||||||
|
login_data = {
|
||||||
|
'email': email,
|
||||||
|
'password': password
|
||||||
|
}
|
||||||
|
res = requests.post(self.base_url,
|
||||||
|
data=json.dumps(login_data),
|
||||||
|
headers=self.headers())
|
||||||
|
if res.status_code != 200:
|
||||||
|
raise Exception('Login failed!')
|
||||||
|
|
||||||
|
login_res = res.json()
|
||||||
|
if login_res['is_ok'] != 1:
|
||||||
|
raise Exception('Login failed! (2)')
|
||||||
|
|
||||||
|
self.user = login_res['user']
|
||||||
|
self.accounts = login_res['accounts']
|
||||||
|
return login_res
|
||||||
|
|
||||||
|
def find_account(self, name):
|
||||||
|
# FIXME: implement search
|
||||||
|
return self.accounts[0]
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
class ACClient:
|
||||||
|
|
||||||
|
account = None
|
||||||
|
token = None
|
||||||
|
|
||||||
|
base_url = None
|
||||||
|
|
||||||
|
# FIXME: put into config
|
||||||
|
# API Version
|
||||||
|
api_version = '1'
|
||||||
|
|
||||||
|
# FIXME: put into config
|
||||||
|
user_agent = 'Active Collab API Wrapper; v3.0.0'
|
||||||
|
|
||||||
|
def __init__(self, account, token):
|
||||||
|
self.account = account
|
||||||
|
self.token = token
|
||||||
|
#
|
||||||
|
self.base_url = self.account['url'] + '/api/v%s' % self.api_version
|
||||||
|
|
||||||
|
def headers(self):
|
||||||
|
return {
|
||||||
|
'Content-Type': 'application/json; charset=utf8',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'X-Angie-AuthApiToken': self.token,
|
||||||
|
'User-Agent': self.user_agent
|
||||||
|
}
|
||||||
|
|
||||||
|
def _get(self, url):
|
||||||
|
return requests.get(self.base_url + '/' + url,
|
||||||
|
headers=self.headers())
|
||||||
|
|
||||||
|
def _post(self, url, data):
|
||||||
|
return requests.post(
|
||||||
|
self.base_url + '/' + url,
|
||||||
|
headers=self.headers(),
|
||||||
|
data=json.dumps(data))
|
||||||
|
|
||||||
|
def get_info(self):
|
||||||
|
return self._get('info')
|
||||||
|
|
||||||
|
def get_projects(self):
|
||||||
|
return self._get('projects')
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
class ACTokenAuthenticator:
|
||||||
|
|
||||||
|
account = None
|
||||||
|
user = None
|
||||||
|
base_url = ""
|
||||||
|
token = None
|
||||||
|
|
||||||
|
# FIXME: put into config
|
||||||
|
client_name = 'Python Script'
|
||||||
|
client_vendor = 'Me'
|
||||||
|
|
||||||
|
# FIXME: put into config
|
||||||
|
# API Version
|
||||||
|
api_version = '1'
|
||||||
|
|
||||||
|
# FIXME: put into config
|
||||||
|
user_agent = 'Active Collab API Wrapper; v3.0.0'
|
||||||
|
|
||||||
|
def __init__(self, account, user):
|
||||||
|
self.account = account
|
||||||
|
self.user = user
|
||||||
|
#
|
||||||
|
self.base_url = self.account['url'] + '/api/v%s' % self.api_version
|
||||||
|
|
||||||
|
def issue_token_intent(self):
|
||||||
|
# use intent to get a token
|
||||||
|
data = {
|
||||||
|
'intent': self.user['intent'],
|
||||||
|
'client_name': self.client_name,
|
||||||
|
'client_vendor': self.client_vendor
|
||||||
|
}
|
||||||
|
r = requests.post(self.base_url+ '/issue-token-intent',
|
||||||
|
headers=self.headers(),
|
||||||
|
data=json.dumps(data))
|
||||||
|
if r.status_code != 200:
|
||||||
|
raise Exception('Error in issuing token intent!')
|
||||||
|
token_res = r.json()
|
||||||
|
if token_res['is_ok'] != 1:
|
||||||
|
raise Exception('Error in issuing token (2)')
|
||||||
|
return token_res['token']
|
||||||
|
|
||||||
|
def headers(self):
|
||||||
|
return {
|
||||||
|
'Content-Type': 'application/json; charset=utf8',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
'User-Agent': self.user_agent
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
[LOGIN]
|
||||||
|
username = you@example.com
|
||||||
|
password = very-secret
|
||||||
|
account_name = "#123456"
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
import configparser
|
||||||
|
import logging
|
||||||
|
from pprint import pprint
|
||||||
|
|
||||||
|
from ActiveCollabAPI.ACAuthenticator import ACAuthenticator
|
||||||
|
from ActiveCollabAPI.ACClient import ACClient
|
||||||
|
from ActiveCollabAPI.ACTokenAuthenticator import ACTokenAuthenticator
|
||||||
|
|
||||||
|
# Enabling debugging at http.client level (requests->urllib3->http.client)
|
||||||
|
# you will see the REQUEST, including HEADERS and DATA, and RESPONSE with HEADERS but without DATA.
|
||||||
|
# the only thing missing will be the response.body which is not logged.
|
||||||
|
from http.client import HTTPConnection
|
||||||
|
|
||||||
|
|
||||||
|
HTTPConnection.debuglevel = 1
|
||||||
|
|
||||||
|
logging.basicConfig() # you need to initialize logging, otherwise you will not see anything from requests
|
||||||
|
logging.getLogger().setLevel(logging.DEBUG)
|
||||||
|
requests_log = logging.getLogger("urllib3")
|
||||||
|
requests_log.setLevel(logging.DEBUG)
|
||||||
|
requests_log.propagate = True
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read('config.ini')
|
||||||
|
|
||||||
|
# FIXME: put into config
|
||||||
|
username = config['LOGIN']['username']
|
||||||
|
password = config['LOGIN']['password']
|
||||||
|
account_name = config['LOGIN']['account_name']
|
||||||
|
|
||||||
|
# 1. you need to login to get a session and a list of accounts
|
||||||
|
# (here we use only the first account)
|
||||||
|
auth = ACAuthenticator()
|
||||||
|
session = auth.login(username, password)
|
||||||
|
pprint(session)
|
||||||
|
user = session['user']
|
||||||
|
# use first account
|
||||||
|
account = auth.find_account(account_name)
|
||||||
|
|
||||||
|
# 2. you need to get a token for this account
|
||||||
|
token = ACTokenAuthenticator(account, user).issue_token_intent()
|
||||||
|
pprint(token)
|
||||||
|
|
||||||
|
# 3. now you can query the API
|
||||||
|
ac = ACClient(account, token)
|
||||||
|
res = ac.get_projects()
|
||||||
|
pprint(res.json())
|
||||||
|
|
||||||
|
res = ac.get_info()
|
||||||
|
pprint(res.json())
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
requests
|
||||||
Reference in New Issue
Block a user