Skip to content

Commit

Permalink
Merge pull request #21 from FromDoppler/DE-441-redefine-api
Browse files Browse the repository at this point in the history
DE-441 - Redefine API
  • Loading branch information
andresmoschini authored Jan 27, 2022
2 parents 87ed033 + fc6d2fd commit c303180
Show file tree
Hide file tree
Showing 12 changed files with 160 additions and 400 deletions.
40 changes: 22 additions & 18 deletions Doppler.HtmlEditorApi.Test/GetCampaignTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public GetCampaignTest(WebApplicationFactory<Startup> factory, ITestOutputHelper
}

[Theory]
[InlineData("/accounts/x@x.com/campaigns/123/content/design", HttpStatusCode.Unauthorized)]
[InlineData("/accounts/x@x.com/campaigns/123/content", HttpStatusCode.Unauthorized)]
public async Task GET_campaign_should_require_token(string url, HttpStatusCode expectedStatusCode)
{
// Arrange
Expand All @@ -49,8 +49,8 @@ public async Task GET_campaign_should_require_token(string url, HttpStatusCode e
}

[Theory]
[InlineData("/accounts/x@x.com/campaigns/123/content/design", TOKEN_ACCOUNT_123_TEST1_AT_TEST_DOT_COM_EXPIRE_20330518, HttpStatusCode.Forbidden)]
[InlineData("/accounts/x@x.com/campaigns/123/content/design", TOKEN_EXPIRE_20330518, HttpStatusCode.Forbidden)]
[InlineData("/accounts/x@x.com/campaigns/123/content", TOKEN_ACCOUNT_123_TEST1_AT_TEST_DOT_COM_EXPIRE_20330518, HttpStatusCode.Forbidden)]
[InlineData("/accounts/x@x.com/campaigns/123/content", TOKEN_EXPIRE_20330518, HttpStatusCode.Forbidden)]
public async Task GET_campaign_should_not_accept_the_token_of_another_account(string url, string token, HttpStatusCode expectedStatusCode)
{
// Arrange
Expand All @@ -66,8 +66,8 @@ public async Task GET_campaign_should_not_accept_the_token_of_another_account(st
}

[Theory]
[InlineData("/accounts/test1@test.com/campaigns/123/content/design", TOKEN_ACCOUNT_123_TEST1_AT_TEST_DOT_COM_EXPIRE_20010908, HttpStatusCode.Unauthorized)]
[InlineData("/accounts/test1@test.com/campaigns/123/content/design", TOKEN_SUPERUSER_EXPIRE_20010908, HttpStatusCode.Unauthorized)]
[InlineData("/accounts/test1@test.com/campaigns/123/content", TOKEN_ACCOUNT_123_TEST1_AT_TEST_DOT_COM_EXPIRE_20010908, HttpStatusCode.Unauthorized)]
[InlineData("/accounts/test1@test.com/campaigns/123/content", TOKEN_SUPERUSER_EXPIRE_20010908, HttpStatusCode.Unauthorized)]
public async Task GET_campaign_should_not_accept_a_expired_token(string url, string token, HttpStatusCode expectedStatusCode)
{
// Arrange
Expand All @@ -86,14 +86,14 @@ public async Task GET_campaign_should_not_accept_a_expired_token(string url, str
}

[Theory]
[InlineData("/accounts/test1@test.com/campaigns/123/content/design", TOKEN_ACCOUNT_123_TEST1_AT_TEST_DOT_COM_EXPIRE_20330518, "test1@test.com", 123)]
[InlineData("/accounts/test1@test.com/campaigns/123/content/design", TOKEN_SUPERUSER_EXPIRE_20330518, "test1@test.com", 123)]
[InlineData("/accounts/otro@test.com/campaigns/123/content/design", TOKEN_SUPERUSER_EXPIRE_20330518, "otro@test.com", 123)]
[InlineData("/accounts/test1@test.com/campaigns/123/content", TOKEN_ACCOUNT_123_TEST1_AT_TEST_DOT_COM_EXPIRE_20330518, "test1@test.com", 123)]
[InlineData("/accounts/test1@test.com/campaigns/123/content", TOKEN_SUPERUSER_EXPIRE_20330518, "test1@test.com", 123)]
[InlineData("/accounts/otro@test.com/campaigns/123/content", TOKEN_SUPERUSER_EXPIRE_20330518, "otro@test.com", 123)]
public async Task GET_campaign_should_accept_right_tokens_and_return_404_when_DB_returns_null(string url, string token, string expectedAccountName, int expectedIdCampaign)
{
// Arrange
// TODO: consider to mock Dapper in place of IRepository
ContentModel emptyContentModel = null;
CampaignContent emptyContentModel = null;
var repositoryMock = new Mock<IRepository>();
repositoryMock.Setup(x => x.GetCampaignModel(expectedAccountName, expectedIdCampaign))
.ReturnsAsync(emptyContentModel);
Expand All @@ -118,21 +118,22 @@ public async Task GET_campaign_should_accept_right_tokens_and_return_404_when_DB
}

[Theory]
[InlineData("/accounts/test1@test.com/campaigns/123/content/design", TOKEN_ACCOUNT_123_TEST1_AT_TEST_DOT_COM_EXPIRE_20330518, "test1@test.com", 123)]
[InlineData("/accounts/test1@test.com/campaigns/123/content/design", TOKEN_SUPERUSER_EXPIRE_20330518, "test1@test.com", 123)]
[InlineData("/accounts/otro@test.com/campaigns/123/content/design", TOKEN_SUPERUSER_EXPIRE_20330518, "otro@test.com", 123)]
[InlineData("/accounts/test1@test.com/campaigns/123/content", TOKEN_ACCOUNT_123_TEST1_AT_TEST_DOT_COM_EXPIRE_20330518, "test1@test.com", 123)]
[InlineData("/accounts/test1@test.com/campaigns/123/content", TOKEN_SUPERUSER_EXPIRE_20330518, "test1@test.com", 123)]
[InlineData("/accounts/otro@test.com/campaigns/123/content", TOKEN_SUPERUSER_EXPIRE_20330518, "otro@test.com", 123)]
public async Task GET_campaign_should_accept_right_tokens_and_return_content_as_it_is_in_DB(string url, string token, string expectedAccountName, int expectedIdCampaign)
{
// Arrange
ContentModel contentModel = new ContentModel()
var expectedSchemaVersion = 999;
var campaignContent = new CampaignContent(JsonSerializer.SerializeToElement(new
{
schemaVersion = 9999
};
schemaVersion = expectedSchemaVersion
}), "<html></html>");

// TODO: consider to mock Dapper in place of IRepository
var repositoryMock = new Mock<IRepository>();
repositoryMock.Setup(x => x.GetCampaignModel(expectedAccountName, expectedIdCampaign))
.ReturnsAsync(contentModel);
.ReturnsAsync(campaignContent);

var client = _factory
.WithWebHostBuilder(c =>
Expand All @@ -149,12 +150,15 @@ public async Task GET_campaign_should_accept_right_tokens_and_return_content_as_
var response = await client.GetAsync(url);
_output.WriteLine(response.GetHeadersAsString());
var responseContent = await response.Content.ReadAsStringAsync();
var contentModelResponse = JsonSerializer.Deserialize<ContentModel>
var contentModelResponse = JsonSerializer.Deserialize<CampaignContent>
(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });

// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(contentModel.schemaVersion, contentModelResponse.schemaVersion);
Assert.True(contentModelResponse.meta.TryGetProperty("schemaVersion", out var resultSchemaVersionProp), "schemaVersion property is not present");
Assert.Equal(JsonValueKind.Number, resultSchemaVersionProp.ValueKind);
Assert.True(resultSchemaVersionProp.TryGetInt32(out var resultSchemaVersion), "schemaVersion is not a valid Int32 value");
Assert.Equal(expectedSchemaVersion, resultSchemaVersion);

// TODO: fix it, why does it not work?
// Assert.Equal("application/json", response.Headers.GetValues("Content-Type").First());
Expand Down
10 changes: 5 additions & 5 deletions Doppler.HtmlEditorApi/Controllers/CampaignsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ public CampaignsController(IRepository Repository)
}

[Authorize(Policies.OWN_RESOURCE_OR_SUPERUSER)]
[HttpGet("/accounts/{accountName}/campaigns/{campaignId}/content/design")]
public async Task<ActionResult<ContentModel>> GetCampaign(string accountName, int campaignId)
[HttpGet("/accounts/{accountName}/campaigns/{campaignId}/content")]
public async Task<ActionResult<CampaignContent>> GetCampaign(string accountName, int campaignId)
{
// TODO: Considere refactoring accountName validation
var campaignModel = await _repository.GetCampaignModel(accountName, campaignId);
Expand All @@ -39,10 +39,10 @@ public Task<ActionResult> GetCampaignThumbnail(string accountName, int campaignI
}

[Authorize(Policies.OWN_RESOURCE_OR_SUPERUSER)]
[HttpPut("/accounts/{accountName}/campaigns/{campaignId}/content/")]
public async Task<IActionResult> SaveCampaign(string accountName, int campaignId, CampaignContentRequest data)
[HttpPut("/accounts/{accountName}/campaigns/{campaignId}/content")]
public async Task<IActionResult> SaveCampaign(string accountName, int campaignId, CampaignContent campaignContent)
{
await _repository.SaveCampaignContent(accountName, campaignId, data);
await _repository.SaveCampaignContent(accountName, campaignId, campaignContent);
return new OkObjectResult($"La campaña '{campaignId}' del usuario '{accountName}' se guardó exitosamente ");
}
}
Expand Down
8 changes: 4 additions & 4 deletions Doppler.HtmlEditorApi/Controllers/TemplatesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,28 +25,28 @@ public TemplatesController(IRepository Repository)

[Authorize(Policies.OWN_RESOURCE_OR_SUPERUSER)]
[HttpGet("/accounts/{accountName}/templates/{templateId}")]
public Task<ActionResult<TemplateModel>> GetTemplate(string accountName, int templateId)
public Task<ActionResult<Template>> GetTemplate(string accountName, int templateId)
{
throw new NotImplementedException();
}

[Authorize(Policies.OWN_RESOURCE_OR_SUPERUSER)]
[HttpPut("/accounts/{accountName}/templates/{templateId}")]
public Task<IActionResult> SaveTemplate(string accountName, int templateId, TemplateModel templateModel)
public Task<IActionResult> SaveTemplate(string accountName, int templateId, Template templateModel)
{
throw new NotImplementedException();
}

[Authorize(Policies.OWN_RESOURCE_OR_SUPERUSER)]
[HttpPost("/accounts/{accountName}/templates")]
public Task<IActionResult> CreateTemplate(string accountName, TemplateModel templateModel)
public Task<IActionResult> CreateTemplate(string accountName, Template templateModel)
{
throw new NotImplementedException();
}

[Authorize(Policies.ONLY_SUPERUSER)]
[HttpPost("/shared/templates/{templateId}")]
public Task<ActionResult<TemplateModel>> GetSharedTemplate(int templateId)
public Task<ActionResult<Template>> GetSharedTemplate(int templateId)
{
throw new NotImplementedException();
}
Expand Down

This file was deleted.

102 changes: 54 additions & 48 deletions Doppler.HtmlEditorApi/Infrastructure/DummyRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,61 +8,67 @@ namespace Doppler.HtmlEditorApi.Infrastructure
{
public class DummyRepository : IRepository
{
public Task<ContentModel> GetCampaignModel(string accountName, int campaignId)
private static readonly object _demoMeta = new
{
return Task.FromResult(new ContentModel()
counters = new
{
counters = new()
{
u_row = 1,
u_column = 2,
u_content_text = 1,
u_content_heading = 1,
u_content_menu = 1
},
body = new()
u_row = 1,
u_column = 2,
u_content_text = 1,
u_content_heading = 1,
u_content_menu = 1
},
body = new
{
rows = new object[0],
values = new
{
rows = new List<Row>(),
values = new()
textColor = "#000000",
backgroundColor = "#e7e7e7",
backgroundImage = new
{
url = "",
fullWidth = true,
repeat = false,
center = true,
cover = false
},
contentWidth = "500px",
contentAlign = "center",
fontFamily = new
{
label = "Arial",
value = "arial,helvetica,sans-serif"
},
preheaderText = "",
linkStyle = new
{
textColor = "#000000",
backgroundColor = "#e7e7e7",
backgroundImage = new()
{
url = "",
fullWidth = true,
repeat = false,
center = true,
cover = false
},
contentWidth = "500px",
contentAlign = "center",
fontFamily = new()
{
label = "Arial",
value = "arial,helvetica,sans-serif"
},
preheaderText = "",
linkStyle = new()
{
body = true,
linkColor = "#0000ee",
linkHoverColor = "#0000ee",
linkUnderline = true,
linkHoverUnderline = true
},
_meta = new()
{
htmlID = "u_body",
htmlClassNames = "u_body"
}
body = true,
linkColor = "#0000ee",
linkHoverColor = "#0000ee",
linkUnderline = true,
linkHoverUnderline = true
},
_meta = new
{
htmlID = "u_body",
htmlClassNames = "u_body"
}
},
schemaVersion = 6
});
}
},
schemaVersion = 6
};

public Task<CampaignContent> GetCampaignModel(string accountName, int campaignId)
{
var campaign = new CampaignContent(
meta: JsonSerializer.SerializeToElement(_demoMeta),
htmlContent: "<html></html>");

return Task.FromResult(campaign);
}

public Task SaveCampaignContent(string accountName, int campaignId, CampaignContentRequest campaignModel)
public Task SaveCampaignContent(string accountName, int campaignId, CampaignContent campaignModel)
{
return Task.CompletedTask;
}
Expand Down
4 changes: 2 additions & 2 deletions Doppler.HtmlEditorApi/Infrastructure/IRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Doppler.HtmlEditorApi.Infrastructure
{
public interface IRepository
{
Task<ContentModel> GetCampaignModel(string accountName, int campaignId);
Task SaveCampaignContent(string accountName, int campaignId, CampaignContentRequest data);
Task<CampaignContent> GetCampaignModel(string accountName, int campaignId);
Task SaveCampaignContent(string accountName, int campaignId, CampaignContent data);
}
}
21 changes: 16 additions & 5 deletions Doppler.HtmlEditorApi/Infrastructure/Repository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public Repository(IDatabaseConnectionFactory connectionFactory)
_connectionFactory = connectionFactory;
}

public async Task<ContentModel> GetCampaignModel(string accountName, int campaignId)
public async Task<CampaignContent> GetCampaignModel(string accountName, int campaignId)
{
using (var connection = await _connectionFactory.GetConnection())
{
Expand All @@ -24,11 +24,21 @@ public async Task<ContentModel> GetCampaignModel(string accountName, int campaig
JOIN [User] u ON u.IdUser = ca.IdUser
WHERE co.IdCampaign = @campaignId AND u.Email = @accountName AND co.EditorType = 5";
var result = await connection.QueryFirstOrDefaultAsync<ContentRow>(databaseQuery, new { campaignId, accountName });
return result == null ? null : JsonSerializer.Deserialize<ContentModel>(result.Meta);

if (result == null)
{
return null;
}

using var doc = JsonDocument.Parse(result.Meta);

return new CampaignContent(
meta: doc.RootElement,
htmlContent: result.Content);
}
}

public async Task SaveCampaignContent(string accountName, int campaignId, CampaignContentRequest request)
public async Task SaveCampaignContent(string accountName, int campaignId, CampaignContent campaignContent)
{
using (var connection = await _connectionFactory.GetConnection())
{
Expand All @@ -44,8 +54,9 @@ public async Task SaveCampaignContent(string accountName, int campaignId, Campai
databaseExec = @"UPDATE Content SET Content = @htmlContent, Meta = @metaModel WHERE IdCampaign = @campaignId";
}

var metaModel = request.Meta.ToString();
await connection.ExecuteAsync(databaseExec, new { campaignId, htmlContent = request.Content, metaModel });
var metaModel = campaignContent.meta.ToString();

await connection.ExecuteAsync(databaseExec, new { campaignId, htmlContent = campaignContent.htmlContent, metaModel });
}
}
}
Expand Down
Loading

0 comments on commit c303180

Please sign in to comment.