Merge pull request 'security' (#9) from security into master
Reviewed-on: http://git.plannaplan.pl/filipizydorczyk/backend/pulls/9
This commit is contained in:
commit
579da3f038
@ -1,5 +1,7 @@
|
|||||||
package com.plannaplan.entities;
|
package com.plannaplan.entities;
|
||||||
|
|
||||||
|
import java.sql.Date;
|
||||||
|
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.GenerationType;
|
import javax.persistence.GenerationType;
|
||||||
@ -14,11 +16,35 @@ public class User {
|
|||||||
private Long id;
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
private String surname;
|
private String surname;
|
||||||
|
private String email;
|
||||||
private UserRoles role;
|
private UserRoles role;
|
||||||
|
private String token;
|
||||||
|
private Date tokenCreatedDate;
|
||||||
|
|
||||||
public User() {
|
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() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,9 +3,15 @@ package com.plannaplan.repositories;
|
|||||||
import com.plannaplan.entities.User;
|
import com.plannaplan.entities.User;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
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;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
public interface UserRepository extends JpaRepository<User, Long> {
|
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);
|
||||||
}
|
}
|
@ -1,6 +1,10 @@
|
|||||||
package com.plannaplan.services;
|
package com.plannaplan.services;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import com.plannaplan.abstracts.EventWatcher;
|
import com.plannaplan.abstracts.EventWatcher;
|
||||||
|
import com.plannaplan.entities.User;
|
||||||
|
import com.plannaplan.exceptions.UserNotFoundException;
|
||||||
import com.plannaplan.repositories.UserRepository;
|
import com.plannaplan.repositories.UserRepository;
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -15,4 +19,27 @@ public class UserService extends EventWatcher {
|
|||||||
super();
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
package com.plannaplan.types;
|
package com.plannaplan.types;
|
||||||
|
|
||||||
public enum UserRoles {
|
public enum UserRoles {
|
||||||
STUDENT, DEANERY, ADMIN
|
STUDENT, DEANERY, ADMIN, TEST_USER
|
||||||
}
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
docs/api.md
35
docs/api.md
@ -1,11 +1,12 @@
|
|||||||
# Dokumetacja API
|
# Dokumetacja API
|
||||||
|
|
||||||
| Api | Zadania endpointa |
|
| Api | Zadania endpointa |
|
||||||
| ---------------------------------------------- | ---------------------------------------------------------- |
|
| ------------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
||||||
| [/config](#config) | Załadowanie konfiguracji startowej do aplikacji PlanNaPlan |
|
| [/api/v1/configurator/config](#config) | Załadowanie konfiguracji startowej do aplikacji PlanNaPlan |
|
||||||
| [/getCoursesWithGroups](#getcourseswithgroups) | Zwrócenie wszytskich kursów razem z grupami |
|
| [/api/v1/courses/getCoursesWithGroups](#getcourseswithgroups) | Zwrócenie wszytskich kursów razem z grupami |
|
||||||
| [/getCourseGroups](#getcoursegroups) | Zwrócenie grup dla danego kursu |
|
| [/api/v1/groups/getCourseGroups](#getcoursegroups) | Zwrócenie grup dla danego kursu |
|
||||||
| [/getCourses](#getcourses) | Zwrócenie wszystkich kursów |
|
| [/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
|
## 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)
|
Source code: [link](../restservice/src/main/java/com/plannaplan/controllers/getCoursesWithGroups.java)
|
||||||
|
|
||||||
```
|
```
|
||||||
GET /getCoursesWithGroups
|
GET /api/v1/courses/getCoursesWithGroups
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Opis
|
#### 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)
|
Source code: [link](../restservice/src/main/java/com/plannaplan/controllers/GroupController.java)
|
||||||
|
|
||||||
```
|
```
|
||||||
GET /getCourseGroups
|
GET /api/v1/groups/getCourseGroups
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Opis
|
#### Opis
|
||||||
@ -61,9 +62,27 @@ Zwraca wszytskie grupy dla danego kursu.
|
|||||||
Source code: [link](../restservice/src/main/java/com/plannaplan/controllers/CoursesController.java)
|
Source code: [link](../restservice/src/main/java/com/plannaplan/controllers/CoursesController.java)
|
||||||
|
|
||||||
```
|
```
|
||||||
GET /getCourses
|
GET /api/v1/courses/getCourses
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Opis
|
#### Opis
|
||||||
|
|
||||||
Zwraca wszystkie dostepne kursy.
|
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 |
|
||||||
|
@ -31,11 +31,23 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
<version>4.5.10</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
<version>2.3.3.RELEASE</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
@ -48,6 +60,12 @@
|
|||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-lang3</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<artifactId>buisnesslogic</artifactId>
|
<artifactId>buisnesslogic</artifactId>
|
||||||
<groupId>com.plannaplan</groupId>
|
<groupId>com.plannaplan</groupId>
|
||||||
|
@ -1,15 +1,38 @@
|
|||||||
package com.plannaplan;
|
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.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||||
|
import org.springframework.context.event.EventListener;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class App {
|
public class App {
|
||||||
|
|
||||||
|
public final static String API_VERSION = "v1";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
UserService userService;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
Logo logo = new Logo("beta");
|
Logo logo = new Logo("beta");
|
||||||
System.out.println(logo.getLogo());
|
System.out.println(logo.getLogo());
|
||||||
System.out.println("|=============================================================================================|");
|
System.out.println(
|
||||||
|
"|=============================================================================================|");
|
||||||
SpringApplication.run(App.class, args);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.plannaplan.App;
|
||||||
import com.plannaplan.Controller;
|
import com.plannaplan.Controller;
|
||||||
import com.plannaplan.models.ConfigData;
|
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.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
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.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@CrossOrigin
|
@CrossOrigin
|
||||||
|
@RequestMapping("/api/" + App.API_VERSION + "/configurator")
|
||||||
public class ConfigController {
|
public class ConfigController {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
|
@ -5,6 +5,7 @@ import java.util.Dictionary;
|
|||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.plannaplan.App;
|
||||||
import com.plannaplan.entities.Course;
|
import com.plannaplan.entities.Course;
|
||||||
import com.plannaplan.entities.Groups;
|
import com.plannaplan.entities.Groups;
|
||||||
import com.plannaplan.services.CourseService;
|
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.CrossOrigin;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@CrossOrigin
|
@CrossOrigin
|
||||||
|
@RequestMapping("/api/" + App.API_VERSION + "/courses")
|
||||||
public class CoursesController {
|
public class CoursesController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private CourseService courseService;
|
private CourseService courseService;
|
||||||
|
|
||||||
@GetMapping("/getCourses")
|
@GetMapping("/getCourses")
|
||||||
public ResponseEntity<List<Dictionary<String,Object>>> getMethodName() {
|
public ResponseEntity<List<Dictionary<String, Object>>> getMethodName() {
|
||||||
List<Course> courses = this.courseService.getAllCourses();
|
List<Course> courses = this.courseService.getAllCourses();
|
||||||
List<Dictionary<String,Object>> response = new ArrayList<>();
|
List<Dictionary<String, Object>> response = new ArrayList<>();
|
||||||
for(Course c : courses){
|
for (Course c : courses) {
|
||||||
Dictionary<String, Object> element = new Hashtable<>();
|
Dictionary<String, Object> element = new Hashtable<>();
|
||||||
element.put("id", c.getId());
|
element.put("id", c.getId());
|
||||||
element.put("name",c.getName());
|
element.put("name", c.getName());
|
||||||
response.add(element);
|
response.add(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,16 +40,16 @@ public class CoursesController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/getCoursesWithGroups")
|
@GetMapping("/getCoursesWithGroups")
|
||||||
public ResponseEntity<List<Dictionary<String,Object>>> getCoursesWithGroups() {
|
public ResponseEntity<List<Dictionary<String, Object>>> getCoursesWithGroups() {
|
||||||
List<Course> courses = this.courseService.getAllCourses();
|
List<Course> courses = this.courseService.getAllCourses();
|
||||||
List<Dictionary<String,Object>> response = new ArrayList<>();
|
List<Dictionary<String, Object>> response = new ArrayList<>();
|
||||||
for(Course c : courses){
|
for (Course c : courses) {
|
||||||
Dictionary<String, Object> element = new Hashtable<>();
|
Dictionary<String, Object> element = new Hashtable<>();
|
||||||
element.put("id", c.getId());
|
element.put("id", c.getId());
|
||||||
element.put("name",c.getName());
|
element.put("name", c.getName());
|
||||||
List<Dictionary<String,Object>> groups = new ArrayList<>();
|
List<Dictionary<String, Object>> groups = new ArrayList<>();
|
||||||
for(Groups g : c.getGroups()){
|
for (Groups g : c.getGroups()) {
|
||||||
Dictionary<String,Object> group = new Hashtable<>();
|
Dictionary<String, Object> group = new Hashtable<>();
|
||||||
group.put("id", g.getId());
|
group.put("id", g.getId());
|
||||||
group.put("day", g.getDay().label);
|
group.put("day", g.getDay().label);
|
||||||
group.put("time", g.getTimeString());
|
group.put("time", g.getTimeString());
|
||||||
|
@ -5,6 +5,7 @@ import java.util.Dictionary;
|
|||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.plannaplan.App;
|
||||||
import com.plannaplan.entities.Groups;
|
import com.plannaplan.entities.Groups;
|
||||||
import com.plannaplan.services.GroupService;
|
import com.plannaplan.services.GroupService;
|
||||||
|
|
||||||
@ -13,21 +14,23 @@ import org.springframework.http.HttpStatus;
|
|||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
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.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@CrossOrigin
|
@CrossOrigin
|
||||||
|
@RequestMapping("/api/" + App.API_VERSION + "/groups")
|
||||||
public class GroupController {
|
public class GroupController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private GroupService groupService;
|
private GroupService groupService;
|
||||||
|
|
||||||
@GetMapping("/getCourseGroups")
|
@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<Groups> groups = this.groupService.getGroupsByCourse(id);
|
||||||
List<Dictionary<String, Object>> response = new ArrayList<>();
|
List<Dictionary<String, Object>> response = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
for (Groups g : groups) {
|
for (Groups g : groups) {
|
||||||
Dictionary<String, Object> group = new Hashtable<>();
|
Dictionary<String, Object> group = new Hashtable<>();
|
||||||
group.put("id", g.getId());
|
group.put("id", g.getId());
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user