Skip to content

Commit ccb804e

Browse files
authored
Merge pull request #423 from clowder-framework/release/1.22.0
Release/1.22.0
2 parents 4e85b7d + c5d8ace commit ccb804e

File tree

78 files changed

+1472
-704
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+1472
-704
lines changed

.github/workflows/ci.yml

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
build:
3131
runs-on: ubuntu-latest
3232
steps:
33-
- uses: actions/checkout@v2
33+
- uses: actions/checkout@v3
3434
- name: github branch
3535
run: |
3636
if [ "${{ github.event.release.target_commitish }}" != "" ]; then
@@ -46,9 +46,10 @@ jobs:
4646
else
4747
echo "CLOWDER_VERSION=testing" >> $GITHUB_ENV
4848
fi
49-
- uses: actions/setup-java@v1
49+
- uses: actions/setup-java@v3
5050
with:
51-
java-version: 1.8
51+
distribution: 'zulu'
52+
java-version: 8
5253
- name: Cache SBT ivy cache
5354
uses: actions/cache@v1
5455
with:
@@ -84,7 +85,7 @@ jobs:
8485
ports:
8586
- 27017:27017
8687
steps:
87-
- uses: actions/checkout@v2
88+
- uses: actions/checkout@v3
8889
- name: github branch
8990
run: |
9091
if [ "${{ github.event.release.target_commitish }}" != "" ]; then
@@ -100,16 +101,17 @@ jobs:
100101
else
101102
echo "CLOWDER_VERSION=testing" >> $GITHUB_ENV
102103
fi
103-
- uses: actions/setup-java@v1
104+
- uses: actions/setup-java@v3
104105
with:
105-
java-version: 1.8
106+
distribution: 'zulu'
107+
java-version: 8
106108
- name: Cache SBT ivy cache
107-
uses: actions/cache@v1
109+
uses: actions/cache@v3
108110
with:
109111
path: ~/.ivy2/cache
110112
key: ${{ runner.os }}-sbt-ivy-cache-${{ hashFiles('project/Build.scala') }}
111113
- name: Cache SBT
112-
uses: actions/cache@v1
114+
uses: actions/cache@v3
113115
with:
114116
path: ~/.sbt
115117
key: ${{ runner.os }}-sbt-${{ hashFiles('project/Build.scala') }}
@@ -128,7 +130,7 @@ jobs:
128130
runs-on: ubuntu-latest
129131
needs: build
130132
steps:
131-
- uses: actions/checkout@v2
133+
- uses: actions/checkout@v3
132134
- name: github branch
133135
run: |
134136
if [ "${{ github.event.release.target_commitish }}" != "" ]; then
@@ -144,16 +146,17 @@ jobs:
144146
else
145147
echo "CLOWDER_VERSION=testing" >> $GITHUB_ENV
146148
fi
147-
- uses: actions/setup-java@v1
149+
- uses: actions/setup-java@v3
148150
with:
149-
java-version: 1.8
151+
distribution: 'zulu'
152+
java-version: 8
150153
- name: Cache SBT ivy cache
151-
uses: actions/cache@v1
154+
uses: actions/cache@v3
152155
with:
153156
path: ~/.ivy2/cache
154157
key: ${{ runner.os }}-sbt-ivy-cache-${{ hashFiles('project/Build.scala') }}
155158
- name: Cache SBT
156-
uses: actions/cache@v1
159+
uses: actions/cache@v3
157160
with:
158161
path: ~/.sbt
159162
key: ${{ runner.os }}-sbt-${{ hashFiles('project/Build.scala') }}
@@ -204,7 +207,7 @@ jobs:
204207
runs-on: ubuntu-latest
205208
needs: build
206209
steps:
207-
- uses: actions/checkout@v2
210+
- uses: actions/checkout@v3
208211
- name: github branch
209212
run: |
210213
if [ "${{ github.event.release.target_commitish }}" != "" ]; then
@@ -220,16 +223,17 @@ jobs:
220223
else
221224
echo "CLOWDER_VERSION=testing" >> $GITHUB_ENV
222225
fi
223-
- uses: actions/setup-java@v1
226+
- uses: actions/setup-java@v3
224227
with:
225-
java-version: 1.8
228+
distribution: 'zulu'
229+
java-version: 8
226230
- name: Cache SBT ivy cache
227-
uses: actions/cache@v1
231+
uses: actions/cache@v3
228232
with:
229233
path: ~/.ivy2/cache
230234
key: ${{ runner.os }}-sbt-ivy-cache-${{ hashFiles('project/Build.scala') }}
231235
- name: Cache SBT
232-
uses: actions/cache@v1
236+
uses: actions/cache@v3
233237
with:
234238
path: ~/.sbt
235239
key: ${{ runner.os }}-sbt-${{ hashFiles('project/Build.scala') }}

