Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

Mengelola Peran dan Status dalam Sistem

Ada banyak cara untuk memecahkan masalah, dan itulah yang terjadi dengan mengelola peran dan status pengguna dalam sistem perangkat lunak. Dalam artikel ini, Anda akan menemukan evolusi sederhana dari ide tersebut serta beberapa tips dan contoh kode yang berguna.

Ide Dasar

Di sebagian besar sistem, biasanya ada kebutuhan untuk memiliki peran dan status user pengguna .

Peran terkait dengan hak yang dimiliki pengguna saat menggunakan sistem setelah berhasil masuk. Contoh peran adalah “karyawan pusat panggilan”, “manajer pusat panggilan”, “karyawan back office”, “manajer back office”, atau “manajer”. Secara umum itu berarti bahwa pengguna akan memiliki akses ke beberapa fungsi jika dia memiliki peran yang sesuai. Sebaiknya asumsikan bahwa pengguna dapat memiliki banyak peran pada saat yang bersamaan.

Status jauh lebih ketat dan menentukan apakah pengguna memiliki hak untuk masuk ke sistem atau tidak. Seorang pengguna hanya dapat memiliki satu status pada suatu waktu. Contoh statusnya adalah:“bekerja”, “berlibur”, “cuti sakit”, “kontrak berakhir”.

Saat kami mengubah status pengguna, kami masih dapat mempertahankan semua peran yang terkait dengan pengguna tersebut tidak berubah. Itu sangat membantu karena sebagian besar waktu kami hanya ingin mengubah status pengguna. Jika pengguna yang bekerja sebagai karyawan call center pergi berlibur, kita cukup mengubah statusnya menjadi “liburan” dan mengembalikannya ke status “bekerja” saat dia kembali.

Menguji peran dan status selama login memungkinkan kami memutuskan apa yang akan terjadi. Misalnya, mungkin kita ingin melarang login meskipun username dan password sudah benar. Kita dapat melakukannya jika status pengguna saat ini tidak menunjukkan bahwa dia bekerja atau jika pengguna tidak memiliki peran apa pun dalam sistem.

Dalam semua model yang diberikan di bawah ini, tabel status dan role adalah sama.

Tabel status memiliki bidang id dan status_name dan atribut is_active . Jika atribut is_active disetel ke “True”, artinya pengguna yang memiliki status tersebut sedang bekerja. Misalnya, status "bekerja" akan memiliki atribut is_active dengan nilai Benar, sementara yang lain (“berlibur”, “cuti sakit”, “kontrak berakhir”) akan memiliki nilai Salah.

Tabel peran hanya memiliki dua bidang:id dan role_name .

user_account tabel sama dengan user_account tabel yang disajikan dalam artikel ini. Hanya pada model pertama user_account tabel berisi dua atribut tambahan (role_id dan status_id ).

Beberapa model akan dihadirkan. Semuanya berfungsi dan dapat digunakan tetapi memiliki kelebihan dan kekurangannya masing-masing.

Model Sederhana

Ide pertama bisa jadi kita cukup menambahkan hubungan kunci asing ke user_account tabel, merujuk pada tabel status dan role . Keduanya role_id dan status_id adalah wajib.




Ini cukup sederhana untuk dirancang dan juga untuk menangani data dengan kueri tetapi memiliki beberapa kelemahan:

  1. Kami tidak menyimpan data riwayat (atau masa depan).

    Saat kami mengubah status atau peran, kami cukup memperbarui status_id dan role_id di user_account meja. Itu akan berfungsi dengan baik untuk saat ini, jadi ketika kami membuat perubahan, itu akan tercermin dalam sistem. Tidak apa-apa jika kita tidak perlu tahu bagaimana status dan peran telah berubah secara historis. Juga ada masalah karena kami tidak dapat menambahkan masa depan peran atau status tanpa menambahkan tabel tambahan ke model ini. Satu situasi di mana kita mungkin ingin memiliki pilihan itu adalah ketika kita tahu bahwa seseorang akan berlibur mulai Senin depan. Contoh lain adalah ketika kita memiliki karyawan baru; mungkin kita ingin memasukkan status dan perannya sekarang dan untuk itu menjadi valid di beberapa titik di masa depan.

    Ada juga komplikasi jika kami memiliki acara terjadwal yang menggunakan peran dan status. Acara yang menyiapkan data untuk hari kerja berikutnya biasanya berjalan saat sebagian besar pengguna tidak menggunakan sistem (misalnya saat malam hari). Jadi, jika seseorang tidak bekerja besok, kita harus menunggu sampai akhir hari ini dan kemudian mengubah peran dan statusnya sebagaimana mestinya. Misalnya, jika kita memiliki karyawan yang saat ini bekerja dan memiliki peran "karyawan call center", mereka akan mendapatkan daftar klien yang harus mereka hubungi. Jika seseorang secara tidak sengaja memiliki status dan peran itu, dia juga akan mendapatkan kliennya dan kita harus meluangkan waktu untuk memperbaikinya.

  2. Pengguna hanya dapat memiliki satu peran dalam satu waktu.

    Umumnya pengguna harus dapat memiliki lebih dari satu peran didalam sistem. Mungkin pada saat Anda mendesain database tidak perlu hal seperti itu. Perlu diingat bahwa perubahan alur kerja/proses dapat terjadi. Misalnya, pada suatu saat klien dapat memutuskan untuk menggabungkan dua peran menjadi satu. Salah satu solusi yang mungkin adalah membuat peran baru dan menetapkan semua fungsi dari peran sebelumnya ke peran tersebut. Solusi lain (jika pengguna dapat memiliki lebih dari satu peran) adalah klien hanya menetapkan kedua peran tersebut kepada pengguna yang membutuhkannya. Tentu saja solusi kedua lebih praktis dan memberikan klien kemampuan untuk menyesuaikan sistem dengan kebutuhannya lebih cepat (yang tidak didukung oleh model ini).

