Login-Register Update

main
unknown 6 months ago
parent d1f9f85a9e
commit 4108506fc5
  1. 6
      App.xaml.cs
  2. 1
      AppShell.xaml
  3. 27
      Helpers/AuthHelper.cs
  4. 1
      Models/User.cs
  5. 20
      Views/DashboardPage.xaml
  6. 2
      Views/DashboardPage.xaml.cs
  7. 3
      Views/LoginPage.xaml
  8. 22
      Views/LoginPage.xaml.cs
  9. 32
      Views/RegistrationPage.xaml
  10. 130
      Views/RegistrationPage.xaml.cs

@ -19,7 +19,11 @@ namespace Justice
var dbHelper = new DatabaseHelper(); var dbHelper = new DatabaseHelper();
await dbHelper.InitializeAsync<EmergencyContact>(); await dbHelper.InitializeAsync<EmergencyContact>();
await dbHelper.InitializeAsync<IncidentReport>(); await dbHelper.InitializeAsync<IncidentReport>();
await dbHelper.InitializeAsync<User>();// Asynchronously create the EmergencyContact table await dbHelper.InitializeAsync<User>();
Task.Run(async () =>
{
await dbHelper.InitializeAsync<User>(); // Initialize the User table
}).Wait();// Asynchronously create the EmergencyContact table
} }
catch (Exception ex) catch (Exception ex)
{ {

@ -10,6 +10,7 @@
<ShellContent Title="Login" ContentTemplate="{DataTemplate views:LoginPage}" Route="LoginPage" /> <ShellContent Title="Login" ContentTemplate="{DataTemplate views:LoginPage}" Route="LoginPage" />
<ShellContent Title="Dashboard" ContentTemplate="{DataTemplate views:DashboardPage}" Route="DashboardPage" /> <ShellContent Title="Dashboard" ContentTemplate="{DataTemplate views:DashboardPage}" Route="DashboardPage" />
<ShellContent Title="View Reports" ContentTemplate="{DataTemplate views:ViewReportsPage}" Route="ViewReportsPage" /> <ShellContent Title="View Reports" ContentTemplate="{DataTemplate views:ViewReportsPage}" Route="ViewReportsPage" />
<ShellContent Title="Register" ContentTemplate="{DataTemplate views:RegistrationPage}" Route="RegistrationPage" />
<MenuItem Text="Logout" Command="{Binding LogoutCommand}" /> <MenuItem Text="Logout" Command="{Binding LogoutCommand}" />
</Shell> </Shell>

@ -0,0 +1,27 @@
using Microsoft.Maui.Storage;
namespace Justice.Helpers
{
public static class AuthHelper
{
private const string IsLoggedInKey = "IsLoggedIn";
private const string UserRoleKey = "UserRole";
public static bool IsLoggedIn => Preferences.Get(IsLoggedInKey, false);
public static string UserRole => Preferences.Get(UserRoleKey, string.Empty);
public static void Login(string role)
{
Preferences.Set(IsLoggedInKey, true);
Preferences.Set(UserRoleKey, role);
}
public static void Logout()
{
Preferences.Remove(IsLoggedInKey);
Preferences.Remove(UserRoleKey);
}
}
}

@ -13,6 +13,7 @@ namespace Justice.Models
public string Password { get; set; } public string Password { get; set; }
public string Role { get; set; } public string Role { get; set; }
public string AuthorityType { get; set; } public string AuthorityType { get; set; }
public string IdentityFilePath { get; set; }
} }
public class AuthorityUser : User public class AuthorityUser : User
{ {

@ -5,17 +5,19 @@
Title="DashboardPage" BackgroundColor="WhiteSmoke"> Title="DashboardPage" BackgroundColor="WhiteSmoke">
<ScrollView> <ScrollView>
<VerticalStackLayout> <VerticalStackLayout>
<Label Text="Welcome to the End User Dashboard!" FontSize="Large" HorizontalOptions="Center" />
<!-- Logout Button --> <!-- Logout Button -->
<Button Text="Logout" Clicked="OnLogoutClicked" HorizontalOptions="Center" VerticalOptions="EndAndExpand" /> <Grid>
<Button Text="Get Current Location" <Grid.ColumnDefinitions>
HorizontalOptions="Fill" <ColumnDefinition Width="*"/>
BackgroundColor="White" <ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
TextColor="DarkGray"/> <VerticalStackLayout>
<Label Grid.Column="0" Text="Welcome to the User Dashboard!" FontSize="Medium" HorizontalOptions="Center" Margin="10" FontAttributes="Bold" TextColor="DarkGray"/>
<Border></Border>
</VerticalStackLayout>
<Button Grid.Column="1" Text="Logout" Clicked="OnLogoutClicked" HorizontalOptions="Start" VerticalOptions="EndAndExpand" />
</Grid>
<Grid RowSpacing="10" ColumnSpacing="10"> <Grid RowSpacing="10" ColumnSpacing="10">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>

@ -43,8 +43,10 @@ public partial class DashboardPage : ContentPage
bool confirm = await DisplayAlert("Logout", "Are you sure you want to log out?", "Yes", "No"); bool confirm = await DisplayAlert("Logout", "Are you sure you want to log out?", "Yes", "No");
if (confirm) if (confirm)
{ {
// Redirect to Login Page // Redirect to Login Page
await Shell.Current.GoToAsync("//LoginPage"); await Shell.Current.GoToAsync("//LoginPage");
} }
} }
} }

