예제 #1
1
def test_context_local():
    responses.add(responses.GET, "https://google.com")

    # set up two apps with two different set of auth tokens
    app1 = Flask(__name__)
    ghbp1 = make_github_blueprint("foo1", "bar1", redirect_to="url1")
    app1.register_blueprint(ghbp1)
    ghbp1.token_getter(lambda: {"access_token": "app1"})

    app2 = Flask(__name__)
    ghbp2 = make_github_blueprint("foo2", "bar2", redirect_to="url2")
    app2.register_blueprint(ghbp2)
    ghbp2.token_getter(lambda: {"access_token": "app2"})

    # outside of a request context, referencing functions on the `github` object
    # will raise an exception
    with pytest.raises(RuntimeError):
        github.get("https://google.com")

    # inside of a request context, `github` should be a proxy to the correct
    # blueprint session
    with app1.test_request_context("/"):
        app1.preprocess_request()
        github.get("https://google.com")
        request = responses.calls[0].request
        assert request.headers["Authorization"] == "Bearer app1"


    with app2.test_request_context("/"):
        app2.preprocess_request()
        github.get("https://google.com")
        request = responses.calls[1].request
        assert request.headers["Authorization"] == "Bearer app2"
예제 #2
0
def logged_in(blueprint, token):
    from .models import User
    if blueprint.name == "facebook":
        resp = facebook.get("/me?fields=name,first_name,email")
        email = resp.json()["email"]
        f_name = resp.json()["first_name"]
        account_type = "facebook"
    elif blueprint.name == "github":
        user_info = github.get("/user")
        user_email = github.get("/user/emails")
        email = user_email.json()[0]["email"]
        f_name = user_info.json()["name"]
        account_type = "github"
    elif blueprint.name == "gitlab":
        resp = gitlab.get("user")
        email = resp.json()["email"]
        f_name = resp.json()["name"].split()[0]
        account_type = "gitlab"
    user = User.query.filter_by(email=email).first()
    if not user:
        user = User(email=email, f_name=f_name)
        user.account_type = account_type
        try:
            db.session.add(user)
            db.session.commit()
        except Exception as err:
            db.session.rollback()
            print(err)
    login_user(user)
    g.user = user
    flash(_("You have been logged in."), category="success")
예제 #3
0
def get_repos():
    """Endpoint to get all repos and store in DB"""
    # Get our users repos and check
    user_resp = github.get("/user")
    resp = github.get("/user/repos")
    if not resp.ok:
        render_template('error.html', status_code=300)

    # Convert to readable
    user_resp = user_resp.json()
    username = user_resp['login']
    resp = resp.json()
    # Loop and and save
    repos = {}
    for repo in resp:
        repos[repo['name']] = repo['git_url']

    # Add/update database
    try:
        user_data = octoDB.query_user(username)
        if not user_data:
            raise Exception("Count not find user")
        user_data['repos'] = repos
        octoDB.update_user(username, user_data)
    except Exception as e:
        logging.warning(f"Something went wrong when syncing repos for {username}\nException: {e}")
        render_template('error.html', status_code=505)

    return redirect('/dashboard')
예제 #4
0
def control_panel():
    """
    TEAM COPPER ONLY!!!
    """
    if not github.authorized:
        return redirect(url_for("github.login"))
    username = github.get("/user").json()['login']
    resp = github.get("/user/orgs")
    if resp.ok:

        # Only Team Copper members can access the control panel
        all_orgs = resp.json()
        for org in all_orgs:
            if org['login'] == 'dcppc':
                copper_team_id = '2700235'
                mresp = github.get('/teams/%s/members/%s' %
                                   (copper_team_id, username))
                if mresp.status_code == 204:
                    # Business as usual
                    return render_template("controlpanel.html")

        # Not in dcppc
        return render_template('403.html')

    # Could not reach Github
    return render_template('404.html')
예제 #5
0
def catch_all(path):

    if not github.authorized:
        return redirect(url_for("github.login"))

    username = github.get("/user").json()['login']
    target_org = 'microsoft'

    static_path = app.config["RESULT_STATIC_PATH"]
    resp = github.get("/user/orgs")
    if resp.ok:

        all_orgs = resp.json()
        for org in all_orgs:
            if org['login'] == target_org:

                if (path == ''):
                    return send_from_directory(static_path, 'index.html')

                elif (isdir(join(static_path, path))):
                    return send_from_directory(join(static_path, path),
                                               'index.html')

                elif (isfile(join(static_path, path))):
                    return send_from_directory(static_path, path)

                else:
                    return contents404

    return contents403
예제 #6
0
def list_docs(doctype):
    if not github.authorized:
        return redirect(url_for("github.login"))
    username = github.get("/user").json()['login']
    resp = github.get("/user/orgs")
    if resp.ok:
        all_orgs = resp.json()
        for org in all_orgs:
            if org['login'] == 'dcppc':
                # Business as usual
                search = Search(app.config["INDEX_DIR"])
                results_list = search.get_list(doctype)
                for result in results_list:
                    if 'created_time' in result.keys():
                        ct = result['created_time']
                        result['created_time'] = datetime.strftime(
                            ct, "%Y-%m-%d %I:%M %p")
                    if 'modified_time' in result.keys():
                        mt = result['modified_time']
                        result['modified_time'] = datetime.strftime(
                            mt, "%Y-%m-%d %I:%M %p")
                    if 'indexed_time' in result.keys():
                        it = result['indexed_time']
                        result['indexed_time'] = datetime.strftime(
                            it, "%Y-%m-%d %I:%M %p")
                return jsonify(results_list)

    # nope
    return render_template('403.html')
예제 #7
0
def index():
    if not github.authorized:
        return render_template("landing.html")
    else:
        json_username = github.get("/user").json()
        if 'message' in json_username.keys():
            if 'API rate limit exceeded' in json_username['message']:
                return '<h2>Error connecting to Github!</h2> <p>Please file an issue in <a href="https://github.com/dcppc/centillion">dcppc/centillion</a></p>'

        username = github.get("/user").json()['login']
        resp = github.get("/user/orgs")
        if resp.ok:

            # If they are in dcppc, redirect to search.
            # Otherwise, hit em with a 403
            all_orgs = resp.json()
            for org in all_orgs:
                if org['login'] == 'dcppc':
                    # Business as usual
                    return redirect(url_for("search", query="", fields=""))

            # Not in dcppc
            return render_template('403.html')

        # Could not reach Github
        return render_template('404.html')
예제 #8
0
파일: auth.py 프로젝트: loleg/dribdat
def github_login():
    if not github.authorized:
        flash('Access denied - please try again', 'warning')
        return redirect(url_for("auth.login", local=1))

    resp = github.get("/user")
    if not resp.ok:
        flash('Unable to access GitHub data', 'danger')
        return redirect(url_for("auth.login", local=1))
    resp_user = resp.json()
    if 'email' not in resp_user or 'login' not in resp_user:
        flash('Invalid GitHub data format', 'danger')
        # print(resp_user)
        return redirect(url_for("auth.login", local=1))

    resp_emails = github.get("/user/emails")
    if not resp.ok:
        flash('Unable to access GitHub e-mail data', 'danger')
        return redirect(url_for("auth.login", local=1))
    for u in resp_emails.json():
        if u['primary'] and u['verified']:
            return get_or_create_sso_user(
                resp_user['id'], resp_user['login'], u['email'],
                'https://github.com/%s' % resp_user['login'])
    flash('Please verify an e-mail with GitHub', 'danger')
    return redirect(url_for("auth.login", local=1))
예제 #9
0
def index():
    if not github.authorized:
        return redirect(url_for("github.login"))

    # Get user details
    resp = github.get("/user")
    ret = '<h2>USER DETAILS:</h2><br>'
    if resp.ok:
        ret += "You are %s on GitHub<br>" % resp.json()["login"]
    else:
        ret += 'FAILED AT GETTING USER DATA<br>'

    # Get user organizations
    ret += '<h2>ORGANIZATIONS:</h2><br>'
    resp = github.get("/user/orgs")
    if not resp.ok:
        ret += 'FAILED AT GETTING USERORG DATA<br>'
    else:
        u_orgs = resp.json()
        ret += "<pre>%s</pre><br>" % json.dumps(u_orgs, indent=4)

        # Check if user is part of Amedia
        for org in u_orgs:
            if org.get('id', None) == AMEDIA_ORG_ID:
                ret += '<h3>--- YOU ARE PART OF AMEDIA ORGANIZATION --- </h3>'
                break
        else:
            ret += '<h3>--- YOU ARE NOT MEMBER OF AMEDIA --- </h3>'

    # Finally return the retval
    return ret
