diff --git a/Changelog.md b/Changelog.md index 9ed82b94..0e40338f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,17 @@ # Changelog +## v0.25.0 + +*Unreleased* + +### Rest API Changes + +- Removed `sec/collective/previews` endpoint, in favor for new + `admin/attachments/generatePreviews` endpoint which is now an admin + task to generate previews for all files. The now removed enpoint did + this only for one collective. + + ## v0.24.0 *Jun 18, 2021* diff --git a/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala b/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala index 88ad4c7d..135162da 100644 --- a/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala +++ b/modules/backend/src/main/scala/docspell/backend/ops/OItem.scala @@ -193,6 +193,14 @@ trait OItem[F[_]] { account: AccountId, notifyJoex: Boolean ): F[UpdateResult] + + /** Submits a task that (re)generates the preview images for all + * attachments. + */ + def generateAllPreviews( + storeMode: MakePreviewArgs.StoreMode, + notifyJoex: Boolean + ): F[UpdateResult] } object OItem { @@ -699,6 +707,16 @@ object OItem { _ <- if (notifyJoex) joex.notifyAllNodes else ().pure[F] } yield UpdateResult.success + def generateAllPreviews( + storeMode: MakePreviewArgs.StoreMode, + notifyJoex: Boolean + ): F[UpdateResult] = + for { + job <- JobFactory.allPreviews[F](AllPreviewsArgs(None, storeMode), None) + _ <- queue.insertIfNew(job) + _ <- if (notifyJoex) joex.notifyAllNodes else ().pure[F] + } yield UpdateResult.success + private def onSuccessIgnoreError(update: F[Unit])(ar: UpdateResult): F[Unit] = ar match { case UpdateResult.Success => diff --git a/modules/restapi/src/main/resources/docspell-openapi.yml b/modules/restapi/src/main/resources/docspell-openapi.yml index e871a98d..69314c7c 100644 --- a/modules/restapi/src/main/resources/docspell-openapi.yml +++ b/modules/restapi/src/main/resources/docspell-openapi.yml @@ -1136,30 +1136,6 @@ paths: schema: $ref: "#/components/schemas/BasicResult" - /sec/collective/previews: - post: - operationId: "sec-collective-previews-start-generate" - tags: [ Collective ] - summary: Starts the generate previews task - description: | - Submits a task that re-generates preview images of all - attachments of the current collective. Each existing preview - image will be replaced. - - This can be used after changing the `preview` settings. - - If only preview images of selected attachments should be - regenerated, see the `/sec/attachment/{id}/preview` endpoint. - security: - - authTokenHeader: [] - responses: - 200: - description: Ok - content: - application/json: - schema: - $ref: "#/components/schemas/BasicResult" - /sec/user: get: operationId: "sec-user-get-all" @@ -1348,6 +1324,32 @@ paths: schema: $ref: "#/components/schemas/ResetPasswordResult" + /admin/attachments/generatePreviews: + post: + operationId: "admin-attachments-generate-previews" + tags: [Attachment, Admin] + summary: (Re)generate all preview images + description: | + Submits a task that re-generates preview images of all + attachments. Each existing preview image will be replaced. + + This can be used after changing the `preview` settings. + + If only preview images of selected attachments should be + regenerated, see the `/sec/attachment/{id}/preview` endpoint. + + This is an admin route, you need to specify the secret from + the config file via a http header `Docspell-Admin-Secret`. + security: + - adminHeader: [] + responses: + 200: + description: Ok + content: + application/json: + schema: + $ref: "#/components/schemas/BasicResult" + /sec/source: get: operationId: "sec-source-get-all" diff --git a/modules/restserver/src/main/scala/docspell/restserver/RestServer.scala b/modules/restserver/src/main/scala/docspell/restserver/RestServer.scala index e3dd4f7a..60a33b6e 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/RestServer.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/RestServer.scala @@ -108,9 +108,10 @@ object RestServer { def adminRoutes[F[_]: Async](cfg: Config, restApp: RestApp[F]): HttpRoutes[F] = Router( - "fts" -> FullTextIndexRoutes.admin(cfg, restApp.backend), - "user" -> UserRoutes.admin(restApp.backend), - "info" -> InfoRoutes.admin(cfg) + "fts" -> FullTextIndexRoutes.admin(cfg, restApp.backend), + "user" -> UserRoutes.admin(restApp.backend), + "info" -> InfoRoutes.admin(cfg), + "attachments" -> AttachmentRoutes.admin(restApp.backend) ) def redirectTo[F[_]: Async](path: String): HttpRoutes[F] = { diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/AttachmentRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/AttachmentRoutes.scala index 57c5e2fb..85b02b42 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/AttachmentRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/AttachmentRoutes.scala @@ -189,4 +189,19 @@ object AttachmentRoutes { } yield resp } } + + def admin[F[_]: Async](backend: BackendApp[F]): HttpRoutes[F] = { + val dsl = Http4sDsl[F] + import dsl._ + + HttpRoutes.of { case POST -> Root / "generatePreviews" => + for { + res <- backend.item.generateAllPreviews(MakePreviewArgs.StoreMode.Replace, true) + resp <- Ok( + Conversions.basicResult(res, "Generate all previews task submitted.") + ) + } yield resp + } + } + } diff --git a/modules/restserver/src/main/scala/docspell/restserver/routes/CollectiveRoutes.scala b/modules/restserver/src/main/scala/docspell/restserver/routes/CollectiveRoutes.scala index 1fd00d7d..3cbb27cd 100644 --- a/modules/restserver/src/main/scala/docspell/restserver/routes/CollectiveRoutes.scala +++ b/modules/restserver/src/main/scala/docspell/restserver/routes/CollectiveRoutes.scala @@ -12,7 +12,7 @@ import cats.implicits._ import docspell.backend.BackendApp import docspell.backend.auth.AuthToken import docspell.backend.ops.OCollective -import docspell.common.{ListType, MakePreviewArgs} +import docspell.common.ListType import docspell.restapi.model._ import docspell.restserver.conv.Conversions import docspell.restserver.http4s._ @@ -101,18 +101,6 @@ object CollectiveRoutes { resp <- Ok(BasicResult(true, "Task submitted")) } yield resp - case POST -> Root / "previews" => - for { - res <- backend.collective.generatePreviews( - MakePreviewArgs.StoreMode.Replace, - user.account, - true - ) - resp <- Ok( - Conversions.basicResult(res, "Generate all previews task submitted.") - ) - } yield resp - case GET -> Root => for { collDb <- backend.collective.find(user.account.collective) diff --git a/tools/preview/regenerate-previews.sh b/tools/preview/regenerate-previews.sh index cc474c66..fdba0c67 100755 --- a/tools/preview/regenerate-previews.sh +++ b/tools/preview/regenerate-previews.sh @@ -11,23 +11,12 @@ JQ_CMD="jq" BASE_URL="${1:-http://localhost:7880}" -LOGIN_URL="$BASE_URL/api/v1/open/auth/login" -TRIGGER_URL="$BASE_URL/api/v1/sec/collective/previews" +TRIGGER_URL="$BASE_URL/api/v1/admin/attachments/generatePreviews" echo "Login to trigger regenerating preview images." echo "Using url: $BASE_URL" -echo -n "Account: " -read USER -echo -n "Password: " -read -s PASS +echo -n "Admin Secret: " +read -s ADMIN_SECRET echo -auth=$("$CURL_CMD" --fail -XPOST --silent --data-binary "{\"account\":\"$USER\", \"password\":\"$PASS\"}" "$LOGIN_URL") - -if [ "$(echo $auth | $JQ_CMD .success)" == "true" ]; then - echo "Login successful" - auth_token=$(echo $auth | "$JQ_CMD" -r .token) - curl --fail -XPOST -H "X-Docspell-Auth: $auth_token" "$TRIGGER_URL" -else - echo "Login failed." -fi +curl --fail -XPOST -H "Docspell-Admin-Secret: $ADMIN_SECRET" "$TRIGGER_URL" diff --git a/website/site/content/docs/tools/regenerate-previews.md b/website/site/content/docs/tools/regenerate-previews.md index 878a56ef..114f1c40 100644 --- a/website/site/content/docs/tools/regenerate-previews.md +++ b/website/site/content/docs/tools/regenerate-previews.md @@ -20,18 +20,18 @@ It is a bash script that additionally needs # Usage ``` -./regenerate-previews.sh [docspell-base-url] +./regenerate-previews.sh [docspell-base-url] [admin-secret] ``` For example, if docspell is at `http://localhost:7880`: ``` -./convert-all-pdfs.sh http://localhost:7880 +./convert-all-pdfs.sh http://localhost:7880 test123 ``` -The script asks for your account name and password. It then logs in -and triggers the said endpoint. After this you should see a few tasks -running. +The script asks for the admin secret if not given to the command. It +then logs in and triggers the said endpoint. After this you should see +a few tasks running. There will be one task per file to convert. All these tasks are submitted with a low priority. So files uploaded through the webapp or