@ -8,7 +8,7 @@
<!-- Role Picker --> <!-- Role Picker -->
<Entry x:Name="UsernameEntry" Placeholder="Username"/> <Entry x:Name="UsernameEntry" Placeholder="Username"/>
<Entry x:Name="PasswordEntry" Placeholder="Password"/> <Entry x:Name="PasswordEntry" Placeholder="Password" IsPassword="True"/>
<Label Text="Select Role:" FontSize="Medium" /> <Label Text="Select Role:" FontSize="Medium" />
@ -23,5 +23,6 @@
<!-- Login Button --> <!-- Login Button -->
<Button Text="Login" Clicked="OnLoginButtonClicked" /> <Button Text="Login" Clicked="OnLoginButtonClicked" />
<Button Text="Register" Margin="5" BackgroundColor="Green" Clicked="OnRegisterButtonClicked"/>
</StackLayout> </StackLayout>
</ContentPage> </ContentPage>

@ -8,13 +8,22 @@ namespace Justice.Views
{ {
InitializeComponent(); InitializeComponent();
} }
protected override void OnAppearing()
{
base.OnAppearing();
// Clear the fields when the page is loaded
UsernameEntry.Text = string.Empty;
PasswordEntry.Text = string.Empty;
RolePicker.SelectedItem = null; // Clear role selection if needed
}
private async void OnLoginButtonClicked(object sender, EventArgs e) private async void OnLoginButtonClicked(object sender, EventArgs e)
{ {
var endvalidUsername = "test"; var endvalidUsername = "enduser";
var endvalidPassword = "test123"; var endvalidPassword = "enduser123";
var authvalidUsername = "auth"; var authvalidUsername = "authuser";
var authvalidPassword = "auth123"; var authvalidPassword = "authuser123";
var enteredUsername = UsernameEntry?.Text?.Trim(); var enteredUsername = UsernameEntry?.Text?.Trim();
var enteredPassword = PasswordEntry?.Text?.Trim(); var enteredPassword = PasswordEntry?.Text?.Trim();
@ -47,5 +56,10 @@ namespace Justice.Views
await DisplayAlert("Error", "Invalid credentials. Please try again.", "OK"); await DisplayAlert("Error", "Invalid credentials. Please try again.", "OK");
} }
} }
private async void OnRegisterButtonClicked(object sender, EventArgs e)
{
await Shell.Current.GoToAsync("//RegistrationPage");
}
} }
} }

@ -4,21 +4,29 @@
Title="Register"> Title="Register">
<StackLayout Padding="20"> <StackLayout Padding="20">
<Label Text="Register" FontSize="Large" HorizontalOptions="Center" /> <Label Text="Register as End User" FontSize="Large" HorizontalOptions="Center" />
<Entry x:Name="UsernameEntry" Placeholder="Username" /> <!-- Username -->
<Entry x:Name="PasswordEntry" Placeholder="Password" IsPassword="True" /> <Label Text="Username:" FontSize="Medium" />
<Entry x:Name="UsernameEntry" Placeholder="Enter your username" />
<Picker x:Name="RolePicker" Title="Select Role"> <!-- Password -->
<Picker.ItemsSource> <Label Text="Password:" FontSize="Medium" />
<x:Array Type="{x:Type x:String}"> <Entry x:Name="PasswordEntry" Placeholder="Enter your password" IsPassword="True" />
<x:String>EndUser</x:String>
<x:String>AuthorityUser</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
<Entry x:Name="AuthorityTypeEntry" Placeholder="Authority Type (Optional)" IsVisible="False" /> <!-- Confirm Password -->
<Label Text="Confirm Password:" FontSize="Medium" />
<Entry x:Name="ConfirmPasswordEntry" Placeholder="Confirm your password" IsPassword="True" />
<!-- Identity Upload -->
<Label Text="Upload Identity Document:" FontSize="Medium" />
<Button Text="Choose File" Clicked="OnChooseFileClicked" />
<Label x:Name="IdentityFileLabel" Text="No file selected" FontSize="Small" TextColor="Gray" />
<!-- Register Button -->
<Button Text="Register" Clicked="OnRegisterClicked" /> <Button Text="Register" Clicked="OnRegisterClicked" />
<!-- Loader -->
<ActivityIndicator IsRunning="{Binding IsBusy}" IsVisible="{Binding IsBusy}" VerticalOptions="Center" />
</StackLayout> </StackLayout>
</ContentPage> </ContentPage>