Di sisi lain, model ini juga memiliki satu keunggulan besar dibandingkan yang lain. Ini sederhana dan kueri untuk mengubah status dan peran juga sederhana. Juga, kueri yang memeriksa apakah pengguna memiliki hak untuk masuk ke sistem jauh lebih sederhana daripada dalam kasus lain:

select user_account.id, user_account.role_id
from user_account
left join status on user_account.status_id = status.id
where status.is_user_working = True
and user_account.user_name = @user_name
and user_account.password_hash_algorithm = @password;

@user_name dan @password adalah variabel dari formulir input sementara kueri mengembalikan id pengguna dan role_id yang dia miliki. Jika nama_pengguna atau kata sandi tidak valid, pasangan_nama_pengguna dan kata sandi tidak ada, atau pengguna memiliki status yang ditetapkan yang tidak aktif, kueri tidak akan mengembalikan hasil apa pun. Dengan begitu kita bisa melarang login.

Model ini dapat digunakan jika:

  • kami yakin tidak akan ada perubahan dalam proses yang mengharuskan pengguna memiliki lebih dari satu peran
  • kami tidak perlu melacak perubahan peran/status dalam riwayat
  • kami tidak berharap memiliki banyak peran/status administrasi.

Komponen Waktu Ditambahkan

Jika kita perlu melacak peran pengguna dan riwayat status, kita harus menambahkan banyak ke banyak hubungan antara user_account dan role dan user_account dan status . Tentu saja kami akan menghapus role_id dan status_id dari user_account meja. Tabel baru dalam model adalah user_has_role dan user_has_status dan semua bidang di dalamnya, kecuali waktu berakhir, adalah wajib.




Tabel user_has_role berisi data tentang semua peran yang pernah dimiliki pengguna dalam sistem. Kunci alternatifnya adalah (user_account_id , role_id , role_start_time ) karena tidak ada gunanya menetapkan peran yang sama secara bersamaan kepada pengguna lebih dari sekali.

Tabel user_has_status berisi data tentang semua status yang pernah dimiliki pengguna dalam sistem. Kunci alternatif di sini adalah (user_account_id , status_start_time ) karena pengguna tidak dapat memiliki dua status yang dimulai secara bersamaan.

Waktu mulai tidak boleh nol karena saat kita menyisipkan peran/status baru, kita tahu saat mulainya. Waktu berakhir dapat menjadi null jika kita tidak tahu kapan peran/status akan berakhir (mis. peran berlaku mulai besok hingga sesuatu terjadi di masa mendatang).

Selain memiliki histori yang lengkap, kini kita dapat menambahkan status dan peran di masa mendatang. Namun hal ini menimbulkan komplikasi karena kita harus memeriksa tumpang tindih saat melakukan penyisipan atau pembaruan.

Misalnya, pengguna hanya dapat memiliki satu status dalam satu waktu. Sebelum kita menyisipkan status baru, kita harus membandingkan waktu mulai dan waktu berakhir status baru dengan semua status yang ada untuk pengguna tersebut di database. Kita bisa menggunakan query seperti ini:

select *
from user_has_status
where user_has_status.user_account_id = @user_account_id
and 
(
# test if @start_time included in interval of some previous status
(user_has_status.status_start_time <= @start_time and ifnull(user_has_status.status_end_time, "2200-01-01") >= @start_time)
or
# test if @end_time included in interval of some previous status  
(user_has_status.status_start_time <= @end_time and ifnull(user_has_status.status_end_time, "2200-01-01") >= ifnull(@end_time, "2199-12-31"))  
or  
# if @end_time is null we cannot have any statuses after @start_time
(@end_time is null and user_has_status.status_start_time >= @start_time)  
or
# new status "includes" old satus (@start_time <= user_has_status.status_start_time <= @end_time)
(user_has_status.status_start_time >= @start_time and user_has_status.status_start_time <= ifnull(@end_time, "2199-12-31"))  
)

