From b4e7a22c9b216a68bfda9d6690fe09949601a45e Mon Sep 17 00:00:00 2001 From: esoe Date: Fri, 11 Oct 2024 16:53:52 +0300 Subject: [PATCH] qq --- documentation/general/architecture.md | 3 + documentation/general/architecture.png | Bin 0 -> 47512 bytes documentation/general/architecture.puml | 52 +++++++++++++ documentation/general/usecase.puml | 39 ++++++++++ documentation/storage/usecase.puml | 73 ++++++++++++++++++ face/README.md | 1 + storage/logs/teh.log | 24 +++--- storage/logs/teh.log.2024-10-10.0.gz | Bin 0 -> 1044 bytes .../controllers/api/ApiController.java | 15 ++-- .../controllers/face/FaceController.java | 20 +---- .../controllers/hello/HelloController.java | 40 +--------- .../storage/models/xlsx/Xlsx.java | 4 - .../storage/services/FileService.java | 4 +- .../storage/services/FileServiceImpl.java | 13 +++- .../storage/services/RemoteFilesService.java | 13 ---- .../src/main/resources/templates/hello.html | 11 +++ .../main/resources/templates/view-xlsx.html | 6 +- 17 files changed, 221 insertions(+), 97 deletions(-) create mode 100644 documentation/general/architecture.md create mode 100644 documentation/general/architecture.png create mode 100644 documentation/general/architecture.puml create mode 100644 documentation/general/usecase.puml create mode 100644 documentation/storage/usecase.puml create mode 100644 face/README.md create mode 100644 storage/logs/teh.log.2024-10-10.0.gz diff --git a/documentation/general/architecture.md b/documentation/general/architecture.md new file mode 100644 index 0000000..fdceb7a --- /dev/null +++ b/documentation/general/architecture.md @@ -0,0 +1,3 @@ +# Архитектура платформы teh +## диаграмма компонентов +![диаграмма компонентов](architecture.png) diff --git a/documentation/general/architecture.png b/documentation/general/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..a388a73d0dd9f060f630d20ab3a65f1464ff9a10 GIT binary patch literal 47512 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 in83 : "Данные СУБД\n в json-формате" + out82 --> in83 : "Данные файловой системы\n в json-формате" + out5432 --> in81 : "данные СУБД\n в виде персистентных объектов" + out81 --> in85 : "Логи исполнения\n кода приложения" + out82 --> in85 : "Логи исполнения\n кода приложения" + out83 --> in85 : "Логи исполнения\n кода приложения" + } + jvm --> env + maven --> env + git --> env +} + + +@enduml \ No newline at end of file diff --git a/documentation/general/usecase.puml b/documentation/general/usecase.puml new file mode 100644 index 0000000..062e1fa --- /dev/null +++ b/documentation/general/usecase.puml @@ -0,0 +1,39 @@ +@startuml +title "usecase: teh" +left to right direction + +actor "Пользователь" as user + +package "mainframe" { + frame "Статистика файлообменника (storage-stat)" { + usecase "Данные по видам и количеству размещенных на сервере документов" + usecase "Переход: к файлообменнику (storage)" + } + frame "Статистика хранилища данных (base-stat)" { + usecase "Просмотр данных реестра обученных" + usecase "Переход: к формированию отчетов" + } +} + +package "storage" { + usecase "Переход: к mainframe" + usecase "Размещение в хранилище файлов" as upload + usecase "Скачивание файла с сервера" as download + usecase "Удаление файлов из хранилища" as delete + usecase "Просмотр списка файлов в хранилище" as list + usecase "Просмотр/получение сведений о файле" as info + usecase "Переход: к просмотру содержимого файла" + usecase "Переход: к формам экспорта данных" +} + +package "view-xlsx" as viewXlsx{ + usecase "Просмотр/получение содержимого файла (xlsx)" as view + usecase "Навигация по файлу" + usecase "Переход: к mainframe" + usecase "Переход: к storage" +} + +user --> mainframe +user --> storage +user --> viewXlsx +@enduml \ No newline at end of file diff --git a/documentation/storage/usecase.puml b/documentation/storage/usecase.puml new file mode 100644 index 0000000..9e5ff99 --- /dev/null +++ b/documentation/storage/usecase.puml @@ -0,0 +1,73 @@ +@startuml +title "USECASE: teh.storage" +allowmixing +left to right direction +' пользователи +actor "Пользователь" as user +actor "Стороний сервис" as service + +' возможности использования +usecase "получение сведений о корневой директории" as getRoot +usecase "Загрузка файла на сервер" as upload +usecase "Загрузка файлов на сервер пакетом" as uploads +usecase "Скачивание файла с сервера" as download +usecase "Удаление файла с сервера" as delete +usecase "Просмотр/получение перечня файлов на сервере" as list +usecase "Просмотр/получение сведений о файле" as fileInfo +usecase "Настройка параметров просмотра файла (xlsx)" as setParams +usecase "Просмотр/получение содержимого файла (xlsx)" as viewXlsx + +' FACE +user --> upload +user --> uploads +user --> download +user --> delete +user --> list +user --> fileInfo +user --> setParams +user --> viewXlsx + +' REST API +upload <-- service : "POST /api/v1/files/store" +uploads <-- service : "POST /api/v1/files/store-multiple" +download <-- service : "GET /api/v1/files/download" +delete <-- service : "DELETE /api/v1/files/delete" +list <-- service : "GET /api/v1/files" +fileInfo <-- service : "получаем с пусой страницей xlsxPage" +viewXlsx <-- service : "GET /api/v1/files/xlsx" +getRoot <-- service : "GET /api/v1/root" + +json "Сведения о файле" as fileMetadata { + "name":"наименование файла", + "extension":["xlsx", "pdf", "..."], + "rootPath": "/app/storage/uploads", + "relativePath":"/filename.xlsx", + "absolutePath":"/app/storage/uploads/filename.xlsx", + "size":"размер файла в байтах", + "createdDate":"время создания файла", + "lastModifiedDate":"время последнего изменения файла", + "owner":"пользователь - владелец файла", + "type": "файл или директория", + "permissions": "права, установленные файлу на сервере" +} + +json "Содержимое файла" as page { + "content":"выборка данных xlsx", + "metadata":"FileMetadata", + "pageSize": "размер страницы", + "pageNumber": "номер страницы", + "offset": "смещение", + "headerLine": "номер строки с заголовками", + "last": "является ли последней страницей", + "first": "является ли первой страницей", + "hasNext": "имеется ли следующая страница", + "hasPrevious": "имеется ли предыдущая страница", + "totalLines": "всего строк в xlsx-файле", + "totalColumns": "всего столбцов", + "totalPages": "всего страниц" +} + +fileInfo --{ fileMetadata +viewXlsx --{ page + +@enduml diff --git a/face/README.md b/face/README.md new file mode 100644 index 0000000..4ab5662 --- /dev/null +++ b/face/README.md @@ -0,0 +1 @@ +# teh.face \ No newline at end of file diff --git a/storage/logs/teh.log b/storage/logs/teh.log index 46f5913..b8eea9a 100644 --- a/storage/logs/teh.log +++ b/storage/logs/teh.log @@ -1,12 +1,12 @@ -{"@timestamp":"2024-10-10T05:48:48.071013600Z","log.level":"INFO","process.pid":5360,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"Starting StorageApplicationTests using Java 17.0.7 with PID 5360 (started by devuser in C:\\Users\\devuser\\Documents\\code\\teh\\storage)","ecs.version":"8.11"} -{"@timestamp":"2024-10-10T05:48:48.083108600Z","log.level":"INFO","process.pid":5360,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"No active profile set, falling back to 1 default profile: \"default\"","ecs.version":"8.11"} -{"@timestamp":"2024-10-10T05:48:49.021430Z","log.level":"INFO","process.pid":5360,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.services.FileServiceImpl","message":"Создание директории root(), для хранения файлов: C:\\Users\\devuser\\Documents\\code\\teh\\storage\\uploads","ecs.version":"8.11"} -{"@timestamp":"2024-10-10T05:48:49.895543100Z","log.level":"INFO","process.pid":5360,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"Started StorageApplicationTests in 2.251 seconds (process running for 3.281)","ecs.version":"8.11"} -{"@timestamp":"2024-10-10T06:10:14.369765600Z","log.level":"INFO","process.pid":5140,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"Starting StorageApplicationTests using Java 17.0.7 with PID 5140 (started by devuser in C:\\Users\\devuser\\Documents\\code\\teh\\storage)","ecs.version":"8.11"} -{"@timestamp":"2024-10-10T06:10:14.376062200Z","log.level":"INFO","process.pid":5140,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"No active profile set, falling back to 1 default profile: \"default\"","ecs.version":"8.11"} -{"@timestamp":"2024-10-10T06:10:15.441671200Z","log.level":"INFO","process.pid":5140,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.services.FileServiceImpl","message":"Создание директории root(), для хранения файлов: C:\\Users\\devuser\\Documents\\code\\teh\\storage\\uploads","ecs.version":"8.11"} -{"@timestamp":"2024-10-10T06:10:16.498992600Z","log.level":"INFO","process.pid":5140,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"Started StorageApplicationTests in 2.565 seconds (process running for 3.659)","ecs.version":"8.11"} -{"@timestamp":"2024-10-10T06:16:30.410659500Z","log.level":"INFO","process.pid":16080,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"Starting StorageApplicationTests using Java 17.0.7 with PID 16080 (started by devuser in C:\\Users\\devuser\\Documents\\code\\teh\\storage)","ecs.version":"8.11"} -{"@timestamp":"2024-10-10T06:16:30.416388500Z","log.level":"INFO","process.pid":16080,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"No active profile set, falling back to 1 default profile: \"default\"","ecs.version":"8.11"} -{"@timestamp":"2024-10-10T06:16:31.402964900Z","log.level":"INFO","process.pid":16080,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.services.FileServiceImpl","message":"Создание директории root(), для хранения файлов: C:\\Users\\devuser\\Documents\\code\\teh\\storage\\uploads","ecs.version":"8.11"} -{"@timestamp":"2024-10-10T06:16:32.211194900Z","log.level":"INFO","process.pid":16080,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"Started StorageApplicationTests in 2.244 seconds (process running for 3.327)","ecs.version":"8.11"} +{"@timestamp":"2024-10-11T06:10:07.994244Z","log.level":"INFO","process.pid":13084,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"Starting StorageApplicationTests using Java 17.0.7 with PID 13084 (started by devuser in C:\\Users\\devuser\\Documents\\code\\teh\\storage)","ecs.version":"8.11"} +{"@timestamp":"2024-10-11T06:10:08.012254100Z","log.level":"INFO","process.pid":13084,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"No active profile set, falling back to 1 default profile: \"default\"","ecs.version":"8.11"} +{"@timestamp":"2024-10-11T06:10:08.913700800Z","log.level":"INFO","process.pid":13084,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.services.FileServiceImpl","message":"Создание директории root(), для хранения файлов: C:\\Users\\devuser\\Documents\\code\\teh\\storage\\uploads","ecs.version":"8.11"} +{"@timestamp":"2024-10-11T06:10:09.780682400Z","log.level":"INFO","process.pid":13084,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"Started StorageApplicationTests in 2.237 seconds (process running for 3.3)","ecs.version":"8.11"} +{"@timestamp":"2024-10-11T06:35:21.950719700Z","log.level":"INFO","process.pid":8196,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"Starting StorageApplicationTests using Java 17.0.7 with PID 8196 (started by devuser in C:\\Users\\devuser\\Documents\\code\\teh\\storage)","ecs.version":"8.11"} +{"@timestamp":"2024-10-11T06:35:21.956727800Z","log.level":"INFO","process.pid":8196,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"No active profile set, falling back to 1 default profile: \"default\"","ecs.version":"8.11"} +{"@timestamp":"2024-10-11T06:35:22.854946600Z","log.level":"INFO","process.pid":8196,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.services.FileServiceImpl","message":"Создание директории root(), для хранения файлов: C:\\Users\\devuser\\Documents\\code\\teh\\storage\\uploads","ecs.version":"8.11"} +{"@timestamp":"2024-10-11T06:35:23.702006500Z","log.level":"INFO","process.pid":8196,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"Started StorageApplicationTests in 2.194 seconds (process running for 3.32)","ecs.version":"8.11"} +{"@timestamp":"2024-10-11T07:10:32.899864600Z","log.level":"INFO","process.pid":6096,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"Starting StorageApplicationTests using Java 17.0.7 with PID 6096 (started by devuser in C:\\Users\\devuser\\Documents\\code\\teh\\storage)","ecs.version":"8.11"} +{"@timestamp":"2024-10-11T07:10:32.906864100Z","log.level":"INFO","process.pid":6096,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"No active profile set, falling back to 1 default profile: \"default\"","ecs.version":"8.11"} +{"@timestamp":"2024-10-11T07:10:33.959310800Z","log.level":"INFO","process.pid":6096,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.services.FileServiceImpl","message":"Создание директории root(), для хранения файлов: C:\\Users\\devuser\\Documents\\code\\teh\\storage\\uploads","ecs.version":"8.11"} +{"@timestamp":"2024-10-11T07:10:34.884139900Z","log.level":"INFO","process.pid":6096,"process.thread.name":"main","service.name":"face","service.version":"1","service.environment":"Production","service.node.name":"Primary","log.logger":"gsp.technologies.storage.StorageApplicationTests","message":"Started StorageApplicationTests in 2.442 seconds (process running for 3.562)","ecs.version":"8.11"} diff --git a/storage/logs/teh.log.2024-10-10.0.gz b/storage/logs/teh.log.2024-10-10.0.gz new file mode 100644 index 0000000000000000000000000000000000000000..e17aedf6b1792ad4c3c536c1210b832135dd5a27 GIT binary patch literal 1044 zcmV+v1nc`BiwFP!00000|LvO1irhvJ$M1QHMyEAwn*RRKDZ$3DIXDaJT!JpLre{`I zBMp*ff-!**l5?IRZxBM3Y+~YP(7sWsvl@GSSVmR`#I`&LMyjsvk?Kd)f4W<*qc7Tg z?V2`SZ=yJ2go)27f#W%mu`qC8qA8(V5%O(x8Wq(F7jEYYa6WtX^lLC}>MCWtghVUbycoi*+R>C zT`jg*>)q}QS1sO+d0yx1w0^a}-)gmTHJDe;2DdJ|EGsbOuE9-P)#=LNi`(xnH=82Q zQa|u>2uTC|Av6uNKrL?igznewZTDyQNB3LzPj}s2AvnFh`Jub&{=WIK zdkbgR-8HJKsy%sh>KotO{DN+N2D|TYv3FYm+`Utg-VJ0c$T2_^d2A%X#K=rmPecmmr8ga}F9aG{|Oi4@y=E`a% zhn6@hLZ&fRt{^It%GEoTS`o$A+*wW~SGO1>7J@2GgT^oq#kvKmu&~Bj_Nhh=Q7ozC zA;nVCj;wMj<^&5$U<5gg235p_jANu^{TG(0HLItoxG|q-PAFQyfnq_JRl)|%VK%A- zL}BhgDYbzUJ>Eo1h(of)nI2c@n2ibe2_k^UKpcb^6EKdkvgN}vv25*WYWNIIu5f8i zCtIF_g(An8F=1!bTx1J~QUZR43mY)b<4v_VKRDImW^|Pk3KOj?8@ixGr4}LM7^_)6 zEYoY2r)d}`WZ=Skz%(b-EZ|@vtB4Fct7fEGLSrKoQ&a~{^k}k0?LpaMMvW_Ug8Q`$ zCM{)yr&^LR5ipL?vISw8ShjkaN)j#x%T};7r;{zu!RIa0R)?KcbCE4il=~$qLX8QU z=+R`0AKcdxY+RX>G^Ws76D#=;5{z;cFo=A}wRvxItOcO8%4fKfb4cdd-S#->MgH*&)$6P>np$*|f7v2?R0pl3Godsc; zQnTLEWRlCl|Lw!2Igx1f93 listFiles(String path, Boolean recursive); @@ -38,5 +39,6 @@ public interface FileService { String permissions(Path path); List children(Path path); FileMetadata parent(Path path); - FileMetadata metaFromPath(Path relative); + FileMetadata meta(Path relative); + Xlsx xlsx(Path relative); } \ No newline at end of file diff --git a/storage/src/main/java/gsp/technologies/storage/services/FileServiceImpl.java b/storage/src/main/java/gsp/technologies/storage/services/FileServiceImpl.java index 692c451..3fa022b 100644 --- a/storage/src/main/java/gsp/technologies/storage/services/FileServiceImpl.java +++ b/storage/src/main/java/gsp/technologies/storage/services/FileServiceImpl.java @@ -26,6 +26,7 @@ import org.springframework.web.multipart.MultipartFile; import gsp.technologies.storage.config.StorageConfig; import gsp.technologies.storage.models.FileMetadata; +import gsp.technologies.storage.models.xlsx.Xlsx; import jakarta.annotation.PostConstruct; @Service @@ -252,7 +253,7 @@ public class FileServiceImpl implements FileService { catch (IOException e) { System.out.println("Не удалось сохранить файл " + file.getOriginalFilename()); } - return metaFromPath(Path.of(file.getOriginalFilename())); + return meta(Path.of(file.getOriginalFilename())); } @Override @@ -381,7 +382,7 @@ public class FileServiceImpl implements FileService { List list = List.of(); try { list = Files.list(path) - .map(p -> metaFromPath(p.getFileName())) + .map(p -> meta(p.getFileName())) .collect(Collectors.toList()); } catch (IOException e) { log.error("Не удалось получить метаданные для файла {}", filename(path)); @@ -390,10 +391,10 @@ public class FileServiceImpl implements FileService { } public FileMetadata parent(Path path){ - return metaFromPath(path.getParent()); + return meta(path.getParent()); } - public FileMetadata metaFromPath(Path relative) { + public FileMetadata meta(Path relative) { log.info("Создаем объект FileMetadata для пути {}", relative.toString()); FileMetadata meta = new FileMetadata(); Path absolute = this.absolute(relative); @@ -411,4 +412,8 @@ public class FileServiceImpl implements FileService { meta.setPermissions(permissions(absolute)); return meta; } + + public Xlsx xlsx(Path relative){ + return new Xlsx(meta(relative), this); + } } \ No newline at end of file diff --git a/storage/src/main/java/gsp/technologies/storage/services/RemoteFilesService.java b/storage/src/main/java/gsp/technologies/storage/services/RemoteFilesService.java index 7a9527b..84b75a0 100644 --- a/storage/src/main/java/gsp/technologies/storage/services/RemoteFilesService.java +++ b/storage/src/main/java/gsp/technologies/storage/services/RemoteFilesService.java @@ -9,7 +9,6 @@ import org.springframework.core.io.Resource; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.reactive.function.client.WebClient; -import org.springframework.web.util.UriBuilder; import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; @@ -50,17 +49,6 @@ public class RemoteFilesService { .block(); } - // public void uploadFile(String originalFilename, byte[] bytes) { - // System.out.println("originalFilename: " + originalFilename); - // System.out.println("bytes.length: " + bytes.length); - // client.post() - // .uri(filesURL + "/" + originalFilename) - // .body(Mono.just(bytes), byte[].class) - // .retrieve() - // .toBodilessEntity() - // .block(); - // } - public void uploadFile(MultipartFile file) { System.out.println("RemoteFilesService#uploadFile(): OK"); UriComponents uriComponents; @@ -102,7 +90,6 @@ public class RemoteFilesService { .retrieve() .toBodilessEntity() .block(); - } public Resource loadAsResource(String filename) { diff --git a/storage/src/main/resources/templates/hello.html b/storage/src/main/resources/templates/hello.html index 6a8f67e..f056275 100644 --- a/storage/src/main/resources/templates/hello.html +++ b/storage/src/main/resources/templates/hello.html @@ -9,6 +9,17 @@ xmlns:th="http://www.thymeleaf.org"> +

TEST: moodle links

+ https://ruphp.com/moodle-accept.html +
+ + + + +
+
+ +

hello-page

\ No newline at end of file diff --git a/storage/src/main/resources/templates/view-xlsx.html b/storage/src/main/resources/templates/view-xlsx.html index 8786776..8f2c51b 100644 --- a/storage/src/main/resources/templates/view-xlsx.html +++ b/storage/src/main/resources/templates/view-xlsx.html @@ -33,9 +33,13 @@ - path: + absolutePath: + + relativePath: + + root: