C. User Management & Profile

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:

  1. Frontend Components yang perlu dibuat:

    • Profile settings page

    • Change password form

    • Avatar upload component

    • User list table

    • User edit modal

    • Role management interface

  2. Backend Features yang perlu ditambahkan:

    • Password change functionality

    • Avatar upload handling

    • User search dan filtering

    • Pagination untuk user list

    • Advanced role permissions

  3. Security Considerations:

    • Validasi input untuk semua forms

    • Sanitasi data sebelum menyimpan ke database

    • File upload restrictions

    • Role-based access control yang ketat

  4. Additional Features untuk diimplementasikan:

    • User activity logs

    • Last login tracking

    • Session management

    • Email notifications untuk password changes

    • Two-factor authentication

Untuk testing:

  1. Test CRUD operations untuk users

  2. Verify role-based access

  3. Test profile updates

  4. Validate file uploads

  5. Check error handling

  6. Test form validations

Last updated