예제 #10
0
def login():
    if env == 'dev':
        flash('You are in dev mode, and don\'t need to login')
        return redirect(url_for('index'))

    if not github.authorized:
        return redirect(url_for("github.login"))

    user = github.get("/user").json()
    orgs = github.get(user['organizations_url']).json()

    # if you have opengridcc in your public organizations, you are a contributor :-)
    session['contributor'] = 'opengridcc' in {org['login'] for org in orgs}
    session['username'] = user["login"]

    if user_is_contributor():
        flash('Welcome, {user}. Thanks for contributing to OpenGrid!'.format(
            user=session['username']))
    else:
        flash(
            'Welcome, {user}. Become an OpenGrid member to view all restricted pages\n'
            'To register yourself as OpenGrid member, send a mail to [email protected]'
            .format(user=session['username']))

    return redirect(url_for('index'))
예제 #11
0
def authorized(blueprint, token):
    if google.authorized:
        user_info = google.get("/oauth2/v2/userinfo")
        assert user_info.ok
        user_info = {'google': user_info.json()}
        user_email = user_info['google']['email'].lower()
    elif github.authorized:
        user_emails = github.get("/user/emails")
        user_email = [x for x in user_emails.json() if x['primary']][0]["email"].lower()
        user_info = {'github': github.get('/user').json()}
        user_info['github']['email'] = user_email
    else:
        flash("Error logging in!")
        return redirect(url_for("auth.choose_login"))

    # Create or get existing user.
    user = user_ds(user_email)
    if not user._exists:
        user.user_email = user_email
        user.user_info = user_info
        user.email_confirmation_code = unique_id()
        user.user_id = unique_id()[0:8]
        user.username = slugify("{}_{}".format(user_email.split("@")[0], unique_id()[0:4]))

    user.last_login = arrow.utcnow().datetime
    user.save()

    session['user'] = user.to_dict()
    logger.debug(session)

    flash("Successfully logged in!", 'success')
    return redirect(session.get("login_referrer", url_for('primary.primary')))
예제 #12
0
def update_index(run_which):
    """
    TEAM COPPER ONLY!!!
    """
    if not github.authorized:
        return redirect(url_for("github.login"))
    username = github.get("/user").json()['login']
    resp = github.get("/user/orgs")
    if resp.ok:

        # Only Team Copper members can update the index
        all_orgs = resp.json()
        for org in all_orgs:
            if org['login'] == 'dcppc':
                copper_team_id = '2700235'
                mresp = github.get('/teams/%s/members/%s' %
                                   (copper_team_id, username))
                if mresp.status_code == 204:
                    # Business as usual
                    UpdateIndexTask(app.config,
                                    diff_index=False,
                                    run_which=run_which)
                    flash("Rebuilding index, check console output")
                    # This redirects user to /control_panel route
                    # to prevent accidental re-indexing
                    return redirect(url_for("control_panel"))

    return render_template('403.html')
예제 #13
0
파일: myapp.py 프로젝트: huijuannan/mipe
def before_request():
    '''在 request 之前:
    1、建立 MySQL 数据库连接
    2、检验用户登录状态,若已登录则存入 g.user
    '''
    
    # 建立 MySQL 连接,参数:host:port, database, user, passwd
    # torndb 默认已将 charset 设为 utf-8
    g.db = torndb.Connection(
        config.MYSQL_HOST,
        config.MYSQL_DB,
        config.MYSQL_USER,
        config.MYSQL_PW
        )
    
    g.user = None

    if github.authorized:
        gh_name = github.get("/user").json()['login']

        find_user = g.db.get("SELECT * FROM User where ghName=%s", gh_name)

        if find_user == None:
            # 获取用户邮箱,需要用户在 github 的 profile 设置里把邮箱设为公开可见
            email = github.get("/user").json()['email']

            g.db.insert("INSERT INTO User (ghName, email) VALUES (%s, %s)", 
                gh_name, email)

        g.user = g.db.get("SELECT * FROM User where ghName=%s", gh_name)
예제 #14
0
            def new_function(old_function):
                if not github.authorized:
                    if self.is_landing_page:
                        return render_template("landing.html")
                    else:
                        return redirect(url_for("github.login"))

                try:
                    username_payload = github.get('/user').json()
                    username = username_payload['login']
                except KeyError:
                    err = "ERROR: Could not find 'login' key from /user endpoint of Github API, "
                    err += "may have hit rate limit.\n"
                    err += "Payload:\n"
                    err += "%s" % (username_payload)
                    logging.exception(err)
                    return render_template('404.html')

                # The admin setting in the config file
                # affects which whitelist we use to
                # control access to the page.
                #
                # If this is an admin page,
                # use the admin whitelist, &c.
                if self.admin:
                    logins_whitelist = app.config[
                        'ADMIN_WHITELIST_GITHUB_LOGINS']
                    orgs_whitelist = app.config['ADMIN_WHITELIST_GITHUB_ORGS']
                    teams_whitelist = app.config[
                        'ADMIN_WHITELIST_GITHUB_TEAMS']
                else:
                    logins_whitelist = app.config['WHITELIST_GITHUB_LOGINS']
                    orgs_whitelist = app.config['WHITELIST_GITHUB_ORGS']
                    teams_whitelist = app.config['WHITELIST_GITHUB_TEAMS']

                if username in logins_whitelist:
                    old_function(*args, **kwargs)  # Proceed

                # For each of the user's organizations,
                # see if any are on the orgs whitelist
                resp = github.get("/user/orgs")
                if resp.ok:
                    all_orgs = resp.json()
                    for org in all_orgs:
                        if org['login'] in orgs_whitelist:
                            old_function(*args, **kwargs)  # Proceed

                # For each of the team IDs on the whitelist,
                # check if the user is a member of that team
                for teamid in teams_whitelist:
                    teamresp = github.get('/teams/%s/members/%s' %
                                          (copper_team_id, username))
                    if mresp.status_code == 204:
                        old_function(*args, **kwargs)  # Proceed

                # User is not on any whitelists
                return render_template('403.html')
예제 #15
0
def index():
    if not github.authorized:
        return redirect(url_for('github.login'))
    username = github.get('/user').json()['login']
    orgs = json.loads(github.get(f'/users/{username}/orgs').text)
    for org in orgs:
        if app.config.get('GITHUB_OAUTH_ALLOWED_ORGANIZATIONS') in org['login']:
            return render_template('index.html')
    return render_template('403page.html')
예제 #16
0
def templates():
    if not github.authorized:
        return redirect(url_for('github.login'))
    username = github.get('/user').json()['login']
    orgs = json.loads(github.get(f'/users/{username}/orgs').text)
    for org in orgs:
        if app.config.get('GITHUB_OAUTH_ALLOWED_ORGANIZATIONS') in org['login']:
            templates = db.session.query(Templates).order_by(Templates.template_id).all()
            return render_template('snippets/templates.html', templates=templates)
    return render_template('403page.html')