@ -1,53 +1,141 @@
using Justice.Helpers; using Justice.Helpers;
using Justice.Models; using Justice.Models;
using Org.BouncyCastle.Crypto.Generators; using Microsoft.Maui.Storage;
using System; using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace Justice.Views namespace Justice.Views
{ {
public partial class RegistrationPage : ContentPage public partial class RegistrationPage : ContentPage, INotifyPropertyChanged
{ {
private readonly DatabaseHelper _dbHelper; private readonly DatabaseHelper _dbHelper;
private string _identityFilePath;
private bool _isBusy;
public bool IsBusy
{
get => _isBusy;
set
{
_isBusy = value;
OnPropertyChanged();
}
}
public RegistrationPage() public RegistrationPage()
{ {
InitializeComponent(); InitializeComponent();
_dbHelper = new DatabaseHelper(); _dbHelper = new DatabaseHelper();
RolePicker.SelectedIndexChanged += (s, e) => BindingContext = this;
{
AuthorityTypeEntry.IsVisible = RolePicker.SelectedItem?.ToString() == "AuthorityUser";
};
} }
private async void OnRegisterClicked(object sender, EventArgs e) private async void OnChooseFileClicked(object sender, EventArgs e)
{ {
if (string.IsNullOrWhiteSpace(UsernameEntry.Text) || string.IsNullOrWhiteSpace(PasswordEntry.Text) || RolePicker.SelectedItem == null) try
{ {
await DisplayAlert("Error", "All fields are required.", "OK"); var customFileType = new FilePickerFileType(new Dictionary<DevicePlatform, IEnumerable<string>>
return; {
} { DevicePlatform.Android, new[] { "*/*" } }, // Allow all files on Android
{ DevicePlatform.iOS, new[] { "public.data" } },
{ DevicePlatform.WinUI, new[] { "*" } }
});
var options = new PickOptions
{
PickerTitle = "Select Identity Document",
FileTypes = customFileType
};
var hashedPassword = BCrypt.Net.BCrypt.HashPassword(PasswordEntry.Text.Trim()); var result = await FilePicker.PickAsync(options);
var user = new User
if (result != null)
{
_identityFilePath = result.FullPath;
IdentityFileLabel.Text = $"Selected File: {result.FileName}";
}
else
{
IdentityFileLabel.Text = "No file selected";
}
}
catch (Exception ex)
{ {
Username = UsernameEntry.Text.Trim(), await DisplayAlert("Error", $"Failed to select file: {ex.Message}", "OK");
Password = hashedPassword, }
Role = RolePicker.SelectedItem.ToString(), }
AuthorityType = AuthorityTypeEntry.IsVisible ? AuthorityTypeEntry.Text.Trim() : null
}; private async void OnRegisterClicked(object sender, EventArgs e)
{
if (IsBusy) return;
IsBusy = true;
try try
{ {
var username = UsernameEntry?.Text?.Trim();
var password = PasswordEntry?.Text?.Trim();
var confirmPassword = ConfirmPasswordEntry?.Text?.Trim();
// Validate inputs
if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password) || string.IsNullOrWhiteSpace(confirmPassword))
{
await DisplayAlert("Error", "All fields are required.", "OK");
return;
}
if (string.IsNullOrWhiteSpace(_identityFilePath))
{
await DisplayAlert("Error", "Please upload an identity document.", "OK");
return;
}
if (password != confirmPassword)
{
await DisplayAlert("Error", "Passwords do not match.", "OK");
return;
}
// Hash the password asynchronously
var hashedPassword = await Task.Run(() => BCrypt.Net.BCrypt.HashPassword(password));
var user = new User
{
Username = username,
Password = hashedPassword,
Role = "End User", // Fixed role for End User
IdentityFilePath = _identityFilePath // Save file path
};
// Save to database
await _dbHelper.InitializeAsync<User>(); await _dbHelper.InitializeAsync<User>();
var existingUser = await _dbHelper.FindAsync<User>("SELECT * FROM User WHERE Username = ?", username);
if (existingUser != null)
{
await DisplayAlert("Error", "Username already exists.", "OK");
return;
}
await _dbHelper.InsertAsync(user); await _dbHelper.InsertAsync(user);
await DisplayAlert("Success", "Registration successful!", "OK");
await DisplayAlert("Success", "User registered successfully.", "OK"); // Redirect to Login Page
await Navigation.PopAsync(); await Shell.Current.GoToAsync("//LoginPage");
} }
catch (Exception ex) catch (Exception ex)
{ {
await DisplayAlert("Error", $"Failed to register: {ex.Message}", "OK"); await DisplayAlert("Error", $"Failed to register: {ex.Message}", "OK");
} }
finally
{
IsBusy = false;
}
}
// INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
} }
} }
} }

Loading…
Cancel
Save