From a15e5b01b7c86d84852b79c6865bebab749fa08e Mon Sep 17 00:00:00 2001
From: Hilmi Al-Biruni <hilmi.albiruni@ui.ac.id>
Date: Wed, 9 Nov 2022 17:47:34 +0700
Subject: [PATCH] Feat/tutorial 7 belajarbelajar

---
 README.md                                     | 113 +++++++++++++-----
 belajarbelajar/build.gradle                   |   4 +-
 .../controller/BaseController.java            |  12 --
 .../controller/PageController.java            | 112 +++++++++++++++++
 .../controller/UserController.java            |  90 ++++++++++++++
 .../belajarbelajar/model/RoleModel.java       |  34 ++++++
 .../belajarbelajar/model/UserModel.java       |  56 +++++++++
 .../belajarbelajar/repository/RoleDb.java     |  12 ++
 .../belajarbelajar/repository/UserDb.java     |  13 ++
 .../security/UserDetailsServiceImpl.java      |  27 +++++
 .../security/WebSecurityConfig.java           |  61 ++++++++++
 .../security/xml/Attributes.java              |  29 +++++
 .../security/xml/AuthenticationSuccess.java   |  20 ++++
 .../security/xml/ServiceResponse.java         |  23 ++++
 .../belajarbelajar/service/RoleService.java   |   8 ++
 .../service/RoleServiceImpl.java              |  30 +++++
 .../belajarbelajar/service/UserService.java   |  23 ++++
 .../service/UserServiceImpl.java              |  76 ++++++++++++
 .../belajarbelajar/setting/Setting.java       |  12 ++
 .../src/main/resources/application.properties |   5 +-
 .../main/resources/templates/delete-user.html |  26 ++++
 .../main/resources/templates/error/400.html   |   2 +-
 .../main/resources/templates/error/403.html   |  17 +++
 .../main/resources/templates/error/405.html   |   2 +-
 .../main/resources/templates/error/500.html   |   2 +-
 .../resources/templates/form-add-user.html    |  49 ++++++++
 .../templates/form-update-password.html       |  46 +++++++
 .../templates/fragments/fragment.html         |   3 +
 .../src/main/resources/templates/home.html    |  27 +++++
 .../src/main/resources/templates/login.html   |  48 ++++++++
 .../templates/sukses-update-password.html     |  26 ++++
 .../resources/templates/viewall-user.html     |  46 +++++++
 32 files changed, 1006 insertions(+), 48 deletions(-)
 delete mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/controller/BaseController.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/controller/PageController.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/controller/UserController.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/model/RoleModel.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/model/UserModel.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/repository/RoleDb.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/repository/UserDb.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/UserDetailsServiceImpl.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/WebSecurityConfig.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/xml/Attributes.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/xml/AuthenticationSuccess.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/xml/ServiceResponse.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/RoleService.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/RoleServiceImpl.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/UserService.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/UserServiceImpl.java
 create mode 100644 belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/setting/Setting.java
 create mode 100644 belajarbelajar/src/main/resources/templates/delete-user.html
 create mode 100644 belajarbelajar/src/main/resources/templates/error/403.html
 create mode 100644 belajarbelajar/src/main/resources/templates/form-add-user.html
 create mode 100644 belajarbelajar/src/main/resources/templates/form-update-password.html
 create mode 100644 belajarbelajar/src/main/resources/templates/login.html
 create mode 100644 belajarbelajar/src/main/resources/templates/sukses-update-password.html
 create mode 100644 belajarbelajar/src/main/resources/templates/viewall-user.html

diff --git a/README.md b/README.md
index b7b739d..df3dba8 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,51 @@
 ## Authors
 * **Hilmi Al Biruni** - *2006463843* - *APAP-B*
 ---
+## Tutorial 7
+### Pertanyaan 1: Jelaskan secara singkat perbedaan Otentikasi dan Otorisasi! Di bagian mana (dalam kode yang telah anda buat) konsep tersebut diimplementasi?
+
+#### Otentikasi adalah proses melakukan verifikasi apakah pengguna yang ingin melakukan login dengan username yang dimiliki terlah tersedia di database dan dapat masuk untuk mengakses aplikasi. Sedangkan, otorisasi adalah proses untuk menentukan hak pengguna apakah pengguna tersebut memiliki akses ke halaman tertentu yang telah ditentukan otentifikasinya.
+
+#### Implementasi otentikasi pada class WebSecurityConfig
+```
+@Autowired
+    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
+        auth.userDetailsService(userDetailsService).passwordEncoder(encoder());
+    }
+```
+
+#### Implementasi otorisasi pada class WebSecurityConfig
+```
+http
+                .authorizeRequests()
+                .antMatchers("/css/**").permitAll()
+                .antMatchers("/js/**").permitAll()
+                .antMatchers("/login-sso", "/validate-ticket").permitAll()
+                .anyRequest().authenticated()
+                .and()
+                .formLogin()
+                .loginPage("/login").permitAll()
+                .and()
+                .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
+                .logoutSuccessUrl("/login").permitAll();
+```
+
+### Pertanyaan 2: Apa itu BCryptPasswordEncoder? Jelaskan secara singkat cara kerja dan tujuannya.
+
+#### BCryptPasswordEncoder merupakan sebuah class yang mengimplementasikan PasswordEncoder dan juga menyediakan password hashing. Untuk melakukan register password, tidak mungkin dengan menggunakan plaintext, maka penyimpanan password menggunakan hashing. BCryptPasswordEncoder bekerja dengan menyimpan password yang telah di-hashing terlebih dahulu.
+
+### Pertanyaan 3: Apakah penyimpanan password sebaiknya menggunakan encryption atau hashing? Mengapa demikian?
+
+#### Encryption dan hashing merupakan dua istilah yang berbeda. Encryption adalah proses mengubah sebuah pesan normal (plaintext) menjadi pesan yang tidak mudah dibaca (ciphertext). Ciphertext yang diperoleh dari encryption dapat dengan mudah diubah menjadi plaintext menggunakan encryption key. Hashing adalah proses mengubah informasi menjadi kunci menggunakan hash function. Informasi asli tidak dapat diambil dari hash key dengan cara apapun. Dengan demikian, penyimpanan password akan lebih aman jika dilakukan dengan hashing daripada encryption.
+
+### Pertanyaan 4: Jelaskan secara singkat apa itu UUID beserta penggunaannya! 
+
+#### UUID (Universally Unique Identifier) merupakan kode dengan jumlah hashing terbanyak yaitu sebanyak 32 karakter yang akan digunakan untuk keamanan data. UUID di-generate untuk id pengguna. Dibandingkan dengan BCrypt yang merupakan password yang berguna untuk mengamankan id dari hacking. Dapat dipastikan UUID yang tergenerate unik untuk tiap objek yang ada di internet, jadi id yang dimiliki pengguna akan aman.
+
+### Pertanyaan 5: Apa kegunaan class UserDetailsServiceImpl.java? Mengapa harus ada class tersebut?
+
+#### Class UserDetailsServiceImpl.java memberikan informasi mengenai Otentikasi dan Otorisasi akun yang ada pada class lain. Class ini harus diimplementasikan, jika tidak informasi tersebut tidak dapat diberikan. Kemampuan tersebut ada karena class mengimplementasikan UserDetailService. UserDetailService merupakan interface yang ada dari Spring Security. Selain itu, class ini meng-override loadUserByUsername() yang bisa dilakukan kustomisasi untuk pencarian user.
+---
 ## Tutorial 6
 ### Pertanyaan 1: Perhatikan apa yang terjadi pada file index.html pada branch feat/tutorial-6-advancedgit-1. Apa yang terjadi setelah git cherry-pick dilakukan? Apakah kita bisa melakukan cherrypick tanpa harus melakukan commit?
 #### File index.html dipull dari branch tut6-for-cherrypick sehingga index.html ada pada branch feat/tutorial-6-advancedgit-1. Git cherry pick mencari commit-id yang akan mengambil file dari branch tertentu. Dalam melakukan hal itu, perlu dilakuka commit agar dapat terdefinisi commit-id
