Пример #1
0
    def validate(self, attrs):
        code = attrs.get('code')
        state = attrs.get('state')

        user = None

        if not CLIENT_ID or not CLIENT_SECRET:
            msg = 'Lifebelt not configurated properly. Please contact administrators'
            raise exceptions.ValidationError(msg)

        if code and state:
            headers = {'Accept': 'application/json'}
            data = {"client_id": CLIENT_ID, "client_secret": CLIENT_SECRET, "code": code, "state": state}
            url = 'https://github.com/login/oauth/access_token'

            r = requests.post(url=url, headers=headers, data=data)

            if 'access_token' not in r.json():
                msg = 'This smells...'

                if 'error' in r.json():
                    msg = r.json()['error']

                raise exceptions.ValidationError(msg)

            token = r.json()['access_token']

            # https://github3py.readthedocs.org/en/master/
            gh = GitHub(token=token)

            user = Member.objects.get(github_id=gh.me().id)

            if not user:
                msg = 'User with this GitHub name is not found'
                raise exceptions.ValidationError(msg)

            user.avatar_url = gh.me().as_dict().get('avatar_url')
            user.github_token = token
            user.save()
        else:
            msg = ('You must provide a valid email and a special code to authenticate')
            raise exceptions.ValidationError(msg)

        attrs['user'] = user.user
        return attrs
Пример #2
0
def one_repo_only(owner, reponame, gh_token=''):
    """
    Go back and see why this or that denied request. Provide a valid token.
    """
    gh = GitHub(token=gh_token)
    user = gh.me()
    body = ISSUE_BODY.format(user)
    repo = gh.repository(owner, reponame)
    i = repo.create_issue(ISSUE_TITLE, body=body)
    print(i)
Пример #3
0
def one_repo_only(owner, reponame, gh_token=''):
    """
    Go back and see why this or that denied request. Provide a valid token.
    """
    gh = GitHub(token=gh_token)
    user = gh.me()
    body = ISSUE_BODY.format(user)
    repo = gh.repository(owner, reponame)
    i = repo.create_issue(ISSUE_TITLE, body=body)
    print(i)
Пример #4
0
def go_forth_and_multiply(owner, listfile, gh_token=''):
    """
    Open issues! Provide a valid token.
    """
    gh = GitHub(token=gh_token)
    user = gh.me()
    body = ISSUE_BODY.format(user)

    # Only allowed to spam pre-approved list now.
    with open(listfile) as fin:
        repositories = [
            s.strip() for s in fin.readlines() if not s.startswith('#')
        ]

    tot_n = len(repositories)

    if tot_n == 0:
        print('No repository to process!')
        return

    max_n_per_chunk = 30
    n_chunks = math.ceil(tot_n / max_n_per_chunk)
    i_chunk = 0

    while i_chunk < n_chunks:
        i_start = i_chunk * max_n_per_chunk
        i_end = min(i_start + max_n_per_chunk, tot_n)

        for reponame in repositories[i_start:i_end]:
            time.sleep(0.5)  # Prevent API limit but not abuse detection
            repo = gh.repository(owner, reponame)
            if repo.archived:
                print('Skipped {0} -- archived'.format(repo.name))
                continue
            try:
                i = repo.create_issue('Update the help', body=body)
            except Exception as e:  # denied!
                print('Skipped {0} -- {1}'.format(repo.name, str(e)))
            else:
                print(i)

        i_chunk += 1
        if i_chunk < n_chunks:
            time.sleep(10)  # Prevent abuse detection, maybe
Пример #5
0
def go_forth_and_multiply(owner, listfile, gh_token=''):
    """
    Open issues! Provide a valid token.
    """
    gh = GitHub(token=gh_token)
    user = gh.me()
    body = ISSUE_BODY.format(user)

    # Only allowed to spam pre-approved list now.
    with open(listfile) as fin:
        repositories = [s.strip() for s in fin.readlines()
                        if not s.startswith('#')]

    tot_n = len(repositories)

    if tot_n == 0:
        print('No repository to process!')
        return

    max_n_per_chunk = 30
    n_chunks = math.ceil(tot_n / max_n_per_chunk)
    i_chunk = 0

    while i_chunk < n_chunks:
        i_start = i_chunk * max_n_per_chunk
        i_end = min(i_start + max_n_per_chunk, tot_n)

        for reponame in repositories[i_start:i_end]:
            time.sleep(0.5)  # Prevent API limit but not abuse detection
            repo = gh.repository(owner, reponame)
            if repo.archived:
                print('Skipped {0} -- archived'.format(repo.name))
                continue
            try:
                i = repo.create_issue('Update the help', body=body)
            except Exception as e:  # denied!
                print('Skipped {0} -- {1}'.format(repo.name, str(e)))
            else:
                print(i)

        i_chunk += 1
        if i_chunk < n_chunks:
            time.sleep(10)  # Prevent abuse detection, maybe
Пример #6
0
import re
import tempfile
import subprocess

try:
    from github3 import GitHub
