11using System ;
22using System . Collections . Generic ;
33using System . Linq ;
4+ using System . Text ;
45using System . Threading . Tasks ;
56using AgileConfig . Server . Apisite . Filters ;
67using AgileConfig . Server . Apisite . Models ;
1415using AgileConfig . Server . IService ;
1516using Microsoft . AspNetCore . Authorization ;
1617using Microsoft . AspNetCore . Mvc ;
18+ using Newtonsoft . Json ;
1719
1820namespace AgileConfig . Server . Apisite . Controllers ;
1921
@@ -22,14 +24,20 @@ namespace AgileConfig.Server.Apisite.Controllers;
2224public class AppController : Controller
2325{
2426 private readonly IAppService _appService ;
27+ private readonly IConfigService _configService ;
28+ private readonly ISettingService _settingService ;
2529 private readonly ITinyEventBus _tinyEventBus ;
2630 private readonly IUserService _userService ;
2731
2832 public AppController ( IAppService appService ,
2933 IUserService userService ,
34+ IConfigService configService ,
35+ ISettingService settingService ,
3036 ITinyEventBus tinyEventBus )
3137 {
3238 _userService = userService ;
39+ _configService = configService ;
40+ _settingService = settingService ;
3341 _tinyEventBus = tinyEventBus ;
3442 _appService = appService ;
3543 }
@@ -107,6 +115,26 @@ private async Task AppendInheritancedInfo(List<AppListVM> list)
107115 }
108116 }
109117
118+ private async Task < bool > IsCurrentUserAdmin ( string currentUserId )
119+ {
120+ if ( string . IsNullOrWhiteSpace ( currentUserId ) ) return false ;
121+
122+ var roles = await _userService . GetUserRolesAsync ( currentUserId ) ;
123+ return roles . Any ( r => r . Id == SystemRoleConstants . AdminId || r . Id == SystemRoleConstants . SuperAdminId ) ;
124+ }
125+
126+ private async Task < App > GetAuthorizedAppAsync ( string appId , string currentUserId , bool isAdmin )
127+ {
128+ var app = await _appService . GetAsync ( appId ) ;
129+ if ( app == null ) return null ;
130+
131+ if ( isAdmin ) return app ;
132+
133+ var searchResult = await _appService . SearchAsync ( appId , null , null , nameof ( App . Id ) , "ascend" , 1 , 1 ,
134+ currentUserId , false ) ;
135+ return searchResult . Apps . FirstOrDefault ( x => x . Id == appId ) ;
136+ }
137+
110138 [ TypeFilter ( typeof ( PermissionCheckAttribute ) , Arguments = new object [ ] { Functions . App_Add } ) ]
111139 [ HttpPost ]
112140 public async Task < IActionResult > Add ( [ FromBody ] AppVM model )
@@ -273,6 +301,87 @@ public async Task<IActionResult> Delete(string id)
273301 } ) ;
274302 }
275303
304+ [ TypeFilter ( typeof ( PermissionCheckAttribute ) , Arguments = new object [ ] { Functions . App_Read } ) ]
305+ [ HttpPost ]
306+ public async Task < IActionResult > Export ( [ FromBody ] AppExportRequest model )
307+ {
308+ ArgumentNullException . ThrowIfNull ( model ) ;
309+
310+ var appIds = model . AppIds ?
311+ . Where ( x => ! string . IsNullOrWhiteSpace ( x ) )
312+ . Distinct ( StringComparer . OrdinalIgnoreCase )
313+ . ToList ( ) ?? new List < string > ( ) ;
314+ if ( ! appIds . Any ( ) ) throw new ArgumentException ( "appIds" ) ;
315+
316+ var currentUserId = await this . GetCurrentUserId ( _userService ) ;
317+ var isAdmin = await IsCurrentUserAdmin ( currentUserId ) ;
318+
319+ var apps = new List < App > ( ) ;
320+ foreach ( var appId in appIds )
321+ {
322+ var app = await GetAuthorizedAppAsync ( appId , currentUserId , isAdmin ) ;
323+ if ( app == null )
324+ {
325+ Response . StatusCode = 403 ;
326+ return new ContentResult ( ) ;
327+ }
328+
329+ apps . Add ( app ) ;
330+ }
331+
332+ var envs = ( await _settingService . GetEnvironmentList ( ) )
333+ . Where ( x => ! string . IsNullOrWhiteSpace ( x ) )
334+ . Distinct ( StringComparer . OrdinalIgnoreCase )
335+ . OrderBy ( x => x , StringComparer . Ordinal )
336+ . ToList ( ) ;
337+
338+ var exportFile = new AppExportFileVM
339+ {
340+ ExportedAt = DateTime . UtcNow
341+ } ;
342+
343+ foreach ( var app in apps )
344+ {
345+ var inheritancedApps = await _appService . GetInheritancedAppsAsync ( app . Id ) ;
346+ var exportItem = new AppExportItemVM
347+ {
348+ App = new AppExportAppVM
349+ {
350+ Id = app . Id ,
351+ Name = app . Name ,
352+ Group = app . Group ,
353+ Secret = app . Secret ,
354+ Enabled = app . Enabled ,
355+ Type = ( int ) app . Type ,
356+ Inheritanced = app . Type == AppType . Inheritance ,
357+ InheritancedApps = inheritancedApps . Select ( x => x . Id ) . ToList ( )
358+ }
359+ } ;
360+
361+ foreach ( var env in envs )
362+ {
363+ var configs = await _configService . GetByAppIdAsync ( app . Id , env ) ;
364+ exportItem . Envs [ env ] = configs
365+ . OrderBy ( x => x . Group ?? string . Empty , StringComparer . Ordinal )
366+ . ThenBy ( x => x . Key ?? string . Empty , StringComparer . Ordinal )
367+ . Select ( x => new AppExportConfigVM
368+ {
369+ Group = x . Group ,
370+ Key = x . Key ,
371+ Value = x . Value ,
372+ Description = x . Description
373+ } )
374+ . ToList ( ) ;
375+ }
376+
377+ exportFile . Apps . Add ( exportItem ) ;
378+ }
379+
380+ var json = JsonConvert . SerializeObject ( exportFile , Formatting . Indented ) ;
381+ var fileName = $ "agileconfig-export-{ DateTime . UtcNow : yyyyMMddHHmmss} .json";
382+ return File ( Encoding . UTF8 . GetBytes ( json ) , "application/json" , fileName ) ;
383+ }
384+
276385 /// <summary>
277386 /// Get all applications that can be inherited.
278387 /// </summary>
0 commit comments