예제 #17
0
파일: app.py 프로젝트: legalian/synergi
def joinjoin():
	data = request.json
	repo = Project.query.filter_by(id=int(data['projectId'])).first()
	if repo == None: return "nah bruh",403
	creds=session['githubuser']
	if creds == None: return "nah son- you got no credentials",403

	#github api calls are done with github.get(path) or github.post(path). you can see the pattern below.
	#here we need to tell the user to f**k themselves with a rusty pipe if they try to edit a repo they dont have write permissions for
	#dunno which api endpoint to hit but its probably not too bad

	write_user_list = github.get("/repos/"+repo.owner+"/"+repo.repo + "/contributors").json()
	for user in write_user_list:
		if user['login'] == session['githubuser']:
			break
	else:
		return "User does not have write access", 403


	sesh = Session.query.filter_by(project_id=int(repo.id)).first()
	if sesh == None:
		print("session does not exist, creating new session")
		master = github.get("/repos/"+repo.owner+"/"+repo.repo+"/branches/"+repo.branch)
		head_tree_sha = master.json()['commit']['commit']['tree']['sha']
		sesh = Session(
			owner      = repo.owner,
			repo       = repo.repo,
			branch     = repo.branch,
			sha        = head_tree_sha,
			project_id = repo.id,
			activemembers = None,
		)
		db.session.add(sesh)
		db.session.commit()
		# make every file in the tree a temFile

		file_tree = github.get("/repos/"+ repo.owner +"/"+ repo.repo +"/git/trees/"+ head_tree_sha +"?recursive=1").json()
		for file in file_tree['tree']:
			formattedprint(file)
			if(file['type'] != "tree"):
				book = TemFile(
					session_id = sesh.id,
					path = file['path'],
					content = "",
					sha = file['sha'],
					md5 = hashlib.md5("".encode("utf-8")).hexdigest()
				)
				formattedprint(book.path)

				db.session.add(book)
		db.session.commit()

	session['sessionId'] = sesh.id

	return "OK"
예제 #18
0
def process_pr():
    """
    Process (or re-process) a pull request.

    Normally, when a pull request is opened, we check to see if the author is
    an edX employee, or a contractor working for edX. If so, we don't process
    the pull request normally -- either it is skipped, or we add an informative
    comment without making a JIRA ticket. Using this endpoint will skip those
    checks. We will make a JIRA ticket if one doesn't already exist, without
    checking to see if the author is special.
    """
    repo = request.form.get("repo", "")
    if not repo:
        resp = jsonify({"error": "Pull request repo required"})
        resp.status_code = 400
        return resp
    num = request.form.get("number")
    if not num:
        resp = jsonify({"error": "Pull request number required"})
        resp.status_code = 400
        return resp
    num = int(num)
    pr_resp = github.get("/repos/{repo}/pulls/{num}".format(repo=repo,
                                                            num=num))
    if not pr_resp.ok:
        resp = jsonify({"error": pr_resp.text})
        resp.status_code = 400
        return resp

    repo_resp = github.get("/repos/{repo}".format(repo=repo))
    repo_json = repo_resp.json()
    if not repo_json["permissions"]["admin"]:
        resp = jsonify({
            "error":
            "This bot does not have permissions for repo '{}'.\n\nPlease manually make an OSPR ticket on JIRA."
            .format(repo)
        })
        resp.status_code = 400
        return resp

    pr = pr_resp.json()
    result = pull_request_opened.delay(
        pr,
        ignore_internal=False,
        check_contractor=False,
        wsgi_environ=minimal_wsgi_environ(),
    )
    status_url = url_for("tasks.status", task_id=result.id, _external=True)
    resp = jsonify({"message": "queued", "status_url": status_url})
    resp.status_code = 202
    resp.headers["Location"] = status_url
    return resp
예제 #19
0
def index():
    if not github.authorized:
        return redirect(url_for("github.login"))

    username = github.get("/user").json()['login']
    target_org = 'microsoft'

    resp = github.get("/user/orgs")
    if resp.ok:

        all_orgs = resp.json()
        for org in all_orgs:
            if org['login'] == target_org:
                return send_from_directory(os.getcwd(), 'index.html')
예제 #20
0
    def index(name=None):
        if not github.authorized:
            return redirect(url_for("github.login"))
        resp = github.get("/user")
        assert resp.ok
        user = resp.json()

        resp = github.get("/rate_limit")
        assert resp.ok
        rate = resp.json()

        return render_template('index.html',
                               name=user["login"],
                               rate=rate['resources'])
예제 #21
0
def parse_request():

    if not github.authorized:
        return redirect(url_for("github.login"))
    username = github.get("/user").json()['login']
    resp = github.get("/user/orgs")
    if resp.ok:
        all_orgs = resp.json()
        for org in all_orgs:
            if org['login'] == 'dcppc':

                try:
                    # Business as usual
                    data = request.form.to_dict()
                    data['github_login'] = username
                    data['timestamp'] = datetime.now().strftime(
                        "%Y-%m-%d %H:%M:%S")

                    feedback_database = 'feedback_database.json'
                    if not os.path.isfile(feedback_database):
                        with open(feedback_database, 'w') as f:
                            json_data = [data]
                            json.dump(json_data, f, indent=4)

                    else:
                        json_data = []
                        with open(feedback_database, 'r') as f:
                            json_data = json.load(f)

                        json_data.append(data)

                        with open(feedback_database, 'w') as f:
                            json.dump(json_data, f, indent=4)

                    ## Should be done with Javascript
                    #flash("Thank you for your feedback!")
                    return jsonify({
                        'status': 'ok',
                        'message': 'Thank you for your feedback!'
                    })
                except:
                    return jsonify({
                        'status':
                        'error',
                        'message':
                        'An error was encountered while submitting your feedback. Try submitting an issue in the <a href="https://github.com/dcppc/centillion/issues/new">dcppc/centillion</a> repository.'
                    })

    # nope
    return render_template('403.html')
예제 #22
0
def jira_issue_status_changed(issue, changelog, bugsnag_context=None):
    bugsnag_context = bugsnag_context or {}
    pr_num = github_pr_num(issue)
    pr_repo = github_pr_repo(issue)
    pr_url = github_pr_url(issue)
    issue_url = pr_url.replace("pulls", "issues")

    status_changelog = [item for item in changelog["items"] if item["field"] == "status"][0]
    old_status = status_changelog["fromString"]
    new_status = status_changelog["toString"]

    # get github issue
    gh_issue_resp = github.get(issue_url)
    if not gh_issue_resp.ok:
        raise requests.exceptions.RequestException(gh_issue_resp.text)
    gh_issue = gh_issue_resp.json()

    # get repo labels
    repo_labels_resp = github.get("/repos/{repo}/labels".format(repo=pr_repo))
    if not repo_labels_resp.ok:
        raise requests.exceptions.RequestException(repo_labels_resp.text)
    # map of label name to label URL
    repo_labels = {l["name"]: l["url"] for l in repo_labels_resp.json()}
    # map of label name lowercased to label name in the case that it is on Github
    repo_labels_lower = {name.lower(): name for name in repo_labels}

    # Get all the existing labels on this PR
    pr_labels = [label["name"] for label in gh_issue["labels"]]
    print("old labels: {}".format(pr_labels), file=sys.stderr)

    # remove old status label
    old_status_label = repo_labels_lower.get(old_status.lower(), old_status)
    print("old status label: {}".format(old_status_label), file=sys.stderr)
    if old_status_label in pr_labels:
        pr_labels.remove(old_status_label)
    # add new status label
    new_status_label = repo_labels_lower[new_status.lower()]
    print("new status label: {}".format(new_status_label), file=sys.stderr)
    if new_status_label not in pr_labels:
        pr_labels.append(new_status_label)

    print("new labels: {}".format(pr_labels), file=sys.stderr)

    # Update labels on github
    update_label_resp = github.patch(issue_url, json={"labels": pr_labels})
    if not update_label_resp.ok:
        raise requests.exceptions.RequestException(update_label_resp.text)
    return "Changed labels of PR #{num} to {labels}".format(num=pr_num, labels=pr_labels)
예제 #23
0
def jira_issue_rejected(issue):
    issue_key = to_unicode(issue["key"])

    pr_num = github_pr_num(issue)
    pr_url = github_pr_url(issue)
    issue_url = pr_url.replace("pulls", "issues")

    gh_issue_resp = github.get(issue_url)
    gh_issue_resp.raise_for_status()
    gh_issue = gh_issue_resp.json()
    sentry.client.extra_context({"github_issue": gh_issue})
    if gh_issue["state"] == "closed":
        # nothing to do
        msg = "{key} was rejected, but PR #{num} was already closed".format(
            key=issue_key, num=pr_num)
        print(msg, file=sys.stderr)
        return msg

    # Comment on the PR to explain to look at JIRA
    username = to_unicode(gh_issue["user"]["login"])
    comment = {
        "body": ("Hello @{username}: We are unable to continue with "
                 "review of your submission at this time. Please see the "
                 "associated JIRA ticket for more explanation.".format(
                     username=username))
    }
    comment_resp = github.post(issue_url + "/comments", json=comment)
    comment_resp.raise_for_status()

    # close the pull request on Github
    close_resp = github.patch(pr_url, json={"state": "closed"})
    close_resp.raise_for_status()

    return "Closed PR #{num}".format(num=pr_num)
