Skip to content

Commit

Permalink
Code Cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
jezzsantos committed Sep 30, 2023
1 parent 9e89c82 commit fee149b
Show file tree
Hide file tree
Showing 74 changed files with 1,619 additions and 1,005 deletions.
12 changes: 6 additions & 6 deletions docs/ValueProposition.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ This person will need to quickly understand the value proposition of SaaStack an
They may encounter some objections, either design decisions or principles behind it, that they can't move past.

* They will be guided by what they already know, so it will have to be a tech stack they know already.
* They may or may not trust examples of things they are not experienced with, and some may not adopt things they won't feel they have mastered yet.
* They may or may not trust examples of things they are not experienced with, and some may not adopt things they won't feel they have mastered yet.
* They will be motivated by associating themselves with the latest and greatest in this technology stack (i.e. .NET).
* They may or may not be up to speed on those things. So they will see value in someone showing them the latest and greatest.
* They may or may not be up to speed on those things. So they will see value in someone showing them the latest and greatest.
* They will be interested to learn more about the proposed architectural styles (e.g. Event Sourcing, Microservices, Clean Architecture, etc.).
* They may or may not be experienced in their uses either. And will be looking for evidence or opinions on why they should consider them for their context.
* They may or may not be experienced in their uses either. And will be looking for evidence or opinions on why they should consider them for their context.

We believe that if the founding developer makes any kind of purchase or contribution to obtaining SaaStack, they are also going to have an expectation of having some support for adopting it, from some kind of community, where they can have questions answered and may provide feedback.

Expand All @@ -85,12 +85,12 @@ We assume that:
- A tech startup has identified some kind of *problem* in some kind of target *market*, and this target market will (in the future) be able to sustain the growth of the business.
- They understand that there is some kind of *opportunity* out there that this problem that the market represents to them, and they accept that there is some kind of risk in competing to be a solution to that problem, that the market will choose over/with other options.
- They may or may not have a concrete solution to this problem at this stage, but must have some ideas to validate in a segment of the market.
- We believe that many tech startups already believe that they have a winning solution in mind, and some have already convinced themselves that they only have to build the solution in their mind, and the market will come knocking on their doors, throwing money at them.
- We believe that many tech startups already believe that they have a winning solution in mind, and some have already convinced themselves that they only have to build the solution in their mind, and the market will come knocking on their doors, throwing money at them.
- In any case, some software will need to be designed, built, and deployed somewhere in order to test, validate, measure, or even acquire buyers/users for their new product business.
- "Making" this software is the primary job of the CTO and/or tech lead of a startup.
- We believe that nowadays, it is imperative to research, design, build, deploy measure, and learn incrementally and iteratively to discover what really works in a market segment. These people understand that.
- We believe that nowadays, it is imperative to research, design, build, deploy measure, and learn incrementally and iteratively to discover what really works in a market segment. These people understand that.
- Those people have to start somewhere with making some software product/prototype, and it is usually starting from scratch.
- We believe that sometimes, it is more cost-effective to start with other low-tech solutions, low-tech tools, no-code solutions, or adapt readily available tools before a tech company accepts the risk and cost of investing in doing their own custom development. All these approaches are very viable approaches, and would likely precede the need for a solution like SaaStack.
- We believe that sometimes, it is more cost-effective to start with other low-tech solutions, low-tech tools, no-code solutions, or adapt readily available tools before a tech company accepts the risk and cost of investing in doing their own custom development. All these approaches are very viable approaches, and would likely precede the need for a solution like SaaStack.

**Early Validation:** So, our first job here is the job of getting some validated results (from a market segment) by using something more economical than making a full-blown software product of their own from scratch.

Expand Down
32 changes: 16 additions & 16 deletions docs/design-principles/0010-rest-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,10 +332,10 @@ These properties generally don't form part of the route.
In the API the naming convention for search type API's has been the following:

