Tutorial User Management & Profile
1. Backend User Management
1.1 Role Middleware (src/middleware/role.js)
const checkRole = (roles) => {
return (req, res, next) => {
if (!req.user) {
return res.status(401).json({ message: 'Unauthorized' });
}
if (!roles.includes(req.user.role)) {
return res.status(403).json({ message: 'Forbidden' });
}
next();
};
};
module.exports = { checkRole };
1.2 User Model (src/models/User.js) - Extend Existing
const db = require('../config/database');
const bcrypt = require('bcryptjs');
const User = {
// Existing methods dari Authentication...
findAll: async () => {
const [rows] = await db.execute('SELECT id, username, email, role, created_at FROM users');
return rows;
},
findById: async (id) => {
const [rows] = await db.execute('SELECT id, username, email, role, created_at FROM users WHERE id = ?', [id]);
return rows[0];
},
update: async (id, userData) => {
const { username, email } = userData;
const [result] = await db.execute(
'UPDATE users SET username = ?, email = ? WHERE id = ?',
[username, email, id]
);
return result;
},
delete: async (id) => {
const [result] = await db.execute('DELETE FROM users WHERE id = ?', [id]);
return result;
},
// Methods untuk profile akan diimplementasikan nanti
/*
updatePassword: async (id, newPassword) => {...},
updateAvatar: async (id, avatarUrl) => {...},
*/
};
module.exports = User;
1.3 User Controller (src/controllers/userController.js)
const User = require('../models/User');
const getAllUsers = async (req, res) => {
try {
const users = await User.findAll();
res.json(users);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
const getUserById = async (req, res) => {
try {
const user = await User.findById(req.params.id);
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
res.json(user);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
const updateUser = async (req, res) => {
try {
const result = await User.update(req.params.id, req.body);
if (result.affectedRows === 0) {
return res.status(404).json({ message: 'User not found' });
}
res.json({ message: 'User updated successfully' });
} catch (error) {
res.status(500).json({ message: error.message });
}
};
const deleteUser = async (req, res) => {
try {
const result = await User.delete(req.params.id);
if (result.affectedRows === 0) {
return res.status(404).json({ message: 'User not found' });
}
res.json({ message: 'User deleted successfully' });
} catch (error) {
res.status(500).json({ message: error.message });
}
};
module.exports = {
getAllUsers,
getUserById,
updateUser,
deleteUser
};
1.4 User Routes (src/routes/user.routes.js)
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
const { auth } = require('../middleware/auth');
const { checkRole } = require('../middleware/role');
router.get('/', auth, checkRole(['admin']), userController.getAllUsers);
router.get('/:id', auth, checkRole(['admin', 'petugas']), userController.getUserById);
router.put('/:id', auth, checkRole(['admin']), userController.updateUser);
router.delete('/:id', auth, checkRole(['admin']), userController.deleteUser);
module.exports = router;
2. Frontend Profile Management
2.1 Profile Service (src/services/profile.service.js)
import api from './api';
const ProfileService = {
getProfile: async () => {
const response = await api.get('/auth/profile');
return response.data;
},
updateProfile: async (data) => {
const response = await api.put('/auth/profile', data);
return response.data;
},
// Service lain akan diimplementasikan nanti
/*
updatePassword: async (data) => {...},
updateAvatar: async (formData) => {...},
*/
};
export default ProfileService;
2.2 Profile Component (src/components/profile/ProfileForm.js)
import React, { useState, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import ProfileService from '../../services/profile.service';
const ProfileForm = () => {
const [formData, setFormData] = useState({
username: '',
email: '',
});
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const user = useSelector((state) => state.auth.user);
useEffect(() => {
if (user) {
setFormData({
username: user.username,
email: user.email,
});
}
}, [user]);
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
try {
await ProfileService.updateProfile(formData);
setError(null);
} catch (err) {
setError(err.response?.data?.message || 'Update failed');
} finally {
setLoading(false);
}
};
// Template akan diimplementasikan nanti
return (
<div>
<h2>Profile Settings</h2>
{/* Form akan diimplementasikan nanti */}
</div>
);
};
export default ProfileForm;
2.3 User Management Components (src/components/admin/UserManagement.js)
import React, { useState, useEffect } from 'react';
import UserService from '../../services/user.service';
const UserManagement = () => {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetchUsers();
}, []);
const fetchUsers = async () => {
try {
const data = await UserService.getAllUsers();
setUsers(data);
setError(null);
} catch (err) {
setError(err.response?.data?.message || 'Failed to fetch users');
} finally {
setLoading(false);
}
};
const handleDeleteUser = async (userId) => {
if (window.confirm('Are you sure you want to delete this user?')) {
try {
await UserService.deleteUser(userId);
setUsers(users.filter(user => user.id !== userId));
} catch (err) {
setError(err.response?.data?.message || 'Failed to delete user');
}
}
};
// Template akan diimplementasikan nanti
return (
<div>
<h2>User Management</h2>
{/* Table dan actions akan diimplementasikan nanti */}
</div>
);
};
export default UserManagement;
2.4 User Service (src/services/user.service.js)
import api from './api';
const UserService = {
getAllUsers: async () => {
const response = await api.get('/users');
return response.data;
},
getUserById: async (id) => {
const response = await api.get(`/users/${id}`);
return response.data;
},
updateUser: async (id, data) => {
const response = await api.put(`/users/${id}`, data);
return response.data;
},
deleteUser: async (id) => {
const response = await api.delete(`/users/${id}`);
return response.data;
},
};
export default UserService;
Catatan Implementasi:
Frontend Components yang perlu dibuat:
Role management interface
Backend Features yang perlu ditambahkan:
Password change functionality
User search dan filtering
Pagination untuk user list
Advanced role permissions
Security Considerations:
Validasi input untuk semua forms
Sanitasi data sebelum menyimpan ke database
Role-based access control yang ketat
Additional Features untuk diimplementasikan:
Email notifications untuk password changes
Two-factor authentication
Untuk testing:
Test CRUD operations untuk users