Skip to content

Commit cacde6e

Browse files
authored
Merge pull request #10 from yesitha/dev-yesitha
video upload to AWS S3 implemented
2 parents ce8a723 + 1361896 commit cacde6e

13 files changed

Lines changed: 281 additions & 53 deletions

File tree

lib-global/src/main/java/com/itgura/util/URIPrefix.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,7 @@ public class URIPrefix {
2828
public static final String GET_PRICE = "/get-price";
2929
public static final String UPDATE_TAGS = "/update-tags";
3030
public static final String GET_VIDEO_Signed_Url = "/get-video-signed-url";
31+
public static final String Upload_Video_Material = "/upload-video";
32+
public static final String GET_Pre_Signed_Url_To_Upload_Video = "/get-pre-signed-url-to-upload-video";
33+
public static final String MARKED_VIDEO_AS_UPLOADED = "/marked-video-as-uploaded";
3134
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.itgura.config;
2+
3+
import org.springframework.beans.factory.annotation.Value;
4+
import org.springframework.context.annotation.Bean;
5+
import org.springframework.context.annotation.Configuration;
6+
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
7+
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
8+
import software.amazon.awssdk.regions.Region;
9+
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
10+
11+
@Configuration
12+
public class S3Config {
13+
14+
@Value("${aws.s3.accessKey}")
15+
private String S3_ACCESS_KEY;
16+
17+
@Value("${aws.s3.secretKey}")
18+
private String S3_SECRET_KEY;
19+
20+
21+
@Bean
22+
public S3Presigner s3Presigner() {
23+
return S3Presigner.builder()
24+
.region(Region.AP_SOUTH_1) // Replace with your AWS region
25+
.credentialsProvider(StaticCredentialsProvider.create(
26+
AwsBasicCredentials.create(
27+
S3_ACCESS_KEY,
28+
S3_SECRET_KEY
29+
)
30+
))
31+
.build();
32+
}
33+
}

resource-management/resource-management-all/src/main/java/com/itgura/controller/MaterialController.java

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22

33
import com.itgura.dto.AppRequest;
44
import com.itgura.dto.AppResponse;
5+
import com.itgura.exception.ValueNotExistException;
56
import com.itgura.request.MaterialRequest;
67
import com.itgura.request.SignedUrlRequest;
7-
import com.itgura.response.dto.MaterialResponseDto;
8+
import com.itgura.request.VideoUploadRequest;
9+
import com.itgura.response.dto.PreSignedUrlToUploadVideoResponseDto;
810
import com.itgura.service.MaterialService;
911
import com.itgura.util.ResourceManagementURI;
1012
import com.itgura.util.URIPathVariable;
1113
import com.itgura.util.URIPrefix;
14+
import io.swagger.annotations.ApiOperation;
1215
import org.springframework.beans.factory.annotation.Autowired;
16+
import org.springframework.security.access.prepost.PreAuthorize;
1317
import org.springframework.web.bind.annotation.*;
1418

1519
import java.util.UUID;
@@ -20,6 +24,7 @@
2024
public class MaterialController {
2125
@Autowired
2226
private MaterialService materialService;
27+
@PreAuthorize("hasAuthority('ROLE_ADMIN') or hasAuthority('ROLE_TEACHER')")
2328
@PostMapping( ResourceManagementURI.MATERIAL+URIPrefix.CREATE+ResourceManagementURI.SESSION_ID)
2429
public AppResponse<String> createMaterial(@PathVariable UUID sessionId, @RequestBody AppRequest<MaterialRequest> request) {
2530
try {
@@ -30,6 +35,7 @@ public AppResponse<String> createMaterial(@PathVariable UUID sessionId, @Request
3035
return AppResponse.error(null, e.getMessage(), "Server Error", "500", "");
3136
}
3237
}
38+
@PreAuthorize("hasAuthority('ROLE_ADMIN') or hasAuthority('ROLE_TEACHER')")
3339
@PatchMapping( ResourceManagementURI.MATERIAL+URIPrefix.UPDATE+ResourceManagementURI.MATERIAL_ID)
3440
public AppResponse<String> updateMaterial(@PathVariable UUID materialId, @RequestBody AppRequest<MaterialRequest> request) {
3541
try {
@@ -40,6 +46,7 @@ public AppResponse<String> updateMaterial(@PathVariable UUID materialId, @Reques
4046
return AppResponse.error(null, e.getMessage(), "Server Error", "500", "");
4147
}
4248
}
49+
@PreAuthorize("hasAuthority('ROLE_ADMIN') or hasAuthority('ROLE_TEACHER')")
4350
@DeleteMapping( ResourceManagementURI.MATERIAL+URIPrefix.DELETE+ResourceManagementURI.MATERIAL_ID)
4451
public AppResponse<String> deleteMaterial(@PathVariable UUID materialId) {
4552
try {
@@ -51,7 +58,7 @@ public AppResponse<String> deleteMaterial(@PathVariable UUID materialId) {
5158
}
5259
}
5360

54-
@PostMapping (ResourceManagementURI.MATERIAL + URIPrefix.GET_VIDEO_Signed_Url)
61+
@PostMapping (ResourceManagementURI.MATERIAL+URIPrefix.GET_VIDEO_Signed_Url)
5562
public AppResponse<String> getVideoMaterialSignedUrl(@RequestBody AppRequest<SignedUrlRequest> request) {
5663
try {
5764
String s = materialService.getVideoMaterialSignedUrl(request.getData());
@@ -61,26 +68,42 @@ public AppResponse<String> getVideoMaterialSignedUrl(@RequestBody AppRequest<Sig
6168
return AppResponse.error(null, e.getMessage(), "Server Error", "500", "");
6269
}
6370
}
64-
@GetMapping (ResourceManagementURI.MATERIAL + ResourceManagementURI.MATERIAL_ID)
65-
public AppResponse<MaterialResponseDto> getMaterialById(@PathVariable UUID materialId) {
71+
72+
@PreAuthorize("hasAuthority('ROLE_ADMIN') or hasAuthority('ROLE_TEACHER')")
73+
@PostMapping (ResourceManagementURI.MATERIAL+URIPrefix.GET_Pre_Signed_Url_To_Upload_Video)
74+
public AppResponse<PreSignedUrlToUploadVideoResponseDto> getPreSignedUrlToUploadVideo(@RequestBody AppRequest<VideoUploadRequest> request) {
6675
try {
67-
MaterialResponseDto dto = materialService.getMaterialById(materialId);
68-
return AppResponse.ok(dto);
69-
} catch (Exception e) {
76+
PreSignedUrlToUploadVideoResponseDto responseDto = materialService.getPreSignedUrlToUploadVideo(request.getData());
77+
return AppResponse.ok(responseDto);
78+
} catch (ValueNotExistException e) {
79+
e.printStackTrace();
80+
return AppResponse.error(null, e.getMessage(), "Value Not Found", "404", "");
81+
}catch (Exception e) {
7082
e.printStackTrace();
7183
return AppResponse.error(null, e.getMessage(), "Server Error", "500", "");
7284
}
7385
}
74-
@GetMapping (ResourceManagementURI.MATERIAL +URIPrefix.GET_ALL+ ResourceManagementURI.SESSION_ID)
75-
public AppResponse<List<MaterialResponseDto>> getAllMaterialBySessionId(@PathVariable UUID sessionId) {
86+
87+
@PreAuthorize("hasAuthority('ROLE_ADMIN') or hasAuthority('ROLE_TEACHER')")
88+
@PostMapping (ResourceManagementURI.MATERIAL+URIPrefix.MARKED_VIDEO_AS_UPLOADED+ResourceManagementURI.MATERIAL_ID)
89+
public AppResponse<String> markedVideoAsUploaded( @PathVariable UUID materialId) {
7690
try {
77-
List<MaterialResponseDto> dto = materialService.getAllMaterialBySessionId(sessionId);
78-
return AppResponse.ok(dto);
91+
String s = materialService.markedVideoAsUploaded(materialId);
92+
return AppResponse.ok(s);
93+
94+
} catch (ValueNotExistException ex) {
95+
ex.printStackTrace();
96+
return AppResponse.error(null, ex.getMessage(), "Value Not Found", "404", "");
97+
7998
} catch (Exception e) {
8099
e.printStackTrace();
81100
return AppResponse.error(null, e.getMessage(), "Server Error", "500", "");
82101
}
83102
}
84103

85104

105+
106+
107+
108+
86109
}

resource-management/resource-management-all/src/main/resources/application.properties

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ spring.servlet.multipart.max-request-size=10MB
1414
#cloudfront.keyPairId=YOUR_KEY_PAIR_ID
1515
#cloudfront.privateKeyPath=classpath:private-key.pem # Ensure the private key file is in the classpath
1616

17-
cloudfront.domain=https://yourdistribution.cloudfront.net
18-
cloudfront.keyPairId=YOUR_KEY_PAIR_ID
19-
cloudfront.privateKeyPath=classpath:private-key.pem # Ensure the private key file is in the classpath
17+
#AWS s3
18+
aws.s3.bucketName= YourBucketName
19+
aws.s3.accessKey=YOUR_ACCESS_KEY
20+
aws.s3.secretKey=YOUR_SECRET_KEY

resource-management/resource-management-dao/src/main/java/com/itgura/entity/Material.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import lombok.NoArgsConstructor;
77
import lombok.Setter;
88

9+
import java.time.Instant;
910
import java.util.UUID;
1011

1112
@Entity
@@ -14,13 +15,19 @@
1415
@NoArgsConstructor
1516
@Getter
1617
@Setter
17-
@PrimaryKeyJoinColumn(name = "material_id")
18+
@PrimaryKeyJoinColumn(name = "material_id") // For video this was video_id
1819
public class Material extends Content {
1920

20-
@Column(name = "material_name")
21+
@Column(name = "material_name") // For video this was original video name
2122
private String materialName;
22-
@Column(name = "reference")
23+
@Column(name = "reference") // For video this was S3 Key
2324
private String reference;
25+
@Column(name="signedUrlExpireTime")
26+
private int signedUrlExpireTime;
27+
@Column(name="status")
28+
private String status; // For video this was video status (pending,uploaded)
29+
@Column(name="created_at")
30+
private Instant createdAt; // For video this was video created at
2431
@Column(name = "description",columnDefinition = "TEXT")
2532
private String description;
2633
@ManyToOne
@@ -32,4 +39,11 @@ public class Material extends Content {
3239
@Column(name = "is_available_for_students")
3340
private Boolean isAvailableForStudents;
3441

42+
@PrePersist
43+
public void prePersist() {
44+
if (this.createdAt == null) {
45+
this.createdAt = Instant.now();
46+
}
47+
}
48+
3549
}

resource-management/resource-management-dao/src/main/java/com/itgura/entity/MaterialType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class MaterialType {
2121
@GeneratedValue(strategy = GenerationType.UUID)
2222
@Column(name = "material_type_id")
2323
private UUID materialTypeId;
24-
@Column(name = "material_type")
24+
@Column(name = "material_type") // e.g. VIDEO, PDF, DOCX, PPT
2525
private String materialType;
2626
@OneToMany(mappedBy = "materialType",cascade = {CascadeType.PERSIST, CascadeType.MERGE})
2727
private List<Material> materialList;

resource-management/resource-management-dao/src/main/java/com/itgura/repository/MaterialRepository.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22

33
import com.itgura.entity.Material;
44
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.data.jpa.repository.Query;
56
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
67
import org.springframework.stereotype.Repository;
78

9+
import java.time.Instant;
810
import java.util.List;
911
import java.util.UUID;
1012

1113
@Repository
1214
@EnableJpaRepositories
1315
public interface MaterialRepository extends JpaRepository<Material, UUID> {
14-
List<Material> findAllBySession_ContentId(UUID sessionId);
16+
@Query("SELECT m FROM Material m WHERE m.status = ?1 AND m.createdAt < ?2")
17+
List<Material> findAllByStatusAndCreatedAtBefore(String pending, Instant cutoffTime);
1518
}

resource-management/resource-management-dao/src/main/java/com/itgura/repository/MaterialTypeRepository.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.itgura.entity.MaterialType;
44
import org.springframework.data.jpa.repository.JpaRepository;
5+
import org.springframework.data.jpa.repository.Query;
56
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
67
import org.springframework.stereotype.Repository;
78

@@ -10,4 +11,6 @@
1011
@Repository
1112
@EnableJpaRepositories
1213
public interface MaterialTypeRepository extends JpaRepository<MaterialType, UUID> {
14+
@Query("SELECT mt FROM MaterialType mt WHERE mt.materialType = :name")
15+
MaterialType findByName(String name);
1316
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.itgura.request;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import jakarta.validation.constraints.NotNull;
5+
import lombok.AllArgsConstructor;
6+
import lombok.Builder;
7+
import lombok.Data;
8+
import lombok.NoArgsConstructor;
9+
10+
import java.util.UUID;
11+
12+
@Data
13+
@AllArgsConstructor
14+
@NoArgsConstructor
15+
@Builder
16+
public class VideoUploadRequest {
17+
18+
@NotNull(message = "Original file name is required")
19+
@JsonProperty("original_file_name")
20+
private String OriginalFileName;
21+
22+
@NotNull(message = "Signed URL expire time required")
23+
@JsonProperty("signed_url_expire_time")
24+
private Integer signedUrlExpireTime;
25+
26+
@JsonProperty("Description")
27+
private String description;
28+
29+
@JsonProperty("session_id")
30+
private UUID sessionId;
31+
32+
@JsonProperty("is_available_for_students")
33+
private Boolean isAvailableForStudents;
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.itgura.response.dto;
2+
3+
4+
import com.fasterxml.jackson.annotation.JsonProperty;
5+
import lombok.AllArgsConstructor;
6+
import lombok.Builder;
7+
import lombok.Data;
8+
import lombok.NoArgsConstructor;
9+
10+
import java.util.UUID;
11+
12+
@Data
13+
@AllArgsConstructor
14+
@NoArgsConstructor
15+
@Builder
16+
public class PreSignedUrlToUploadVideoResponseDto {
17+
18+
@JsonProperty("video_uuid")
19+
private UUID id;
20+
@JsonProperty("pre_signed_url")
21+
private String preSignedUrl;
22+
}

0 commit comments

Comments
 (0)