* For search type API's, where the request contains something to search for, (even in cases where only a single result is expected) we have been using the convention: `GET /resources/search`, and defining the search criteria in the QueryString.
* For example, to determine if a user exists for a specified email address, we have the SearchUsers API: `GET /users/[email protected]`.
* For example, to determine if a user exists for a specified email address, we have the SearchUsers API: `GET /users/[email protected]`.

* For Listing type API's, where the request may not contain any search criteria, and usually returns different variants of a resource based upon the caller, or context, we have been using the convention: `GET /resources`, and defining any parameters in the QueryString also.
* For example, to list the car that you own, we have the ListForCallerCars API: `GET /cars`.
* For example, to list the car that you own, we have the ListForCallerCars API: `GET /cars`.

The difference in the naming convention is purely for semantics. For search APIs, the route adds the `/search` part.

Expand Down Expand Up @@ -628,26 +628,26 @@ We report errors as HTTP status codes `4XX` and `5XX`).
These are the common HTTP status codes for errors:

* `400 - BadRequest` (the request is incorrectly formatted)
* Validation failed
* A required input is missing or invalid at the time
* The request is not allowed at this time because the resource/context is not in a required state - (i.e. business rule violation).
* Validation failed
* A required input is missing or invalid at the time
* The request is not allowed at this time because the resource/context is not in a required state - (i.e. business rule violation).
* `401 - NotAuthorized` (the user has not authenticated when authentication is required)
* No access_token provided for a secure call
* The access_token expired or is invalid
* No access_token provided for a secure call
* The access_token expired or is invalid
* `402 - PaymentRequired` (the user is using a feature that has not been paid for)
* The caller is using a feature associated to a subscription plan that the user does not have
* The caller is using a feature associated to a subscription plan that the user does not have
* `403 - Forbidden` (the user may be authenticated, but they are not authorized to this specific resource at this time)
* The caller is not in the required role
* [May decide to throw 404 instead to obscure reason from hacker]
* The caller is not in the required role
* [May decide to throw 404 instead to obscure reason from hacker]
* `404 - NotFound` (a resource does not exist)
* The resource does not exist
* [May decide to throw 404 instead of a 403 if the caller is not allowed access to this resource to obscure the resource rather than admit it exists but the authenticated user does not have access to it]
* The resource does not exist
* [May decide to throw 404 instead of a 403 if the caller is not allowed access to this resource to obscure the resource rather than admit it exists but the authenticated user does not have access to it]
* `405 - MethodNotAllowed` (Verb/API cannot be called at this time)
* i.e. It is invalid to call it for this resource at this time.
* i.e. It no longer exists for this resource at this time, or it never existed for this resource (not implemented yet).
* i.e. It is invalid to call it for this resource at this time.
* i.e. It no longer exists for this resource at this time, or it never existed for this resource (not implemented yet).
* `409 - Conflict` (conflict with the current state of the target resource)
* Resource already exists
* Resource already exists
* `500 - InternalServerError` (something bad happened in our code that we did not expect, and did not handle in the code)
* Unhandled/Unexpected exception (not covered above)
* Unhandled/Unexpected exception (not covered above)