@@ -38,42 +83,42 @@
 ---
 ## Tutorial 5
 
-### 1. Apa itu Postman? Apa kegunaannya?
+### Pertanyaan 1: Apa itu Postman? Apa kegunaannya?
 
 #### Postman adalah sebuah developent tool API yang digunakan untuk build, modify, dan test API. Penggunaan Postman dapat digunakan untuk mendesign, mock, debug, tes, dokumentasi, monitor, dan juga menerbitkan API. Postman memiliki fungsi REST Client yang dapat digunakan untuk menguji REST API.
 
-### 2. Jelaskan fungsi dari anotasi @JsonIgnoreProperties dan @JsonProperty
+### Pertanyaan 2: Jelaskan fungsi dari anotasi @JsonIgnoreProperties dan @JsonProperty
 
 #### @JsonIgnoreProperties digunnakan untuk memberikan spesifikasi list atribut dari sebuah class yang diabaikan saat menjalankan serialization dan deserialozation JSON. Jika #### @JsonIgnoreProperties tidak disertakan, nantinya akan menyebabkan error saat menjalankan serialization dan deserialization saat Java Object tidak memiliki field yang ada pada JSON.
 
-### 3. Apa kegunaan atribut WebClient?
+### Pertanyaan 3: Apa kegunaan atribut WebClient?
 
 #### Kegunaan dari Webclient adalah untuk menghubungkan personal komputer ke jaringan internet yang meminta informasi. Dalam mengakses webserver diperlukan sebuah WebClient untuk menggunakan aplikasi yaitu WebBrowser.
 
-### 4. Apa itu ResponseEntity dan BindingResult? Apa kegunaannya?
+### Pertanyaan 4: Apa itu ResponseEntity dan BindingResult? Apa kegunaannya?
 
 #### ResponseEntity merupakan representasi keluruhan HTTP Response dari status code, header, dan body. Dengan demikian, dapat digunakan untuk mengkonfigurasi secara lengkap HTTP response. BindingResult adalah sebuah objek spring yang akan menyimpan hasil validasi, binding, dan error dari model objek yang divalidasikan. Penggunaan BindingResult diletakkan setelah parameter objek divalidasi.
 ---
 ## Tutorial 4
-### Jelaskan perbedaan th:include dan th:replace!
+### Pertanyaan 1: Jelaskan perbedaan th:include dan th:replace!
 
 #### Perbedaan dari include dan replace adalah penempatan suatu konten dari fragment
 #### Include akan memanggil isi dari fragment ke dalam th:include tersebut. Lalu, include akan memasukkan konten fragment tanpa menyisipkan tag fragment itu sendiri.
 #### Berbeda dengan include, replace menerapkan konsep parent-kid dalam pengimplementasian fragment tersebut. Replace akan memasukkan konten dari fragment dengan mengganti tag menjadi tag yang mendefinisikan fragment sehingga dapat di kustomisasi.
 
-### Jelaskan apa fungsi dari th:object! 
+### Pertanyaan 2: Jelaskan apa fungsi dari th:object! 
 
 #### th:object digunakan untuk menyederhanakan pemanggilan suatu objek di dalam HTML. th:object akan menggunakan atribut langsung dari objek tanpa harus menspesifikasikan objek yang dipanggil.
 
-### Jelaskan perbedaan dari * dan $ pada saat penggunaan th:object! Kapan harus dipakai?
+### Pertanyaan 3: Jelaskan perbedaan dari * dan $ pada saat penggunaan th:object! Kapan harus dipakai?
 
 #### * digunakan untuk menyatakan sebuah selection dan menunjuk kepada atribut darri suatu objek. Berbeda dengan $ yang digunakan untuk menyatakan sebuah variabel/value dan menunjuk kepada atribut suatu objek.
 
-### Bagaimana parameter/params tersebut bekerja sehingga Anda dapat menambahkan 1 baris penyelenggara pada form tambah course?
+### Pertanyaan 4: Bagaimana parameter/params tersebut bekerja sehingga Anda dapat menambahkan 1 baris penyelenggara pada form tambah course?
 
 #### params perlu dibuat terlebih dahulu logic-nya dalam struktur data List. params akan mendefinisikan semacam "function" agar dapat diimplementasikan di dalam <button> dalam variable "name". 
 
-### Bagaimana parameter/params tersebut bekerja sehingga Anda dapat menghapus 1 baris penyelenggara pada form tambah course?
+### Pertanyaan 5: Bagaimana parameter/params tersebut bekerja sehingga Anda dapat menghapus 1 baris penyelenggara pada form tambah course?
 
 #### params perlu dibuat terlebih dahulu logic-nya sebagai berikut:
 ##### final Integer rowId = Integer.valueOf(row);
@@ -82,6 +127,7 @@
 
 ## Tutorial 3
 ### Pertanyaan 1: Tolong jelaskan secara singkat apa kegunaan dari anotasi-anotasi yang ada pada model (@AllArgsConstructor, @NoArgsConstructor, @Setter, @Getter, @Entity, @Table)
+
 #### @AllArgsConstructor digunakan untuk menghasilkan constructor pada semua field pada class dengan suatu parameter.
 #### @NoArgsConstructor digunakan untuk menghasilkan no-args constructor yang akan menghasilkan pesan error jika constructor terseebut tidak dapat ditulis karena adanya final fields
 #### @Setter dan @Getter digunakan untuk mempermudah generate setter dan getter sehingga tidak perlu membuat manual, hanya memanggil get dan set saja.
@@ -99,7 +145,8 @@
 #### Sedangkan @JoinColumn menyimpan id dari entity lain di column baru di tabel yang sama. Penggunaan @JoinColumn ketika entity memiliki direct relationship seperti foreign key antara dua entity.
 
 ### Pertanyaan 4: Pada class Pengajar, digunakan anotasi @JoinColumn pada atribut Course, apa kegunaan dari name, referencedColumnName, dan nullable dalam anotasi tersebut? dan apa perbedaan nullable dan penggunaan anotasi @NotNull
-Pada @JoinColumn di atribut Course, name berguna untuk menyatakan nama dari foreign key column. Lalu, referencedColumnName berguna untuk mencari nama dari column yang direferensi oleh foreign key column. Kemudian, nullable untuk menyatakan apakah foreign key kolomnya null atau tidak. Perbedaan dari nullable dengan anotasi @NotNull adalah nullable hanya menambahkan batasan null yang true / false ke definisi tabel, sedangkan anotasi @NotNull memeriksa apakah atributnya bukan null.
+
+#### Pada @JoinColumn di atribut Course, name berguna untuk menyatakan nama dari foreign key column. Lalu, referencedColumnName berguna untuk mencari nama dari column yang direferensi oleh foreign key column. Kemudian, nullable untuk menyatakan apakah foreign key kolomnya null atau tidak. Perbedaan dari nullable dengan anotasi @NotNull adalah nullable hanya menambahkan batasan null yang true / false ke definisi tabel, sedangkan anotasi @NotNull memeriksa apakah atributnya bukan null.
 
 
 ### Pertanyaan 5: Jelaskan kegunaan FetchType.LAZY, CascadeType.ALL, dan FetchType.EAGER
