Skip to content

Commit

Permalink
Add folder lock functionality (#725)
Browse files Browse the repository at this point in the history
  • Loading branch information
sujaygarlanka authored Mar 15, 2021
1 parent 895cc91 commit 6927cc8
Show file tree
Hide file tree
Showing 12 changed files with 303 additions and 1 deletion.
99 changes: 99 additions & 0 deletions Box.V2.Test/BoxFoldersManagerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -963,5 +964,103 @@ public async Task RemoveWatermarkFromFolder_ValidResponse_RemovedWatermark()
Assert.AreEqual(true, result);

}

[TestMethod]
[TestCategory("CI-UNIT-TEST")]
public async Task GetFolderLocks_ValidResponse()
{
/*** Arrange ***/
string responseString = "{\"entries\":[{\"folder\":{\"id\":\"12345\",\"etag\":\"1\",\"type\":\"folder\",\"sequence_id\":\"3\",\"name\":\"Contracts\"},\"id\":\"12345678\",\"type\":\"folder_lock\",\"created_by\":{\"id\":\"11446498\",\"type\":\"user\"},\"created_at\":\"2020-09-14T23:12:53Z\",\"locked_operations\":{\"move\":true,\"delete\":true},\"lock_type\":\"freeze\"}],\"limit\":1000,\"next_marker\":null}";
IBoxRequest boxRequest = null;
Handler.Setup(h => h.ExecuteAsync<BoxCollection<BoxFolderLock>>(It.IsAny<IBoxRequest>()))
.Returns(Task.FromResult<IBoxResponse<BoxCollection<BoxFolderLock>>>(new BoxResponse<BoxCollection<BoxFolderLock>>()
{
Status = ResponseStatus.Success,
ContentString = responseString
}))
.Callback<IBoxRequest>(r => boxRequest = r);

/*** Act ***/
string id = "5010739069";
BoxCollection<BoxFolderLock> result = await _foldersManager.GetLocksAsync(id);

/*** Assert ***/
//Request check
Assert.IsNotNull(boxRequest);
Assert.AreEqual(RequestMethod.Get, boxRequest.Method);
Assert.AreEqual(Constants.FolderLocksEndpointString + "?folder_id=" + id, boxRequest.AbsoluteUri.AbsoluteUri);

//Response check
Assert.AreEqual("12345678", result.Entries[0].Id);
Assert.AreEqual("freeze", result.Entries[0].LockType);
Assert.AreEqual(true, result.Entries[0].LockedOperations.Delete);

}

[TestMethod]
[TestCategory("CI-UNIT-TEST")]
public async Task CreateFolderLock_ValidResponse()
{
/*** Arrange ***/
string responseString = "{\"id\":12345678,\"type\":\"folder_lock\",\"created_at\":\"2020-09-14T23:12:53Z\",\"created_by\":{\"id\":11446498,\"type\":\"user\"},\"folder\":{\"id\":12345,\"type\":\"folder\",\"etag\":1,\"name\":\"Contracts\",\"sequence_id\":3},\"lock_type\":\"freeze\",\"locked_operations\":{\"delete\":true,\"move\":true}}";
IBoxRequest boxRequest = null;
Handler.Setup(h => h.ExecuteAsync<BoxFolderLock>(It.IsAny<IBoxRequest>()))
.Returns(Task.FromResult<IBoxResponse<BoxFolderLock>>(new BoxResponse<BoxFolderLock>()
{
Status = ResponseStatus.Success,
ContentString = responseString
}))
.Callback<IBoxRequest>(r => boxRequest = r);

/*** Act ***/
string id = "5010739069";
BoxFolderLock result = await _foldersManager.CreateLockAsync(id);

/*** Assert ***/
//Request check
Assert.IsNotNull(boxRequest);
Assert.AreEqual(RequestMethod.Post, boxRequest.Method);
Assert.AreEqual(Constants.FolderLocksEndpointString, boxRequest.AbsoluteUri.AbsoluteUri);
JObject payload = JObject.Parse(boxRequest.Payload);
Assert.AreEqual("folder", payload["folder"]["type"]);
Assert.AreEqual(id, payload["folder"]["id"]);
Assert.AreEqual(true, payload["locked_operations"]["move"]);
Assert.AreEqual(true, payload["locked_operations"]["delete"]);

//Response check
Assert.AreEqual("12345678", result.Id);
Assert.AreEqual("freeze", result.LockType);
Assert.AreEqual(true, result.LockedOperations.Delete);

}

