Skip to content

Commit

Permalink
Merge pull request #2287 from greymistcube/rebase/release-70
Browse files Browse the repository at this point in the history
🔀 Partially rebase release/70 and cherry-pick from release/62
  • Loading branch information
greymistcube authored Nov 7, 2023
2 parents ba98283 + b0e1912 commit f43535a
Show file tree
Hide file tree
Showing 18 changed files with 190 additions and 213 deletions.
14 changes: 11 additions & 3 deletions .github/workflows/deploy_gh_pages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,20 @@ jobs:
-G "https://9c-dx.s3.ap-northeast-2.amazonaws.com/empty-genesis-block-20230511" &
sleep 60s
graphql-inspector introspect http://localhost:30000/graphql --write schema.graphql
- name: Build
- name: Build GraphQL Document
run: |
yarn global add spectaql
spectaql ./spectaql-config.yaml
spectaql --target-dir public/graphql ./spectaql-config.yaml
- name: Build CLI Document
run: |
mkdir -p public/cli
dotnet run --project NineChronicles.Headless.Executable -- \
docs \
public/cli
- name: Copy Landing Page to deploy
run: cp Docs/resources/landing.html public/index.html
- name: Copy GraphQL Schema to deploy
run: cp schema.graphql doc
run: cp schema.graphql public/schema.graphql
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/push_docker_image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ jobs:
docker:
- repo: planetariumhq/ninechronicles-headless
dockerfile: Dockerfile
- repo: planetariumhq/access-control-center
dockerfile: Dockerfile.ACC
if: github.ref_type == 'branch'
runs-on: ubuntu-latest
steps:
Expand Down
25 changes: 25 additions & 0 deletions Docs/resources/landing.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>NineChronicles Headless</title>
<meta charset="UTF-8"/>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>
<body>
<div class="flex min-h-screen min-w-screen justify-center items-center">
<div class="flex flex-col justify-center items-center gap-5">
<p class="bg-gray-700 p-5 text-white text-4xl font-extrabold">NineChronicles.Headless</p>
<span>A headless node to validate, network, operate NineChronicles chain.</span>
<hr class="w-full" />
<div class="flex flex-row justify-center items-center gap-2">
<a href="https://github.com/planetarium/NineChronicles.Headless"><i class="fa fa-github"></i> Repository</a>
<span>|</span>
<a href="https://planetarium.github.io/NineChronicles.Headless/graphql">GraphQL Docs</a>
<span>|</span>
<a href="https://planetarium.github.io/NineChronicles.Headless/cli">CLI Docs</a>
</div>
</div>
</div>
</body>
</html>
2 changes: 1 addition & 1 deletion Lib9c
Submodule Lib9c updated 182 files
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using NineChronicles.Headless.AccessControlCenter.AccessControlService;

