Skip to content

Commit

Permalink
Merge pull request #288 from kmyk/issue/200
Browse files Browse the repository at this point in the history
#200 add --check option to login command
  • Loading branch information
fukatani authored Feb 3, 2019
2 parents e7944f4 + be98673 commit e4c092f
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 14 deletions.
4 changes: 2 additions & 2 deletions LOGIN_WITH_COOKIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ Please replace current `REVEL_SESSION` value to value which you copied by the br
5. Confirm logged in.

``` console
$ oj login https://yukicoder.me/
$ oj login --check https://yukicoder.me/
[x] service recognized: <onlinejudge.service.yukicoder.YukicoderService object at 0x7f4467a0a2b0>: https://yukicoder.me/
[x] load cookie from: ~/.local/share/online-judge-tools/cookie.jar
[x] GET: https://yukicoder.me/auth/github
[x] 200 OK
[x] 302 Found
[*] You have already signed in.
[x] save cookie to: ~/.local/share/online-judge-tools/cookie.jar
```
Expand Down
33 changes: 21 additions & 12 deletions onlinejudge/implementation/command/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,25 @@ def login(args: 'argparse.Namespace') -> None:
log.failure('login for %s: invalid option: --method %s', service.get_name(), args.method)
sys.exit(1)

# login
def get_credentials() -> Tuple[str, str]:
if args.username is None:
args.username = input('Username: ')
if args.password is None:
args.password = getpass.getpass()
return args.username, args.password

log.warning('If you don\'t want to give your password to this program, you can give only your session tokens.')
log.info('see: https://github.com/kmyk/online-judge-tools/blob/master/LOGIN_WITH_COOKIES.md')

with utils.with_cookiejar(utils.new_default_session(), path=args.cookie) as sess:
service.login(get_credentials, session=sess, **kwargs) # type: ignore

if args.check:
if service.is_logged_in(session=sess):
log.info('You have already signed in.')
else:
log.info('You are not signed in.')
sys.exit(1)

else:
# login
def get_credentials() -> Tuple[str, str]:
if args.username is None:
args.username = input('Username: ')
if args.password is None:
args.password = getpass.getpass()
return args.username, args.password

log.warning('If you don\'t want to give your password to this program, you can give only your session tokens.')
log.info('see: https://github.com/kmyk/online-judge-tools/blob/master/LOGIN_WITH_COOKIES.md')

service.login(get_credentials, session=sess, **kwargs) # type: ignore
1 change: 1 addition & 0 deletions onlinejudge/implementation/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def get_parser() -> argparse.ArgumentParser:
subparser.add_argument('url')
subparser.add_argument('-u', '--username')
subparser.add_argument('-p', '--password')
subparser.add_argument('--check', action='store_true', help='check whether you are logged in or not')
subparser.add_argument('--method')

# submit
Expand Down
7 changes: 7 additions & 0 deletions onlinejudge/service/atcoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ def login(self, get_credentials: onlinejudge.type.CredentialsProvider, session:
AtCoderService._report_messages(msgs)
return 'login' not in resp.url # AtCoder redirects to the top page if success

def is_logged_in(self, session: Optional[requests.Session] = None) -> bool:
session = session or utils.new_default_session()
url = 'https://practice.contest.atcoder.jp/login'
resp = _request('GET', url, session=session, allow_redirects=False)
msgs = AtCoderService._get_messages_from_cookie(resp.cookies)
return bool(msgs)

def get_url(self) -> str:
return 'https://atcoder.jp/'

Expand Down
6 changes: 6 additions & 0 deletions onlinejudge/service/codeforces.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ def login(self, get_credentials: onlinejudge.type.CredentialsProvider, session:
log.failure('Invalid handle or password.')
return False

def is_logged_in(self, session: Optional[requests.Session] = None) -> bool:
session = session or utils.new_default_session()
url = 'https://codeforces.com/enter'
resp = utils.request('GET', url, session=session, allow_redirects=False)
return resp.status_code == 302

def get_url(self) -> str:
return 'https://codeforces.com/'

Expand Down
7 changes: 7 additions & 0 deletions onlinejudge/service/yukicoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,13 @@ def login_with_twitter(self, get_credentials: onlinejudge.type.CredentialsProvid
url = 'https://yukicoder.me/auth/twitter'
raise NotImplementedError

def is_logged_in(self, session: Optional[requests.Session] = None, method: Optional[str] = None) -> bool:
session = session or utils.new_default_session()
url = 'https://yukicoder.me/auth/github'
resp = utils.request('GET', url, session=session, allow_redirects=False)
assert resp.status_code == 302
return 'oauth' not in resp.headers['Location']

def get_url(self) -> str:
return 'https://yukicoder.me/'

Expand Down
3 changes: 3 additions & 0 deletions onlinejudge/type.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ class Service(object):
def login(self, get_credentials: CredentialsProvider, session: Optional['requests.Session'] = None) -> bool:
raise NotImplementedError

def is_logged_in(self, session: Optional['requests.Session'] = None) -> bool:
raise NotImplementedError

def get_url(self) -> str:
raise NotImplementedError

Expand Down
42 changes: 42 additions & 0 deletions tests/command_login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import os
import subprocess
import sys
import time
import unittest

import tests.utils


class LoginTest(unittest.TestCase):
def snippet_call_login_check_failure(self, url):
ojtools = os.path.abspath('oj')
with tests.utils.sandbox(files=[]) as tempdir:
env = dict(**os.environ)
env['HOME'] = tempdir
self.assertRaises
proc = subprocess.run([ojtools, 'login', '--check', url], env=env, stdout=sys.stdout, stderr=sys.stderr)
self.assertEqual(proc.returncode, 1)

def test_call_login_check_atcoder_failure(self):
self.snippet_call_login_check_failure('https://atcoder.jp/')

def test_call_login_check_codeforces_failure(self):
self.snippet_call_login_check_failure('https://codeforces.com/')

def test_call_login_check_yukicoder_failure(self):
self.snippet_call_login_check_failure('https://yukicoder.me/')

@unittest.skipIf('CI' in os.environ, 'login is required')
def test_call_login_check_atcoder_success(self):
ojtools = os.path.abspath('oj')
subprocess.check_call([ojtools, 'login', '--check', 'https://atcoder.jp/'], stdout=sys.stdout, stderr=sys.stderr)

@unittest.skipIf('CI' in os.environ, 'login is required')
def test_call_login_check_codeforces_success(self):
ojtools = os.path.abspath('oj')
subprocess.check_call([ojtools, 'login', '--check', 'https://codeforces.com/'], stdout=sys.stdout, stderr=sys.stderr)

@unittest.skipIf('CI' in os.environ, 'login is required')
def test_call_login_check_yukicoder_success(self):
ojtools = os.path.abspath('oj')
subprocess.check_call([ojtools, 'login', '--check', 'https://yukicoder.me/'], stdout=sys.stdout, stderr=sys.stderr)

0 comments on commit e4c092f

Please sign in to comment.