diff --git a/rubberduckvba.Server/Api/Admin/AdminController.cs b/rubberduckvba.Server/Api/Admin/AdminController.cs index cf48508..9cb8ed6 100644 --- a/rubberduckvba.Server/Api/Admin/AdminController.cs +++ b/rubberduckvba.Server/Api/Admin/AdminController.cs @@ -2,12 +2,13 @@ using Microsoft.AspNetCore.Cors; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; +using rubberduckvba.Server.Services; namespace rubberduckvba.Server.Api.Admin; [ApiController] -public class AdminController(ConfigurationOptions options, HangfireLauncherService hangfire) : ControllerBase +public class AdminController(ConfigurationOptions options, HangfireLauncherService hangfire, CacheService cache) : ControllerBase { /// /// Enqueues a job that updates xmldoc content from the latest release/pre-release tags. @@ -35,6 +36,15 @@ public IActionResult UpdateTagMetadata() return Ok(jobId); } + [Authorize("github")] + [EnableCors("CorsPolicy")] + [HttpPost("admin/cache/clear")] + public IActionResult ClearCache() + { + cache.Clear(); + return Ok(); + } + #if DEBUG [HttpGet("admin/config/current")] public IActionResult Config() diff --git a/rubberduckvba.Server/Services/CacheService.cs b/rubberduckvba.Server/Services/CacheService.cs index d11e47b..40a82be 100644 --- a/rubberduckvba.Server/Services/CacheService.cs +++ b/rubberduckvba.Server/Services/CacheService.cs @@ -150,6 +150,12 @@ public void Invalidate(AnnotationsFeatureViewModel newContent) } } + public void Clear() + { + _cache.Clear(); + _logger.LogInformation("Cache was cleared."); + } + private bool IsTagsCacheValid() => IsCacheValid(TagsJobState, () => TagsJobState); private bool IsXmldocCacheValid() => IsCacheValid(XmldocJobState, () => XmldocJobState); diff --git a/rubberduckvba.client/src/app/components/auth-menu/auth-menu.component.html b/rubberduckvba.client/src/app/components/auth-menu/auth-menu.component.html index 7667f64..ca5cf7f 100644 --- a/rubberduckvba.client/src/app/components/auth-menu/auth-menu.component.html +++ b/rubberduckvba.client/src/app/components/auth-menu/auth-menu.component.html @@ -26,6 +26,12 @@ Update xmldoc metadata +
+
+ +
@@ -100,3 +106,26 @@
Confirm
+ + + + diff --git a/rubberduckvba.client/src/app/components/auth-menu/auth-menu.component.ts b/rubberduckvba.client/src/app/components/auth-menu/auth-menu.component.ts index 672b29c..2739df8 100644 --- a/rubberduckvba.client/src/app/components/auth-menu/auth-menu.component.ts +++ b/rubberduckvba.client/src/app/components/auth-menu/auth-menu.component.ts @@ -26,6 +26,7 @@ export class AuthMenuComponent implements OnInit { @ViewChild('confirmbox', { read: TemplateRef }) confirmbox: TemplateRef | undefined; @ViewChild('confirmtagsbox', { read: TemplateRef }) confirmtagsbox: TemplateRef | undefined; @ViewChild('confirmxmldocsbox', { read: TemplateRef }) confirmxmldocsbox: TemplateRef | undefined; + @ViewChild('confirmclearcachebox', { read: TemplateRef }) confirmclearcachebox: TemplateRef | undefined; public modal = inject(NgbModal); constructor(private auth: AuthService, private api: ApiClientService, private fa: FaIconLibrary) { @@ -57,6 +58,10 @@ export class AuthMenuComponent implements OnInit { this.modal.open(this.confirmxmldocsbox); } + public confirmClearCache(): void { + this.modal.open(this.confirmclearcachebox); + } + public signin(): void { this.auth.signin(); this.getUserInfo(); @@ -76,4 +81,9 @@ export class AuthMenuComponent implements OnInit { this.modal.dismissAll(); this.api.updateXmldocMetadata().subscribe(jobId => console.log(`UpdateXmldocMetadata has scheduled job id ${jobId}`)); } + + public clearCache(): void { + this.modal.dismissAll(); + this.api.clearCache().subscribe(() => console.log(`Cache has been cleared`)); + } } diff --git a/rubberduckvba.client/src/app/services/api-client.service.ts b/rubberduckvba.client/src/app/services/api-client.service.ts index c6ea06c..5be402b 100644 --- a/rubberduckvba.client/src/app/services/api-client.service.ts +++ b/rubberduckvba.client/src/app/services/api-client.service.ts @@ -65,6 +65,11 @@ export class ApiClientService { return this.data.postAsync(url); } + public clearCache(): Observable { + const url = `${environment.apiBaseUrl}admin/cache/clear`; + return this.data.postAsync(url); + } + public getIndenterDefaults(): Observable { const url = `${environment.apiBaseUrl}indenter/defaults`; return this.data.getAsync(url).pipe(map(model => new IndenterViewModelClass(model)));