Skip to content
This repository has been archived by the owner on Nov 7, 2023. It is now read-only.

release: v0.12.0 #90

Merged
merged 75 commits into from
Oct 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
7bca0c6
docs: Update `README` (#18)
PedroChaparro Aug 20, 2023
8ff1a42
[ci skip] chore(release): 0.0.9
shoriwe Aug 20, 2023
b502749
feat: PostgreSQL connection and Migrations (#20)
PedroChaparro Aug 21, 2023
4faa603
[ci skip] chore(release): 0.0.10
shoriwe Aug 21, 2023
e0518b9
docs: Openapi spec (#23)
PedroChaparro Aug 23, 2023
862a9f1
[ci skip] chore(release): 0.0.11
shoriwe Aug 23, 2023
84eae11
Merge branch 'main' into dev
PedroChaparro Aug 23, 2023
a30711f
[ci skip] chore(release): 0.0.12
shoriwe Aug 23, 2023
c1edb5d
fix(cd): Build the Docker image without running tests (#35)
PedroChaparro Sep 1, 2023
9b9f69b
[ci skip] chore(release): 0.0.13
shoriwe Sep 1, 2023
94e1444
Feat: Save metadata (#31)
PedroChaparro Sep 5, 2023
442c642
[ci skip] chore(release): 0.0.14
shoriwe Sep 5, 2023
9c2ec5f
ci: Add lint step (#36)
PedroChaparro Sep 6, 2023
9294959
[ci skip] chore(release): 0.0.15
shoriwe Sep 6, 2023
b1f745e
ci: Replace tagging pipeline (#42)
PedroChaparro Sep 7, 2023
7530a2b
fix(ci): Fix tagging pipeline (#43)
PedroChaparro Sep 7, 2023
7ca8be0
chore(release): v0.1.0 [skip ci]
shoriwe Sep 7, 2023
a1140d5
feat: New files are unshared by default (#44)
PedroChaparro Sep 10, 2023
c900db6
chore(release): v0.2.0 [skip ci]
shoriwe Sep 10, 2023
539d84c
docs: Update openapi spec (#45)
PedroChaparro Sep 11, 2023
d4063bd
docs(openapi): Fix overlapping routes error (#46)
PedroChaparro Sep 11, 2023
5e2ea56
fix: Update save metadata endpoint to avoid endpoints overlapping (#47)
PedroChaparro Sep 11, 2023
aa04f13
chore(release): v0.2.1 [skip ci]
shoriwe Sep 11, 2023
1c2e8ea
feat: Share files (#48)
PedroChaparro Sep 11, 2023
093ba2e
chore(release): v0.3.0 [skip ci]
shoriwe Sep 11, 2023
e1577c2
feat: Can read endpoint (#49)
PedroChaparro Sep 11, 2023
b4b35f9
chore(release): v0.4.0 [skip ci]
shoriwe Sep 11, 2023
2ef830f
refactor(tests): Global setup of HTTP server (#51)
PedroChaparro Sep 11, 2023
f66a70a
feat: Mark files as ready (#52)
PedroChaparro Sep 12, 2023
93a5bef
chore(release): v0.5.0 [skip ci]
shoriwe Sep 12, 2023
22542c6
feat: Obtain file metadata (#53)
PedroChaparro Sep 12, 2023
8930e8e
chore(release): v0.6.0 [skip ci]
shoriwe Sep 12, 2023
2abf2f0
docs(openapi): Update spec (#54)
PedroChaparro Sep 12, 2023
0323e9b
Merge branch 'main' into dev
PedroChaparro Sep 12, 2023
b7d1409
ci: Restore lint step
PedroChaparro Sep 12, 2023
d09e225
chore: Remove old files
PedroChaparro Sep 12, 2023
4111fea
feat: List files shared with user (#56)
PedroChaparro Sep 13, 2023
de696ed
chore(release): v0.7.0 [skip ci]
shoriwe Sep 13, 2023
4cbb5bb
feat: Shared with who (#57)
PedroChaparro Sep 15, 2023
be1765f
chore(release): v0.8.0 [skip ci]
shoriwe Sep 15, 2023
db1f85c
fix: Production migrations (#61)
PedroChaparro Sep 15, 2023
47bec0e
chore(release): v0.8.1 [skip ci]
shoriwe Sep 15, 2023
24fee9d
Merge branch 'main' into dev
PedroChaparro Sep 15, 2023
3aab30f
chore: Remove old directory
PedroChaparro Sep 15, 2023
6a91d21
feat: Rename files (#63)
PedroChaparro Sep 18, 2023
0d73ad3
chore(release): v0.9.0 [skip ci]
shoriwe Sep 18, 2023
21f4932
refactor: remove hashsum column (#66)
PedroChaparro Sep 19, 2023
0684246
feat: Move file (#67)
PedroChaparro Sep 21, 2023
cb497ef
chore(release): v0.10.0 [skip ci]
shoriwe Sep 21, 2023
7f63347
fix: Update is_shared column when a file is shared (#70)
PedroChaparro Sep 26, 2023
2eaa043
chore(release): v0.10.1 [skip ci]
shoriwe Sep 26, 2023
1ffd432
Merge branch 'main' into dev
PedroChaparro Sep 26, 2023
712fa39
chore: Fix merge conflicts
PedroChaparro Sep 26, 2023
fa5467f
fix: Ignore ready state validations for directories (#73)
PedroChaparro Sep 29, 2023
053743b
chore(release): v0.10.2 [skip ci]
shoriwe Sep 29, 2023
9ae4d0d
fix: Parse null-able extension field (#75)
PedroChaparro Oct 1, 2023
d5c3ba6
chore(release): v0.10.3 [skip ci]
shoriwe Oct 1, 2023
6be7dc5
Merge branch 'main' into dev
PedroChaparro Oct 1, 2023
f825a84
refactor: Use same filename in ArchiveMeta class to fix warning
PedroChaparro Oct 1, 2023
2691493
ci: Run tests when a pull request is created to main
PedroChaparro Oct 1, 2023
0286714
style: Format file
PedroChaparro Oct 1, 2023
34f60cb
style: Format file
PedroChaparro Oct 1, 2023
30dbcff
fix: Update controllers error handler (#80)
PedroChaparro Oct 3, 2023
30032cd
chore(release): v0.10.4 [skip ci]
shoriwe Oct 3, 2023
75f1559
feat: List files (#78)
PedroChaparro Oct 3, 2023
af127de
chore(release): v0.11.0 [skip ci]
shoriwe Oct 3, 2023
befc3d8
Merge branch 'main' into dev
PedroChaparro Oct 3, 2023
3e27c2d
refactor: Add logs and fix Scala warnings (#83)
PedroChaparro Oct 4, 2023
b25818c
docs(http): Add bruno collection (#84)
PedroChaparro Oct 12, 2023
8d46afa
fix: Include files size (#86)
PedroChaparro Oct 14, 2023
609b807
chore(release): v0.11.1 [skip ci]
shoriwe Oct 14, 2023
f6c9bc2
Merge branch 'main' into dev
PedroChaparro Oct 14, 2023
be58b4a
feat: Unshare file (#89)
sdbaronc Oct 22, 2023
9a6129f
chore(release): v0.12.0 [skip ci]
shoriwe Oct 22, 2023
d936167
Merge branch 'main' into dev
PedroChaparro Oct 22, 2023
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
18 changes: 9 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
# [0.12.0](https://github.com/hawks-atlanta/metadata-scala/compare/v0.11.1...v0.12.0) (2023-10-22)


### Features

* Unshare file ([#89](https://github.com/hawks-atlanta/metadata-scala/issues/89)) ([be58b4a](https://github.com/hawks-atlanta/metadata-scala/commit/be58b4ad112ebe141f88781e8ea7d04713f1bd7d))



## [0.11.1](https://github.com/hawks-atlanta/metadata-scala/compare/v0.11.0...v0.11.1) (2023-10-14)


Expand Down Expand Up @@ -34,12 +43,3 @@



## [0.10.2](https://github.com/hawks-atlanta/metadata-scala/compare/v0.10.1...v0.10.2) (2023-09-29)


### Bug Fixes

* Ignore ready state validations for directories ([#73](https://github.com/hawks-atlanta/metadata-scala/issues/73)) ([fa5467f](https://github.com/hawks-atlanta/metadata-scala/commit/fa5467f86bda9312a6dad474bbdd3f5360a875c9))



2 changes: 1 addition & 1 deletion docs/bruno/shared-with-who/shared-with-who.bru
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ meta {
}

get {
url: {{BASE_URL}}/files/shared_with_who/22a7c6ca-8e57-46d2-9977-43dcbfcac760
url: {{BASE_URL}}/files/shared_with_who/76c5a635-08c4-46c9-89ef-89c120e2e55f
body: none
auth: none
}
17 changes: 17 additions & 0 deletions docs/bruno/unshare-file/unshare-file.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
meta {
name: unshare-file
type: http
seq: 1
}

post {
url: {{BASE_URL}}/files/unshare/5c8e5e9d-7d82-450f-9fe3-43fc73aa5a39/76c5a635-08c4-46c9-89ef-89c120e2e55f
body: json
auth: none
}

body:json {
{
"otherUserUUID": "e1139bb6-d291-4170-8fb0-94dd787fa84b"
}
}
27 changes: 27 additions & 0 deletions src/main/scala/files_metadata/application/FilesMetaUseCases.scala
Original file line number Diff line number Diff line change
Expand Up @@ -228,4 +228,31 @@ class FilesMetaUseCases {

repository.updateFileParent( fileUUID, newParentUUID )
}

def unShareFile(
ownerUUID: UUID,
fileUUID: UUID,
otherUserUUID: UUID
): Unit = {
val fileMeta = repository.getFileMeta( fileUUID )

if (fileMeta.ownerUuid != ownerUUID) {
throw DomainExceptions.FileNotOwnedException(
"You don't own the file"
)
}
if (ownerUUID == otherUserUUID) {
throw DomainExceptions.FileNotOwnedException(
"You cannot un-share a file with yourself"
)
}

if (!repository.isFileDirectlySharedWithUser( fileUUID, otherUserUUID )) {
throw DomainExceptions.FileAlreadySharedException(
"The file is not shared with the given user"
)
}

repository.unShareFile( fileUUID, otherUserUUID )
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ trait FilesMetaRepository {
def updateFileName( fileUUID: UUID, newName: String ): Unit

def updateFileParent( fileUUID: UUID, parentUUID: Option[UUID] ): Unit
def unShareFile( fileUUID: UUID, userUUID: UUID ): Unit

// --- Delete ---
def deleteFileMeta( ownerUuid: UUID, uuid: UUID ): Unit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -589,5 +589,36 @@ class FilesMetaPostgresRepository extends FilesMetaRepository {
}
}

override def unShareFile( fileUUID: UUID, userUUID: UUID ): Unit = {
val connection: Connection = pool.getConnection()
connection.setAutoCommit( false )

try {
val shareStatement = connection.prepareStatement(
"DELETE FROM shared_files WHERE file_uuid =? AND user_uuid =?"
)
shareStatement.setObject( 1, fileUUID )
shareStatement.setObject( 2, userUUID )
shareStatement.executeUpdate()

val checkSharedStatement = connection.prepareStatement(
"SELECT * FROM shared_files WHERE file_uuid = ?"
)
checkSharedStatement.setObject( 1, fileUUID )
val resultSet = checkSharedStatement.executeQuery()
if (!resultSet.next()) {
val updateStatement = connection.prepareStatement(
"UPDATE files SET is_shared = false WHERE uuid = ?"
)
updateStatement.setObject( 1, fileUUID )
updateStatement.executeUpdate()
}

connection.commit()
} finally {
connection.close()
}
}

override def deleteFileMeta( ownerUuid: UUID, uuid: UUID ): Unit = ???
}
Original file line number Diff line number Diff line change
Expand Up @@ -622,4 +622,47 @@ class MetadataControllers {
case e: Exception => _handleException( e )
}
}

def UnShareFileController(
request: cask.Request,
ownerUUID: String,
fileUUID: String
): cask.Response[Obj] = {
try {
val decoded: ShareReqSchema = read[ShareReqSchema](
request.text()
)

val isOwnerUUIDValid = CommonValidator.validateUUID( ownerUUID )
val isFileUUIDValid = CommonValidator.validateUUID( fileUUID )

val validationRule: Validator[ShareReqSchema] =
ShareReqSchema.shareSchemaValidator
val validationResult = validate[ShareReqSchema]( decoded )(
validationRule
)
if (!isOwnerUUIDValid || !isFileUUIDValid || validationResult.isFailure) {
return cask.Response(
ujson.Obj(
"error" -> true,
"message" -> "Fields validation failed"
),
statusCode = 400
)
}

useCases.unShareFile(
ownerUUID = UUID.fromString( ownerUUID ),
fileUUID = UUID.fromString( fileUUID ),
otherUserUUID = UUID.fromString( decoded.otherUserUUID )
)

cask.Response(
None,
statusCode = 204
)
} catch {
case e: Exception => _handleException( e )
}
}
}
15 changes: 15 additions & 0 deletions src/main/scala/files_metadata/infrastructure/MetadataRoutes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,20 @@ case class MetadataRoutes() extends cask.Routes {
)
}

private val unShareMetadataEndpoint =
s"$basePath/unshare/:ownerUUID/:fileUUID"

@cask.post( unShareMetadataEndpoint )
def UnShareMetadataHandler(
request: cask.Request,
ownerUUID: String,
fileUUID: String
): cask.Response[Obj] = {
StdoutLogger.logAndReturnEndpointResponse(
unShareMetadataEndpoint,
controllers.UnShareFileController( request, ownerUUID, fileUUID )
)
}

initialize()
}
23 changes: 23 additions & 0 deletions src/test/scala/files_metadata/FilesTestsUtils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,21 @@ object FilesTestsUtils {
)
}

def UnShareFile(
ownerUUID: String,
fileUUID: String,
payload: util.HashMap[String, Any]
): Response = {
`given`()
.port( 8080 )
.contentType( "application/json" )
.body( payload )
.when()
.post(
s"${ UnShareFileTestsData.API_PREFIX }/$ownerUUID/$fileUUID"
)
}

def generateShareFilePayload(
otherUserUUID: UUID
): util.HashMap[String, Any] = {
Expand All @@ -116,6 +131,14 @@ object FilesTestsUtils {
shareFilePayload
}

def generateUnshareFilePayload(
otherUserUUID: UUID
): util.HashMap[String, Any] = {
val unShareFilePayload = new util.HashMap[String, Any]()
unShareFilePayload.put( "otherUserUUID", otherUserUUID.toString )
unShareFilePayload
}

def GetSharedWithUser( userUUID: String ): Response = {
`given`()
.port( 8080 )
Expand Down
150 changes: 150 additions & 0 deletions src/test/scala/files_metadata/UnshareFile.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package org.hawksatlanta.metadata
package files_metadata

import java.util.UUID

import org.junit.runner.manipulation.Alphanumeric
import org.junit.runner.OrderWith
import org.junit.Before
import org.junit.Test
import org.scalatestplus.junit.JUnitSuite

object UnShareFileTestsData {
val API_PREFIX: String = "/api/v1/files/unshare"
val OWNER_USER_UUID: UUID = UUID.randomUUID()
val OTHER_USER_UUID: UUID = UUID.randomUUID()

private var unsharePayload: java.util.HashMap[String, Any] = _
var savedDirectoryUUID: UUID = _
var savedFileUUID: UUID = _
var sharedFileUUID: UUID = _
var sharedDirectoryUUID: UUID = _

def getUnsharePayload(): java.util.HashMap[String, Any] = {
if (unsharePayload == null) {
unsharePayload = FilesTestsUtils.generateUnshareFilePayload(
otherUserUUID = OTHER_USER_UUID
)
}

unsharePayload.clone().asInstanceOf[java.util.HashMap[String, Any]]
}
}

@OrderWith( classOf[Alphanumeric] )
class UnShareFileTests extends JUnitSuite {
def saveFilesAndShareToUnhare(): Unit = {
// Save a file to share
val saveFilePayload = FilesTestsUtils.generateFilePayload(
ownerUUID = UnShareFileTestsData.OWNER_USER_UUID,
parentDirUUID = None
)

val saveFileResponse = FilesTestsUtils.SaveFile( saveFilePayload )
UnShareFileTestsData.savedFileUUID =
UUID.fromString( saveFileResponse.jsonPath().get( "uuid" ) )

// Save a directory to share
val saveDirectoryPayload = FilesTestsUtils.generateDirectoryPayload(
ownerUUID = UnShareFileTestsData.OWNER_USER_UUID,
parentDirUUID = None
)

val saveDirectoryResponse =
FilesTestsUtils.SaveFile( saveDirectoryPayload )
UnShareFileTestsData.savedDirectoryUUID =
UUID.fromString( saveDirectoryResponse.jsonPath().get( "uuid" ) )

val ShareFilePayload = FilesTestsUtils.generateShareFilePayload(
otherUserUUID = UnShareFileTestsData.OTHER_USER_UUID
)
val ShareFileResponse = FilesTestsUtils.ShareFile(
ownerUUID = UnShareFileTestsData.OWNER_USER_UUID.toString,
fileUUID = UnShareFileTestsData.savedFileUUID.toString,
payload = ShareFilePayload
)
val ShareDirectoryPayload = FilesTestsUtils.generateShareFilePayload(
otherUserUUID = UnShareFileTestsData.OTHER_USER_UUID
)
val ShareDirectoryResponse = FilesTestsUtils.ShareFile(
ownerUUID = UnShareFileTestsData.OWNER_USER_UUID.toString,
fileUUID = UnShareFileTestsData.savedDirectoryUUID.toString,
payload = ShareDirectoryPayload
)

}

@Before
def startHttpServer(): Unit = {
FilesTestsUtils.StartHttpServer()
}
@Test
def T1_UnShareFileBadRequest(): Unit = {
saveFilesAndShareToUnhare()
// 1. Bad other user
val requestBody = ShareFileTestsData.getSharePayload()
requestBody.put( "otherUserUUID", "Not an UUID" )
val response = FilesTestsUtils.UnShareFile(
ownerUUID = UnShareFileTestsData.OWNER_USER_UUID.toString,
fileUUID = UnShareFileTestsData.savedFileUUID.toString,
payload = requestBody
)
assert( response.statusCode() == 400 )
assert( response.jsonPath().getBoolean( "error" ) )
// 2. Bad ownerUserUUID
val response2 = FilesTestsUtils.UnShareFile(
ownerUUID = "Not an UUID",
fileUUID = UnShareFileTestsData.savedFileUUID.toString,
payload = UnShareFileTestsData.getUnsharePayload()
)
assert( response2.statusCode() == 400 )
assert( response2.jsonPath().getBoolean( "error" ) )
// 3. Bad fileUUID
val response3 = FilesTestsUtils.UnShareFile(
ownerUUID = UnShareFileTestsData.OWNER_USER_UUID.toString,
fileUUID = "Not an UUID",
payload = UnShareFileTestsData.getUnsharePayload()
)
assert( response3.statusCode() == 400 )
assert( response3.jsonPath().getBoolean( "error" ) )
}
@Test
def T2_UnshareSuccess(): Unit = {
// Unshare the File
val fileResponse = FilesTestsUtils.UnShareFile(
ownerUUID = UnShareFileTestsData.OWNER_USER_UUID.toString,
fileUUID = UnShareFileTestsData.savedFileUUID.toString,
payload = UnShareFileTestsData.getUnsharePayload()
)
assert( fileResponse.statusCode() == 204 )
// Unshare the File
val fileResponse2 = FilesTestsUtils.UnShareFile(
ownerUUID = UnShareFileTestsData.OWNER_USER_UUID.toString,
fileUUID = UnShareFileTestsData.savedDirectoryUUID.toString,
payload = UnShareFileTestsData.getUnsharePayload()
)
assert( fileResponse2.statusCode() == 204 )
}

@Test
def T3_UnshareFileNotFound(): Unit = {
val response = FilesTestsUtils.UnShareFile(
ownerUUID = UnShareFileTestsData.OWNER_USER_UUID.toString,
fileUUID = UUID.randomUUID().toString,
payload = UnShareFileTestsData.getUnsharePayload()
)
assert( response.statusCode() == 404 )
assert( response.jsonPath().getBoolean( "error" ) )
}

@Test
def T4_ShareFileForbidden(): Unit = {
val response = FilesTestsUtils.UnShareFile(
ownerUUID = UnShareFileTestsData.OTHER_USER_UUID.toString,
fileUUID = UnShareFileTestsData.savedFileUUID.toString,
payload = UnShareFileTestsData.getUnsharePayload()
)
assert( response.statusCode() == 403 )
assert( response.jsonPath().getBoolean( "error" ) )
}
}
2 changes: 1 addition & 1 deletion version.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"version": "0.11.1"
"version": "0.12.0"
}
Loading