forked from DGNum/uptime-kuma-api
implement 2FA login
This commit is contained in:
parent
59181ddba2
commit
512057ab61
3 changed files with 62 additions and 5 deletions
1
tests/requirements.txt
Normal file
1
tests/requirements.txt
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pyotp==2.6.0
|
56
tests/test_2fa.py
Normal file
56
tests/test_2fa.py
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
import unittest
|
||||||
|
from urllib import parse
|
||||||
|
|
||||||
|
import pyotp
|
||||||
|
|
||||||
|
from uptime_kuma_test_case import UptimeKumaTestCase
|
||||||
|
|
||||||
|
|
||||||
|
def parse_secret(uri):
|
||||||
|
query = parse.urlsplit(uri).query
|
||||||
|
params = dict(parse.parse_qsl(query))
|
||||||
|
return params["secret"]
|
||||||
|
|
||||||
|
|
||||||
|
def generate_token(secret):
|
||||||
|
totp = pyotp.TOTP(secret)
|
||||||
|
return totp.now()
|
||||||
|
|
||||||
|
|
||||||
|
class Test2FA(UptimeKumaTestCase):
|
||||||
|
def test_2fa(self):
|
||||||
|
# check 2fa is disabled
|
||||||
|
r = self.api.twofa_status()
|
||||||
|
self.assertEqual(r["status"], False)
|
||||||
|
|
||||||
|
# prepare 2fa
|
||||||
|
r = self.api.prepare_2fa(self.password)
|
||||||
|
uri = r["uri"]
|
||||||
|
self.assertTrue(uri.startswith("otpauth://totp/"))
|
||||||
|
secret = parse_secret(uri)
|
||||||
|
|
||||||
|
# verify token
|
||||||
|
token = generate_token(secret)
|
||||||
|
r = self.api.verify_token(token, self.password)
|
||||||
|
self.assertEqual(r["valid"], True)
|
||||||
|
|
||||||
|
# save 2fa
|
||||||
|
r = self.api.save_2fa(self.password)
|
||||||
|
self.assertEqual(r["msg"], "2FA Enabled.")
|
||||||
|
|
||||||
|
# check 2fa is enabled
|
||||||
|
r = self.api.twofa_status()
|
||||||
|
self.assertEqual(r["status"], True)
|
||||||
|
|
||||||
|
# relogin using the totp token
|
||||||
|
self.api.logout()
|
||||||
|
token = generate_token(secret)
|
||||||
|
self.api.login(self.username, self.password, token)
|
||||||
|
|
||||||
|
# disable 2fa
|
||||||
|
r = self.api.disable_2fa(self.password)
|
||||||
|
self.assertEqual(r["msg"], "2FA Disabled.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
|
@ -801,6 +801,9 @@ class UptimeKumaApi(object):
|
||||||
def prepare_2fa(self, password: str):
|
def prepare_2fa(self, password: str):
|
||||||
return self._call('prepare2FA', password)
|
return self._call('prepare2FA', password)
|
||||||
|
|
||||||
|
def verify_token(self, token: str, password: str):
|
||||||
|
return self._call('verifyToken', (token, password))
|
||||||
|
|
||||||
def save_2fa(self, password: str):
|
def save_2fa(self, password: str):
|
||||||
return self._call('save2FA', password)
|
return self._call('save2FA', password)
|
||||||
|
|
||||||
|
@ -809,19 +812,16 @@ class UptimeKumaApi(object):
|
||||||
|
|
||||||
# login
|
# login
|
||||||
|
|
||||||
def login(self, username: str, password: str):
|
def login(self, username: str, password: str, twofa_token: str = ""):
|
||||||
return self._call('login', {
|
return self._call('login', {
|
||||||
"username": username,
|
"username": username,
|
||||||
"password": password,
|
"password": password,
|
||||||
"token": ""
|
"token": twofa_token
|
||||||
})
|
})
|
||||||
|
|
||||||
def login_by_token(self, token: str):
|
def login_by_token(self, token: str):
|
||||||
return self._call('loginByToken', token)
|
return self._call('loginByToken', token)
|
||||||
|
|
||||||
def verify_token(self, token: str, password: str):
|
|
||||||
return self._call('verifyToken', (token, password))
|
|
||||||
|
|
||||||
def logout(self):
|
def logout(self):
|
||||||
return self._call('logout')
|
return self._call('logout')
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue