Skip to content

Commit 6bb4741

Browse files
committed
add admin endpoints, edit summary/description
1 parent 7530c56 commit 6bb4741

23 files changed

+333
-89
lines changed

rubberduckvba.Server/Api/Admin/AdminController.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
namespace rubberduckvba.Server.Api.Admin;
88

99
[ApiController]
10+
[EnableCors(CorsPolicies.AllowAll)]
1011
public class AdminController(ConfigurationOptions options, HangfireLauncherService hangfire, CacheService cache) : ControllerBase
1112
{
1213
/// <summary>
1314
/// Enqueues a job that updates xmldoc content from the latest release/pre-release tags.
1415
/// </summary>
1516
/// <returns>The unique identifier of the enqueued job.</returns>
1617
[Authorize("github")]
17-
[EnableCors(CorsPolicies.AllowAuthenticated)]
1818
[HttpPost("admin/update/xmldoc")]
1919
public IActionResult UpdateXmldocContent()
2020
{
@@ -27,7 +27,6 @@ public IActionResult UpdateXmldocContent()
2727
/// </summary>
2828
/// <returns>The unique identifier of the enqueued job.</returns>
2929
[Authorize("github")]
30-
[EnableCors(CorsPolicies.AllowAuthenticated)]
3130
[HttpPost("admin/update/tags")]
3231
public IActionResult UpdateTagMetadata()
3332
{
@@ -36,7 +35,6 @@ public IActionResult UpdateTagMetadata()
3635
}
3736

3837
[Authorize("github")]
39-
[EnableCors(CorsPolicies.AllowAuthenticated)]
4038
[HttpPost("admin/cache/clear")]
4139
public IActionResult ClearCache()
4240
{
@@ -46,7 +44,6 @@ public IActionResult ClearCache()
4644

4745
#if DEBUG
4846
[AllowAnonymous]
49-
[EnableCors(CorsPolicies.AllowAll)]
5047
[HttpGet("admin/config/current")]
5148
public IActionResult Config()
5249
{

rubberduckvba.Server/Api/Features/FeatureEditViewModel.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public static FeatureEditViewModel Default(RepositoryId repository, FeatureOptio
1717
Repositories = repositories,
1818

1919
RepositoryId = repository,
20-
ParentId = parent?.Id,
20+
FeatureId = parent?.Id,
2121
Name = parent is null ? "NewFeature" : $"New{parent.Name}Feature",
2222
Title = "Feature Title",
2323
ShortDescription = "A short description; markdown is supported.",
@@ -29,7 +29,7 @@ public Feature ToFeature()
2929
return new Feature
3030
{
3131
Id = Id ?? default,
32-
FeatureId = ParentId,
32+
ParentId = FeatureId,
3333
RepositoryId = RepositoryId,
3434
Name = Name,
3535
Title = Title,
@@ -43,7 +43,7 @@ public Feature ToFeature()
4343
public FeatureEditViewModel(Feature model, FeatureOptionViewModel[] features, RepositoryOptionViewModel[] repositories)
4444
{
4545
Id = model.Id;
46-
ParentId = model.FeatureId;
46+
FeatureId = model.ParentId;
4747
RepositoryId = model.RepositoryId;
4848

4949
Name = model.Name;
@@ -59,7 +59,7 @@ public FeatureEditViewModel(Feature model, FeatureOptionViewModel[] features, Re
5959
}
6060

6161
public int? Id { get; init; }
62-
public int? ParentId { get; init; }
62+
public int? FeatureId { get; init; }
6363
public RepositoryId RepositoryId { get; init; }
6464

6565
public string Name { get; init; }

rubberduckvba.Server/Api/Features/FeatureViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public FeatureViewModel(Feature model, bool summaryOnly = false)
1111
DateInserted = model.DateTimeInserted;
1212
DateUpdated = model.DateTimeUpdated;
1313

14-
FeatureId = model.FeatureId;
14+
FeatureId = model.ParentId;
1515
FeatureName = model.FeatureName;
1616

1717
Name = model.Name;

rubberduckvba.Server/Api/Features/FeaturesController.cs

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,24 @@
99

1010
namespace rubberduckvba.Server.Api.Features;
1111

12+
public class MarkdownContentViewModel
13+
{
14+
public string Content { get; init; } = string.Empty;
15+
}
16+
1217

1318
[AllowAnonymous]
19+
[EnableCors(CorsPolicies.AllowAll)]
1420
public class FeaturesController : RubberduckApiController
1521
{
1622
private readonly CacheService cache;
1723
private readonly IRubberduckDbService db;
1824
private readonly FeatureServices features;
1925
private readonly IRepository<TagAssetEntity> assetsRepository;
2026
private readonly IRepository<TagEntity> tagsRepository;
27+
private readonly IMarkdownFormattingService markdownService;
2128

22-
public FeaturesController(CacheService cache, IRubberduckDbService db, FeatureServices features,
29+
public FeaturesController(CacheService cache, IRubberduckDbService db, FeatureServices features, IMarkdownFormattingService markdownService,
2330
IRepository<TagAssetEntity> assetsRepository, IRepository<TagEntity> tagsRepository, ILogger<FeaturesController> logger)
2431
: base(logger)
2532
{
@@ -28,6 +35,7 @@ public FeaturesController(CacheService cache, IRubberduckDbService db, FeatureSe
2835
this.features = features;
2936
this.assetsRepository = assetsRepository;
3037
this.tagsRepository = tagsRepository;
38+
this.markdownService = markdownService;
3139
}
3240

3341
private static RepositoryOptionViewModel[] RepositoryOptions { get; } =
@@ -38,8 +46,6 @@ await db.GetTopLevelFeatures(repositoryId)
3846
.ContinueWith(t => t.Result.Select(e => new FeatureOptionViewModel { Id = e.Id, Name = e.Name, Title = e.Title }).ToArray());
3947

4048
[HttpGet("features")]
41-
[EnableCors(CorsPolicies.AllowAll)]
42-
[AllowAnonymous]
4349
public IActionResult Index()
4450
{
4551
return GuardInternalAction(() =>
@@ -68,8 +74,6 @@ public IActionResult Index()
6874
}
6975

7076
[HttpGet("features/{name}")]
71-
[EnableCors(CorsPolicies.AllowAll)]
72-
[AllowAnonymous]
7377
public IActionResult Info([FromRoute] string name)
7478
{
7579
return GuardInternalAction(() =>
@@ -85,8 +89,6 @@ public IActionResult Info([FromRoute] string name)
8589
}
8690

8791
[HttpGet("inspections/{name}")]
88-
[EnableCors(CorsPolicies.AllowAll)]
89-
[AllowAnonymous]
9092
public IActionResult Inspection([FromRoute] string name)
9193
{
9294
return GuardInternalAction(() =>
@@ -107,8 +109,6 @@ public IActionResult Inspection([FromRoute] string name)
107109
}
108110

109111
[HttpGet("annotations/{name}")]
110-
[EnableCors(CorsPolicies.AllowAll)]
111-
[AllowAnonymous]
112112
public IActionResult Annotation([FromRoute] string name)
113113
{
114114
return GuardInternalAction(() =>
@@ -129,8 +129,6 @@ public IActionResult Annotation([FromRoute] string name)
129129
}
130130

131131
[HttpGet("quickfixes/{name}")]
132-
[EnableCors(CorsPolicies.AllowAll)]
133-
[AllowAnonymous]
134132
public IActionResult QuickFix([FromRoute] string name)
135133
{
136134
return GuardInternalAction(() =>
@@ -151,7 +149,6 @@ public IActionResult QuickFix([FromRoute] string name)
151149
}
152150

153151
[HttpGet("features/create")]
154-
[EnableCors(CorsPolicies.AllowAuthenticated)]
155152
[Authorize("github")]
156153
public async Task<ActionResult<FeatureEditViewModel>> Create([FromQuery] RepositoryId repository = RepositoryId.Rubberduck, [FromQuery] int? parentId = default)
157154
{
@@ -163,7 +160,6 @@ public async Task<ActionResult<FeatureEditViewModel>> Create([FromQuery] Reposit
163160
}
164161

165162
[HttpPost("create")]
166-
[EnableCors(CorsPolicies.AllowAuthenticated)]
167163
[Authorize("github")]
168164
public async Task<ActionResult<FeatureEditViewModel>> Create([FromBody] FeatureEditViewModel model)
169165
{
@@ -179,14 +175,14 @@ public async Task<ActionResult<FeatureEditViewModel>> Create([FromBody] FeatureE
179175
}
180176

181177
var feature = model.ToFeature();
182-
var result = await db.SaveFeature(feature);
183178

179+
var result = await db.SaveFeature(feature);
184180
var features = await GetFeatureOptions(model.RepositoryId);
181+
185182
return Ok(new FeatureEditViewModel(result, features, RepositoryOptions));
186183
}
187184

188185
[HttpPost("features/update")]
189-
[EnableCors(CorsPolicies.AllowAuthenticated)]
190186
[Authorize("github")]
191187
public async Task<ActionResult<FeatureEditViewModel>> Update([FromBody] FeatureEditViewModel model)
192188
{
@@ -201,12 +197,25 @@ public async Task<ActionResult<FeatureEditViewModel>> Update([FromBody] FeatureE
201197
return BadRequest("Model is invalid for this endpoint.");
202198
}
203199

204-
var result = await db.SaveFeature(model.ToFeature());
200+
var feature = model.ToFeature();
201+
202+
var result = await db.SaveFeature(feature);
205203
var features = await GetFeatureOptions(model.RepositoryId);
206204

207205
return new FeatureEditViewModel(result, features, RepositoryOptions);
208206
}
209207

208+
[HttpPost("markdown/format")]
209+
public MarkdownContentViewModel FormatMarkdown([FromBody] MarkdownContentViewModel model)
210+
{
211+
var markdown = model.Content;
212+
var formatted = markdownService.FormatMarkdownDocument(markdown, withSyntaxHighlighting: true);
213+
return new MarkdownContentViewModel
214+
{
215+
Content = formatted
216+
};
217+
}
218+
210219
private InspectionsFeatureViewModel GetInspections()
211220
{
212221
InspectionsFeatureViewModel result;
@@ -274,5 +283,4 @@ private FeatureViewModel GetFeature(string name)
274283

275284
return result;
276285
}
277-
278-
}
286+
}

rubberduckvba.Server/Model/Entity/FeatureEntity.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ namespace rubberduckvba.Server.Model.Entity;
44

55
public record class FeatureEntity : Entity
66
{
7-
public int? FeatureId { get; init; }
7+
public int? ParentId { get; init; }
88
public string FeatureName { get; init; } = default!;
99
public int RepositoryId { get; init; }
1010
public string Title { get; init; } = default!;

rubberduckvba.Server/Model/Feature.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public Feature(FeatureEntity entity) : this()
2727
DateTimeInserted = entity.DateTimeInserted;
2828
DateTimeUpdated = entity.DateTimeUpdated;
2929
Name = entity.Name;
30-
FeatureId = entity.FeatureId;
30+
ParentId = entity.ParentId;
3131
FeatureName = entity.FeatureName;
3232
RepositoryId = (Services.RepositoryId)entity.RepositoryId;
3333
Title = entity.Title;
@@ -45,7 +45,7 @@ public Feature(FeatureEntity entity) : this()
4545
public DateTime? DateTimeUpdated { get; init; }
4646
public string Name { get; init; } = string.Empty;
4747

48-
public int? FeatureId { get; init; }
48+
public int? ParentId { get; init; }
4949
public string FeatureName { get; init; } = string.Empty;
5050
public Services.RepositoryId RepositoryId { get; init; } = Services.RepositoryId.Rubberduck;
5151
public string Title { get; init; } = string.Empty;
@@ -69,7 +69,7 @@ public Feature(FeatureEntity entity) : this()
6969
IsNew = IsNew,
7070
Name = Name,
7171
ShortDescription = ShortDescription,
72-
FeatureId = FeatureId,
72+
ParentId = ParentId,
7373
FeatureName = FeatureName,
7474
RepositoryId = (int)Services.RepositoryId.Rubberduck,
7575
Title = Title,

rubberduckvba.Server/Program.cs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ public class HangfireAuthenticationFilter : IDashboardAuthorizationFilter
3535
public static class CorsPolicies
3636
{
3737
public const string AllowAll = "AllowAll";
38-
public const string AllowAuthenticated = "AllowAuthenticated";
3938
}
4039

4140
public class Program
@@ -57,17 +56,9 @@ public static void Main(string[] args)
5756
{
5857
policy
5958
.SetIsOriginAllowed(origin => true)
60-
.AllowAnyHeader()
61-
.WithMethods("OPTIONS", "GET", "POST")
62-
.Build();
63-
});
64-
builder.AddPolicy(CorsPolicies.AllowAuthenticated, policy =>
65-
{
66-
policy
67-
.SetIsOriginAllowed(origin => true)
68-
.WithHeaders("X-ACCESS-TOKEN")
6959
.WithMethods("OPTIONS", "GET", "POST")
70-
.AllowCredentials()
60+
.AllowAnyHeader()
61+
.AllowAnyOrigin()
7162
.Build();
7263
});
7364
});

rubberduckvba.Server/Services/RubberduckDbService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ public async Task<FeatureGraph> ResolveFeature(RepositoryId repositoryId, string
160160
{
161161
var features = _featureServices.Get(topLevelOnly: false).ToList();
162162
var feature = features.Single(e => string.Equals(e.Name, name, StringComparison.OrdinalIgnoreCase));
163-
var children = features.Where(e => e.FeatureId == feature.Id);
163+
var children = features.Where(e => e.ParentId == feature.Id);
164164
return new FeatureGraph(feature.ToEntity())
165165
{
166166
Features = children.ToArray()

rubberduckvba.Server/Services/rubberduckdb/FeatureServices.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class FeatureServices(
1515
public IEnumerable<Feature> Get(bool topLevelOnly = true)
1616
{
1717
return featureRepository.GetAll()
18-
.Where(e => !topLevelOnly || e.FeatureId is null)
18+
.Where(e => !topLevelOnly || e.ParentId is null)
1919
.Select(e => new Feature(e));
2020
}
2121

rubberduckvba.client/src/app/app.module.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import { AnnotationItemBoxComponent } from './components/feature-item-box/annota
2626
import { BlogLinkBoxComponent } from './components/blog-link-box/blog-link-box.component';
2727
import { QuickFixItemBoxComponent } from './components/feature-item-box/quickfix-item-box/quickfix-item-box.component';
2828

29+
import { EditFeatureComponent } from './components/edit-feature/edit-feature.component';
30+
2931
import { HomeComponent } from './routes/home/home.component';
3032
import { AboutComponent } from './routes/about/about.component';
3133
import { FeaturesComponent } from './routes/features/features.component';
@@ -78,7 +80,8 @@ export class LowerCaseUrlSerializer extends DefaultUrlSerializer {
7880
InspectionComponent,
7981
AnnotationComponent,
8082
QuickFixComponent,
81-
AboutComponent
83+
AboutComponent,
84+
EditFeatureComponent
8285
],
8386
bootstrap: [AppComponent],
8487
imports: [

0 commit comments

Comments
 (0)