@@ -109,51 +156,55 @@ Pada @JoinColumn di atribut Course, name berguna untuk menyatakan nama dari fore
 
 #### FetchType.EAGER berisi seluruh data java objects yang telah di-fetch langsung. fetchtype ini akan melakukan fetch-nya diawal. Berbeda dengan tipe LAZY, tipe ini digunakan untuk relasi many-to-one atau one-to-one.
 
-
-
-
-
-
 ---
 ## Tutorial 2
 ### Pertanyaan 1: Cobalah untuk menambahkan sebuah Course dengan mengakses link berikut: http://localhost:8080/course/add?code=APAP&nameCourse=APAP%20Tutorial2&description=2020%20Fasilkom&jumlahSks=3 Apa yang terjadi? Jelaskan mengapa hal tersebut dapat terjadi?
-Jika link tersebut diakses akan memunculkan Whitelabel Error Page Service Error 500. Hal ini dikarenakan sudah ada perintah return "add-course" pada controller. Controller merupakan file yang berfungsi untuk melakukan mapping dari request yang diinput, kemudian akan diminta untuk memanggil template html yang akan direturn. Sedangkan html "add-course" belum dibuat, sehingga hal ini akan menyebabkan error.
+
+#### Jika link tersebut diakses akan memunculkan Whitelabel Error Page Service Error 500. Hal ini dikarenakan sudah ada perintah return "add-course" pada controller. Controller merupakan file yang berfungsi untuk melakukan mapping dari request yang diinput, kemudian akan diminta untuk memanggil template html yang akan direturn. Sedangkan html "add-course" belum dibuat, sehingga hal ini akan menyebabkan error.
 
 ### Pertanyaan 2: Menurut kamu anotasi @Autowired pada class Controller tersebut merupakan implementasi dari konsep apa? Dan jelaskan secara singkat cara kerja @Autowired tersebut dalam konteks service dan controller yang telah kamu buat
- Anotasi @Autowired pada Controller merupakan implementasi dari konsep dependancy injection. @Autowired dapat memasukkan dependensi objek secara implisit. Sehingga, @Autowired pada CourseController tidak perlu dibuat constructor, setter, dan getter. Hal ini dikarenakan @Autowired otomatis mencari service yang mengimplementasikan interface CourseService.
+
+#### Anotasi @Autowired pada Controller merupakan implementasi dari konsep dependancy injection. @Autowired dapat memasukkan dependensi objek secara implisit. Sehingga, @Autowired pada CourseController tidak perlu dibuat constructor, setter, dan getter. Hal ini dikarenakan @Autowired otomatis mencari service yang mengimplementasikan interface CourseService.
 
 ### Pertanyaan 3: Cobalah untuk menambahkan sebuah Course dengan mengakses link berikut: http://localhost:8080/course/add?code=APAP&nameCourse=APAP%20Tutorial2&jumlahSks=3   Apa yang terjadi? Jelaskan mengapa hal tersebut dapat terjadi.
-Jika link tersebut diakses akan memunculkan Whitelabel Error Page type=Bad Request status=400. Hal ini dikarenakan suatu parameter tidak dicantumkan. Sedangkan seluruh atribut harus terisi dan tidak boleh null.
+
+#### Jika link tersebut diakses akan memunculkan Whitelabel Error Page type=Bad Request status=400. Hal ini dikarenakan suatu parameter tidak dicantumkan. Sedangkan seluruh atribut harus terisi dan tidak boleh null.
 
 ### Pertanyaan 4: Jika Papa APAP ingin melihat Course dengan kode APAP, link apa yang harus diakses?
-http://localhost:8080/course/view?code=APAP 
+#### http://localhost:8080/course/view?code=APAP 
 
 ### Pertanyaan 5: Tambahkan 1 contoh Course lainnya sesukamu. Lalu cobalah untuk mengakses http://localhost:8080/course/viewAll  , apa yang akan ditampilkan? Sertakan juga bukti screenshotmu. 
-Akan bertambah course lain
 
-https://drive.google.com/file/d/1NGZj0VJENBv4pRQjVcsHjZRmML3h7E9O/view?usp=sharing
+#### Akan bertambah course lain
+
+#### https://drive.google.com/file/d/1NGZj0VJENBv4pRQjVcsHjZRmML3h7E9O/view?usp=sharing
 
 ---
 ## Tutorial 1
 ### What I have learned today
-Pada tutorial ini, saya mempelajari tentang cara mengoperasikan Git secara lebih advance. Sebelumnya, saya pernah melakukan hal berikut saat mengerjakan TK Basdat oleh teman saya dari Ilmu Komputer. Lalu, saya juga baru memahami secara dasar tentang Java Springboot. 
+#### Pada tutorial ini, saya mempelajari tentang cara mengoperasikan Git secara lebih advance. Sebelumnya, saya pernah melakukan hal berikut saat mengerjakan TK Basdat oleh teman saya dari Ilmu Komputer. Lalu, saya juga baru memahami secara dasar tentang Java Springboot. 
+
 ### GitLab
-1. Apa itu Issue Tracker? Apa saja masalah yang dapat diselesaikan dengan Issue Tracker?
+### Pertanyaan 1: Apa itu Issue Tracker? Apa saja masalah yang dapat diselesaikan dengan Issue Tracker?
 #### Issue Tracker adalah fitur Gitlab yang akan menandakan letak isu yang terjadi saat mengoperasikan git. Masalah umum seperti commit, branch, merge, dan lain-lain akan dinotice oleh Issue Tracker
-2. Apa perbedaan dari git merge dan git merge --squash?
+
+### Pertanyaan 2: Apa perbedaan dari git merge dan git merge --squash?
 #### git merge hanya melakukan merging git, sedangkan git merge --squash seperti merging yang simpel yang tidak akan membuat commit di dalam history branch
-3. Apa keunggulan menggunakan Version Control System seperti Git dalam pengembangan
-suatu aplikasi?
+
+### Pertanyaan 3: Apa keunggulan menggunakan Version Control System seperti Git dalam pengembangan suatu aplikasi?
 #### Menggunakan Git akan mempermudah dalam mengorganize repository. Git juga sudah sangat familiar oleh banyak orang sehingga tidak akan susah dalam menggunakan Git
 ### Spring
-4. Apa itu library & dependency?
+
+### Pertanyaan 4: Apa itu library & dependency?
 #### Library dan dependency adalah sesuatu yang berkaitan tetapi tidak sama. Kode pada library akan menjadi sebuah dependency ketika project lain digunakan, dan tidak akan menjadi dependency oleh project yang lain.
-5. Apa itu Gradle? Mengapa kita menggunakan Gradle? Apakah ada alternatif dari Gradle?
+
+### Pertanyaan 5: Apa itu Gradle? Mengapa kita menggunakan Gradle? Apakah ada alternatif dari Gradle?
 #### Gradle adalah sebuah program yang berfungsi untuk melakukan build secara otomatis. Karena itu, Gradle sering disebut sebagai build-tool. Alasan menggunakan Gradle adalah agar pekerjaan dalam melakukan build akan dapat otomatis dilakukan. Aplikasi alternatif dari Gradle adalah CMake, SCons, GNU Make, Maven, Meson, Buck, Ant, Cake, Rake, dan SBT.
-6. Selain untuk pengembangan web, apa saja yang bisa dikembangkan dengan Spring
-framework?
+
+### Pertanyaan 6: Selain untuk pengembangan web, apa saja yang bisa dikembangkan dengan Spring framework?
 #### Bisa digunakan untuk mengembangkan enterprise