.github/workflows/swagger.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
lint:
2121
runs-on: ubuntu-latest
2222
steps:
23-
- uses: actions/checkout@v2
23+
- uses: actions/checkout@v3
2424

2525
- name: openapi-lint
2626
uses: mbowman100/swagger-validator-action@master

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ doc/src/sphinx/_build
3030
.DS_Store
3131
/doc/src/sphinx/_build
3232
**/.c9/*
33+
*~

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,30 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/)
66
and this project adheres to [Semantic Versioning](http://semver.org/).
77

8+
## 1.22.0 - 2023-09-12
9+
10+
### Added
11+
- Users can be marked as ReadOnly [#405](https://github.com/clowder-framework/clowder/issues/405)
12+
- Delete button to delete section [#347](https://github.com/clowder-framework/clowder/issues/347)
13+
- When parameter on API endpoints to enable pagination [#266](https://github.com/clowder-framework/clowder/issues/266)
14+
- Extractors can now specify an extractor_key and an owner (email address) when sending a
15+
registration or heartbeat to Clowder that will restrict use of that extractor to them.
16+
- Added a dropdown menu to space listing to select all spaces, your spaces and also the spaces you have access to. [#374](https://github.com/clowder-framework/clowder/issues/374)
17+
- Support for SMTP_FROM in docker-compose yml file. [#417](https://github.com/clowder-framework/clowder/issues/417)
18+
- Keycloak provider with secure social [#419](https://github.com/clowder-framework/clowder/issues/419)
19+
- Documentation on how to do easy testing of pull requests
20+
- citation.cff
21+
- New GET sections endpoint to file API and fix missing section routes in javascriptRoutes [#410](https://github.com/clowder-framework/clowder/pull/410)
22+
- Google's model viewer within viewer_three.js previewer
23+
24+
### Fixed
25+
- Updated lastModifiesDate when updating file or metadata to a dataset, added lastModified to UI [386](https://github.com/clowder-framework/clowder/issues/386)
26+
- Disabled button after creating new dataset [#311](https://github.com/clowder-framework/clowder/issues/311)
27+
- Changed default to 'Viewer' while inviting users to new spaces [#375](https://github.com/clowder-framework/clowder/issues/375)
28+
- Complex extracted JSON metadata objects using arrays are now being indexed properly for search.
29+
- Fixed positioning problems related to how the 3D models appear on the screen
30+
- Search results are checked to verify nothing has been put in trash before display [#377](https://github.com/clowder-framework/clowder/issues/377)
31+
- Previewer source URL in the documentation to point to the Clowder GitHub repo. [#395](https://github.com/clowder-framework/clowder/issues/395)
832

933
## 1.21.0 - 2022-08-23
1034

CONTRIBUTORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Following is a list of contributors in alphabetical order:
2020
- Kastan Day
2121
- Kaveh Karimi-Asli
2222
- Kenton McHenry
23+
- Lachlan Deakin
2324
- Luigi Marini
2425
- Maria-Spyridoula Tzima
2526
- Mario Felarca

TESTING.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Testing Clowder PR
2+
3+
Download the [docker-compose.yml](https://raw.githubusercontent.com/clowder-framework/clowder/develop/docker-compose.yml) file in a new folder. Next create a .env file with the following data:
4+
5+
```ini
6+
COMPOSE_PROJECT_NAME=clowder
7+
TRAEFIK_HOST=Host:yourmachine.ncsa.illinois.edu;
8+
TRAEFIK_HTTP_PORT=80
9+
TRAEFIK_HTTPS_PORT=443
10+
TRAEFIK_HTTPS_OPTIONS=TLS
11+
TRAEFIK_ACME_ENABLE=true
12+
TRAEFIK_ACME_EMAIL[email protected]
13+
TRAEFIK_HTTP_REDIRECT=Redirect.EntryPoint:https
14+
CLOWDER_SSL=true
15+
CLOWDER_ADMINS[email protected]
16+
```
17+
18+
Next create a docker-compose.override.yml file:
19+
20+
```yaml
21+
version: '3.5'
22+
23+
services:
24+
# point to the PR image (in this case PR-404)
25+
clowder:
26+
image: ghcr.io/clowder-framework/clowder:PR-404
27+
28+
# add any more extractors if you want
29+
# extract preview image
30+
imagepreview:
31+
image: clowder/extractors-image-preview:latest
32+
restart: unless-stopped
33+
networks:
34+
- clowder
35+
depends_on:
36+
rabbitmq:
37+
condition: service_started
38+
environment:
39+
- RABBITMQ_URI=${RABBITMQ_URI:-amqp://guest:guest@rabbitmq/%2F}
40+
41+
# extract image metadata
42+
imagemetadata:
43+
image: clowder/extractors-image-metadata:latest
44+
restart: unless-stopped
45+
networks:
46+
- clowder
47+
depends_on:
48+
rabbitmq:
49+
condition: service_started
50+
environment:
51+
- RABBITMQ_URI=${RABBITMQ_URI:-amqp://guest:guest@rabbitmq/%2F}
52+
53+
# digest
54+
digest:
55+
image: clowder/extractors-digest:latest
56+
restart: unless-stopped
57+
networks:
58+
- clowder
59+
depends_on:
60+
rabbitmq:
61+
condition: service_started
62+
environment:
63+
- RABBITMQ_URI=${RABBITMQ_URI:-amqp://guest:guest@rabbitmq/%2F}
64+
```
65+
66+
It is best practice to start with a `docker-compose pull` to make sure you have all the latest versions of the containers, followed by a `docker-compose up -d`. This will start all containers. You should be able to go to https://yourmachine.ncsa.illinois.edu.
67+
68+
If this is the first time running the stack (or if you removed the mongo database), you will need to create the initial user again:
69+
70+
```bash
71+
docker run --rm -it \
72+
--network clowder_clowder \
73+
-e "FIRSTNAME=Admin" \
74+
-e "LASTNAME=User" \
75+
-e "ADMIN=true" \
76+
-e "PASSWORD=areallygoodpassword" \
77+
78+
-e "MONGO_URI=mongodb://mongo:27017/clowder" \
79+
clowder/mongo-init
80+
```
81+
82+

app/api/Admin.scala

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,10 @@ class Admin @Inject() (userService: UserService,
125125
list.foreach(id =>
126126
userService.findById(UUID(id)) match {
127127
case Some(u: ClowderUser) => {
128-
if (u.status == UserStatus.Inactive) {
128+
if (u.status != UserStatus.Active) {
129129
userService.update(u.copy(status = UserStatus.Active))
130-
val subject = s"[${AppConfiguration.getDisplayName}] account activated"
131-
val body = views.html.emails.userActivated(u, active = true)(request)
130+
val subject = s"[${AppConfiguration.getDisplayName}] account is now active"
131+
val body = views.html.emails.userChanged(u, "activated")(request)
132132
util.Mail.sendEmail(subject, request.user, u, body)
133133
}
134134
}
@@ -138,10 +138,10 @@ class Admin @Inject() (userService: UserService,
138138
list.foreach(id =>
139139
userService.findById(UUID(id)) match {
140140
case Some(u: ClowderUser) => {
141-
if (!(u.status == UserStatus.Inactive)) {
141+
if (u.status != UserStatus.Inactive) {
142142
userService.update(u.copy(status = UserStatus.Inactive))
143-
val subject = s"[${AppConfiguration.getDisplayName}] account deactivated"
144-
val body = views.html.emails.userActivated(u, active = false)(request)
143+
val subject = s"[${AppConfiguration.getDisplayName}] account is deactivated"
144+
val body = views.html.emails.userChanged(u, "deactivated")(request)
145145
util.Mail.sendEmail(subject, request.user, u, body)
146146
}
147147
}
@@ -150,26 +150,27 @@ class Admin @Inject() (userService: UserService,
150150
(request.body \ "admin").asOpt[List[String]].foreach(list =>
151151
list.foreach(id =>
152152
userService.findById(UUID(id)) match {
153-
case Some(u: ClowderUser) if (u.status == UserStatus.Active) => {
154-
155-
userService.update(u.copy(status = UserStatus.Admin))
156-
val subject = s"[${AppConfiguration.getDisplayName}] admin access granted"
157-
val body = views.html.emails.userAdmin(u, admin = true)(request)
158-
util.Mail.sendEmail(subject, request.user, u, body)
159-
153+
case Some(u: ClowderUser) => {
154+
if (u.status != UserStatus.Admin) {
155+
userService.update(u.copy(status = UserStatus.Admin))
156+
val subject = s"[${AppConfiguration.getDisplayName}] account is now an admin"
157+
val body = views.html.emails.userChanged(u, "an admin account")(request)
158+
util.Mail.sendEmail(subject, request.user, u, body)
159+
}
160160
}
161161
case _ => Logger.error(s"Could not update user with id=${id}")
162162
}))
163-
(request.body \ "unadmin").asOpt[List[String]].foreach(list =>
163+
(request.body \ "readonly").asOpt[List[String]].foreach(list =>
164164
list.foreach(id =>
165165
userService.findById(UUID(id)) match {
166-
case Some(u: ClowderUser) if (u.status == UserStatus.Admin) => {
167-
userService.update(u.copy(status = UserStatus.Active))
168-
val subject = s"[${AppConfiguration.getDisplayName}] admin access revoked"
169-
val body = views.html.emails.userAdmin(u, admin = false)(request)
170-
util.Mail.sendEmail(subject, request.user, u, body)
166+
case Some(u: ClowderUser) => {
167+
if (u.status != UserStatus.ReadOnly) {
168+
userService.update(u.copy(status = UserStatus.ReadOnly))
169+
val subject = s"[${AppConfiguration.getDisplayName}] account is now an read-only"
170+
val body = views.html.emails.userChanged(u, "read-only")(request)
171+
util.Mail.sendEmail(subject, request.user, u, body)
172+
}
171173
}
172-
173174
case _ => Logger.error(s"Could not update user with id=${id}")
174175
}))
175176
Ok(toJson(Map("status" -> "success")))

app/api/ApiController.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,13 @@ trait ApiController extends Controller {
8888
userRequest.user match {
8989
case Some(u) if !AppConfiguration.acceptedTermsOfServices(u.termsOfServices) => Future.successful(Unauthorized("Terms of Service not accepted"))
9090
case Some(u) if (u.status == UserStatus.Inactive) => Future.successful(Unauthorized("Account is not activated"))
91+
case Some(u) if (u.status == UserStatus.ReadOnly && !api.Permission.READONLY.contains(permission) && permission != Permission.DownloadFiles) => Future.successful(Unauthorized("Account is ReadOnly"))
9192
case Some(u) if u.superAdminMode || Permission.checkPermission(userRequest.user, permission, resourceRef) => block(userRequest)
9293
case Some(u) => {
9394
affectedResource match {
9495
case Some(resource) if Permission.checkOwner(u, resource) => block(userRequest)
9596
case _ => Future.successful(Unauthorized("Not authorized"))
96-
}
97+
}
9798
}
9899
case None if Permission.checkPermission(userRequest.user, permission, resourceRef) => block(userRequest)
99100
case _ => Future.successful(Unauthorized("Not authorized"))

app/api/Collections.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ class Collections @Inject() (datasets: DatasetService,
157157
case Some(collection) => {
158158
val useTrash = play.api.Play.configuration.getBoolean("useTrash").getOrElse(false)
159159
if (!useTrash || (useTrash && collection.trash)){
160+
Logger.debug("Deleting collection from indexes " + collectionId)
161+
current.plugin[ElasticsearchPlugin].foreach {
162+
_.delete(collectionId.stringify)
163+
}
160164
events.addObjectEvent(request.user , collection.id, collection.name, EventType.DELETE_COLLECTION.toString)
161165
collections.delete(collectionId)
162166
current.plugin[AdminsNotifierPlugin].foreach {

app/api/Datasets.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,7 @@ class Datasets @Inject()(
882882

883883
datasets.index(id)
884884
Ok(toJson(Map("status" -> "success")))
885+
885886
}
886887
case None => Logger.error(s"Error getting dataset $id"); NotFound(toJson(s"Error getting dataset $id"))
887888
}
@@ -928,6 +929,7 @@ class Datasets @Inject()(
928929
events.addObjectEvent(request.user, id, x.name, EventType.ADD_METADATA_DATASET.toString)
929930

930931
datasets.index(id)
932+
931933
Ok(toJson("Metadata successfully added to db"))
932934
}
933935
case e: JsError => {
@@ -2039,6 +2041,11 @@ class Datasets @Inject()(
20392041
def deleteDatasetHelper(id: UUID, request: UserRequest[AnyContent]) = {
20402042
datasets.get(id) match {
20412043
case Some(dataset) => {
2044+
Logger.debug("Deleting dataset from indexes " + id)
2045+
current.plugin[ElasticsearchPlugin].foreach {
2046+
_.delete(id.stringify)
2047+
}
2048+
20422049
//remove dataset from RDF triple store if triple store is used
20432050
configuration.getString("userdfSPARQLStore").getOrElse("no") match {
20442051
case "yes" => rdfsparql.removeDatasetFromGraphs(id)

0 commit comments

Comments
 (0)