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

Commit

Permalink
feat: Unshare file (#89)
Browse files Browse the repository at this point in the history
* feat: add unshare file method to the repository

* feat: add endpoint unshare file

* fix: repair path route unshare metadata

* feat: add utils unshare and generate Unshare

* feat: add test unshare

* refactor: add format code

* refactor: repair messages exeptions

* docs(http): Update bruno collection

---------

Co-authored-by: Pedro Andrés Chaparro Quintero <pedro.chaparro.2020@upb.edu.co>
  • Loading branch information
sdbaronc and PedroChaparro authored Oct 22, 2023
1 parent f6c9bc2 commit be58b4a
Show file tree
Hide file tree
Showing 9 changed files with 308 additions and 1 deletion.
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" ) )
}
}

0 comments on commit be58b4a

Please sign in to comment.