Skip to content

Commit 6757faa

Browse files
committed
Added API support for Profile import/export
1 parent 37d4597 commit 6757faa

File tree

4 files changed

+162
-4
lines changed

4 files changed

+162
-4
lines changed

OpenBioCardServer/Controllers/Classic/ClassicUserController.cs

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public async Task<IActionResult> GetProfile(string username)
5252
[HttpPost("{username}")]
5353
public async Task<IActionResult> UpdateProfile(string username, [FromBody] ClassicProfile request)
5454
{
55-
var token = Request.Headers["Authorization"].FirstOrDefault()?.Replace("Bearer ", "");
55+
var token = GetTokenFromHeader();
5656

5757
if (string.IsNullOrEmpty(token))
5858
{
@@ -84,8 +84,98 @@ public async Task<IActionResult> UpdateProfile(string username, [FromBody] Class
8484
}
8585
catch (Exception)
8686
{
87-
// Exception is already logged in the service
8887
return StatusCode(500, new { error = "Profile update failed" });
8988
}
9089
}
90+
91+
/// <summary>
92+
/// Export user data (requires authentication)
93+
/// </summary>
94+
[HttpGet("{username}/export")]
95+
public async Task<IActionResult> ExportData(string username)
96+
{
97+
var token = GetTokenFromHeader();
98+
99+
if (string.IsNullOrEmpty(token))
100+
{
101+
return Unauthorized(new { error = "Missing authentication token" });
102+
}
103+
104+
var (isValid, account) = await _authService.ValidateTokenAsync(token);
105+
106+
if (!isValid || account == null)
107+
{
108+
return Unauthorized(new { error = "Invalid token" });
109+
}
110+
111+
if (account.UserName != username)
112+
{
113+
return Unauthorized(new { error = "Token does not match username" });
114+
}
115+
116+
try
117+
{
118+
var exportData = await _profileService.GetExportDataAsync(username, token);
119+
120+
if (exportData == null)
121+
{
122+
return NotFound(new { error = "User data not found" });
123+
}
124+
125+
return Ok(exportData);
126+
}
127+
catch (Exception ex)
128+
{
129+
_logger.LogError(ex, "Error exporting data for user: {Username}", username);
130+
return StatusCode(500, new { error = "Export failed" });
131+
}
132+
}
133+
134+
/// <summary>
135+
/// Import user data (requires authentication)
136+
/// </summary>
137+
[HttpPost("{username}/import")]
138+
public async Task<IActionResult> ImportData(string username, [FromBody] ClassicImportExportDto request)
139+
{
140+
var token = GetTokenFromHeader();
141+
142+
if (string.IsNullOrEmpty(token))
143+
{
144+
return Unauthorized(new { error = "Missing authentication token" });
145+
}
146+
147+
var (isValid, account) = await _authService.ValidateTokenAsync(token);
148+
149+
if (!isValid || account == null)
150+
{
151+
return Unauthorized(new { error = "Invalid token" });
152+
}
153+
154+
if (account.UserName != username)
155+
{
156+
return Unauthorized(new { error = "Token does not match username" });
157+
}
158+
159+
try
160+
{
161+
var success = await _profileService.ImportDataAsync(username, request);
162+
163+
if (!success)
164+
{
165+
return BadRequest(new { error = "Import failed or username mismatch" });
166+
}
167+
168+
return Ok(new { success = true });
169+
}
170+
catch (Exception ex)
171+
{
172+
_logger.LogError(ex, "Error importing data for user: {Username}", username);
173+
return StatusCode(500, new { error = "Import failed" });
174+
}
175+
}
176+
177+
private string? GetTokenFromHeader()
178+
{
179+
return Request.Headers["Authorization"].FirstOrDefault()?.Replace("Bearer ", "");
180+
}
91181
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using Newtonsoft.Json;
2+
3+
namespace OpenBioCardServer.Models.DTOs.Classic;
4+
5+
public class ClassicImportExportDto
6+
{
7+
[JsonProperty("user")]
8+
public ClassicUserExportDto User { get; set; } = new();
9+
10+
[JsonProperty("profile")]
11+
public ClassicProfile Profile { get; set; } = new();
12+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Newtonsoft.Json;
2+
3+
namespace OpenBioCardServer.Models.DTOs.Classic;
4+
5+
public class ClassicUserExportDto
6+
{
7+
[JsonProperty("username")]
8+
public string Username { get; set; } = string.Empty;
9+
10+
[JsonProperty("type")]
11+
public string Type { get; set; } = string.Empty;
12+
13+
[JsonProperty("token")]
14+
public string Token { get; set; } = string.Empty;
15+
}

OpenBioCardServer/Services/ClassicProfileService.cs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using Microsoft.EntityFrameworkCore;
22
using OpenBioCardServer.Data;
3-
using OpenBioCardServer.Interfaces;
43
using OpenBioCardServer.Models.DTOs.Classic;
54
using OpenBioCardServer.Utilities.Mappers;
65
using ZiggyCreatures.Caching.Fusion;
@@ -46,11 +45,53 @@ private static string GetProfileCacheKey(string username) =>
4645
.Include(p => p.WorkExperiences)
4746
.Include(p => p.SchoolExperiences)
4847
.Include(p => p.Gallery)
49-
.FirstOrDefaultAsync(p => p.Username == username, token); // 传入 token
48+
.FirstOrDefaultAsync(p => p.Username == username, token);
5049
return profile == null ? null : ClassicMapper.ToClassicProfile(profile);
5150
});
5251
}
5352

53+
/// <summary>
54+
/// 获取用户完整导出数据 (User + Profile)
55+
/// </summary>
56+
public async Task<ClassicImportExportDto?> GetExportDataAsync(string username, string currentToken)
57+
{
58+
var account = await _context.Accounts
59+
.AsNoTracking()
60+
.FirstOrDefaultAsync(a => a.UserName == username);
61+
62+
if (account == null) return null;
63+
64+
var profileDto = await GetProfileAsync(username);
65+
if (profileDto == null) return null;
66+
67+
return new ClassicImportExportDto
68+
{
69+
User = new ClassicUserExportDto
70+
{
71+
Username = account.UserName,
72+
Type = account.Type.ToString().ToLowerInvariant(),
73+
Token = currentToken
74+
},
75+
Profile = profileDto
76+
};
77+
}
78+
79+
/// <summary>
80+
/// 导入用户数据 (主要更新 Profile)
81+
/// </summary>
82+
public async Task<bool> ImportDataAsync(string username, ClassicImportExportDto data)
83+
{
84+
// 验证导入的数据是否属于当前用户
85+
if (!string.Equals(data.User.Username, username, StringComparison.OrdinalIgnoreCase))
86+
{
87+
_logger.LogWarning("Import username mismatch. Target: {Target}, Import: {Import}",
88+
username, data.User.Username);
89+
return false;
90+
}
91+
92+
return await UpdateProfileAsync(username, data.Profile);
93+
}
94+
5495
/// <summary>
5596
/// 更新用户 Profile
5697
/// </summary>

0 commit comments

Comments
 (0)