Beispiel #1
0
    def auth(self, response: Message):
        """Метод, отвечающий за авторизацию на сервере"""
        if response.action == REGISTER or response.action == AUTH:
            try:
                if response.action == REGISTER:
                    data = {
                        ACTION: REGISTER,
                        FROM: self.user_name,
                        TEXT: self.password
                    }
                    self.send(Message(**data))
                    response = receive(self.__sock, self.__logger)[0]

                # Получаем публичный ключ и декодируем его из байтов
                pubkey = self.keys.publickey().export_key().decode(
                    'ascii') if self.keys else None

                # Запускаем процедуру авторизации
                # Получаем хэш пароля
                passwd_bytes = self.password.encode('utf-8')
                salt = self.user_name.lower().encode('utf-8')
                passwd_hash = hashlib.pbkdf2_hmac('sha512', passwd_bytes, salt,
                                                  10000)
                passwd_hash_string = binascii.hexlify(passwd_hash)
                # Если сервер вернул ошибку, бросаем исключение.
                if response.response:
                    if response.response == FORBIDDEN:
                        raise ServerError(response.text)
                    elif response.response == OK:
                        # Если всё нормально,
                        # то продолжаем процедуру авторизации.
                        ans_data = response.text
                        hash_str = hmac.new(passwd_hash_string,
                                            ans_data.encode('utf-8'))
                        digest = hash_str.digest()
                        request_data = {
                            ACTION: AUTH,
                            FROM: self.user_name,
                            TEXT: binascii.b2a_base64(digest).decode('ascii'),
                            USER: pubkey
                        }
                        self.send(Message(**request_data))
                        responses = receive(self.__sock, self.__logger)
                        if responses and responses[0].response == OK:
                            info_msg = f'Клиент запущен ({self.user_name}).'
                            print(info_msg)
                            self.__logger.info(info_msg)
                            return True
                        else:
                            return False
            except OSError:
                raise ServerError('Сбой соединения в процессе авторизации.')
Beispiel #2
0
 def interact(self):
     while True:
         try:
             num = abs(
                 int(
                     input(' | '.join([
                         f'{key}. {action["name"]}'
                         for key, action in enumerate(self.__actions, 0)
                     ]) + ' | Выберите действие: ')))
             if 0 <= num <= len(self.__actions):
                 start = self.__actions[num]
             else:
                 raise ValueError
             if start[ACTION] == 'exit':
                 raise KeyboardInterrupt
             params = {ACTION: start[ACTION]}
             if 'params' in start:
                 for param in start['params']:
                     p = str(input(f'Выберите параметр "{param}": '))
                     params[param] = p
             print()
             break
         except ValueError:
             pass
     return Message(**params)
Beispiel #3
0
 def load_contacts(self):
     """Метод загрузки списка контактов"""
     data = {ACTION: GET_CONTACTS, FROM: self.user_name}
     request = Message(data)
     self.send(request)
     time.sleep(1)
     messages = receive(self.__sock, self.__logger)
     return messages or False
Beispiel #4
0
 def __check_presence(self):
     """Метод проверки соединения"""
     data = {ACTION: PRESENCE, FROM: self.__user_name}
     request = Message(data)
     self.send(request)
     messages = receive(self.__sock, self.__logger)
     return messages[0] if messages and messages[0].response == OK \
         else False
Beispiel #5
0
 def send_message(self, to, message):
     """
     Метод, составляющий запрос на отправку сообщения контакту.
     :param to: Имя контакта
     :param message: Сообщение
     :return:
     """
     data = {ACTION: SEND_MSG, TO: to, TEXT: message}
     self.__client.send(Message(**data))
Beispiel #6
0
 def user_list_update(self):
     """
     Метод, составляющий запрос на получение списка подключённых клиентов.
     :return:
     """
     self.__client.logger.debug(
         f'Запрос списка известных пользователей {self.__client.user_name}')
     data = {
         ACTION: GET_CONNECTED,
     }
     self.__client.send(Message(**data))
Beispiel #7
0
 def remove_contact(self, contact):
     """
     Метод, составляющий запрос на удаление контакта
     :param contact: Имя контакта
     :return:
     """
     self.__client.logger.debug(f'Удаление контакта {contact}')
     data = {
         ACTION: DEL_CONTACT,
         USER: contact,
     }
     self.__client.send(Message(**data))
Beispiel #8
0
 def add_contact(self, contact):
     """
     Метод, составляющий запрос на добавление контакта.
     :param contact: Имя контакта
     :return:
     """
     self.__client.logger.debug(f'Создание контакта {contact}')
     data = {
         ACTION: ADD_CONTACT,
         USER: contact,
     }
     self.__client.send(Message(**data))
Beispiel #9
0
 def key_request(self, user_name):
     """
     Метод, составляющий запрос на получение открытого ключа контакта.
     :param user_name: Имя контакта
     :return:
     """
     data = {
         ACTION: PUBLIC_KEY_REQUEST,
         FROM: self.user_name,
         USER: user_name
     }
     self.__client.send(Message(**data))
