From bc3550b0ff9959cd44702e6e98a5df43a3f52254 Mon Sep 17 00:00:00 2001 From: Johannes Löthberg Date: Fri, 3 Oct 2014 00:14:59 +0200 Subject: another big dump. github oauth authentiation is "working" But it's done really hackily and probably should never be done like this. --- app/__init__.py | 1 + app/models.py | 6 +---- app/views.py | 73 ++++++++++++++++++++++++++++++++++++++---------------- client/bug.py | 1 - client/bug_list.py | 39 ++++++----------------------- client/bug_open.py | 6 ++--- client/bug_show.py | 8 ------ config.py | 6 +++++ run.py | 2 +- 9 files changed, 72 insertions(+), 70 deletions(-) diff --git a/app/__init__.py b/app/__init__.py index f441218..d698823 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -3,6 +3,7 @@ from flask.ext.sqlalchemy import SQLAlchemy app = Flask(__name__) app.config.from_object('config') +app.secret_key = 'SUPERSEEKRITKEY' db = SQLAlchemy(app) from app import views, models diff --git a/app/models.py b/app/models.py index 4df6689..dc6a7cd 100644 --- a/app/models.py +++ b/app/models.py @@ -5,8 +5,7 @@ class User(db.Model): id = db.Column(db.Integer, primary_key=True) nickname = db.Column(db.String(64), index=True, unique=True) email = db.Column(db.String(120), index=True, unique=True) - opened = db.relationship('Ticket', backref='opened_by', lazy='dynamic', primaryjoin = 'Ticket.opened_by_user_id == User.id') - assigned = db.relationship('Ticket', backref='assigned_to', lazy='dynamic', primaryjoin = 'Ticket.assigned_to_user_id == User.id') + opened = db.relationship('Ticket', backref='opened_by', lazy='dynamic') def __repr__(self): @@ -22,12 +21,9 @@ class Ticket(db.Model): updated_at = db.Column(db.DateTime) status = db.Column(db.String(64), nullable=False, default='open') - resolution = db.Column(db.String(64)) reason = db.Column(db.String(140)) - deleted = db.Column(db.Boolean, default=False) opened_by_user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) - assigned_to_user_id = db.Column(db.Integer, db.ForeignKey('user.id')) def __repr__(self): return '' % (self.id) diff --git a/app/views.py b/app/views.py index 2e6ba6f..3cc8891 100644 --- a/app/views.py +++ b/app/views.py @@ -1,6 +1,8 @@ -from flask import jsonify, abort, make_response, request, url_for +from flask import jsonify, abort, make_response, request, url_for, redirect, session +from requests_oauthlib import OAuth2Session from datetime import datetime from app import app, db, models +import json def make_public_ticket(ticket): new_ticket = ticket.copy() @@ -11,8 +13,6 @@ def ticket_to_dict(ticket): nt = {} nt['id'] = ticket.id - nt['deleted'] = ticket.deleted - nt['summary'] = ticket.summary nt['body'] = ticket.body @@ -25,7 +25,6 @@ def ticket_to_dict(ticket): nt['status'] = ticket.status - nt['resolution'] = ticket.resolution nt['reason'] = ticket.reason if ticket.opened_by: @@ -37,29 +36,61 @@ def ticket_to_dict(ticket): else: nt['opened_by'] = {'id': None, 'nickname': None, 'email': None} - if ticket.assigned_to: - nt['assigned_to'] = { - 'id': ticket.assigned_to.id, - 'nickname': ticket.assigned_to.nickname, - 'email': ticket.assigned_to.email, - } - else: - nt['assigned_to'] = None - return nt +@app.route('/authorized') +def authorized_callback(): + github = OAuth2Session(app.config['GITHUB_CLIENT_ID'], state=session['oauth_state']) + + token = github.fetch_token(app.config['TOKEN_URL'], client_secret=app.config['GITHUB_CLIENT_SECRET'], + authorization_response=request.url) + + session['oauth_token'] = token + + user_data = github.get('https://api.github.com/user') + + if user_data.status_code == 401: + abort(401) + + json_data = user_data.json() + user = models.User.query.filter(models.User.id == json_data['id']).first() + if not user: + user = models.User( + id = json_data['id'], + nickname = json_data['login'], + email = json_data['email'] + ) + db.session.add(user) + db.session.commit() + + return "Your access token is: {}".format(token['access_token']) + +@app.route('/login') +def login(): + github = OAuth2Session(app.config['GITHUB_CLIENT_ID']) + authorization_url, state = github.authorization_url(app.config['AUTHORIZATION_BASE_URL']) + + session['oauth_state'] = state + return redirect(authorization_url) + @app.route('/tbt/api/1.0/tickets', methods=['GET']) def get_tickets(): - ts = models.Ticket.query.filter(models.Ticket.deleted != True).all() + ts = models.Ticket.query.all() tickets = map(ticket_to_dict, ts) return jsonify({'tickets': list(map(make_public_ticket, tickets))}) @app.route('/tbt/api/1.0/ticket', methods=['POST']) def create_ticket(): - if not request.json or not ('summary' and 'body' and 'user_nickname') in request.json: + if not request.json or not ('summary' and 'body' and 'token') in request.json: abort(400) - user = models.User.query.filter(models.User.nickname == request.json['user_nickname']).first() + token = {"scope": [""], "access_token": request.json['token'], "token_type": "bearer"} + github = OAuth2Session(app.config['GITHUB_CLIENT_ID'], token=token) + user_data = github.get('https://api.github.com/user') + if user_data.status_code == 401: + abort(401) + + user = models.User.query.get(user_data.json()['id']) ticket = models.Ticket(summary=request.json['summary'], body=request.json['body'], @@ -90,18 +121,18 @@ def update_ticket(ticket_id): ticket['summary'] = request.json.get('summary', ticket['summary']) ticket['body'] = request.json.get('body', ticket['body']) ticket['status'] = request.json.get('status', ticket['status']) - ticket['resolution'] = request.json.get('resolution', ticket['resolution']) ticket['reason'] = request.json.get('reason', ticket['reason']) - ticket['assigned-to'] = request.json.get('assigned-to', ticket['assigned-to']) return jsonify({'ticket': make_public_ticket(ticket)}) @app.route('/tbt/api/1.0/ticket/', methods=['DELETE']) def delete_ticket(ticket_id): - ticket = next((t for t in tickets if t['id'] == ticket_id), None) + ticket = models.Ticket.query.get(ticket_id) if not ticket: abort(404) - #tickets.remove(ticket) - ticket['deleted'] = True + + db.session.delete(ticket) + db.session.commit() + return jsonify({'result': True}) @app.errorhandler(404) diff --git a/client/bug.py b/client/bug.py index 24a523c..ff7958f 100755 --- a/client/bug.py +++ b/client/bug.py @@ -13,7 +13,6 @@ commands: show Show a specific ticket by ID [Not implemented yet:] - resolution Set the resolution status of a ticket edit Edit a ticket reopen Reopen a previously closed ticket close Close a ticket diff --git a/client/bug_list.py b/client/bug_list.py index 6084414..701b327 100755 --- a/client/bug_list.py +++ b/client/bug_list.py @@ -11,6 +11,7 @@ required. from docopt import docopt from textwrap import indent from datetime import datetime +from bug_show import show_ticket import json, requests if __name__ == '__main__': @@ -20,37 +21,13 @@ def call(args): print(args) api_endpoint = args['--uri'] + '/api/1.0/tickets' - r = requests.get(api_endpoint) + r = requests.get(api_endpoint, verify=False) - tickets = json.loads(r.text).get('tickets') + tickets = json.loads(r.text) + if not tickets: + exit("No tickets found.") - for ticket in tickets: - output = '[TBT#{}] '.format(ticket['id']) - - if 'deleted' in ticket and ticket['deleted'] == True: - output += '[DELETED] ' - - output += '[{}] '.format(ticket['status']) - - output += '{}\n'.format(ticket['summary']) - - if ticket['status'] != 'open': - output += 'Resolution: {}\n'.format(ticket['resolution']) - - if ticket['reason']: - output += 'Reason: {}\n'.format(ticket['reason']) + tickets = tickets.get('tickets') - output += 'Opened by: {} <{}>\n'.format(ticket['opened_by']['nickname'], ticket['opened_by']['email']) - output += 'Opened at: {} UTC\n'.format(datetime.strptime( ticket['opened_at'], "%Y-%m-%dT%H:%M:%S" )) - - if ticket['assigned_to']: - output += 'Assigned to: {} <{}>\n'.format(ticket['assigned_to']['nickname'], ticket['assigned_to']['email']) - else: - output += 'Assigned to: Unassigned\n' - - if ticket['updated_at']: - output += 'Updated at: {} UTC\n'.format(datetime.strptime(ticket['opened_at'], "%Y-%m-%dT%H:%M:%S" )) - - output += '\n' + indent('{}'.format(ticket['body']), ' ') + '\n' - - print(output) + for ticket in tickets: + print(show_ticket(ticket)) diff --git a/client/bug_open.py b/client/bug_open.py index 17a3e4f..e9ecb19 100755 --- a/client/bug_open.py +++ b/client/bug_open.py @@ -38,16 +38,16 @@ def call(args): ticket = { 'summary': summary, 'body': body, - 'user_nickname': 'demi' + 'token': 'TOKENHERE' } headers = { 'Content-Type': 'application/json', - 'Accept': 'text/plain' + 'Accept': 'text/plain', } payload = json.dumps(ticket) - r = requests.post(api_endpoint, data=payload, headers=headers) + r = requests.post(api_endpoint, data=payload, headers=headers, verify=False) t = json.loads(r.text).get('ticket') diff --git a/client/bug_show.py b/client/bug_show.py index 0c3c9b8..18175ef 100755 --- a/client/bug_show.py +++ b/client/bug_show.py @@ -34,19 +34,11 @@ def show_ticket(ticket): if ticket['status'] != 'open': - output += 'Resolution: {}\n'.format(ticket['resolution']) - - if ticket['reason']: output += 'Reason: {}\n'.format(ticket['reason']) output += 'Opened by: {} <{}>\n'.format(ticket['opened_by']['nickname'], ticket['opened_by']['email']) output += 'Opened at: {} UTC\n'.format(datetime.strptime( ticket['opened_at'], "%Y-%m-%dT%H:%M:%S" )) - if ticket['assigned_to']: - output += 'Assigned to: {} <{}>\n'.format(ticket['assigned_to']['nickname'], ticket['assigned_to']['email']) - else: - output += 'Assigned to: Unassigned\n' - if ticket['updated_at']: output += 'Updated at: {} UTC\n'.format(datetime.strptime(ticket['opened_at'], "%Y-%m-%dT%H:%M:%S" )) diff --git a/config.py b/config.py index 7160e5d..f27b5fc 100644 --- a/config.py +++ b/config.py @@ -4,3 +4,9 @@ basedir = os.path.abspath(os.path.dirname(__file__)) SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'app.db') SQLALCHEMY_MIGRATE_REPO = os.path.join(basedir, 'db_repository') + +TOKEN_URL = 'https://github.com/login/oauth/access_token' +AUTHORIZATION_BASE_URL = 'https://github.com/login/oauth/authorize' + +GITHUB_CLIENT_ID = 'SEEKRIT' +GITHUB_CLIENT_SECRET = 'SEEKRIT' diff --git a/run.py b/run.py index 178fd8a..b21a2c5 100755 --- a/run.py +++ b/run.py @@ -1,3 +1,3 @@ #!flask/bin/python from app import app -app.run(debug=True) +app.run(debug=True, ssl_context='adhoc') -- cgit v1.2.3-54-g00ecf