Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b8dab8846b | ||
|
6233af8e11 | ||
|
3a861f03c3 | ||
|
9671929787 | ||
|
5503210aeb | ||
|
2f164e7922 | ||
|
1d5744c16e | ||
|
04c6247522 | ||
|
096386e7aa |
6
pom.xml
6
pom.xml
@ -33,7 +33,11 @@
|
|||||||
<artifactId>basiclti-util</artifactId>
|
<artifactId>basiclti-util</artifactId>
|
||||||
<version>1.1.2</version>
|
<version>1.1.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.xml.parsers</groupId>
|
||||||
|
<artifactId>jaxp-api</artifactId>
|
||||||
|
<version>1.4.5</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>mysql</groupId>
|
<groupId>mysql</groupId>
|
||||||
<artifactId>mysql-connector-java</artifactId>
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
@ -8,9 +8,11 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|||||||
public class MvcConfig implements WebMvcConfigurer {
|
public class MvcConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
public void addViewControllers(ViewControllerRegistry registry) {
|
public void addViewControllers(ViewControllerRegistry registry) {
|
||||||
registry.addViewController("/home").setViewName("home");
|
registry.addViewController("/courses/addCourse").setViewName("addCourse");
|
||||||
registry.addViewController("/").setViewName("home");
|
registry.addViewController("/").setViewName("start");
|
||||||
registry.addViewController("/login").setViewName("login");
|
registry.addViewController("/login").setViewName("login");
|
||||||
|
registry.addViewController("/start").setViewName("start");
|
||||||
|
registry.addViewController("/register").setViewName("register");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,43 +1,67 @@
|
|||||||
package com.wmi.lti.config;
|
package com.wmi.lti.config;
|
||||||
|
|
||||||
|
import com.wmi.lti.model.user.MyUserDetailsService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.context.annotation.Configuration;
|
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.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
import org.springframework.security.core.userdetails.User;
|
import org.springframework.security.core.userdetails.User;
|
||||||
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
|
@ComponentScan
|
||||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public void configAuthentication(final AuthenticationManagerBuilder auth) throws Exception {
|
||||||
|
auth.userDetailsService(userDetailsService()).passwordEncoder(new BCryptPasswordEncoder());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http
|
http.authorizeRequests()
|
||||||
.authorizeRequests()
|
.antMatchers( "/", "/courses/**").authenticated()
|
||||||
.antMatchers("/", "/home").permitAll()
|
.antMatchers( "/courses").authenticated()
|
||||||
.anyRequest().authenticated()
|
.antMatchers("/", "/register").permitAll()
|
||||||
|
.antMatchers("/", "/start").authenticated()
|
||||||
|
//.anyRequest().authenticated()
|
||||||
.and()
|
.and()
|
||||||
.formLogin()
|
.formLogin()
|
||||||
.loginPage("/login")
|
.loginPage("/login")
|
||||||
.permitAll()
|
.permitAll()
|
||||||
.and()
|
.and().
|
||||||
.logout()
|
// .logout()
|
||||||
.permitAll();
|
//.permitAll().
|
||||||
|
cors().and().
|
||||||
|
csrf().disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Override
|
@Override
|
||||||
public UserDetailsService userDetailsService() {
|
public UserDetailsService userDetailsService() {
|
||||||
UserDetails user =
|
/* UserDetails user =
|
||||||
User.withDefaultPasswordEncoder()
|
User.withDefaultPasswordEncoder()
|
||||||
.username("adrianw")
|
.username("adrianw")
|
||||||
.password("eduserwis1245")
|
.password("eduserwis1245")
|
||||||
.roles("USER")
|
.roles("USER")
|
||||||
.build();
|
.build();
|
||||||
|
*/
|
||||||
return new InMemoryUserDetailsManager(user);
|
return new MyUserDetailsService() {
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
54
src/main/java/com/wmi/lti/controllers/CourseController.java
Normal file
54
src/main/java/com/wmi/lti/controllers/CourseController.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package com.wmi.lti.controllers;
|
||||||
|
|
||||||
|
import com.wmi.lti.model.course.Course;
|
||||||
|
import com.wmi.lti.model.course.CourseRepository;
|
||||||
|
import com.wmi.lti.model.user.UserPrincipal;
|
||||||
|
import org.imsglobal.lti.launch.LtiOauthSigner;
|
||||||
|
import org.imsglobal.lti.launch.LtiSigner;
|
||||||
|
import org.imsglobal.lti.launch.LtiSigningException;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/courses")
|
||||||
|
public class CourseController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CourseRepository courseRepository;
|
||||||
|
|
||||||
|
@GetMapping("")
|
||||||
|
public String listCourses() {
|
||||||
|
|
||||||
|
//model.addAttribute("message", name);
|
||||||
|
|
||||||
|
return "start"; //view
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/addCourse")
|
||||||
|
public String addCourseView() {
|
||||||
|
return "addCourse"; //view
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("")
|
||||||
|
public String addCourse(
|
||||||
|
@RequestParam(name = "key", required = false, defaultValue = "")
|
||||||
|
String key, @RequestParam(name = "secret", required = false, defaultValue = "")
|
||||||
|
String secret, @RequestParam(name = "url", required = false, defaultValue = "")
|
||||||
|
String url, @RequestParam(name = "name", required = false, defaultValue = "")
|
||||||
|
String name, Model model) {
|
||||||
|
|
||||||
|
courseRepository.save(new Course(null, name, url, key, secret, null));
|
||||||
|
return "start"; //view
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
90
src/main/java/com/wmi/lti/controllers/GradeController.java
Normal file
90
src/main/java/com/wmi/lti/controllers/GradeController.java
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
package com.wmi.lti.controllers;
|
||||||
|
|
||||||
|
import com.wmi.lti.model.course.Course;
|
||||||
|
import com.wmi.lti.model.course.CourseRepository;
|
||||||
|
import com.wmi.lti.model.grade.Grade;
|
||||||
|
import com.wmi.lti.model.grade.GradeRepository;
|
||||||
|
import com.wmi.lti.model.user.User;
|
||||||
|
import com.wmi.lti.model.user.UserRepository;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
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.RestController;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
@RequestMapping("/grades")
|
||||||
|
@RestController
|
||||||
|
public class GradeController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private GradeRepository gradeRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserRepository userRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CourseRepository courseRepository;
|
||||||
|
|
||||||
|
@PostMapping("")
|
||||||
|
public String addCourse(@RequestParam(required = false) Map<String, String> args, HttpServletRequest request) throws IOException {
|
||||||
|
String gradeXML = extractPostRequestBody(request);
|
||||||
|
double gradeValue = Double.valueOf(gradeXML.split("<textString>")[1].split("</textString>")[0]);
|
||||||
|
String cell = gradeXML.split("<sourcedId>")[1].split("</sourcedId>")[0];
|
||||||
|
User user = userRepository.findByUsername(cell.replaceFirst("_.*", ""));
|
||||||
|
Course course = courseRepository.findFirstByName(cell.replaceFirst(".*_", ""));
|
||||||
|
|
||||||
|
Optional<Grade> gradeCheck = gradeRepository.findGradeByCourseAndUser(course, user);
|
||||||
|
Grade grade = gradeCheck.orElseGet(Grade::new);
|
||||||
|
grade.setCourse(course);
|
||||||
|
grade.setGrade(gradeValue);
|
||||||
|
grade.setUser(user);
|
||||||
|
gradeRepository.save(grade);
|
||||||
|
return response();
|
||||||
|
}
|
||||||
|
|
||||||
|
static String extractPostRequestBody(HttpServletRequest request) throws IOException {
|
||||||
|
if ("POST".equalsIgnoreCase(request.getMethod())) {
|
||||||
|
Scanner s = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A");
|
||||||
|
return s.hasNext() ? s.next() : "";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private String response(){
|
||||||
|
return "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||||
|
"<imsx_POXEnvelopeResponse xmlns=\"http://www.imsglobal.org/services/ltiv1p1/xsd/imsoms_v1p0\">\n" +
|
||||||
|
" <imsx_POXHeader>\n" +
|
||||||
|
" <imsx_POXResponseHeaderInfo>\n" +
|
||||||
|
" <imsx_version>V1.0</imsx_version>\n" +
|
||||||
|
" <imsx_messageIdentifier>4560</imsx_messageIdentifier>\n" +
|
||||||
|
" <imsx_statusInfo>\n" +
|
||||||
|
" <imsx_codeMajor>success</imsx_codeMajor>\n" +
|
||||||
|
" <imsx_severity>status</imsx_severity>\n" +
|
||||||
|
" <imsx_messageRefIdentifier>999999123</imsx_messageRefIdentifier>\n" +
|
||||||
|
" <imsx_operationRefIdentifier>replaceResult</imsx_operationRefIdentifier>\n" +
|
||||||
|
" </imsx_statusInfo>\n" +
|
||||||
|
" </imsx_POXResponseHeaderInfo>\n" +
|
||||||
|
" </imsx_POXHeader>\n" +
|
||||||
|
" <imsx_POXBody>\n" +
|
||||||
|
" <replaceResultResponse />\n" +
|
||||||
|
" </imsx_POXBody>\n" +
|
||||||
|
"</imsx_POXEnvelopeResponse>";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,20 +0,0 @@
|
|||||||
package com.wmi.lti.controllers;
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.ui.Model;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
|
|
||||||
@Controller
|
|
||||||
public class HomeController {
|
|
||||||
|
|
||||||
@GetMapping("/home")
|
|
||||||
public String home(
|
|
||||||
@RequestParam(name = "name", required = false, defaultValue = "")
|
|
||||||
String name, Model model) {
|
|
||||||
|
|
||||||
//model.addAttribute("message", name);
|
|
||||||
|
|
||||||
return "home"; //view
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,46 +1,80 @@
|
|||||||
package com.wmi.lti.controllers;
|
package com.wmi.lti.controllers;
|
||||||
|
|
||||||
|
import com.wmi.lti.model.course.Course;
|
||||||
|
import com.wmi.lti.model.course.CourseRepository;
|
||||||
|
import com.wmi.lti.model.grade.Grade;
|
||||||
|
import com.wmi.lti.model.grade.GradeDTO;
|
||||||
|
import com.wmi.lti.model.grade.GradeRepository;
|
||||||
|
import com.wmi.lti.model.user.User;
|
||||||
|
import com.wmi.lti.model.user.UserPrincipal;
|
||||||
|
import com.wmi.lti.model.user.UserRepository;
|
||||||
import org.imsglobal.lti.launch.LtiOauthSigner;
|
import org.imsglobal.lti.launch.LtiOauthSigner;
|
||||||
import org.imsglobal.lti.launch.LtiSigner;
|
import org.imsglobal.lti.launch.LtiSigner;
|
||||||
import org.imsglobal.lti.launch.LtiSigningException;
|
import org.imsglobal.lti.launch.LtiSigningException;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.core.userdetails.User;
|
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
import java.net.URLEncoder;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
public class StartController {
|
public class StartController {
|
||||||
|
|
||||||
@GetMapping("/start")
|
@Autowired
|
||||||
public String start(
|
private CourseRepository courseRepository;
|
||||||
@RequestParam(name = "key", required = false, defaultValue = "")
|
|
||||||
String key, @RequestParam(name = "secret", required = false, defaultValue = "")
|
|
||||||
String secret, @RequestParam(name = "url", required = false, defaultValue = "")
|
|
||||||
String url, Model model) {
|
|
||||||
|
|
||||||
LtiSigner signer = new LtiOauthSigner();
|
@Autowired
|
||||||
Map<String, String> parameters = new HashMap<>();
|
private UserRepository userRepository;
|
||||||
parameters.put("lti_message_type","basic-lti-launch-request");
|
|
||||||
parameters.put("lti_version", "LTI-1p0");
|
@Autowired
|
||||||
parameters.put("resource_link_id", "gsdgsdgsdgsdsgddsg3g3");
|
private GradeRepository gradeRepository;
|
||||||
//parameters.put("resource_link_id", ((User) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername());
|
|
||||||
try {
|
@GetMapping("")
|
||||||
Map<String, String> signedParameters = signer.signParameters(parameters, key, secret, url, "POST");
|
public String start(Model model){
|
||||||
String link = url + "?" + "oauth_nonce=" + signedParameters.get("oauth_nonce") + "&oauth_signature=" + signedParameters.get("oauth_signature") + "&oauth_consumer_key=" + signedParameters.get("oauth_consumer_key") + "&oauth_signature_method=" + signedParameters.get("oauth_signature_method") + "&oauth_timestamp=" + signedParameters.get("oauth_timestamp") + "&oauth_version=" + signedParameters.get("oauth_version") + "<i_message_type=" + signedParameters.get("lti_message_type") + "<i_version=" + signedParameters.get("lti_version") + "&resource_link_id=" + signedParameters.get("resource_link_id");
|
List<Course> courses = courseRepository.findAll();
|
||||||
model.addAttribute("parameters", signedParameters);
|
List<Course> coursesToReturn = new ArrayList<>();
|
||||||
model.addAttribute("launchUrl", link);
|
User user = userRepository.findByUsername(((UserPrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getUsername());
|
||||||
} catch (LtiSigningException e) {
|
for (Course course : courses) {
|
||||||
e.printStackTrace();
|
LtiSigner signer = new LtiOauthSigner();
|
||||||
|
Map<String, String> parameters = new HashMap<>();
|
||||||
|
parameters.put("lti_message_type", "basic-lti-launch-request");
|
||||||
|
parameters.put("lti_version", "LTI-1p0");
|
||||||
|
parameters.put("resource_link_id", user.getUsername() + "_" + course.getCourse_key());
|
||||||
|
parameters.put("user_id", user.getId().toString());
|
||||||
|
parameters.put("lis_person_name_given", user.getUsername());
|
||||||
|
parameters.put("tool_consumer_instance_name", "wmi.lti");
|
||||||
|
//parameters.put("target", "frame");
|
||||||
|
parameters.put("lis_outcome_service_url", "http://localhost:8080/grades");
|
||||||
|
parameters.put("lis_result_sourcedid", user.getUsername() + "_" + course.getCourse_key());
|
||||||
|
try {
|
||||||
|
Map<String, String> signedParameters = signer.signParameters(parameters, course.getCourse_key(), course.getSecret(), course.getUrl(), "POST");
|
||||||
|
/* String link = course.getUrl();
|
||||||
|
link += "?oauth_nonce=" + signedParameters.get("oauth_nonce") + "&oauth_signature=" + signedParameters.get("oauth_signature") + "&oauth_consumer_key=" + signedParameters.get("oauth_consumer_key") + "&oauth_signature_method=" + signedParameters.get("oauth_signature_method") + "&oauth_timestamp=" + signedParameters.get("oauth_timestamp") + "&oauth_version=" + signedParameters.get("oauth_version") + "<i_message_type=" + signedParameters.get("lti_message_type") + "<i_version=" + signedParameters.get("lti_version") + "&resource_link_id=" + signedParameters.get("resource_link_id") + "&user_id=" + signedParameters.get("user_id") + "&lis_person_name_given=" + signedParameters.get("lis_person_name_given") + "&tool_consumer_instance_name=" + signedParameters.get("tool_consumer_instance_name") + "&target=" + signedParameters.get("target");
|
||||||
|
*/
|
||||||
|
course.setSecret(null);
|
||||||
|
course.setSignedParameters(signedParameters);
|
||||||
|
coursesToReturn.add(course);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//model.addAttribute("message", name);
|
|
||||||
return "start"; //view
|
|
||||||
|
|
||||||
|
List<Grade> grades = gradeRepository.findAllByUser(user);
|
||||||
|
List<GradeDTO> gradeDTOS = new ArrayList<>();
|
||||||
|
for (Grade grade : grades){
|
||||||
|
gradeDTOS.add(new GradeDTO(grade.getCourse().getName(), grade.getGrade()* 100 + "%"));
|
||||||
|
}
|
||||||
|
|
||||||
|
model.addAttribute("courses", coursesToReturn);
|
||||||
|
model.addAttribute("grades", gradeDTOS);
|
||||||
|
return "start"; //view
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
38
src/main/java/com/wmi/lti/controllers/UserController.java
Normal file
38
src/main/java/com/wmi/lti/controllers/UserController.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package com.wmi.lti.controllers;
|
||||||
|
|
||||||
|
import com.wmi.lti.model.user.User;
|
||||||
|
import com.wmi.lti.model.user.UserRepository;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/users")
|
||||||
|
public class UserController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserRepository userRepository;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
|
@PostMapping("")
|
||||||
|
public String create(@RequestParam String username, @RequestParam String password, Model model) {
|
||||||
|
User user = new User();
|
||||||
|
user.setUsername(username);
|
||||||
|
user.setPassword(passwordEncoder.encode(password));
|
||||||
|
userRepository.save(user);
|
||||||
|
return "login";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/register")
|
||||||
|
public String getRegisterView() {
|
||||||
|
return "register";
|
||||||
|
}
|
||||||
|
}
|
43
src/main/java/com/wmi/lti/model/course/Course.java
Normal file
43
src/main/java/com/wmi/lti/model/course/Course.java
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
package com.wmi.lti.model.course;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Course {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private String course_key;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private String secret;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Transient
|
||||||
|
private Map<String, String> signedParameters;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.wmi.lti.model.course;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface CourseRepository extends JpaRepository<Course, Long> {
|
||||||
|
|
||||||
|
Course findFirstByName(String name);
|
||||||
|
|
||||||
|
}
|
41
src/main/java/com/wmi/lti/model/grade/Grade.java
Normal file
41
src/main/java/com/wmi/lti/model/grade/Grade.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package com.wmi.lti.model.grade;
|
||||||
|
|
||||||
|
import com.wmi.lti.model.course.Course;
|
||||||
|
import com.wmi.lti.model.user.User;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class Grade {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ManyToOne
|
||||||
|
private Course course;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ManyToOne
|
||||||
|
private User user;
|
||||||
|
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Double grade;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private String description;
|
||||||
|
}
|
14
src/main/java/com/wmi/lti/model/grade/GradeDTO.java
Normal file
14
src/main/java/com/wmi/lti/model/grade/GradeDTO.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package com.wmi.lti.model.grade;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class GradeDTO {
|
||||||
|
|
||||||
|
private String courseName;
|
||||||
|
private String score;
|
||||||
|
}
|
14
src/main/java/com/wmi/lti/model/grade/GradeRepository.java
Normal file
14
src/main/java/com/wmi/lti/model/grade/GradeRepository.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package com.wmi.lti.model.grade;
|
||||||
|
|
||||||
|
import com.wmi.lti.model.course.Course;
|
||||||
|
import com.wmi.lti.model.user.User;
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface GradeRepository extends JpaRepository<Grade, Long> {
|
||||||
|
Optional<Grade> findGradeByCourseAndUser(Course course, User user);
|
||||||
|
|
||||||
|
List<Grade> findAllByUser(User user);
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.wmi.lti.model.user;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class MyUserDetailsService implements UserDetailsService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserRepository userRepository;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserDetails loadUserByUsername(String username) {
|
||||||
|
User user = userRepository.findByUsername(username);
|
||||||
|
if (user == null) {
|
||||||
|
throw new UsernameNotFoundException(username);
|
||||||
|
}
|
||||||
|
return new UserPrincipal(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
src/main/java/com/wmi/lti/model/user/User.java
Normal file
28
src/main/java/com/wmi/lti/model/user/User.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package com.wmi.lti.model.user;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class User {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Column(nullable = false, unique = true)
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
}
|
49
src/main/java/com/wmi/lti/model/user/UserPrincipal.java
Normal file
49
src/main/java/com/wmi/lti/model/user/UserPrincipal.java
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package com.wmi.lti.model.user;
|
||||||
|
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
public class UserPrincipal implements UserDetails {
|
||||||
|
private User user;
|
||||||
|
|
||||||
|
public UserPrincipal(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return user.getPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return user.getUsername();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonExpired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonLocked() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCredentialsNonExpired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
9
src/main/java/com/wmi/lti/model/user/UserRepository.java
Normal file
9
src/main/java/com/wmi/lti/model/user/UserRepository.java
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package com.wmi.lti.model.user;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
|
||||||
|
public interface UserRepository extends JpaRepository<User, Long> {
|
||||||
|
|
||||||
|
User findByUsername(String username);
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
spring.jpa.hibernate.ddl-auto=update
|
spring.jpa.hibernate.ddl-auto=update
|
||||||
spring.datasource.url=jdbc:mysql://localhost:3306/lti
|
spring.datasource.url=jdbc:mysql://localhost:3307/lti
|
||||||
spring.datasource.username=lti
|
spring.datasource.username=lti
|
||||||
spring.datasource.password=YnBDC0hqqhKaxt94
|
spring.datasource.password=YnBDC0hqqhKaxt94
|
||||||
|
|
||||||
|
21
src/main/resources/templates/addCourse.html
Normal file
21
src/main/resources/templates/addCourse.html
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
|
||||||
|
<title>LTI</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" th:href="@{/css/main.css}"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
This is tool consumer for LTI<br>
|
||||||
|
<form th:action="@{/courses}" method="post">
|
||||||
|
<div><label> URL: <input type="text" name="url"/></label></div>
|
||||||
|
<div><label> Key: <input type="text" name="key"/></label></div>
|
||||||
|
<div><label> Secret: <input type="text" name="secret"/></label></div>
|
||||||
|
<div><label> Course name: <input type="text" name="name"/></label></div>
|
||||||
|
<div><input type="submit" value="Submit"/></div>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -1,15 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
||||||
|
|
||||||
<title>LTI</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" th:href="@{/css/main.css}"/>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
This is tool consumer for LTI<br>
|
|
||||||
<button type="button" th:onclick="|window.location.href='/start?url=https://cloud.scorm.com/sc/blti&key=7ec922aa-7095-497d-a1b8-5a507008fb90&secret=Fr5hG91UdCPQ2mKodG82u3UNqf0SLJ7NB1wSxAJ8'|">Launch</button>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -16,5 +16,9 @@
|
|||||||
<div><label> Password: <input type="password" name="password"/> </label></div>
|
<div><label> Password: <input type="password" name="password"/> </label></div>
|
||||||
<div><input type="submit" value="Sign In"/></div>
|
<div><input type="submit" value="Sign In"/></div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<form th:action="@{/users/register}" method="get">
|
||||||
|
<div><input type="submit" value="Register"/></div>
|
||||||
|
</form>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
18
src/main/resources/templates/register.html
Normal file
18
src/main/resources/templates/register.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
|
||||||
|
<title>LTI start</title>
|
||||||
|
|
||||||
|
<link rel="stylesheet" th:href="@{/css/main.css}"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form th:action="@{/users}" method="post">
|
||||||
|
<div><label> User Name : <input type="text" name="username"/></label></div>
|
||||||
|
<div><label> Password: <input type="password" name="password"/></label></div>
|
||||||
|
<div><input type="submit" value="Register"/></div>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -9,8 +9,55 @@
|
|||||||
<link rel="stylesheet" th:href="@{/css/main.css}"/>
|
<link rel="stylesheet" th:href="@{/css/main.css}"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<form th:action="${launchUrl}" target="_blank" method="POST">
|
|
||||||
<input type="submit">Launch Tool</input>
|
<style>
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
td, th {
|
||||||
|
border: 1px solid #dddddd;
|
||||||
|
text-align: left;
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background-color: #dddddd;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<tr th:each="course: ${courses}">
|
||||||
|
<form target = "_blank" th:action="${course.url}" method="POST">
|
||||||
|
<th:block th:each="parameter : ${course.signedParameters}">
|
||||||
|
<input type="hidden" th:name="${parameter.key}" th:value="${parameter.value}" />
|
||||||
|
</th:block>
|
||||||
|
<input th:value="${course.name}" type="submit"/>
|
||||||
|
</form>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
|
<br><br><br>
|
||||||
|
<form th:action="@{/courses/addCourse}" method="GET">
|
||||||
|
<div><input type="submit" value="Add new content"/></div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<br><br><br>
|
||||||
|
<H3>Grades</H3>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Course</th>
|
||||||
|
<th>Grade</th>
|
||||||
|
</tr>
|
||||||
|
<th:block th:each="grade: ${grades}">
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td th:text="${grade.courseName}">...</td>
|
||||||
|
<td th:text="${grade.score}">...</td>
|
||||||
|
</tr>
|
||||||
|
</th:block>
|
||||||
|
</table>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
Loading…
Reference in New Issue
Block a user