AppLoidx / helios-rest-api

REST API for helios queue service

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool




Helios REST API side

🙂Author

Arthur Kupriyanov

📙Документация к API Helios

API docs v1 : Веб-версия идентичная с README.md

Запуск

Перед запуском необходимо настроить hiberante.cfg.xml

mvn install
java -jar target/fileName.jar

Общие сведения

Предназначение

Этот API должен быть доступным для пользования всеми разработчиками, в том числе для создания собственных сервисов, интеграции с социальными сетями и тому подобным. Также следовательно он должен иметь методы аутентификации и идентификации пользователей через протокол OAuth.

Документацию по использованию API и примеры можно найти здесь

Средства разработки

Реализован JAX-RS через Jersey и поднят на сервере GrizzlyHttpServer от Apache. Задеплоен в сервисе heroku

Сборка производится через maven с системой автоматической сборки на travis-ci

Иерархия файлов

com.apploidxxx :

  • api - классы и методы отвечающие за обработку запросов
    • exceptions - пользовательские исключения
    • filter - фильтры запросов
    • model - POJO объекты
  • ds - средства инициализации datasource (HibernateSession)
  • entity - хранимые объекты (persistence units)
    • dao - расположение всех DAO и их сервисов

test:

  • api - тесты по API (запросы через rest-assured)
  • entity - тесты по логике работы хранимых объектов

resources/static:

  • external - формы для авторизации\регистрации через OAuth

api/exceptions

IResponsibleException

  • Интерфейс для всех исключений выбрасываемых в работе с API и которые могут генерировать Response для отправки клиенту.
import javax.ws.rs.core.Response;
public interface IResponsibleException {  
	  Response getResponse();  
	  String getErrorMessage();  
	  String getErrorDescription();  
}

ResponsibleException

  • Прослойка между интерфейсом IResponsibleException и самими реализациями исключений, которая наследуется от Exception и является абстрактной:
public abstract class ResponsibleException extends Exception implements IResponsibleException {  }

Наследование исключения от этого класса (его реализация IResponsibleException) дает нам возможность использовать (вместе с try/catch конструкциями) такого вида упрощения обработки ошибок:

Листинг 1.1 QueueApi

public Response getQueue(   @Valid@NotNull@QueryParam("queue_name") String queueName){  
  
  try {  
	Queue q = QueueManager.getQueue(queueName);
	return Response.ok(q).build();  
  } catch (InvalidQueueException e) {  
        return e.getResponse();  
  }  
}

Таким образом, исключение умеет генерировать Response, который можно возвращать пользователю. Вот его реализация:

Листинг 1.2 InvalidQueueException

public class InvalidQueueException extends ResponsibleException{  
  
    @Override  
  public Response getResponse() {  
        return Response  
                .status(Response.Status.NOT_FOUND)  
                .entity(new ErrorMessage(getErrorMessage(), getErrorDescription()))  
                .build();  
  }  
  
    @Override  
  public String getErrorMessage() {  
        return "invalid_queue";  
  }  
  
    @Override  
  public String getErrorDescription() {  
        return "queue not found";  
  }  
}

api/model

Здесь представлены POJO объекты, которые по назначению должны сериализовываться в json. Все имена полей я буду приводить как они написаны в самом коде (то есть в верблюжем стиле), но все они при сериализации меняют свой проперти на стиль json, то есть this_is_my_value

ErrorMessage

Объект являющийся стандартным для отправки ответа запросам, которые вызывали ошибку или были некорректны. Содержит поля error и errorDescription

Check

Объект содержащий поле exist. Обычно используется для CheckApi, например, для проверки существования такого имени пользователя или очереди.

UserInfo

Класс-враппер для сущности User. Вот его поля:

private User user;  
private List<String[]> queues; 
 
@JsonProperty("queues_member")    
private List<String[]> queuesMember;  

@JsonProperty("swap_requests")  
private List<Map<String, String>> swapRequests;
  • queues - коллекция из массива очередей, содержащих два значения - короткое имя (ссылка) и полное имя очереди. Например, {["shortLink","My Queue Fullname" ]}. Этот список содержит очереди, в которых пользователь находится как участник или администратор.
  • queuesMember - такой же список как queues, но содержит очереди, в которых пользователь является лишь участником (не входят очереди, в которых он администратор)
  • user - данные о пользователе, кроме приватных данных, как например, пароль
  • swapRequests - список мапов описывающих заявки на обмен местами (пока только исходящих). Метод добавляющий значение в swapRequest:
    Листинг 2.1 UserInfo
     private void addSwapRequest(Queue queue, User user){  
       SwapContainer sc = queue.getSwapContainer();  
       User target = sc.getSwapRequest(user);  
       if (target != null) {  
               Map<String, String> hashMap = new HashMap<>();  
     		  hashMap.put("queue_name", queue.getName());  
     		  hashMap.put("queue_fullname", queue.getFullname());  
     		  hashMap.put("target_username", target.getUsername());  
     		  hashMap.put("target_firstname", target.getFirstName());  
     		  hashMap.put("target_lastname", target.getLastName());  
     		  swapRequests.add(hashMap);  
       }  
     }

