def get_path_to_image(address, name_file): """ Метод получения пути к нужному файлу отдельного пользователя :param address: <str> адрес пользователя :param name_file: <str> имя нужного файла :return: <str> Путь к файлу """ users_list = JsonFiles().get_json(const.PATH_TO_BCH_USERS_MAP) if not users_list or not users_list[address]: return '' id_user = users_list[address] directory = os.path.join(const.PATH_TO_BCH_USERS, id_user, const.PATH_TO_USER_BUILD_FILES) path = os.path.join(const.PATH_TO_BCH_USERS, id_user, const.PATH_TO_USER_BUILD_FILES, name_file) if not JsonFiles().is_file(path): return '' dir_to = os.path.join(const.FLASK_STATIC_IMAGE_TMP, id_user) if not JsonFiles().is_file(os.path.join(dir_to, name_file)): JsonFiles().copy_file(name_file, directory, dir_to) return const.NAME_TMP + '/' + id_user + '/' + name_file
def todo_login(): public_key = request.files.get('publicKey') private_key = request.files.get('privateKey') address = request.files.get('address') if not public_key or not private_key or not address: return redirect(url_for('login', error='Один из файлов не был получен!')) if not JsonFiles().is_dir(const.PATH_TO_TMP_LOGIN): JsonFiles().create_directory(const.PATH_TO_TMP_LOGIN) public_key.save(os.path.join(const.PATH_TO_TMP_LOGIN, 'public_key.txt')) private_key.save(os.path.join(const.PATH_TO_TMP_LOGIN, 'private_key.txt')) address.save(os.path.join(const.PATH_TO_TMP_LOGIN, 'address.txt')) keys = Keys().get_keys(os.path.join(const.PATH_TO_TMP_LOGIN, 'public_key.txt'), os.path.join(const.PATH_TO_TMP_LOGIN, 'private_key.txt')) address = JsonFiles().get_text(os.path.join(const.PATH_TO_TMP_LOGIN, 'address.txt')) if not address == Keys().pubkey_to_address(keys[0]): return redirect(url_for('login', error='Данный публичный ключ не соответсвует адресу!')) data = User().get_info_user(address) if data: JsonFiles().set_json_in_file(const.PATH_TO_DATA, data) else: return redirect(url_for('login', error='Такой пользователь не найден!')) return redirect(url_for('admin'))
def todo_register(): form = request.form Keys().generate_keys() # Создаем ключи keys = Keys().get_keys() # Получаем их строковое представление address = Keys().pubkey_to_address(keys[0]) # Генерируем адресс JsonFiles().write_to_data(const.PATH_TO_ADDRESS, address) # Запись адреса data = get_users(address, form) # Вносим данные path_to_dir = User().create_user_dir(address) # Создаем папку для пользователя JsonFiles().write_to_data(os.path.join(const.PATH_TO_BCH_USERS, path_to_dir, 'public_key.txt'), keys[0]) # Пишем туда ключ JsonFiles().set_json_in_file(os.path.join(const.PATH_TO_BCH_USERS, path_to_dir, const.PATH_TO_USER_INFO), data) Transactions().new_transaction('new_user', data) return redirect(url_for('message', type='registration'))
def todo_edit_section(): data = request.json print(data) print(request.form) print(request.data) user_info = User().get_this_user_info() user_info['sections'] = data dir_user = User().get_dir_user(user_info['id']) JsonFiles().set_json_in_file(const.PATH_TO_DATA, user_info) JsonFiles().set_json_in_file(os.path.join(dir_user, const.PATH_TO_USER_INFO), user_info) Transactions().new_transaction('update', user_info) return jsonify({'status': 'ok'})
def user_profile(path): path_to_user_info = os.path.join(const.PATH_TO_BCH_USERS, path, const.PATH_TO_USER_INFO) if not os.path.isfile(path_to_user_info): return redirect(url_for('index', error='Данный пользователь не найден!')) data = JsonFiles().get_json(path_to_user_info) return render_template('user.html', name='user', data=data, address=data['id'])
def todo_edit_profile(): data = request.json user_info = JsonFiles().get_json(const.PATH_TO_DATA) user_info_new = user_info if data["type"] == 'public_info': user_info_new = get_edit_data_user_public(data, user_info) JsonFiles().set_json_in_file(const.PATH_TO_DATA, user_info_new) name_dir = User().get_dir_user(user_info['id']) JsonFiles().set_json_in_file( os.path.join(const.PATH_TO_USER_INFO, name_dir, const.PATH_TO_USER_INFO), user_info_new ) Transactions().new_transaction('update', user_info_new) return jsonify({'status': 'ok'})
def get_list_users(): dirs = os.listdir(const.PATH_TO_BCH_USERS) list_users = [] for el in dirs: path = os.path.join(const.PATH_TO_BCH_USERS, el) if os.path.isdir(path): data_path = os.path.join(path, const.PATH_TO_USER_INFO) data = JsonFiles().get_json(data_path) if JsonFiles().get_prop(data, 'main_info.role') == '0': list_users.append({ "name": JsonFiles().get_prop(data, 'main_info.name'), "profession": JsonFiles().get_prop( data, 'public_info.profession.props.profession_name.value' ), "path": el }) return list_users
def todo_update_photo(type): if type == 'update': file = request.files.get('action_load_file') filename = file.filename user_info = User().get_this_user_info() dir_user = User().get_dir_user(user_info['id']) user_info = JsonFiles().set_prop(user_info, 'main_info.user_photo', filename) JsonFiles().set_json_in_file(const.PATH_TO_DATA, user_info) file.save(os.path.join(dir_user, const.PATH_TO_USER_BUILD_FILES, filename)) Transactions().new_transaction('update', user_info) elif type == 'remove': user_info = User().get_this_user_info() user_info = JsonFiles().set_prop(user_info, 'main_info.user_photo', '') JsonFiles().set_json_in_file(const.PATH_TO_DATA, user_info) Transactions().new_transaction('update', user_info) return jsonify({'status': 'ok'})
class ActionLearner(object): """Класс для выполнение сетевых запросов learner узла""" __json__ = JsonFiles() def _action(self, message): """ Метод обработки запросов от других пользователей :param message: <obj> Объект запроса :return: """ type_message = self.__json__.get_prop(message, 'header.type').split('_') if type_message[0] == 'learner': pass elif type_message[0] == 'user': if type_message[1] == 'check-action': print('CHECK ACTION!!!') elif type_message[1] == 'enter': print('ENTER!!!')
def admin_edit(menu): config = JsonFiles().get_json(const.PATH_TO_CONFIG_EDIT_USER) test = False for link in config["links"]: if menu == link["name"]: test = True if not test: return redirect(url_for('admin', error='Страница не найдена!')) data = User().get_this_user_info() if not Mage().action_user() or not data: return redirect(url_for('login')) if menu == 'public_info': return render_template('admin_edit.html', name='edit_profile', menu=menu, data=data, address=data['id'], config=config) elif menu == 'section': return render_template('admin_edit_section.html', name='edit_profile_section', menu=menu, data=data, address=data['id'], config=config)
class ActionUser(object): """Класс для выполнение сетевых запросов user узла""" __json__ = JsonFiles() __network__ = Network() __files___ = Files() __directorys__ = Directory __keys__ = Keys def _action(self, message): """ Метод обработки запросов от других пользователей :param message: <obj> Объект запроса :return: """ print(message) type_message = self.__json__.get_prop(message, 'header.type').split('_') if type_message[0] == 'lerner': if type_message[1] == 'check-active': self.__send_active(self.__json__.get_prop(message, 'header.id'), 'learner') # далее хрень какая та написана elif type_message[0] == 'transaction': transaction = self.__json__.get_prop(message, 'data') # TODO: Всё работает только если if True!!! Что то не так с проверкой транзакции if Transactions().verify_transaction(transaction): # Берём хеш транзакции и далее его хешируем # Это используется для наименования файлов transaction_hash = self.__json__.get_prop(message, 'data.hash') name_file_transaction = hashlib.sha1(transaction_hash.encode()).hexdigest() # TODO: Нужно по красивее сделать путь к папке (да и вообще не понятно правильно ли я прописал путь) # Кто нибудь помогите с путями!!! if transaction.get("type") == "new_user": # Создаём файл hash = self.create_user_dir(transaction["data"]["id"]) path_transaction = os.path.join(const.PATH_TO_BCH_USERS, hash, const.PATH_TO_USER_INFO) self.__json__.set_json_in_file(path_transaction, transaction["data"]) # path_transaction = const.PATH_TO_BCH_RAW_TRANSACTION + '/' + name_file_transaction +'.json' # self.__files___.create_file(path_transaction) elif transaction.get("type") == "update": hash = self.get_dir_user(transaction["data"]["id"]) path_transaction = os.path.join(const.PATH_TO_BCH_USERS, hash, const.PATH_TO_USER_INFO) self.__json__.set_json_in_file(path_transaction, transaction["data"]) # Записываем транзакцию в файл #self.__json__.set_json_in_file(path_transaction, transaction["data"]) else: pass elif type_message[0] == 'block': block = self.__json__.get_prop(message, 'data') # TODO: Опять что то не так с проверкой # if (self.__blockchain__.check_block(block)) == True: # if True: if Blockchain().check_block(block): # Находим номер последнего элемента str_mass = os.listdir(const.PATH_TO_BCH_BLOCKS) int_mass = [] for name in str_mass: int_mass.append(int(name[:-5])) # Уже не надо # int_mass = result = [int(item) for item in str_mass] last_item = max(int_mass) name_file_block = str(last_item + 1) path_block = const.PATH_TO_BCH_BLOCKS + '/' + name_file_block + '.json' self.__files___.create_file(path_block) self.__json__.set_json_in_file(path_block, block) # далее нужно пропарсить блок и найти транзакции созданий пользователей # что бы записать их в users # Это массив транзакций mass_transactions = self.__json__.get_prop(message, 'data.transactions') for transaction in mass_transactions: type_transaction = self.__json__.get_prop(transaction, 'type') if type_transaction == 'new_user': # Создание директории # user_address = self.__json__.get_prop(message, 'transaction.sender') user_address = transaction["sender"] hash_addr = self.create_user_dir(user_address) self.__json__.set_json_in_file( os.path.join(const.PATH_TO_BCH_USERS, hash_addr), transaction["data"] ) # Создание файлика с ключём path_public_key = os.path.join(const.PATH_TO_BCH_USERS, hash_addr, 'public_key.txt') self.__files___.create_file(path_public_key) user_public_key = self.__keys__.address_to_pubkey(user_address) public_key_txt = open(path_public_key, "w") public_key_txt.write(user_public_key) public_key_txt.close() if type_transaction == 'update': # Перезаписываем файл data # address_update_user = self.__json__.get_prop(message, 'transaction.sender') address_update_user = transaction["hash"] address_update_user_dir = self.get_dir_user(address_update_user) print(address_update_user_dir) # Не знаю как перезаписать, так что просто удоляю и создаю заново self.__files___.write_to_data( os.path.join(const.PATH_TO_BCH_USERS, address_update_user_dir, const.PATH_TO_USER_INFO), transaction["data"] ) else: pass def __send_active(self, id_answer, role='learner'): """ Метод отправки ответа, что данный узел в сети :param id_answer: <str> id пользователя, который отправил запрос :param role: <str> Базовая роль пользователя (learner or user) :return: <bool> Успешность отправки ответа """ data = self.__json__.get_json(const.PATH_TO_DATA) id_user = '' if data: if data.get('id'): id_user = data["id"] data_user = {} if role == 'learner': learners = self.__json__.get_json(const.PATH_TO_LIST_LEARNERS) data_user = learners[id_answer] message = self.__network__.create_message(id_user, 'user_check-action', {}) success = self.__network__.send( data_user["ip"], const.PORT_LEARNER if role == 'learner' else const.PORT_USER, message ) return True if success else False # TODO: То что ниже не должно находиться в этом файле!!!! # Нужно отдельно сделать фалй и класс PARSER # Работает! def get_user_data(self, address): """ Метод, который возвращает объект с данными пользователя :param address: Адрес пользователя :return: объект с данными пользователя """ # data = self.__json__.get_json(const.PATH_TO_BCH_USERS_MAP) - TODO: Не робит!!! path = os.path.join(const.PATH_TO_BCH_USERS, str(address), const.PATH_TO_USER_INFO) data = self.__json__.get_json(path) return data # Работает def get_user_transactions_by_type(self, address, type): """ Метод который возвращает массив транзакций пользователя по типу :param address: адрес пользователя :param type: тип транзакции :return: массив транзакций """ blocks_mass = os.listdir(const.PATH_TO_BCH_BLOCKS) mass_hash = [] for block in blocks_mass: path = os.path.join(const.PATH_TO_BCH_BLOCKS, block) data = self.__json__.get_json(path) transactions = self.__json__.get_prop(data, 'transactions') for transaction in transactions: # print(transaction) # print(transaction["type"]) # print(transaction["sender"]) if (transaction["type"] == type) and (transaction["sender"] == address): mass_hash.append(transaction) else: pass return mass_hash def get_ip(self): # data = self.__json__.get_json("../../data/IP/ip.json") data = self.__json__.get_json(os.path.join(const.PATH_TO_FILES, 'IP', 'ip.json')) mass_ip = data["ip_address"] return mass_ip def create_user_dir(self, address, count=0): """ Метод для создания директории, в которой будет хранится вся информация о нужном пользователе :param address: <str> адресс пользователя :param count: <int> смещение адреса, на случай если директория уже имеется :return: <str> имя созданной директории """ map_users = {} if not self.__json__.is_file(const.PATH_TO_BCH_USERS_MAP): self.__json__.create_file(const.PATH_TO_BCH_USERS_MAP) else: map_users = self.__json__.get_json(const.PATH_TO_BCH_USERS_MAP) if map_users.get(address): return map_users.get(address) hash_address = hashlib.sha1((address + str(count) if count else '').encode()).hexdigest() for addr, key in map_users.items(): if key == hash_address: count += 1 return self.create_user_dir(address, count) map_users[address] = hash_address self.__json__.set_json_in_file(const.PATH_TO_BCH_USERS_MAP, map_users) path = os.path.join(const.PATH_TO_BCH_USERS, hash_address) self.__json__.create_directory(path) self.__json__.create_file(os.path.join(path, const.PATH_TO_USER_INFO)) self.__json__.create_directory(os.path.join(path, const.PATH_TO_USER_PART_FILES)) self.__json__.create_directory(os.path.join(path, const.PATH_TO_USER_BUILD_FILES)) return hash_address def get_dir_user(self, address): """ Метод получения имени директории, в которой лежим информация о пользователе :param address: <str> адресс пользователя :return: <str> путь к директории """ map_users = self.__json__.get_json(const.PATH_TO_BCH_USERS_MAP) if map_users.get(address): return os.path.join(const.PATH_TO_BCH_USERS, map_users.get(address)) else: return ''
def get_users(address, data): data_info = User().create_user_object(address, data) JsonFiles().set_json_in_file(const.PATH_TO_DATA, data_info) return data_info
def todo_exit(): if JsonFiles().is_file(const.PATH_TO_DATA): JsonFiles().clear_file(const.PATH_TO_DATA) return redirect(url_for('index'))
class Learner(ActionLearner): """ Класс доверенного узла """ __PAUSE_CHECK_USERS__ = 10 # Задержка проверки сети на наличие пользователей (в секундах) __network__ = Network() # Свойство для работы с сетью __json__ = JsonFiles() # Свойство для работы с json файлами def __init__(self, start=False): super().__init__() self.__clear_start_files() if start: self.start() def start(self): """Метод запуска основных функций learner""" self.__server() self.check_network() @thread def check_network(self): """Метод проверки всех узлов на наличие в сети. Запускается в отдельном потоке и в бесконечном цикле запускает метод проверки Метод проверки запускается с паузой, останавливая данный поток """ print('CHECK NETWORK START...') while True: self.__check_network() @thread def __server(self): """Запуск сервера на прослушку сети""" self.__network__.server(const.PORT_LEARNER, self.__get_message, const.LISTEN_LEARNER) @pause(__PAUSE_CHECK_USERS__) @thread def __check_network(self): users = self.__json__.get_json(const.PATH_TO_LIST_USERS) data = self.__json__.get_json(const.PATH_TO_DATA) if not users: return id_learner = '' if data: if data.get('id'): id_learner = data["id"] dis_active_users = [] active_users = {} for id_user, data_user in users.items(): message = self.__network__.create_message(id_learner, "lerner_check-active", {}) success = self.__network__.send(data_user["ip"], const.PORT_USER, message) if success: active_users[id_user] = data_user else: dis_active_users.append(id_user) print('action users: ' + str(len(active_users))) change = self.verify_action_users(active_users, dis_active_users) print(change) def verify_action_users(self, action_users, dis_active_users): """ Метод проверки изменения активности пользователей Если какой-то пользователь зашел в сеть или же наоборот вышел, то данные об этом обновляются :param action_users: <obj> json объект активных пользователей :param dis_active_users: <arr str> Массив id пользователей, которые сейчас не в сети :return: <obj> json объект, в котором указаны изменния активности """ change = {"action": [], "dis_active": []} users = self.__json__.get_json(const.PATH_TO_LIST_USERS_ACTION) for id_user, data in action_users.items(): if not users.get(id_user): change["action"].append(id_user) users[id_user] = data for id_user in dis_active_users: if not users.get(id_user) is None: change["dis_active"].append(id_user) del users[id_user] if change["action"] or change["dis_active"]: self.__json__.set_json_in_file(const.PATH_TO_TMP_USERS, action_users) return change def __get_message(self, message): """Метод обработки всех пришедших сообщений""" self._action(json.loads(message)) def __clear_start_files(self): """Очистка файлов и дерикторий, оставшихся после последнего запуска""" self.__json__.delete_file(const.PATH_TO_LIST_USERS_ACTION) self.__json__.clear_directory(const.PATH_TO_TMP)
def action_user(): if JsonFiles().is_zero_file(const.PATH_TO_DATA): return False return True
class User(ActionUser): __network__ = Network() __json__ = JsonFiles() def __init__(self, action_server=False): super().__init__() if action_server: self.server() self.__active() @thread def server(self): """Запуск сервера на прослушку сети""" self.__network__.server(const.PORT_USER, self.__get_message, const.LISTEN_USER) @staticmethod def create_user_object(address, data): """ Метод создания базового образца обхекта пользователя :param address: <str> Сгенерированный адрес пользователя :param data: <obj json|dict> Информация о пользователе :return: <obj json|dict> Объект со всему необходимыми данными """ return { "id": address, "main_info": { "name": data.get('name'), "role": data.get('role'), "user_photo": "", }, "public_info": { "age_and_gender": { "title": "Возраст и пол", "props": { "age": { "title": "Возраст", "value": "" }, "gender": { "title": "Пол", "value": "m", "description": { "m": "Мужской", "w": "Женский" } } } }, "contact_info": { "title": "Контактнная информация", "props": { "phone": { "title": "Телефон", "value": "" }, "email": { "title": "Почта", "value": "" } } }, "profession": { "title": "Сфера деятельности", "props": { "profession_name": { "title": "Профессия", "value": "web-developer" } } } }, "about_us": {}, "sections": [] } def get_this_user_info(self): """Метод получения информации о данном пользователе""" return self.__json__.get_json(const.PATH_TO_DATA) def get_info_user(self, address=''): """ Метод получения информации о пользователе. Если информация не была получена ранее, то она ищется в бокчейне :param address: <str> Адрес пользователя, о котором мы ищем информацию :return: <obj json> Вся известная информация о пользователе """ if not address: return {} path_to_dir = self.get_dir_user(address) if not path_to_dir: # TODO: тянем с блокчейна и т.д. pass if self.__json__.is_dir(path_to_dir): return self.__json__.get_json( os.path.join(path_to_dir, const.PATH_TO_USER_INFO)) def __get_message(self, message): """Метод обработки всех пришедших сообщений""" self._action(json.loads(message)) def __active(self): """ Метод, который сообщает сети о том, что он в сети :return: null """ learners = self.__json__.get_json(const.PATH_TO_LIST_LEARNERS) data = self.__json__.get_json(const.PATH_TO_DATA) id_user = '' if data: if data.get('id'): id_user = data["id"] message = self.__network__.create_message(id_user, 'user_enter', {}) for learner_id, learner_data in learners.items(): self.__network__.send(learner_data["ip"], const.PORT_LEARNER, message)