예제 #24
0
def github_whoami():
    self_resp = github.get("/user")
    rate_limit_info = {k: v for k, v in self_resp.headers.items() if "ratelimit" in k}
    print("Rate limits: {}".format(rate_limit_info), file=sys.stderr)
    if not self_resp.ok:
        raise requests.exceptions.RequestException(self_resp.text)
    return self_resp.json()
예제 #25
0
def process_pr():
    if request.method == "GET":
        return render_template("github_process_pr.html")
    repo = request.form.get("repo", "")
    if not repo:
        resp = jsonify({"error": "repo required"})
        resp.status_code = 400
        return resp
    num = request.form.get("number")
    if not num:
        resp = jsonify({"error": "num required"})
        resp.status_code = 400
        return resp
    num = int(num)
    pr_resp = github.get("/repos/{repo}/pulls/{num}".format(repo=repo, num=num))
    if not pr_resp.ok:
        resp = jsonify({"error": pr_resp.text})
        resp.status_code = 400
        return resp

    pr = pr_resp.json()
    result = pull_request_opened.delay(
        pr, ignore_internal=False, check_contractor=False,
        wsgi_environ=minimal_wsgi_environ(),
    )
    status_url = url_for("tasks.status", task_id=result.id, _external=True)
    resp = jsonify({"message": "queued", "status_url": status_url})
    resp.status_code = 202
    resp.headers["Location"] = status_url
    return resp
예제 #26
0
    def wrapper_fetch_user(*args, **kwargs):
        if github.authorized:
            if not session.get("user_id"):
                r = github.get("/user")
                github_user = json.loads(r.text)
                user = User.query.filter(User.id == github_user["id"]).first()

                if user:
                    user.github_login = github_user["login"]
                else:
                    user = User(github_user["id"], github_user["login"],
                                github_user["login"], "")
                    db.session.add(user)

                db.session.commit()
                db.session.refresh(user)
                session["user_id"] = user.id

            else:
                user = User.query.filter(User.id == session["user_id"]).first()

            session["user"] = user.to_dict()
            session["user"]["is_admin"] = session["user"][
                "github_login"] in app.config["DASHBOARD_ADMIN"]
            db.session.close()

        return func(*args, **kwargs)
예제 #27
0
 def rateLimit():
     if not github.authorized:
         return redirect(url_for("github.login"))
     resp = github.get("/rate_limit")
     assert resp.ok
     data = resp.json()
     return data
예제 #28
0
def add_alias():
    """This is for adding alias"""
    # If not authorized
    if not github.authorized:
        return render_template('error.html', status_code=487)
    # Get the user and pull up their DB info
    resp = github.get("/user")
    if not resp.ok:
        render_template('error.html', status_code=300)
    resp = resp.json()
    username = resp['login']

    # Get our users data, if they don't have any data create it
    try:
        user_data = octoDB.query_user(username)
        if not user_data:
            raise Exception("User not found")

        # Create a random number and email it to the user
        user_data = mail_client.send_code(resp['email'], user_data)
        octoDB.update_user(username, user_data)
    except Exception as e:
        logging.warning(f"Something went wrong when adding alias for {username}\nException: {e}")
        return render_template('error.html', status_code=505)

    kwargs = "alias_requested"
    return redirect(f"/dashboard?kwargs={kwargs}")
예제 #29
0
def jira_issue_rejected(issue):
    issue_key = to_unicode(issue["key"])

    pr_num = github_pr_num(issue)
    pr_url = github_pr_url(issue)
    issue_url = pr_url.replace("pulls", "issues")

    gh_issue_resp = github.get(issue_url)
    gh_issue_resp.raise_for_status()
    gh_issue = gh_issue_resp.json()
    sentry.client.extra_context({"github_issue": gh_issue})
    if gh_issue["state"] == "closed":
        # nothing to do
        msg = "{key} was rejected, but PR #{num} was already closed".format(
            key=issue_key, num=pr_num
        )
        print(msg, file=sys.stderr)
        return msg

    # Comment on the PR to explain to look at JIRA
    username = to_unicode(gh_issue["user"]["login"])
    comment = {"body": (
        "Hello @{username}: We are unable to continue with "
        "review of your submission at this time. Please see the "
        "associated JIRA ticket for more explanation.".format(username=username)
    )}
    comment_resp = github.post(issue_url + "/comments", json=comment)
    comment_resp.raise_for_status()

    # close the pull request on Github
    close_resp = github.patch(pr_url, json={"state": "closed"})
    close_resp.raise_for_status()

    return "Closed PR #{num}".format(num=pr_num)
예제 #30
0
def github_login():
    if not github.authorized:
        return redirect(url_for('github.login'))
    else:
        account_info = github.get('/user')
        if account_info.ok:
            account_info_json = account_info.json()
            print("account info json", account_info_json)
            with app.app_context():
                user = {
                    "username": "******",
                    "email": "*****@*****.**",
                    "login": account_info_json['login'],
                    "location": account_info_json['location'],
                    "roleid": ""
                }

                db = database.createUser(user)
                print("user in db is...", db)
                if db:
                    role = database.getRole(db['roleid'])
                    if role:
                        # token=generate_token.generateToken(account_info_json['name'],role['role'])
                        token = generate_token.generateToken(
                            db['username'], role['role'])
                        print("token is...", token)
                        session['bearerToken'] = token
                        session['username'] = account_info_json['login']
                        rendered = render_template('blog.html', \
                                                   session=session)
                        return rendered
            # return '<h1>Your Github name is {}'.format(account_info_json['login'])

    return '<h1>Request failed!</h1>'
예제 #31
0
파일: app.py 프로젝트: MilRoad/Web-Project
def github_login():
    if not github.authorized:
        return redirect(url_for('github.login'))
    account_info = github.get('/user')
    if account_info.ok:
        account_info_json = account_info.json()
        email = account_info_json['login']
        session['email'] = email
        session['type'] = 'programmer'
        cur.execute('select * from emails where email=%s', (email, ))
        user = cur.fetchone()
        if user == None:
            status = 'False'
            cur.execute(
                'insert into emails (email, status) values (%s, %s) returning id',
                (email, status))
            conn.commit()
            return render_template('github.html', email=email)
        else:
            if user[2] == 'False':
                conn.commit()
                return render_template('github.html', email=email)
            else:
                id = user[0]
                conn.commit()
                return redirect(f'/profile/{id}')
    return '<h1> Request failed </h1>'
예제 #32
0
def dashboard():
    """This is for displaying the dashboard"""
    # Check if our user is authorized and working
    if not github.authorized:
        return redirect(url_for("github.login"))
    resp = github.get("/user")
    if not resp.ok:
        render_template('error.html', status_code=300)

    # Get the username and password
    resp = resp.json()
    username = resp['login']
    email = resp['email']

    # Get our users data, if they don't have any data create it
    try:
        user_data = octoDB.query_user(username)
        if not user_data:
            user_data = octoDB.create_user(username, email)
            if user_data is False:
                raise Exception(f"DB Error updating user {username}")
    except Exception as e:
        logging.warning(f"Something went wrong when getting data for {username}.\nException: {e}")

    kwargs = request.args.get('kwargs')
    return render_template('dashboard.html', user_data=user_data, kwargs=kwargs)