> HTTP Status codes are explained in detail here: [HTTP Status Codes](http://en.wikipedia.org/wiki/Http_error_codes)
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@ public class ValidationsValidatedTestingOnlyRequestValidator : AbstractValidator
{
public ValidationsValidatedTestingOnlyRequestValidator()
{
RuleFor(req => req.Id).NotEmpty().WithMessage(Resources.GetTestingOnlyValidatedRequestValidator_InvalidId);
RuleFor(req => req.Field1).NotEmpty().Matches(@"[\d]{1,3}")
RuleFor(req => req.Id)
.NotEmpty()
.WithMessage(Resources.GetTestingOnlyValidatedRequestValidator_InvalidId);
RuleFor(req => req.Field1)
.NotEmpty()
.Matches(@"[\d]{1,3}")
.WithMessage(Resources.GetTestingOnlyValidatedRequestValidator_InvalidField1);
RuleFor(req => req.Field2).NotEmpty().Matches(@"[\d]{1,3}")
RuleFor(req => req.Field2)
.NotEmpty()
.Matches(@"[\d]{1,3}")
.WithMessage(Resources.GetTestingOnlyValidatedRequestValidator_InvalidField2);
}
}
Expand Down
1 change: 0 additions & 1 deletion src/ApiHost1/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
.ConfigureApiHost(modules, RecorderOptions.BackEndApiHost);
app.Run();


namespace ApiHost1
{
[UsedImplicitly]
Expand Down
2 changes: 1 addition & 1 deletion src/ApiHost1/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
"ASPNETCORE_ENVIRONMENT": "Production"
}
},
"SourceGenerator-Development": {
"ApiHandler-SourceGenerator-Development": {
"commandName": "DebugRoslynComponent",
"targetProject": "../ApiHost1/ApiHost1.csproj"
}
Expand Down
4 changes: 1 addition & 3 deletions src/Application.Common/Caller.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,7 @@ public ExternalWebHookAccountCaller(string? callId = null)
{
CallId = callId ?? GenerateCallId();
Roles = new ICallerContext.CallerRoles(new[] { UserRoles.ServiceAccount }, null);
FeatureSets =
new ICallerContext.CallerFeatureSets(
new[] { UserFeatureSets.Core }, null);
FeatureSets = new ICallerContext.CallerFeatureSets(new[] { UserFeatureSets.Core }, null);
}

public ICallerContext.CallerRoles Roles { get; }
Expand Down
41 changes: 23 additions & 18 deletions src/Application.Interfaces.UnitTests/GetOptionsExtensionsSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,54 +12,59 @@ public void WhenShouldExpandEmbeddedResourceAndNullOptions_ThenReturnsTrue()
{
var result = ((GetOptions)null!).ShouldExpandEmbeddedResource<TestResource>(x => x.AProperty1);

result.Should().BeTrue();
result.Should()
.BeTrue();
}

[Fact]
public void WhenShouldExpandEmbeddedResourceAndExpandIsAll_ThenReturnsTrue()
{
var result = new GetOptions(ExpandOptions.All)
.ShouldExpandEmbeddedResource<TestResource>(x => x.AProperty1);
var result = new GetOptions(ExpandOptions.All).ShouldExpandEmbeddedResource<TestResource>(x => x.AProperty1);

result.Should().BeTrue();
result.Should()
.BeTrue();
}

[Fact]
public void WhenShouldExpandEmbeddedResourceAndExpandIsNone_ThenReturnsFalse()
{
var result = new GetOptions(ExpandOptions.None)
.ShouldExpandEmbeddedResource<TestResource>(x => x.AProperty1);
var result = new GetOptions(ExpandOptions.None).ShouldExpandEmbeddedResource<TestResource>(x => x.AProperty1);

result.Should().BeFalse();
result.Should()
.BeFalse();
}

[Fact]
public void WhenShouldExpandEmbeddedResourceAndExpandIsCustomAndNoChildResources_ThenReturnsFalse()
{
var result = new GetOptions(ExpandOptions.Custom, new List<string>())
.ShouldExpandEmbeddedResource<TestResource>(x => x.AProperty1);
var result =
new GetOptions(ExpandOptions.Custom, new List<string>()).ShouldExpandEmbeddedResource<TestResource>(x =>
x.AProperty1);

result.Should().BeFalse();
result.Should()
.BeFalse();
}

[Fact]
public void WhenShouldExpandEmbeddedResourceAndExpandIsCustomAndUnknownChildResources_ThenReturnsFalse()
{
var result = new GetOptions(ExpandOptions.Custom,
new List<string> { "TestResource.AnotherProperty" })
.ShouldExpandEmbeddedResource<TestResource>(x => x.AProperty1);
var result =
new GetOptions(ExpandOptions.Custom, new List<string> { "TestResource.AnotherProperty" })
.ShouldExpandEmbeddedResource<TestResource>(x => x.AProperty1);

result.Should().BeFalse();
result.Should()
.BeFalse();
}

[Fact]
public void WhenShouldExpandEmbeddedResourceAndExpandIsCustomAndKnownChildResources_ThenReturnsTrue()
{
var result = new GetOptions(ExpandOptions.Custom,
new List<string> { "TestResource.AProperty1" })
.ShouldExpandEmbeddedResource<TestResource>(x => x.AProperty1);
var result =
new GetOptions(ExpandOptions.Custom, new List<string> { "TestResource.AProperty1" })
.ShouldExpandEmbeddedResource<TestResource>(x => x.AProperty1);

result.Should().BeTrue();
result.Should()
.BeTrue();
}
}