-7. Apa perbedaan dari @RequestParam dan @PathVariable? Kapan sebaiknya menggunakan @RequestParam atau @PathVariable?
+
+### Pertanyaan 7: Apa perbedaan dari @RequestParam dan @PathVariable? Kapan sebaiknya menggunakan @RequestParam atau @PathVariable?
 #### @RequestParam digunakan untuk membaca data formulir HTML yang disediakan oleh pengguna dan mengikatnya ke parameter permintaan.
 #### @Pathvariable: Anotasi ini digunakan untuk menangani variabel template dalam pemetaan URI permintaan, dan menggunakannya sebagai parameter metode
 #### @RequestParam digunakan jika anotasi parameter belum ditentukan, @Pathvariable digunakan jika parameter sudah ada
diff --git a/belajarbelajar/build.gradle b/belajarbelajar/build.gradle
index 6dfb47f..dbc5b36 100644
--- a/belajarbelajar/build.gradle
+++ b/belajarbelajar/build.gradle
@@ -14,16 +14,18 @@ repositories {
 
 dependencies {
 	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
-	implementation 'org.springframework.boot:spring-boot-starter-web'
 	developmentOnly 'org.springframework.boot:spring-boot-devtools'
 	testImplementation 'org.springframework.boot:spring-boot-starter-test'
 	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
 	implementation 'mysql:mysql-connector-java:5.1.6'
+	implementation("org.projectlombok:lombok:1.18.24")
 	compileOnly("org.projectlombok:lombok:1.18.24")
 	annotationProcessor('org.projectlombok:lombok:1.18.24')
 	implementation 'org.springframework.boot:spring-boot-starter-validation:2.7.3'
 	implementation 'com.fasterxml.jackson.core:jackson-databind'
 	implementation 'org.springframework.boot:spring-boot-starter-webflux'
+	implementation 'org.springframework.boot:spring-boot-starter-security'
+	implementation 'org.springframework.boot:spring-boot-starter-web'
 }
 
 tasks.named('test') {
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/controller/BaseController.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/controller/BaseController.java
deleted file mode 100644
index dffefdd..0000000
--- a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/controller/BaseController.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package apap.tutorial.belajarbelajar.controller;
-
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.GetMapping;
-
-@Controller
-public class BaseController {
-    @GetMapping("/")
-    private String Home() {
-        return "home";
-    }
-}
\ No newline at end of file
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/controller/PageController.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/controller/PageController.java
new file mode 100644
index 0000000..9562431
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/controller/PageController.java
@@ -0,0 +1,112 @@
+package apap.tutorial.belajarbelajar.controller;
+
+import apap.tutorial.belajarbelajar.model.UserModel;
+import apap.tutorial.belajarbelajar.security.xml.Attributes;
+import apap.tutorial.belajarbelajar.security.xml.ServiceResponse;
+import apap.tutorial.belajarbelajar.service.PengajarService;
+import apap.tutorial.belajarbelajar.service.RoleService;
+import apap.tutorial.belajarbelajar.service.UserService;
+import apap.tutorial.belajarbelajar.setting.Setting;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.servlet.ModelAndView;
+
+import org.springframework.security.core.Authentication;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+
+import java.security.Principal;
+
+@Controller
+public class PageController {
+    @RequestMapping("/")
+    public String home(Model model) {
+        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+        User user = (User) auth.getPrincipal();
+        UserModel userModel = userService.getUserByUsername(user.getUsername());
+        String role = userService.getUserByUsername(user.getUsername()).getRole().getRole();
+        model.addAttribute("role", role);
+        model.addAttribute("user", userModel);
+        return "home";
+    }
+
+    @RequestMapping("/login")
+    public String login(){
+        return "login";
+    }
+
+    private WebClient webClient = WebClient.builder().build();
+
+    @Autowired
+    private UserService userService;
+    @Autowired
+    private RoleService roleService;
+
+    @GetMapping("/validate-ticket")
+    public ModelAndView adminLoginSSO(
+            @RequestParam(value = "ticket", required = false) String ticket,
+            HttpServletRequest request
+    ){
+        ServiceResponse serviceResponse = this.webClient.get().uri(
+                String.format(
+                        Setting.SERVER_VALIDATE_TICKET,
+                        ticket,
+                        Setting.CLIENT_LOGIN
+                )
+        ).retrieve().bodyToMono(ServiceResponse.class).block();
+
+        Attributes attributes = serviceResponse.getAuthenticationSuccess().getAttributes();
+        String username = serviceResponse.getAuthenticationSuccess().getUser();
+
+        UserModel user = userService.getUserByUsername(username);
+
+        if(user == null){
+            user = new UserModel();
+            user.setEmail(username + "@ui.ac.id");
+            user.setNama(attributes.getNama());
+            user.setPassword("belajarbelajar");
+            user.setUsername(username);
+            user.setIsSso(true);
+            user.setRole(roleService.getById(1L));
+            userService.addUser(user);
+        }
+
+        Authentication authentication = new UsernamePasswordAuthenticationToken(username, "belajarbelajar");
+        SecurityContext securityContext = SecurityContextHolder.getContext();
+        securityContext.setAuthentication(authentication);
+
+        HttpSession httpSession = request.getSession(true);
+        httpSession.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, securityContext);
+
+        return new ModelAndView("redirect:/");
+    }
+
+    @GetMapping(value = "/login-sso")
+    public ModelAndView loginSSO(){
+        return new ModelAndView("redirect:" + Setting.SERVER_LOGIN + Setting.CLIENT_LOGIN);
+    }
+
+    @GetMapping(value = "/logout-sso")
+    public ModelAndView logoutSSO(Principal principal){
+        UserModel user = userService.getUserByUsername(principal.getName());
+        if (user.getIsSso() == false){
+            return new ModelAndView("redirect:/logout");
+
+        }
+        return new ModelAndView("redirect:" + Setting.SERVER_LOGOUT + Setting.CLIENT_LOGOUT);
+    }
+}
+
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/controller/UserController.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/controller/UserController.java
new file mode 100644
index 0000000..e778ad6
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/controller/UserController.java
@@ -0,0 +1,90 @@
+package apap.tutorial.belajarbelajar.controller;
+
+import apap.tutorial.belajarbelajar.model.RoleModel;
+import apap.tutorial.belajarbelajar.model.UserModel;
+import apap.tutorial.belajarbelajar.service.RoleService;
+import apap.tutorial.belajarbelajar.service.UserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@Controller
+@RequestMapping("/user")
+public class UserController {
+
+    @Autowired
+    private UserService userService;
+    @Autowired
+    private RoleService roleService;
+
+    @GetMapping(value = "/add")
+    private String addUserFormPage(Model model){
+        UserModel user = new UserModel();
+        List<RoleModel> listRole = roleService.findAll();
+        model.addAttribute("user", user);
+        model.addAttribute("listRole", listRole);
+        return "form-add-user";
+
+    }
+
+    @PostMapping(value = "/add")
+    private String addUserSubmit(@ModelAttribute UserModel user, Model model){
+        user.setIsSso(false);
+        userService.addUser(user);
+        model.addAttribute("user", user);
+        return "redirect:/";
+    }
+    @GetMapping("/delete/{id}")
+    public String deleteUser (@PathVariable String id, Model model) {
+
+        UserModel user = userService.getUserById(id);
+        userService.deleteUser(user);
+        model.addAttribute( "id",user.getId());
+        return "delete-user";
+    }
+
+    @GetMapping("/viewall")
+    public String listUser(Model model) {
+        List<UserModel> listUser = userService.getListUser();
+
+        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
+        User user = (User) auth.getPrincipal();
+        String username = user.getUsername();
+        UserModel userModel = userService.getUserByUsername(username);
+
+        model.addAttribute("listUser", listUser);
+        model.addAttribute("user", userModel);
+
+        return "viewall-user";
+    }
+    @PostMapping("/update-password")
+    public String updatePassword(@ModelAttribute UserModel userModel, String newPassword, String confPassword, Model model){
+        UserModel user = userService.getUserByUsername(userModel.getUsername());
+        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+        if (passwordEncoder.matches(userModel.getPassword(), user.getPassword())){
+            if (newPassword.equals(confPassword)){
+                user.setPassword(newPassword);
+                userService.addUser(user);
+                return "sukses-update-password";
+            } else {
+                model.addAttribute("message", "password yang dikonfirmasi tidak sama. Ulangi!");
+            }
+        }else {
+            model.addAttribute("message", "password lama invalid. Ulangi!");
+        }
+        return "form-update-password";
+    }
+    @GetMapping("/update-password")
+    public String getUpdatePassword(){
+        return "form-update-password";
+    }
+}
+
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/model/RoleModel.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/model/RoleModel.java
new file mode 100644
index 0000000..277160c
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/model/RoleModel.java
@@ -0,0 +1,34 @@
+package apap.tutorial.belajarbelajar.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.annotations.GenericGenerator;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
+
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+import java.util.List;
+
+@Setter
+@Getter
+@Entity
+@Table(name = "role")
+public class RoleModel implements Serializable {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+
+    @NotNull
+    @Size(max = 50)
+    @Column(name = "role", nullable = false)
+    private String role;
+
+    @OneToMany(mappedBy = "role", fetch = FetchType.LAZY)
+    @OnDelete(action = OnDeleteAction.CASCADE)
+    @JsonIgnore
+    private List<UserModel> userRole;
+}
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/model/UserModel.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/model/UserModel.java
new file mode 100644
index 0000000..70ff579
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/model/UserModel.java
@@ -0,0 +1,56 @@
+package apap.tutorial.belajarbelajar.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Getter;
+import lombok.Setter;
+import org.hibernate.annotations.GenericGenerator;
+import org.hibernate.annotations.OnDelete;
+import org.hibernate.annotations.OnDeleteAction;
+
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+
+@Setter
+@Getter
+@Entity
+@Table (name = "user")
+public class UserModel implements Serializable {
+    @Id
+    @GeneratedValue(generator = "system-uuid")
+    @GenericGenerator(name = "system-uuid", strategy = "uuid")
+    private String id;
+
+    @NotNull
+    @Size(max = 50)
+    @Column(name = "username", nullable = false, unique = true)
+    private String username;
+
+    @NotNull
+    @Column(name = "is_Sso", nullable = false)
+    private Boolean isSso;
+
+    @NotNull
+    @Size(max = 50)
+    @Column(name = "nama", nullable = false)
+    private String nama;
+
+    @NotNull
+    @Size(max = 50)
+    @Column(name = "email", nullable = false)
+    private String email;
+
+    @NotNull
+    @Lob
+    @Column(name = "password", nullable = false)
+    private String password;
+
+    @ManyToOne(fetch = FetchType.EAGER)
+    @JoinColumn(name = "id_role", referencedColumnName = "id", nullable = false)
+    @OnDelete(action = OnDeleteAction.CASCADE)
+    @JsonIgnore
+    private RoleModel role;
+
+
+}
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/repository/RoleDb.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/repository/RoleDb.java
new file mode 100644
index 0000000..907bc8e
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/repository/RoleDb.java
@@ -0,0 +1,12 @@
+package apap.tutorial.belajarbelajar.repository;
+import apap.tutorial.belajarbelajar.model.RoleModel;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface RoleDb extends JpaRepository<RoleModel, Long>{
+    Optional<RoleModel> findById(Long id);
+}
\ No newline at end of file
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/repository/UserDb.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/repository/UserDb.java
new file mode 100644
index 0000000..ca3b1cb
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/repository/UserDb.java
@@ -0,0 +1,13 @@
+package apap.tutorial.belajarbelajar.repository;
+
+import  apap.tutorial.belajarbelajar.model.UserModel;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface UserDb extends JpaRepository<UserModel,Long> {
+    UserModel findByUsername(String username);
+    Optional<UserModel> findById(String id);
+}
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/UserDetailsServiceImpl.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/UserDetailsServiceImpl.java
new file mode 100644
index 0000000..098875d
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/UserDetailsServiceImpl.java
@@ -0,0 +1,27 @@
+package apap.tutorial.belajarbelajar.security;//package apap.tutorial.belajarbelajar.service;
+
+import apap.tutorial.belajarbelajar.model.UserModel;
+import apap.tutorial.belajarbelajar.repository.UserDb;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+import java.util.HashSet;
+import java.util.Set;
+
+@Service
+public class UserDetailsServiceImpl implements UserDetailsService {
+    @Autowired
+    private UserDb userDB;
+    @Override
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+        UserModel user = userDB.findByUsername(username);
+        Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
+        grantedAuthorities.add(new SimpleGrantedAuthority(user.getRole().getRole()));
+        return new User(user.getUsername(), user.getPassword(), grantedAuthorities);
+    }
+}
\ No newline at end of file
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/WebSecurityConfig.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/WebSecurityConfig.java
new file mode 100644
index 0000000..f3446ec
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/WebSecurityConfig.java
@@ -0,0 +1,61 @@
+package apap.tutorial.belajarbelajar.security;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+
+@Configuration
+@EnableWebSecurity
+public class WebSecurityConfig {
+
+    @Bean
+    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
+
+        http
+                .authorizeRequests()
+                .antMatchers("/css/**").permitAll()
+                .antMatchers("/js/**").permitAll()
+                .antMatchers("/login-sso", "/validate-ticket").permitAll()
+                .antMatchers("/user/viewall").hasAuthority("Admin")
+                .antMatchers("/user/add").hasAuthority("Admin")
+                .antMatchers("/user/delete").hasAuthority("Admin")
+                .antMatchers("/penyelenggara/add").hasAuthority("Manajer")
+                .anyRequest().authenticated()
+                .and()
+                .formLogin()
+                .loginPage("/login").permitAll()
+                .and()
+                .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
+                .logoutSuccessUrl("/login").permitAll();
+        return http.build();
+    }
+
+    @Bean
+    public BCryptPasswordEncoder encoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+//    @Autowired
+//    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
+//        auth.inMemoryAuthentication()
+//                .passwordEncoder(encoder())
+//                .withUser("hilmi")
+//                .password(encoder().encode("apapABC"))
+//                .roles("USER");
+//    }
+
+    @Autowired
+    private UserDetailsService userDetailsService;
+
+    @Autowired
+    public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
+        auth.userDetailsService(userDetailsService).passwordEncoder(encoder());
+    }
+}
\ No newline at end of file
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/xml/Attributes.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/xml/Attributes.java
new file mode 100644
index 0000000..c88f459
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/xml/Attributes.java
@@ -0,0 +1,29 @@
+package apap.tutorial.belajarbelajar.security.xml;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+@Setter
+@Getter
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Attributes {
+
+    @XmlElement(namespace = "http://www.yale.edu/tp/cas")
+    private String ldap_cn;
+
+    @XmlElement(namespace = "http://www.yale.edu/tp/cas")
+    private  String kd_org;
+
+    @XmlElement(namespace = "http://www.yale.edu/tp/cas")
+    private String peran_user;
+
+    @XmlElement(namespace = "http://www.yale.edu/tp/cas")
+    private String nama;
+
+    @XmlElement(namespace = "http://www.yale.edu/tp/cas")
+    private String npm;
+}
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/xml/AuthenticationSuccess.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/xml/AuthenticationSuccess.java
new file mode 100644
index 0000000..047473a
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/xml/AuthenticationSuccess.java
@@ -0,0 +1,20 @@
+package apap.tutorial.belajarbelajar.security.xml;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+@Setter
+@Getter
+@XmlAccessorType(XmlAccessType.FIELD)
+public class AuthenticationSuccess {
+
+    @XmlElement(name = "user", namespace = "http://www.yale.edu/tp/cas")
+    private String user;
+
+    @XmlElement(name = "attributes", namespace = "http://www.yale.edu/tp/cas")
+    private Attributes attributes;
+}
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/xml/ServiceResponse.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/xml/ServiceResponse.java
new file mode 100644
index 0000000..41764ae
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/security/xml/ServiceResponse.java
@@ -0,0 +1,23 @@
+package apap.tutorial.belajarbelajar.security.xml;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+
+@Setter
+@Getter
+@XmlRootElement(name = "serviceResponse", namespace = "http://www.yale.edu/tp/cas")
+@XmlAccessorType(XmlAccessType.FIELD)
+public class ServiceResponse {
+
+    @XmlElement(name = "authenticationFailure" , namespace = "http://www.yale.edu/tp/cas")
+    private String authenticationFailure;
+
+    @XmlElement(name= "authenticationSuccess", namespace = "http://www.yale.edu/tp/cas")
+    private AuthenticationSuccess authenticationSuccess;
+}
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/RoleService.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/RoleService.java
new file mode 100644
index 0000000..e6c96d1
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/RoleService.java
@@ -0,0 +1,8 @@
+package apap.tutorial.belajarbelajar.service;
+import apap.tutorial.belajarbelajar.model.RoleModel;
+import java.util.List;
+
+public interface RoleService {
+    List<RoleModel> findAll();
+    RoleModel getById(Long id);
+}
\ No newline at end of file
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/RoleServiceImpl.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/RoleServiceImpl.java
new file mode 100644
index 0000000..b39b362
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/RoleServiceImpl.java
@@ -0,0 +1,30 @@
+package apap.tutorial.belajarbelajar.service;
+
+import apap.tutorial.belajarbelajar.model.RoleModel;
+import apap.tutorial.belajarbelajar.repository.RoleDb;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Optional;
+
+@Service
+public class RoleServiceImpl implements RoleService{
+    @Autowired
+    private RoleDb roleDb;
+
+    @Override
+    public List<RoleModel> findAll(){
+        return roleDb.findAll();
+    }
+
+    @Override
+    public RoleModel getById(Long id) {
+        Optional<RoleModel> role = roleDb.findById(id);
+        if(role.isPresent()) {
+            return role.get();
+        } else return null;
+    }
+
+
+}
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/UserService.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/UserService.java
new file mode 100644
index 0000000..b46b34a
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/UserService.java
@@ -0,0 +1,23 @@
+package apap.tutorial.belajarbelajar.service;
+
+import apap.tutorial.belajarbelajar.model.UserModel;
+
+import java.util.List;
+
+public interface UserService {
+    UserModel addUser(UserModel user);
+    public String encrypt(String password);
+    UserModel getUserByUsername(String username);
+
+    List<UserModel> getListUser();
+
+    UserModel getUserById(String id);
+
+    void deleteUser(UserModel user);
+
+    Boolean checkOldPassword(UserModel user, String password);
+
+    void changePassword(UserModel user, String password);
+
+    Boolean checkNewPassword(String password);
+}
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/UserServiceImpl.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/UserServiceImpl.java
new file mode 100644
index 0000000..8ae7857
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/service/UserServiceImpl.java
@@ -0,0 +1,76 @@
+package apap.tutorial.belajarbelajar.service;
+
+import apap.tutorial.belajarbelajar.model.UserModel;
+import apap.tutorial.belajarbelajar.repository.UserDb;
+import org.apache.catalina.User;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Service;
+
+import java.util.Optional;
+import java.util.List;
+
+@Service
+public class UserServiceImpl implements UserService {
+    @Autowired
+    private UserDb userDb;
+
+    @Override
+    public UserModel addUser(UserModel user){
+        String pass = encrypt(user.getPassword());
+        user.setPassword(pass);
+        return userDb.save(user);
+    }
+
+    @Override
+    public String encrypt (String password){
+        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+        String hashedPassword = passwordEncoder.encode(password);
+        return hashedPassword;
+    }
+
+    @Override
+    public UserModel getUserByUsername(String username) {
+        UserModel user = userDb.findByUsername(username);
+        return user;
+    }
+    @Override
+    public List<UserModel> getListUser() {
+        return userDb.findAll();
+    }
+    @Override
+    public UserModel getUserById(String id) {
+        Optional<UserModel> user = userDb.findById(id);
+        if (user.isPresent()) {
+            return user.get();
+        }
+        return null;
+    }
+    @Override
+    public void deleteUser(UserModel user) {
+        userDb.delete(user);
+    }
+    @Override
+    public Boolean checkOldPassword(UserModel user, String password) {
+        return new BCryptPasswordEncoder().matches(password, user.getPassword());
+    }
+
+    @Override
+    public void changePassword(UserModel user, String password) {
+        String hashedPassword = encrypt(password);
+        user.setPassword(hashedPassword);
+        userDb.save(user);
+    }
+
+    @Override
+    public Boolean checkNewPassword(String password) {
+        String huruf = ".*[A-Za-z].*";
+        String angka = ".*[0-9].*";
+        String simbol = ".*[!@#$%&*()_+=|<>?{}\\[\\]~-].*";
+        if(password.length()<8 || !password.matches(huruf) || !password.matches(angka) || !password.matches(simbol)){
+            return false;
+        }
+        return true;
+    }
+
+}
diff --git a/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/setting/Setting.java b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/setting/Setting.java
new file mode 100644
index 0000000..37a2718
--- /dev/null
+++ b/belajarbelajar/src/main/java/apap/tutorial/belajarbelajar/setting/Setting.java
@@ -0,0 +1,12 @@
+package apap.tutorial.belajarbelajar.setting;
+
+public class Setting {
+    final public static String CLIENT_BASE_URL = "http://localhost:8080";
+    final public static String CLIENT_LOGIN = CLIENT_BASE_URL + "/validate-ticket";
+    final public static String CLIENT_LOGOUT= CLIENT_BASE_URL + "/logout";
+
+    final public static String SERVER_BASE_URL = "https://sso.ui.ac.id/cas2";
+    final public static String SERVER_LOGIN = SERVER_BASE_URL + "/login?service=";
+    final public static String SERVER_LOGOUT = SERVER_BASE_URL + "/logout?url=";
+    final public static String SERVER_VALIDATE_TICKET = SERVER_BASE_URL + "/serviceValidate?ticket=%s&service=%s";
+}
diff --git a/belajarbelajar/src/main/resources/application.properties b/belajarbelajar/src/main/resources/application.properties
index 38030bd..ae57aa1 100644
--- a/belajarbelajar/src/main/resources/application.properties
+++ b/belajarbelajar/src/main/resources/application.properties
@@ -9,10 +9,13 @@ spring.datasource.url=jdbc:mysql://localhost:3306/belajarbelajar?useSSL=false&se
 spring.datasource.username=root
 spring.datasource.password=
 
