126 lines
4.1 KiB
C#
126 lines
4.1 KiB
C#
using ManagerService.Data;
|
|
using ManagerService.Helpers;
|
|
using ManagerService.Service.Services;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Security.Cryptography;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace ManagerService.Services
|
|
{
|
|
public class ApiKeyDatabaseService
|
|
{
|
|
private readonly MyInfoMateDbContext _db;
|
|
private readonly IHexIdGeneratorService _idService = new HexIdGeneratorService();
|
|
|
|
public ApiKeyDatabaseService(MyInfoMateDbContext db)
|
|
{
|
|
_db = db;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new API key with a hashed secret (returned once in plain text).
|
|
/// </summary>
|
|
public async Task<string> CreateAsync(string instanceId, string name, ApiKeyAppType appType)
|
|
{
|
|
var plainKey = "ak_" + Convert.ToBase64String(RandomNumberGenerator.GetBytes(32))
|
|
.Replace("+", "-").Replace("/", "_").TrimEnd('=');
|
|
|
|
var keyHash = TokensService.GenerateSHA256String(plainKey);
|
|
|
|
var apiKey = new ApiKey
|
|
{
|
|
Id = _idService.GenerateHexId(),
|
|
Name = name,
|
|
InstanceId = instanceId,
|
|
AppType = appType,
|
|
Key = null,
|
|
KeyHash = keyHash,
|
|
IsActive = true,
|
|
DateCreation = DateTime.UtcNow,
|
|
};
|
|
|
|
_db.ApiKeys.Add(apiKey);
|
|
await _db.SaveChangesAsync();
|
|
|
|
return plainKey;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns (or creates) a persistent plain-text key for a given instance + appType (PIN flow).
|
|
/// </summary>
|
|
public async Task<string> GetOrCreateByPinAsync(string instanceId, ApiKeyAppType appType)
|
|
{
|
|
var existing = await _db.ApiKeys.FirstOrDefaultAsync(k =>
|
|
k.InstanceId == instanceId &&
|
|
k.AppType == appType &&
|
|
k.IsActive &&
|
|
k.Key != null);
|
|
|
|
if (existing != null)
|
|
return existing.Key!;
|
|
|
|
var plainKey = "ak_" + Convert.ToBase64String(RandomNumberGenerator.GetBytes(32))
|
|
.Replace("+", "-").Replace("/", "_").TrimEnd('=');
|
|
|
|
var apiKey = new ApiKey
|
|
{
|
|
Id = _idService.GenerateHexId(),
|
|
Name = $"Auto-{appType}-{instanceId}",
|
|
InstanceId = instanceId,
|
|
AppType = appType,
|
|
Key = plainKey,
|
|
KeyHash = null,
|
|
IsActive = true,
|
|
DateCreation = DateTime.UtcNow,
|
|
};
|
|
|
|
_db.ApiKeys.Add(apiKey);
|
|
await _db.SaveChangesAsync();
|
|
|
|
return plainKey;
|
|
}
|
|
|
|
/// <summary>Returns all API keys for an instance (without secret values).</summary>
|
|
public async Task<List<ApiKeyDTO>> GetByInstanceAsync(string instanceId)
|
|
{
|
|
return await _db.ApiKeys
|
|
.Where(k => k.InstanceId == instanceId)
|
|
.Select(k => new ApiKeyDTO
|
|
{
|
|
Id = k.Id,
|
|
Name = k.Name,
|
|
AppType = k.AppType,
|
|
IsActive = k.IsActive,
|
|
DateCreation = k.DateCreation,
|
|
DateExpiration = k.DateExpiration,
|
|
})
|
|
.ToListAsync();
|
|
}
|
|
|
|
/// <summary>Revokes (deactivates) an API key, verifying ownership.</summary>
|
|
public async Task<bool> RevokeAsync(string id, string callerInstanceId)
|
|
{
|
|
var key = await _db.ApiKeys.FindAsync(id);
|
|
if (key == null || key.InstanceId != callerInstanceId)
|
|
return false;
|
|
|
|
key.IsActive = false;
|
|
await _db.SaveChangesAsync();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public class ApiKeyDTO
|
|
{
|
|
public string Id { get; set; }
|
|
public string Name { get; set; }
|
|
public ApiKeyAppType AppType { get; set; }
|
|
public bool IsActive { get; set; }
|
|
public DateTime DateCreation { get; set; }
|
|
public DateTime? DateExpiration { get; set; }
|
|
}
|
|
}
|