Login auch im Testmodus
Bei falschem Token nur eine Meldung
Exception bei falschem Token während Loadsettings abfangen
This commit is contained in:
2024-10-21 18:55:40 +02:00
parent 959804eb9d
commit 550c131771
7 changed files with 117 additions and 103 deletions

View File

@@ -1,4 +1,5 @@
using Microsoft.Extensions.Logging; using Jugenddienst_Stunden.Models;
using Microsoft.Extensions.Logging;
using ZXing.Net.Maui.Controls; using ZXing.Net.Maui.Controls;
namespace Jugenddienst_Stunden; namespace Jugenddienst_Stunden;
@@ -7,15 +8,16 @@ namespace Jugenddienst_Stunden;
/// Das Hauptprogramm. /// Das Hauptprogramm.
/// </summary> /// </summary>
public static class MauiProgram { public static class MauiProgram {
public static MauiApp CreateMauiApp() {
var builder = MauiApp.CreateBuilder(); public static MauiApp CreateMauiApp() {
builder var builder = MauiApp.CreateBuilder();
.UseMauiApp<App>() builder
.ConfigureFonts(fonts => { .UseMauiApp<App>()
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); .ConfigureFonts(fonts => {
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
}) fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
.UseBarcodeReader(); })
.UseBarcodeReader();
#if DEBUG #if DEBUG
//Preferences.Default.Set("apiKey", "M3xneWlWNG85TmNIcmo1NnpxWkxVYS9JMDBFRlV8aHR0cDovL2hvdXJzLmRhdW5pLm1pbmUubnU6ODEvYXBwYXBp"); //Preferences.Default.Set("apiKey", "M3xneWlWNG85TmNIcmo1NnpxWkxVYS9JMDBFRlV8aHR0cDovL2hvdXJzLmRhdW5pLm1pbmUubnU6ODEvYXBwYXBp");
@@ -23,18 +25,18 @@ public static class MauiProgram {
//Preferences.Default.Set("surname", "Mair"); //Preferences.Default.Set("surname", "Mair");
//Preferences.Default.Set("EmployeeId", 3); //Preferences.Default.Set("EmployeeId", 3);
//Preferences.Default.Set("apiUrl", "http://hours.dauni.mine.nu:81/appapi"); //Preferences.Default.Set("apiUrl", "http://hours.dauni.mine.nu:81/appapi");
HoursBase HoursBase = new HoursBase();
Preferences.Default.Set("apiKey", "MTQxfHNkdFptQkNZTXlPT3ZyMHNBZDl0UnVxNExMRXxodHRwOi8vaG91cnMuZGF1bmkubWluZS5udTo4MS9hcHBhcGk="); HoursBase.apiKey = Preferences.Default.Get("apiKey", "MTQxfHNkdFptQkNZTXlPT3ZyMHNBZDl0UnVxNExMRXxodHRwOi8vaG91cnMuZGF1bmkubWluZS5udTo4MS9hcHBhcGk=");
Preferences.Default.Set("name", "Testserver: Isabell"); HoursBase.name = Preferences.Default.Get("name", "Testserver: Isabell");
Preferences.Default.Set("surname", "Biasi"); HoursBase.surname = Preferences.Default.Get("surname", "Biasi");
Preferences.Default.Set("EmployeeId", 141); HoursBase.EmployeeId = Preferences.Default.Get("EmployeeId", 141);
Preferences.Default.Set("apiUrl", "http://hours.dauni.mine.nu:81/appapi"); HoursBase.apiUrl = Preferences.Default.Get("apiUrl", "http://hours.dauni.mine.nu:81/appapi");
builder.Logging.AddDebug(); builder.Logging.AddDebug();
#endif #endif
return builder.Build(); return builder.Build();
} }
} }

View File

@@ -43,7 +43,6 @@ internal static class BaseFunc {
using (JsonDocument doc = JsonDocument.Parse(responseData, options)) { using (JsonDocument doc = JsonDocument.Parse(responseData, options)) {
JsonElement root = doc.RootElement; JsonElement root = doc.RootElement;
string message = root.GetProperty("message").GetString() ?? throw new Exception("Fehler: 'message' ist null."); string message = root.GetProperty("message").GetString() ?? throw new Exception("Fehler: 'message' ist null.");
throw new Exception(message); throw new Exception(message);
} }
} }