+#error bean
+spring.main.allow-circular-references=true
+
 #optimize query untuk db MySQL
 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
 
 #pembuatan database (create || create drop || validate || update)
 spring.jpa.hibernate.ddl-auto=update
 
-server.port=2020
+server.port=8080
diff --git a/belajarbelajar/src/main/resources/templates/delete-user.html b/belajarbelajar/src/main/resources/templates/delete-user.html
new file mode 100644
index 0000000..4b0fbeb
--- /dev/null
+++ b/belajarbelajar/src/main/resources/templates/delete-user.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://thymeleaf.org">
+
+<head>
+  <title>Deleted User</title>
+  <object th:include="fragments/fragment :: css" th:remove="tag"></object>
+  <object th:include="fragments/fragment :: js" th:remove="tag"></object>
+</head>
+<body>
+<nav th:replace="fragments/fragment :: navbar"></nav>
+<div class="container">
+  <div class="card m-4 p-4">
+    <div class="card-body">
+      <div class="justify-content-center">
+        <br>
+        <h2 th:text="'User berhasil dihapus.'">
+        </h2>
+        <a class="btn btn-primary" th:href="@{/user/viewall}">Kembali</a>
+      </div>
+    </div>
+  </div>
+</div>
+
+</body>
+
+</html>
\ No newline at end of file
diff --git a/belajarbelajar/src/main/resources/templates/error/400.html b/belajarbelajar/src/main/resources/templates/error/400.html
index 5c2de6b..033884a 100644
--- a/belajarbelajar/src/main/resources/templates/error/400.html
+++ b/belajarbelajar/src/main/resources/templates/error/400.html
@@ -2,7 +2,7 @@
 <html lang="en" xmlns:th="http://thymeleaf.org">
 <head>
   <meta charset="UTF-8">
