Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement remaining CRUD operation for user API. #278

Merged
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
108 changes: 108 additions & 0 deletions arangodb-net-standard.Test/UserApi/UserApiClientTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,5 +84,113 @@ await _userClient.PostUserAsync(new PostUserBody()
Assert.NotNull(ex.ApiError.ErrorMessage);
Assert.Equal(1702, ex.ApiError.ErrorNum); // ERROR_USER_DUPLICATE
}

[Fact]
public async Task PutUserAsync_ShouldSucceed()
{
PutUserResponse response = await _userClient.PutUserAsync(
_fixture.UsernameExisting,
new PutUserBody()
{
Extra = new Dictionary<string, object>()
{
["somedata"] = nameof(PutUserAsync_ShouldSucceed)
}
});

Assert.False(response.Error);
Assert.Equal(HttpStatusCode.OK, response.Code);
Assert.Equal(_fixture.UsernameExisting, response.User);
Assert.True(response.Active);
Assert.True(response.Extra.ContainsKey("somedata"));
Assert.Equal(nameof(PutUserAsync_ShouldSucceed), response.Extra["somedata"].ToString());
}

[Fact]
public async Task PutUserAsync_ShouldThrow_WhenUserDoesNotExist()
{
var ex = await Assert.ThrowsAsync<ApiErrorException>(async () =>
{
await _userClient.PutUserAsync(
nameof(PutUserAsync_ShouldThrow_WhenUserDoesNotExist),
new PutUserBody()
{
Extra = new Dictionary<string, object>()
});
});

Assert.True(ex.ApiError.Error);
Assert.Equal(HttpStatusCode.NotFound, ex.ApiError.Code);
Assert.NotNull(ex.ApiError.ErrorMessage);
Assert.Equal(1703, ex.ApiError.ErrorNum); // ERROR_USER_NOT_FOUND
}

[Fact]
public async Task PatchUserAsync_ShouldSucceed()
{
PatchUserResponse response = await _userClient.PatchUserAsync(
_fixture.UsernameExisting,
new PatchUserBody()
{
Extra = new Dictionary<string, object>()
{
["somedata"] = nameof(PatchUserAsync_ShouldSucceed)
}
});

Assert.False(response.Error);
Assert.Equal(HttpStatusCode.OK, response.Code);
Assert.Equal(_fixture.UsernameExisting, response.User);
Assert.True(response.Active);
Assert.True(response.Extra.ContainsKey("somedata"));
Assert.Equal(nameof(PatchUserAsync_ShouldSucceed), response.Extra["somedata"].ToString());
}

[Fact]
public async Task PatchUserAsync_ShouldThrow_WhenUserDoesNotExist()
{
var ex = await Assert.ThrowsAsync<ApiErrorException>(async () =>
{
await _userClient.PatchUserAsync(
nameof(PatchUserAsync_ShouldThrow_WhenUserDoesNotExist),
new PatchUserBody()
{
Extra = new Dictionary<string, object>()
});
});

Assert.True(ex.ApiError.Error);
Assert.Equal(HttpStatusCode.NotFound, ex.ApiError.Code);
Assert.NotNull(ex.ApiError.ErrorMessage);
Assert.Equal(1703, ex.ApiError.ErrorNum); // ERROR_USER_NOT_FOUND
}

[Fact]
public async Task GetUserAsync_ShouldSucceed()
{
GetUserResponse response = await _userClient.GetUserAsync(
_fixture.UsernameExisting);

Assert.False(response.Error);
Assert.Equal(HttpStatusCode.OK, response.Code);
Assert.Equal(_fixture.UsernameExisting, response.User);
Assert.True(response.Active);
Assert.NotNull(response.Extra);
}

[Fact]
public async Task GetUserAsync_ShouldThrow_WhenUserDoesNotExist()
{
var ex = await Assert.ThrowsAsync<ApiErrorException>(async () =>
{
await _userClient.GetUserAsync(
nameof(GetUserAsync_ShouldThrow_WhenUserDoesNotExist));
});

Assert.True(ex.ApiError.Error);
Assert.Equal(HttpStatusCode.NotFound, ex.ApiError.Code);
Assert.NotNull(ex.ApiError.ErrorMessage);
Assert.Equal(1703, ex.ApiError.ErrorNum); // ERROR_USER_NOT_FOUND
}
}
}
35 changes: 35 additions & 0 deletions arangodb-net-standard/UserApi/IUserApiClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,41 @@ public interface IUserApiClient
/// <returns></returns>
Task<PostUserResponse> PostUserAsync(PostUserBody body);

/// <summary>
/// Replace an existing user.
/// You need server access level Administrate in order to execute this REST call.
/// Additionally, a user can change his/her own data.
/// </summary>
/// <param name="username">The name of the user.</param>
/// <param name="body">The user information used for to replace operation.</param>
/// <returns></returns>
Task<PutUserResponse> PutUserAsync(string username, PutUserBody body);

/// <summary>
/// Partially update an existing user.
/// You need server access level Administrate in order to execute this REST call.
/// Additionally, a user can change his/her own data.
/// </summary>
/// <param name="username">The name of the user.</param>
/// <param name="body">The user information used for to replace operation.</param>
/// <returns></returns>
Task<PatchUserResponse> PatchUserAsync(string username, PatchUserBody body);