[TestMethod]
[TestCategory("CI-UNIT-TEST")]
public async Task DeleteFolderLock_ValidResponse()
{
/*** Arrange ***/
string responseString = "";
IBoxRequest boxRequest = null;
Handler.Setup(h => h.ExecuteAsync<BoxFolderLock>(It.IsAny<IBoxRequest>()))
.Returns(Task.FromResult<IBoxResponse<BoxFolderLock>>(new BoxResponse<BoxFolderLock>()
{
Status = ResponseStatus.Success,
ContentString = responseString
}))
.Callback<IBoxRequest>(r => boxRequest = r);

/*** Act ***/
string id = "5010739069";
bool result = await _foldersManager.DeleteLockAsync(id);

/*** Assert ***/
//Request check
Assert.IsNotNull(boxRequest);
Assert.AreEqual(RequestMethod.Delete, boxRequest.Method);
Assert.AreEqual(Constants.FolderLocksEndpointString + id, boxRequest.AbsoluteUri.AbsoluteUri);

//Response check
Assert.AreEqual(true, result);
}
}
}
2 changes: 2 additions & 0 deletions Box.V2.Test/BoxResourceManagerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public abstract class BoxResourceManagerTest
protected Uri MetadataQueryUri = new Uri(Constants.MetadataQueryEndpointString);
protected Uri UserUri = new Uri(Constants.UserEndpointString);
protected Uri InviteUri = new Uri(Constants.BoxApiUriString + Constants.InviteString);
protected Uri FolderLocksUri = new Uri(Constants.FolderLocksEndpointString);

protected BoxResourceManagerTest()
{
Expand All @@ -41,6 +42,7 @@ protected BoxResourceManagerTest()
Config.SetupGet(x => x.MetadataQueryUri).Returns(MetadataQueryUri);
Config.SetupGet(x => x.UserEndpointUri).Returns(UserUri);
Config.SetupGet(x => x.InviteEndpointUri).Returns(InviteUri);
Config.SetupGet(x => x.FolderLocksEndpointUri).Returns(FolderLocksUri);

AuthRepository = new AuthRepository(Config.Object, Service, Converter, new OAuthSession("fakeAccessToken", "fakeRefreshToken", 3600, "bearer"));
}
Expand Down
2 changes: 2 additions & 0 deletions Box.V2/Box.V2.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@
<Compile Include="Models\BoxEnterprise.cs" />
<Compile Include="Models\BoxEnterpriseEvent.cs" />
<Compile Include="Models\BoxFolderEventSource.cs" />
<Compile Include="Models\BoxFolderLock.cs" />
<Compile Include="Models\BoxFolderLockOperations.cs" />
<Compile Include="Models\BoxGroupEventSource.cs" />
<Compile Include="Models\BoxMetadataCascadePolicy.cs" />
<Compile Include="Models\BoxGroupFileCollaborationEventSource.cs" />
Expand Down
4 changes: 4 additions & 0 deletions Box.V2/Config/BoxConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,10 @@ public static IBoxConfig CreateFromJsonString(string jsonString)
/// </summary>
public virtual Uri ZipDownloadsEndpointUri { get { return new Uri(BoxApiUri, Constants.ZipDownloadsString); } }
/// <summary>
/// Gets the folder locks endpoint URI.
/// </summary>
public virtual Uri FolderLocksEndpointUri { get { return new Uri(BoxApiUri, Constants.FolderLocksString); } }
/// <summary>
/// The web proxy for HttpRequestHandler
/// </summary>
public IWebProxy WebProxy { get; set; }
Expand Down
4 changes: 4 additions & 0 deletions Box.V2/Config/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ public static class Constants
public const string StoragePolicyAssignmentsString = @"storage_policy_assignments/";
public const string StoragePolicyAssignmentsForTargetString = @"storage_policy_assignments";
public const string ZipDownloadsString = @"zip_downloads";
public const string FolderLocksString = @"folder_locks/";