-  <title>404 not found</title>
+  <title>400 not found</title>
   <object th:include="fragments/fragment :: css" th:remove="tag"></object>
   <object th:include="fragments/fragment :: js" th:remove="tag"></object>
 
diff --git a/belajarbelajar/src/main/resources/templates/error/403.html b/belajarbelajar/src/main/resources/templates/error/403.html
new file mode 100644
index 0000000..34318c5
--- /dev/null
+++ b/belajarbelajar/src/main/resources/templates/error/403.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://thymeleaf.org">
+<head>
+    <meta charset="UTF-8">
+    <title>404 not found</title>
+    <object th:include="fragments/fragment :: css" th:remove="tag"></object>
+    <object th:include="fragments/fragment :: js" th:remove="tag"></object>
+
+</head>
+<body>
+<nav th:replace="fragments/fragment :: navbar"></nav>
+<div class="container-fluid">
+    <h2>NO ACCESS!</h2>
+    <a th:href="@{/}">Kembali ke home</a>
+</div>
+</body>
+</html>
diff --git a/belajarbelajar/src/main/resources/templates/error/405.html b/belajarbelajar/src/main/resources/templates/error/405.html
index 5c2de6b..97390b4 100644
--- a/belajarbelajar/src/main/resources/templates/error/405.html
+++ b/belajarbelajar/src/main/resources/templates/error/405.html
@@ -2,7 +2,7 @@
 <html lang="en" xmlns:th="http://thymeleaf.org">
 <head>
   <meta charset="UTF-8">
