Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# File-Uploader Plugin (Latest 4.0.0)
# File-Uploader Plugin (Latest 4.0.1)

[![Maintainability](https://api.codeclimate.com/v1/badges/13bfee73c29ecd2ea4b2/maintainability)](https://codeclimate.com/github/causecode/grails-file-uploader/maintainability)
[![Test Coverage](https://api.codeclimate.com/v1/badges/13bfee73c29ecd2ea4b2/test_coverage)](https://codeclimate.com/github/causecode/grails-file-uploader/test_coverage)

File-Uploader Plugin >= 4.0.0 supports Grails 3.3.x (Tested with 3.3.5)
File-Uploader Plugin >= 4.0.1 supports Grails 3.3.x (Tested with 3.3.5)
File-Uploader Plugin <= 3.1.x supports Grails 3.2.x (Tested upto 3.2.5)

# For Grails 2.x refer branch [here](https://github.com/causecode/grails-file-uploader/tree/grails-2.x-master)
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ buildscript {
}
}

version "4.0.0"
version "4.0.1"
group "com.causecode.plugins"

apply plugin: "idea"
Expand Down
7 changes: 6 additions & 1 deletion changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# ChangeLog

## Version 4.0.0 [Unreleased]
## Version 4.0.1 [Unreleased]

### Added
- Field to store the container name in UFile domain.

## Version 4.0.0 [19-12-2018]

### Changed
- Upgraded the plugin to support grails 3.3.5
Expand Down
1 change: 1 addition & 0 deletions grails-app/conf/application.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ fileuploader {
maxSize = 1024 * 1024 * 2 // 2 MB
allowedExtensions = ["jpg", "jpeg", "gif", "png", "txt"]
path = '/tmp'
container = 'test-container'
}
}

Expand Down
8 changes: 5 additions & 3 deletions grails-app/domain/com/causecode/fileuploader/UFile.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class UFile implements Serializable {
String fileGroup
String name
String path
String containerName // Name of the cloud container.

//Contains calculated hash value of file content
String checksum
Expand Down Expand Up @@ -65,6 +66,7 @@ class UFile implements Serializable {
dateCreated bindable: false
lastUpdated bindable: false
envName bindable: false
containerName size: 3..63, nullable: true
}

static mapping = {
Expand Down Expand Up @@ -103,8 +105,8 @@ class UFile implements Serializable {
new File(path).exists()
}

String getContainer() {
containerName(Holders.flatConfig["fileuploader.groups.${fileGroup}.container"])
String getContainerFromConfig() {
containerNameFromConfig(Holders.flatConfig["fileuploader.groups.${fileGroup}.container"])
}

String getFullName() {
Expand All @@ -124,7 +126,7 @@ class UFile implements Serializable {
* @param containerName Name of the Amazon file container or Google bucket.
* @return Modified container name as described above.
*/
static String containerName(String containerName) {
static String containerNameFromConfig(String containerName) {
if (!containerName) {
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ class FileUploaderService {
FileGroup fileGroupInstance = new FileGroup(group)
ChecksumValidator checksumValidator = new ChecksumValidator(fileGroupInstance)

String containerName

if (checksumValidator.shouldCalculateChecksum()) {
UFile uFileInstance = UFile.findByChecksumAndChecksumAlgorithm(checksumValidator.getChecksum(file),
checksumValidator.algorithm)
Expand Down Expand Up @@ -100,6 +102,7 @@ class FileUploaderService {
throw new StorageConfigurationException('Provider not defined in the Config. Please define one.')
}

containerName = getContainerNameFromConfig(fileGroupInstance)
expireOn = isPublicGroup(group) ? null : new Date(new Date().time + expirationPeriod * 1000)
path = uploadFileToCloud(fileData, fileGroupInstance, tempFile)
} else {
Expand All @@ -110,7 +113,8 @@ class FileUploaderService {

UFile ufile = new UFile(
[name : fileData.fileName, size: fileData.fileSize, path: path, type: type,
extension: fileData.fileExtension, expiresOn: expireOn, fileGroup: group, provider: cdnProvider])
extension: fileData.fileExtension, expiresOn: expireOn, fileGroup: group, provider: cdnProvider,
containerName: containerName])

if (checksumValidator.shouldCalculateChecksum()) {
ufile.checksum = checksumValidator.getChecksum(file)
Expand All @@ -121,6 +125,23 @@ class FileUploaderService {
return ufile
}

/**
* This method checks if the configuration {@link FileGroup} contains the {@link String} container name.
*
* @param fileGroup {@link FileGroup}
* @return {@link String} - containerName
* @throws StorageConfigurationException - When container name is not defined.
*/
private static String getContainerNameFromConfig(FileGroup fileGroup) throws StorageConfigurationException {
String containerName = fileGroup.containerName

if (!containerName) {
throw new StorageConfigurationException('Container name not defined in the Config. Please define one.')
}

return containerName
}

/**
* Method is used to upload file to cloud provider. Then it gets the path of uploaded file
* @params fileData , fileGroupInstance, tempFile
Expand Down Expand Up @@ -177,7 +198,7 @@ class FileUploaderService {
CDNFileUploader fileUploaderInstance
try {
fileUploaderInstance = providerService.getProviderInstance(ufileInstance.provider.name())
fileUploaderInstance.deleteFile(ufileInstance.container, ufileInstance.fullName)
fileUploaderInstance.deleteFile(ufileInstance.containerFromConfig, ufileInstance.fullName)
} finally {
fileUploaderInstance?.close()
}
Expand Down Expand Up @@ -375,7 +396,7 @@ class FileUploaderService {
Boolean makePublic = isPublicGroup(uFileInstance.fileGroup)
long expirationPeriod = getExpirationPeriod(uFileInstance.fileGroup)

amazonFileUploaderInstance.updatePreviousFileMetaData(uFileInstance.container,
amazonFileUploaderInstance.updatePreviousFileMetaData(uFileInstance.containerFromConfig,
uFileInstance.fullName, makePublic, expirationPeriod)
}

Expand Down Expand Up @@ -452,13 +473,13 @@ class FileUploaderService {
CDNFileUploader fileUploaderInstance
try {
fileUploaderInstance = providerService.getProviderInstance(toCDNProvider.name())
fileUploaderInstance.uploadFile(uFile.container, downloadedFile, fileName, makePublic,
fileUploaderInstance.uploadFile(uFile.containerFromConfig, downloadedFile, fileName, makePublic,
expirationPeriod)

if (makePublic) {
savedUrlPath = fileUploaderInstance.getPermanentURL(uFile.container, fileName)
savedUrlPath = fileUploaderInstance.getPermanentURL(uFile.containerFromConfig, fileName)
} else {
savedUrlPath = fileUploaderInstance.getTemporaryURL(uFile.container, fileName,
savedUrlPath = fileUploaderInstance.getTemporaryURL(uFile.containerFromConfig, fileName,
expirationPeriod)
}
} finally {
Expand Down
4 changes: 2 additions & 2 deletions src/main/groovy/com/causecode/fileuploader/FileGroup.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,9 @@ class FileGroup {
return fileNameBuilder.toString()
}

// Method which fetches containerName from application.groovy file and returns it.
// Method which fetches container from application.groovy file and returns it.
String getContainerName() {
return UFile.containerName(this.groupConfig.container ?: this.config.container)
return UFile.containerNameFromConfig(this.groupConfig.container ?: this.config.container)
}

// Method that fetched CDNProvider from the config and returns it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class DefaultTemporaryUrlRenewer implements TemporaryUrlRenewer {
private boolean updateExpirationPeriodAndUrl(UFile uFile) {
long expirationPeriod = getExpirationPeriod(uFile.fileGroup)

uFile.path = cdnFileUploader.getTemporaryURL(uFile.container, uFile.fullName, expirationPeriod)
uFile.path = cdnFileUploader.getTemporaryURL(uFile.containerFromConfig, uFile.fullName, expirationPeriod)
uFile.expiresOn = new Date(new Date().time + expirationPeriod * 1000)

if (NucleusUtils.save(uFile, true)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ class BaseFileUploaderServiceSpecSetup extends Specification implements BaseTest
void mockFileGroupConstructor(String storageTypes) {
new FileGroup(_) >> { String group ->
fileGroupMock.groupName = group
fileGroupMock.containerName >> 'test-container'
fileGroupMock.groupConfig >> [storageTypes: storageTypes]

return fileGroupMock
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import grails.util.Holders
import groovy.json.JsonBuilder
import org.apache.commons.fileupload.disk.DiskFileItem
import org.apache.commons.validator.UrlValidator
import org.grails.plugins.codecs.HTMLCodec
import org.springframework.context.MessageSource
import org.springframework.context.i18n.LocaleContextHolder
import org.springframework.web.multipart.MultipartFile
Expand All @@ -34,7 +33,7 @@ import javax.servlet.http.Part
// Suppressed Methods counts since this class contains more than 30 methods.
@ConfineMetaClassChanges([FileUploaderService, File])
@Build([UFile, UFileMoveHistory])
@SuppressWarnings('MethodCount')
@SuppressWarnings(['MethodCount', 'FileLengthRule'])
class FileUploaderServiceSpec extends BaseFileUploaderServiceSpecSetup implements ServiceUnitTest<FileUploaderService>,
BuildDataTest {

Expand Down Expand Up @@ -92,6 +91,7 @@ class FileUploaderServiceSpec extends BaseFileUploaderServiceSpecSetup implement

new FileGroup(_) >> fileGroupMock
fileGroupMock.cdnProvider >> provider
fileGroupMock.containerName >> 'test-bucket'
fileGroupMock.groupConfig >> [storageTypes: 'CDN']

when: 'The saveFile method is called'
Expand All @@ -100,7 +100,7 @@ class FileUploaderServiceSpec extends BaseFileUploaderServiceSpecSetup implement
then: 'UFile instance should be successfully saved'
ufileInstancefile.provider == provider
ufileInstancefile.extension == 'txt'
ufileInstancefile.container == 'causecode-test'
ufileInstancefile.containerFromConfig == 'causecode-test'
ufileInstancefile.fileGroup == fileGroup

file.delete()
Expand All @@ -125,6 +125,7 @@ class FileUploaderServiceSpec extends BaseFileUploaderServiceSpecSetup implement
and: 'Mocked FileGroup class method call'
new FileGroup(_) >> fileGroupMock
fileGroupMock.cdnProvider >> CDNProvider.GOOGLE
fileGroupMock.containerName >> 'test-container'
fileGroupMock.groupConfig >> [storageTypes: 'CDN']
mockGetFileNameAndExtensions()

Expand Down Expand Up @@ -544,6 +545,7 @@ class FileUploaderServiceSpec extends BaseFileUploaderServiceSpecSetup implement
mockGetFileNameAndExtensions()
mockUploadFileMethod(true)
mockGetProviderInstance('google')
4 * fileGroupMock.containerName >> 'test-container'
5 * fileGroupMock.cdnProvider >> {
return
} >> {
Expand All @@ -565,6 +567,7 @@ class FileUploaderServiceSpec extends BaseFileUploaderServiceSpecSetup implement
then: 'Method should return instance of UFile'
result.fileGroup == 'testGoogle'
result.type == UFileType.CDN_PUBLIC
result.containerName == 'test-container'

when: 'saveFile method is hit and file belongs to StandardMultiartFile'
mockUploadFileMethod(true)
Expand Down Expand Up @@ -608,6 +611,7 @@ class FileUploaderServiceSpec extends BaseFileUploaderServiceSpecSetup implement

then: 'Method should return saved UFile instance'
result.id != null
assert result.containerName == null

when: 'saveFile method is called and error occurs while saving file'
result = service.saveFile('testLocal', commonsMultipartFileInstance, 'test')
Expand Down Expand Up @@ -787,6 +791,7 @@ class FileUploaderServiceSpec extends BaseFileUploaderServiceSpecSetup implement
and: 'Mocked FileGroup Instance'
new FileGroup(_) >> fileGroupMock
fileGroupMock.cdnProvider >> CDNProvider.GOOGLE
fileGroupMock.containerName >> 'test-container'
fileGroupMock.groupConfig >> [storageTypes: 'CDN', checksum: [calculate: true, algorithm: Algorithm.SHA1]]

and: 'The saveFile method has been already called once for given file'
Expand Down Expand Up @@ -838,5 +843,32 @@ class FileUploaderServiceSpec extends BaseFileUploaderServiceSpecSetup implement
Exception exception = thrown(IllegalArgumentException)
exception.message == "No enum constant ${Algorithm.canonicalName}.ABCD"
}
}

void "test saveFile method when container name is not defined in the config"() {
given: 'Instances of CommonsMultipartFile to upload'
File fileInstance = getFileInstance('/tmp/test.txt')

DiskFileItem fileItem = getDiskFileItemInstance(fileInstance)
CommonsMultipartFile commonsMultipartFileInstance = new CommonsMultipartFile(fileItem)

and: 'Mocked methods of FileGroup to return empty container name'
mockFileGroupConstructor('CDN')
fileGroupMock.containerName >> {
return null
}

fileGroupMock.cdnProvider >> {
return CDNProvider.GOOGLE
}

and: 'Mocked getFileNameAndExtensions method of fileGroupMock'
mockGetFileNameAndExtensions()

when: 'saveFile is called and container name is not defined'
service.saveFile('testGoogle', commonsMultipartFileInstance, 'test')

then: 'Method should throw StorageConfigurationException and message should match'
StorageConfigurationException exception = thrown(StorageConfigurationException)
exception.message == 'Container name not defined in the Config. Please define one.'
}
}
8 changes: 4 additions & 4 deletions src/test/groovy/com/causecode/fileuploader/UFileSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ class UFileSpec extends Specification implements BaseTestSetup, DomainUnitTest<U
given: 'Parameter variable'
String containerName = null

when: 'containerName method is called and containerName parameter has null value'
def result = UFile.containerName(containerName)
when: 'containerNameFromConfig method is called and containerNameFromConfig parameter has null value'
def result = UFile.containerNameFromConfig(containerName)

then: 'The method should return null'
result == null
Expand All @@ -132,9 +132,9 @@ class UFileSpec extends Specification implements BaseTestSetup, DomainUnitTest<U
return Environment.PRODUCTION
}

result = UFile.containerName(containerName)
result = UFile.containerNameFromConfig(containerName)

then: 'Method returns containerName'
then: 'Method returns containerNameFromConfig'
result == 'test'
}

Expand Down