/// <summary>
/// The shared items constant
Expand Down Expand Up @@ -109,6 +111,7 @@ public static class Constants
public const string StoragePoliciesEndpointString = BoxApiUriString + StoragePoliciesString;
public const string StoragePolicyAssignmentsEndpointString = BoxApiUriString + StoragePolicyAssignmentsString;
public const string StoragePolicyAssignmentsForTargetEndpointString = BoxApiUriString + StoragePolicyAssignmentsForTargetString;
public const string FolderLocksEndpointString = BoxApiUriString + FolderLocksString;

/*** Endpoint Paths ***/
public const string ItemsPathString = @"{0}/items";
Expand Down Expand Up @@ -184,6 +187,7 @@ public static class Constants
public const string TypeStoragePolicy = "storage_policy";
public const string TypeStoragePolicyAssignment = "storage_policy_assignment";
public const string TypeApplication = "application";
public const string TypeFolderLock = "folder_lock";

/*** File Preview ***/
public const int DefaultRetryDelay = 1000; // milliseconds
Expand Down
5 changes: 4 additions & 1 deletion Box.V2/Config/IBoxConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ public interface IBoxConfig
/// Gets the zip downloads endpoint URI.
/// </summary>
Uri ZipDownloadsEndpointUri { get; }

/// <summary>
/// Gets the folder locks endpoint URI.
/// </summary>
Uri FolderLocksEndpointUri { get; }
/// <summary>
/// The web proxy for HttpRequestHandler
/// </summary>
Expand Down
2 changes: 2 additions & 0 deletions Box.V2/Converter/BoxItemConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ protected override BoxEntity Create(Type objectType, JObject jObject)
return new BoxStoragePolicyAssignment();
case Constants.TypeApplication:
return new BoxApplication();
case Constants.TypeFolderLock:
return new BoxFolderLock();
}
}
//There is an inconsistency in the events API where file sources have slightly different field names
Expand Down
72 changes: 72 additions & 0 deletions Box.V2/Managers/BoxFoldersManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Box.V2.Extensions;
using Box.V2.Models;
using Box.V2.Services;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
Expand Down Expand Up @@ -448,5 +449,76 @@ public async Task<bool> RemoveWatermarkAsync(string id)
return response.Status == ResponseStatus.Success;
}

/// <summary>
/// Creates a folder lock on a folder, preventing it from being moved and/or deleted.
/// </summary>
/// <param name="id">Id of the folder to create a lock on</param>
/// <returns>An object representing the lock on the folder</returns>
public async Task<BoxFolderLock> CreateLockAsync(string id)
{
id.ThrowIfNullOrWhiteSpace("id");

JObject bodyObject = new JObject();
JObject folderObject = new JObject();
JObject lockOperationsObject = new JObject();

folderObject.Add("id", id);
folderObject.Add("type", "folder");

lockOperationsObject.Add("move", true);
lockOperationsObject.Add("delete", true);

bodyObject.Add("folder", folderObject);
bodyObject.Add("locked_operations", lockOperationsObject);

BoxRequest request = new BoxRequest(_config.FolderLocksEndpointUri)
.Method(RequestMethod.Post)
.Payload(_converter.Serialize(bodyObject));
request.ContentType = Constants.RequestParameters.ContentTypeJson;

IBoxResponse<BoxFolderLock> response = await ToResponseAsync<BoxFolderLock>(request).ConfigureAwait(false);
return response.ResponseObject;
}