except ImportError:
    raise ImportError('Please conda or pip install github3.py')

BRANCH = 'add_code_of_conduct'
CODE_OF_CONDUCT_REPO = ('spacetelescope', 'stsci-package-template')
CODE_OF_CONDUCT_FILENAME = 'CODE_OF_CONDUCT.md'

GITHUB_API_HOST = 'api.github.com'
gh = GitHub(token='')  # NOTE: Insert a valid token
user = gh.me()

PR_MESSAGE_BODY = re.sub('(\S+)\n', r'\1 ', """
This is an automated addition of spacetelescope code of conduct that is
copied from https://github.com/{0}/{1}/.


*If this is opened in error, please let {2} know!*
""").strip()

# Get CoC content from template
_r = gh.repository(*CODE_OF_CONDUCT_REPO)
_c = _r.file_contents(CODE_OF_CONDUCT_FILENAME).decoded.decode('utf-8')


def run_command(command):
Пример #7
0
#!/usr/bin/env python

import os
from github3 import GitHub
from flask.json import jsonify
from requests_oauthlib import OAuth2Session
from diggit import Digger
from flask import Flask, request, redirect, session, url_for

GH = GitHub()
GH.login(token=os.environ.get('GITHUB_ACCESS_TOKEN'))
user_gh_profile = GH.me()
gh_scraper = Digger(GH)
# GH.ratelimit_remaining
app = Flask(__name__)

@app.route("/")
def home():
    return redirect(url_for('profile'))

@app.route("/profile", methods=["GET"])
def profile():
    """
    """
    return jsonify(user_gh_profile.as_dict())

@app.route("/search/", methods=["GET"])
@app.route("/search/<type>", methods=["GET"])
def scanner(type="user"):
    return jsonify(gh_scraper.get_class())