예제 #33
0
파일: app.py 프로젝트: Abdo-461/myFinance
def githubLogin():
    if not github.authorized:
        return redirect(url_for("github.login"))
    res = github.get("/user")
    if res.ok:
        oauth = github_blueprint.session.access_token
        account_info = res.json()
        session['user_name'] = account_info["name"]
        session['user_email'] = account_info["email"]
        # check if user is in the DB otherwise add email, password, oauth token
        table = dynamodb.Table('oauthusers')
        # Query table to see if email exists
        response = table.query(
            KeyConditionExpression=Key('user_email').eq(session['user_email']))
        items = response['Items']
        # If email doesn't exist add information to database table
        if not items:
            table.put_item(
                Item={
                    'user_email': session['user_email'],
                    'user_name': session['user_name'],
                    'oauth_token': oauth
                })
    # Update oauth token
    if response['Items'][0]['oauth_token'] != oauth:
        table.put_item(
            Item={
                'user_email': session['user_email'],
                'user_name': session['user_name'],
                'oauth_token': oauth
            })
    # validate oauth token
    if oauth == response['Items'][0]['oauth_token']:
        return redirect(url_for('dashboard'))
예제 #34
0
파일: api_func.py 프로젝트: 5d-jh/circruit
def get_gh_projects_info():
    resp = github.get("/user/repos?affiliation=owner")
    json_data = resp.json()
    if resp.ok:
        return resp.json()
    else:
        []
예제 #35
0
def index():
    if not github.authorized:
        return redirect("/auth")
    resp = github.get("/user")
    assert resp.ok

    githubData = resp.json()
    u = User.where('github_id', githubData["id"]).first()

    if u == None:
        print("none")
        user = User()
        user.name = githubData["name"]
        user.username = githubData["login"]
        user.email = githubData["email"]
        user.github_id = githubData["id"]
        user.avatar_url = githubData["avatar_url"]
        user.github_api_url = githubData["url"]
        user.access_token = session["github_oauth_token"]["access_token"]
        user.github_html_url = githubData["html_url"]
        user.save()
        u = user

    session["user"] = u.to_json()
    return render_template("search.html", user=u)
def process_pr():
    """
    Process (or re-process) a pull request.

    Normally, when a pull request is opened, we check to see if the author is
    an edX employee, or a contractor working for edX. If so, we don't process
    the pull request normally -- either it is skipped, or we add an informative
    comment without making a JIRA ticket. Using this endpoint will skip those
    checks. We will make a JIRA ticket if one doesn't already exist, without
    checking to see if the author is special.
    """
    repo = request.form.get("repo", "")
    if not repo:
        resp = jsonify({"error": "Pull request repo required"})
        resp.status_code = 400
        return resp
    num = request.form.get("number")
    if not num:
        resp = jsonify({"error": "Pull request number required"})
        resp.status_code = 400
        return resp
    num = int(num)
    pr_resp = github.get("/repos/{repo}/pulls/{num}".format(repo=repo, num=num))
    if not pr_resp.ok:
        resp = jsonify({"error": pr_resp.text})
        resp.status_code = 400
        return resp

    repo_resp = github.get("/repos/{repo}".format(repo=repo))
    repo_json = repo_resp.json()
    if not repo_json["permissions"]["admin"]:
        resp = jsonify({
            "error": "This bot does not have permissions for repo '{}'.\n\nPlease manually make an OSPR ticket on JIRA.".format(repo)
        })
        resp.status_code = 400
        return resp

    pr = pr_resp.json()
    result = pull_request_opened.delay(
        pr, ignore_internal=False, check_contractor=False,
        wsgi_environ=minimal_wsgi_environ(),
    )
    status_url = url_for("tasks.status", task_id=result.id, _external=True)
    resp = jsonify({"message": "queued", "status_url": status_url})
    resp.status_code = 202
    resp.headers["Location"] = status_url
    return resp
예제 #37
0
def process_pr():
    if request.method == "GET":
        return render_template("github_process_pr.html")
    repo = request.form.get("repo", "")
    if not repo:
        resp = jsonify({"error": "Pull request repo required"})
        resp.status_code = 400
        return resp
    num = request.form.get("number")
    if not num:
        resp = jsonify({"error": "Pull request number required"})
        resp.status_code = 400
        return resp
    num = int(num)
    pr_resp = github.get("/repos/{repo}/pulls/{num}".format(repo=repo, num=num))
    if not pr_resp.ok:
        resp = jsonify({"error": pr_resp.text})
        resp.status_code = 400
        return resp

    repo_resp = github.get("/repos/{repo}".format(repo=repo))
    repo_json = repo_resp.json()
    if not repo_json["permissions"]["admin"]:
        resp = jsonify({
            "error": "This bot does not have permissions for repo '{}'.\n\nPlease manually make an OSPR ticket on JIRA.".format(repo)
        })
        resp.status_code = 400
        return resp

    pr = pr_resp.json()
    result = pull_request_opened.delay(
        pr, ignore_internal=False, check_contractor=False,
        wsgi_environ=minimal_wsgi_environ(),
    )
    status_url = url_for("tasks.status", task_id=result.id, _external=True)
    resp = jsonify({"message": "queued", "status_url": status_url})
    resp.status_code = 202
    resp.headers["Location"] = status_url
    return resp
예제 #38
0
파일: website.py 프로젝트: saroele/website
def login():
    if env == 'dev':
        flash('You are in dev mode, and don\'t need to login')
        return redirect(url_for('index'))

    if not github.authorized:
        return redirect(url_for("github.login"))

    user = github.get("/user").json()
    orgs = github.get(user['organizations_url']).json()

    # if you have opengridcc in your public organizations, you are a contributor :-)
    session['contributor'] = 'opengridcc' in {org['login'] for org in orgs}
    session['username'] = user["login"]

    if user_is_contributor():
        flash('Welcome, {user}. Thanks for contributing to OpenGrid!'.format(user=session['username']))
    else:
        flash('Welcome, {user}. Become an OpenGrid contributor to view all restricted pages'.format(
            user=session['username']))

    return redirect(url_for('index'))
예제 #39
0
def get_jira_issue_key(pull_request):
    # who am I?
    self_resp = github.get("/user")
    rate_limit_info = {k: v for k, v in self_resp.headers.items() if "ratelimit" in k}
    print("Rate limits: {}".format(rate_limit_info), file=sys.stderr)
    if not self_resp.ok:
        raise requests.exceptions.RequestException(self_resp.text)
    my_username = self_resp.json()["login"]
    # get my first comment on this pull request
    comments_resp = github.get("/repos/{repo}/issues/{num}/comments".format(
        repo=pull_request["base"]["repo"]["full_name"], num=pull_request["number"],
    ))
    if not comments_resp.ok:
        raise requests.exceptions.RequestException(comments_resp.text)
    my_comments = [comment for comment in comments_resp.json()
                   if comment["user"]["login"] == my_username]
    if len(my_comments) < 1:
        return None
    # search for the first occurrance of a JIRA ticket key in the comment body
    match = re.search(r"\b([A-Z]{2,}-\d+)\b", my_comments[0]["body"])
    if match:
        return match.group(0)
    return None
예제 #40
0
def index():
    """
    Just to verify that things are working
    """
    github_username = None
    if github_session._client.token:
        gh_user_resp = github_session.get("/user")
        if gh_user_resp.ok:
            github_username = gh_user_resp.json()["login"]
    jira_username = None
    if jira_session.auth.client.resource_owner_key:
        jira_user_resp = jira_session.get("/rest/api/2/myself")
        if jira_user_resp.ok:
            jira_username = jira_user_resp.json()["name"]
    return render_template("main.html",
        github_username=github_username, jira_username=jira_username,
    )
