Skip to content

Commit 5341e90

Browse files
authored
Merge branch 'develop' into bugfix/257-collection-api-create
2 parents 023a90c + 3e27a54 commit 5341e90

File tree

8 files changed

+70
-43
lines changed

8 files changed

+70
-43
lines changed

CHANGELOG.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,27 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/)
55
and this project adheres to [Semantic Versioning](http://semver.org/).
66

7-
## unreleased
7+
## 1.18.1 - 2021-08-16
8+
9+
This release fixes a critical issue where invalid zip files could result in the files not being uploaded correctly. To check to see if you are affected, please use the following query:
10+
11+
```
12+
db.uploads.find({"status": "CREATED", "contentType": "application/x-zip-compressed"}, {"author.fullName": 1, "author.email": 1, "filename": 1, "uploadDate": 1, "length": 1})
13+
```
14+
15+
If any files are returned, you should check to see if these files affected and are missing from clowder.
816

917
### Fixed
18+
- When zip file is uploaded, it will parse the file to check if it is a valid zip file, this couuld result in files not stored in final storage space [#264](https://github.com/clowder-framework/clowder/issues/264)
1019
- Updated swagger documentation
1120
- Return 404 not found when calling file/dataset/space api endpoints with an invalid ID [#251](https://github.com/clowder-framework/clowder/issues/251)
21+
- Line breaks in welcome message breaks swagger build [#187](https://github.com/clowder-framework/clowder/issues/187)
1222
- Collections created using api route are now indexed upon creation. [#257](https://github.com/clowder-framework/clowder/issues/257)
1323

24+
### Changed
25+
- Added more information when writing files to make sure files are written correctly
26+
- Made cilogon group check debug message instead of error message
27+
1428
## 1.18.0 - 2021-07-08
1529

1630
### Added

app/controllers/Application.scala

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ import scala.collection.mutable.ListBuffer
1616
* Main application controller.
1717
*/
1818
@Singleton
19-
class Application @Inject() (files: FileService, collections: CollectionService, datasets: DatasetService,
20-
spaces: SpaceService, events: EventService, comments: CommentService,
21-
sections: SectionService, users: UserService, selections: SelectionService) extends SecuredController {
19+
class Application @Inject()(files: FileService, collections: CollectionService, datasets: DatasetService,
20+
spaces: SpaceService, events: EventService, comments: CommentService,
21+
sections: SectionService, users: UserService, selections: SelectionService) extends SecuredController {
2222
/**
2323
* Redirect any url's that have a trailing /
2424
*
@@ -34,10 +34,10 @@ class Application @Inject() (files: FileService, collections: CollectionService,
3434
Redirect("http://clowder.ncsa.illinois.edu/swagger/?url=" + swagger)
3535
}
3636

37-
/**
38-
* Returns the swagger documentation customized for this site.
39-
*/
40-
def swagger = Action { implicit request =>
37+
/**
38+
* Returns the swagger documentation customized for this site.
39+
*/
40+
def swagger = Action { implicit request =>
4141
Play.resource("/public/swagger.yml") match {
4242
case Some(resource) => {
4343
val https = Utils.https(request)
@@ -62,7 +62,8 @@ class Application @Inject() (files: FileService, collections: CollectionService,
6262
skipit = true
6363
"info:\n" +
6464
" title: " + AppConfiguration.getDisplayName + "\n" +
65-
" description: " + AppConfiguration.getWelcomeMessage + "\n" +
65+
// replace line breaks with space so swagger can build
66+
" description: " + AppConfiguration.getWelcomeMessage.replaceAll("\\n|\\r|\\r\\n", " ") + "\n" +
6667
" version: \"" + sys.props.getOrElse("build.version", default = "0.0.0").toString + "\"\n" +
6768
" termsOfService: " + routes.Application.tos().absoluteURL(https) + "\n" +
6869
" contact: " + "\n" +
@@ -89,29 +90,29 @@ class Application @Inject() (files: FileService, collections: CollectionService,
8990
def index = UserAction(needActive = false) { implicit request =>
9091
val appConfig: AppConfigurationService = DI.injector.getInstance(classOf[AppConfigurationService])
9192

92-
implicit val user = request.user
93+
implicit val user = request.user
9394

9495
var newsfeedEvents = List.empty[Event]
9596
if (!play.Play.application().configuration().getBoolean("clowder.disable.events", false)) {
9697
newsfeedEvents = user.fold(List.empty[Event])(u => events.getEvents(u.followedEntities, Some(20)))
97-
newsfeedEvents = newsfeedEvents ::: events.getRequestEvents(user, Some(20))
98+
newsfeedEvents = newsfeedEvents ::: events.getRequestEvents(user, Some(20))
9899
if (user.isDefined) {
99100
newsfeedEvents = (newsfeedEvents ::: events.getEventsByUser(user.get, Some(20)))
100101
.sorted(Ordering.by((_: Event).created).reverse).distinct.take(20)
101102
}
102103
}
103104

104105
user match {
105-
case Some(clowderUser) if (clowderUser.status==UserStatus.Inactive) => {
106+
case Some(clowderUser) if (clowderUser.status == UserStatus.Inactive) => {
106107
Redirect(routes.Error.notActivated())
107108
}
108-
case Some(clowderUser) if !(clowderUser.status==UserStatus.Inactive) => {
109+
case Some(clowderUser) if !(clowderUser.status == UserStatus.Inactive) => {
109110
newsfeedEvents = newsfeedEvents ::: events.getEventsByUser(clowderUser, Some(20))
110-
if( play.Play.application().configuration().getBoolean("showCommentOnHomepage")) newsfeedEvents = newsfeedEvents :::events.getCommentEvent(clowderUser, Some(20))
111+
if (play.Play.application().configuration().getBoolean("showCommentOnHomepage")) newsfeedEvents = newsfeedEvents ::: events.getCommentEvent(clowderUser, Some(20))
111112
newsfeedEvents = newsfeedEvents.sorted(Ordering.by((_: Event).created).reverse).distinct.take(20)
112113
val datasetsUser = datasets.listUser(12, Some(clowderUser), request.user.fold(false)(_.superAdminMode), clowderUser)
113114
val collectionList = collections.listUser(12, Some(clowderUser), request.user.fold(false)(_.superAdminMode), clowderUser)
114-
val collectionsWithThumbnails = collectionList.map {c =>
115+
val collectionsWithThumbnails = collectionList.map { c =>
115116
if (c.thumbnail_id.isDefined) {
116117
c
117118
} else {
@@ -126,7 +127,7 @@ class Application @Inject() (files: FileService, collections: CollectionService,
126127
for (aCollection <- collectionsWithThumbnails) {
127128
decodedCollections += Utils.decodeCollectionElements(aCollection)
128129
}
129-
val spacesUser = spaces.listUser(12, Some(clowderUser),request.user.fold(false)(_.superAdminMode), clowderUser)
130+
val spacesUser = spaces.listUser(12, Some(clowderUser), request.user.fold(false)(_.superAdminMode), clowderUser)
130131
var followers: List[(UUID, String, String, String)] = List.empty
131132
for (followerID <- clowderUser.followers.take(3)) {
132133
val userFollower = users.findById(followerID)
@@ -190,12 +191,12 @@ class Application @Inject() (files: FileService, collections: CollectionService,
190191
}
191192
Logger.debug("User selections" + user)
192193
val userSelections: List[String] =
193-
if(user.isDefined) selections.get(user.get.identityId.userId).map(_.id.stringify)
194+
if (user.isDefined) selections.get(user.get.identityId.userId).map(_.id.stringify)
194195
else List.empty[String]
195196
Logger.debug("User selection " + userSelections)
196197
Ok(views.html.home(AppConfiguration.getDisplayName, newsfeedEvents, clowderUser, datasetsUser,
197198
decodedCollections.toList, spacesUser, true, followers, followedUsers.take(12), followedFiles.take(8),
198-
followedDatasets.take(8), followedCollections.take(8),followedSpaces.take(8), Some(true), userSelections))
199+
followedDatasets.take(8), followedCollections.take(8), followedSpaces.take(8), Some(true), userSelections))
199200
}
200201
case _ => {
201202
// Set bytes from appConfig
@@ -234,10 +235,10 @@ class Application @Inject() (files: FileService, collections: CollectionService,
234235
val sanitezedWelcomeText = sanitizeHTML(AppConfiguration.getWelcomeMessage)
235236

236237
Ok(views.html.index(datasetsCount, filesCount, filesBytes, collectionsCount,
237-
spacesCount, usersCount, AppConfiguration.getDisplayName, sanitezedWelcomeText))
238+
spacesCount, usersCount, AppConfiguration.getDisplayName, sanitezedWelcomeText))
238239
}
239240

240-
def email(subject: String, body: String) = UserAction(needActive=false) { implicit request =>
241+
def email(subject: String, body: String) = UserAction(needActive = false) { implicit request =>
241242
if (request.user.isEmpty) {
242243
Redirect(routes.Application.index())
243244
} else {
@@ -252,10 +253,10 @@ class Application @Inject() (files: FileService, collections: CollectionService,
252253
Ok(views.html.tos(redirect))
253254
}
254255

255-
def options(path:String) = UserAction(needActive = false) { implicit request =>
256+
def options(path: String) = UserAction(needActive = false) { implicit request =>
256257
Logger.debug("---controller: PreFlight Information---")
257258
Ok("")
258-
}
259+
}
259260

260261
def healthz() = Action { implicit request =>
261262
Ok("healthy")
@@ -269,7 +270,7 @@ class Application @Inject() (files: FileService, collections: CollectionService,
269270
}
270271

271272
/**
272-
* Javascript routing.
273+
* Javascript routing.
273274
*/
274275
def javascriptRoutes = Action { implicit request =>
275276
Ok(
@@ -543,7 +544,7 @@ class Application @Inject() (files: FileService, collections: CollectionService,
543544
controllers.routes.javascript.FileLinks.createLink,
544545
controllers.routes.javascript.Search.search
545546
)
546-
).as(JSON)
547+
).as(JSON)
547548
}
548549

549550
}

app/fileutils/FilesUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ else if(!fileName.toLowerCase().endsWith(".ptm")){
7171
if(allPTMsFlag.equals("found"))
7272
return "multi/files-ptm-zipped";
7373

74-
} catch (IOException e) {
75-
// TODO Auto-generated catch block
74+
} catch (Throwable e) {
75+
Logger.error("Could not read zipfile", e);
7676
return ("ERROR: " + e.getMessage());
7777
}
7878
return mainFileType;

app/services/CILogonProvider.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class CILogonProvider(application: Application) extends OAuth2Provider(applicati
5757
}
5858
}
5959
case (Some(_), None) => throw new AuthenticationException()
60-
case (None, _) => Logger.error("[securesocial] No check needed for groups")
60+
case (None, _) => Logger.debug("[securesocial] No check needed for groups")
6161
}
6262
user.copy(
6363
identityId = IdentityId(userId, id),

app/util/FileUtils.scala

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -399,14 +399,19 @@ object FileUtils {
399399
val fileExecutionContext: ExecutionContext = Akka.system().dispatchers.lookup("akka.actor.contexts.file-processing")
400400
Future {
401401
try {
402-
saveFile(file, f.ref.file, originalZipFile, clowderurl, apiKey, Some(user)).foreach { fixedfile =>
403-
processFileBytes(fixedfile, f.ref.file, dataset)
404-
files.setStatus(fixedfile.id, FileStatus.UPLOADED)
405-
sinkService.logFileUploadEvent(fixedfile, dataset, Option(user))
406-
processFile(fixedfile, clowderurl, index, flagsFromPrevious, showPreviews, dataset, runExtractors, apiKey)
407-
processDataset(file, dataset, folder, clowderurl, user, index, runExtractors, apiKey)
408-
files.setStatus(fixedfile.id, FileStatus.PROCESSED)
402+
saveFile(file, f.ref.file, originalZipFile, clowderurl, apiKey, Some(user)) match {
403+
case Some(fixedfile) => {
404+
processFileBytes(fixedfile, f.ref.file, dataset)
405+
files.setStatus(fixedfile.id, FileStatus.UPLOADED)
406+
sinkService.logFileUploadEvent(fixedfile, dataset, Option(user))
407+
processFile(fixedfile, clowderurl, index, flagsFromPrevious, showPreviews, dataset, runExtractors, apiKey)
408+
processDataset(file, dataset, folder, clowderurl, user, index, runExtractors, apiKey)
409+
files.setStatus(fixedfile.id, FileStatus.PROCESSED)
410+
}
411+
case None => Logger.error(s"File was not saved for ${file.id}, saveFile returned None")
409412
}
413+
} catch {
414+
case e: Throwable => Logger.error(s"File was not saved for ${file.id}", e)
410415
} finally {
411416
f.ref.clean()
412417
}
@@ -455,12 +460,19 @@ object FileUtils {
455460
// process rest of file in background
456461
val fileExecutionContext: ExecutionContext = Akka.system().dispatchers.lookup("akka.actor.contexts.file-processing")
457462
Future {
458-
saveURL(file, url, clowderurl, apiKey, Some(user)).foreach { fixedfile =>
459-
processFileBytes(fixedfile, new java.io.File(path), fileds)
460-
files.setStatus(fixedfile.id, FileStatus.UPLOADED)
461-
processFile(fixedfile, clowderurl, index, flagsFromPrevious, showPreviews, fileds, runExtractors, apiKey)
462-
processDataset(file, fileds, folder, clowderurl, user, index, runExtractors, apiKey)
463-
files.setStatus(fixedfile.id, FileStatus.PROCESSED)
463+
try {
464+
saveURL(file, url, clowderurl, apiKey, Some(user)) match{
465+
case Some(fixedfile) => {
466+
processFileBytes(fixedfile, new java.io.File(path), fileds)
467+
files.setStatus(fixedfile.id, FileStatus.UPLOADED)
468+
processFile(fixedfile, clowderurl, index, flagsFromPrevious, showPreviews, fileds, runExtractors, apiKey)
469+
processDataset(file, fileds, folder, clowderurl, user, index, runExtractors, apiKey)
470+
files.setStatus(fixedfile.id, FileStatus.PROCESSED)
471+
}
472+
case None => Logger.error(s"File was not saved for ${file.id}, saveFile returned None")
473+
}
474+
} catch {
475+
case e: Throwable => Logger.error(s"File was not saved for ${file.id}", e)
464476
}
465477
}(fileExecutionContext)
466478

doc/src/sphinx/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
author = 'Luigi Marini'
2323

2424
# The full version, including alpha/beta/rc tags
25-
release = '1.18.0'
25+
release = '1.18.1'
2626

2727

2828
# -- General configuration ---------------------------------------------------

project/Build.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import NativePackagerKeys._
1313
object ApplicationBuild extends Build {
1414

1515
val appName = "clowder"
16-
val version = "1.18.0"
16+
val version = "1.18.1"
1717
val jvm = "1.7"
1818

1919
def appVersion: String = {

public/swagger.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ info:
99
Clowder is a customizable and scalable data management system to support any
1010
data format and multiple research domains. It is under active development
1111
and deployed for a variety of research projects.
12-
version: 1.18.0
12+
version: 1.18.1
1313
termsOfService: https://clowder.ncsa.illinois.edu/clowder/tos
1414
contact:
1515
name: Clowder

0 commit comments

Comments
 (0)