Browse Source

Fix #10 read with no meta access

isundil 1 năm trước cách đây
mục cha
commit
8b3c0c8914

+ 2 - 1
model/access.js

@@ -20,7 +20,8 @@ const ACCESS_TO = {
 const ACCESS_GRANT = {
     none: 0,
     read: 1,
-    write: 2
+    write: 2,
+    readNoMeta: 3
 };
 
 function AccessModel() {

+ 3 - 1
model/mediaService.js

@@ -84,7 +84,9 @@ MediaStruct.prototype.computeAccess = function(accessList) {
             (i.accessTo === ACCESS_TO.tag && checkTag([].concat(this.fixedTags, this.tags), i))) {
             if (i.grant === ACCESS_GRANT.write)
                 return this.accessType = ACCESS_GRANT.write;
-            this.accessType = ACCESS_GRANT.read;
+            if (i.grant === ACCESS_GRANT.read ||
+                (i.grant === ACCESS_GRANT.readNoMeta && this.accessType === ACCESS_GRANT.none))
+                this.accessType = i.grant;
         }
     }
     return this.accessType;

+ 17 - 6
router/api.js

@@ -8,6 +8,15 @@ const MediaFileMetaModel = require('../model/mediaItemMeta.js').MediaFileMetaMod
 const MediaFileTagModel = require('../model/mediaItemTag.js').MediaFileTagModel;
 const { AccessModel, ACCESS_TYPE, ACCESS_GRANT } = require('../model/access.js');
 
+function MediaToJson(mediaData) {
+    if (mediaData.accessType === ACCESS_GRANT.readNoMeta)
+        mediaData.meta = {
+            height: mediaData.meta?.height,
+            width: mediaData.meta?.width
+        };
+    return mediaData;
+}
+
 module.exports = { register: app => {
     app.router.get("/api/access/list", (req, res) => {
         app.routerUtils.onApiRequest(req, res);
@@ -36,7 +45,7 @@ module.exports = { register: app => {
         if (!data || data.accessType !== ACCESS_GRANT.write)
             return app.routerUtils.onPageNotFound(res);
         await app.databaseHelper.remove(MediaFileTagModel, { md5sum: data.md5sum, tag: decodeURIComponent(req.params.tag), fromMeta: 0 });
-        app.routerUtils.jsonResponse(res, await MediaService.fetchOne(app, req.params.id, req.sessionObj?.accessList));
+        app.routerUtils.jsonResponse(res, MediaToJson(await MediaService.fetchOne(app, req.params.id, req.sessionObj?.accessList)));
     });
     app.router.put("/api/media/:id/tag", async (req, res) => {
         app.routerUtils.onApiRequest(req, res);
@@ -53,7 +62,7 @@ module.exports = { register: app => {
         }
         let tag = new MediaFileTagModel(data.md5sum, requestedTag, false);
         await app.databaseHelper.insertOne(tag);
-        app.routerUtils.jsonResponse(res, await MediaService.fetchOne(app, req.params.id, req.sessionObj?.accessList));
+        app.routerUtils.jsonResponse(res, MediaToJson(await MediaService.fetchOne(app, req.params.id, req.sessionObj?.accessList)));
     });
     app.router.patch("/api/media/:id/meta/:key", async (req, res) => {
         app.routerUtils.onApiRequest(req, res);
@@ -68,7 +77,7 @@ module.exports = { register: app => {
             let newMediaItemMedia = new MediaFileMetaModel(data.md5sum, req.params.key, req.body.value, false);
             await app.databaseHelper.upsertOne(newMediaItemMedia);
         }
-        app.routerUtils.jsonResponse(res, await MediaService.fetchOne(app, req.params.id, req.sessionObj?.accessList));
+        app.routerUtils.jsonResponse(res, MediaToJson(await MediaService.fetchOne(app, req.params.id, req.sessionObj?.accessList)));
     });
     app.router.get("/api/media/list", async (req, res) => {
         app.routerUtils.onApiRequest(req, res);
@@ -82,18 +91,18 @@ module.exports = { register: app => {
         let fromDate = parseInt(req.body?.from);
         let count = parseInt(req.body?.count);
         app.routerUtils.jsonResponse(res, {
-            data: await MediaService.fetchMediasWithAccess(
+            data: (await MediaService.fetchMediasWithAccess(
                 app,
                 isNaN(fromDate) ? 0 : fromDate,
                 isNaN(count) ? 25 : Math.min(150, count),
-                req.sessionObj?.accessList),
+                req.sessionObj?.accessList)).map(MediaToJson),
             first: first,
             last: last
         });
     });
     app.router.get("/api/media/:md5sum", async (req, res) => {
         app.routerUtils.onApiRequest(req, res);
-        let data = await MediaService.fetchOne(app, req.params.md5sum, req.sessionObj?.accessList);
+        let data = MediaToJson(await MediaService.fetchOne(app, req.params.md5sum, req.sessionObj?.accessList));
         if (!data)
             return app.routerUtils.onPageNotFound(res);
         app.routerUtils.jsonResponse(res, data);
@@ -112,6 +121,7 @@ module.exports = { register: app => {
             }
             if (!thumbnail)
                 return app.routerUtils.onPageNotFound(res);
+            //if (data.accessType === ACCESS_GRANT.readNoMeta) -> trim metadata
             res.setHeader("Content-Type", "image/jpeg");
             res.setHeader("Content-Length", fs.statSync(thumbnail.name)?.size || undefined);
             res.setHeader("Cache-Control", "private, max-age=2630000"); // 1 month cache
@@ -129,6 +139,7 @@ module.exports = { register: app => {
         let data = await MediaService.fetchOne(app, req.params.md5sum, req.sessionObj?.accessList);
         if (!data)
             return app.routerUtils.onPageNotFound(res);
+        //if (data.accessType === ACCESS_GRANT.readNoMeta) -> trim metadata
         const fileName = Path.basename(data.path);
         res.setHeader("Content-Type", mime.lookup(data.path));
         res.setHeader("Content-Length", fs.statSync(data.path)?.size || undefined);

+ 6 - 1
static/public/css/style.css

@@ -42,9 +42,13 @@ body.filter-active #pch-navbar .bt-filter-inactive {
     text-align: center;
 }
 
+#pch-mediaList > .pch-image.loading {
+    height: 250px;
+}
+
 #pch-mediaList > .pch-image {
     display: inline-flex;
-    height: 450px;
+    max-height: 450px;
     min-width: 450px;
     justify-content: center;
     padding: 1em;
@@ -52,6 +56,7 @@ body.filter-active #pch-navbar .bt-filter-inactive {
 
 #pch-mediaList > .pch-image img {
     transition: scale 300ms;
+    object-fit: contain;
 }
 
 #pch-mediaList > .pch-image:hover img {

+ 10 - 5
static/public/js/medias.js

@@ -28,12 +28,17 @@ class Media {
 
     resize(maxWidth, maxHeight) {
         let ratio = Math.min(1, Math.max(
-            maxWidth / (this.meta?.width || maxWidth),
-            maxHeight / (this.meta?.height || maxHeight)));
-        return {
-            width: Math.floor(this.meta.width *ratio),
-            height: Math.floor(this.meta.height *ratio),
+            maxWidth / (this.meta?.width?.value || maxWidth),
+            maxHeight / (this.meta?.height?.value || maxHeight)));
+        let result = {
+            width: Math.floor(this.meta.width?.value *ratio),
+            height: Math.floor(this.meta.height?.value *ratio),
         };
+        if (isNaN(result.width) || isNaN(result.height) || !result.height || !result.width) {
+            console.error("Failed to resize image ", this);
+            return null;
+        }
+        return result;
     }
 
     setTags(fixedTags, tags) {

+ 5 - 3
static/public/js/uiMedia.js

@@ -29,14 +29,14 @@ $(() => {
         let editButtonSpan = document.createElement("span");
         editButtonSpan.className = "bi bi-pen";
         editButton.appendChild(editButtonSpan);
-        container.classList.add("pch-image");
-        container.classList.add("loading");
+        container.className = "pch-image loading col-12 col-md-6 col-xl-4";
         loadingImg.classList.add("spinner");
         loadingImg.innerHTML = "<span class='spinner-grow'></span>";
         container.dataset.md5sum = mediaItem.md5sum;
         img.loading = "lazy";
         let requestSize = mediaItem.resize(450, 450);
-        img.src = `${mediaItem.thumbnail}?w=${requestSize.width}&h=${requestSize.height}&q=4`;
+        requestSize = requestSize ? `w=${requestSize.width}&h=${requestSize.height}&` : "";
+        img.src = `${mediaItem.thumbnail}?${requestSize}q=4`;
         img.classList.add("img-fluid");
         img.classList.add("img-thumbnail");
         img.addEventListener("load", () => {
@@ -120,12 +120,14 @@ $(() => {
 
     function buildYear(date) {
         let result = document.createElement('h3');
+        result.className = "col-12";
         result.textContent = date.getUTCFullYear();
         return result;
     }
 
     function buildMonth(date) {
         let result = document.createElement('h4');
+        result.className = "col-12";
         result.textContent = date.toLocaleString('default', { month: 'long' });
         return result;
     }

+ 1 - 1
templates/index.js

@@ -2,7 +2,7 @@
 module.exports = require('./_header.js') +require('./_menu.js')
     +`
 <div id="pch-page">
-    <ul id="pch-mediaList"></ul>
+    <ul id="pch-mediaList" class="container-fluid"></ul>
     <div class="spinner" id="pch-infiniteScrollLoading">
         <div class="spinner-grow"></div>
     </div>`