예제 #41
0
def jira_issue_rejected(issue, bugsnag_context=None):
    bugsnag_context = bugsnag_context or {}
    issue_key = to_unicode(issue["key"])

    pr_num = github_pr_num(issue)
    pr_url = github_pr_url(issue)
    issue_url = pr_url.replace("pulls", "issues")

    gh_issue_resp = github.get(issue_url)
    if not gh_issue_resp.ok:
        raise requests.exceptions.RequestException(gh_issue_resp.text)
    gh_issue = gh_issue_resp.json()
    bugsnag_context["github_issue"] = gh_issue
    bugsnag.configure_request(meta_data=bugsnag_context)
    if gh_issue["state"] == "closed":
        # nothing to do
        msg = "{key} was rejected, but PR #{num} was already closed".format(
            key=issue_key, num=pr_num
        )
        print(msg, file=sys.stderr)
        return msg

    # Comment on the PR to explain to look at JIRA
    username = to_unicode(gh_issue["user"]["login"])
    comment = {"body": (
        "Hello @{username}: We are unable to continue with "
        "review of your submission at this time. Please see the "
        "associated JIRA ticket for more explanation.".format(username=username)
    )}
    comment_resp = github.post(issue_url + "/comments", json=comment)

    # close the pull request on Github
    close_resp = github.patch(pr_url, json={"state": "closed"})
    if not close_resp.ok or not comment_resp.ok:
        bugsnag_context['request_headers'] = close_resp.request.headers
        bugsnag_context['request_url'] = close_resp.request.url
        bugsnag_context['request_method'] = close_resp.request.method
        bugsnag.configure_request(meta_data=bugsnag_context)
        bug_text = ''
        if not close_resp.ok:
            bug_text += "Failed to close; " + close_resp.text
        if not comment_resp.ok:
            bug_text += "Failed to comment on the PR; " + comment_resp.text
        raise requests.exceptions.RequestException(bug_text)
    return "Closed PR #{num}".format(num=pr_num)
예제 #42
0
def index():
    """
    Display an HTML overview page, with links to other functions that
    this application can perform.
    """
    github_username = None
    if github_session.authorized:
        gh_user_resp = github_session.get("/user")
        if gh_user_resp.ok:
            github_username = gh_user_resp.json()["login"]

    jira_username = None
    if jira_session.authorized:
        jira_user_resp = jira_session.get("/rest/api/2/myself")
        if jira_user_resp.ok:
            jira_username = jira_user_resp.json()["name"]

    return render_template("main.html",
        github_username=github_username, jira_username=jira_username,
    )
예제 #43
0
def github_process_pr():
    if request.method == "GET":
        return render_template("github_process_pr.html")
    repo = request.form.get("repo", "")
    if not repo:
        resp = jsonify({"error": "repo required"})
        resp.status_code = 400
        return resp
    num = request.form.get("number")
    if not num:
        resp = jsonify({"error": "num required"})
        resp.status_code = 400
        return resp
    num = int(num)
    pr_resp = github.get("/repos/{repo}/pulls/{num}".format(repo=repo, num=num))
    if not pr_resp.ok:
        resp = jsonify({"error": pr_resp.text})
        resp.status_code = 400
        return resp
    return pr_opened(pr_resp.json(), ignore_internal=False, check_contractor=False)
예제 #44
0
def github_community_pr_comment(pull_request, jira_issue, people=None):
    """
    For a newly-created pull request from an open source contributor,
    write a welcoming comment on the pull request. The comment should:

    * contain a link to the JIRA issue
    * check for contributor agreement
    * check for AUTHORS entry
    * contain a link to our process documentation
    """
    people = people or get_people_file()
    people = {user.lower(): values for user, values in people.items()}
    pr_author = pull_request["user"]["login"].decode('utf-8').lower()
    created_at = parse_date(pull_request["created_at"]).replace(tzinfo=None)
    # does the user have a valid, signed contributor agreement?
    has_signed_agreement = (
        pr_author in people and
        people[pr_author].get("expires_on", date.max) > created_at.date()
    )
    # is the user in the AUTHORS file?
    in_authors_file = False
    name = people.get(pr_author, {}).get("name", "")
    if name:
        authors_url = "https://raw.githubusercontent.com/{repo}/{branch}/AUTHORS".format(
            repo=pull_request["head"]["repo"]["full_name"].decode('utf-8'),
            branch=pull_request["head"]["ref"].decode('utf-8'),
        )
        authors_resp = github.get(authors_url)
        if authors_resp.ok:
            authors_content = authors_resp.text
            if name in authors_content:
                in_authors_file = True

    doc_url = "http://edx-developer-guide.readthedocs.org/en/latest/process/overview.html"
    issue_key = jira_issue["key"].decode('utf-8')
    issue_url = "https://openedx.atlassian.net/browse/{key}".format(key=issue_key)
    contributing_url = "https://github.com/edx/edx-platform/blob/master/CONTRIBUTING.rst"
    agreement_url = "http://open.edx.org/sites/default/files/wysiwyg/individual-contributor-agreement.pdf"
    authors_url = "https://github.com/{repo}/blob/master/AUTHORS".format(
        repo=pull_request["base"]["repo"]["full_name"].decode('utf-8'),
    )
    comment = (
        "Thanks for the pull request, @{user}! I've created "
        "[{issue_key}]({issue_url}) to keep track of it in JIRA. "
        "JIRA is a place for product owners to prioritize feature reviews "
        "by the engineering development teams. "
        "\n\nFeel free to add as much of the following information to the ticket:"
        "\n- supporting documentation"
        "\n- edx-code email threads"
        "\n- timeline information ('this must be merged by XX date', and why that is)"
        "\n- partner information ('this is a course on edx.org')"
        "\n- any other information that can help Product understand the context for the PR"
        "\n\nAll technical communication about the code itself will still be "
        "done via the Github pull request interface. "
        "As a reminder, [our process documentation is here]({doc_url})."
    ).format(
        user=pull_request["user"]["login"].decode('utf-8'),
        issue_key=issue_key,
        issue_url=issue_url,
        doc_url=doc_url,
    )
    if not has_signed_agreement or not in_authors_file:
        todo = ""
        if not has_signed_agreement:
            todo += (
                "submitted a [signed contributor agreement]({agreement_url}) "
                "or indicated your institutional affiliation"
            ).format(
                agreement_url=agreement_url,
            )
        if not has_signed_agreement and not in_authors_file:
            todo += " and "
        if not in_authors_file:
            todo += "added yourself to the [AUTHORS]({authors_url}) file".format(
                authors_url=authors_url,
            )
        comment += ("\n\n"
            "We can't start reviewing your pull request until you've {todo}. "
            "Please see the [CONTRIBUTING]({contributing_url}) file for "
            "more information."
        ).format(todo=todo, contributing_url=contributing_url)
    return comment
예제 #45
0
def pr_opened(pr, ignore_internal=True, check_contractor=True, bugsnag_context=None):
    bugsnag_context = bugsnag_context or {}
    user = pr["user"]["login"].decode('utf-8')
    repo = pr["base"]["repo"]["full_name"]
    num = pr["number"]
    if ignore_internal and is_internal_pull_request(pr):
        # not an open source pull request, don't create an issue for it
        print(
            "@{user} opened PR #{num} against {repo} (internal PR)".format(
                user=user, repo=repo, num=num,
            ),
            file=sys.stderr
        )
        return "internal pull request"

    if check_contractor and is_contractor_pull_request(pr):
        # don't create a JIRA issue, but leave a comment
        comment = {
            "body": github_contractor_pr_comment(pr),
        }
        url = "/repos/{repo}/issues/{num}/comments".format(
            repo=repo, num=num,
        )
        comment_resp = github.post(url, json=comment)
        comment_resp.raise_for_status()
        return "contractor pull request"

    issue_key = get_jira_issue_key(pr)
    if issue_key:
        msg = "Already created {key} for PR #{num} against {repo}".format(
            key=issue_key,
            num=pr["number"],
            repo=pr["base"]["repo"]["full_name"],
        )
        print(msg, file=sys.stderr)
        return msg

    repo = pr["base"]["repo"]["full_name"].decode('utf-8')
    people = get_people_file()
    custom_fields = get_jira_custom_fields()

    if user in people:
        user_name = people[user].get("name", "")
    else:
        user_resp = github.get(pr["user"]["url"])
        if user_resp.ok:
            user_name = user_resp.json().get("name", user)
        else:
            user_name = user

    # create an issue on JIRA!
    new_issue = {
        "fields": {
            "project": {
                "key": "OSPR",
            },
            "issuetype": {
                "name": "Pull Request Review",
            },
            "summary": pr["title"],
            "description": pr["body"],
            custom_fields["URL"]: pr["html_url"],
            custom_fields["PR Number"]: pr["number"],
            custom_fields["Repo"]: pr["base"]["repo"]["full_name"],
            custom_fields["Contributor Name"]: user_name,
        }
    }
    institution = people.get(user, {}).get("institution", None)
    if institution:
        new_issue["fields"][custom_fields["Customer"]] = [institution]
    bugsnag_context["new_issue"] = new_issue
    bugsnag.configure_request(meta_data=bugsnag_context)

    resp = jira.post("/rest/api/2/issue", json=new_issue)
    resp.raise_for_status()
    new_issue_body = resp.json()
    issue_key = new_issue_body["key"].decode('utf-8')
    bugsnag_context["new_issue"]["key"] = issue_key
    bugsnag.configure_request(meta_data=bugsnag_context)
    # add a comment to the Github pull request with a link to the JIRA issue
    comment = {
        "body": github_community_pr_comment(pr, new_issue_body, people),
    }
    url = "/repos/{repo}/issues/{num}/comments".format(
        repo=repo, num=pr["number"],
    )
    comment_resp = github.post(url, json=comment)
    comment_resp.raise_for_status()

    # Add the "Needs Triage" label to the PR
    issue_url = "/repos/{repo}/issues/{num}".format(repo=repo, num=pr["number"])
    label_resp = github.patch(issue_url, data=json.dumps({"labels": ["needs triage", "open-source-contribution"]}))
    label_resp.raise_for_status()

    print(
        "@{user} opened PR #{num} against {repo}, created {issue} to track it".format(
            user=user, repo=repo,
            num=pr["number"], issue=issue_key,
        ),
        file=sys.stderr
    )
    return "created {key}".format(key=issue_key)
