diff --git a/.gitignore b/.gitignore
index a1c2a238..1bc94f32 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,4 @@
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
+/.idea/
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 00000000..f9d2d44f
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,49 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.1
+
+
+ ru.yandex.practicum
+ catsgram
+ 0.0.1-SNAPSHOT
+ catsgram
+ Мини-версия популярной соцсети с фотографиями котов.
+
+ 11
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jdbc
+
+
+ org.postgresql
+ postgresql
+ 42.3.3
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
diff --git a/src/main/java/ru/yandex/practicum/catsgram/CatsgramApplication.java b/src/main/java/ru/yandex/practicum/catsgram/CatsgramApplication.java
new file mode 100644
index 00000000..cae260e2
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/CatsgramApplication.java
@@ -0,0 +1,14 @@
+package ru.yandex.practicum.catsgram;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+
+//@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
+@SpringBootApplication
+public class CatsgramApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(CatsgramApplication.class, args);
+ }
+
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/catsgram/Constants.java b/src/main/java/ru/yandex/practicum/catsgram/Constants.java
new file mode 100644
index 00000000..862424b0
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/Constants.java
@@ -0,0 +1,10 @@
+package ru.yandex.practicum.catsgram;
+
+import java.util.Set;
+
+public class Constants {
+ public static final String DESCENDING_ORDER = "desc";
+ public static final String ASCENDING_ORDER = "asc";
+
+ public static final Set SORTS = Set.of(ASCENDING_ORDER, DESCENDING_ORDER);
+}
diff --git a/src/main/java/ru/yandex/practicum/catsgram/controller/ErrorHandler.java b/src/main/java/ru/yandex/practicum/catsgram/controller/ErrorHandler.java
new file mode 100644
index 00000000..aa28fce8
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/controller/ErrorHandler.java
@@ -0,0 +1,64 @@
+package ru.yandex.practicum.catsgram.controller;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import ru.yandex.practicum.catsgram.exception.IncorrectParameterException;
+import ru.yandex.practicum.catsgram.exception.InvalidEmailException;
+import ru.yandex.practicum.catsgram.exception.PostNotFoundException;
+import ru.yandex.practicum.catsgram.exception.UserAlreadyExistException;
+import ru.yandex.practicum.catsgram.exception.UserNotFoundException;
+import ru.yandex.practicum.catsgram.model.ErrorResponse;
+
+@RestControllerAdvice
+public class ErrorHandler {
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public ErrorResponse handleIncorrectParameterException(final IncorrectParameterException e) {
+ return new ErrorResponse(
+ String.format("Ошибка с полем \"%s\".", e.getParameter())
+ );
+ }
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ public ErrorResponse handleInvalidEmailException(final InvalidEmailException e) {
+ return new ErrorResponse(
+ e.getMessage()
+ );
+ }
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.NOT_FOUND)
+ public ErrorResponse handlePostNotFoundException(final PostNotFoundException e) {
+ return new ErrorResponse(
+ e.getMessage()
+ );
+ }
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.NOT_FOUND)
+ public ErrorResponse handleUserNotFoundException(final UserNotFoundException e) {
+ return new ErrorResponse(
+ e.getMessage()
+ );
+ }
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.CONFLICT)
+ public ErrorResponse handlePostNotFoundException(final UserAlreadyExistException e) {
+ return new ErrorResponse(
+ e.getMessage()
+ );
+ }
+
+ @ExceptionHandler
+ @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
+ public ErrorResponse handleThrowable(final Throwable e) {
+ return new ErrorResponse(
+ "Произошла непредвиденная ошибка."
+ );
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/catsgram/controller/PostController.java b/src/main/java/ru/yandex/practicum/catsgram/controller/PostController.java
new file mode 100644
index 00000000..a1b715a9
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/controller/PostController.java
@@ -0,0 +1,30 @@
+package ru.yandex.practicum.catsgram.controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import ru.yandex.practicum.catsgram.exception.IncorrectParameterException;
+import ru.yandex.practicum.catsgram.model.Post;
+import ru.yandex.practicum.catsgram.service.PostService;
+
+import java.util.Collection;
+import java.util.List;
+
+import static ru.yandex.practicum.catsgram.Constants.DESCENDING_ORDER;
+import static ru.yandex.practicum.catsgram.Constants.SORTS;
+
+@RestController
+public class PostController {
+ private final PostService postService;
+
+ public PostController(PostService postService) {
+ this.postService = postService;
+ }
+
+ @GetMapping("/posts")
+ public Collection findAll(@RequestParam String userId) {
+ return postService.findPostsByUser(userId);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/catsgram/controller/PostFeedController.java b/src/main/java/ru/yandex/practicum/catsgram/controller/PostFeedController.java
new file mode 100644
index 00000000..e06755dd
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/controller/PostFeedController.java
@@ -0,0 +1,26 @@
+package ru.yandex.practicum.catsgram.controller;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import ru.yandex.practicum.catsgram.model.Post;
+import ru.yandex.practicum.catsgram.service.FeedService;
+
+import java.util.List;
+
+@RestController()
+@RequestMapping("/feed")
+public class PostFeedController {
+
+ private final FeedService feedService;
+
+ public PostFeedController(FeedService feedService) {
+ this.feedService = feedService;
+ }
+
+ @GetMapping
+ List getFriendsFeed(@RequestParam("userId") String userId, @RequestParam(defaultValue = "10") int max) {
+ return feedService.getFeedFor(userId, max);
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/catsgram/controller/SimpleController.java b/src/main/java/ru/yandex/practicum/catsgram/controller/SimpleController.java
new file mode 100644
index 00000000..62478e88
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/controller/SimpleController.java
@@ -0,0 +1,28 @@
+package ru.yandex.practicum.catsgram.controller;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+import ru.yandex.practicum.catsgram.service.HackCatService;
+
+import java.util.Optional;
+
+@RestController
+public class SimpleController {
+ private final HackCatService hackCatService;
+ public SimpleController(HackCatService hackCatService) {
+ this.hackCatService = hackCatService;
+ }
+
+ @GetMapping("/do-hack")
+ public Optional doHack(){
+ return hackCatService.doHackNow()
+ .map(password -> "Ура! Пароль подобран: " + password)
+ .or(() -> Optional.of("Не удалось подобрать пароль. "
+ + " Проверьте состояние и настройки базы данных."));
+ }
+
+ @GetMapping("/home")
+ public String homePage() {
+ return "Котограм";
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/catsgram/controller/UserController.java b/src/main/java/ru/yandex/practicum/catsgram/controller/UserController.java
new file mode 100644
index 00000000..7d3e2b72
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/controller/UserController.java
@@ -0,0 +1,24 @@
+package ru.yandex.practicum.catsgram.controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import ru.yandex.practicum.catsgram.model.User;
+import ru.yandex.practicum.catsgram.service.UserService;
+
+import java.util.Optional;
+
+@RestController
+@RequestMapping("/users")
+public class UserController {
+ private final UserService userService;
+
+ public UserController(UserService userService) {
+ this.userService = userService;
+ }
+
+ @GetMapping("/{login}")
+ public Optional getUser(@PathVariable String login){
+ return userService.findUserById(login);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/catsgram/dao/FollowDao.java b/src/main/java/ru/yandex/practicum/catsgram/dao/FollowDao.java
new file mode 100644
index 00000000..4a1c0522
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/dao/FollowDao.java
@@ -0,0 +1,9 @@
+package ru.yandex.practicum.catsgram.dao;
+import ru.yandex.practicum.catsgram.model.Post;
+
+import java.util.List;
+
+public interface FollowDao {
+ List getFollowFeed(String userId, int max);
+}
+
diff --git a/src/main/java/ru/yandex/practicum/catsgram/dao/PostDao.java b/src/main/java/ru/yandex/practicum/catsgram/dao/PostDao.java
new file mode 100644
index 00000000..fff2a920
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/dao/PostDao.java
@@ -0,0 +1,10 @@
+package ru.yandex.practicum.catsgram.dao;
+
+import ru.yandex.practicum.catsgram.model.Post;
+import ru.yandex.practicum.catsgram.model.User;
+
+import java.util.Collection;
+
+public interface PostDao {
+ Collection findPostsByUser(User user);
+}
diff --git a/src/main/java/ru/yandex/practicum/catsgram/dao/UserDao.java b/src/main/java/ru/yandex/practicum/catsgram/dao/UserDao.java
new file mode 100644
index 00000000..7c884686
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/dao/UserDao.java
@@ -0,0 +1,9 @@
+package ru.yandex.practicum.catsgram.dao;
+
+import ru.yandex.practicum.catsgram.model.User;
+
+import java.util.Optional;
+
+public interface UserDao {
+ Optional findUserById(String id);
+}
diff --git a/src/main/java/ru/yandex/practicum/catsgram/dao/impl/FollowDaoImpl.java b/src/main/java/ru/yandex/practicum/catsgram/dao/impl/FollowDaoImpl.java
new file mode 100644
index 00000000..faeb0938
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/dao/impl/FollowDaoImpl.java
@@ -0,0 +1,61 @@
+package ru.yandex.practicum.catsgram.dao.impl;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Component;
+import ru.yandex.practicum.catsgram.dao.FollowDao;
+import ru.yandex.practicum.catsgram.dao.PostDao;
+import ru.yandex.practicum.catsgram.dao.UserDao;
+import ru.yandex.practicum.catsgram.model.Follow;
+import ru.yandex.practicum.catsgram.model.Post;
+import ru.yandex.practicum.catsgram.model.User;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Component
+public class FollowDaoImpl implements FollowDao {
+
+ private final JdbcTemplate jdbcTemplate;
+ private final UserDao userDao;
+ private final PostDao postDao;
+
+ public FollowDaoImpl(JdbcTemplate jdbcTemplate, UserDao userDao, PostDao postDao) {
+ this.jdbcTemplate = jdbcTemplate;
+ this.userDao = userDao;
+ this.postDao = postDao;
+ }
+
+ @Override
+ public List getFollowFeed(String userId, int max) {
+ // получаем все подписки пользователя
+ String sql = "select * from cat_follow where follower_id = ?";
+ List follows = jdbcTemplate.query(sql, (rs, rowNum) -> makeFollow(rs), userId);
+
+ // выгружаем авторов на которых подписан пользователь
+ Set authors = follows.stream()
+ .map(Follow::getAuthor)
+ .map(userDao::findUserById)
+ .filter(Optional::isPresent)
+ .map(Optional::get)
+ .collect(Collectors.toSet());
+
+ if(authors.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ // выгружаем посты полученных выше авторов
+ return authors.stream()
+ .map(postDao::findPostsByUser)
+ .flatMap(Collection::stream)
+ // сортируем от новых к старым
+ .sorted(Comparator.comparing(Post::getCreationDate).reversed())
+ // отбрасываем лишнее
+ .limit(max)
+ .collect(Collectors.toList());
+ }
+
+ private Follow makeFollow(ResultSet rs) throws SQLException {
+ return new Follow(rs.getString("author_id"), rs.getString("follower_id"));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/catsgram/dao/impl/PostDaoImpl.java b/src/main/java/ru/yandex/practicum/catsgram/dao/impl/PostDaoImpl.java
new file mode 100644
index 00000000..b00f7db6
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/dao/impl/PostDaoImpl.java
@@ -0,0 +1,42 @@
+package ru.yandex.practicum.catsgram.dao.impl;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Component;
+import ru.yandex.practicum.catsgram.dao.PostDao;
+import ru.yandex.practicum.catsgram.model.Post;
+import ru.yandex.practicum.catsgram.model.User;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.time.LocalDate;
+import java.util.Collection;
+
+@Component
+public class PostDaoImpl implements PostDao {
+ private final JdbcTemplate jdbcTemplate;
+
+ public PostDaoImpl(JdbcTemplate jdbcTemplate){
+ this.jdbcTemplate = jdbcTemplate;
+ }
+
+ @Override
+ public Collection findPostsByUser(User user) {
+ // метод принимает в виде аргумента строку запроса, преобразователь и аргумент — id пользователя
+ String sql = "select * from cat_post where author_id = ? order by creation_date desc";
+
+ return jdbcTemplate.query(sql, (rs, rowNum) -> makePost(user, rs), user.getId());
+ }
+
+ private Post makePost(User user, ResultSet rs) throws SQLException {
+ // используем конструктор, методы ResultSet
+ // и готовое значение user
+ Integer id = rs.getInt("id");
+ String description = rs.getString("description");
+ String photoUrl = rs.getString("photo_url");
+
+ // Получаем дату и конвертируем её из sql.Date в time.LocalDate
+ LocalDate creationDate = rs.getDate("creation_date").toLocalDate();
+
+ return new Post(id, user, description, photoUrl, creationDate);
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/catsgram/dao/impl/UserDaoImpl.java b/src/main/java/ru/yandex/practicum/catsgram/dao/impl/UserDaoImpl.java
new file mode 100644
index 00000000..9492bd5f
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/dao/impl/UserDaoImpl.java
@@ -0,0 +1,37 @@
+package ru.yandex.practicum.catsgram.dao.impl;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.support.rowset.SqlRowSet;
+import org.springframework.stereotype.Component;
+import ru.yandex.practicum.catsgram.dao.UserDao;
+import ru.yandex.practicum.catsgram.model.User;
+
+import java.util.Optional;
+@Component
+public class UserDaoImpl implements UserDao {
+ private final Logger log = LoggerFactory.getLogger(UserDaoImpl.class);
+ private final JdbcTemplate jdbcTemplate;
+
+ public UserDaoImpl(JdbcTemplate jdbcTemplate){
+ this.jdbcTemplate=jdbcTemplate;
+ }
+
+ @Override
+ public Optional findUserById(String id) {
+ SqlRowSet userRows = jdbcTemplate.queryForRowSet("select * from cat_user where id = ?", id);
+ if(userRows.next()) {
+ log.info("Найден пользователь: {} {}", userRows.getString("id"), userRows.getString("nickname"));
+ // вы заполните данные пользователя в следующем уроке
+ User user = new User(userRows.getString("id"),
+ userRows.getString("username"),
+ userRows.getString("nickname"));
+ user.setId(id);
+ return Optional.of(user);
+ } else {
+ log.info("Пользователь с идентификатором {} не найден.", id);
+ return Optional.empty();
+ }
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/catsgram/exception/IncorrectParameterException.java b/src/main/java/ru/yandex/practicum/catsgram/exception/IncorrectParameterException.java
new file mode 100644
index 00000000..efbea9a9
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/exception/IncorrectParameterException.java
@@ -0,0 +1,13 @@
+package ru.yandex.practicum.catsgram.exception;
+
+public class IncorrectParameterException extends RuntimeException {
+ private final String parameter;
+
+ public IncorrectParameterException(String parameter) {
+ this.parameter = parameter;
+ }
+
+ public String getParameter() {
+ return parameter;
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/catsgram/exception/InvalidEmailException.java b/src/main/java/ru/yandex/practicum/catsgram/exception/InvalidEmailException.java
new file mode 100644
index 00000000..36741ba1
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/exception/InvalidEmailException.java
@@ -0,0 +1,7 @@
+package ru.yandex.practicum.catsgram.exception;
+
+public class InvalidEmailException extends RuntimeException {
+ public InvalidEmailException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/catsgram/exception/PostNotFoundException.java b/src/main/java/ru/yandex/practicum/catsgram/exception/PostNotFoundException.java
new file mode 100644
index 00000000..4eb0c4ae
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/exception/PostNotFoundException.java
@@ -0,0 +1,7 @@
+package ru.yandex.practicum.catsgram.exception;
+
+public class PostNotFoundException extends RuntimeException {
+ public PostNotFoundException(String message){
+ super(message);
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/catsgram/exception/UserAlreadyExistException.java b/src/main/java/ru/yandex/practicum/catsgram/exception/UserAlreadyExistException.java
new file mode 100644
index 00000000..8f52373f
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/exception/UserAlreadyExistException.java
@@ -0,0 +1,7 @@
+package ru.yandex.practicum.catsgram.exception;
+
+public class UserAlreadyExistException extends RuntimeException {
+ public UserAlreadyExistException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/catsgram/exception/UserNotFoundException.java b/src/main/java/ru/yandex/practicum/catsgram/exception/UserNotFoundException.java
new file mode 100644
index 00000000..c4547ea6
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/exception/UserNotFoundException.java
@@ -0,0 +1,7 @@
+package ru.yandex.practicum.catsgram.exception;
+
+public class UserNotFoundException extends RuntimeException {
+ public UserNotFoundException(String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/catsgram/model/ErrorResponse.java b/src/main/java/ru/yandex/practicum/catsgram/model/ErrorResponse.java
new file mode 100644
index 00000000..13659c56
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/model/ErrorResponse.java
@@ -0,0 +1,13 @@
+package ru.yandex.practicum.catsgram.model;
+
+public class ErrorResponse {
+ private final String error;
+
+ public ErrorResponse(String error) {
+ this.error = error;
+ }
+
+ public String getError() {
+ return error;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/catsgram/model/FeedParams.java b/src/main/java/ru/yandex/practicum/catsgram/model/FeedParams.java
new file mode 100644
index 00000000..219b1bc3
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/model/FeedParams.java
@@ -0,0 +1,34 @@
+package ru.yandex.practicum.catsgram.model;
+
+import java.util.List;
+
+public class FeedParams {
+ private String sort;
+ private Integer size;
+ private List friendsEmails;
+
+ public void setSort(String sort) {
+ this.sort = sort;
+ }
+
+ public String getSort() {
+ return sort;
+ }
+
+ public void setSize(Integer size) {
+ this.size = size;
+ }
+
+ public Integer getSize() {
+ return size;
+ }
+
+ public void setFriendsEmails(List friendsEmails) {
+ this.friendsEmails = friendsEmails;
+ }
+
+ public List getFriendsEmails() {
+ return friendsEmails;
+ }
+}
+
diff --git a/src/main/java/ru/yandex/practicum/catsgram/model/Follow.java b/src/main/java/ru/yandex/practicum/catsgram/model/Follow.java
new file mode 100644
index 00000000..9b2d1c99
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/model/Follow.java
@@ -0,0 +1,27 @@
+package ru.yandex.practicum.catsgram.model;
+public class Follow {
+ private String author;
+ private String follower;
+
+ public Follow(String author, String follower) {
+ this.author = author;
+ this.follower = follower;
+ }
+
+ public String getAuthor() {
+ return author;
+ }
+
+ public void setAuthor(String author) {
+ this.author = author;
+ }
+
+ public String getFollower() {
+ return follower;
+ }
+
+ public void setFollower(String follower) {
+ this.follower = follower;
+ }
+}
+
diff --git a/src/main/java/ru/yandex/practicum/catsgram/model/Post.java b/src/main/java/ru/yandex/practicum/catsgram/model/Post.java
new file mode 100644
index 00000000..6ee6b34f
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/model/Post.java
@@ -0,0 +1,59 @@
+package ru.yandex.practicum.catsgram.model;
+
+import java.time.Instant;
+import java.time.LocalDate;
+
+public class Post {
+ private Integer id;
+ private final User author; // автор
+ private final LocalDate creationDate; // дата создания
+ private String description; // описание
+ private String photoUrl; // url-адрес фотографии
+
+ public Post(User author, String description, String photoUrl) {
+ this.author = author;
+ this.description = description;
+ this.photoUrl = photoUrl;
+ this.creationDate = LocalDate.now();
+ }
+
+ public Post(Integer id, User author, String description, String photoUrl, LocalDate creationDate) {
+ this.id = id;
+ this.author = author;
+ this.description = description;
+ this.photoUrl = photoUrl;
+ this.creationDate = creationDate;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public User getAuthor() {
+ return author;
+ }
+
+ public LocalDate getCreationDate() {
+ return creationDate;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getPhotoUrl() {
+ return photoUrl;
+ }
+
+ public void setPhotoUrl(String photoUrl) {
+ this.photoUrl = photoUrl;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/catsgram/model/User.java b/src/main/java/ru/yandex/practicum/catsgram/model/User.java
new file mode 100644
index 00000000..79c19ae0
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/model/User.java
@@ -0,0 +1,42 @@
+package ru.yandex.practicum.catsgram.model;
+
+import java.time.LocalDate;
+import java.util.Objects;
+
+public class User {
+ private String id;
+
+ private String username;
+
+ private String nickname;
+
+ public User(String id, String username, String nickname) {
+ this.id = id;
+ this.username = username;
+ this.nickname = nickname;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getNickname() {
+ return nickname;
+ }
+
+ public void setNickname(String nickname) {
+ this.nickname = nickname;
+ }
+
+ public String getId() {
+ return id;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/catsgram/service/FeedService.java b/src/main/java/ru/yandex/practicum/catsgram/service/FeedService.java
new file mode 100644
index 00000000..0df25b30
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/service/FeedService.java
@@ -0,0 +1,20 @@
+package ru.yandex.practicum.catsgram.service;
+
+import org.springframework.stereotype.Service;
+import ru.yandex.practicum.catsgram.dao.FollowDao;
+import ru.yandex.practicum.catsgram.model.Post;
+
+import java.util.List;
+
+@Service
+public class FeedService {
+ private final FollowDao followDao;
+
+ public FeedService(FollowDao followDao) {
+ this.followDao = followDao;
+ }
+
+ public List getFeedFor(String userId, int max) {
+ return followDao.getFollowFeed(userId, max);
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/catsgram/service/HackCatService.java b/src/main/java/ru/yandex/practicum/catsgram/service/HackCatService.java
new file mode 100644
index 00000000..78a96d50
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/service/HackCatService.java
@@ -0,0 +1,42 @@
+package ru.yandex.practicum.catsgram.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.datasource.DriverManagerDataSource;
+import org.springframework.stereotype.Service;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class HackCatService {
+ private Logger log = LoggerFactory.getLogger(getClass());
+ public static final String JDBC_URL="jdbc:postgresql://127.0.0.1:5432/cats";
+ public static final String JDBC_USERNAME="kitty";
+ public static final String JDBC_DRIVER="org.postgresql.Driver";
+
+ public void tryPassword(String jdbcPassword) {
+ DriverManagerDataSource dataSourceConst = new DriverManagerDataSource();
+ dataSourceConst.setDriverClassName(JDBC_DRIVER);
+ dataSourceConst.setUrl(JDBC_URL);
+ dataSourceConst.setUsername(JDBC_USERNAME);
+ dataSourceConst.setPassword(jdbcPassword);
+ JdbcTemplate jdbcTemplateConst = new JdbcTemplate(dataSourceConst);
+ jdbcTemplateConst.execute("SELECT 1;");
+ }
+
+ public Optional doHackNow(){
+ List catWordList = Arrays.asList("meow", "purr", "purrrrrr", "zzz");
+ for (String word : catWordList) {
+ try {
+ tryPassword(word);
+ return Optional.of(word);
+ } catch (Exception e) {
+ log.info("Такой пароль не подходит: " + word);
+ }
+ }
+ return Optional.empty();
+ }
+}
diff --git a/src/main/java/ru/yandex/practicum/catsgram/service/PostService.java b/src/main/java/ru/yandex/practicum/catsgram/service/PostService.java
new file mode 100644
index 00000000..79b309d6
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/service/PostService.java
@@ -0,0 +1,42 @@
+package ru.yandex.practicum.catsgram.service;
+
+import org.springframework.stereotype.Service;
+import ru.yandex.practicum.catsgram.dao.PostDao;
+import ru.yandex.practicum.catsgram.exception.UserNotFoundException;
+import ru.yandex.practicum.catsgram.model.Post;
+import ru.yandex.practicum.catsgram.model.User;
+
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+@Service
+public class PostService {
+ private final PostDao postDao;
+ private final UserService userService;
+
+ public PostService(PostDao postDao, UserService userService) {
+ this.postDao = postDao;
+ this.userService = userService;
+ }
+
+ public Collection findPostsByUser(String userId) {
+ User user = userService.findUserById(userId)
+ .orElseThrow(() ->new UserNotFoundException("Пользователь с идентификатором " + userId + " не найден."));
+
+ return postDao.findPostsByUser(user);
+ }
+
+ public Collection findPostsByUser(String authorId, Integer size, String sort) {
+ return findPostsByUser(authorId)
+ .stream()
+ .sorted((p0, p1) -> {
+ int comp = p0.getCreationDate().compareTo(p1.getCreationDate()); //прямой порядок сортировки
+ if (sort.equals("desc")) {
+ comp = -1 * comp; //обратный порядок сортировки
+ }
+ return comp;
+ })
+ .limit(size)
+ .collect(Collectors.toList());
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/ru/yandex/practicum/catsgram/service/UserService.java b/src/main/java/ru/yandex/practicum/catsgram/service/UserService.java
new file mode 100644
index 00000000..ad0ca6fa
--- /dev/null
+++ b/src/main/java/ru/yandex/practicum/catsgram/service/UserService.java
@@ -0,0 +1,20 @@
+package ru.yandex.practicum.catsgram.service;
+
+import org.springframework.stereotype.Service;
+import ru.yandex.practicum.catsgram.dao.UserDao;
+import ru.yandex.practicum.catsgram.model.User;
+
+import java.util.Optional;
+
+@Service
+public class UserService {
+ private final UserDao userDao;
+
+ public UserService(UserDao userDao) {
+ this.userDao = userDao;
+ }
+
+ public Optional findUserById(String id) {
+ return userDao.findUserById(id);
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 00000000..fbe9f2e7
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,5 @@
+
+spring.datasource.url=jdbc:postgresql://localhost:5432/cats
+spring.datasource.username=kitty
+spring.datasource.password=purrrrrr
+spring.datasource.driver-class-name=org.postgresql.Driver
\ No newline at end of file
diff --git a/src/test/java/ru/yandex/practicum/catsgram/CatsgramApplicationTests.java b/src/test/java/ru/yandex/practicum/catsgram/CatsgramApplicationTests.java
new file mode 100644
index 00000000..32936573
--- /dev/null
+++ b/src/test/java/ru/yandex/practicum/catsgram/CatsgramApplicationTests.java
@@ -0,0 +1,13 @@
+package test.java.ru.yandex.practicum.catsgram;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class CatsgramApplicationTests {
+
+ @Test
+ void contextLoads() {
+ }
+
+}
diff --git a/target/classes/application.properties b/target/classes/application.properties
new file mode 100644
index 00000000..fbe9f2e7
--- /dev/null
+++ b/target/classes/application.properties
@@ -0,0 +1,5 @@
+
+spring.datasource.url=jdbc:postgresql://localhost:5432/cats
+spring.datasource.username=kitty
+spring.datasource.password=purrrrrr
+spring.datasource.driver-class-name=org.postgresql.Driver
\ No newline at end of file
diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
new file mode 100644
index 00000000..e69de29b
diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
new file mode 100644
index 00000000..02a8a6c8
--- /dev/null
+++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
@@ -0,0 +1,21 @@
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\dao\impl\UserDaoImpl.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\model\ErrorResponse.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\exception\UserNotFoundException.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\controller\PostFeedController.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\controller\ErrorHandler.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\CatsgramApplication.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\controller\PostController.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\exception\UserAlreadyExistException.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\service\UserService.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\dao\UserDao.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\exception\InvalidEmailException.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\model\FeedParams.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\controller\UserController.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\model\User.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\service\HackCatService.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\model\Post.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\service\PostService.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\Constants.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\exception\PostNotFoundException.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\exception\IncorrectParameterException.java
+C:\Users\Aleks\dev\module2_catsgram\src\main\java\ru\yandex\practicum\catsgram\controller\SimpleController.java