Giter Club home page Giter Club logo

helios-rest-api's Introduction




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)

helios-rest-api's People

Contributors

apploidx avatar dependabot[bot] avatar

Watchers

 avatar

Forkers

lgtm-migrator

helios-rest-api's Issues

SwapRequest для пользователей

Проблема

Нужно чтобы у пользователя была возможность просматривать свои заявка на обмен в очереди.

Сейчас реализовано в виде Map<User, User> внутри entity SwapContainer:

    @ElementCollection(targetClass=User.class, fetch = FetchType.EAGER)
    @MapKeyColumn(name="userMap")
    private Map<User , User> swapMap;

    public void addSwapRequest(User user, User target){
        swapMap.put(user, target);
        if (user.equals(swapMap.get(target))){
            queue.swap(user, target);
        }
    }

С точки зрения лишь обмена мест в серверном режиме это удобно, так как по ключу мы уже можем проверить, существует ли обратная заявка,
тем не менее, при этом совершенно невозможно (очень затратно) найти все заявки поданные пользователем.

Предлагаемое решение

Создать класс SwapRequest, который имеет отношение ManyToOne с User.

Таким образом, каждый пользователь может иметь несколько заявок (внутри которых указан кто является целью и в какой очереди).

Затем нужно добавить в метод api/check вызов проверки заявок (возвращает список заявок, можно создать какую-нибудь вспомогательную модель)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.