/// <summary>
/// Fetches data about the specified user.
/// You can fetch information about yourself or you need the Administrate
/// server access level in order to execute this REST call.
/// </summary>
/// <param name="username">The name of the user.</param>
/// <returns></returns>
Task<GetUserResponse> GetUserAsync(string username);

/// <summary>
/// Delete a user permanently.
/// You need Administrate for the server access level in order to execute this REST call.
/// </summary>
/// <param name="username">The name of the user.</param>
/// <returns></returns>
Task<DeleteUserResponse> DeleteUserAsync(string username);
}
}
9 changes: 9 additions & 0 deletions arangodb-net-standard/UserApi/Models/GetUserResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace ArangoDBNetStandard.UserApi.Models
{
/// <summary>
/// Represents a response returned after fetching a user.
/// </summary>
public class GetUserResponse : UserResponseBase
{
}
}
27 changes: 27 additions & 0 deletions arangodb-net-standard/UserApi/Models/PatchUserBody.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Collections.Generic;

namespace ArangoDBNetStandard.UserApi.Models
{
/// <summary>
/// Represents a request body to update an existing user.
/// </summary>
public class PatchUserBody
{
/// <summary>
/// The user password. Specifying a password is mandatory,
/// but the empty string is allowed for passwords.
/// </summary>
public string Passwd { get; set; }

/// <summary>
/// An optional flag that specifies whether the user is active.
/// If not specified, this will default to true.
/// </summary>
public bool? Active { get; set; }

/// <summary>
/// Optional object with arbitrary extra data about the user.
/// </summary>
public Dictionary<string, object> Extra { get; set; }
}
}
11 changes: 11 additions & 0 deletions arangodb-net-standard/UserApi/Models/PatchUserResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Net;

namespace ArangoDBNetStandard.UserApi.Models
{
/// <summary>
/// Represents a response returned after updating an existing user.
/// </summary>
public class PatchUserResponse : UserResponseBase
{
}
}
34 changes: 5 additions & 29 deletions arangodb-net-standard/UserApi/Models/PostUserResponse.cs
Original file line number Diff line number Diff line change
@@ -1,33 +1,9 @@
using System.Collections.Generic;
using System.Net;

namespace ArangoDBNetStandard.UserApi.Models
namespace ArangoDBNetStandard.UserApi.Models
{
public class PostUserResponse
/// <summary>
/// Represents a response returned after creating a user.
/// </summary>
public class PostUserResponse : UserResponseBase
{
/// <summary>
/// The name of the user.
/// </summary>
public string User { get; set; }

/// <summary>
/// Whether the user is active.
/// </summary>
public bool Active { get; set; }

/// <summary>
/// Object with arbitrary extra data about the user.
/// </summary>
public Dictionary<string, object> Extra { get; set; }

/// <summary>
/// Indicates whether an error occurred (false in this case).
/// </summary>
public bool Error { get; set; }

/// <summary>
/// The HTTP status code.
/// </summary>
public HttpStatusCode Code { get; set; }
}
}
27 changes: 27 additions & 0 deletions arangodb-net-standard/UserApi/Models/PutUserBody.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Collections.Generic;

namespace ArangoDBNetStandard.UserApi.Models
{
/// <summary>
/// Represents a request body to replace an existing user.
/// </summary>
public class PutUserBody
{
/// <summary>
/// The user password. Specifying a password is mandatory,
/// but the empty string is allowed for passwords.
/// </summary>
public string Passwd { get; set; }

/// <summary>
/// An optional flag that specifies whether the user is active.
/// If not specified, this will default to true.
/// </summary>
public bool? Active { get; set; }

/// <summary>
/// Optional object with arbitrary extra data about the user.
/// </summary>
public Dictionary<string, object> Extra { get; set; }
}
}
12 changes: 12 additions & 0 deletions arangodb-net-standard/UserApi/Models/PutUserResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Collections.Generic;
using System.Net;

namespace ArangoDBNetStandard.UserApi.Models
{
/// <summary>
/// Represents a response returned after replacing an existing user.
/// </summary>
public class PutUserResponse : UserResponseBase
{
}
}
37 changes: 37 additions & 0 deletions arangodb-net-standard/UserApi/Models/UserResponseBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Collections.Generic;
using System.Net;

namespace ArangoDBNetStandard.UserApi.Models
{
/// <summary>
/// Represents a common response class with user information
/// returned after performing an operation.
/// </summary>
public class UserResponseBase
{
/// <summary>
/// The name of the user.
/// </summary>
public string User { get; set; }

/// <summary>
/// Whether the user is active.
/// </summary>
public bool Active { get; set; }

/// <summary>
/// Object with arbitrary extra data about the user.
/// </summary>
public Dictionary<string, object> Extra { get; set; }

/// <summary>
/// Indicates whether an error occurred (false in this case).
/// </summary>
public bool Error { get; set; }

/// <summary>
/// The HTTP status code.
/// </summary>
public HttpStatusCode Code { get; set; }
}
}
Loading