Added role based access to android login
- Admin has access to everything - Staff has limited access to what they can edit in listfragment - Customers cannot login to app - added validations to pets, supplier and services in their detailed view
This commit is contained in:
@@ -39,12 +39,18 @@ public class MainActivity extends AppCompatActivity {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Check if user is already logged in
|
||||
if (TokenManager.getInstance(this).isLoggedIn()) {
|
||||
TokenManager tokenManager = TokenManager.getInstance(this);
|
||||
if (tokenManager.isLoggedIn()) {
|
||||
if ("CUSTOMER".equalsIgnoreCase(tokenManager.getRole())) {
|
||||
// If a customer somehow remained logged in, clear them out
|
||||
tokenManager.clearLoginData();
|
||||
} else {
|
||||
Intent intent = new Intent(this, HomeActivity.class);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.activity_main);
|
||||
@@ -83,11 +89,20 @@ public class MainActivity extends AppCompatActivity {
|
||||
@Override
|
||||
public void onResponse(Call<AuthDTO.LoginResponse> call, Response<AuthDTO.LoginResponse> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
String role = response.body().getRole();
|
||||
|
||||
// Check if the user is a CUSTOMER and deny login if so
|
||||
if ("CUSTOMER".equalsIgnoreCase(role)) {
|
||||
Toast.makeText(MainActivity.this, "Access denied: Customers are not allowed to log in.", Toast.LENGTH_LONG).show();
|
||||
tvLoginStatus.setText("Customers are not allowed to log in");
|
||||
return;
|
||||
}
|
||||
|
||||
//save login data in shared preferences
|
||||
TokenManager.getInstance(MainActivity.this).saveLoginData(
|
||||
response.body().getToken(),
|
||||
response.body().getUsername(),
|
||||
response.body().getRole()
|
||||
role
|
||||
);
|
||||
|
||||
//fetch user id from api then login to home activity
|
||||
|
||||
@@ -14,6 +14,7 @@ import android.widget.LinearLayout;
|
||||
|
||||
import com.example.petstoremobile.R;
|
||||
|
||||
import com.example.petstoremobile.api.auth.TokenManager;
|
||||
import com.example.petstoremobile.fragments.listfragments.PetFragment;
|
||||
import com.example.petstoremobile.fragments.listfragments.ServiceFragment;
|
||||
import com.example.petstoremobile.fragments.listfragments.SupplierFragment;
|
||||
@@ -49,6 +50,13 @@ public class ListFragment extends Fragment {
|
||||
drawerInventory = view.findViewById(R.id.drawerInventory);
|
||||
drawerProducts = view.findViewById(R.id.drawerProducts);
|
||||
|
||||
// Check user role and restrict access for STAFF
|
||||
String role = TokenManager.getInstance(requireContext()).getRole();
|
||||
if ("STAFF".equalsIgnoreCase(role)) {
|
||||
drawerSuppliers.setVisibility(View.GONE);
|
||||
drawerInventory.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
//needed to disable touches on the innerContainer while the drawer is open
|
||||
touchBlocker = view.findViewById(R.id.touchBlocker);
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ import com.example.petstoremobile.api.RetrofitClient;
|
||||
import com.example.petstoremobile.dtos.PetDTO;
|
||||
import com.example.petstoremobile.fragments.ListFragment;
|
||||
import com.example.petstoremobile.fragments.listfragments.PetFragment;
|
||||
import com.example.petstoremobile.utils.ActivityLogger;
|
||||
import com.example.petstoremobile.utils.InputValidator;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
@@ -65,26 +67,27 @@ public class PetDetailFragment extends Fragment {
|
||||
|
||||
//Method to Update or Add a pet
|
||||
private void savePet() {
|
||||
// Validates all fields using InputValidator
|
||||
if (!InputValidator.isNotEmpty(etPetName, "Pet Name")) return;
|
||||
if (!InputValidator.isNotEmpty(etPetSpecies, "Species")) return;
|
||||
if (!InputValidator.isNotEmpty(etPetBreed, "Breed")) return;
|
||||
if (!InputValidator.isPositiveInteger(etPetAge, "Age")) return;
|
||||
if (!InputValidator.isPositiveDecimal(etPetPrice, "Price")) return;
|
||||
|
||||
//get all the values from the fields
|
||||
String name = etPetName.getText().toString().trim();
|
||||
String species = etPetSpecies.getText().toString().trim();
|
||||
String breed = etPetBreed.getText().toString().trim();
|
||||
String ageStr = etPetAge.getText().toString().trim();
|
||||
int age = Integer.parseInt(etPetAge.getText().toString().trim());
|
||||
String priceStr = etPetPrice.getText().toString().trim();
|
||||
String status = spinnerPetStatus.getSelectedItem().toString();
|
||||
|
||||
//check if all the fields are filled
|
||||
if (name.isEmpty() || species.isEmpty() || breed.isEmpty() || ageStr.isEmpty() || priceStr.isEmpty()) {
|
||||
Toast.makeText(getContext(), "Please fill in all fields", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
//create a pet object to send to the API
|
||||
PetDTO petDTO = new PetDTO();
|
||||
petDTO.setPetName(name);
|
||||
petDTO.setPetSpecies(species);
|
||||
petDTO.setPetBreed(breed);
|
||||
petDTO.setPetAge(Integer.parseInt(ageStr));
|
||||
petDTO.setPetAge(age);
|
||||
petDTO.setPetPrice(priceStr);
|
||||
petDTO.setPetStatus(status);
|
||||
|
||||
@@ -98,6 +101,7 @@ public class PetDetailFragment extends Fragment {
|
||||
@Override
|
||||
public void onResponse(Call<PetDTO> call, Response<PetDTO> response) {
|
||||
if (response.isSuccessful()) {
|
||||
ActivityLogger.logChange(requireContext(), "Pet", "UPDATED", petId);
|
||||
Toast.makeText(getContext(), "Pet updated successfully!", Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
} else {
|
||||
@@ -107,6 +111,7 @@ public class PetDetailFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<PetDTO> call, Throwable t) {
|
||||
ActivityLogger.logException(requireContext(), "PetDetailFragment.updatePet", new Exception(t));
|
||||
Log.e("PetDetailFragment", "Error updating pet", t);
|
||||
Toast.makeText(getContext(), "Error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
@@ -117,6 +122,7 @@ public class PetDetailFragment extends Fragment {
|
||||
@Override
|
||||
public void onResponse(Call<PetDTO> call, Response<PetDTO> response) {
|
||||
if (response.isSuccessful()) {
|
||||
ActivityLogger.log(requireContext(), "Added new Pet: " + name);
|
||||
Toast.makeText(getContext(), "Pet added successfully!", Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
} else {
|
||||
@@ -126,6 +132,7 @@ public class PetDetailFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<PetDTO> call, Throwable t) {
|
||||
ActivityLogger.logException(requireContext(), "PetDetailFragment.createPet", new Exception(t));
|
||||
Log.e("PetDetailFragment", "Error adding pet", t);
|
||||
Toast.makeText(getContext(), "Error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
@@ -146,6 +153,7 @@ public class PetDetailFragment extends Fragment {
|
||||
@Override
|
||||
public void onResponse(Call<Void> call, Response<Void> response) {
|
||||
if (response.isSuccessful()) {
|
||||
ActivityLogger.logChange(requireContext(), "Pet", "DELETED", petId);
|
||||
Toast.makeText(getContext(), "Pet deleted successfully!", Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
} else {
|
||||
@@ -155,6 +163,7 @@ public class PetDetailFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<Void> call, Throwable t) {
|
||||
ActivityLogger.logException(requireContext(), "PetDetailFragment.deletePet", new Exception(t));
|
||||
Log.e("PetDetailFragment", "Error deleting pet", t);
|
||||
Toast.makeText(getContext(), "Error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import com.example.petstoremobile.api.ServiceApi;
|
||||
import com.example.petstoremobile.dtos.ServiceDTO;
|
||||
import com.example.petstoremobile.fragments.ListFragment;
|
||||
import com.example.petstoremobile.fragments.listfragments.ServiceFragment;
|
||||
import com.example.petstoremobile.utils.ActivityLogger;
|
||||
import com.example.petstoremobile.utils.InputValidator;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
@@ -58,24 +60,24 @@ public class ServiceDetailFragment extends Fragment {
|
||||
|
||||
//Method to Update or Add a service
|
||||
private void saveService() {
|
||||
// Validates all fields using InputValidator
|
||||
if (!InputValidator.isNotEmpty(etServiceName, "Service Name")) return;
|
||||
if (!InputValidator.isNotEmpty(etServiceDesc, "Description")) return;
|
||||
if (!InputValidator.isPositiveInteger(etServiceDuration, "Duration")) return;
|
||||
if (!InputValidator.isPositiveDecimal(etServicePrice, "Price")) return;
|
||||
|
||||
//get all the values from the fields
|
||||
String name = etServiceName.getText().toString().trim();
|
||||
String desc = etServiceDesc.getText().toString().trim();
|
||||
String durationStr = etServiceDuration.getText().toString().trim();
|
||||
String priceStr = etServicePrice.getText().toString().trim();
|
||||
|
||||
//check if all the fields are filled (desc is optional)
|
||||
if (name.isEmpty() || durationStr.isEmpty() || priceStr.isEmpty()) {
|
||||
Toast.makeText(getContext(), "Please fill in all fields", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
int duration = Integer.parseInt(etServiceDuration.getText().toString().trim());
|
||||
double price = Double.parseDouble(etServicePrice.getText().toString().trim());
|
||||
|
||||
//create a service object to send to the API
|
||||
ServiceDTO serviceDTO = new ServiceDTO();
|
||||
serviceDTO.setServiceName(name);
|
||||
serviceDTO.setServiceDesc(desc);
|
||||
serviceDTO.setServiceDuration(Integer.parseInt(durationStr));
|
||||
serviceDTO.setServicePrice(Double.parseDouble(priceStr));
|
||||
serviceDTO.setServiceDuration(duration);
|
||||
serviceDTO.setServicePrice(price);
|
||||
|
||||
ServiceApi serviceApi = RetrofitClient.getServiceApi(requireContext());
|
||||
|
||||
@@ -87,6 +89,7 @@ public class ServiceDetailFragment extends Fragment {
|
||||
@Override
|
||||
public void onResponse(Call<ServiceDTO> call, Response<ServiceDTO> response) {
|
||||
if (response.isSuccessful()) {
|
||||
ActivityLogger.logChange(requireContext(), "Service", "UPDATED", serviceId);
|
||||
Toast.makeText(getContext(), "Service updated successfully!", Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
} else {
|
||||
@@ -96,6 +99,7 @@ public class ServiceDetailFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<ServiceDTO> call, Throwable t) {
|
||||
ActivityLogger.logException(requireContext(), "ServiceDetailFragment.updateService", new Exception(t));
|
||||
Log.e("ServiceDetailFragment", "Error updating service", t);
|
||||
Toast.makeText(getContext(), "Error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
@@ -106,6 +110,7 @@ public class ServiceDetailFragment extends Fragment {
|
||||
@Override
|
||||
public void onResponse(Call<ServiceDTO> call, Response<ServiceDTO> response) {
|
||||
if (response.isSuccessful()) {
|
||||
ActivityLogger.log(requireContext(), "Added new Service: " + name);
|
||||
Toast.makeText(getContext(), "Service added successfully!", Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
} else {
|
||||
@@ -115,6 +120,7 @@ public class ServiceDetailFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<ServiceDTO> call, Throwable t) {
|
||||
ActivityLogger.logException(requireContext(), "ServiceDetailFragment.createService", new Exception(t));
|
||||
Log.e("ServiceDetailFragment", "Error adding service", t);
|
||||
Toast.makeText(getContext(), "Error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
@@ -134,6 +140,7 @@ public class ServiceDetailFragment extends Fragment {
|
||||
@Override
|
||||
public void onResponse(Call<Void> call, Response<Void> response) {
|
||||
if (response.isSuccessful()) {
|
||||
ActivityLogger.logChange(requireContext(), "Service", "DELETED", serviceId);
|
||||
Toast.makeText(getContext(), "Service deleted successfully!", Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
} else {
|
||||
@@ -143,6 +150,7 @@ public class ServiceDetailFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<Void> call, Throwable t) {
|
||||
ActivityLogger.logException(requireContext(), "ServiceDetailFragment.deleteService", new Exception(t));
|
||||
Log.e("ServiceDetailFragment", "Error deleting service", t);
|
||||
Toast.makeText(getContext(), "Error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import com.example.petstoremobile.api.SupplierApi;
|
||||
import com.example.petstoremobile.dtos.SupplierDTO;
|
||||
import com.example.petstoremobile.fragments.ListFragment;
|
||||
import com.example.petstoremobile.fragments.listfragments.SupplierFragment;
|
||||
import com.example.petstoremobile.utils.ActivityLogger;
|
||||
import com.example.petstoremobile.utils.InputValidator;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
@@ -58,6 +60,13 @@ public class SupplierDetailFragment extends Fragment {
|
||||
|
||||
//Method to Update or Add a supplier
|
||||
private void saveSupplier() {
|
||||
// Validates all fields using InputValidator
|
||||
if (!InputValidator.isNotEmpty(etSupCompany, "Company Name")) return;
|
||||
if (!InputValidator.isNotEmpty(etSupContactFirstName, "First Name")) return;
|
||||
if (!InputValidator.isNotEmpty(etSupContactLastName, "Last Name")) return;
|
||||
if (!InputValidator.isValidEmail(etSupEmail)) return;
|
||||
if (!InputValidator.isValidPhone(etSupPhone)) return;
|
||||
|
||||
//get all the values from the fields
|
||||
String company = etSupCompany.getText().toString().trim();
|
||||
String firstName = etSupContactFirstName.getText().toString().trim();
|
||||
@@ -65,12 +74,6 @@ public class SupplierDetailFragment extends Fragment {
|
||||
String email = etSupEmail.getText().toString().trim();
|
||||
String phone = etSupPhone.getText().toString().trim();
|
||||
|
||||
//check if all the fields are filled
|
||||
if (company.isEmpty() || firstName.isEmpty() || lastName.isEmpty() || email.isEmpty() || phone.isEmpty()) {
|
||||
Toast.makeText(getContext(), "Please fill in all fields", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
//create a supplier object to send to the API
|
||||
SupplierDTO supplierDTO = new SupplierDTO();
|
||||
supplierDTO.setSupCompany(company);
|
||||
@@ -89,6 +92,7 @@ public class SupplierDetailFragment extends Fragment {
|
||||
@Override
|
||||
public void onResponse(Call<SupplierDTO> call, Response<SupplierDTO> response) {
|
||||
if (response.isSuccessful()) {
|
||||
ActivityLogger.logChange(requireContext(), "Supplier", "UPDATED", supId);
|
||||
Toast.makeText(getContext(), "Supplier updated successfully!", Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
} else {
|
||||
@@ -98,6 +102,7 @@ public class SupplierDetailFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<SupplierDTO> call, Throwable t) {
|
||||
ActivityLogger.logException(requireContext(), "SupplierDetailFragment.updateSupplier", new Exception(t));
|
||||
Log.e("SupplierDetailFragment", "Error updating supplier", t);
|
||||
Toast.makeText(getContext(), "Error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
@@ -108,6 +113,7 @@ public class SupplierDetailFragment extends Fragment {
|
||||
@Override
|
||||
public void onResponse(Call<SupplierDTO> call, Response<SupplierDTO> response) {
|
||||
if (response.isSuccessful()) {
|
||||
ActivityLogger.log(requireContext(), "Added new Supplier: " + company);
|
||||
Toast.makeText(getContext(), "Supplier added successfully!", Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
} else {
|
||||
@@ -117,6 +123,7 @@ public class SupplierDetailFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<SupplierDTO> call, Throwable t) {
|
||||
ActivityLogger.logException(requireContext(), "SupplierDetailFragment.createSupplier", new Exception(t));
|
||||
Log.e("SupplierDetailFragment", "Error adding supplier", t);
|
||||
Toast.makeText(getContext(), "Error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
@@ -136,6 +143,7 @@ public class SupplierDetailFragment extends Fragment {
|
||||
@Override
|
||||
public void onResponse(Call<Void> call, Response<Void> response) {
|
||||
if (response.isSuccessful()) {
|
||||
ActivityLogger.logChange(requireContext(), "Supplier", "DELETED", supId);
|
||||
Toast.makeText(getContext(), "Supplier deleted successfully!", Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
} else {
|
||||
@@ -145,6 +153,7 @@ public class SupplierDetailFragment extends Fragment {
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<Void> call, Throwable t) {
|
||||
ActivityLogger.logException(requireContext(), "SupplierDetailFragment.deleteSupplier", new Exception(t));
|
||||
Log.e("SupplierDetailFragment", "Error deleting supplier", t);
|
||||
Toast.makeText(getContext(), "Error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
@@ -197,6 +206,11 @@ public class SupplierDetailFragment extends Fragment {
|
||||
etSupContactLastName = view.findViewById(R.id.etSupContactLastName);
|
||||
etSupEmail = view.findViewById(R.id.etSupEmail);
|
||||
etSupPhone = view.findViewById(R.id.etSupPhone);
|
||||
|
||||
// Add phone number formatting (CA) and limit length to 14 characters
|
||||
etSupPhone.addTextChangedListener(new android.telephony.PhoneNumberFormattingTextWatcher("CA"));
|
||||
etSupPhone.setFilters(new android.text.InputFilter[]{new android.text.InputFilter.LengthFilter(14)});
|
||||
|
||||
btnSaveSupplier = view.findViewById(R.id.btnSaveSupplier);
|
||||
btnDeleteSupplier = view.findViewById(R.id.btnDeleteSupplier);
|
||||
btnBack = view.findViewById(R.id.btnBack);
|
||||
|
||||
Reference in New Issue
Block a user