Skip to content

Commit 857ad0a

Browse files
committed
josegonzalez#123: Support Authenticating As Github Application
1 parent 3f65ead commit 857ad0a

File tree

2 files changed

+35
-11
lines changed

2 files changed

+35
-11
lines changed

bin/github-backup

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,12 @@ def main():
2626
if args.lfs_clone:
2727
check_git_lfs_install()
2828

29-
log_info('Backing up user {0} to {1}'.format(args.user, output_directory))
29+
if not args.as_app:
30+
log_info('Backing up user {0} to {1}'.format(args.user, output_directory))
31+
authenticated_user = get_authenticated_user(args)
32+
else:
33+
authenticated_user = {'login': None}
3034

31-
authenticated_user = get_authenticated_user(args)
3235
repositories = retrieve_repositories(args, authenticated_user)
3336
repositories = filter_repositories(args, repositories)
3437
backup_repositories(args, output_directory, repositories)

github_backup/github_backup.py

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,16 @@ def parse_args():
168168
parser.add_argument('-t',
169169
'--token',
170170
dest='token',
171-
help='personal access or OAuth token, or path to token (file://...)') # noqa
171+
help='personal access, OAuth, or JSON Web token, or path to token (file://...)') # noqa
172+
parser.add_argument('--as-app',
173+
action='store_true',
174+
dest='as_app',
175+
help='authenticate as github app instead of as a user. '
176+
'Using this option will probably break the following options: '
177+
'starred, all-starred, watched, gists, starred-gists, '
178+
'followers, following. '
179+
'Other options may be affected. '
180+
'User account information will not be backed up.')
172181
parser.add_argument('-o',
173182
'--output-directory',
174183
default='.',
@@ -325,7 +334,7 @@ def parse_args():
325334
return parser.parse_args()
326335

327336

328-
def get_auth(args, encode=True):
337+
def get_auth(args, encode=True, for_git_cli=False):
329338
auth = None
330339

331340
if args.osx_keychain_item_name:
@@ -353,7 +362,13 @@ def get_auth(args, encode=True):
353362
if args.token.startswith(_path_specifier):
354363
args.token = open(args.token[len(_path_specifier):],
355364
'rt').readline().strip()
356-
auth = args.token + ':' + 'x-oauth-basic'
365+
if not args.as_app:
366+
auth = args.token + ':' + 'x-oauth-basic'
367+
else:
368+
if not for_git_cli:
369+
auth = args.token
370+
else:
371+
auth = 'x-access-token:' + args.token
357372
elif args.username:
358373
if not args.password:
359374
args.password = getpass.getpass()
@@ -399,7 +414,7 @@ def get_github_repo_url(args, repository):
399414
if args.prefer_ssh:
400415
return repository['ssh_url']
401416

402-
auth = get_auth(args, False)
417+
auth = get_auth(args, encode=False, for_git_cli=True)
403418
if auth and repository['private'] == True:
404419
repo_url = 'https://{0}@{1}/{2}/{3}.git'.format(
405420
auth,
@@ -413,14 +428,14 @@ def get_github_repo_url(args, repository):
413428

414429

415430
def retrieve_data_gen(args, template, query_args=None, single_request=False):
416-
auth = get_auth(args)
431+
auth = get_auth(args, encode=not args.as_app)
417432
query_args = get_query_args(query_args)
418433
per_page = 100
419434
page = 0
420435

421436
while True:
422437
page = page + 1
423-
request = _construct_request(per_page, page, query_args, template, auth) # noqa
438+
request = _construct_request(per_page, page, query_args, template, auth, as_app=args.as_app) # noqa
424439
r, errors = _get_response(request, auth, template)
425440

426441
status_code = int(r.getcode())
@@ -430,7 +445,7 @@ def retrieve_data_gen(args, template, query_args=None, single_request=False):
430445
print('API request returned HTTP 502: Bad Gateway. Retrying in 5 seconds')
431446
retries += 1
432447
time.sleep(5)
433-
request = _construct_request(per_page, page, query_args, template, auth) # noqa
448+
request = _construct_request(per_page, page, query_args, template, auth, as_app=args.as_app) # noqa
434449
r, errors = _get_response(request, auth, template)
435450

436451
status_code = int(r.getcode())
@@ -495,15 +510,21 @@ def _get_response(request, auth, template):
495510
return r, errors
496511

497512

498-
def _construct_request(per_page, page, query_args, template, auth):
513+
def _construct_request(per_page, page, query_args, template, auth, as_app=None):
499514
querystring = urlencode(dict(list({
500515
'per_page': per_page,
501516
'page': page
502517
}.items()) + list(query_args.items())))
503518

504519
request = Request(template + '?' + querystring)
505520
if auth is not None:
506-
request.add_header('Authorization', 'Basic '.encode('ascii') + auth)
521+
if not as_app:
522+
request.add_header('Authorization', 'Basic '.encode('ascii') + auth)
523+
else:
524+
if not PY2:
525+
auth = auth.encode('ascii')
526+
request.add_header('Authorization', 'token '.encode('ascii') + auth)
527+
request.add_header('Accept', 'application/vnd.github.machine-man-preview+json')
507528
log_info('Requesting {}?{}'.format(template, querystring))
508529
return request
509530

0 commit comments

Comments
 (0)