예제 #46
0
def pr_opened(pr, bugsnag_context=None):
    bugsnag_context = bugsnag_context or {}
    user = pr["user"]["login"]
    repo = pr["base"]["repo"]["full_name"]
    people = get_people_file()

    if user in people and people[user].get("institution", "") == "edX":
        # not an open source pull request, don't create an issue for it
        print(
            "@{user} opened PR #{num} against {repo} (internal PR)".format(
                user=user, repo=pr["base"]["repo"]["full_name"],
                num=pr["number"]
            ),
            file=sys.stderr
        )
        return "internal pull request"

    field_resp = jira.get("/rest/api/2/field")
    if not field_resp.ok:
        raise requests.exceptions.RequestException(field_resp.text)
    field_map = dict(pop_dict_id(f) for f in field_resp.json())
    custom_fields = {
        value["name"]: id
        for id, value in field_map.items()
        if value["custom"]
    }

    user_resp = github.get(pr["user"]["url"])
    if user_resp.ok:
        user_name = user_resp.json().get("name", user)
    else:
        user_name = user

    # create an issue on JIRA!
    new_issue = {
        "fields": {
            "project": {
                "key": "OSPR",
            },
            "issuetype": {
                "name": "Pull Request Review",
            },
            "summary": pr["title"],
            "description": pr["body"],
            custom_fields["URL"]: pr["html_url"],
            custom_fields["PR Number"]: pr["number"],
            custom_fields["Repo"]: pr["base"]["repo"]["full_name"],
            custom_fields["Contributor Name"]: user_name,
        }
    }
    institution = people.get(user, {}).get("institution", None)
    if institution:
        new_issue["fields"][custom_fields["Customer"]] = [institution]
    bugsnag_context["new_issue"] = new_issue
    bugsnag.configure_request(meta_data=bugsnag_context)

    resp = jira.post("/rest/api/2/issue", data=json.dumps(new_issue))
    if not resp.ok:
        raise requests.exceptions.RequestException(resp.text)
    new_issue_body = resp.json()
    bugsnag_context["new_issue"]["key"] = new_issue_body["key"]
    bugsnag.configure_request(meta_data=bugsnag_context)
    # add a comment to the Github pull request with a link to the JIRA issue
    comment = {
        "body": github_pr_comment(pr, new_issue_body, people),
    }
    url = "/repos/{repo}/issues/{num}/comments".format(
        repo=repo, num=pr["number"],
    )
    comment_resp = github.post(url, data=json.dumps(comment))
    if not comment_resp.ok:
        raise requests.exceptions.RequestException(comment_resp.text)
    print(
        "@{user} opened PR #{num} against {repo}, created {issue} to track it".format(
            user=user, repo=repo,
            num=pr["number"], issue=new_issue_body["key"]
        ),
        file=sys.stderr
    )
    return "created!"
예제 #47
0
def jira_issue_updated():
    """
    Received an "issue updated" event from JIRA.
    https://developer.atlassian.com/display/JIRADEV/JIRA+Webhooks+Overview
    """
    try:
        event = request.get_json()
    except ValueError:
        raise ValueError("Invalid JSON from JIRA: {data}".format(
            data=request.data.decode('utf-8')
        ))
    bugsnag_context = {"event": event}
    bugsnag.configure_request(meta_data=bugsnag_context)

    if app.debug:
        print(json.dumps(event), file=sys.stderr)

    issue_key = event["issue"]["key"].decode('utf-8')

    # is the issue an open source pull request?
    if event["issue"]["fields"]["project"]["key"] != "OSPR":
        # TODO: if the issue has just been moved from the OSPR project to a new project,
        # change the label to "engineering review". Need to figure out if we can tell that
        # the ticket has just moved projects.
        return "I don't care"

    # is there a changelog?
    changelog = event.get("changelog")
    if not changelog:
        # it was just someone adding a comment
        return "I don't care"

    # did the issue change status?
    status_changelog_items = [item for item in changelog["items"] if item["field"] == "status"]
    if len(status_changelog_items) == 0:
        return "I don't care"

    # construct Github API URL
    custom_fields = get_jira_custom_fields()
    pr_repo = event["issue"]["fields"].get(custom_fields["Repo"], "")
    pr_num = event["issue"]["fields"].get(custom_fields["PR Number"])
    if not pr_repo or not pr_num:
        fail_msg = '{key} is missing "Repo" or "PR Number" fields'.format(key=issue_key)
        raise Exception(fail_msg)
    pr_num = int(pr_num)

    pr_url = "/repos/{repo}/pulls/{num}".format(repo=pr_repo, num=pr_num)
    # Need to use the Issues API for label manipulation
    issue_url = "/repos/{repo}/issues/{num}".format(repo=pr_repo, num=pr_num)

    old_status = status_changelog_items[0]["fromString"]
    new_status = status_changelog_items[0]["toString"]

    if new_status == "Rejected":
        issue_resp = github.get(issue_url)
        if not issue_resp.ok:
            raise requests.exceptions.RequestException(issue_resp.text)
        issue = issue_resp.json()
        if issue["state"] == "closed":
            # nothing to do
            msg = "{key} was rejected, but PR #{num} was already closed".format(
                key=issue_key, num=pr_num
            )
            print(msg, file=sys.stderr)
            return msg

        # Comment on the PR to explain to look at JIRA
        username = issue["user"]["login"].decode('utf-8')
        comment = {"body": (
            "Hello @{username}: We are unable to continue with "
            "review of your submission at this time. Please see the "
            "associated JIRA ticket for more explanation.".format(username=username)
        )}
        comment_resp = github.post(issue_url + "/comments", json=comment)

        # close the pull request on Github
        close_resp = github.patch(pr_url, json={"state": "closed"})
        if not close_resp.ok or not comment_resp.ok:
            bugsnag_context['request_headers'] = close_resp.request.headers
            bugsnag_context['request_url'] = close_resp.request.url
            bugsnag_context['request_method'] = close_resp.request.method
            bugsnag.configure_request(meta_data=bugsnag_context)
            bug_text = ''
            if not close_resp.ok:
                bug_text += "Failed to close; " + close_resp.text
            if not comment_resp.ok:
                bug_text += "Failed to comment on the PR; " + comment_resp.text
            raise requests.exceptions.RequestException(bug_text)
        return "Closed PR #{num}".format(num=pr_num)

    elif new_status in STATUS_LABEL_DICT:
        # Get all the existing labels on this PR
        label_list = github.get(issue_url).json()["labels"]

        # Add in the label representing the new status - just add in the plain string label
        label_list.append(STATUS_LABEL_DICT[new_status][0])

        # remove the label representing the old status, if it exists
        if old_status in STATUS_LABEL_DICT:
            # Sometimes labels are strings ("needs triage") whereas other times they're dictionaries
            # with the label name, color, and url defined. Have not pinned down when or why this happens.
            for old_label in STATUS_LABEL_DICT[old_status]:
                try:
                    if isinstance(old_label, dict):
                        old_label["url"] = old_label["url"].format(pr_repo=pr_repo)
                    label_list.remove(old_label)
                except ValueError:
                    print("PR {num} does not have label {old_label} to remove".format(num=pr_num, old_label=old_label))
                    print("PR {num} only has labels {labels}".format(num=pr_num, labels=label_list))
                else:
                    print("PR {num}: Successfully removed label {old_label}".format(num=pr_num, old_label=old_label))
                    break

        # Post the new set of labels to github
        label_resp = github.patch(issue_url, json={"labels": label_list})
        if not label_resp.ok:
            raise requests.exceptions.RequestException(label_resp.text)
        return "Changed label of PR #{num} to {labels}".format(num=pr_num, labels=label_list)

    return "no change necessary"
