pyauthenticator 0.2.1__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ *.pyd
6
+
7
+ # Coverage reports
8
+ .coverage
9
+ .coverage.*
10
+ htmlcov/
11
+
12
+ # Test artifacts
13
+ *.png
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyauthenticator
3
- Version: 0.2.1
3
+ Version: 0.3.0
4
4
  Summary: Similar to the Google authenticator just written in python.
5
5
  Project-URL: Homepage, https://github.com/jan-janssen/pyauthenticator
6
6
  Project-URL: Documentation, https://github.com/jan-janssen/pyauthenticator/blob/master/README.md
@@ -32,7 +32,7 @@ Requires-Dist: qrcode>=8.2
32
32
  Description-Content-Type: text/markdown
33
33
 
34
34
  # pyauthenticator
35
- [![Python package](https://github.com/jan-janssen/pyauthenticator/actions/workflows/unittest.yml/badge.svg?branch=main)](https://github.com/jan-janssen/pyauthenticator/actions/workflows/unittest.yml)
35
+ [![Pipeline](https://github.com/jan-janssen/pyauthenticator/actions/workflows/pipeline.yml/badge.svg)](https://github.com/jan-janssen/pyauthenticator/actions/workflows/pipeline.yml)
36
36
  [![Coverage Status](https://coveralls.io/repos/github/jan-janssen/pyauthenticator/badge.svg?branch=main)](https://coveralls.io/github/jan-janssen/pyauthenticator?branch=main)
37
37
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
38
38
 
@@ -107,7 +107,7 @@ For any support requests feel free to open an [issue on Github](https://github.c
107
107
  # For Developers
108
108
  ## Python Interface
109
109
  The same functionality which is available on the command line is also available via the python interface:
110
- ```
110
+ ```python
111
111
  from pyauthenticator import get_two_factor_code
112
112
  get_two_factor_code(service)
113
113
  ```
@@ -117,10 +117,10 @@ factor authentication.
117
117
  ## Configuration
118
118
  The configuration is stored in `~/.pyauthenticator` it is written in the JSON format. For a given service like `github`
119
119
  the config file contains:
120
- ```
120
+ ```JSON
121
121
  {"google": "otpauth://totp/Google:<username>?secret=<secret>&issuer=Google"}
122
122
  ```
123
123
  With the Google username `<username>` and the corresponding secret `<secret>` being contained in the QR code.
124
124
 
125
125
  ## License
126
- The `pyauthenticator` package is licensed under the [BSD-3-Clause license](https://github.com/jan-janssen/pyauthenticator/blob/main/LICENSE).
126
+ The `pyauthenticator` package is licensed under the [BSD-3-Clause license](https://github.com/jan-janssen/pyauthenticator/blob/main/LICENSE).
@@ -1,5 +1,5 @@
1
1
  # pyauthenticator
2
- [![Python package](https://github.com/jan-janssen/pyauthenticator/actions/workflows/unittest.yml/badge.svg?branch=main)](https://github.com/jan-janssen/pyauthenticator/actions/workflows/unittest.yml)
2
+ [![Pipeline](https://github.com/jan-janssen/pyauthenticator/actions/workflows/pipeline.yml/badge.svg)](https://github.com/jan-janssen/pyauthenticator/actions/workflows/pipeline.yml)
3
3
  [![Coverage Status](https://coveralls.io/repos/github/jan-janssen/pyauthenticator/badge.svg?branch=main)](https://coveralls.io/github/jan-janssen/pyauthenticator?branch=main)
4
4
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
5
5
 
@@ -74,7 +74,7 @@ For any support requests feel free to open an [issue on Github](https://github.c
74
74
  # For Developers
75
75
  ## Python Interface
76
76
  The same functionality which is available on the command line is also available via the python interface:
77
- ```
77
+ ```python
78
78
  from pyauthenticator import get_two_factor_code
79
79
  get_two_factor_code(service)
80
80
  ```
@@ -84,10 +84,10 @@ factor authentication.
84
84
  ## Configuration
85
85
  The configuration is stored in `~/.pyauthenticator` it is written in the JSON format. For a given service like `github`
86
86
  the config file contains:
87
- ```
87
+ ```JSON
88
88
  {"google": "otpauth://totp/Google:<username>?secret=<secret>&issuer=Google"}
89
89
  ```
90
90
  With the Google username `<username>` and the corresponding secret `<secret>` being contained in the QR code.
91
91
 
92
92
  ## License
93
- The `pyauthenticator` package is licensed under the [BSD-3-Clause license](https://github.com/jan-janssen/pyauthenticator/blob/main/LICENSE).
93
+ The `pyauthenticator` package is licensed under the [BSD-3-Clause license](https://github.com/jan-janssen/pyauthenticator/blob/main/LICENSE).
@@ -50,26 +50,30 @@ Source = "https://github.com/jan-janssen/pyauthenticator"
50
50
  Tracker = "https://github.com/jan-janssen/pyauthenticator/issues"
51
51
 
52
52
  [project.scripts]
53
- pyauthenticator = "pyauthenticator.__main__:command_line_parser"
53
+ pyauthenticator = "pyauthenticator._cmd:command_line_parser"
54
54
 
55
55
  [tool.hatch.build]
56
56
  include = [
57
- "pyauthenticator"
57
+ "src/pyauthenticator"
58
58
  ]
59
59
 
60
60
  [tool.hatch.build.hooks.vcs]
61
- version-file = "pyauthenticator/_version.py"
61
+ version-file = "src/pyauthenticator/_version.py"
62
62
 
63
63
  [tool.hatch.build.targets.sdist]
64
64
  include = [
65
- "pyauthenticator"
65
+ "src/pyauthenticator"
66
66
  ]
67
67
 
68
68
  [tool.hatch.build.targets.wheel]
69
69
  packages = [
70
- "pyauthenticator"
70
+ "src/pyauthenticator"
71
71
  ]
72
72
 
73
73
  [tool.hatch.version]
74
74
  source = "vcs"
75
- path = "pyauthenticator/_version.py"
75
+ path = "src/pyauthenticator/_version.py"
76
+
77
+ [tool.coverage.run]
78
+ source = ["pyauthenticator"]
79
+ command_line = "-m unittest discover tests"
@@ -0,0 +1,19 @@
1
+ """
2
+ Generate two factor authentication codes on the command line
3
+ """
4
+
5
+ from . import _version
6
+ from pyauthenticator._user import (
7
+ write_qrcode_to_file,
8
+ get_two_factor_code,
9
+ add_two_factor_provider,
10
+ list_two_factor_providers,
11
+ )
12
+
13
+ __all__ = [
14
+ "write_qrcode_to_file",
15
+ "get_two_factor_code",
16
+ "add_two_factor_provider",
17
+ "list_two_factor_providers",
18
+ ]
19
+ __version__: str = _version.__version__
@@ -0,0 +1,9 @@
1
+ """
2
+ Generate two factor authentication codes on the command line
3
+ """
4
+
5
+ from pyauthenticator._cmd import command_line_parser
6
+
7
+
8
+ if __name__ == "__main__":
9
+ command_line_parser()
@@ -4,17 +4,18 @@ Generate two factor authentication codes on the command line
4
4
 
5
5
  import argparse
6
6
  import sys
7
+ from typing import Optional, Sequence
7
8
 
8
- from pyauthenticator.share import (
9
+ from pyauthenticator._config import load_config
10
+ from pyauthenticator.api import (
9
11
  add_service,
10
12
  generate_qrcode,
11
- get_two_factor_code,
13
+ get_totp_for_key_in_dict,
12
14
  list_services,
13
- load_config,
14
15
  )
15
16
 
16
17
 
17
- def command_line_parser(cmd_args=None):
18
+ def command_line_parser(cmd_args: Optional[Sequence[str]] = None) -> None:
18
19
  """
19
20
  Main function primarly used for the command line interface
20
21
  """
@@ -46,8 +47,14 @@ def command_line_parser(cmd_args=None):
46
47
  )
47
48
  args = parser.parse_args(args=cmd_args)
48
49
  if args.qrcode:
49
- generate_qrcode(key=args.service, config_dict=config_dict)
50
- print("The qrcode file <" + args.service + ".png> was generated.")
50
+ try:
51
+ generate_qrcode(key=args.service, config_dict=config_dict)
52
+ except KeyError:
53
+ _print_service_does_not_exists(
54
+ config_dict=config_dict, service=args.service
55
+ )
56
+ else:
57
+ print("The qrcode file <" + args.service + ".png> was generated.")
51
58
  elif args.add:
52
59
  add_service(
53
60
  key=args.service, qrcode_png_file_name=args.add, config_dict=config_dict
@@ -61,23 +68,25 @@ def command_line_parser(cmd_args=None):
61
68
  )
62
69
  else:
63
70
  try:
64
- print(get_two_factor_code(key=args.service, config_dict=config_dict))
65
- except ValueError:
66
- if len(config_dict) > 0:
67
- print(
68
- 'The service "'
69
- + args.service
70
- + '" does not exist.\n\nThe config file ~/.pyauthenticator contains the following services:'
71
- )
72
- for service in list_services(config_dict=config_dict):
73
- print(" * " + service)
74
- print("\nChoose one of these or add a new service using:")
75
- else:
76
- print(
77
- "The config file ~/.pyauthenticator does not contain any services. To add a new service use:"
78
- )
79
- print(" pyauthenticator --add <qr-code.png> <servicename>\n")
71
+ print(get_totp_for_key_in_dict(key=args.service, config_dict=config_dict))
72
+ except KeyError:
73
+ _print_service_does_not_exists(
74
+ config_dict=config_dict, service=args.service
75
+ )
80
76
 
81
77
 
82
- if __name__ == "__main__":
83
- command_line_parser()
78
+ def _print_service_does_not_exists(config_dict: dict, service: str) -> None:
79
+ if len(config_dict) > 0:
80
+ print(
81
+ 'The service "'
82
+ + service
83
+ + '" does not exist.\n\nThe config file ~/.pyauthenticator contains the following services:'
84
+ )
85
+ for service_in_config in list_services(config_dict=config_dict):
86
+ print(" * " + service_in_config)
87
+ print("\nChoose one of these or add a new service using:")
88
+ else:
89
+ print(
90
+ "The config file ~/.pyauthenticator does not contain any services. To add a new service use:"
91
+ )
92
+ print(" pyauthenticator --add <qr-code.png> <servicename>\n")
@@ -0,0 +1,42 @@
1
+ """
2
+ Configuration file handling for pyauthenticator
3
+ """
4
+
5
+ import json
6
+ from os.path import exists, abspath, expanduser
7
+ from typing import Any, Dict
8
+
9
+ # default configuration file
10
+ default_config_file: str = "~/.pyauthenticator"
11
+
12
+
13
+ def load_config(config_file_to_load: str = default_config_file) -> Dict[str, Any]:
14
+ """
15
+ Load configuration file
16
+
17
+ Args:
18
+ config_file_to_load (str): path to config file
19
+
20
+ Returns:
21
+ dict: Dictionary with service names as keys and the otpauth url as values
22
+ """
23
+ abs_config_path = abspath(expanduser(config_file_to_load))
24
+ if exists(abs_config_path):
25
+ with open(abs_config_path, "r") as f:
26
+ return json.load(f)
27
+ else:
28
+ return {}
29
+
30
+
31
+ def write_config(
32
+ config_dict: Dict[str, Any], config_file_to_write: str = default_config_file
33
+ ) -> None:
34
+ """
35
+ Write configuration file
36
+
37
+ Args:
38
+ config_dict (dict): configuration dictionary
39
+ config_file_to_write (str): path to config file
40
+ """
41
+ with open(abspath(expanduser(config_file_to_write)), "w") as f:
42
+ json.dump(config_dict, f)
@@ -0,0 +1,64 @@
1
+ """
2
+ Core functionality to generate two factor authentication codes
3
+ """
4
+
5
+ from typing import Any
6
+
7
+ import pyotp
8
+ import qrcode
9
+ from PIL import Image
10
+ from pyzbar.pyzbar import decode
11
+
12
+
13
+ def decode_qrcode(qrcode_png_file_name: str) -> str:
14
+ """
15
+ Decode qrcode from png file
16
+
17
+ Args:
18
+ qrcode_png_file_name (str): path to the png file which contains the qr code
19
+
20
+ Returns:
21
+ str: decoded otpauth string
22
+ """
23
+ return decode(Image.open(qrcode_png_file_name))[0].data.decode("utf-8")
24
+
25
+
26
+ def encode_qrcode(otpauth_str: str, file_name: str) -> None:
27
+ """
28
+ Encode otpauth string into qrcode image saved as png file
29
+
30
+ Args:
31
+ otpauth_str (str): otpauth string
32
+ file_name (str): path to the png file which will contain the qr code
33
+ """
34
+ qrcode.make(otpauth_str).save(file_name, "PNG")
35
+
36
+
37
+ def get_totp(otpauth_str: str) -> str:
38
+ """
39
+ Get TOTP code for a specific service based on its otpauth dictionary
40
+
41
+ Args:
42
+ otpauth_str (str): otpauth string for the service
43
+
44
+ Returns:
45
+ str: TOTP code for the service
46
+ """
47
+ otpauth_dict = {
48
+ kv[0]: kv[1]
49
+ for kv in [
50
+ otpvar.split("=") for otpvar in otpauth_str.replace("?", "&").split("&")[1:]
51
+ ]
52
+ }
53
+
54
+ kwargs: dict[str, Any] = {}
55
+ if "digits" in otpauth_dict.keys():
56
+ kwargs["digits"] = int(otpauth_dict["digits"])
57
+ if "period" in otpauth_dict.keys():
58
+ kwargs["interval"] = int(otpauth_dict["period"])
59
+ if "issuer" in otpauth_dict.keys():
60
+ kwargs["issuer"] = otpauth_dict["issuer"]
61
+ return pyotp.TOTP(
62
+ **kwargs,
63
+ s=otpauth_dict["secret"],
64
+ ).now()
@@ -0,0 +1,65 @@
1
+ """
2
+ Generate two factor authentication codes on the command line
3
+ """
4
+
5
+ from typing import Optional
6
+ from pyauthenticator._config import default_config_file, load_config
7
+ from pyauthenticator.api import (
8
+ add_service,
9
+ generate_qrcode,
10
+ get_totp_for_key_in_dict,
11
+ list_services,
12
+ )
13
+
14
+
15
+ def write_qrcode_to_file(service: str, file_name: Optional[str] = None) -> None:
16
+ """
17
+ Write qrcode to file to scan it with a mobile application
18
+
19
+ Args:
20
+ service (str): lower case name of the service
21
+ file_name (str/ None): default file name <service.png>
22
+ """
23
+ generate_qrcode(key=service, config_dict=load_config(), file_name=file_name)
24
+
25
+
26
+ def get_two_factor_code(service: str) -> str:
27
+ """
28
+ Generate two factor authentication code
29
+
30
+ Args:
31
+ service (str): lower case name of the service
32
+
33
+ Returns:
34
+ str: two factor authentication code
35
+ """
36
+ return get_totp_for_key_in_dict(
37
+ key=service,
38
+ config_dict=load_config(),
39
+ )
40
+
41
+
42
+ def add_two_factor_provider(service: str, qrcode_png_file_name: str) -> None:
43
+ """
44
+ Add new two factor authentication provider to configuration file
45
+
46
+ Args:
47
+ service (str): lower case name of the service
48
+ qrcode_png_file_name (str): path to the png file which contains the qr code
49
+ """
50
+ add_service(
51
+ key=service,
52
+ qrcode_png_file_name=qrcode_png_file_name,
53
+ config_dict=load_config(),
54
+ config_file_to_write=default_config_file,
55
+ )
56
+
57
+
58
+ def list_two_factor_providers() -> list[str]:
59
+ """
60
+ List all two factor authentication providers in the configuration file
61
+
62
+ Returns:
63
+ list[str]: list of two factor authentication providers
64
+ """
65
+ return list_services(config_dict=load_config())
@@ -1,7 +1,14 @@
1
1
  # file generated by setuptools-scm
2
2
  # don't change, don't track in version control
3
3
 
4
- __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
5
12
 
6
13
  TYPE_CHECKING = False
7
14
  if TYPE_CHECKING:
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
9
16
  from typing import Union
10
17
 
11
18
  VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
12
20
  else:
13
21
  VERSION_TUPLE = object
22
+ COMMIT_ID = object
14
23
 
15
24
  version: str
16
25
  __version__: str
17
26
  __version_tuple__: VERSION_TUPLE
18
27
  version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
19
30
 
20
- __version__ = version = '0.2.1'
21
- __version_tuple__ = version_tuple = (0, 2, 1)
31
+ __version__ = version = '0.3.0'
32
+ __version_tuple__ = version_tuple = (0, 3, 0)
33
+
34
+ __commit_id__ = commit_id = None
@@ -0,0 +1,70 @@
1
+ """
2
+ Shared functionality to generate two factor authentication codes
3
+ """
4
+
5
+ from typing import Any, Dict, List, Optional
6
+
7
+ from pyauthenticator._core import decode_qrcode, encode_qrcode, get_totp
8
+ from pyauthenticator._config import default_config_file, write_config
9
+
10
+
11
+ def get_totp_for_key_in_dict(key: str, config_dict: Dict[str, Any]) -> str:
12
+ """
13
+ Generate the two factor authentication code
14
+
15
+ Args:
16
+ key (str): lower case name of the service
17
+ config_dict (dict): configuration dictionary
18
+
19
+ Returns:
20
+ str: two factor authentication code as string
21
+ """
22
+ return get_totp(otpauth_str=config_dict[key])
23
+
24
+
25
+ def add_service(
26
+ key: str,
27
+ qrcode_png_file_name: str,
28
+ config_dict: Dict[str, Any],
29
+ config_file_to_write: str = default_config_file,
30
+ ) -> None:
31
+ """
32
+ Add new service to configuration file
33
+
34
+ Args:
35
+ key (str): lower case name of the service
36
+ qrcode_png_file_name (str): path to the png file which contains the qr code
37
+ config_dict (dict): configuration dictionary
38
+ config_file_to_write (str): path to config file
39
+ """
40
+ config_dict[key] = decode_qrcode(qrcode_png_file_name=qrcode_png_file_name)
41
+ write_config(config_dict=config_dict, config_file_to_write=config_file_to_write)
42
+
43
+
44
+ def generate_qrcode(
45
+ key: str, config_dict: Dict[str, Any], file_name: Optional[str] = None
46
+ ) -> None:
47
+ """
48
+ Write qrcode to file to scan it with a mobile application
49
+
50
+ Args:
51
+ key (str): lower case name of the service
52
+ config_dict (dict): configuration dictionary
53
+ file_name (str/ None): default file name <service.png>
54
+ """
55
+ if file_name is None:
56
+ file_name = key + ".png"
57
+ encode_qrcode(otpauth_str=config_dict[key], file_name=file_name)
58
+
59
+
60
+ def list_services(config_dict: Dict[str, Any]) -> List[str]:
61
+ """
62
+ List available services
63
+
64
+ Args:
65
+ config_dict (dict): configuration dictionary
66
+
67
+ Returns:
68
+ list: list of available services
69
+ """
70
+ return list(config_dict.keys())
@@ -1,37 +0,0 @@
1
- """
2
- Generate two factor authentication codes on the command line
3
- """
4
-
5
- from . import _version
6
- from pyauthenticator.share import generate_qrcode
7
- from pyauthenticator.share import get_two_factor_code as get_two_factor_code_internal
8
- from pyauthenticator.share import load_config
9
-
10
- __version__ = _version.__version__
11
-
12
-
13
- def write_qrcode_to_file(service, file_name=None):
14
- """
15
- Write qrcode to file to scan it with a mobile application
16
-
17
- Args:
18
- service (str): lower case name of the service
19
- file_name (str/ None): default file name <service.png>
20
- """
21
- generate_qrcode(key=service, config_dict=load_config(), file_name=file_name)
22
-
23
-
24
- def get_two_factor_code(service):
25
- """
26
- Generate two factor authentication code
27
-
28
- Args:
29
- service (str): lower case name of the service
30
-
31
- Returns:
32
- str: two factor authentication code
33
- """
34
- return get_two_factor_code_internal(
35
- key=service,
36
- config_dict=load_config(),
37
- )
@@ -1,167 +0,0 @@
1
- """
2
- Shared functionality to generate two factor authentication codes
3
- """
4
-
5
- import json
6
- import os
7
- from inspect import signature
8
-
9
- import pyotp
10
- import qrcode
11
- from PIL import Image
12
- from pyzbar.pyzbar import decode
13
-
14
- # default configuration file
15
- config_file = "~/.pyauthenticator"
16
-
17
-
18
- def expand_path(path):
19
- """
20
- Expand path by expanding the user variable and converting the path to an absolute path
21
-
22
- Args:
23
- path (str): path before expansion
24
-
25
- Returns:
26
- str: expanded path
27
- """
28
- return os.path.abspath(os.path.expanduser(path))
29
-
30
-
31
- def load_config(config_file_to_load=config_file):
32
- """
33
- Load configuration file
34
-
35
- Args:
36
- config_file_to_load (str): path to config file
37
-
38
- Returns:
39
- dict: Dictionary with service names as keys and the otpauth url as values
40
- """
41
- abs_config_path = expand_path(path=config_file_to_load)
42
- if os.path.exists(abs_config_path):
43
- with open(abs_config_path, "r") as f:
44
- return json.load(f)
45
- else:
46
- return {}
47
-
48
-
49
- def write_config(config_dict, config_file_to_write=config_file):
50
- """
51
- Write configuration file
52
-
53
- Args:
54
- config_dict (dict): configuration dictionary
55
- config_file_to_write (str): path to config file
56
- """
57
- with open(expand_path(path=config_file_to_write), "w") as f:
58
- json.dump(config_dict, f)
59
-
60
-
61
- def get_otpauth_dict(otpauth_str):
62
- """
63
- Parse otpauth url
64
-
65
- Args:
66
- otpauth_str (str): otpauth url as string
67
-
68
- Returns:
69
- dict: Dictionary with the parameters of the otpauth url as key-value pairs
70
- """
71
- return {
72
- kv[0]: kv[1]
73
- for kv in [
74
- otpvar.split("=") for otpvar in otpauth_str.replace("?", "&").split("&")[1:]
75
- ]
76
- }
77
-
78
-
79
- def check_if_key_in_config(key, config_dict):
80
- """
81
- Check if a given key is included in a dictionary, raise an ValueError if it is not.
82
-
83
- Args:
84
- key (str): key as string
85
- config_dict (dict): configuration dictionary
86
- """
87
- if key not in config_dict.keys():
88
- raise ValueError()
89
-
90
-
91
- def get_two_factor_code(key, config_dict):
92
- """
93
- Generate the two factor authentication code
94
-
95
- Args:
96
- key (str): lower case name of the service
97
- config_dict (dict): configuration dictionary
98
-
99
- Returns:
100
- str: two factor authentication code as string
101
- """
102
- check_if_key_in_config(key=key, config_dict=config_dict)
103
- decode_dict_internal = get_otpauth_dict(otpauth_str=config_dict[key])
104
- funct_sig = signature(pyotp.TOTP)
105
- if "digits" in decode_dict_internal.keys():
106
- digits = int(decode_dict_internal["digits"])
107
- else:
108
- digits = funct_sig.parameters["digits"].default
109
- if "period" in decode_dict_internal.keys():
110
- interval = int(decode_dict_internal["period"])
111
- else:
112
- interval = funct_sig.parameters["interval"].default
113
- if "issuer" in decode_dict_internal.keys():
114
- issuer = decode_dict_internal["issuer"]
115
- else:
116
- issuer = funct_sig.parameters["issuer"].default
117
- return pyotp.TOTP(
118
- s=decode_dict_internal["secret"],
119
- digits=digits,
120
- issuer=issuer,
121
- interval=interval,
122
- ).now()
123
-
124
-
125
- def add_service(
126
- key, qrcode_png_file_name, config_dict, config_file_to_write=config_file
127
- ):
128
- """
129
- Add new service to configuration file
130
-
131
- Args:
132
- key (str): lower case name of the service
133
- qrcode_png_file_name (str): path to the png file which contains the qr code
134
- config_dict (dict): configuration dictionary
135
- config_file_to_write (str): path to config file
136
- """
137
- otpauth_str = decode(Image.open(qrcode_png_file_name))[0].data.decode("utf-8")
138
- config_dict[key] = otpauth_str
139
- write_config(config_dict=config_dict, config_file_to_write=config_file_to_write)
140
-
141
-
142
- def generate_qrcode(key, config_dict, file_name=None):
143
- """
144
- Write qrcode to file to scan it with a mobile application
145
-
146
- Args:
147
- key (str): lower case name of the service
148
- config_dict (dict): configuration dictionary
149
- file_name (str/ None): default file name <service.png>
150
- """
151
- if file_name is None:
152
- file_name = key + ".png"
153
- check_if_key_in_config(key=key, config_dict=config_dict)
154
- qrcode.make(config_dict[key]).save(file_name, "PNG")
155
-
156
-
157
- def list_services(config_dict):
158
- """
159
- List available services
160
-
161
- Args:
162
- config_dict (dict): configuration dictionary
163
-
164
- Returns:
165
- list: list of available services
166
- """
167
- return list(config_dict.keys())
File without changes