Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
No results found
Show changes
Commits on Source (84)
Showing
with 833 additions and 11 deletions
File deleted
{
"extends": "standard"
}
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
......@@ -25,7 +25,7 @@ Setiap kelompok beranggotakan **3 orang dari kelas yang sama**. Jika jumlah maha
7. Pada Readme terdapat tampilan aplikasi dan penjelasan mengenai pembagian tugas masing-masing anggota (lihat formatnya pada bagian **pembagian tugas**).
8. Merge request dari repository anda ke repository ini dengan format **Nama kelompok** - **NIM terkecil** - **Nama Lengkap dengan NIM terkecil** sebelum **Senin, 27 November 2017 23.59**.
![](img/arsitektur_umum.png)
![](misc/docs/arsitektur_umum.png)
### Arsitektur Umum
Tugas 3 ini terdiri dari komponen Tugas 2 dan tambahan yang harus dibuat:
......@@ -68,7 +68,7 @@ Kali ini, Anda diminta untuk merubah sedikit fungsionalitas order yang sudah ada
### Rincian Arsitektur Aplikasi Chat
![](img/mekanisme_chat.png)
![](misc/docs/mekanisme_chat.png)
Proses untuk komunikasi antar client adalah sebagai berikut:
1. Ketika client dijalankan, client akan meminta token (token yang berbeda dengan token untuk authentication dari Identity Service) dari FCM.
......@@ -116,19 +116,19 @@ Token tidak perlu dienkripsi-dekripsi (for simplicity)
### Tampilan Program
Halaman Order pada Driver
![](img/driver_halaman_order.png)
![](misc/docs/driver_halaman_order.png)
Halaman Order pada Driver Ketika Melakukan Finding Order
![](img/driver_finding_order.png)
![](misc/docs/driver_finding_order.png)
Halaman Order pada Driver Ketika Mendapat Order
![](img/driver_got_order.png)
![](misc/docs/driver_got_order.png)
Halaman Order pada Pengguna, Chat Driver
![](img/pengguna_chat_driver.png)
![](misc/docs/pengguna_chat_driver.png)
Perlu diperhatikan bahwa chat yang dikirim oleh user yang sedang login berada disisi sebelah kanan dan lawan chatnya lain di sisi sebelah kirim. Isi chat jga harus ditampilkan sesuai urutan waktu diterima (paling atas adalah chat paling lama dan makin ke bawah chat makin baru).
......@@ -156,13 +156,13 @@ Harap semua anggota kelompok mengerjakan baik implementasi Firebase sebagai *clo
Chat App Front-end :
1. Fungsionalitas A : 135140XX
2. Fungsionalitas B : 135140XX
1. Fungsionalitas A : 135140XX
2. Fungsionalitas B : 135140XX
Chat REST Service:
1. Fungsionalitas C : 135140XX
2. Fungsionalitas D : 135140XX
Chat REST Service:
1. Fungsionalitas C : 135140XX
2. Fungsionalitas D : 135140XX
Fitur security (IP, User-agent) :
1. Fungsionalitas E : 135140XX
......
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# Declare files that will always have CRLF line endings on checkout.
*.bat text eol=crlf
# Created by https://www.gitignore.io/api/java-web,androidstudio,jetbrains+all
### AndroidStudio ###
# Covers files to be ignored for android development using Android Studio.
# Built application files
*.apk
*.ap_
# Files for the ART/Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
out/
# Gradle files
.gradle
.gradle/
build/
# Signing files
.signing/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio
/*/build/
/*/local.properties
/*/out
/*/*/build
/*/*/production
captures/
.navigation/
*.ipr
*~
*.swp
# Android Patch
gen-external-apklibs
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
# NDK
obj/
# IntelliJ IDEA
*.iml
*.iws
/out/
# User-specific configurations
.idea/libraries/
.idea/workspace.xml
.idea/tasks.xml
.idea/.name
.idea/compiler.xml
.idea/copyright/profiles_settings.xml
.idea/encodings.xml
.idea/misc.xml
.idea/modules.xml
.idea/scopes/scope_settings.xml
.idea/dictionaries
.idea/vcs.xml
.idea/jsLibraryMappings.xml
.idea/datasources.xml
.idea/dataSources.ids
.idea/sqlDataSources.xml
.idea/dynamic.xml
.idea/uiDesigner.xml
# OS-specific files
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
# Legacy Eclipse project files
.classpath
.project
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.war
*.ear
# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml)
hs_err_pid*
## Plugin-specific files:
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Mongo Explorer plugin
.idea/mongoSettings.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
### AndroidStudio Patch ###
!/gradle/wrapper/gradle-wrapper.jar
### Java-Web ###
## ignoring target file
target/
### JetBrains+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff:
.idea/**/workspace.xml
.idea/**/tasks.xml
# Sensitive or high-churn files:
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.xml
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
# Gradle:
.idea/**/gradle.xml
.idea/**/libraries
# CMake
cmake-build-debug/
# Mongo Explorer plugin:
.idea/**/mongoSettings.xml
## File-based project format:
## Plugin-specific files:
# IntelliJ
# mpeltonen/sbt-idea plugin
# JIRA plugin
# Cursive Clojure plugin
.idea/replstate.xml
# Ruby plugin and RubyMine
/.rakeTasks
# Crashlytics plugin (for Android Studio and IntelliJ)
### JetBrains+all Patch ###
# Ignores the whole idea folder
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
.idea/
# End of https://www.gitignore.io/api/java-web,androidstudio,jetbrains+all
src/main/resources/config/db.properties
plugins {
id 'java'
id 'war'
id 'org.akhikhl.gretty'
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile project(':SharedLibrary')
// https://mvnrepository.com/artifact/junit/junit
testCompile 'junit:junit:4.12'
// https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api
providedCompile 'javax.servlet:javax.servlet-api:4.0.0'
// https://mvnrepository.com/artifact/com.google.code.gson/gson
compile 'com.google.code.gson:gson:2.8.2'
// https://mvnrepository.com/artifact/com.sun.xml.ws/jaxws-ri
gretty 'com.sun.xml.ws:jaxws-ri:2.3.0'
// https://mvnrepository.com/artifact/mysql/mysql-connector-java
gretty 'mysql:mysql-connector-java:5.1.44'
}
package com.adaapa.identityservice.models;
import com.adaapa.bean.UserBean;
import com.adaapa.models.BaseModel;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
public class UserModel extends BaseModel {
Connection conn;
public UserModel() {
super("users", "id");
}
public UserBean parseResultSet(ResultSet rs) throws SQLException {
UserBean res = new UserBean();
res.id = rs.getInt("id");
res.name = rs.getString("name");
res.email = rs.getString("email");
res.username = rs.getString("username");
res.phoneNumber = rs.getString("phone_number");
return res;
}
public UserBean findUser(Integer id) {
UserBean res = null;
try {
ResultSet rs = find(id);
if (rs.next()) {
res = parseResultSet(rs);
}
} catch (Exception e) {
e.printStackTrace();
}
return res;
}
public UserBean findUser(String username) {
UserBean res = null;
try {
ResultSet rs = query(String.format("SELECT * FROM %s WHERE username = '%s'", tableName, username));
;
if (rs.next()) {
res = parseResultSet(rs);
}
} catch (Exception e) {
e.printStackTrace();
}
return res;
}
public UserBean findUserByEmail(String email) {
UserBean res = null;
try {
ResultSet rs = query(String.format("SELECT * FROM %s WHERE email = '%s'", tableName, email));
;
if (rs.next()) {
res = parseResultSet(rs);
}
} catch (Exception e) {
e.printStackTrace();
}
return res;
}
/**
* @param username Username yang diterima oleh servlet
* @param password Password yang diterima oleh servlet
* @return UserBean object jika terautentikasi, null jika tidak
*/
public UserBean authenticate(String username, String password) {
UserBean ubean = null;
try {
ResultSet rs = query(String.format(
"SELECT * FROM %s WHERE username = '%s' and password = '%s'",
tableName, username, password));
if (rs.next()) {
ubean = parseResultSet(rs);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
return ubean;
}
}
/**
* Menyimpan token yang telah digenerate
*
* @param token token yang sudah digenerate oleh generate token
* @return true jika token berhasil disimpan, false jika tidak berhasil
*/
public Boolean saveToken(Integer userId, String token) {
try {
ResultSet rs = queryUpdate(String.format(
"UPDATE %s SET last_token='%s',token_expire=DATE_ADD(now(), INTERVAL 7 DAY) where id=%d", this.tableName, token, userId
));
} catch (SQLException e) {
e.printStackTrace();
}
return true;
}
public Boolean deleteToken(String token) {
try {
ResultSet rs = queryUpdate(String.format(
"UPDATE %s SET last_token=%s,token_expire=%s WHERE last_token='%s'", this.tableName, null, null, token
));
} catch (SQLException e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* @return Userbean dimana token ditemukan, null validasi gagal
*/
public UserBean validateToken() {
return null;
}
/**
* Fungsi untuk menyimpan data user yang akan diregister ke database
*
* @param user bean dari servlet
* @param password password yang diterima oleh servlet
* @return id yang didapatkan oleh user yang teregister, null jika register gagal
*/
public Integer register(UserBean user, String password) {
UserBean ubean = null;
Integer res = null;
UserBean ubeanuname = findUser(user.getUsername());
UserBean ubeanemail = findUserByEmail(user.getEmail());
if (ubeanuname == null && ubeanemail == null) {
ResultSet resultSet = null;
try {
resultSet = queryUpdate(String.format(
"INSERT INTO %s (name,email,username,password,phone_number)"
+ "VALUES ('%s','%s','%s','%s','%s')",
tableName, user.name, user.email, user.username, password, user.phoneNumber
));
} catch (Exception e) {
e.printStackTrace();
}
try {
ResultSet temp = query(String.format(
"SELECT * FROM %s WHERE username = '%s'", this.tableName, user.getUsername()));
if (temp.next()) {
ubean = parseResultSet(temp);
}
} catch (Exception e) {
e.printStackTrace();
}
res = ubean.getId();
}
return res;
}
public UserBean findUserByToken(String token) {
UserBean res = null;
try {
ResultSet rs = query(String.format("SELECT * FROM %s WHERE last_token = '%s'", tableName, token));
;
if (rs.next()) {
Timestamp timestamp = rs.getTimestamp("token_expire");
Timestamp currentTimestamp = new Timestamp(System.currentTimeMillis());
if (timestamp.after(currentTimestamp)) {
res = parseResultSet(rs);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return res;
}
public void updateTokenLifetime(Integer userId) {
try {
ResultSet rs = queryUpdate(String.format(
"UPDATE %s SET token_expire=DATE_ADD(now(), INTERVAL 7 DAY) where id=%d", this.tableName, userId
));
} catch (SQLException e) {
e.printStackTrace();
}
}
}
\ No newline at end of file
package com.adaapa.identityservice.services;
import java.util.Base64;
import java.util.Random;
public class TokenService {
//TODO: generate Token
/**
* Generate token menghasilkan token string random
*
* @return token yang telah digenerate
*/
//TODO:Generate Token, validate token, regenerate token(bonus)
public String generateToken() {
byte[] r = new byte[96];
Random rand = new Random();
rand.nextBytes(r);
String s = Base64.getEncoder().encodeToString(r);
return s;
}
}
package com.adaapa.identityservice.servlets;
import com.adaapa.bean.LoginResponseBean;
import com.adaapa.bean.UserBean;
import com.adaapa.identityservice.models.UserModel;
import com.adaapa.identityservice.services.TokenService;
import com.google.gson.Gson;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* Created by kennethhalim on 10/26/17.
*/
public class LoginServlet extends HttpServlet {
private String message;
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
TokenService tokenService = new TokenService();
String username = req.getParameter("username");
String password = req.getParameter("password");
String userAgent = req.getParameter("user_agent");
String ipAddress = req.getParameter("ip_address");
PrintWriter out = resp.getWriter();
Gson gson = new Gson();
UserModel userModel = new UserModel();
UserBean user = userModel.authenticate(username, password);
UserBean responseUser = new UserBean();
if (user != null) {
//Call Generate token here, then save it to database via usermodel;
responseUser.username = user.username;
String access_token = tokenService.generateToken() + "#" + userAgent + "#" + ipAddress;
userModel.saveToken(user.id, access_token);
out.println(gson.toJson(new LoginResponseBean("accepted", access_token, LoginResponseBean.TOKEN_AGE_DEFAULT, responseUser)));
} else {
out.println(gson.toJson(new LoginResponseBean("failed", "", 0, null)));
}
}
public void destroy() {
// do nothing.
}
}
package com.adaapa.identityservice.servlets;
import com.adaapa.bean.LogoutResponseBean;
import com.adaapa.identityservice.models.UserModel;
import com.google.gson.Gson;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class LogoutServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
String token = req.getParameter("access_token");
UserModel userModel = new UserModel();
PrintWriter out = resp.getWriter();
LogoutResponseBean logoutResponse = new LogoutResponseBean();
if (userModel.deleteToken(token)) {
logoutResponse.setStatus("accepted");
} else {
logoutResponse.setStatus("failed");
}
Gson gson = new Gson();
out.println(gson.toJson(logoutResponse));
}
}
package com.adaapa.identityservice.servlets;
import com.adaapa.bean.LoginResponseBean;
import com.adaapa.bean.UserBean;
import com.adaapa.identityservice.models.UserModel;
import com.adaapa.identityservice.services.TokenService;
import com.google.gson.Gson;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//Implement Register Here
UserBean user = new UserBean();
UserModel userModel = new UserModel();
UserModel usermodel = new UserModel();
TokenService tokenService = new TokenService();
//Parsing data
PrintWriter out = resp.getWriter();
user.name = req.getParameter("name");
user.username = req.getParameter("username");
user.email = req.getParameter("email");
user.phoneNumber = req.getParameter("phoneNumber");
String password = req.getParameter("password");
String userAgent = req.getParameter("user_agent");
String ipAddress = req.getParameter("ip_address");
Gson gson = new Gson();
user.id = userModel.register(user, password);
UserBean responseUser = new UserBean();
if (user.id != null) {
//Register berhasil
//Generate token here, then save token
String token = tokenService.generateToken() + "#" + userAgent + "#" + ipAddress;
userModel.saveToken(user.id, token);
responseUser.username = user.username;
out.println(gson.toJson(new LoginResponseBean("accepted", token, LoginResponseBean.TOKEN_AGE_DEFAULT, responseUser)));
} else {
out.println(gson.toJson(new LoginResponseBean("failed", "", 0, null)));
}
}
}
\ No newline at end of file
package com.adaapa.identityservice.servlets;
import com.adaapa.bean.TokenVerificationResponse;
import com.adaapa.bean.UserBean;
import com.adaapa.identityservice.models.UserModel;
import com.google.gson.Gson;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
@WebService(targetNamespace = "tokenverifier.adaapa.com")
public class TokenVerifier {
@WebMethod(operationName = "verifyToken")
@WebResult(name = "userObjectInJSON")
public String verifyToken(@WebParam(name = "access_token") String access_token) {
UserModel userModel = new UserModel();
UserBean userBean = userModel.findUserByToken(access_token);
TokenVerificationResponse response = new TokenVerificationResponse();
if (userBean != null) {
userModel.updateTokenLifetime(userBean.getId());
response.setStatus(TokenVerificationResponse.TOKEN_VALID);
response.setUser(userBean);
} else {
response.setStatus(TokenVerificationResponse.TOKEN_INVALID);
}
return (new Gson().toJson(response));
}
}
DB_HOST = localhost
DB_USER = test
DB_PASS = test
DB_NAME = test_wbd3_id
<?xml version="1.0" encoding="UTF-8"?>
<endpoints
xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
version="2.0">
<endpoint
name="TokenVerifier"
implementation="com.adaapa.identityservice.servlets.TokenVerifier"
url-pattern="/verifytoken"/>
</endpoints>
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/j2ee"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<listener>
<listener-class>
com.sun.xml.ws.transport.http.servlet.WSServletContextListener
</listener-class>
</listener>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.adaapa.identityservice.servlets.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>LogoutServlet</servlet-name>
<servlet-class>com.adaapa.identityservice.servlets.LogoutServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LogoutServlet</servlet-name>
<url-pattern>/logout</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>RegisterServlet</servlet-name>
<servlet-class>com.adaapa.identityservice.servlets.RegisterServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>RegisterServlet</servlet-name>
<url-pattern>/register</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>web-jaxws</servlet-name>
<servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>web-jaxws</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
plugins {
id 'java'
id 'war'
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
// https://mvnrepository.com/artifact/junit/junit
testCompile 'junit:junit:4.12'
// https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api
providedCompile 'javax.servlet:javax.servlet-api:4.0.0'
}
package com.adaapa.bean;
import java.io.Serializable;
public class DriverBean implements Serializable {
private Integer id;
private String name;
private Double rating;
private Integer vote;
private String image;
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getRating() {
return rating;
}
public void setRating(Double rating) {
this.rating = rating;
}
public Integer getVote() {
return vote;
}
public void setVote(Integer vote) {
this.vote = vote;
}
}
package com.adaapa.bean;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
public class LoginRequestBean implements Serializable {
private String username;
private String password;
private String userAgent;
private String ipAddress;
public LoginRequestBean(String username, String password, String userAgent, String ipAddress) {
this.username = username;
this.password = password;
this.userAgent = userAgent;
this.ipAddress = ipAddress;
}
public String getURLParameter() throws UnsupportedEncodingException {
return String.format(
"username=%s&password=%s&user_agent=%s&ip_address=%s",
URLEncoder.encode(username, "UTF-8"),
URLEncoder.encode(password, "UTF-8"),
URLEncoder.encode(userAgent, "UTF-8"),
URLEncoder.encode(ipAddress, "UTF-8")
);
}
}