예제 #48
0
def github_whoami():
    self_resp = github.get("/user")
    rate_limit_info = {k: v for k, v in self_resp.headers.items() if "ratelimit" in k}
    print("Rate limits: {}".format(rate_limit_info), file=sys.stderr)
    self_resp.raise_for_status()
    return self_resp.json()
예제 #49
0
def github_pr_comment(pull_request, jira_issue, people=None):
    """
    For a newly-created pull request from an open source contributor,
    write a welcoming comment on the pull request. The comment should:

    * contain a link to the JIRA issue
    * check for contributor agreement
    * check for AUTHORS entry
    * contain a link to our process documentation
    """
    people = people or get_people_file()
    people = {user.lower(): values for user, values in people.items()}
    pr_author = pull_request["user"]["login"].lower()
    # does the user have a signed contributor agreement?
    has_signed_agreement = pr_author in people
    # is the user in the AUTHORS file?
    in_authors_file = False
    authors_entry = people.get(pr_author, {}).get("authors_entry", "")
    if authors_entry:
        authors_url = "https://raw.githubusercontent.com/{repo}/{branch}/AUTHORS".format(
            repo=pull_request["head"]["repo"]["full_name"], branch=pull_request["head"]["ref"],
        )
        authors_resp = github.get(authors_url)
        if authors_resp.ok:
            authors_content = authors_resp.text
            if authors_entry in authors_content:
                in_authors_file = True

    doc_url = "http://edx.readthedocs.org/projects/userdocs/en/latest/process/overview.html"
    issue_key = jira_issue["key"]
    issue_url = "https://openedx.atlassian.net/browse/{key}".format(key=issue_key)
    contributing_url = "https://github.com/edx/edx-platform/blob/master/CONTRIBUTING.rst"
    agreement_url = "http://code.edx.org/individual-contributor-agreement.pdf"
    authors_url = "https://github.com/edx/edx-platform/blob/master/AUTHORS"
    comment = (
        "Thanks for the pull request, @{user}! I've created "
        "[{issue_key}]({issue_url}) to keep track of it in JIRA. "
        "JIRA is a place for product owners to prioritize feature reviews "
        "by the engineering development teams. Supporting information that is "
        "good to add there is anything that can help Product understand the "
        "context for the PR - supporting documentation, edx-code email threads, "
        "timeline information ('this must be merged by XX date', and why that is), "
        "partner information (this is for a course on edx.org, for example), etc. "
        "\n\nAll technical communication about the code itself will still be "
        "done via the Github pull request interface. "
        "As a reminder, [our process documentation is here]({doc_url})."
    ).format(
        user=pull_request["user"]["login"],
        issue_key=issue_key, issue_url=issue_url, doc_url=doc_url,
    )
    if not has_signed_agreement or not in_authors_file:
        todo = ""
        if not has_signed_agreement:
            todo += (
                "submitted a [signed contributor agreement]({agreement_url}) "
                "or indicated your institutional affiliation"
            ).format(
                agreement_url=agreement_url,
            )
        if not has_signed_agreement and not in_authors_file:
            todo += " and "
        if not in_authors_file:
            todo += "added yourself to the [AUTHORS]({authors_url}) file".format(
                authors_url=authors_url,
            )
        comment += ("\n\n"
            "We can't start reviewing your pull request until you've {todo}. "
            "Please see the [CONTRIBUTING]({contributing_url}) file for "
            "more information."
        ).format(todo=todo, contributing_url=contributing_url)
    return comment
예제 #50
0
def jira_issue_updated():
    """
    Received an "issue updated" event from JIRA. See `JIRA's webhook docs`_.

    .. _JIRA's webhook docs: https://developer.atlassian.com/display/JIRADEV/JIRA+Webhooks+Overview
    """
    try:
        event = request.get_json()
    except ValueError:
        raise ValueError("Invalid JSON from JIRA: {data}".format(
            data=request.data.decode('utf-8')
        ))
    bugsnag_context = {"event": event}
    bugsnag.configure_request(meta_data=bugsnag_context)

    if app.debug:
        print(json.dumps(event), file=sys.stderr)

    if "issue" not in event:
        # It's rare, but we occasionally see junk data from JIRA. For example,
        # here's a real API request we've received on this handler:
        #   {"baseUrl": "https://openedx.atlassian.net",
        #    "key": "jira:1fec1026-b232-438f-adab-13b301059297",
        #    "newVersion": 64005, "oldVersion": 64003}
        # If we don't have an "issue" key, it's junk.
        return "What is this shit!?", 400

    # is this a comment?
    comment = event.get("comment")
    if comment:
        return jira_issue_comment_added(event["issue"], comment, bugsnag_context)

    # is the issue an open source pull request?
    if event["issue"]["fields"]["project"]["key"] != "OSPR":
        return "I don't care"

    # we don't care about OSPR subtasks
    if event["issue"]["fields"]["issuetype"]["subtask"]:
        return "ignoring subtasks"

    # don't care about feature proposals
    if event["issue"]["fields"]["issuetype"]["name"] == "Feature Proposal":
        return "ignoring feature propsals"

    # is there a changelog?
    changelog = event.get("changelog")
    if not changelog:
        # it was just someone adding a comment
        return "I don't care"

    # did the issue change status?
    status_changelog_items = [item for item in changelog["items"] if item["field"] == "status"]
    if len(status_changelog_items) == 0:
        return "I don't care"

    pr_repo = github_pr_repo(event["issue"])
    if not pr_repo:
        issue_key = to_unicode(event["issue"]["key"])
        fail_msg = '{key} is missing "Repo" field'.format(key=issue_key)
        fail_msg += ' {0}'.format(event["issue"]["fields"]["issuetype"])
        raise Exception(fail_msg)
    repo_labels_resp = github.get("/repos/{repo}/labels".format(repo=pr_repo))
    if not repo_labels_resp.ok:
        raise requests.exceptions.RequestException(repo_labels_resp.text)
    # map of label name to label URL
    repo_labels = {l["name"]: l["url"] for l in repo_labels_resp.json()}
    # map of label name lowercased to label name in the case that it is on Github
    repo_labels_lower = {name.lower(): name for name in repo_labels}

    old_status = status_changelog_items[0]["fromString"]
    new_status = status_changelog_items[0]["toString"]

    changes = []
    if new_status == "Rejected":
        change = jira_issue_rejected(event["issue"], bugsnag_context)
        changes.append(change)

    elif 'blocked' in new_status.lower():
        print("New status is: {}".format(new_status))
        print("repo_labels_lower: {}".format(repo_labels_lower))

    if new_status.lower() in repo_labels_lower:
        change = jira_issue_status_changed(event["issue"], event["changelog"], bugsnag_context)
        changes.append(change)

    if changes:
        return "\n".join(changes)
    else:
        return "no change necessary"
예제 #51
0
 def index():
     if not github.authorized:
         return redirect(url_for("github.login"))
     resp = github.get("/user")
     assert resp.ok
     return "You are @{login} on GitHub".format(login=resp.json()["login"])