api/util

ErrorResponseFactory

Реализация паттерна фабрики - имеет статические методы возвращающие объекты Response с тем или иным кодом ошибки и как говорилось ранее, объектом ErrorMessage в качестве ответа пользователю:

Листинг 2.2 ErrorResponseFactory

public abstract class ErrorResponseFactory {  
    public static Response getInvalidParamErrorResponse(String description){  
        return Response  
                .status(Response.Status.BAD_REQUEST)  
                .entity(new ErrorMessage("invalid_param", description))  
                .build();  
  }  
  
    public static Response getForbiddenErrorResponse(String description){  
        return Response  
                .status(Response.Status.FORBIDDEN)  
                .entity(new ErrorMessage("insufficient_rights", description))  
                .build();  
  }  
  
    public static Response getForbiddenErrorResponse(){  
        return getForbiddenErrorResponse("You don't have enough rights");  
  }  
  ...
}

Password

Класс для проверки и валидации паролей. Использует MD5 хэширование. Имеет два публичных метода:

Листинг 2.3 Password

public static String hash(String password){  
    return Md5Crypt.md5Crypt((password + salt).getBytes());  
}
public static boolean isEqual(String rawPassword, String hashedPassword){  
    return hashedPassword.equals(hash(rawPassword, hashedPassword));  
}

Собственно, hash хэширует пароль для хранения в БД, а isEqual проверяет совпадение паролей.

QueueManager, UserManager, UserSessionManager

Это обертки над QueueService и UserService, которые работают с сущностями БД. Они имеют методы, которые могут выкидывать специфичные исключение, как например, InvalidQueueException или UserNotFoundException.

Листинг 2.4 QueueManager

public class QueueManager {  
  public  static Queue getQueue(String queueName) throws InvalidQueueException {  
      Queue q = QueueService.findQueue(queueName);  
	  if (q == null){  
	      throw new InvalidQueueException();  
	  } else {  
	      return q;  
	  }  
  }  
}

VulnerabilityChecker

Проверяет строковые данные на уязвимости и наличие опасных значений, таких как <script>. Имеет один метод checkWord, который в случае опасности выбрасывает исключение VulnerabilityException.

entity/dao

В этом пакете находятся DAO-объекты, при этом каждого такого объекта область видимости ограничивается лишь пакетом, а публичный доступ дается через сервисный класс (подробнее далее)

DAOBasicOperations

Класс который реализует простые операции с сущностями и БД, чтобы не писать много boilerplate-кода он был вынесен в отдельный класс и используется с обобщениями:

public class DAOBasicOperations<T> {  
    public void save(T obj) {  
      Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();  
	  Transaction tx1 = session.beginTransaction();  
	  session.save(obj);  
	  tx1.commit();  
	  session.close();  
  }  
  
    public void update(T obj) {  
      Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();  
	  Transaction tx1 = session.beginTransaction();  
	  session.update(obj);  
	  tx1.commit();  
	  session.close();  
  }  
  
    public void delete(T obj) {  
	  Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();  
	  Transaction tx1 = session.beginTransaction();  
	  session.delete(obj);  
	  tx1.commit();  
	  session.close();  
	}  
}

Рассмотрим его использование на примере:

Листинг 3.1 MessageDAO

public class MessageDAO {  
      private DAOBasicOperations<Message> basicOperations = new DAOBasicOperations<>();  
	  Message findById(Long id) {  
	        return HibernateSessionFactoryUtil.getSessionFactory().openSession().get(Message.class, id);  
	  }  
  
	  void save(Message user) {  
	        basicOperations.save(user);  
	  }  
  
    void update(Message user) {  
	        basicOperations.update(user);  
    }  
  
    void delete(Message user) {  
	        basicOperations.delete(user);  
    }  
    List<Message> findAll() {  
        try (Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession()){  
            return session.createQuery("from Message", Message.class).list();  
	    }  
    }  
}

entity

Сущность Назначение
User Данные о пользователе
ContactDetails Дополнительные данные о пользователе (email, vk id ...)
Chat Чат очереди (one-to-one Queue)
Message Сообщение в чате (one-to-one Chat)
Queue Информация об очереди
Session Сессия с пользователем (accessToken, refreshToken)

About

REST API for helios queue service


Languages

Language:Java 100.0%