diff --git a/.github/workflows/swagger.yml b/.github/workflows/swagger.yml index 9db7bbfca..b0f328a67 100644 --- a/.github/workflows/swagger.yml +++ b/.github/workflows/swagger.yml @@ -23,6 +23,6 @@ jobs: - uses: actions/checkout@v2 - name: openapi-lint - uses: mhiew/redoc-lint-github-action@v2 + uses: mbowman100/swagger-validator-action@master with: - args: 'public/swagger.yml --skip-rule operation-operationId' + files: public/swagger.yml diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b23d0aae..0cf7f16a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## 1.20.2 - 2022-04-30 + +### Fixed +- swagger lint action +- When downloading a file with a `'` in the name it would save the file as blob +- Fix for a rare race condition with masonry where tiles could end up overlapping in space page. +- Fixes bug where same extractor shows up multiple times and all Clowder instances index db on reindex [#327](https://github.com/clowder-framework/clowder/issues/327) + +### Changed +- Changed `Enabled By SuperAdmin` to read `Enabled by Server Admin` [#344](https://github.com/clowder-framework/clowder/issues/344) + ## 1.20.1 - 2022-04-04 ### Fixed diff --git a/app/services/mongodb/MongoDBQueueService.scala b/app/services/mongodb/MongoDBQueueService.scala index b52030465..6fab9539f 100644 --- a/app/services/mongodb/MongoDBQueueService.scala +++ b/app/services/mongodb/MongoDBQueueService.scala @@ -93,7 +93,8 @@ trait MongoDBQueueService { // start pool to being processing queue actions def listen() = { - if (queueTimer == null) { + //only if this is the primary clowder instance + if (queueTimer == null && configuration.getBoolean("clowder.primary").getOrElse(true)) { // TODO: Need to make these in a separate pool queueTimer = Akka.system().scheduler.schedule(0 seconds, 5 millis) { getNextQueuedAction match { diff --git a/app/services/rabbitmq/RabbitMQMessageService.scala b/app/services/rabbitmq/RabbitMQMessageService.scala index a5d5699a6..47ed9da6b 100644 --- a/app/services/rabbitmq/RabbitMQMessageService.scala +++ b/app/services/rabbitmq/RabbitMQMessageService.scala @@ -128,24 +128,27 @@ class RabbitMQMessageService extends MessageService { new MsgConsumer(channel.get, event_filter.get) ) - // Start actor to listen to extractor heartbeats - Logger.info("Starting extractor heartbeat listener") - // create fanout exchange if it doesn't already exist - channel.get.exchangeDeclare("extractors", "fanout", true) - // anonymous queue - val heartbeatsQueue = channel.get.queueDeclare().getQueue - // bind queue to exchange - channel.get.queueBind(heartbeatsQueue, "extractors", "*") - extractorsHeartbeats = Some(Akka.system.actorOf( - Props(new ExtractorsHeartbeats(channel.get, heartbeatsQueue)), name = "ExtractorsHeartbeats" - )) - Logger.debug("Initializing a MsgConsumer for the ExtractorsHeartbeats") - channel.get.basicConsume( - heartbeatsQueue, - false, // do not auto ack - "ExtractorsHeartbeats", // tagging the consumer is important if you want to stop it later - new MsgConsumer(channel.get, extractorsHeartbeats.get) - ) + //register new extractor only if this is the primary clowder instance + if (configuration.getBoolean("clowder.primary").getOrElse(true)) { + // Start actor to listen to extractor heartbeats + Logger.info("Starting extractor heartbeat listener") + // create fanout exchange if it doesn't already exist + channel.get.exchangeDeclare("extractors", "fanout", true) + // anonymous queue + val heartbeatsQueue = channel.get.queueDeclare().getQueue + // bind queue to exchange + channel.get.queueBind(heartbeatsQueue, "extractors", "*") + extractorsHeartbeats = Some(Akka.system.actorOf( + Props(new ExtractorsHeartbeats(channel.get, heartbeatsQueue)), name = "ExtractorsHeartbeats" + )) + Logger.debug("Initializing a MsgConsumer for the ExtractorsHeartbeats") + channel.get.basicConsume( + heartbeatsQueue, + false, // do not auto ack + "ExtractorsHeartbeats", // tagging the consumer is important if you want to stop it later + new MsgConsumer(channel.get, extractorsHeartbeats.get) + ) + } // Setup Actor to submit new extractions to broker extractQueue = Some(Akka.system.actorOf(Props(new PublishDirectActor(channel = channel.get, diff --git a/app/util/FileUtils.scala b/app/util/FileUtils.scala index 1d66d2f93..fd5790f1d 100644 --- a/app/util/FileUtils.scala +++ b/app/util/FileUtils.scala @@ -856,37 +856,20 @@ object FileUtils { //Download CONTENT-DISPOSITION encoding // def encodeAttachment(filename: String, userAgent: String) : String = { - val filenameStar = if (userAgent.indexOf("MSIE") > -1) { - URLEncoder.encode(filename, "UTF-8") - } else if (userAgent.indexOf("Edge") > -1){ - MimeUtility.encodeText(filename - .replaceAll(",","%2C") - .replaceAll("\"","%22") - .replaceAll("/","%2F") - .replaceAll("=","%3D") - .replaceAll("&","%26") - .replaceAll(":","%3A") - .replaceAll(";","%3B") - .replaceAll("\\?","%3F") - .replaceAll("\\*","%2A") + val filenameStar = MimeUtility.encodeText(filename + .replaceAll("%","%25") + .replaceAll(" ","%20") + .replaceAll("\"","%22") + .replaceAll("'","%27") + .replaceAll(",","%2C") + .replaceAll("/","%2F") + .replaceAll("=","%3D") + .replaceAll(":","%3A") + .replaceAll(";","%3B") + .replaceAll("\\*","%2A") ,"utf-8","Q") - } else { - MimeUtility.encodeText(filename - .replaceAll("%","%25") - .replaceAll(" ","%20") - .replaceAll("\"","%22") - .replaceAll(",","%2C") - .replaceAll("/","%2F") - .replaceAll("=","%3D") - .replaceAll(":","%3A") - .replaceAll(";","%3B") - .replaceAll("\\*","%2A") - ,"utf-8","Q") - } - Logger.debug(userAgent + ": " + filenameStar) //Return the complete attachment header info "attachment; filename*=UTF-8''" + filenameStar } - } diff --git a/app/views/spaces/space.scala.html b/app/views/spaces/space.scala.html index 696b81112..363b67a3a 100644 --- a/app/views/spaces/space.scala.html +++ b/app/views/spaces/space.scala.html @@ -148,7 +148,7 @@