View File

@@ -14,7 +14,7 @@ internal class HoursBase {
public static string surname = Preferences.Default.Get("surname", ""); public static string surname = Preferences.Default.Get("surname", "");
public static string apiUrl = Preferences.Default.Get("apiUrl", ""); public static string apiUrl = Preferences.Default.Get("apiUrl", "");
internal static TokenData tokendata = new TokenData(apiKey); internal static TokenData tokendata;
/// <summary> /// <summary>
@@ -24,7 +24,7 @@ internal class HoursBase {
string data = await BaseFunc.GetApiDataWithAuthAsync(tokendata.Url + "?settings", tokendata.ApiKey); string data = await BaseFunc.GetApiDataWithAuthAsync(tokendata.Url + "?settings", tokendata.ApiKey);
Settings _settings = JsonConvert.DeserializeObject<Settings>(data) ?? throw new Exception("Fehler beim Deserialisieren der Daten"); Settings _settings = JsonConvert.DeserializeObject<Settings>(data);
return _settings; return _settings;
} }

View File

@@ -10,8 +10,17 @@ internal class TokenData {
public string Operator_id { get; set; } public string Operator_id { get; set; }
public TokenData(string ak) { public TokenData(string ak) {
string dat = Encoding.UTF8.GetString(Convert.FromBase64String(ak)); if (string.IsNullOrEmpty(ak)) {
Token = dat.Split('|')[1]; ; throw new ArgumentException("API key cannot be null or empty", nameof(ak));
}
string dat = Encoding.UTF8.GetString(Convert.FromBase64String(ak));
string[] parts = dat.Split('|');
if (parts.Length < 3) {
throw new FormatException("API key format is invalid");
}
Token = dat.Split('|')[1]; ;
Url = dat.Split('|')[2]; ; Url = dat.Split('|')[2]; ;
Operator_id = dat.Split('|')[0]; ; Operator_id = dat.Split('|')[0]; ;
ApiKey = ak; ApiKey = ak;

View File

@@ -95,21 +95,28 @@ public class StundeViewModel : ObservableObject, IQueryAttributable {
} }
private async void LoadSettingsAsync() { private async void LoadSettingsAsync() {
Settings = await HoursBase.LoadSettings();
try {
Settings = await HoursBase.LoadSettings();
OptionsGemeinde = Settings.Gemeinden;
OptionsProjekt = Settings.Projekte;
OptionsFreistellung = Settings.Freistellungen;
GemeindeAktivSet = Settings.GemeindeAktivSet;
ProjektAktivSet = Settings.ProjektAktivSet;
OnPropertyChanged(nameof(OptionsGemeinde));
OnPropertyChanged(nameof(OptionsFreistellung));
OnPropertyChanged(nameof(OptionsProjekt));
OnPropertyChanged(nameof(GemeindeAktivSet));
OnPropertyChanged(nameof(ProjektAktivSet));
} catch (Exception e) {
AlertEvent?.Invoke(this, e.Message);
}
OptionsGemeinde = Settings.Gemeinden;
OptionsProjekt = Settings.Projekte;
OptionsFreistellung = Settings.Freistellungen;
GemeindeAktivSet = Settings.GemeindeAktivSet;
ProjektAktivSet = Settings.ProjektAktivSet;
OnPropertyChanged(nameof(OptionsGemeinde));
OnPropertyChanged(nameof(OptionsFreistellung));
OnPropertyChanged(nameof(OptionsProjekt));
OnPropertyChanged(nameof(GemeindeAktivSet));
OnPropertyChanged(nameof(ProjektAktivSet));
} }

View File

@@ -2,11 +2,8 @@
using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Input;
using Jugenddienst_Stunden.Models; using Jugenddienst_Stunden.Models;
using Jugenddienst_Stunden.Types; using Jugenddienst_Stunden.Types;
using Newtonsoft.Json.Linq;
using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
@@ -151,13 +148,14 @@ internal class StundenViewModel : ObservableObject, IQueryAttributable, INotifyP
/// </summary> /// </summary>
public bool ProjektAktivSet { get; set; } public bool ProjektAktivSet { get; set; }
private bool doContinue = true;
/// <summary> /// <summary>
/// CTOR /// CTOR
/// </summary> /// </summary>
public StundenViewModel() { public StundenViewModel() {
_hour = new Hours(); _hour = new Hours();
//LoadSettingsAsync();
LoadDataCommand = new AsyncRelayCommand(LoadData); LoadDataCommand = new AsyncRelayCommand(LoadData);
NewEntryCommand = new AsyncRelayCommand(NewEntryAsync); NewEntryCommand = new AsyncRelayCommand(NewEntryAsync);
@@ -166,17 +164,23 @@ internal class StundenViewModel : ObservableObject, IQueryAttributable, INotifyP
RefreshCommand = new Command(async () => await RefreshItemsAsync()); RefreshCommand = new Command(async () => await RefreshItemsAsync());
Task task = LoadDay(DateTime.Today); Task task = LoadDay(DateTime.Today);
LoadSettingsAsync();
} }
private async void LoadSettingsAsync() { private async Task LoadSettingsAsync() {
Settings = await HoursBase.LoadSettings(); try {
Settings = await HoursBase.LoadSettings();
GemeindeAktivSet = Settings.GemeindeAktivSet; GemeindeAktivSet = Settings.GemeindeAktivSet;
ProjektAktivSet = Settings.ProjektAktivSet; ProjektAktivSet = Settings.ProjektAktivSet;
OnPropertyChanged(nameof(GemeindeAktivSet)); OnPropertyChanged(nameof(GemeindeAktivSet));
OnPropertyChanged(nameof(ProjektAktivSet)); OnPropertyChanged(nameof(ProjektAktivSet));
doContinue = true;
} catch (Exception e) {
doContinue = false;
AlertEvent?.Invoke(this, e.Message);
}
} }
@@ -222,43 +226,42 @@ internal class StundenViewModel : ObservableObject, IQueryAttributable, INotifyP
/// </summary> /// </summary>
public async Task LoadDay(DateTime date) { public async Task LoadDay(DateTime date) {
DayTotal = new TimeOnly(0); DayTotal = new TimeOnly(0);
LoadSettingsAsync(); await LoadSettingsAsync();
try { //if (doContinue) {
DayTimes = await HoursBase.LoadDay(date); try {
DayTimes = await HoursBase.LoadDay(date);
List<Sollstunden> _soll;
List<Sollstunden> _soll; TimeSpan span = TimeSpan.Zero;
TimeSpan span = TimeSpan.Zero; bool merker = false;
bool merker = false; foreach (DayTime dt in DayTimes) {
foreach (DayTime dt in DayTimes) { span += dt.End - dt.Begin;
span += dt.End - dt.Begin; //Nachtstunden dazurechnen
//Nachtstunden dazurechnen if (dt.Night.Ticks > 0 && !merker) {
if (dt.Night.Ticks > 0 && !merker) { span += dt.Night.ToTimeSpan() * .5;
span += dt.Night.ToTimeSpan() * .5; merker = true;
merker = true; }
_soll = Settings.Nominal.Where(w => w.Timetable == dt.TimeTable && w.Wochentag == dt.Wday).ToList();
if (_soll.Count > 0)
Sollstunden = TimeOnly.FromTimeSpan(TimeSpan.FromHours(_soll[0].Zeit));
} }
_soll = Settings.Nominal.Where(w => w.Timetable == dt.TimeTable && w.Wochentag == dt.Wday).ToList(); DayTotal = TimeOnly.FromTimeSpan(span);
if (_soll.Count > 0)
Sollstunden = TimeOnly.FromTimeSpan(TimeSpan.FromHours(_soll[0].Zeit));
} catch (Exception e) {
DayTimes = new List<DayTime>();
//TODO: hier könnte auch ein Fehler kommen, dann wäre InfoEvent falsch.
InfoEvent?.Invoke(this, e.Message);
} finally {
OnPropertyChanged(nameof(DayTotal));
OnPropertyChanged(nameof(Sollstunden));
//OnPropertyChanged(nameof(DayTimes));
} }
DayTotal = TimeOnly.FromTimeSpan(span); //}
} catch (Exception e) {
DayTimes = new List<DayTime>();
//TODO: hier könnte auch ein Fehler kommen, dann wäre InfoEvent falsch.
InfoEvent?.Invoke(this, e.Message);
} finally {
OnPropertyChanged(nameof(DayTotal));
OnPropertyChanged(nameof(Sollstunden));
//OnPropertyChanged(nameof(DayTimes));
}
} }
async void IQueryAttributable.ApplyQueryAttributes(IDictionary<string, object> query) { async void IQueryAttributable.ApplyQueryAttributes(IDictionary<string, object> query) {
if (query.ContainsKey("date")) { if (query.ContainsKey("date")) {
await LoadDay(Convert.ToDateTime(query["date"])); await LoadDay(Convert.ToDateTime(query["date"]));

View File

@@ -1,14 +1,5 @@
using System;
using Jugenddienst_Stunden.Models; using Jugenddienst_Stunden.Models;
using Jugenddienst_Stunden.ViewModels;
using Microsoft.Maui.Controls;
using System.Collections.Generic;
using ZXing.Net.Maui; using ZXing.Net.Maui;
using Microsoft.Maui.Devices;
using static Microsoft.Maui.ApplicationModel.Permissions;
using ZXing.Net.Maui.Controls;
using ZXing.QrCode.Internal;
using System.Linq;
namespace Jugenddienst_Stunden.Views; namespace Jugenddienst_Stunden.Views;
@@ -19,12 +10,13 @@ public partial class LoginPage : ContentPage {
private DateTime _lastDetectionTime; private DateTime _lastDetectionTime;
private readonly TimeSpan _detectionInterval = TimeSpan.FromSeconds(5); private readonly TimeSpan _detectionInterval = TimeSpan.FromSeconds(5);
private bool hasCamera = false;
/// <summary> internal HoursBase HoursBase = new HoursBase();
/// CTOR
/// </summary> /// <summary>
public LoginPage() { /// CTOR
/// </summary>
public LoginPage() {
InitializeComponent(); InitializeComponent();
//if (BindingContext is LoginViewModel vm) { //if (BindingContext is LoginViewModel vm) {
@@ -55,11 +47,13 @@ public partial class LoginPage : ContentPage {
try { try {
var tokendata = new TokenData(barcode.Value); var tokendata = new TokenData(barcode.Value);
var op = await Models.HoursBase.LoadOperator(barcode.Value); HoursBase.tokendata = tokendata;
Models.HoursBase.apiKey = barcode.Value;
Models.HoursBase.name = op.name; var op = await HoursBase.LoadOperator(barcode.Value);
Models.HoursBase.surname = op.surname; HoursBase.apiKey = barcode.Value;
Models.HoursBase.EmployeeId = int.Parse(op.id); HoursBase.name = op.name;
HoursBase.surname = op.surname;
HoursBase.EmployeeId = int.Parse(op.id);
Title = op.name + " " + op.surname; Title = op.name + " " + op.surname;
ServerLabel.Text = "Server: " + tokendata.Url.Replace("/appapi", "").Replace("https://", "").Replace("http://", ""); ServerLabel.Text = "Server: " + tokendata.Url.Replace("/appapi", "").Replace("https://", "").Replace("http://", "");
@@ -125,11 +119,11 @@ public partial class LoginPage : ContentPage {
Types.User response = await BaseFunc.AuthUserPass(username, password, server); Types.User response = await BaseFunc.AuthUserPass(username, password, server);
var tokendata = new TokenData(response.Token); var tokendata = new TokenData(response.Token);
var op = await Models.HoursBase.LoadOperator(response.Token); var op = await HoursBase.LoadOperator(response.Token);
Models.HoursBase.apiKey = response.Token; HoursBase.apiKey = response.Token;
Models.HoursBase.name = op.name; HoursBase.name = op.name;
Models.HoursBase.surname = op.surname; HoursBase.surname = op.surname;
Models.HoursBase.EmployeeId = int.Parse(op.id); HoursBase.EmployeeId = int.Parse(op.id);
Title = op.name + " " + op.surname; Title = op.name + " " + op.surname;
ServerLabel.Text = "Server: " + tokendata.Url.Replace("/appapi", "").Replace("https://", "").Replace("http://", ""); ServerLabel.Text = "Server: " + tokendata.Url.Replace("/appapi", "").Replace("https://", "").Replace("http://", "");