add modified function login anda logout

This commit is contained in:
unknown 2025-06-09 16:28:28 +07:00
parent 98b1df4f12
commit e14b2ff46c
4 changed files with 339 additions and 23 deletions

View File

@ -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
});
};

View File

@ -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

View File

@ -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

View File

@ -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(