-  <title>404 not found</title>
+  <title>405 not found</title>
   <object th:include="fragments/fragment :: css" th:remove="tag"></object>
   <object th:include="fragments/fragment :: js" th:remove="tag"></object>
 
diff --git a/belajarbelajar/src/main/resources/templates/error/500.html b/belajarbelajar/src/main/resources/templates/error/500.html
index 5c2de6b..159fba7 100644
--- a/belajarbelajar/src/main/resources/templates/error/500.html
+++ b/belajarbelajar/src/main/resources/templates/error/500.html
@@ -2,7 +2,7 @@
 <html lang="en" xmlns:th="http://thymeleaf.org">
 <head>
   <meta charset="UTF-8">
-  <title>404 not found</title>
+  <title>500 not found</title>
   <object th:include="fragments/fragment :: css" th:remove="tag"></object>
   <object th:include="fragments/fragment :: js" th:remove="tag"></object>
 
diff --git a/belajarbelajar/src/main/resources/templates/form-add-user.html b/belajarbelajar/src/main/resources/templates/form-add-user.html
new file mode 100644
index 0000000..10898a3
--- /dev/null
+++ b/belajarbelajar/src/main/resources/templates/form-add-user.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://thymeleaf.org">
+<head>
+  <title>Tambah User</title>
+  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" rel="stylesheet"
+        integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
+  <object th:include="fragments/fragment :: css" th:remove="tag"></object>
+  <object th:include="fragments/fragment :: js" th:remove="tag"></object>
+
+<body>
+<nav th:replace="fragments/fragment :: navbar"></nav>
+
+<div class="container">
+  <div class="card m-4 p-4">
+    <div class="card-body">
+      <div class="justify-content-center">
+        <h2>Tambah User Baru</h2>
+        <br>
+        <form th:action="@{/user/add}" th:object="${user}" method="POST">
+          <label>Username</label>
+          <input type="text" name="username" class="form-control"/>
+
+          <label>Nama</label>
+          <input type="text" name="nama" class="form-control"/>
+
+          <label>E-mail</label>
+          <input type="text" name="email" class="form-control"/>
+
+          <label>Password</label>
+          <input type="text" name="password" class="form-control"/>
+
+          <label>Role</label>
+          <select name="role" class="form-control">
+            <option selected value="">--Pilih Role--</option>
+            <option th:each="role : ${listRole}"
+                    th:value="${role.id}"
+                    th:text="${role.role}">
+            </option>
+          </select>
+          <br>
+          <button type="submit" class="btn btn-primary">Submit</button>
+          <a class="btn btn-link" href="/">Home</a>
+        </form>
+      </div>
+    </div>
+  </div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/belajarbelajar/src/main/resources/templates/form-update-password.html b/belajarbelajar/src/main/resources/templates/form-update-password.html
new file mode 100644
index 0000000..96ab436
--- /dev/null
+++ b/belajarbelajar/src/main/resources/templates/form-update-password.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://thymeleaf.org">
+
+<head>
+  <meta charset="UTF-8">
+  <title>21 Cineplux</title>
+  <object th:include="fragments/fragment :: css" th:remove="tag"></object>
+  <object th:include="fragments/fragment :: js" th:remove="tag"></object>
+</head>
+
+<body>
+<nav th:replace="fragments/fragment :: navbar (pagetitle='View All')"></nav>
+<div class="container">
+  <div class="row justify-content-center">
+    <div class="col-md-6">
+      <div class="card">
+        <div class="card-header">Ubah Password</div>
+        <div class="m-auto row text-danger font-weight-bold">
+          <div th:text="${message}"></div>
+        </div>
+        <div class="card-body">
+          <form th:action="@{/user/update-password}" method="POST">
+            <input type="hidden" name="username" th:value="${#httpServletRequest.userPrincipal.name}">
+
+            <label>Password Lama</label>
+            <input required type="password" name="password" class="form-control"/>
+
+            <label>Password Baru</label>
+            <input required type="password" name="newPassword" class="form-control" pattern="^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$" title="password user harus mengandung angka, huruf besar, huruf kecil, dan simbol serta minimal memiliki 8 karakter"/>
+
+            <label>Konfirmasi Password Baru</label>
+            <input required type="password" name="confPassword" class="form-control" pattern="^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$" title="password user harus mengandung angka, huruf besar, huruf kecil, dan simbol serta minimal memiliki 8 karakter"/>
+
+            <br>
+            <button type="submit" class="btn btn-outline-success">Simpan</button>
+            <a class="btn btn-outline-success" href="/">Home</a>
+          </form>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+
+</body>
+
+</html>
\ No newline at end of file
diff --git a/belajarbelajar/src/main/resources/templates/fragments/fragment.html b/belajarbelajar/src/main/resources/templates/fragments/fragment.html
index 1003095..aaf8a83 100644
--- a/belajarbelajar/src/main/resources/templates/fragments/fragment.html
+++ b/belajarbelajar/src/main/resources/templates/fragments/fragment.html
@@ -66,6 +66,9 @@
              name="code" placeholder="Code Course" aria-label="Search">
       <button class="btn btn-outline-primary my-2 my-sm-0" type="submit">Search</button>
     </form>
