1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
|
"""
Copyright (c) 2023 Proton AG
This file is part of Proton.
Proton is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Proton is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ProtonVPN. If not, see <https://www.gnu.org/licenses/>.
"""
import json
import os
from ..utils import ExecutionEnvironment
from ._base import Keyring
from .exceptions import KeyringError
class KeyringBackendJsonFiles(Keyring):
"""Primitive data storage implementation, to be used when no better keyring is present.
It stores each entry a json in the configuration path.
"""
def __init__(self, path_config=None):
super().__init__()
self.__path_base = path_config or ExecutionEnvironment().path_config
def _get_item(self, key):
filepath = self.__get_filename_for_key(key)
if not os.path.exists(filepath):
raise KeyError(key)
try:
with open(filepath, 'r') as f:
return json.load(f)
except json.JSONDecodeError as e:
self._del_item(key)
raise KeyError(key) from e
def _del_item(self, key):
filepath = self.__get_filename_for_key(key)
if not os.path.exists(filepath):
raise KeyError(key)
os.unlink(filepath)
def _set_item(self, key, value):
try:
with open(self.__get_filename_for_key(key), 'w') as f:
json.dump(value, f)
except TypeError as e:
# The value we got is not serializable, thus a type error is thrown,
# we re-raise it as a ValueError because the value that was provided was in
# in un-expected format/type
raise ValueError(value) from e
except FileNotFoundError as e:
# if the path was not previously created for some reason,
# we get a FileNotFoundError
raise KeyringError(key) from e
def __get_filename_for_key(self, key):
return os.path.join(self.__path_base, f'keyring-{key}.json')
@classmethod
def _get_priority(cls) -> int:
return -1000
@classmethod
def _validate(cls):
is_able_to_write_in_dir = True
try:
ExecutionEnvironment().path_config
except: # noqa
is_able_to_write_in_dir = False
return is_able_to_write_in_dir
|