Пример #8
0
class WsgiApplication(github.GitHub):  # pylint:disable=too-many-instance-attributes
    _URLS = routing.Map((
        routing.Rule('/', endpoint='index'),
        routing.Rule('/<repository_name>/', endpoint='repository'),
        routing.Rule('/<repository_name>/release/<release_name>.tar.gz',
                     endpoint='download'),
    ))

    _cache = None  # type: FileSystemCache
    _users_and_organizations = None  # type: (github.Organization | github.User, ...)
    _index_template = None  # type: str
    _repository_template = None  # type: str
    _auth = None  # type: dict[str]
    _request_domain = None  # type: str
    _request_urls = None  # type: routing.MapAdapter

    @property
    def repositories(self):
        """
        :rtype: dict[str, repos.ShortRepository]
        """
        value = self._cache.get(CACHE_KEY)

        if value is None:
            data = self.get_installable_repositories(
                *self._users_and_organizations)
            value = {key: repo._json_data for key, repo in data.items()}  # pylint:disable=protected-access
            self._cache.set(CACHE_KEY, value)
            return data

        return {
            key: repos.ShortRepository(json, self.github_api.session)
            for key, json in value.items()
        }

    # noinspection PyTypeChecker
    def __init__(
        self,
        *users_and_organizations,
        cache_dir,  # Should be an absolute path!
        index_template=None,
        repository_template=None,
    ) -> None:
        """
        :type users_and_organizations: (github.Organization | github.User, ...)
        :type index_template: str
        :type repository_template: str
        :rtype: None
        """
        self._cache = FileSystemCache(cache_dir=cache_dir, default_timeout=900)
        self._users_and_organizations = users_and_organizations
        self._index_template = index_template or templates.INDEX
        self._repository_template = repository_template or templates.REPOSITORY
        self._auth = None
        self._request_domain = None
        self._request_urls = None
        self.current_user = None
        self.github_api = None

    def __call__(self, environ, start_response):
        """
        :type environ: dict
        :type start_response: werkzeug.serving.WSGIRequestHandler.start_response
        :rtype: werkzeug.wsgi.ClosingIterator
        """
        request = wrappers.Request(environ)

        if b'purge_cache' in request.query_string:
            self._cache.delete(CACHE_KEY)

        try:
            self._get_authorization(request)
            self._authorize_github()
            self._request_domain = self._get_request_domain(request)

            self._request_urls = self._URLS.bind_to_environ(request.environ)
            endpoint, values = self._request_urls.match()

            func_name = 'dispatch_{}'.format(endpoint)
            response = (getattr(self, func_name)(request, **values) if hasattr(
                self, func_name) else exceptions.NotFound())
        except exceptions.HTTPException as ex:
            response = ex

        return response(environ, start_response)

    def _get_authorization(self, request):
        """
        :type request: werkzeug.wrappers.request.Request
        :rtype: dict[str]
        :raises werkzeug.exceptions.Unauthorized: If authorization information not available in `request`
        """
        auth = request.authorization or {}
        username = auth.get('username', '').strip()
        password = auth.get('password', '').strip()
        if not username:
            raise exceptions.Unauthorized(
                www_authenticate='Basic realm="Simple index"')

        self._auth = {
            'username': username,
            'password': password
        } if username and password else {
            'token': username
        }

    def _authorize_github(self):
        """
        :rtype: None
        :raises werkzeug.exceptions.Forbidden: If cannot login to GitHub using `auth` credentials
        """
        self.github_api = GitHubApi(**self._auth)
        try:
            self.current_user = self.github_api.me()
        except gh_exc.AuthenticationFailed:
            raise exceptions.Forbidden()
        if self.current_user is None:
            raise exceptions.Forbidden()

    def _get_request_domain(self, request):
        """
        :type request: werkzeug.wrappers.request.Request
        :rtype: str
        """
        base_url = parse.urlsplit(request.base_url)  # type: parse.SplitResult
        netloc = ('{scheme}://{token}@{domain}' if 'token' in self._auth else
                  '{scheme}://{username}:{password}@{domain}')

        format_dict = {'domain': base_url.netloc.split('@')[-1].rstrip('/')}
        format_dict.update(self._auth)
        format_dict.update(base_url._asdict())

        return netloc.format(**format_dict)

    # Endpoints

    def dispatch_download(self, request, repository_name, release_name):  # pylint:disable=unused-argument
        repo_releases = self._get_releases(repository_name)
        if not repo_releases:
            raise exceptions.NotFound()

        wanted_release = repo_releases[release_name]  # type: release.Release
        asset_url = self._find_release_download_link(
            wanted_release)  # type: str

        with requests.get(asset_url,
                          headers={'Accept': 'application/octet-stream'},
                          stream=True) as tarball:
            if tarball.status_code != HTTPStatus.OK:
                raise exceptions.NotFound()

            stream = ResponseStream(tarball.iter_content(1024))
            return wrappers.Response(stream.read(),
                                     direct_passthrough=True,
                                     mimetype='application/x-compressed')

    def dispatch_index(self, request):  # pylint:disable=unused-argument
        """
        :type request: werkzeug.wrappers.request.Request
        :rtype: werkzeug.wrappers.response.Response
        """
        return wrappers.Response(
            self._index_template % {
                'links':
                '\n'.join(
                    '<a href="%(domain)s%(endpoint)s">%(name)s</a>' % {
                        'domain':
                        self._request_domain,
                        'endpoint':
                        self._request_urls.build(
                            'repository', {'repository_name': repo_name}),
                        'name':
                        repo.full_name,
                    } for repo_name, repo in self.repositories.items()),
            },
            mimetype='text/html',
        )

    def dispatch_repository(self, request, repository_name):  # pylint:disable=unused-argument
        """
        :type request: werkzeug.wrappers.request.Request
        :type repository_name: str
        :rtype: werkzeug.wrappers.response.Response
        :raises werkzeug.exceptions.NotFound: If `repository_name` not found on GitHub
        """
        releases = self._get_repo_releases_links(repository_name)
        return wrappers.Response(
            self._repository_template % {
                'repository_name':
                repository_name,
                'links':
                '\n'.join('<a href="%(url)s">%(tag_name)s</a>' % item
                          for item in releases),
            },
            mimetype='text/html',
        )

    # Helpers

    def _get_repo_releases_links(self, repository_name):
        """
        :type repository_name: str
        :rtype: (dict[str, str], ...) | None
        """
        repo_releases = self._get_releases(repository_name)
        if not repo_releases:
            return None

        return tuple({
            'url': '%(domain)s%(endpoint)s' % {
                'domain':
                self._request_domain,
                'endpoint':
                self._request_urls.build('download', {
                    'repository_name': repository_name,
                    'release_name': tag_name
                }),
            },
            'tag_name': tag_name
        } for tag_name in repo_releases.keys())

    def _get_releases(self, repository_name):
        """
        :type repository_name: str
        :rtype: dict[str, release.Release] | None
        """
        repositories_with_aliases = {}
        for key, value in self.repositories.items():
            repositories_with_aliases[key] = value
            repositories_with_aliases[key.replace('_', '-')] = value

        try:
            repository = repositories_with_aliases[
                repository_name]  # type: repos.ShortRepository
        except KeyError:
            raise exceptions.NotFound()

        repo_releases = collections.OrderedDict(
            (item.tag_name, item)
            for item in sorted(repository.releases(),
                               key=lambda item: item.created_at))
        return repo_releases or None

    def _find_release_download_link(self, release_instance):
        """
        :type: release.Release
        :rtype: str
        :raises werkzeug.exceptions.NotFound:
        """
        asset_url = None
        for asset in release_instance.assets():  # type: release_instance.Asset
            if asset.name == ASSET_FILENAME:
                asset_url = '{download_url}?access_token={access_token}'.format(
                    download_url=asset.download_url,
                    access_token=self._auth.get('token',
                                                self._auth.get('password')),
                )
                break

        if not asset_url:
            raise exceptions.NotFound(
                'Asset "{}" not found in release "{}"'.format(
                    ASSET_FILENAME, release_instance.name))
        return asset_url