add modified function login anda logout
This commit is contained in:
parent
98b1df4f12
commit
e14b2ff46c
|
@ -41,9 +41,9 @@ exports.register = async (req, res) => {
|
|||
}
|
||||
};
|
||||
|
||||
// Penyimpanan sesi login (in-memory)
|
||||
const activeSessions = {};
|
||||
const sessionTimeouts = {};
|
||||
// Inisialisasi global variables di awal file
|
||||
const activeSessions = {}; // { userId: true }
|
||||
const sessionTimeouts = {}; // { userId: timeoutId }
|
||||
|
||||
// Login
|
||||
exports.login = async (req, res) => {
|
||||
|
@ -58,7 +58,10 @@ exports.login = async (req, res) => {
|
|||
|
||||
// 🔹 Cek apakah user sudah login di device lain
|
||||
if (activeSessions[user.id]) {
|
||||
return res.status(403).json({ message: "Akun ini sedang digunakan di perangkat lain." });
|
||||
return res.status(403).json({
|
||||
message: "Akun ini sedang digunakan di perangkat lain.",
|
||||
debug: `User ${user.id} masih dalam sesi aktif`
|
||||
});
|
||||
}
|
||||
|
||||
// 🔹 Verifikasi password
|
||||
|
@ -75,42 +78,144 @@ exports.login = async (req, res) => {
|
|||
);
|
||||
|
||||
// 🔹 Tandai user sedang login (aktif)
|
||||
activeSessions[user.id] = true;
|
||||
activeSessions[user.id] = {
|
||||
loginTime: new Date(),
|
||||
email: user.email
|
||||
};
|
||||
|
||||
// 🔹 Atur timer logout otomatis setelah 5 menit (300000 ms)
|
||||
// 🔹 Bersihkan timeout lama jika ada
|
||||
if (sessionTimeouts[user.id]) {
|
||||
clearTimeout(sessionTimeouts[user.id]); // Bersihkan timer lama jika ada
|
||||
clearTimeout(sessionTimeouts[user.id]);
|
||||
delete sessionTimeouts[user.id];
|
||||
}
|
||||
|
||||
// 🔹 Atur timer logout otomatis setelah 5 menit
|
||||
sessionTimeouts[user.id] = setTimeout(() => {
|
||||
console.log(`User ID ${user.id} (${user.email}) otomatis logout karena timeout`);
|
||||
delete activeSessions[user.id];
|
||||
delete sessionTimeouts[user.id];
|
||||
console.log(`User ID ${user.id} otomatis logout karena timeout`);
|
||||
}, 5 * 60 * 1000); // 5 menit
|
||||
|
||||
console.log("User ID dari backend:", user.id);
|
||||
console.log("Login berhasil - User ID:", user.id, "Email:", user.email);
|
||||
console.log("Active sessions:", Object.keys(activeSessions));
|
||||
|
||||
// 🔹 Kirim response
|
||||
res.status(200).json({
|
||||
message: "Login berhasil",
|
||||
token,
|
||||
role: user.role
|
||||
role: user.role,
|
||||
userId: user.id
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
res.status(500).json({ message: "Terjadi kesalahan", error });
|
||||
console.error("Login error:", error);
|
||||
res.status(500).json({ message: "Terjadi kesalahan", error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
//logout
|
||||
// Logout (Versi yang lebih robust)
|
||||
exports.logout = async (req, res) => {
|
||||
const userId = req.user?.id;
|
||||
try {
|
||||
// Coba ambil userId dari berbagai sumber
|
||||
let userId = req.user?.id;
|
||||
|
||||
// Jika tidak ada dari middleware, coba ambil dari body atau query
|
||||
if (!userId) {
|
||||
userId = req.body?.userId || req.query?.userId;
|
||||
}
|
||||
|
||||
// Jika masih tidak ada, coba decode token manual
|
||||
if (!userId && req.headers.authorization) {
|
||||
try {
|
||||
const token = req.headers.authorization.split(' ')[1];
|
||||
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
||||
userId = decoded.id;
|
||||
} catch (tokenError) {
|
||||
console.log("Token decode error:", tokenError.message);
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Logout attempt - User ID:", userId);
|
||||
console.log("Active sessions before logout:", Object.keys(activeSessions));
|
||||
|
||||
if (userId && activeSessions[userId]) {
|
||||
// Hapus sesi aktif
|
||||
delete activeSessions[userId];
|
||||
|
||||
// Bersihkan timeout
|
||||
if (sessionTimeouts[userId]) {
|
||||
clearTimeout(sessionTimeouts[userId]);
|
||||
delete sessionTimeouts[userId];
|
||||
}
|
||||
|
||||
console.log("Logout berhasil - User ID:", userId);
|
||||
console.log("Active sessions after logout:", Object.keys(activeSessions));
|
||||
|
||||
return res.status(200).json({
|
||||
message: "Logout berhasil",
|
||||
userId: userId
|
||||
});
|
||||
}
|
||||
|
||||
console.log("Logout gagal - Tidak ada sesi aktif untuk User ID:", userId);
|
||||
res.status(400).json({
|
||||
message: "Tidak ada sesi login aktif",
|
||||
userId: userId,
|
||||
activeSessions: Object.keys(activeSessions)
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error("Logout error:", error);
|
||||
res.status(500).json({ message: "Terjadi kesalahan saat logout", error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
// Tambahkan endpoint untuk debugging (opsional - hapus di production)
|
||||
exports.debugSessions = (req, res) => {
|
||||
res.json({
|
||||
activeSessions: activeSessions,
|
||||
sessionTimeouts: Object.keys(sessionTimeouts),
|
||||
message: "Debug info - hapus endpoint ini di production"
|
||||
});
|
||||
};
|
||||
|
||||
// Force logout (untuk admin atau debugging)
|
||||
exports.forceLogout = (req, res) => {
|
||||
const { userId } = req.body;
|
||||
|
||||
if (userId && activeSessions[userId]) {
|
||||
delete activeSessions[userId];
|
||||
if (sessionTimeouts[userId]) {
|
||||
clearTimeout(sessionTimeouts[userId]);
|
||||
delete sessionTimeouts[userId];
|
||||
}
|
||||
return res.json({ message: `User ${userId} berhasil di-force logout` });
|
||||
}
|
||||
|
||||
res.status(404).json({ message: "User tidak ditemukan dalam sesi aktif" });
|
||||
};
|
||||
|
||||
// Clear semua sessions (untuk debugging)
|
||||
exports.clearAllSessions = (req, res) => {
|
||||
const sessionCount = Object.keys(activeSessions).length;
|
||||
|
||||
// Bersihkan semua timeout
|
||||
Object.keys(sessionTimeouts).forEach(userId => {
|
||||
clearTimeout(sessionTimeouts[userId]);
|
||||
delete sessionTimeouts[userId];
|
||||
return res.status(200).json({ message: "Logout berhasil" });
|
||||
}
|
||||
res.status(400).json({ message: "Tidak ada sesi login aktif" });
|
||||
});
|
||||
|
||||
// Bersihkan semua active sessions
|
||||
Object.keys(activeSessions).forEach(userId => {
|
||||
delete activeSessions[userId];
|
||||
});
|
||||
|
||||
console.log(`Cleared ${sessionCount} active sessions`);
|
||||
|
||||
res.json({
|
||||
message: "Semua sesi aktif berhasil dibersihkan",
|
||||
clearedSessions: sessionCount
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -74,17 +74,196 @@ router.post('/register', authController.register);
|
|||
* responses:
|
||||
* 200:
|
||||
* description: Login berhasil
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* message:
|
||||
* type: string
|
||||
* example: Login berhasil
|
||||
* token:
|
||||
* type: string
|
||||
* example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
|
||||
* role:
|
||||
* type: string
|
||||
* example: user
|
||||
* userId:
|
||||
* type: integer
|
||||
* example: 1
|
||||
* 401:
|
||||
* description: Password salah
|
||||
* description: Email atau password salah
|
||||
* 403:
|
||||
* description: Akun sedang digunakan di perangkat lain
|
||||
* 404:
|
||||
* description: User tidak ditemukan
|
||||
* description: Akun sedang digunakan di perangkat lain
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* message:
|
||||
* type: string
|
||||
* example: Akun ini sedang digunakan di perangkat lain.
|
||||
* debug:
|
||||
* type: string
|
||||
* example: User 1 masih dalam sesi aktif
|
||||
* 500:
|
||||
* description: Terjadi kesalahan server
|
||||
*/
|
||||
router.post('/login', authController.login);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/auth/logout:
|
||||
* post:
|
||||
* summary: Logout dari akun
|
||||
* tags: [Authentication]
|
||||
* security:
|
||||
* - bearerAuth: []
|
||||
* requestBody:
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* userId:
|
||||
* type: integer
|
||||
* description: ID user (opsional, diambil dari token jika tidak disediakan)
|
||||
* example: 1
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Logout berhasil
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* message:
|
||||
* type: string
|
||||
* example: Logout berhasil
|
||||
* userId:
|
||||
* type: integer
|
||||
* example: 1
|
||||
* 400:
|
||||
* description: Tidak ada sesi login aktif
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* message:
|
||||
* type: string
|
||||
* example: Tidak ada sesi login aktif
|
||||
* userId:
|
||||
* type: integer
|
||||
* example: 1
|
||||
* activeSessions:
|
||||
* type: array
|
||||
* items:
|
||||
* type: string
|
||||
* example: ["2", "3"]
|
||||
* 500:
|
||||
* description: Terjadi kesalahan server
|
||||
*/
|
||||
router.post('/logout', authController.logout);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/auth/debug-sessions:
|
||||
* get:
|
||||
* summary: Debug - Lihat semua sesi aktif (HAPUS DI PRODUCTION!)
|
||||
* tags: [Debug]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Informasi debug sesi
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* activeSessions:
|
||||
* type: object
|
||||
* description: Objek berisi semua sesi aktif
|
||||
* example:
|
||||
* "1":
|
||||
* loginTime: "2024-01-01T10:00:00.000Z"
|
||||
* email: "johndoe@gmail.com"
|
||||
* sessionTimeouts:
|
||||
* type: array
|
||||
* items:
|
||||
* type: string
|
||||
* description: Array ID user yang memiliki timeout aktif
|
||||
* example: ["1", "2"]
|
||||
* message:
|
||||
* type: string
|
||||
* example: Debug info - hapus endpoint ini di production
|
||||
*/
|
||||
router.get('/debug-sessions', authController.debugSessions);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/auth/force-logout:
|
||||
* post:
|
||||
* summary: Debug - Force logout user tertentu (HAPUS DI PRODUCTION!)
|
||||
* tags: [Debug]
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - userId
|
||||
* properties:
|
||||
* userId:
|
||||
* type: integer
|
||||
* description: ID user yang akan di-force logout
|
||||
* example: 1
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Force logout berhasil
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* message:
|
||||
* type: string
|
||||
* example: User 1 berhasil di-force logout
|
||||
* 404:
|
||||
* description: User tidak ditemukan dalam sesi aktif
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* message:
|
||||
* type: string
|
||||
* example: User tidak ditemukan dalam sesi aktif
|
||||
*/
|
||||
router.post('/force-logout', authController.forceLogout);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
* /api/auth/clear-all-sessions:
|
||||
* post:
|
||||
* summary: Debug - Bersihkan semua sesi aktif (HAPUS DI PRODUCTION!)
|
||||
* tags: [Debug]
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Semua sesi berhasil dibersihkan
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* message:
|
||||
* type: string
|
||||
* example: Semua sesi aktif berhasil dibersihkan
|
||||
* clearedSessions:
|
||||
* type: integer
|
||||
* example: 3
|
||||
*/
|
||||
router.post('/clear-all-sessions', authController.clearAllSessions);
|
||||
|
||||
/**
|
||||
* @swagger
|
||||
|
|
|
@ -223,6 +223,8 @@ Future<List<Map<String, dynamic>>> getAllHistori() async {
|
|||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
print("User ID dari respons login: ${responseData['userId']}"); // Tambahkan log
|
||||
await prefs.setString('userId', responseData['userId'].toString());
|
||||
await prefs.setString('token', responseData['token']);
|
||||
await prefs.setString('role', responseData['role']);
|
||||
|
||||
return responseData;
|
||||
} else {
|
||||
|
@ -239,6 +241,7 @@ Future<List<Map<String, dynamic>>> getAllHistori() async {
|
|||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove('token');
|
||||
await prefs.remove('role');
|
||||
await prefs.remove('userId');
|
||||
}
|
||||
|
||||
// Fungsi Cek Login
|
||||
|
|
|
@ -5,19 +5,48 @@ import 'riwayat_diagnosa_page.dart';
|
|||
import 'profile_page.dart';
|
||||
import 'basis_pengetahuan_page.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'login_page.dart';
|
||||
import 'dart:async';
|
||||
|
||||
class HomePage extends StatefulWidget {
|
||||
|
||||
const HomePage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_HomePageState createState() => _HomePageState();
|
||||
}
|
||||
|
||||
class _HomePageState extends State<HomePage> {
|
||||
String userId = ''; // Variabel untuk menyimpan userId
|
||||
Timer? _logoutTimer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
super.initState();
|
||||
_startAutoLogoutTimer();
|
||||
}
|
||||
|
||||
void _startAutoLogoutTimer() {
|
||||
_logoutTimer?.cancel(); // Pastikan timer sebelumnya di-cancel
|
||||
|
||||
_logoutTimer = Timer(const Duration(minutes: 5), () async {
|
||||
// Hapus semua data login
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.clear();
|
||||
|
||||
// Redirect ke LoginPage
|
||||
if (!mounted) return;
|
||||
Navigator.of(context).pushAndRemoveUntil(
|
||||
MaterialPageRoute(builder: (context) => LoginPage()),
|
||||
(route) => false, // Menghapus semua halaman sebelumnya
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_logoutTimer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> navigateToRiwayatDiagnosaPage(BuildContext context) async {
|
||||
|
@ -32,8 +61,8 @@ class _HomePageState extends State<HomePage> {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
|
|
Loading…
Reference in New Issue