@start_time dan @end_time adalah variabel yang berisi waktu mulai dan waktu berakhir dari status yang ingin kita sisipkan dan @user_account_id adalah id pengguna yang kami masukkan. @end_time bisa menjadi nol dan kita harus menanganinya dalam kueri. Untuk tujuan ini, nilai null diuji dengan ifnull() fungsi. Jika nilainya nol, nilai tanggal tinggi ditetapkan (cukup tinggi sehingga ketika seseorang melihat kesalahan dalam kueri, kami akan lama pergi :). Kueri memeriksa semua kombinasi waktu mulai dan waktu berakhir untuk status baru dibandingkan dengan waktu mulai dan waktu berakhir dari status yang ada. Jika kueri mengembalikan catatan apa pun, maka kami memiliki tumpang tindih dengan status yang ada dan kami harus melarang penyisipan status baru. Juga akan menyenangkan untuk memunculkan kesalahan khusus.

Jika kami ingin memeriksa daftar peran dan status saat ini (hak pengguna), kami cukup menguji menggunakan waktu mulai dan waktu berakhir.

select user_account.id, user_has_role.id
from user_account
left join user_has_role on user_has_role.user_account_id = user_account.id
left join user_has_status on user_account.id = user_has_status.user_account_id
left join status on user_has_status.status_id = status.id
where user_account.user_name = @user_name
and user_account.password_hash_algorithm = @password
and user_has_role.role_start_time <= @time and ifnull(user_has_role.role_end_time,"2200-01-01") >= @time
and user_has_status.status_start_time <= @time and ifnull(user_has_status.status_end_time,"2200-01-01") >= @time
and status.is_user_working = True

@user_name dan @password adalah variabel dari formulir input sementara @time dapat diatur ke Now(). Saat pengguna mencoba masuk, kami ingin memeriksa haknya saat itu. Hasil adalah daftar semua peran yang dimiliki pengguna dalam sistem jika nama_pengguna dan kata sandi cocok dan pengguna saat ini memiliki status aktif. Jika pengguna memiliki status aktif tetapi tidak ada peran yang ditetapkan, kueri tidak akan mengembalikan apa pun.

Kueri ini lebih sederhana daripada yang ada di bagian 3 dan model ini memungkinkan kita memiliki riwayat status dan peran. Selain itu, kami dapat mengelola status dan peran untuk masa depan dan semuanya akan berfungsi dengan baik.

Model Akhir

Ini hanyalah gambaran tentang bagaimana model sebelumnya dapat diubah jika kami ingin meningkatkan kinerja. Karena pengguna hanya dapat memiliki satu status aktif dalam satu waktu, kami dapat menambahkan status_id ke user_account tabel (current_status_id ). Dengan begitu, kita dapat menguji nilai atribut tersebut dan tidak perlu bergabung dengan user_has_status meja. Kueri yang dimodifikasi akan terlihat seperti ini:

select user_account.id, user_has_role.id
from user_account
left join user_has_role on user_has_role.user_account_id = user_account.id
left join status on user_account.current_status_id = status.id
where user_account.user_name = @user_name
and user_account.password_hash_algorithm = @password
and user_has_role.role_start_time <= @time and ifnull(user_has_role.role_end_time,"2200-01-01") >= @time
and status.is_user_working = True




Jelas ini menyederhanakan kueri dan menghasilkan kinerja yang lebih baik tetapi ada masalah yang lebih besar yang perlu dipecahkan. current_status_id di user_account tabel harus diperiksa dan diubah jika perlu dalam situasi berikut:

  • pada setiap sisipan/perbarui/hapus di user_has_status meja
  • setiap hari dalam acara terjadwal, kita harus memeriksa apakah status seseorang berubah (status aktif saat ini kedaluwarsa atau/dan beberapa status di masa mendatang menjadi aktif) dan memperbaruinya sebagaimana mestinya

Sebaiknya simpan nilai yang akan sering digunakan kueri. Dengan begitu kita akan menghindari melakukan pemeriksaan yang sama berulang-ulang dan membagi pekerjaan. Di sini kita akan menghindari bergabung dengan user_has_status tabel dan kami akan membuat perubahan pada current_status_id hanya ketika itu terjadi (masukkan/perbarui/hapus) atau ketika sistem tidak terlalu banyak digunakan (peristiwa terjadwal biasanya berjalan ketika sebagian besar pengguna tidak menggunakan sistem). Mungkin dalam hal ini kita tidak akan mendapatkan banyak keuntungan dari current_status_id tetapi lihat ini sebagai ide yang dapat membantu dalam situasi serupa.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kejutan dan Asumsi Kinerja :STRING_SPLIT()

  2. Bagaimana Cara Memesan dengan Hitungan di SQL?

  3. Memfilter Data dengan JDBC RowSet

  4. Lembar Cheat SQL UNION dengan 10 Tips Mudah dan Berguna

  5. SQL Pilih Berbeda