NEW: Privacy Policy and TOS Popup
This commit is contained in:
@@ -37,6 +37,8 @@ PODS:
|
||||
- file_picker (0.0.1):
|
||||
- DKImagePickerController/PhotoGallery
|
||||
- Flutter
|
||||
- file_saver (0.0.1):
|
||||
- Flutter
|
||||
- fl_downloader (0.0.1):
|
||||
- Flutter
|
||||
- Flutter (1.0.0)
|
||||
@@ -93,6 +95,7 @@ DEPENDENCIES:
|
||||
- app_settings (from `.symlinks/plugins/app_settings/ios`)
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
- file_saver (from `.symlinks/plugins/file_saver/ios`)
|
||||
- fl_downloader (from `.symlinks/plugins/fl_downloader/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||
@@ -128,6 +131,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||
file_picker:
|
||||
:path: ".symlinks/plugins/file_picker/ios"
|
||||
file_saver:
|
||||
:path: ".symlinks/plugins/file_saver/ios"
|
||||
fl_downloader:
|
||||
:path: ".symlinks/plugins/fl_downloader/ios"
|
||||
Flutter:
|
||||
@@ -171,6 +176,7 @@ SPEC CHECKSUMS:
|
||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
|
||||
fl_downloader: dc99aa8dd303f862cccb830087f37acc9b0156ee
|
||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||
|
||||
29
Frontend/lib/mih_components/mih_objects/user_consent.dart
Normal file
29
Frontend/lib/mih_components/mih_objects/user_consent.dart
Normal file
@@ -0,0 +1,29 @@
|
||||
class UserConsent {
|
||||
String app_id;
|
||||
DateTime privacy_policy_accepted;
|
||||
DateTime terms_of_services_accepted;
|
||||
|
||||
UserConsent({
|
||||
required this.app_id,
|
||||
required this.privacy_policy_accepted,
|
||||
required this.terms_of_services_accepted,
|
||||
});
|
||||
|
||||
factory UserConsent.fromJson(Map<String, dynamic> json) {
|
||||
return UserConsent(
|
||||
app_id: json['app_id'],
|
||||
privacy_policy_accepted: DateTime.parse(json['privacy_policy_accepted']),
|
||||
terms_of_services_accepted:
|
||||
DateTime.parse(json['terms_of_services_accepted']),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'app_id': app_id,
|
||||
'privacy_policy_accepted': privacy_policy_accepted.toIso8601String(),
|
||||
'terms_of_services_accepted':
|
||||
terms_of_services_accepted.toIso8601String(),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
@@ -99,7 +100,7 @@ class _MihPackageAlertState extends State<MihPackageAlert> {
|
||||
height: 50,
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
context.pop();
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.close,
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:ken_logger/ken_logger.dart';
|
||||
import 'package:mzansi_innovation_hub/main.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_objects/arguments.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_objects/user_consent.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_action.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_alert.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_tools.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_circle_avatar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_objects/app_user.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_package_window.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_scack_bar.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_pop_up_messages/mih_loading_circle.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
@@ -14,32 +21,13 @@ import 'package:mzansi_innovation_hub/mih_packages/mih_home/package_tools/mih_bu
|
||||
import 'package:mzansi_innovation_hub/mih_packages/mih_home/package_tools/mih_personal_home.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_service_calls.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_services/mih_user_consent_services.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class MihHome extends StatefulWidget {
|
||||
// final AppUser signedInUser;
|
||||
// final BusinessUser? businessUser;
|
||||
// final Business? business;
|
||||
// final Patient? patient;
|
||||
// final List<MIHNotification> notifications;
|
||||
// final ImageProvider<Object>? propicFile;
|
||||
// final bool isUserNew;
|
||||
// final bool isBusinessUser;
|
||||
// final bool isBusinessUserNew;
|
||||
// final bool isDevActive;
|
||||
final bool personalSelected;
|
||||
const MihHome({
|
||||
super.key,
|
||||
// required this.signedInUser,
|
||||
// required this.businessUser,
|
||||
// required this.business,
|
||||
// required this.patient,
|
||||
// required this.notifications,
|
||||
// required this.propicFile,
|
||||
// required this.isUserNew,
|
||||
// required this.isBusinessUser,
|
||||
// required this.isBusinessUserNew,
|
||||
// required this.isDevActive,
|
||||
required this.personalSelected,
|
||||
});
|
||||
|
||||
@@ -52,6 +40,79 @@ class _MihHomeState extends State<MihHome> {
|
||||
late int _selcetedIndex;
|
||||
late bool _personalSelected;
|
||||
late Future<HomeArguments> profileData;
|
||||
late Future<UserConsent?> futureUserConsent;
|
||||
bool showUserConsent = false;
|
||||
DateTime latestPrivacyPolicyDate = DateTime.parse("2024-12-01");
|
||||
DateTime latestTermOfServiceDate = DateTime.parse("2024-12-01");
|
||||
|
||||
bool showPolicyWindow(UserConsent? userConsent) {
|
||||
if (userConsent == null) {
|
||||
return true;
|
||||
} else {
|
||||
if (userConsent.privacy_policy_accepted
|
||||
.isAfter(latestPrivacyPolicyDate) &&
|
||||
userConsent.terms_of_services_accepted
|
||||
.isAfter(latestTermOfServiceDate)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void createOrUpdateAccpetance(UserConsent? userConsent, String app_id) {
|
||||
userConsent != null
|
||||
? MihUserConsentServices()
|
||||
.updateUserConsentStatus(
|
||||
app_id,
|
||||
DateTime.now().toIso8601String(),
|
||||
DateTime.now().toIso8601String(),
|
||||
)
|
||||
.then((value) {
|
||||
if (value == 200) {
|
||||
// setState(() {
|
||||
// showUserConsent = false;
|
||||
// });
|
||||
context.goNamed("mihHome", extra: false);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
MihSnackBar(
|
||||
child: Text("Thank you for accepting our Policies"),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
MihSnackBar(
|
||||
child: Text("There was an error, please try again later"),
|
||||
),
|
||||
);
|
||||
}
|
||||
})
|
||||
: MihUserConsentServices()
|
||||
.insertUserConsentStatus(
|
||||
app_id,
|
||||
DateTime.now().toIso8601String(),
|
||||
DateTime.now().toIso8601String(),
|
||||
)
|
||||
.then((value) {
|
||||
if (value == 201) {
|
||||
// setState(() {
|
||||
// showUserConsent = false;
|
||||
// });
|
||||
context.goNamed("mihHome", extra: false);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
MihSnackBar(
|
||||
child: Text("Thank you for accepting our Policies"),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
MihSnackBar(
|
||||
child: Text("There was an error, please try again later"),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
@@ -62,6 +123,7 @@ class _MihHomeState extends State<MihHome> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
profileData = MIHApiCalls().getProfile(10, context);
|
||||
futureUserConsent = MihUserConsentServices().getUserConsentStatus();
|
||||
if (widget.personalSelected == true) {
|
||||
setState(() {
|
||||
_selcetedIndex = 0;
|
||||
@@ -96,30 +158,259 @@ class _MihHomeState extends State<MihHome> {
|
||||
);
|
||||
} else if (asyncSnapshot.connectionState == ConnectionState.done &&
|
||||
asyncSnapshot.hasData) {
|
||||
return MihPackage(
|
||||
appActionButton: getAction(asyncSnapshot.data!.profilePicUrl),
|
||||
appTools:
|
||||
getTools(asyncSnapshot.data!.signedInUser.type != "personal"),
|
||||
appBody: getToolBody(asyncSnapshot.data!),
|
||||
appToolTitles: getToolTitle(),
|
||||
actionDrawer: getActionDrawer(
|
||||
asyncSnapshot.data!.signedInUser,
|
||||
asyncSnapshot.data!.profilePicUrl,
|
||||
),
|
||||
selectedbodyIndex: _selcetedIndex,
|
||||
onIndexChange: (newValue) {
|
||||
if (_selcetedIndex == 0) {
|
||||
setState(() {
|
||||
_selcetedIndex = newValue;
|
||||
_personalSelected = true;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_selcetedIndex = newValue;
|
||||
_personalSelected = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
return Stack(
|
||||
children: [
|
||||
MihPackage(
|
||||
appActionButton: getAction(asyncSnapshot.data!.profilePicUrl),
|
||||
appTools: getTools(
|
||||
asyncSnapshot.data!.signedInUser.type != "personal"),
|
||||
appBody: getToolBody(asyncSnapshot.data!),
|
||||
appToolTitles: getToolTitle(),
|
||||
actionDrawer: getActionDrawer(
|
||||
asyncSnapshot.data!.signedInUser,
|
||||
asyncSnapshot.data!.profilePicUrl,
|
||||
),
|
||||
selectedbodyIndex: _selcetedIndex,
|
||||
onIndexChange: (newValue) {
|
||||
if (_selcetedIndex == 0) {
|
||||
setState(() {
|
||||
_selcetedIndex = newValue;
|
||||
_personalSelected = true;
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
_selcetedIndex = newValue;
|
||||
_personalSelected = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
FutureBuilder(
|
||||
future: futureUserConsent,
|
||||
builder: (context, asyncSnapshotUserConsent) {
|
||||
if (asyncSnapshotUserConsent.connectionState ==
|
||||
ConnectionState.waiting) {
|
||||
showUserConsent = false;
|
||||
} else if (asyncSnapshotUserConsent.connectionState ==
|
||||
ConnectionState.done &&
|
||||
asyncSnapshotUserConsent.hasData) {
|
||||
showUserConsent =
|
||||
showPolicyWindow(asyncSnapshotUserConsent.data);
|
||||
} else if (asyncSnapshotUserConsent.connectionState ==
|
||||
ConnectionState.done &&
|
||||
!asyncSnapshotUserConsent.hasData) {
|
||||
showUserConsent = true;
|
||||
} else {
|
||||
showUserConsent = false;
|
||||
}
|
||||
return Visibility(
|
||||
visible: showUserConsent,
|
||||
child: Container(
|
||||
color: Colors.black.withValues(alpha: 0.5),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
MihPackageWindow(
|
||||
fullscreen: false,
|
||||
windowTitle:
|
||||
"Privacy Policy & Terms Of Service Alert!",
|
||||
onWindowTapClose: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return MihPackageAlert(
|
||||
alertIcon: Icon(
|
||||
Icons.warning_amber_rounded,
|
||||
size: 100,
|
||||
color: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark",
|
||||
),
|
||||
),
|
||||
alertTitle:
|
||||
"Oops, Looks like you missed a step!",
|
||||
alertBody: Text(
|
||||
"We're excited for you to keep using the MIH app! Before you do, please take a moment to accept our Privacy Policy and Terms of Service. Thanks for helping us keep your experience great!",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark",
|
||||
),
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
alertColour: MihColors.getRedColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark",
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
windowBody: Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.policy,
|
||||
size: 150,
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark",
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Welcome to the MIH App",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark",
|
||||
),
|
||||
fontSize: 30,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"To keep using the MIH app, please take a moment to review and accept our Privacy Policy and Terms of Service. our agreement helps us keep things running smoothly and securely.",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: MihColors.getSecondaryColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark",
|
||||
),
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.normal,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Center(
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.goNamed(
|
||||
"aboutMih",
|
||||
extra: AboutArguments(
|
||||
widget.personalSelected,
|
||||
1,
|
||||
),
|
||||
);
|
||||
},
|
||||
buttonColor: MihColors.getOrangeColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Privacy Policy",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(
|
||||
context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
context.goNamed(
|
||||
"aboutMih",
|
||||
extra: AboutArguments(
|
||||
widget.personalSelected,
|
||||
2,
|
||||
),
|
||||
);
|
||||
},
|
||||
buttonColor: MihColors.getYellowColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Terms of Service",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(
|
||||
context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
MihButton(
|
||||
onPressed: () {
|
||||
DateTime now = DateTime.now();
|
||||
KenLogger.success(
|
||||
"Date Time Now: $now");
|
||||
createOrUpdateAccpetance(
|
||||
asyncSnapshotUserConsent.data,
|
||||
asyncSnapshot
|
||||
.data!.signedInUser.app_id,
|
||||
);
|
||||
},
|
||||
buttonColor: MihColors.getGreenColor(
|
||||
MzansiInnovationHub.of(context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
elevation: 10,
|
||||
width: 300,
|
||||
child: Text(
|
||||
"Accept",
|
||||
style: TextStyle(
|
||||
color: MihColors.getPrimaryColor(
|
||||
MzansiInnovationHub.of(
|
||||
context)!
|
||||
.theme
|
||||
.mode ==
|
||||
"Dark"),
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
return MihHomeError(
|
||||
|
||||
57
Frontend/lib/mih_services/mih_user_consent_services.dart
Normal file
57
Frontend/lib/mih_services/mih_user_consent_services.dart
Normal file
@@ -0,0 +1,57 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:mzansi_innovation_hub/mih_components/mih_objects/user_consent.dart';
|
||||
import 'package:mzansi_innovation_hub/mih_config/mih_env.dart';
|
||||
import 'package:supertokens_flutter/http.dart' as http;
|
||||
import 'package:supertokens_flutter/supertokens.dart';
|
||||
|
||||
class MihUserConsentServices {
|
||||
Future<UserConsent?> getUserConsentStatus() async {
|
||||
var app_id = await SuperTokens.getUserId();
|
||||
final response = await http.get(
|
||||
Uri.parse("${AppEnviroment.baseApiUrl}/user-consent/user/$app_id"));
|
||||
if (response.statusCode == 200) {
|
||||
Map<String, dynamic> userMap = jsonDecode(response.body);
|
||||
UserConsent userConsent = UserConsent.fromJson(userMap);
|
||||
return userConsent;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> insertUserConsentStatus(
|
||||
String app_id,
|
||||
String latestPrivacyPolicyDate,
|
||||
String latestTermOfServiceDate,
|
||||
) async {
|
||||
UserConsent userConsent = UserConsent(
|
||||
app_id: app_id,
|
||||
privacy_policy_accepted: DateTime.parse(latestPrivacyPolicyDate),
|
||||
terms_of_services_accepted: DateTime.parse(latestTermOfServiceDate),
|
||||
);
|
||||
final response = await http.post(
|
||||
Uri.parse("${AppEnviroment.baseApiUrl}/user-consent/insert/"),
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: jsonEncode(userConsent.toJson()),
|
||||
);
|
||||
return response.statusCode;
|
||||
}
|
||||
|
||||
Future<int> updateUserConsentStatus(
|
||||
String app_id,
|
||||
String latestPrivacyPolicyDate,
|
||||
String latestTermOfServiceDate,
|
||||
) async {
|
||||
UserConsent userConsent = UserConsent(
|
||||
app_id: app_id,
|
||||
privacy_policy_accepted: DateTime.parse(latestPrivacyPolicyDate),
|
||||
terms_of_services_accepted: DateTime.parse(latestTermOfServiceDate),
|
||||
);
|
||||
final response = await http.put(
|
||||
Uri.parse("${AppEnviroment.baseApiUrl}/user-consent/update"),
|
||||
headers: {"Content-Type": "application/json"},
|
||||
body: jsonEncode(userConsent.toJson()),
|
||||
);
|
||||
return response.statusCode;
|
||||
}
|
||||
}
|
||||
BIN
backend/.DS_Store
vendored
BIN
backend/.DS_Store
vendored
Binary file not shown.
@@ -18,6 +18,7 @@ import routers.access_request as access_request
|
||||
import routers.patient_access as patient_access
|
||||
import routers.mzansi_wallet as mzansi_wallet
|
||||
import routers.mzansi_directory as mzansi_directory
|
||||
import routers.user_consent as user_consent
|
||||
import routers.icd10_codes as icd10_codes
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from fastapi.middleware import Middleware
|
||||
@@ -94,6 +95,7 @@ app.include_router(business.router)
|
||||
app.include_router(notifications.router)
|
||||
app.include_router(mzansi_wallet.router)
|
||||
app.include_router(mzansi_directory.router)
|
||||
app.include_router(user_consent.router)
|
||||
app.include_router(icd10_codes.router)
|
||||
app.include_router(appointments.router)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from sqlalchemy import DateTime, Column, Integer, String
|
||||
from sqlalchemy import DateTime, Column, Integer, String, text
|
||||
from sqlalchemy.orm import declarative_base
|
||||
Base = declarative_base()
|
||||
|
||||
@@ -81,4 +81,20 @@ class BookmarkedBusiness(Base):
|
||||
return (
|
||||
f"<BusinessRating(idbookmarked_businesses={self.idbookmarked_businesses}, app_id='{self.app_id}', "
|
||||
f"business_id='{self.business_id}', created_date='{self.created_date}')>"
|
||||
)
|
||||
|
||||
class UserConsent(Base):
|
||||
__tablename__ = 'user_consent'
|
||||
__table_args__ = {'schema': 'app_data'}
|
||||
iduser_consent = Column(Integer, primary_key=True)
|
||||
app_id = Column(String(128), nullable=False,server_default=text("''"))
|
||||
privacy_policy_accepted = Column(DateTime, nullable=True)
|
||||
terms_of_services_accepted = Column(DateTime, nullable=True)
|
||||
|
||||
def __repr__(self):
|
||||
return (
|
||||
f"<UserConsent(iduser_consent={self.iduser_consent}, "
|
||||
f"app_id='{self.app_id}', "
|
||||
f"privacy_policy_accepted='{self.privacy_policy_accepted}', "
|
||||
f"terms_of_services_accepted='{self.terms_of_services_accepted}')>"
|
||||
)
|
||||
138
backend/routers/user_consent.py
Normal file
138
backend/routers/user_consent.py
Normal file
@@ -0,0 +1,138 @@
|
||||
from fastapi import APIRouter, HTTPException, status
|
||||
from pydantic import BaseModel
|
||||
#from ..mih_database import dbConnection
|
||||
import mih_database
|
||||
import mih_database.mihDbConnections
|
||||
from mih_database.mihDbObjects import UserConsent
|
||||
from sqlalchemy import desc, or_
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy.sql import func
|
||||
from sqlalchemy.exc import IntegrityError, SQLAlchemyError
|
||||
#SuperToken Auth from front end
|
||||
from supertokens_python.recipe.session.framework.fastapi import verify_session
|
||||
from supertokens_python.recipe.session import SessionContainer
|
||||
from fastapi import Depends
|
||||
from datetime import datetime
|
||||
import uuid
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
class userConsentInsertRequest(BaseModel):
|
||||
app_id: str
|
||||
privacy_policy_accepted: datetime
|
||||
terms_of_services_accepted: datetime
|
||||
|
||||
class userConsentUpdateRequest(BaseModel):
|
||||
app_id: str
|
||||
privacy_policy_accepted: datetime
|
||||
terms_of_services_accepted: datetime
|
||||
|
||||
@router.get("/user-consent/user/{app_id}", tags=["User Consent"])
|
||||
async def get_user_consent(app_id: str, session: SessionContainer = Depends(verify_session())):
|
||||
dbEngine = mih_database.mihDbConnections.dbAllConnect()
|
||||
dbSession = Session(dbEngine)
|
||||
try:
|
||||
queryResults = dbSession.query(UserConsent).\
|
||||
filter(UserConsent.app_id == app_id).\
|
||||
first()
|
||||
if queryResults:
|
||||
return {
|
||||
"idUserConsent": queryResults.iduser_consent,
|
||||
"app_id": queryResults.app_id,
|
||||
"privacy_policy_accepted": queryResults.privacy_policy_accepted,
|
||||
"terms_of_services_accepted": queryResults.terms_of_services_accepted
|
||||
}
|
||||
else:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User Consent not found")
|
||||
except HTTPException as http_exc:
|
||||
# Re-raise HTTPException directly if it was raised within the try block
|
||||
raise http_exc
|
||||
except Exception as e:
|
||||
print(f"An error occurred during the ORM query: {e}")
|
||||
if dbSession.is_active:
|
||||
dbSession.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail="Failed to retrieve records due to an internal server error."
|
||||
)
|
||||
finally:
|
||||
dbSession.close()
|
||||
|
||||
@router.post("/user-consent/insert/",
|
||||
tags=["User Consent"],
|
||||
status_code=status.HTTP_201_CREATED)
|
||||
async def insert_user_consent(itemRequest: userConsentInsertRequest,
|
||||
session: SessionContainer = Depends(verify_session())):
|
||||
dbEngine = mih_database.mihDbConnections.dbAllConnect()
|
||||
dbSession = Session(dbEngine)
|
||||
try:
|
||||
newUserConsent = UserConsent(
|
||||
app_id = itemRequest.app_id,
|
||||
privacy_policy_accepted = itemRequest.privacy_policy_accepted,
|
||||
terms_of_services_accepted = itemRequest.terms_of_services_accepted,
|
||||
)
|
||||
dbSession.add(newUserConsent)
|
||||
dbSession.commit()
|
||||
dbSession.refresh(newUserConsent)
|
||||
return {"message": "Successfully Created file Record"}
|
||||
except IntegrityError as e:
|
||||
dbSession.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT, # 409 Conflict is often suitable for constraint errors
|
||||
detail=f"Data integrity error: The provided data violates a database constraint. Details: {e.orig}"
|
||||
) from e
|
||||
except SQLAlchemyError as e:
|
||||
dbSession.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"A database error occurred during insertion. Details: {e.orig}"
|
||||
) from e
|
||||
except Exception as e:
|
||||
dbSession.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"An unexpected error occurred: {e}"
|
||||
) from e
|
||||
finally:
|
||||
dbSession.close()
|
||||
|
||||
@router.put("/user-consent/update/", tags=["User Consent"])
|
||||
async def update_user_consent(itemRequest: userConsentUpdateRequest,
|
||||
session: SessionContainer = Depends(verify_session())):
|
||||
dbEngine = mih_database.mihDbConnections.dbAllConnect()
|
||||
dbSession = Session(dbEngine)
|
||||
# pp_accepted_dt = datetime.strptime(itemRequest.privacy_policy_accepted, "%Y-%m-%d %H:%M:%S")
|
||||
# tos_accepted_dt = datetime.strptime(itemRequest.terms_of_services_accepted, "%Y-%m-%d %H:%M:%S")
|
||||
try:
|
||||
existing_consent = dbSession.query(UserConsent).filter(UserConsent.app_id == itemRequest.app_id).first()
|
||||
if not existing_consent:
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User Consent not found")
|
||||
|
||||
existing_consent.privacy_policy_accepted = itemRequest.privacy_policy_accepted
|
||||
existing_consent.terms_of_services_accepted = itemRequest.terms_of_services_accepted
|
||||
|
||||
dbSession.commit()
|
||||
return {"message": "Successfully Updated User Consent Record"}
|
||||
except HTTPException as http_exc:
|
||||
# Re-raise HTTPException directly if it was raised within the try block
|
||||
raise http_exc
|
||||
except IntegrityError as e:
|
||||
dbSession.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_409_CONFLICT,
|
||||
detail=f"Data integrity error: The provided data violates a database constraint. Details: {e.orig}"
|
||||
) from e
|
||||
except SQLAlchemyError as e:
|
||||
dbSession.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"A database error occurred during update. Details: {e.orig}"
|
||||
) from e
|
||||
except Exception as e:
|
||||
dbSession.rollback()
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"An unexpected error occurred: {e}"
|
||||
) from e
|
||||
finally:
|
||||
dbSession.close()
|
||||
Reference in New Issue
Block a user