Ini adalah lanjutan aplikasi dari assignment sebelumnya yaitu Task Tracker Plus yang dirancang untuk membantu mahasiswa dalam mengatur jadwal studi mereka. Dibangun menggunakan bahasa pemrograman Go (Golang).
Pada tugas ini, kalian akan mengimplementasikan konsep REST API dan juga akan membangun sebuah aplikasi web yang akan mengimplementasikan konsep MVC. Aplikasi ini adalah monolith dimana seluruh sistemnya memakai server, logika, database, hingga user interface yang sama:
/user/register
untuk proses registrasi/user/login
untuk proses login/user/tasks
./task/add
./task/get/:id
./task/update/:id
./task/delete/:id
./task/list
./task/category/:id
./category/add
./category/get/:id
./category/update/:id
./category/delete/:id
./category/list
.Gunakan fungsi pada subpackage di db/filebased
untuk berhubungan dengan database, seluruh fungsinya dapat dipelajari di db/filebased/README.md
dan juga kamu bisa membaca sendiri kode yang ada di dalamnya.
Note: untuk mengakses endpoint
task
dancategory
pengguna harus melakukan login terlebih dahulu.
Client (Frontend)
index
Halaman landing page dari aplikasi ini dapat diakses dari root endpoint /
Disini berjalan di
http://localhost:8080/
users
/client/login
./client/login/process
menggunakan metode POST./client/register
./client/register/process
menggunakan metode POST../client/logout
.dashboard
/client/dashboard
.task
/client/task
.category
/client/category
.modal
/client/modal
.š repository
Warning : abaikan code yang tidak berhubungan dengan instruksi di bawah ini pada folder
repository
repository/session.go
AddSessions
: fungsi ini menerima parameter bertipe model.Session
dan berfungsi menyimpan data sesuai parameter tersebut ke tabel sessions
UpdateSessions
: fungsi ini menerima parameter bertipe model.Session
dan berfungsi mengubah data session sesuai parameter tersebut ke tabel sessions
dengan kondisi sama antara email parameter dengan database.DeleteSession
: fungsi ini menerima parameter token bertipe string
dan berfungsi menghapus data tabel sessions
sesuai dengan target token dari parameter yang diterima.SessionAvailToken
: fungsi ini menerima parameter token bertipe string
dan berfungsi memeriksa apakah token tersedia pada tabel sessions
sesuai dengan kolom token sama dengan nilai dari parameter.model.Session
dan error nil
model.Session
dan error messageSessionAvailEmail
: fungsi ini menerima parameter email bertipe string
dan berfungsi memeriksa apakah token tersedia pada tabel sessions
sesuai dengan kolom email sama dengan nilai dari parameter.model.Session
dan error nil
model.Session{}
dan error messagerepository/user.go
GetUserByEmail
: fungsi ini mengambil data pengguna berdasarkan alamat email yang diberikan sebagai argumen.user
yang merupakan objek dari model User
. fungsi akan mengembalikan user
dan nil
sebagai error.user
kosong dan nil
sebagai error.GetUserTaskCategory
: fungsi ini digunakan untuk mendapatkan kategori tugas pengguna dari database.nil
sebagai error.repository/task.go
Update
: fungsi akan mengeksekusi sebuah query UPDATE
untuk memperbarui data tugas tersebut di dalam tabel tasks
berdasarkan id yang diberikan pada parameter. Query tersebut akan menggunakan nilai dari variabel model.Task
yang diberikan sebagai argumen.nil
sebagai error
.error
yang terjadi.Delete
: fungsi untuk menghapus data tugas berdasarkan id
yang diberikan sebagai argumen. Fungsi ini akan mengeksekusi sebuah query DELETE
untuk menghapus data tugas dengan id
tersebut dari tabel tasks
.nil
sebagai error
.error
yang terjadi.GetList
: fungsi untuk mengambil daftar data tugas dari tabel tasks
. Fungsi akan mengeksekusi sebuah query SELECT
untuk mengambil semua data tugas yang ada dalam tabel.[]*model.Task
yang berisi data tugas yang ditemukan, serta nil
sebagai error
.nil
sebagai slice []*model.Task
, serta error
yang terjadi.GetTaskCategory
: fungsi untuk mengambil kategori tugas berdasarkan id
yang diberikan sebagai argumen. Fungsi akan mengeksekusi sebuah query SELECT
dengan menggunakan join tabel antara tasks
dan categories
untuk mengambil informasi kategori tugas yang sesuai dengan id
yang diberikan.[]*model.TaskCategory
yang berisi kategori tugas yang ditemukan, serta nil
sebagai error
.nil
sebagai slice []*model.TaskCategory
, serta error
yang terjadi.repository/category.go
Update
: fungsi untuk memperbarui kategori berdasarkan id
yang diberikan sebagai argumen. Fungsi akan mengeksekusi sebuah query UPDATE
untuk memperbarui data kategori yang sesuai dengan id
yang diberikan dalam tabel categories
. Query tersebut akan menggunakan nilai dari variabel model.Category
yang diberikan sebagai argumen.nil
sebagai error
.error
yang terjadi.Delete
: fungsi untuk menghapus kategori berdasarkan id
yang diberikan sebagai argumen. Fungsi akan mengeksekusi sebuah query DELETE
untuk menghapus data kategori dengan id
tersebut dari tabel categories
.nil
sebagai error
.error
yang terjadi.GetList
: fungsi untuk mengambil daftar kategori dari tabel categories
. Fungsi akan mengeksekusi sebuah query SELECT
untuk mengambil semua data kategori yang ada dalam tabel.[]*model.Category
yang berisi data kategori yang ditemukan, serta nil
sebagai error
.nil
sebagai slice []*model.Category
, serta error
yang terjadi.š service
Layer service digunakan untuk memproses data sesuai dengan aturan bisnis yang telah ditentukan.
service/session.go
GetSessionByEmail
: fungsi ini menggunakan repository sessionRepo
untuk menampilkan data session tabel sessions kolom email sama dengan email yang diberikan dari parameter.model.Session
dan error nil
model.Session{}
dan error messageservice/user.go
GetUserTaskCategory
: Fungsi ini digunakan untuk mendapatkan kategori tugas pengguna.userRepo
untuk mengambil daftar kategori tugas pengguna dari database.service/task.go
Update
: fungsi ini menggunakan repository taskRepository
untuk memperbarui data tugas.nil
sebagai error
error
yang terjadi.Delete
: fungsi ini menggunakan repository taskRepository
untuk menghapus data tugas berdasarkan id
.nil
sebagai error
.error
yang terjadi.GetList
: fungsi ini menggunakan repository taskRepository
untuk mengambil daftar tugas.[]*model.Task
) dan nil
sebagai error
.[]*model.Task
) dan error
yang terjadi.GetTaskCategory
: fungsi ini menggunakan repository taskRepository
untuk mengambil daftar tugas beserta dengan kategorinya.[]*model.TaskCategory
) dan nil
sebagai error
.nil
sebagai kategori tugas ([]*model.TaskCategory
) dan error
yang terjadi.service/category.go
Update
: fungsi ini menggunakan repository categoryRepository
untuk memperbarui data kategori berdasarkan id
yang diberikan dari parameter.nil
sebagai error
error
yang terjadi.Delete
: fungsi ini menggunakan repository categoryRepository
untuk menghapus data kategori berdasarkan id
.nil
sebagai error
.error
yang terjadi.GetList
: fungsi ini menggunakan repository categoryRepository
untuk mengambil daftar kategori.[]*model.Category
) dan nil
sebagai error
.nil
sebagai daftar kategori ([]*model.Category
) dan error
yang terjadi.š middleware
Di file middleware/auth.go
terdapat fungsi Auth()
yang digunakan untuk melakukan autentikasi pengguna dengan menggunakan JWT (JSON Web Token). Middleware ini berfungsi untuk mengecek apakah user yang mengakses suatu endpoint atau route tertentu sudah terotentikasi atau belum. Fungsi ini terdiri dari beberapa langkah:
Mengambil cookie dengan nama session_token dari request dengan key session_token
. Cookie ini berisi JWT token yang digunakan untuk autentikasi.
Parsing JWT token pada cookie tersebut untuk mendapatkan claims yang berisi informasi mengenai email
. JWT token pada cookie tersebut akan di-parse menggunakan JWT library pada Go, yaitu jwt-go. Setelah di-parse, claims pada token tersebut akan dimasukkan ke dalam struct Claims
.
type Claims struct {
Email int `json:"email"`
jwt.StandardClaims
}
Claims pada JWT token ini dapat berisi informasi user yang terotentikasi seperti user ID, email, dan lain-lain. Disini, hanya user ID yang dimasukkan ke dalam context.
Menentukan respons HTTP berdasarkan hasil parsing JWT token dan keberadaan cookie.
Menyimpan nilai Email dari claims ke dalam context dengan key "email". Nilai Email ini nantinya akan dapat digunakan di handler atau endpoint selanjutnya.
Setelah semua langkah selesai, middleware akan memanggil Next untuk melanjutkan request ke handler atau endpoint selanjutnya.
š api
Warning : abaikan code yang tidak berhubungan dengan instruksi di bawah ini pada folder
api
api/user.go
method Login
: adalah sebuah handler yang menerima parameter *gin.Context
. Method ini akan melakukan login user dengan memanggil userService.Login dengan parameter context dan *model.User
yang sudah didapatkan dari body request.
Method ini wajib mengirim data json dengan contoh format sebagai berikut:
{
"email": <string>,
"password": <string>
}
Jika data email
atau password
kosong maka method ini akan mengembalikan response dengan status code 400
dan pesan error sebagai berikut:
{
"error": "email or password is empty"
}
Jika terjadi error saat menggunakan userService.Login
, maka method ini akan mengembalikan response dengan status code 500
dan pesan error sebagai berikut:
{
"error": "error internal server"
}
Jika user berhasil login, maka method ini akan membuat token JWT dengan Email
sebagai payload dan expirationTime
sebagai waktu kadaluwarsa. Setelah itu, token JWT akan di-sign dengan menggunakan model.JwtKey
.
Setelah token JWT berhasil di-sign, method akan membuat cookie
baru dengan nama session_token
dan value tokenString
yang sudah didapatkan dari JWT sebelumnya. Jika cookie dengan nama session_token
sudah ada, maka value cookie tersebut akan diganti dengan tokenString
yang baru.
Method akan mengembalikan response dengan status code 200
dan data user yang sudah login. Jika sukses, maka response akan berisi status 200
dan data JSON berikut:
{
"user_id": <int>,
"message": "login success"
}
Method GetUserTaskCategory
: Ini adalah handler yang menerima parameter *gin.Context
. Method ini digunakan untuk mendapatkan daftar tugas pengguna dengan kategori yang terkait. Method ini akan memanggil fungsi userService.GetUserTaskCategory
untuk mengambil data tugas pengguna.
Method ini tidak memerlukan input dari permintaan. Permintaan dapat dikirim tanpa body atau dengan body kosong.
Jika terjadi error saat menggunakan userService.GetUserTaskCategory
, method ini akan mengembalikan respons dengan kode status 500
dan pesan error sebagai berikut:
{
"error": "error internal server"
}
Jika data tugas pengguna berhasil diambil, method ini akan mengembalikan respons dengan kode status 200
dan data JSON yang berisi daftar tugas pengguna dengan kategori terkait.
Contoh respons dengan kode status 200
:
[
{
"ID": 1,
"Fullname": "test",
"Email": "[email protected]",
"Task": "Task 2",
"Deadline": "2023-06-01",
"Priority": 1,
"Status": "Completed",
"Category": "Category 2"
},
{
"ID": 1,
"Fullname": "test",
"Email": "[email protected]",
"Task": "Task 5",
"Deadline": "2023-06-07",
"Priority": 5,
"Status": "In Progress",
"Category": "Category 3"
}
]
api/task.go
UpdateTask
: fungsi ini digunakan untuk mengupdate data mahasiswa dengan id
yang sesuai dengan nilai yang diberikan sebagai argumen.
id
tidak valid, fungsi akan mengirimkan respons dengan kode status 400
dan pesan error dalam format JSON {"error": "invalid task ID"}
.400
dan pesan error dalam format JSON.Update
dari taskService
untuk memperbarui tugas dengan taskID
yang diberikan sebagai argumen. Assign taskID
ke struct model.Task.ID
yang akan dikirim ke fungsi tersebut.200
dan pesan sukses dalam format JSON {"message": "update task success"}
.500
dan pesan error dalam format JSON.DeleteTask
: fungsi ini digunakan untuk menghapus tugas dengan id
yang sesuai dengan nilai yang diberikan sebagai argumen.
id
tidak valid, fungsi akan mengirimkan respons dengan kode status 400
dan pesan error dalam format JSON {"error": "invalid task ID"}
.Delete
dari taskService
untuk menghapus tugas dengan taskID
yang diberikan sebagai argumen.500
Internal Server Error dan pesan error.200
OK dan pesan sukses {"message": "delete Task success"}
.GetTaskList
: fungsi ini digunakan untuk mendapatkan daftar tugas.
Pertama, fungsi memanggil GetList
dari taskService
untuk mendapatkan daftar tugas.
Jika terjadi error saat mengambil daftar tugas, fungsi akan mengirimkan tanggapan JSON dengan kode status HTTP 500
Internal Server Error dan pesan error yang sesuai ke client.
Jika tidak terjadi error, fungsi akan mengirimkan tanggapan JSON dengan kode status HTTP 200
OK dan daftar tugas ke client. Contoh:
[
{
"id": 1,
"title": "Task 1",
"deadline": "2023-05-30",
"priority": 2,
"category_id": "1",
"status": "In Progress"
},
{
"id": 2,
"title": "Task 2",
"deadline": "2023-06-10",
"priority": 1,
"category_id": "2",
"status": "Completed"
},
...
]
GetTaskListByCategory
: fungsi ini digunakan untuk mendapatkan daftar tugas dengan nama kategorinya.
Pertama, fungsi memanggil GetTaskListByCategory
dari taskService
untuk mendapatkan daftar tugas.
Jika terjadi error saat mengambil daftar tugas, fungsi akan mengirimkan tanggapan JSON dengan kode status HTTP 500
Internal Server Error dan pesan error yang sesuai ke client.
Jika tidak terjadi error, fungsi akan mengirimkan tanggapan JSON dengan kode status HTTP 200
OK dan daftar tugas beserta nama kategorinya ke client. Contoh:
[
{
"id": 1,
"title": "Task 1",
"category": "Category 1"
},
{
"id": 2,
"title": "Task 2",
"category": "Category 2"
},
...
]
api/category.go
UpdateCategory
: fungsi ini digunakan untuk mengupdate kategori dengan id
yang sesuai dengan nilai yang diberikan sebagai argumen.
id
tidak valid (gagal dikonversi menjadi tipe data int), fungsi akan mengirimkan respons JSON dengan kode status HTTP 400
Bad Request dan pesan error dalam format JSON {"error": "invalid Category ID"}
.400
Bad Request dan pesan error dalam format JSON.Update
pada categoryService
untuk mengupdate kategori dengan ID yang sesuai dengan nilai yang diberikan.200
OK dan pesan sukses dalam format JSON {"message": "category update success"}
.500
Internal Server Error dan pesan error dalam format JSON.DeleteCategory
: fungsi ini digunakan untuk menghapus kategori dengan id
yang sesuai dengan nilai yang diberikan sebagai argumen.
id
tidak valid (gagal dikonversi menjadi tipe data int), fungsi akan mengirimkan respons JSON dengan kode status HTTP 400
Bad Request dan pesan error dalam format JSON {"error": "Invalid category ID"}
.id
valid, fungsi akan memanggil fungsi Delete
pada categoryService
untuk menghapus kategori dengan ID
yang sesuai dengan nilai yang diberikan.200
OK dan pesan sukses dalam format JSON {"message": "category delete success"}
.500
Internal Server Error dan pesan error dalam format JSON.GetCategoryList
: fungsi ini digunakan untuk mendapatkan daftar kategori.
Fungsi memanggil GetList
dari categoryService
untuk mendapatkan daftar kategori.
Jika terjadi error saat mengambil daftar kategori, fungsi akan mengirimkan respons JSON dengan kode status HTTP 500
Internal Server Error dan pesan error yang sesuai ke client.
Jika tidak terjadi error, fungsi akan mengirimkan respons JSON dengan kode status HTTP 200
OK dan daftar kategori ke client. Contoh:
[
{
"id": 1,
"name": "Category 1"
},
{
"id": 2,
"name": "Category 2"
},
...
]
Untuk tugas pada Client (Frontend), kamu diminta untuk melengkapi tampilan user interface pada file berikut dengan mengikuti acceptance criteria yang di jelaskan:
File: views/main/index.html
Contoh tampilan:
Berikut adalah acceptance criteria dari halaman index.html
(Landing Page) yang harus dibuat:
div
atau section
.h1
, h2
, h3
, h4
, h5
, atau h6
.p
.h1
yang memiliki teks "Task Tracker Plus"
.a
dengan teks "Login"
dan atribut href
yang mengarah ke "/client/login"
.a
dengan teks "Register"
dan atribut href
yang mengarah ke "/client/register"
.div
atau section
h1
, h2
, h3
, h4
, h5
, atau h6
File: views/auth/register.html
Contoh tampilan:
Berikut adalah acceptance criteria dari halaman Register
yang harus dibuat:
h1
, h2
, h3
, h4
, h5
, atau h6
.input
, masing-masing memiliki atribut type
dengan nilai text
, email
dan password
.button
yang memiliki teks "Register"
.a
dengan teks "Login"
dan atribut href
yang mengarah ke "/client/login"
.div
atau section
h1
, h2
, h3
, h4
, h5
, atau h6
File: views/auth/login.html
Contoh tampilan:
Berikut adalah acceptance criteria dari halaman Login
yang harus dibuat:
h1
, h2
, h3
, h4
, h5
, atau h6
.input
dan atribut type
bernilai "email"
.input
dan atribut type
bernilai "password"
.button
yang memiliki teks "Login"
.a
dengan teks "Register"
dan atribut href
yang mengarah ke "/client/register"
.div
atau section
h1
, h2
, h3
, h4
, h5
, atau h6
Input:
POST /api/v1/user/register HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"fullname": "John Doe",
"email": "[email protected]",
"password": "password123"
}
Expected Output / Behavior:
Jika registrasi berhasil, server harus mengembalikan kode status HTTP 201
Created dan respons JSON dengan pesan sukses:
{
"message": "register success"
}
Jika terjadi kesalahan validasi data registrasi, server harus mengembalikan kode status HTTP 400
Bad Request dan respons JSON dengan pesan kesalahan:
{
"error": "invalid data"
}
Jika terjadi kesalahan server saat menyimpan data pengguna, server harus mengembalikan kode status HTTP 500
Internal Server Error dan respons JSON dengan pesan kesalahan:
{
"error": "internal server error"
}
Input:
POST /api/v1/user/login HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"email": "[email protected]",
"password": "password123"
}
Expected Output / Behavior:
Jika login berhasil, server harus mengembalikan kode status HTTP 200
OK dan respons JSON dengan pesan sukses:
{
"message": "login success"
}
Jika terjadi kesalahan validasi data login, server harus mengembalikan kode status HTTP 400
Bad Request dan respons JSON dengan pesan kesalahan:
{
"error": "email or password is empty"
}
Jika terjadi kesalahan server saat melakukan login, server harus mengembalikan kode status HTTP 500
Internal Server Error dan respons JSON dengan pesan kesalahan:
{
"error": "internal server error"
}
Input:
POST /api/v1/task/add HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"title": "Task 1",
"deadline": "2023-06-30",
"priority": 2,
"category_id": "1",
"status": "In Progress"
}
Expected Output / Behavior:
Jika permintaan berhasil, server harus mengembalikan kode status HTTP 200
OK dan respons JSON dengan pesan sukses:
{
"message": "add task success"
}
Jika permintaan gagal karena kesalahan validasi, server harus mengembalikan kode status HTTP 400
Bad Request dan respons JSON dengan pesan kesalahan:
{
"error": "invalid data"
}
Jika terjadi kesalahan server saat menyimpan tugas, server harus mengembalikan kode status HTTP 500
Internal Server Error dan respons JSON dengan pesan kesalahan:
{
"error": "internal server error"
}
Input:
GET /api/v1/task/list HTTP/1.1
Host: localhost:8080
Expected Output / Behavior:
Jika permintaan berhasil, server harus mengembalikan kode status HTTP 200
OK dan respons JSON dengan daftar tugas.
[
{
"id": 1,
"title": "Task 1",
"deadline": "2023-05-30",
"priority": 2,
"category_id": "1",
"status": "In Progress"
},
{
"id": 2,
"title": "Task 2",
"deadline": "2023-06-10",
"priority": 1,
"category_id": "2",
"status": "Completed"
},
...
]
Jika terjadi kesalahan saat mendapatkan daftar tugas, server harus mengembalikan kode status HTTP 500
Internal Server Error dan respons JSON dengan pesan kesalahan.
{
"error": "[error messages]"
}
Input:
PUT /api/v1/task/update/{id} HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"title": "Task 1",
"deadline": "2023-06-30",
"priority": 2,
"category_id": "1",
"status": "In Progress"
}
Expected Output / Behavior:
Jika permintaan berhasil dan ID tugas valid, server harus mengembalikan kode status HTTP 200
OK dan respons JSON dengan pesan sukses.
{
"message": "update Task success"
}
Jika permintaan gagal karena ID tugas tidak valid, server harus mengembalikan kode status HTTP 400
Bad Request dan respons JSON dengan pesan kesalahan.
{
"error": "Invalid task ID"
}
Jika permintaan gagal karena format data tugas tidak sesuai yang diharapkan, server harus mengembalikan kode status HTTP 400
Bad Request dan respons JSON dengan pesan kesalahan.
{
"error": "[error messages]"
}
Jika terjadi kesalahan saat memperbarui data tugas, server harus mengembalikan kode status HTTP 500
Internal Server Error dan respons JSON dengan pesan kesalahan.
{
"error": "[error messages]"
}
Input:
DELETE /api/v1/task/delete/{id} HTTP/1.1
Host: localhost:8080
Expected Output / Behavior:
Jika permintaan berhasil dan ID tugas valid, server harus mengembalikan kode status HTTP 200
OK dan respons JSON dengan pesan sukses.
{
"message": "delete Task success"
}
Jika permintaan gagal karena ID tugas tidak valid, server harus mengembalikan kode status HTTP 400
Bad Request dan respons JSON dengan pesan kesalahan.
{
"error": "Invalid task ID"
}
Jika terjadi kesalahan saat menghapus tugas, server harus mengembalikan kode status HTTP 500
Internal Server Error dan respons JSON dengan pesan kesalahan.
{
"error": "[error messages]"
}