/// <summary>
/// Lists all folder locks for a given folder.
/// </summary>
/// <param name="id">Id of the folder</param>
/// <param name="autoPaginate">Whether or not to auto-paginate to fetch all locks. Currently only one lock can exist per folder.; defaults to false.</param>
/// <returns>A collection of locks on the folder</returns>
public async Task<BoxCollection<BoxFolderLock>> GetLocksAsync(string id, bool autoPaginate = false)
{
id.ThrowIfNullOrWhiteSpace("id");

BoxRequest request = new BoxRequest(_config.FolderLocksEndpointUri)
.Method(RequestMethod.Get)
.Param("folder_id", id);

if (autoPaginate)
{
return await AutoPaginateLimitOffset<BoxFolderLock>(request, 1000);
}
else
{
IBoxResponse<BoxCollection<BoxFolderLock>> response = await ToResponseAsync<BoxCollection<BoxFolderLock>>(request).ConfigureAwait(false);
return response.ResponseObject;
}
}

/// <summary>
/// Delete a folder lock on a folder
/// </summary>
/// <param name="id">Id of the folder lock</param>
/// <returns>True will be returned upon successful deletionr</returns>
public async Task<bool> DeleteLockAsync(string id)
{
id.ThrowIfNullOrWhiteSpace("id");

BoxRequest request = new BoxRequest(_config.FolderLocksEndpointUri, id)
.Method(RequestMethod.Delete);

IBoxResponse<BoxFolderLock> response = await ToResponseAsync<BoxFolderLock>(request).ConfigureAwait(false);
return response.Status == ResponseStatus.Success;
}
}
}
47 changes: 47 additions & 0 deletions Box.V2/Models/BoxFolderLock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Newtonsoft.Json;
using System;

namespace Box.V2.Models
{
/// <summary>
/// Box representation of a folder lock in box
/// </summary>
public class BoxFolderLock : BoxEntity
{
public const string FieldCreatedAt = "created_at";
public const string FieldCreatedBy = "created_by";
public const string FieldFolder = "folder";
public const string FieldLockType = "lock_type";
public const string FieldLockedOperations = "locked_operations";

/// <summary>
/// The time the lock was created
/// </summary>
[JsonProperty(PropertyName = FieldCreatedAt)]
public DateTime? CreatedAt { get; private set; }

/// <summary>
/// The user who created this lock
/// </summary>
[JsonProperty(PropertyName = FieldCreatedBy)]
public BoxUser CreatedBy { get; private set; }

/// <summary>
/// The folder that the lock applies to
/// </summary>
[JsonProperty(PropertyName = FieldFolder)]
public BoxFolder Folder { get; private set; }

/// <summary>
/// The lock type
/// </summary>
[JsonProperty(PropertyName = FieldLockType)]
public string LockType { get; private set; }

/// <summary>
/// The operations locked by a folder lock
/// </summary>
[JsonProperty(PropertyName = FieldLockedOperations)]
public BoxFolderLockOperations LockedOperations { get; private set; }
}
}
26 changes: 26 additions & 0 deletions Box.V2/Models/BoxFolderLockOperations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using Newtonsoft.Json;

namespace Box.V2.Models
{
/// <summary>
/// Box representation of a operations that have been locked on a folder lock in box
/// </summary>
public class BoxFolderLockOperations
{
public const string FieldDelete = "delete";
public const string FieldMove = "move";

/// <summary>
/// Whether deleting the folder is restricted
/// </summary>
[JsonProperty(PropertyName = FieldDelete)]
public bool Delete { get; private set; }

/// <summary>
/// Whether deleting the folder is restricted
/// </summary>
[JsonProperty(PropertyName = FieldMove)]
public bool Move { get; private set; }
}
}
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

- Add filter fields to get file version retentions ([#717](https://github.com/box/box-windows-sdk-v2/pull/717))
- Add support for search param to get shared link items ([#721](https://github.com/box/box-windows-sdk-v2/pull/721))
- Add folder lock functionality ([#725](https://github.com/box/box-windows-sdk-v2/pull/725))

## 3.25.0 [2020-10-19]

Expand Down
Loading

0 comments on commit 6927cc8

Please sign in to comment.