таблица lms_content, связь с task
This commit is contained in:
parent
ea4bfe281f
commit
3997e2d2ab
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
```shell
|
||||
# Генерация RSA ключа (2048 или 4096 бит)
|
||||
openssl genrsa -out private.key 2048
|
||||
|
||||
# Конвертация в PEM?
|
||||
|
||||
# Извлечение публичного ключа
|
||||
openssl rsa -in private.key -pubout -out public.key
|
||||
|
||||
```
|
||||
|
|
@ -2,4 +2,4 @@ spring:
|
|||
datasource:
|
||||
url: jdbc:postgresql://localhost:5432/lti
|
||||
username: postgres
|
||||
password: postgres
|
||||
password: oodbpasswd
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
services:
|
||||
|
||||
zookeeper:
|
||||
image: confluentinc/cp-zookeeper:7.6.1
|
||||
container_name: zookeeper
|
||||
environment:
|
||||
ZOOKEEPER_CLIENT_PORT: 2181
|
||||
ZOOKEEPER_TICK_TIME: 2000
|
||||
restart: unless-stopped
|
||||
|
||||
kafka:
|
||||
image: confluentinc/cp-kafka:7.6.1
|
||||
container_name: kafka
|
||||
depends_on:
|
||||
- zookeeper
|
||||
ports:
|
||||
- "29092:29092"
|
||||
environment:
|
||||
KAFKA_BROKER_ID: 1
|
||||
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
|
||||
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092,PLAINTEXT_HOST://localhost:29092
|
||||
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
|
||||
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
|
||||
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
|
||||
KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
|
||||
KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
|
||||
networks:
|
||||
lti-net:
|
||||
driver: bridge
|
||||
default:
|
||||
name: lti-net
|
||||
15
pom.xml
15
pom.xml
|
|
@ -33,6 +33,11 @@
|
|||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-oauth2-jose</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
|
|
@ -58,10 +63,20 @@
|
|||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
package ru.oa2.lti;
|
||||
|
||||
import jakarta.transaction.Transactional;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.oa2.lti.model.LtiLogin;
|
||||
import ru.oa2.lti.repository.LMSContentRepository;
|
||||
import ru.oa2.lti.repository.entities.LMSContent;
|
||||
import ru.oa2.lti.repository.entities.Task;
|
||||
import ru.oa2.lti.service.jwt.JwtService;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@Service
|
||||
@Transactional
|
||||
public class ApplicationService {
|
||||
|
||||
private final JwtService jwtService;
|
||||
private final LMSContentRepository lmsContentRepository;
|
||||
|
||||
public ApplicationService(JwtService jwtService,
|
||||
LMSContentRepository lmsContentRepository) {
|
||||
this.jwtService = jwtService;
|
||||
this.lmsContentRepository = lmsContentRepository;
|
||||
}
|
||||
|
||||
public String getTask(LtiLogin ltiLogin) {
|
||||
var payload = jwtService.getPayload(ltiLogin.getLoginHint());
|
||||
|
||||
var content = lmsContentRepository.getLMSContentByContentId(payload.getContextId());
|
||||
|
||||
if(content.isPresent()) {
|
||||
LMSContent lmsContent = content.get();
|
||||
Collection<Task> tasks = lmsContent.getTasks();
|
||||
|
||||
//TODO добавить версию в Task и выбирать самую старшую и опубликованную
|
||||
Object data = tasks.stream().findFirst().get().getData();
|
||||
return (String)data;
|
||||
} else {
|
||||
return "Not Page";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,8 +2,10 @@ package ru.oa2.lti;
|
|||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableTransactionManagement
|
||||
public class LTIProviderApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
package ru.oa2.lti.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.oauth2.jwt.JwtDecoder;
|
||||
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
|
||||
|
||||
|
||||
@Configuration
|
||||
public class JwtConfig {
|
||||
|
||||
@Bean
|
||||
public JwtDecoder jwtDecoder() {
|
||||
return NimbusJwtDecoder
|
||||
.withJwkSetUri("http://openolat.local/lti/keys") //TODO адрес из application
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package ru.oa2.lti.controller;
|
||||
|
||||
import jakarta.servlet.ServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.oa2.lti.ApplicationService;
|
||||
import ru.oa2.lti.model.LtiLogin;
|
||||
|
||||
@Slf4j
|
||||
|
|
@ -9,6 +11,12 @@ import ru.oa2.lti.model.LtiLogin;
|
|||
@RequestMapping("/tool/lti")
|
||||
public class LoginController {
|
||||
|
||||
private final ApplicationService service;
|
||||
|
||||
public LoginController(ApplicationService applicationService) {
|
||||
this.service = applicationService;
|
||||
}
|
||||
|
||||
@PostMapping("/login")
|
||||
public String login(
|
||||
@RequestParam("client_id") String clientId,
|
||||
|
|
@ -16,8 +24,8 @@ public class LoginController {
|
|||
@RequestParam("login_hint") String loginHint,
|
||||
@RequestParam("lti_deployment_id") String ltiDeploymentId,
|
||||
@RequestParam("lti_message_hint") String ltiMessageHint,
|
||||
@RequestParam("target_link_uri") String targetLinkUri
|
||||
) {
|
||||
@RequestParam("target_link_uri") String targetLinkUri,
|
||||
ServletRequest servletRequest) {
|
||||
var ltiLogin = LtiLogin.builder()
|
||||
.clientId(clientId)
|
||||
.iss(iss)
|
||||
|
|
@ -29,7 +37,6 @@ public class LoginController {
|
|||
|
||||
log.info("BODY: {}", ltiLogin);
|
||||
|
||||
//TODO service get context (by student/teatcher)
|
||||
return "redirect:" + "/page1";
|
||||
return service.getTask(ltiLogin);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
```shell
|
||||
curl -XPOST http://localhost:8080/tool/lti/login \
|
||||
curl -XPOST http://localhost:9999/tool/lti/login \
|
||||
-d 'client_id=27e2d42d-d218-4ab9-b063-85e3ec87ec8f&iss=https%3A%2F%2Flocalhost&login_hint=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImU5ODA3YTg2LTVhNWQtNDI0MC1hYjI1LWNhYTUyZDliZjUxOSJ9.eyJkZXBsb3ltZW50S2V5IjoxLCJkZXBsb3ltZW50SWQiOiIyNzE1ZDA0NS03N2M1LTRkODgtYTFlNC05MmQ3MjFmY2M1NGIiLCJjb250ZXh0S2V5IjoxLCJjb250ZXh0SWQiOiJlMmE4ZGQxMy04MWJhLTQwMTEtODgwNi0wMjA5NGZkZjg5ZjMiLCJjb3Vyc2VhZG1pbiI6ZmFsc2UsImNvYWNoIjpmYWxzZSwicGFydGljaXBhbnQiOnRydWV9.vgPLHQA9scdED3_OwOy46h6VmzpN4arIHY3-YDBdhH4kuEqeCOjjtFbGdDqauKoQBTSVo4UvoK4JQLMhak6qsFchCj54mPob8jbaKLd0GnO_jY0sR609Nrk7Muq7cki_4PjVMX8TTHp-VYlSHjVxQH_z_D5Wld27J95z4qJjRU59GmvLGDqdLyerVVBO-zaavYsUbEEiAxoX3hmytxrarmJ7OHpxufNOeXzZ0DSGUmU5ycuTAqxODaHO1Y4rQM6XlvSfDh_TmXP8QEkatlp2cdjRpNWyOdUW_hZfbtkqukwt1ZP7KEgWzNI3vivpBjm2xfUG2YLwXPJqHa47NQgvsQ<i_deployment_id=2715d045-77c5-4d88-a1e4-92d721fcc54b<i_message_hint=1802240&target_link_uri=https%3A%2F%2Fopenolat.local%2Ftool'
|
||||
```
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package ru.oa2.lti.domain.carecase;
|
||||
|
||||
public class GetTask {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package ru.oa2.lti.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import ru.oa2.lti.repository.entities.LMSContent;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
@Repository
|
||||
public interface LMSContentRepository extends JpaRepository<LMSContent, Long> {
|
||||
|
||||
Optional<LMSContent> getLMSContentByContentKey(long id);
|
||||
Optional<LMSContent> getLMSContentByContentId(UUID contentId);
|
||||
Optional<LMSContent> findByContentId(UUID contentId);
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
package ru.oa2.lti.repository;
|
||||
|
||||
public interface TaskRepository {
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package ru.oa2.lti.repository.entities;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "lms_content")
|
||||
public class LMSContent {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
long id;
|
||||
|
||||
@Column(name = "content_key")
|
||||
long contentKey;
|
||||
|
||||
@Column(name = "content_uuid")
|
||||
UUID contentId;
|
||||
|
||||
@Column(name = "deployment_id")
|
||||
UUID deploymentId;
|
||||
|
||||
@OneToMany(mappedBy="id", fetch = FetchType.LAZY)
|
||||
Collection<Task> tasks;
|
||||
}
|
||||
|
|
@ -1,20 +1,22 @@
|
|||
package ru.oa2.lti.repository.entities;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
import ru.oa2.lti.model.TaskType;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Table(name = "task")
|
||||
public class Task {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
long taskId;
|
||||
long id;
|
||||
|
||||
@Column(length = 20)
|
||||
@Column(name = "task_type", length = 20)
|
||||
@Enumerated(EnumType.STRING)
|
||||
TaskType taskType;
|
||||
|
||||
@Column(columnDefinition = "jsonb")
|
||||
@Column(name = "data", columnDefinition = "jsonb")
|
||||
Object data;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
package ru.oa2.lti.service.jwt;
|
||||
|
||||
public interface JwtService {
|
||||
|
||||
Payload getPayload(String jwt);
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package ru.oa2.lti.service.jwt;
|
||||
|
||||
import org.springframework.security.oauth2.jwt.JwtDecoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class JwtServiceImpl implements JwtService {
|
||||
|
||||
private JwtDecoder jwtDecoder;
|
||||
|
||||
public JwtServiceImpl(JwtDecoder jwtDecoder) {
|
||||
this.jwtDecoder = jwtDecoder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Payload getPayload(String token) {
|
||||
var jwt = jwtDecoder.decode(token);
|
||||
|
||||
return Payload.builder()
|
||||
.deploymentKey(jwt.getClaim("deploymentKey"))
|
||||
.deploymentId(UUID.fromString(jwt.getClaim("deploymentId")))
|
||||
.contextKey(jwt.getClaim("contextKey"))
|
||||
.contextId(UUID.fromString(jwt.getClaim("contextId")))
|
||||
.courseadmin(jwt.getClaim("courseadmin"))
|
||||
.coach(jwt.getClaim("coach"))
|
||||
.participant(jwt.getClaim("participant"))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package ru.oa2.lti.service.jwt;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class Payload {
|
||||
private Long deploymentKey;
|
||||
private UUID deploymentId;
|
||||
private Long contextKey;
|
||||
private UUID contextId;
|
||||
private Boolean courseadmin;
|
||||
private Boolean coach;
|
||||
private Boolean participant;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ru.oa2.lti.service;
|
||||
package ru.oa2.lti.service.task;
|
||||
|
||||
import ru.oa2.lti.model.ResultRequest;
|
||||
import ru.oa2.lti.model.TaskResult;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ru.oa2.lti.service;
|
||||
package ru.oa2.lti.service.task;
|
||||
|
||||
import ru.oa2.lti.model.ResultRequest;
|
||||
import ru.oa2.lti.model.TaskResult;
|
||||
|
|
@ -1,5 +1,12 @@
|
|||
spring:
|
||||
|
||||
jpa:
|
||||
# Показывать SQL запросы
|
||||
show-sql: true
|
||||
properties:
|
||||
hibernate:
|
||||
format_sql: true
|
||||
|
||||
application:
|
||||
name: lti-provider
|
||||
|
||||
|
|
@ -12,4 +19,7 @@ spring:
|
|||
server:
|
||||
port: 9999
|
||||
|
||||
|
||||
logging:
|
||||
level:
|
||||
org.hibernate.SQL: DEBUG
|
||||
org.hibernate.type.descriptor.sql.BasicBinder: TRACE
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<databaseChangeLog
|
||||
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
|
||||
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.10.xsd"
|
||||
objectQuotingStrategy="QUOTE_ONLY_RESERVED_WORDS">
|
||||
|
||||
<changeSet id="2025-12-01" author="dzyk">
|
||||
|
||||
<createTable tableName="lms_content">
|
||||
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="PK_LMS_CONTENT"/>
|
||||
</column>
|
||||
|
||||
<column name="deployment_id" type="uuid"/>
|
||||
|
||||
<column name="content_key" type="bigint"/>
|
||||
|
||||
<column name="content_uuid" type="uuid"/>
|
||||
|
||||
<column name="task_id" type="bigint"/>
|
||||
|
||||
</createTable>
|
||||
|
||||
<addForeignKeyConstraint
|
||||
baseTableName="lms_content"
|
||||
baseColumnNames="task_id"
|
||||
constraintName="fk_lms_content_task"
|
||||
referencedTableName="task"
|
||||
referencedColumnNames="id"
|
||||
onDelete="NO ACTION"/>
|
||||
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
<createTable tableName="task">
|
||||
|
||||
<column autoIncrement="true" name="task_id" type="BIGINT">
|
||||
<column autoIncrement="true" name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="PK_TASK"/>
|
||||
</column>
|
||||
|
||||
|
|
|
|||
|
|
@ -9,5 +9,6 @@
|
|||
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.3.xsd">
|
||||
|
||||
<include file="/db/changelog/1.0.0/2025-12-add_task.xml"/>
|
||||
<include file="/db/changelog/1.0.0/2025-12-add_lms_content.xml"/>
|
||||
|
||||
</databaseChangeLog>
|
||||
Loading…
Reference in New Issue