Expand Down
53 changes: 36 additions & 17 deletions src/Application.Interfaces.UnitTests/SearchOptionsExtensionsSpec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ public void WhenToMetadataSafeWithNullSearchOptions_ThenReturnsDefaultSearchMeta
{
var results = ((SearchOptions)null!).ToMetadata();

results.Total.Should().Be(0);
results.Total.Should()
.Be(0);
}

[Fact]
public void WhenToMetadataSafeWithNullSearchOptionsAndTotal_ThenReturnsDefaultSearchMetadata()
{
var results = ((SearchOptions)null!).ToMetadata(11);

results.Total.Should().Be(11);
results.Total.Should()
.Be(11);
}

[Fact]
Expand All @@ -29,7 +31,8 @@ public void WhenToMetadataSafeWithInitialSearchOptions_ThenReturnsSearchMetadata

var results = searchOptions.ToMetadata();

results.Total.Should().Be(0);
results.Total.Should()
.Be(0);
}

[Fact]
Expand All @@ -45,13 +48,21 @@ public void WhenToMetadataSafe_ThenReturnsPopulatedSearchMetadata()

var results = searchOptions.ToMetadata();

results.Total.Should().Be(0);
results.Sort!.Direction.Should().Be(SortDirection.Descending);
results.Sort.By.Should().Be("asortfield");
results.Offset.Should().Be(9);
results.Limit.Should().Be(6);
results.Filter!.Fields.Count.Should().Be(1);
results.Filter.Fields[0].Should().Be("afilterfield");
results.Total.Should()
.Be(0);
results.Sort!.Direction.Should()
.Be(SortDirection.Descending);
results.Sort.By.Should()
.Be("asortfield");
results.Offset.Should()
.Be(9);
results.Limit.Should()
.Be(6);
results.Filter!.Fields.Count.Should()
.Be(1);
results.Filter.Fields[0]
.Should()
.Be("afilterfield");
}

[Fact]
Expand All @@ -67,12 +78,20 @@ public void WhenToMetadataSafeAndTotal_ThenReturnsPopulatedSearchMetadata()

var results = searchOptions.ToMetadata(11);

results.Total.Should().Be(11);
results.Sort!.Direction.Should().Be(SortDirection.Descending);
results.Sort.By.Should().Be("asortfield");
results.Offset.Should().Be(9);
results.Limit.Should().Be(6);
results.Filter!.Fields.Count.Should().Be(1);
results.Filter.Fields[0].Should().Be("afilterfield");
results.Total.Should()
.Be(11);
results.Sort!.Direction.Should()
.Be(SortDirection.Descending);
results.Sort.By.Should()
.Be("asortfield");
results.Offset.Should()
.Be(9);
results.Limit.Should()
.Be(6);
results.Filter!.Fields.Count.Should()
.Be(1);
results.Filter.Fields[0]
.Should()
.Be("afilterfield");
}
}
Loading

0 comments on commit fee149b

Please sign in to comment.