+    <ul class="navbar-nav pull-right">
+      <a class="nav-item nav-link text-text-secondary" th:href="@{/logout-sso}">Log out</a>
+    </ul>
   </div>
 </nav>
 
diff --git a/belajarbelajar/src/main/resources/templates/home.html b/belajarbelajar/src/main/resources/templates/home.html
index ca7fa62..5481b77 100644
--- a/belajarbelajar/src/main/resources/templates/home.html
+++ b/belajarbelajar/src/main/resources/templates/home.html
@@ -9,6 +9,26 @@
 <body>
 <nav th:replace="fragments/fragment :: navbar"></nav>
 
+<div class="d-flex justify-content-center">
+  <h2 th:text="'Hello '+${#httpServletRequest.remoteUser}+'!'">Login as</h2>
+</div>
+<button type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup"
+        aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation"
+        class="navbar-toggler">
+  <span class="navbar-toggler-icon"></span>
+</button>
+<div class="collapse navbar-collapse">
+  <ul class="navbar-nav mr-auto">
+    <a class="nav-item nav-link active text-secondary" th:href="@{/}"></a>
+    Home <span class="sr-only">(current)</span>
+  </ul>
+  <form class="form-inline my-2 my-lg-0" th:action="@{/agensi/view}" method="GET">
+    <input class="form-control mr-sm-2" type="search" placeholder="Code Course" aria-label="Search"
+           name="codeCourse">
+    <button class="btn btn-outline-primary my-2 my-sm-0" type="submit">Search</button>
+  </form>
+</div>
+</nav>
 <div class="d-flex justify-content-center">
   <div class="m-4">
     <h2>Selamat datang di BelajarBelajar</h2>
@@ -22,6 +42,13 @@
       <a th:href="@{/penyelenggara/viewall}" class="mx-2 btn btn-primary">Lihat semua penyelenggara</a>
       <a th:href="@{/penyelenggara/add}" class="mx-2 btn btn-outline-primary">Tambah penyelenggara</a>
     </div>
+    <div class="my-3 d-flex justify-content-center">
+      <a th:href="@{/user/viewall}" class="mx-2 btn btn-primary">Lihat semua user</a>
+      <a th:href="@{/user/add}" class="mx-2 btn btn-outline-primary">Tambah User Baru</a>
+    </div>
+    <div class="my-3 d-flex justify-content-center">
+      <a th:href="@{/user/update-password}" class="mx-2 btn btn-primary">Update Password</a>
+    </div>
   </div>
 </div>
 
diff --git a/belajarbelajar/src/main/resources/templates/login.html b/belajarbelajar/src/main/resources/templates/login.html
new file mode 100644
index 0000000..f304bd2
--- /dev/null
+++ b/belajarbelajar/src/main/resources/templates/login.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html xmlns:th="http://www.thymeleaf.org">
+<head>
+  <title>Login</title>
+
+  <object th:include="fragments/fragment :: css" th:remove="tag"></object>
+  <object th:include="fragments/fragment :: js" th:remove="tag"></object>
+</head>
+
+<body>
+<div class="container-fluid text-center">
+  <br>
+  <h2>Hello !</h2>
+  <br>
+  <div class="row justify-content-center">
+    <div class="col-md-4">
+      <div class="card">
+        <div class="card-header">
+          Log in
+        </div>
+        <div class="card-body">
+          <div th:if="${param.error}">
+            <span style="color: red">Invalid username and password.</span>
+          </div>
+          <br>
+          <form th:action="@{/login}" method="POST">
+            <div class="row form-group">
+              <label class="col-sm-4">Username:</label>
+              <input type="text" class="col-sm-8 form-control input-sm" name="username">
+            </div>
+            <div class="row form-group">
+              <label class="col-sm-4">Password:</label>
+              <input type="password" class="col-sm-8 form-control input-sm" name="password">
+            </div>
+            <div class="row form-group justify-content-center">
+              <button type="submit" class="btn btn-primary">Sign In</button>
+            </div>
+            <div>
+              atau <a th:href="@{/login-sso}">Masuk sebagai Admin (SSO UI)</a>
+            </div>
+          </form>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+</body>
+</html>
\ No newline at end of file
diff --git a/belajarbelajar/src/main/resources/templates/sukses-update-password.html b/belajarbelajar/src/main/resources/templates/sukses-update-password.html
new file mode 100644
index 0000000..8504d79
--- /dev/null
+++ b/belajarbelajar/src/main/resources/templates/sukses-update-password.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://thymeleaf.org">
+
+<head>
+  <title>Updated Password</title>
+  <object th:include="fragments/fragment :: css" th:remove="tag"></object>
+  <object th:include="fragments/fragment :: js" th:remove="tag"></object>
+</head>
+<body>
+<nav th:replace="fragments/fragment :: navbar"></nav>
+<div class="container">
+  <div class="card m-4 p-4">
+    <div class="card-body">
+      <div class="justify-content-center">
+        <br>
+        <h2 th:text="'Password berhasil diubah'">
+        </h2>
+        <a class="btn btn-primary" th:href="@{/}">Kembali</a>
+      </div>
+    </div>
+  </div>
+</div>
+
+</body>
+
+</html>
\ No newline at end of file
diff --git a/belajarbelajar/src/main/resources/templates/viewall-user.html b/belajarbelajar/src/main/resources/templates/viewall-user.html
new file mode 100644
index 0000000..6c0ac6a
--- /dev/null
+++ b/belajarbelajar/src/main/resources/templates/viewall-user.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://thymeleaf.org">
+
+<head>
+  <title>BelajarBelajar</title>
+  <object th:include="fragments/fragment :: css" th:remove="tag"></object>
+  <object th:include="fragments/fragment :: js" th:remove="tag"></object>
+</head>
+
+<body>
+<nav th:replace="fragments/fragment :: navbar (pagetitle='View All')"></nav>
+<div th:if="${user.getRole().getRole() == 'Admin'}" class="container">
+  <h2>Daftar Seluruh User</h2>
+
+  <br>
+  <br>
+  <table class="table">
+    <thead>
+    <tr>
+      <th>No</th>
+      <th>Username User</th>
+      <th>Nama User</th>
+      <th>Email User</th>
+      <th>Role User</th>
+      <th></th>
+      <th></th>
+    </tr>
+    </thead>
+    <tbody>
+    <tr th:each="user, iterationStatus : ${listUser}">
+      <td th:text="${iterationStatus.count}"></td>
+      <td th:text="${user.username}"></td>
+      <td th:text="${user.nama}"></td>
+      <td th:text="${user.email}"></td>
+      <td th:text="${user.role.role}"></td>
+      <td><a class="btn btn-danger" th:href="@{/user/delete/} + ${user.id}">Delete</a></td>
+    </tr>
+    </tbody>
+  </table>
+  <a class="btn btn-primary" href="/">Home</a>
+  <a class="btn btn-warning" th:href="@{/user/add}">Tambah User</a>
+</div>
+
+</body>
+
+</html>
\ No newline at end of file
-- 
GitLab