namespace NineChronicles.Headless.AccessControlCenter
{
public class AcsService
public class AccService
{
public AcsService(Configuration configuration)
public AccService(Configuration configuration)
{
Configuration = configuration;
}
Expand Down Expand Up @@ -49,6 +49,33 @@ public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();

services.AddSwaggerGen(c =>
{
c.SwaggerDoc(
"v1",
new OpenApiInfo { Title = "Access Control Center API", Version = "v1" }
);
c.DocInclusionPredicate(
(docName, apiDesc) =>
{
var controllerType =
apiDesc.ActionDescriptor
as Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor;
if (controllerType != null)
{
var assemblyName = controllerType.ControllerTypeInfo.Assembly
.GetName()
.Name;
var namespaceName = controllerType.ControllerTypeInfo.Namespace;
return namespaceName?.StartsWith(
"NineChronicles.Headless.AccessControlCenter"
) ?? false;
}
return false;
}
);
});

var accessControlService = MutableAccessControlServiceFactory.Create(
Enum.Parse<MutableAccessControlServiceFactory.StorageType>(
Configuration.AccessControlServiceType,
Expand All @@ -62,10 +89,11 @@ public void ConfigureServices(IServiceCollection services)

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
app.UseSwagger();
app.UseSwaggerUI(c =>
{
app.UseDeveloperExceptionPage();
}
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Access Control Center API V1");
});

app.UseRouting();
app.UseAuthorization();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ namespace NineChronicles.Headless.AccessControlCenter.AccessControlService
{
public interface IMutableAccessControlService : IAccessControlService
{
void DenyAccess(Address address);
void AllowAccess(Address address);
List<Address> ListBlockedAddresses(int offset, int limit);
void AddTxQuota(Address address, int quota);
void RemoveTxQuota(Address address);
List<Address> ListTxQuotaAddresses(int offset, int limit);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,42 @@
using System.Linq;
using Libplanet.Crypto;
using NineChronicles.Headless.Services;
using StackExchange.Redis;

namespace NineChronicles.Headless.AccessControlCenter.AccessControlService
{
public class MutableRedisAccessControlService : RedisAccessControlService, IMutableAccessControlService
public class MutableRedisAccessControlService
: RedisAccessControlService,
IMutableAccessControlService
{
public MutableRedisAccessControlService(string storageUri) : base(storageUri)
public MutableRedisAccessControlService(string storageUri)
: base(storageUri)
{
}

public void DenyAccess(Address address)
public void AddTxQuota(Address address, int quota)
{
_db.StringSet(address.ToString(), "denied");
_db.StringSet(address.ToString(), quota.ToString());
}

public void AllowAccess(Address address)
public void RemoveTxQuota(Address address)
{
_db.KeyDelete(address.ToString());
}

public List<Address> ListBlockedAddresses(int offset, int limit)
public List<Address> ListTxQuotaAddresses(int offset, int limit)
{
var server = _db.Multiplexer.GetServer(_db.Multiplexer.GetEndPoints().First());
return server
.Keys()
.Select(k => new Address(k.ToString()))
.Skip(offset)
.Take(limit)
.ToList();

var result = (RedisResult[]?)
server.Execute("SCAN", offset.ToString(), "COUNT", limit.ToString());
if (result != null)
{
RedisKey[] keys = (RedisKey[])result[1]!;
return keys.Select(k => new Address(k.ToString())).ToList();
}

return new List<Address>();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using Microsoft.Data.Sqlite;
using Libplanet.Crypto;
Expand All @@ -7,55 +8,56 @@ namespace NineChronicles.Headless.AccessControlCenter.AccessControlService
{
public class MutableSqliteAccessControlService : SQLiteAccessControlService, IMutableAccessControlService
{
private const string DenyAccessSql =
"INSERT OR IGNORE INTO blocklist (address) VALUES (@Address)";
private const string AllowAccessSql = "DELETE FROM blocklist WHERE address=@Address";
private const string AddTxQuotaSql =
"INSERT OR IGNORE INTO txquotalist (address, quota) VALUES (@Address, @Quota)";
private const string RemoveTxQuotaSql = "DELETE FROM txquotalist WHERE address=@Address";

public MutableSqliteAccessControlService(string connectionString) : base(connectionString)
{
}

public void DenyAccess(Address address)
public void AddTxQuota(Address address, int quota)
{
using var connection = new SqliteConnection(_connectionString);
connection.Open();

using var command = connection.CreateCommand();
command.CommandText = DenyAccessSql;
command.CommandText = AddTxQuotaSql;
command.Parameters.AddWithValue("@Address", address.ToString());
command.Parameters.AddWithValue("@Quota", quota);
command.ExecuteNonQuery();
}

public void AllowAccess(Address address)
public void RemoveTxQuota(Address address)
{
using var connection = new SqliteConnection(_connectionString);
connection.Open();

using var command = connection.CreateCommand();
command.CommandText = AllowAccessSql;
command.CommandText = RemoveTxQuotaSql;
command.Parameters.AddWithValue("@Address", address.ToString());
command.ExecuteNonQuery();
}

public List<Address> ListBlockedAddresses(int offset, int limit)
public List<Address> ListTxQuotaAddresses(int offset, int limit)
{
var blockedAddresses = new List<Address>();
var txQuotaAddresses = new List<Address>();

using var connection = new SqliteConnection(_connectionString);
connection.Open();

using var command = connection.CreateCommand();
command.CommandText = $"SELECT address FROM blocklist LIMIT @Limit OFFSET @Offset";
command.CommandText = $"SELECT address FROM txquotalist LIMIT @Limit OFFSET @Offset";
command.Parameters.AddWithValue("@Limit", limit);
command.Parameters.AddWithValue("@Offset", offset);

using var reader = command.ExecuteReader();
while (reader.Read())
{
blockedAddresses.Add(new Address(reader.GetString(0)));
txQuotaAddresses.Add(new Address(reader.GetString(0)));
}

return blockedAddresses;
return txQuotaAddresses;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using NineChronicles.Headless.AccessControlCenter.AccessControlService;
Expand All @@ -17,30 +18,50 @@ public AccessControlServiceController(IMutableAccessControlService accessControl
}

[HttpGet("entries/{address}")]
public ActionResult<bool> IsAccessDenied(string address)
public ActionResult<int?> GetTxQuota(string address)
{
return _accessControlService.IsAccessDenied(new Address(address));
return _accessControlService.GetTxQuota(new Address(address));
}

[HttpPost("entries/{address}/deny")]
public ActionResult DenyAccess(string address)
[HttpPost("entries/add-tx-quota/{address}/{quota:int}")]
public ActionResult AddTxQuota(string address, int quota)
{
_accessControlService.DenyAccess(new Address(address));
var maxQuota = 10;
if (quota > maxQuota)
{
return BadRequest($"The quota cannot exceed {maxQuota}.");
}

_accessControlService.AddTxQuota(new Address(address), quota);
return Ok();
}

[HttpPost("entries/{address}/allow")]
public ActionResult AllowAccess(string address)
[HttpPost("entries/remove-tx-quota/{address}")]
public ActionResult RemoveTxQuota(string address)
{
_accessControlService.AllowAccess(new Address(address));
_accessControlService.RemoveTxQuota(new Address(address));
return Ok();
}

[HttpGet("entries")]
public ActionResult<List<string>> ListBlockedAddresses(int offset, int limit)
{
var maxLimit = 10;
if (_accessControlService is MutableRedisAccessControlService)
{
maxLimit = 10;
}
else if (_accessControlService is MutableSqliteAccessControlService)
{
maxLimit = 100;
}
if (limit > maxLimit)
{
return BadRequest($"The limit cannot exceed {maxLimit}.");
}

return _accessControlService
.ListBlockedAddresses(offset, limit)
.ListTxQuotaAddresses(offset, limit)
.Select(a => a.ToString())
.ToList();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion NineChronicles.Headless.AccessControlCenter/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static void Main(string[] args)
var acsConfig = new Configuration();
config.Bind(acsConfig);

var service = new AcsService(acsConfig);
var service = new AccService(acsConfig);
var hostBuilder = service.Configure(Host.CreateDefaultBuilder(), acsConfig.Port);
var host = hostBuilder.Build();
host.Run();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

<ItemGroup>
<PackageReference Include="Cocona.Lite" Version="2.1.*" />
<PackageReference Include="Cocona.Docs" Version="0.2.0-dev.2023103141721" />
<PackageReference Include="Destructurama.Attributed" Version="2.0.0" />
<PackageReference Include="Sentry.Serilog" Version="3.23.0" />
<PackageReference Include="Sentry" Version="3.23.0" />
Expand Down
1 change: 1 addition & 0 deletions NineChronicles.Headless.Executable/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

namespace NineChronicles.Headless.Executable
{
[HasSubCommands(typeof(Cocona.Docs.DocumentCommand), "docs")]
[HasSubCommands(typeof(AccountCommand), "account")]
[HasSubCommands(typeof(ValidationCommand), "validation")]
[HasSubCommands(typeof(ChainCommand), "chain")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ public async Task Query()
["level"] = 5,
["multiplier"] = 300,
},
new Dictionary<string, object>
{
["level"] = 6,
["multiplier"] = 300,
},
new Dictionary<string, object>
{
["level"] = 7,
["multiplier"] = 300,
},
};
var expected = new Dictionary<string, object> { { "orderedList", list } };
Assert.Equal(expected, data);
Expand Down
Loading

0 comments on commit f43535a

Please sign in to comment.