27 Commits

Author SHA1 Message Date
e91965e9b5 Merge pull request 'CourseServiceTest' (#10) from CourseServiceTest into master
Reviewed-on: http://git.plannaplan.pl/filipizydorczyk/backend/pulls/10
2020-09-17 16:24:58 +02:00
6be6bd0184 Added LecturerServiceTest with createAndDeleteLecturer
Signed-off-by: Marcin Woźniak <y0rune@aol.com>
2020-09-16 17:41:36 +02:00
1cff3ceb74 Added delete method into LecturerService
Signed-off-by: Marcin Woźniak <y0rune@aol.com>
2020-09-16 17:35:39 +02:00
a717a85a80 Created test GroupServiceTest.java. It contains createAndDeleteGroup
Signed-off-by: Marcin Woźniak <y0rune@aol.com>
2020-09-16 17:33:39 +02:00
d5e32a487b Added delete method in GroupService
Signed-off-by: Marcin Woźniak <y0rune@aol.com>
2020-09-16 17:23:33 +02:00
551011db1c Zmiana nazwy z Remove na Delete, dodanie testu na usuwanie.
Signed-off-by: Marcin Woźniak <y0rune@aol.com>
2020-09-16 17:21:01 +02:00
283be6603d Dodanie usuniecie kursu.
Signed-off-by: Marcin Woźniak <y0rune@aol.com>
2020-09-16 17:15:56 +02:00
43660c4fe9 Dodanie nowego testu do dodawnia kursu.
Signed-off-by: Marcin Woźniak <y0rune@aol.com>
2020-09-16 17:14:37 +02:00
579da3f038 Merge pull request 'security' (#9) from security into master
Reviewed-on: http://git.plannaplan.pl/filipizydorczyk/backend/pulls/9
2020-09-15 17:27:04 +02:00
b951f1f934 Added some endpoints not protected 2020-09-15 11:31:30 +02:00
82c4c9d0fe Added forbiden urls and protected 2020-09-14 14:02:05 +02:00
478ea27480 Endpoint returnung token if valid data 2020-09-14 12:55:47 +02:00
11f3625684 User service added login and returning token 2020-09-14 12:39:25 +02:00
8c16b2f3d1 Added auth endpoint 2020-09-11 14:33:29 +02:00
c9f50c5b16 Cas update 2020-09-11 14:12:13 +02:00
3deebe9248 Added CasValidator 2020-09-11 13:15:22 +02:00
824c137141 Merge pull request 'Removed ConfiguratorTest.java, and rewrite it into configutils/FileToDatabaseMigratorTest.java' (#8) from ConfiguratorTest-to-FileToDatabaseMigratorTest into master
Reviewed-on: http://git.plannaplan.pl/filipizydorczyk/backend/pulls/8
2020-09-09 16:34:00 +02:00
408c8a8242 Removed ConfiguratorTest.java, and rewrite it into configutils/FileToDatabaseMigratorTest.java
Signed-off-by: Marcin Woźniak <y0rune@aol.com>
2020-09-09 16:26:42 +02:00
333ceb9b74 Merge pull request 'testing-web' (#7) from testing-web into master
Testy zakończone sukcesem. Brak błędów pomiędzy discro.

Reviewed-on: http://git.plannaplan.pl/filipizydorczyk/backend/pulls/7
2020-09-04 16:25:40 +02:00
7a7c882163 Added config test 2020-09-04 16:24:00 +02:00
16b9cb3cf2 Spring starts on test run 2020-09-04 16:09:57 +02:00
56e519dcd6 Updated
Signed-off-by: Marcin Woźniak <y0rune@aol.com>
2020-09-03 17:09:35 +02:00
b659f70a1f Changed version junit 4.11 to 4.12
Signed-off-by: Marcin Woźniak <y0rune@aol.com>
2020-09-03 17:02:17 +02:00
f6d4674ec8 Inny error, zmiana lokalizacji pliku
Signed-off-by: Marcin Woźniak <y0rune@aol.com>
2020-09-03 16:59:27 +02:00
9ea2912e98 Added ConfiguratorTest.java. Updated pom.xml
Signed-off-by: Marcin Woźniak <y0rune@aol.com>
2020-09-03 16:30:42 +02:00
b65c56078b Merge pull request 'sql -> hql' (#6) from hql into master
Reviewed-on: http://git.plannaplan.pl/filipizydorczyk/backend/pulls/6
2020-09-03 15:27:37 +02:00
bf5b78c3b6 sql -> hql 2020-09-02 16:56:49 +02:00
31 changed files with 779 additions and 45 deletions

View File

@ -12,8 +12,7 @@
<version>1.0-SNAPSHOT</version>
<name>buisnesslogic</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<url>http://plannaplan.pl</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@ -25,11 +24,20 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>

View File

@ -1,5 +1,7 @@
package com.plannaplan.entities;
import java.sql.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
@ -14,11 +16,35 @@ public class User {
private Long id;
private String name;
private String surname;
private String email;
private UserRoles role;
private String token;
private Date tokenCreatedDate;
public User() {
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getTokenCreatedDate() {
return tokenCreatedDate;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.tokenCreatedDate = new Date(System.currentTimeMillis());
this.token = token;
}
public String getName() {
return name;
}

View File

@ -0,0 +1,13 @@
package com.plannaplan.exceptions;
public class UserNotFoundException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public UserNotFoundException(String message) {
super(message);
}
}

View File

@ -9,6 +9,6 @@ import org.springframework.stereotype.Repository;
@Repository
public interface CourseRepository extends JpaRepository<Course, Long> {
@Query(value = "SELECT * FROM course WHERE name = :name", nativeQuery = true)
@Query("FROM Course WHERE name = ?1")
Course findByName(@Param("name") String name);
}

View File

@ -11,10 +11,10 @@ import org.springframework.stereotype.Repository;
@Repository
public interface GroupRepository extends JpaRepository<Groups, Long> {
@Query(value = "SELECT * FROM groups WHERE time = :time AND room = :room AND capacity = :capacity ", nativeQuery = true)
@Query("FROM Groups WHERE time = ?1 AND room = ?2 AND capacity = ?3")
Groups find(@Param("time") int time, @Param("room") String room, @Param("capacity") int capacity);
@Query(value = "SELECT * FROM groups WHERE course_id = :id", nativeQuery = true)
@Query("FROM Groups WHERE course_id = ?1")
List<Groups> getByCourse(@Param("id") Long id);
}

View File

@ -9,6 +9,6 @@ import org.springframework.stereotype.Repository;
@Repository
public interface LecturerRepository extends JpaRepository<Lecturer, Long> {
@Query(value = "SELECT * FROM lecturer WHERE name = :name AND surname = :surname AND title = :title ", nativeQuery = true)
@Query("FROM Lecturer WHERE title = ?1 AND name = ?2 AND surname = ?3")
Lecturer find(@Param("title") String title, @Param("name") String name, @Param("surname") String surname);
}

View File

@ -3,9 +3,15 @@ package com.plannaplan.repositories;
import com.plannaplan.entities.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
@Query("FROM User WHERE email = ?1")
User getByAuthority(@Param("authority") String authority);
@Query("FROM User WHERE token = ?1")
User getByToken(@Param("token") String token);
}

View File

@ -24,4 +24,12 @@ public class CourseService {
public void save(Course course) {
this.repo.save(course);
}
public void delete(Course course){
this.repo.delete(course);
}
public int getCoursesAmmount(){
return (int)this.repo.count();
}
}

View File

@ -27,4 +27,12 @@ public class GroupService {
public void save(Groups group) {
this.repo.save(group);
}
public void delete(Groups groups){
this.repo.delete(groups);
}
public int getGroupsAmmount(){
return (int)this.repo.count();
}
}

View File

@ -18,4 +18,12 @@ public class LecturerService {
public void save(Lecturer lecturer) {
repo.save(lecturer);
}
public void delete(Lecturer lecturer) {
repo.delete(lecturer);
}
public int getLecturersAmmount(){
return (int)this.repo.count();
}
}

View File

@ -1,6 +1,10 @@
package com.plannaplan.services;
import java.util.UUID;
import com.plannaplan.abstracts.EventWatcher;
import com.plannaplan.entities.User;
import com.plannaplan.exceptions.UserNotFoundException;
import com.plannaplan.repositories.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
@ -15,4 +19,27 @@ public class UserService extends EventWatcher {
super();
}
public String login(String authority) throws UserNotFoundException {
User user = this.repo.getByAuthority(authority.replace("\n", "").trim());
if (user == null) {
throw new UserNotFoundException("Can not find user with given authority");
}
String token = UUID.randomUUID().toString();
user.setToken(token);
this.repo.save(user);
return token;
}
public void save(User user) {
this.repo.save(user);
}
public User getUserByEmail(String email) {
return this.repo.getByAuthority(email.replace("\n", "").trim());
}
public User getByToken(String token) {
return this.repo.getByToken(token);
}
}

View File

@ -1,5 +1,5 @@
package com.plannaplan.types;
public enum UserRoles {
STUDENT, DEANERY, ADMIN
STUDENT, DEANERY, ADMIN, TEST_USER
}

View File

@ -0,0 +1,8 @@
package com.plannaplan;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class TestApplication {
}

View File

@ -1,19 +1,52 @@
package com.plannaplan.configutils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.Assert.assertTrue;
import java.io.InputStream;
import com.plannaplan.models.FileData;
import com.plannaplan.Configurator;
import com.plannaplan.models.ConfigData;
import com.plannaplan.services.CourseService;
import com.plannaplan.services.GroupService;
import com.plannaplan.services.LecturerService;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration
public class FileToDatabaseMigratorTest {
private static String FILE_NAME = "Zajecia.xlsx";
@Autowired
private Configurator restTemplate;
@Autowired
private CourseService courseService;
@Autowired
private GroupService groupService;
@Autowired
private LecturerService lecturerService;
@Test
public void shouldInsertToDatabase() {
// FileToDatabaseMigrator migrator = new FileToDatabaseMigrator();
// InputStream inputStream =
// getClass().getClassLoader().getResourceAsStream("Zajecia.xlsx");
// FileReader r = new FileReader(inputStream);
// FileData d = r.read();
// migrator.migrate(d);
public void shouldImportDataFromFileToDatabase() throws Exception {
final InputStream inputStream = getClass().getClassLoader().getResourceAsStream(FILE_NAME);
final ConfigData data = new ConfigData(null, null, inputStream);
this.restTemplate.config(data);
int courses_ammount = this.courseService.getCoursesAmmount();
int groups_ammount = this.groupService.getGroupsAmmount();
int lecturers_ammount = this.lecturerService.getLecturersAmmount();
assertTrue(courses_ammount > 0 && groups_ammount > 0 && lecturers_ammount > 0);
}
}

View File

@ -0,0 +1,37 @@
package com.plannaplan.services;
import static org.junit.Assert.assertTrue;
import com.plannaplan.entities.Course;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration
public class CourseServiceTest {
@Autowired
private CourseService courseService;
@Test
public void createAndDeleteCourse() {
Course course;
int startAmmount = this.courseService.getCoursesAmmount();
// Create course
course = new Course();
course.setName("Testowy kurs");
course.setSymbol("TK");
courseService.save(course);
assertTrue(this.courseService.getCoursesAmmount() > startAmmount);
// Delete course
courseService.delete(course);
assertTrue(this.courseService.getCoursesAmmount() == startAmmount);
}
}

View File

@ -0,0 +1,37 @@
package com.plannaplan.services;
import static org.junit.Assert.assertTrue;
import com.plannaplan.entities.Groups;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration
public class GroupServiceTest {
@Autowired
private GroupService groupService;
@Test
public void createAndDeleteGroup() {
Groups group;
int startAmmount = this.groupService.getGroupsAmmount();
//Create group
group = new Groups();
group.setRoom("A1");
groupService.save(group);
assertTrue(this.groupService.getGroupsAmmount() > startAmmount);
// Delete course
groupService.delete(group);
assertTrue(this.groupService.getGroupsAmmount() == startAmmount);
}
}

View File

@ -0,0 +1,38 @@
package com.plannaplan.services;
import static org.junit.Assert.assertTrue;
import com.plannaplan.entities.Lecturer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration
public class LecturerServiceTest {
@Autowired
private LecturerService lecturerService;
@Test
public void createAndDeleteLecturer(){
Lecturer lecturer;
int startAmmount = this.lecturerService.getLecturersAmmount();
// Create lecturer
lecturer = new Lecturer();
lecturer.setName("Tomasz");
lecturer.setSurname("Kowalski");
lecturer.setTitle("prof.");
lecturerService.save(lecturer);
assertTrue(this.lecturerService.getLecturersAmmount() > startAmmount);
// Delete lecturer
lecturerService.delete(lecturer);
assertTrue(this.lecturerService.getLecturersAmmount() == startAmmount);
}
}

View File

@ -0,0 +1,64 @@
package com.plannaplan.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import static org.junit.jupiter.api.Assertions.assertTrue;
import com.plannaplan.entities.User;
import com.plannaplan.exceptions.UserNotFoundException;
import com.plannaplan.types.UserRoles;
import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.runner.RunWith;
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration
@TestMethodOrder(OrderAnnotation.class)
public class UserServiceTest {
public static String TEST_USER_MAIL = "noteexisitingmail@notexistingdomain.com";
public static String TEST_USER_NAME = "Tom";
public static String TEST_USER_SUERNAME = "Kovalsky";
@Autowired
UserService userService;
@Before
public void initialize() {
User testUser = new User();
testUser.setEmail(TEST_USER_MAIL);
testUser.setName(TEST_USER_NAME);
testUser.setSurname(TEST_USER_SUERNAME);
testUser.setRole(UserRoles.TEST_USER);
this.userService.save(testUser);
}
@Test
public void shouldReturnToken() {
try {
String token = this.userService.login(TEST_USER_MAIL);
System.out.println("Returned token: " + token);
assertTrue(token != null);
assertTrue(this.userService.getUserByEmail(TEST_USER_MAIL).getToken() != null);
} catch (UserNotFoundException e) {
e.printStackTrace();
assertTrue(false);
}
}
@Test
public void shouldThrowException() {
try {
this.userService.login("thiseamilisnotindatabase@gmail.com");
assertTrue(false);
} catch (UserNotFoundException e) {
assertTrue(true);
}
}
}

View File

@ -1,11 +1,12 @@
# Dokumetacja API
| Api | Zadania endpointa |
| ---------------------------------------------- | ---------------------------------------------------------- |
| [/config](#config) | Załadowanie konfiguracji startowej do aplikacji PlanNaPlan |
| [/getCoursesWithGroups](#getcourseswithgroups) | Zwrócenie wszytskich kursów razem z grupami |
| [/getCourseGroups](#getcoursegroups) | Zwrócenie grup dla danego kursu |
| [/getCourses](#getcourses) | Zwrócenie wszystkich kursów |
| Api | Zadania endpointa |
| ------------------------------------------------------------- | ---------------------------------------------------------------------------- |
| [/api/v1/configurator/config](#config) | Załadowanie konfiguracji startowej do aplikacji PlanNaPlan |
| [/api/v1/courses/getCoursesWithGroups](#getcourseswithgroups) | Zwrócenie wszytskich kursów razem z grupami |
| [/api/v1/groups/getCourseGroups](#getcoursegroups) | Zwrócenie grup dla danego kursu |
| [/api/v1/courses/getCourses](#getcourses) | Zwrócenie wszystkich kursów |
| [/token](#token) | Wymienia ticket z CAS-a na token ktorym beda autoryzowane chronione requesty |
## config
@ -30,7 +31,7 @@ Endpoint konfigurujacy caly system i importujacy dane do bazy.
Source code: [link](../restservice/src/main/java/com/plannaplan/controllers/getCoursesWithGroups.java)
```
GET /getCoursesWithGroups
GET /api/v1/courses/getCoursesWithGroups
```
#### Opis
@ -42,7 +43,7 @@ Zwraca wszystkie dostepne kursy wraz z listą grup.
Source code: [link](../restservice/src/main/java/com/plannaplan/controllers/GroupController.java)
```
GET /getCourseGroups
GET /api/v1/groups/getCourseGroups
```
#### Opis
@ -61,9 +62,27 @@ Zwraca wszytskie grupy dla danego kursu.
Source code: [link](../restservice/src/main/java/com/plannaplan/controllers/CoursesController.java)
```
GET /getCourses
GET /api/v1/courses/getCourses
```
#### Opis
Zwraca wszystkie dostepne kursy.
## token
Source code: [link](../restservice/src/main/java/com/plannaplan/controllers/TokenController.java)
```
GET /token?ticket=ST-668405-W0gfvSVDRBdMUWLweKzv-cas.amu.edu.pl
```
#### Opis
Po odpytaniu tego endpointa z podanym ticketem system zrobi nma nim validate i dostanie uzytkownika dla ktorego zostal on wygenerowany. System utworzy dla niego access token i go zwroci w odpowiedzi
#### Parametry
| Type | Name | Consumes | Opis | Type |
| ----------- | ------------------------- | -------- | --------------------------------------- | ------ |
| Query Param | **ticket** </br> required | - | ticket uzyskany z logowania poprzez CAS | string |

View File

@ -31,11 +31,23 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
@ -48,6 +60,12 @@
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<artifactId>buisnesslogic</artifactId>
<groupId>com.plannaplan</groupId>

View File

@ -1,15 +1,38 @@
package com.plannaplan;
import com.plannaplan.entities.User;
import com.plannaplan.services.UserService;
import com.plannaplan.types.UserRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
@SpringBootApplication
public class App {
public final static String API_VERSION = "v1";
@Autowired
UserService userService;
public static void main(String[] args) {
Logo logo = new Logo("beta");
System.out.println(logo.getLogo());
System.out.println("|=============================================================================================|");
System.out.println(
"|=============================================================================================|");
SpringApplication.run(App.class, args);
}
@EventListener(ApplicationReadyEvent.class)
public void importData() {
User testUser = new User();
testUser.setEmail("filizy@st.amu.edu.pl");
testUser.setName("Filip");
testUser.setSurname("Izydorczyk");
testUser.setRole(UserRoles.STUDENT);
this.userService.save(testUser);
}
}

View File

@ -5,6 +5,7 @@ import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import com.plannaplan.App;
import com.plannaplan.Controller;
import com.plannaplan.models.ConfigData;
@ -12,11 +13,13 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
@RestController
@CrossOrigin
@RequestMapping("/api/" + App.API_VERSION + "/configurator")
public class ConfigController {
@Autowired

View File

@ -5,6 +5,7 @@ import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import com.plannaplan.App;
import com.plannaplan.entities.Course;
import com.plannaplan.entities.Groups;
import com.plannaplan.services.CourseService;
@ -15,21 +16,23 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController
@CrossOrigin
@RequestMapping("/api/" + App.API_VERSION + "/courses")
public class CoursesController {
@Autowired
private CourseService courseService;
@GetMapping("/getCourses")
public ResponseEntity<List<Dictionary<String,Object>>> getMethodName() {
public ResponseEntity<List<Dictionary<String, Object>>> getMethodName() {
List<Course> courses = this.courseService.getAllCourses();
List<Dictionary<String,Object>> response = new ArrayList<>();
for(Course c : courses){
List<Dictionary<String, Object>> response = new ArrayList<>();
for (Course c : courses) {
Dictionary<String, Object> element = new Hashtable<>();
element.put("id", c.getId());
element.put("name",c.getName());
element.put("name", c.getName());
response.add(element);
}
@ -37,16 +40,16 @@ public class CoursesController {
}
@GetMapping("/getCoursesWithGroups")
public ResponseEntity<List<Dictionary<String,Object>>> getCoursesWithGroups() {
public ResponseEntity<List<Dictionary<String, Object>>> getCoursesWithGroups() {
List<Course> courses = this.courseService.getAllCourses();
List<Dictionary<String,Object>> response = new ArrayList<>();
for(Course c : courses){
List<Dictionary<String, Object>> response = new ArrayList<>();
for (Course c : courses) {
Dictionary<String, Object> element = new Hashtable<>();
element.put("id", c.getId());
element.put("name",c.getName());
List<Dictionary<String,Object>> groups = new ArrayList<>();
for(Groups g : c.getGroups()){
Dictionary<String,Object> group = new Hashtable<>();
element.put("name", c.getName());
List<Dictionary<String, Object>> groups = new ArrayList<>();
for (Groups g : c.getGroups()) {
Dictionary<String, Object> group = new Hashtable<>();
group.put("id", g.getId());
group.put("day", g.getDay().label);
group.put("time", g.getTimeString());

View File

@ -5,6 +5,7 @@ import java.util.Dictionary;
import java.util.Hashtable;
import java.util.List;
import com.plannaplan.App;
import com.plannaplan.entities.Groups;
import com.plannaplan.services.GroupService;
@ -13,21 +14,23 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
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;
@RestController
@CrossOrigin
@RequestMapping("/api/" + App.API_VERSION + "/groups")
public class GroupController {
@Autowired
private GroupService groupService;
@GetMapping("/getCourseGroups")
public ResponseEntity<List<Dictionary<String, Object>>> getCourses(@RequestParam("id") Long id, @RequestParam(name="capacity", defaultValue="true") Boolean capacity){
public ResponseEntity<List<Dictionary<String, Object>>> getCourses(@RequestParam("id") Long id,
@RequestParam(name = "capacity", defaultValue = "true") Boolean capacity) {
List<Groups> groups = this.groupService.getGroupsByCourse(id);
List<Dictionary<String, Object>> response = new ArrayList<>();
for (Groups g : groups) {
Dictionary<String, Object> group = new Hashtable<>();
group.put("id", g.getId());

View File

@ -0,0 +1,42 @@
package com.plannaplan.controllers;
import com.plannaplan.exceptions.UserNotFoundException;
import com.plannaplan.security.CasValidationExcepiton;
import com.plannaplan.security.CasValidator;
import com.plannaplan.services.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin
public class TokenController {
public static String SERVICE_URL = "http://localhost:3000";
@Autowired
private UserService userService;
@GetMapping("/token")
public ResponseEntity<String> getToken(@RequestParam("ticket") final String ticket) {
CasValidator validator = new CasValidator(SERVICE_URL, ticket);
try {
String authority = validator.validate();
String token = this.userService.login(authority);
return new ResponseEntity<>(token, HttpStatus.OK);
} catch (CasValidationExcepiton e) {
return new ResponseEntity<>("Wrong ticket", HttpStatus.UNAUTHORIZED);
} catch (UserNotFoundException e) {
return new ResponseEntity<>("User not found", HttpStatus.NOT_FOUND);
} catch (Exception e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}

View File

@ -0,0 +1,49 @@
package com.plannaplan.security;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.RequestMatcher;
import static org.springframework.http.HttpHeaders.AUTHORIZATION;
public class AuthenticationFilter extends AbstractAuthenticationProcessingFilter {
AuthenticationFilter(final RequestMatcher requiresAuth) {
super(requiresAuth);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
String token = request.getHeader(AUTHORIZATION);
if (token == null) {
token = "";
} else {
token = StringUtils.removeStart(token, "Bearer").trim();
}
Authentication requestAuthentication = new UsernamePasswordAuthenticationToken(token, token);
return getAuthenticationManager().authenticate(requestAuthentication);
}
@Override
protected void successfulAuthentication(final HttpServletRequest request, final HttpServletResponse response,
final FilterChain chain, final Authentication authResult) throws IOException, ServletException {
SecurityContextHolder.getContext().setAuthentication(authResult);
chain.doFilter(request, response);
}
}

View File

@ -0,0 +1,91 @@
package com.plannaplan.security;
import java.util.Collection;
import com.plannaplan.entities.User;
import com.plannaplan.services.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
@Component
public class AuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
@Autowired
private UserService userService;
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails,
UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
// TODO Auto-generated method stub
}
@Override
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
throws AuthenticationException {
String token = authentication.getCredentials().toString();
User user = this.userService.getByToken(token);
if (user == null) {
throw new UsernameNotFoundException("Cannot find user with authentication token=" + token);
}
UserDetails response = new UserDetails() {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getPassword() {
return null;
}
@Override
public String getUsername() {
return user.getName() + " " + user.getSurname();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean isEnabled() {
return true;
}
};
return response;
}
}

View File

@ -0,0 +1,13 @@
package com.plannaplan.security;
public class CasValidationExcepiton extends RuntimeException {
/**
*
*/
private static final long serialVersionUID = 1L;
public CasValidationExcepiton(String s) {
super(s);
}
}

View File

@ -0,0 +1,45 @@
package com.plannaplan.security;
import java.net.URLEncoder;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class CasValidator {
private static String CAS_URL = "https://cas.amu.edu.pl/cas";
private final CloseableHttpClient httpClient = HttpClients.createDefault();
private String service;
private String ticket;
public CasValidator(String service, String ticket) {
this.service = service;
this.ticket = ticket;
}
public String validate() throws Exception, CasValidationExcepiton{
HttpGet request = new HttpGet(CasValidator.CAS_URL + "/validate?service="
+ URLEncoder.encode(this.service, "UTF-8") + "&ticket=" + URLEncoder.encode(this.ticket, "UTF-8"));
try (CloseableHttpResponse response = httpClient.execute(request)) {
HttpEntity entity = response.getEntity();
String result = null;
if (entity != null) {
// return it as a String
result = EntityUtils.toString(entity);
if(result.replace("\n", "").trim().equals("no")){
throw new CasValidationExcepiton("Validation failed");
}
}
String res = result.substring(result.indexOf('\n') + 1);
return res;
}
}
}

View File

@ -0,0 +1,64 @@
package com.plannaplan.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.http.HttpStatus;
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final RequestMatcher PROTECTED_URLS = new OrRequestMatcher(new AntPathRequestMatcher("/api/**"));
AuthenticationProvider provider;
public WebSecurityConfig(final AuthenticationProvider authenticationProvider) {
super();
this.provider = authenticationProvider;
}
@Override
protected void configure(final AuthenticationManagerBuilder auth) {
auth.authenticationProvider(provider);
}
@Override
public void configure(final WebSecurity webSecurity) {
webSecurity.ignoring().antMatchers("/token**").antMatchers("/api/v1/courses/getCourses")
.antMatchers("/api/v1/groups/getCourseGroups").antMatchers("/api/v1/courses/getCoursesWithGroups");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().formLogin().disable().httpBasic().disable().logout().disable().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().exceptionHandling().and()
.authenticationProvider(provider)
.addFilterBefore(authenticationFilter(), AnonymousAuthenticationFilter.class).authorizeRequests()
.anyRequest().authenticated();
}
AuthenticationFilter authenticationFilter() throws Exception {
final AuthenticationFilter filter = new AuthenticationFilter(PROTECTED_URLS);
filter.setAuthenticationManager(authenticationManager());
return filter;
}
@Bean
AuthenticationEntryPoint forbiddenEntryPoint() {
return new HttpStatusEntryPoint(HttpStatus.FORBIDDEN);
}
}

View File

@ -0,0 +1,40 @@
package com.plannaplan.security;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.Ignore;
import org.junit.Test;
public class CasValidatorTest {
@Test
@Ignore
public void shouldValidateTicket() {
//you need to privide fresh ticket to make this test pass that's why it is marked as ignored
CasValidator validator = new CasValidator("http://localhost:3000",
"ST-572267-cbgKrcJLd0tdCubeLqdW-cas.amu.edu.pl");
try {
System.out.println(validator.validate());
} catch (Exception e) {
e.printStackTrace();
assertTrue(false);
}
}
@Test
public void shouldNotValidateTicket() {
//you need to privide fresh ticket to make this test pass that's why it is marked as ignored
CasValidator validator = new CasValidator("http://localhost:3000",
"notticket");
try {
assertTrue(validator.validate().trim().equals(""));
}
catch (CasValidationExcepiton e){
assertTrue(true);
}
catch (Exception e) {
e.printStackTrace();
assertTrue(false);
}
}
}