Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions FinTrack/Core/SecureTokenStorage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace FinTrack.Core
{
public class SecureTokenStorage
{
private readonly string _filePath;

private static readonly byte[] s_entropy = Encoding.UTF8.GetBytes("E5A3B8B8_4A8C_4F1D_9F0B_2B3A7F9C1D0E"); // [TEST]

public SecureTokenStorage()
{
var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var appFolder = Path.Combine(appDataPath, "FinTrack");
Directory.CreateDirectory(appFolder);
_filePath = Path.Combine(appFolder, "user.token");
}

public void SaveToken(string token)
{
if (string.IsNullOrEmpty(token))
throw new ArgumentException("Token cannot be null or empty.", nameof(token));

try
{
var encryptedToken = ProtectedData.Protect(Encoding.UTF8.GetBytes(token), s_entropy, DataProtectionScope.CurrentUser);
File.WriteAllBytes(_filePath, encryptedToken);
}
catch (Exception ex)
{
Console.WriteLine($"Error saving token: {ex.Message}");
Copy link

Copilot AI Jun 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider replacing Console.WriteLine with a proper logging framework to improve error tracking and maintainability in production environments.

Copilot uses AI. Check for mistakes.
throw;
}
}

public string? GetToken()
{
if (!File.Exists(_filePath))
return null;

try
{
var encryptedBytes = File.ReadAllBytes(_filePath);
var tokenBytes = ProtectedData.Unprotect(encryptedBytes, s_entropy, DataProtectionScope.CurrentUser);
return Encoding.UTF8.GetString(tokenBytes);
}
catch (Exception ex)
{
Console.WriteLine($"Error retrieving token: {ex.Message}");
ClearToken();
return null;
}
}

public void ClearToken()
{
if (File.Exists(_filePath))
{
try
{
File.Delete(_filePath);
}
catch (Exception ex)
{
Console.WriteLine($"Error clearing token: {ex.Message}");
}
}
}
}
}
4 changes: 4 additions & 0 deletions FinTrack/Models/AccountModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ public class AccountModel
[Column("UpdateAt")]
public DateTime? UpdatedAtUtc { get; set; }

[Required]
[Column("IsSynced")]
public bool IsSynced { get; set; } = false;

public virtual ICollection<TransactionModel> Transactions { get; set; } = new List<TransactionModel>();
}

Expand Down
4 changes: 4 additions & 0 deletions FinTrack/Models/BudgetCategoryModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,9 @@ public class BudgetCategoryModel
[Column("AllocatedAmount", TypeName = "decimal(18, 2)")]
[Range(0.00, (double)decimal.MaxValue)]
public decimal AllocatedAmount { get; set; }

[Required]
[Column("IsSynced")]
public bool IsSynced { get; set; } = false;
}
}
4 changes: 4 additions & 0 deletions FinTrack/Models/BudgetModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ public class BudgetModel
[Column("UpdatedAtUtc")]
public DateTime? UpdatedAtUtc { get; set; }

[Required]
[Column("IsSynced")]
public bool IsSynced { get; set; } = false;

public virtual ICollection<BudgetCategoryModel> BudgetCategories { get; set; } = new List<BudgetCategoryModel>();
}
}
4 changes: 4 additions & 0 deletions FinTrack/Models/CategoryModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public class CategoryModel
[Column("CategoryType")]
public CategoryType Type { get; set; }

[Required]
[Column("IsSynced")]
public bool IsSynced { get; set; } = false;

public virtual ICollection<BudgetCategoryModel> BudgetAllocations { get; set; } = new List<BudgetCategoryModel>();
public virtual ICollection<TransactionModel> Transactions { get; set; } = new List<TransactionModel>();
}
Expand Down
4 changes: 4 additions & 0 deletions FinTrack/Models/TransactionModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,9 @@ public class TransactionModel
[Column("UpdatedAt")]
[DataType(DataType.DateTime)]
public DateTime? UpdatedAtUtc { get; set; }

[Required]
[Column("IsSynced")]
public bool IsSynced { get; set; } = false;
}
}
4 changes: 4 additions & 0 deletions FinTrack/Models/UserSettingsModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,9 @@ public class UserSettingsModel
[Column("EntryDate")]
[DataType(DataType.DateTime)]
public DateTime EntryDate { get; set; } = DateTime.UtcNow;

[Required]
[Column("IsSynced")]
public bool IsSynced { get; set; } = false;
}
}
2 changes: 1 addition & 1 deletion FinTrack/Services/AuthService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public AuthService()
{
_httpClient = new HttpClient
{
BaseAddress = new Uri("http://localhost:5246/")
BaseAddress = new Uri("http://localhost:5000/")
};

_httpClient.DefaultRequestHeaders.Accept.Clear();
Expand Down
8 changes: 8 additions & 0 deletions FinTrack/ViewModels/HomeViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using CommunityToolkit.Mvvm.ComponentModel;

namespace FinTrack.ViewModels
{
public partial class HomeViewModel : ObservableObject
{
}
}
18 changes: 18 additions & 0 deletions FinTrack/ViewModels/LoginViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ public partial class LoginViewModel : ObservableObject
public LoginViewModel()
{
_authService = new AuthService();

RegisteredTokenLogin();
}

private void RegisteredTokenLogin()
{
SecureTokenStorage secureTokenStorage = new SecureTokenStorage();
string? token = secureTokenStorage.GetToken();
if (!string.IsNullOrEmpty(token))
{
SessionManager.SetToken(token);
MessageBox.Show("Giriş başarılı! Token kullanıldı.", "Bilgi", MessageBoxButton.OK, MessageBoxImage.Information);
Copy link

Copilot AI Jun 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Consider decoupling UI messaging from the ViewModel by using an event or messaging service instead of directly calling MessageBox.Show to improve testability and separation of concerns.

Copilot uses AI. Check for mistakes.
}
}

[RelayCommand]
Expand All @@ -45,7 +58,12 @@ private async Task Login_LoginView_Button()
MessageBox.Show("Giriş başarısız oldu. Lütfen e-posta ve şifrenizi kontrol edin.", "Hata", MessageBoxButton.OK, MessageBoxImage.Error);
return;
}

SessionManager.SetToken(token);

SecureTokenStorage secureTokenStorage = new SecureTokenStorage();
secureTokenStorage.SaveToken(token);

MessageBox.Show("Giriş başarılı!", "Bilgi", MessageBoxButton.OK, MessageBoxImage.Information);
}

Expand Down
Loading