Beispiel #10
0
 def key_request(self, user_name):
     """
     Метод, составляющий запрос на получение открытого ключа контакта.
     :param user_name: Имя контакта
     :return:
     """
     data = {
         ACTION: PUBLIC_KEY_REQUEST,
         FROM: self.user_name,
         USER: user_name
     }
     with socket_lock:
         self.__client.send(Message(**data))
         responses = receive(self.__client.sock, self.__client.logger)
         if responses:
             response = responses[0]
             if response.response and response.text:
                 return response.text
         self.__client.logger.error(
             f'Не удалось получить ключ собеседника{user_name}.')
Beispiel #11
0
 def key_request(self, user_name: str) -> str:
     """
     Метод получающий открытый ключ контакта с сервера.
     :param user_name: Имя контакта
     :return:
     """
     data = {
         ACTION: PUBLIC_KEY_REQUEST,
         FROM: self.__client.user_name,
         USER: user_name
     }
     with socket_lock:
         self.__client.send(Message(**data))
         responses = receive(self.__client.sock, self.__client.logger)
         if responses:
             response = responses[0]
             if response.response and response.text:
                 return response.text
         self.__client.logger.error(
             f'Не удалось получить ключ собеседника{user_name}.')
Beispiel #12
0
 def interact(self) -> Message:
     """
     Метод взаимодействия с пользователем.
     :return:
     """
     while True:
         try:
             params = {}
             num = abs(int(input('Выберите действие: ')))
             if 0 <= num <= len(self.__actions):
                 start = self.__actions[num]
             else:
                 raise ValueError
             if start[ACTION] == 'exit':
                 raise KeyboardInterrupt
             elif start[ACTION] == 'help':
                 print(self.__help_info)
                 continue
             params = {ACTION: start[ACTION]}
             if 'params' in start:
                 for param in start['params']:
                     p = str(input(f'Выберите параметр "{param}": '))
                     params[param] = p
             if start[ACTION] == ADD_CONTACT:
                 self.__repo.add_contact(params[USER])
             elif start[ACTION] == DEL_CONTACT:
                 self.__repo.del_contact(params[USER])
             elif start[ACTION] == SEND_MSG:
                 if params[TO] == '' or params[TO] == '*':
                     to = ', '.join(self.__repo.get_contacts())
                 else:
                     to = params[TO]
                 self.__repo.save_message(to, "out", params[TEXT])
             break
         except ValueError:
             print('Действие не распознано, попробуйте еще раз...')
             pass
     return Message(**params)
Beispiel #13
0
 async def run_action(self, request: Message):
     """
     Метод, обрабатывающий сообщения от клиента
     :param request: Сообщение клиента
     :return: Созданные ответы
     """
     if request.action in (PRESENCE, REGISTER, AUTH):
         return self.auth(request)
     elif request.action == SEND_MSG:
         contacts = request.destination.replace(' ', '').split(',')
         if len(contacts) == 1 and (not contacts[0] or contacts[0] == '*'):
             contacts = self.__repo.get_contact_list(request.sender)
         if len(contacts) == 1 and contacts[0] == 'Общий_чат':
             contacts = self.__repo.users_list(active=True)
             contacts.remove(request.sender)
             self.__repo.add_general_chat_history(request.sender,
                                                  request.text)
             request.sender = 'Общий_чат'
         responses = []
         for contact in contacts:
             data = {
                 ACTION: SEND_MSG,
                 TEXT: request.text,
                 TO: contact,
                 FROM: request.sender,
             }
             self.__repo.process_message(request.sender, contact)
             responses.append(success(**data))
         return responses
     elif request.action == GET_CONTACTS:
         names = self.__repo.get_contact_list(request.sender)
         count = len(names)
         data = {
             ACTION: GET_CONTACTS,
             QUANTITY: count,
         }
         responses = [accepted(**data)]
         for contact in names:
             data = {
                 ACTION: GET_CONTACTS,
                 USER: contact,
             }
             responses.append(accepted(**data))
         return responses
     elif request.action == GET_CONNECTED:
         names = self.__repo.users_list(active=True)
         responses = []
         for contact in names:
             data = {
                 ACTION: GET_CONNECTED,
                 USER: contact,
             }
             responses.append(accepted(**data))
         return responses
     # Если это запрос публичного ключа пользователя
     elif request.action == PUBLIC_KEY_REQUEST and request.user:
         data = {
             ACTION: PUBLIC_KEY_REQUEST,
             TEXT: self.__repo.get_pubkey(request.user)
         }
         if data[TEXT]:
             return success(**data)
         else:
             return error('Нет публичного ключа для данного пользователя')
     elif request.action == ADD_CONTACT:
         if request.sender == request.user:
             return error('Нельзя добавить себя')
         try:
             self.__repo.add_contact(request.sender, request.user)
             return success()
         except Exception:
             return error('Контакта не существует')
     elif request.action == DEL_CONTACT:
         try:
             self.__repo.remove_contact(request.sender, request.user)
             return success()
         except Exception:
             return error('Контакта не существует')
     elif request.action == ERROR:
         return error('Ошибка действия')
     else:
         return error('Действие недоступно')
 def __check_presence(self):
     data = {ACTION: PRESENCE, FROM: self.__user_name}
     request = Message(data)
     self.send(request)
     messages = receive(self.__sock, self.__logger)
     return messages[0].response == OK if messages else False