Skip to content

Commit 6f3684e

Browse files
committed
more fixes and improvements. added CredentialsDAO
1 parent 938f28b commit 6f3684e

16 files changed

Lines changed: 263 additions & 192 deletions

File tree

common/src/main/java/com/imsproject/common/dataAccess/OfflineResultSet.kt

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -47,27 +47,53 @@ class OfflineResultSet(rs: ResultSet) {
4747
return false
4848
}
4949

50-
inline fun <reified T> getTyped(columnName: String): T? {
50+
fun getObject(columnName: String): Any? {
51+
val row = currentRowData ?: return null
52+
return row[columnName.lowercase()]
53+
}
54+
55+
fun getString(columnName: String): String? {
56+
return getObject(columnName) as String?
57+
}
58+
59+
fun getInt(columnName: String): Int? {
60+
return getObject(columnName) as Int?
61+
}
62+
63+
fun getLong(columnName: String): Long? {
64+
return getObject(columnName) as Long?
65+
}
66+
67+
fun getDouble(columnName: String): Double? {
68+
return getObject(columnName) as Double?
69+
}
70+
71+
fun getBoolean(columnName: String): Boolean? {
72+
return getObject(columnName) as Boolean?
73+
}
74+
75+
fun getLocalDate(columnName: String): LocalDate? {
5176
val obj = getObject(columnName) ?: return null
52-
if(T::class == LocalDateTime::class)
53-
return LocalDateTime.parse(obj as String, DateTimeFormatter.ISO_LOCAL_DATE_TIME) as T
54-
if(T::class == LocalDate::class)
55-
return LocalDate.parse(obj as String, DateTimeFormatter.ISO_LOCAL_DATE) as T
56-
if(T::class == LocalTime::class)
57-
return LocalTime.parse(obj as String, DateTimeFormatter.ISO_LOCAL_TIME) as T
58-
if(T::class.java.isEnum){
59-
val enumConstants = T::class.java.enumConstants
60-
for (enumConstant in enumConstants) {
61-
if((enumConstant as Enum<*>).name == obj)
62-
return enumConstant
63-
}
64-
}
77+
return LocalDate.parse(obj as String, DateTimeFormatter.ISO_LOCAL_DATE)
78+
}
6579

66-
return obj as T
80+
fun getTime(columnName: String): LocalTime? {
81+
val obj = getObject(columnName) ?: return null
82+
return LocalTime.parse(obj as String, DateTimeFormatter.ISO_LOCAL_TIME)
6783
}
6884

69-
fun getObject(columnName: String): Any? {
70-
val row = currentRowData ?: return null
71-
return row[columnName.lowercase()]
85+
fun getLocalDateTime(columnName: String): LocalDateTime? {
86+
val obj = getObject(columnName) ?: return null
87+
return LocalDateTime.parse(obj as String, DateTimeFormatter.ISO_LOCAL_DATE_TIME)
88+
}
89+
90+
inline fun <reified T> getEnum(columnName: String): T? {
91+
val obj = getObject(columnName) ?: return null
92+
val enumConstants = T::class.java.enumConstants
93+
for (enumConstant in enumConstants) {
94+
if((enumConstant as Enum<*>).name == obj)
95+
return enumConstant
96+
}
97+
throw IllegalArgumentException("Value '$obj' is not a valid enum constant for ${T::class.java.name}")
7298
}
7399
}

common/src/main/java/com/imsproject/common/dataAccess/abstracts/CounterDAOBase.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ abstract class CounterDAOBase protected constructor(
4747
throw DaoException("Failed to select $columnName", e)
4848
}
4949
if (resultSet.next()) {
50-
return resultSet.getTyped(columnName) ?: throw DaoException("Failed to select $columnName")
50+
return resultSet.getInt(columnName) ?: throw DaoException("Failed to select $columnName")
5151
} else {
5252
throw DaoException("Failed to select $columnName")
5353
}

common/src/main/java/com/imsproject/common/dataAccess/abstracts/DAOBase.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ abstract class DAOBase<T, PK : PrimaryKey> protected constructor(
184184
try {
185185
val keysResultSet = cursor.executeInsert(insertQuery,values, transactionId)
186186
if(keysResultSet.next()) {
187-
val id = keysResultSet.getTyped<Int>(idColumnName)
187+
val id = keysResultSet.getInt(idColumnName)
188188
if(id != null){
189189
return id;
190190
}
@@ -198,15 +198,14 @@ abstract class DAOBase<T, PK : PrimaryKey> protected constructor(
198198
/**
199199
* @return the affected row count
200200
*/
201-
fun buildQueryAndBulkInsert(idColumnName: String, values: List<Array<out Any?>>, transactionId: String?): Int {
201+
fun buildQueryAndBulkInsert(values: List<Array<out Any?>>, transactionId: String?): Int {
202202
val questionmarks = List(nonKeyColumnNames.size) { "?" }.joinToString(", "); //don't ask please
203-
val insertQuery = "INSERT INTO $tableName (${nonKeyColumnNames.joinToString()}) VALUES (${questionmarks}) RETURNING $idColumnName"
203+
val insertQuery = "INSERT INTO $tableName (${nonKeyColumnNames.joinToString()}) VALUES (${questionmarks})"
204204
try {
205205
return cursor.executeBulkInsert(insertQuery,values, transactionId)
206206
} catch (e: SQLException) {
207207
throw DaoException("Failed to insert to table $tableName", e)
208208
}
209-
throw DaoException("Error in insertion to $tableName")
210209
}
211210

212211
fun buildQueryAndUpdate(idColumnName: String, id: Int, values: Array<out Any?>, transactionId: String?): Unit {

database/init.sql

Lines changed: 54 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,65 @@
1-
2-
-- Create the Participants table
3-
CREATE TABLE Participants (
4-
pid SERIAL PRIMARY KEY,
5-
first_name VARCHAR(50) NOT NULL,
6-
last_name VARCHAR(50) NOT NULL,
7-
age INT,
8-
gender VARCHAR(15),
9-
phone VARCHAR(15),
10-
email VARCHAR(100) UNIQUE
1+
CREATE TABLE IF NOT EXISTS Participants (
2+
pid SERIAL PRIMARY KEY,
3+
first_name VARCHAR(50) NOT NULL,
4+
last_name VARCHAR(50) NOT NULL,
5+
age INT NOT NULL,
6+
gender VARCHAR(15) NOT NULL,
7+
phone VARCHAR(15) NOT NULL,
8+
email VARCHAR(100) UNIQUE NOT NULL,
119
);
1210

13-
-- Create the Lobby table
14-
CREATE TABLE Experiments (
15-
exp_id SERIAL PRIMARY KEY,
16-
pid1 INT,
17-
pid2 INT,
18-
FOREIGN KEY (pid1) REFERENCES Participants(pid),
19-
FOREIGN KEY (pid2) REFERENCES Participants(pid)
11+
CREATE TABLE IF NOT EXISTS Experiments (
12+
exp_id SERIAL PRIMARY KEY,
13+
pid1 INT,
14+
pid2 INT,
15+
FOREIGN KEY (pid1) REFERENCES Participants(pid),
16+
FOREIGN KEY (pid2) REFERENCES Participants(pid)
2017
);
2118

22-
CREATE TABLE ExperimentsFeedback (
23-
exp_id INT NOT NULL,
24-
pid INT NOT NULL,
25-
question VARCHAR(100) NOT NULL,
26-
answer VARCHAR(300) NOT NULL,
27-
PRIMARY KEY (exp_id, pid, question),
28-
FOREIGN KEY (pid) REFERENCES Participants(pid),
29-
FOREIGN KEY (exp_id) REFERENCES Experiments(exp_id)
19+
CREATE TABLE IF NOT EXISTS ExperimentsFeedback (
20+
exp_id INT,
21+
pid INT,
22+
question VARCHAR(100),
23+
answer VARCHAR(300) NOT NULL,
24+
PRIMARY KEY (exp_id, pid, question),
25+
FOREIGN KEY (pid) REFERENCES Participants(pid),
26+
FOREIGN KEY (exp_id) REFERENCES Experiments(exp_id)
3027
);
3128

32-
-- Create the Sessions table
33-
CREATE TABLE Sessions ( -- SESSIONS WILL BE INSERTED TOGETHER WITH LOBBY
34-
session_id SERIAL PRIMARY KEY,
35-
exp_id INT,
36-
duration INT,
37-
session_type VARCHAR(50),
38-
session_order INT,
39-
tolerance INT,
40-
window_length INT,
41-
state VARCHAR(50),
42-
FOREIGN KEY (exp_id) REFERENCES Experiments(exp_id)
29+
CREATE TABLE IF NOT EXISTS Sessions (
30+
session_id SERIAL PRIMARY KEY,
31+
exp_id INT,
32+
duration INT NOT NULL,
33+
session_type VARCHAR(50) NOT NULL,
34+
session_order INT NOT NULL,
35+
tolerance INT NOT NULL,
36+
window_length INT NOT NULL,
37+
state VARCHAR(50) NOT NULL,
38+
FOREIGN KEY (exp_id) REFERENCES Experiments(exp_id)
4339
);
4440

45-
CREATE TABLE SessionsFeedback (
46-
exp_id INT NOT NULL,
47-
session_id INT NOT NULL,
48-
pid INT NOT NULL,
49-
question VARCHAR(100) NOT NULL,
50-
answer VARCHAR(300) NOT NULL,
51-
PRIMARY KEY (exp_id, session_id, pid, question),
52-
FOREIGN KEY (pid) REFERENCES Participants(pid),
53-
FOREIGN KEY (session_id) REFERENCES Sessions(session_id),
54-
FOREIGN KEY (exp_id) REFERENCES Experiments(exp_id)
41+
CREATE TABLE IF NOT EXISTS SessionsFeedback (
42+
session_id INT,
43+
pid INT,
44+
question VARCHAR(100),
45+
answer VARCHAR(300) NOT NULL,
46+
PRIMARY KEY (session_id, pid, question),
47+
FOREIGN KEY (pid) REFERENCES Participants(pid),
48+
FOREIGN KEY (session_id) REFERENCES Sessions(session_id)
5549
);
5650

57-
58-
-- Create the SessionUserInputEvent table
59-
CREATE TABLE SessionEvents (
60-
event_id SERIAL PRIMARY KEY,
61-
session_id INT,
62-
type VARCHAR(50) NOT NULL,
63-
subtype VARCHAR(50) NOT NULL,
64-
timestamp INT NOT NULL,
65-
actor VARCHAR(100) NOT NULL,
66-
data TEXT,
67-
FOREIGN KEY (session_id) REFERENCES Sessions(session_id)
51+
CREATE TABLE IF NOT EXISTS SessionEvents (
52+
event_id SERIAL PRIMARY KEY,
53+
session_id INT,
54+
type VARCHAR(50) NOT NULL,
55+
subtype VARCHAR(50) NOT NULL,
56+
timestamp INT NOT NULL,
57+
actor VARCHAR(100) NOT NULL,
58+
data TEXT,
59+
FOREIGN KEY (session_id) REFERENCES Sessions(session_id)
6860
);
61+
62+
CREATE TABLE IF NOT EXISTS Credentials (
63+
user_id VARCHAR(50) PRIMARY KEY,
64+
password VARCHAR(50) NOT NULL,
65+
)

game_server/src/main/kotlin/com/imsproject/gameserver/api/RestHandler.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,14 +201,13 @@ class RestHandler(
201201
}
202202
}
203203

204-
private data class SessionFeedback(val expId: Int, val sessionId: Int, val pid: Int, val qnas: List<QnA>)
204+
private data class SessionFeedback(val sessionId: Int, val pid: Int, val qnas: List<QnA>)
205205
@PostMapping("/data/session/insert/feedback")
206206
fun dataInsertSessionFeedback(@RequestBody body: String): ResponseEntity<String> {
207207
return withParsedBody<SessionFeedback>(body) { feedback ->
208208
withErrorHandling("Error inserting session feedback") {
209209
val feedbackDTOs = feedback.qnas.map {
210210
SessionFeedbackDTO(
211-
expId = feedback.expId,
212211
sessionId = feedback.sessionId,
213212
pid = feedback.pid,
214213
question = it.question,
@@ -217,7 +216,7 @@ class RestHandler(
217216
}
218217
try{
219218
val (_, runTime) = runTimed { daoController.handleBulkInsertSessionFeedback(feedbackDTOs) }
220-
log.debug("Inserted {} feedback entries in {}ms for expId {}", feedbackDTOs.size, runTime, feedback.expId)
219+
log.debug("Inserted {} feedback entries in {}ms for sessionId {}", feedbackDTOs.size, runTime, feedback.sessionId)
221220
Response.getOk().toResponseEntity()
222221
} catch(e: DaoException){
223222
log.error("Error inserting session feedback - Feedback already submitted", e)

game_server/src/main/kotlin/com/imsproject/gameserver/business/auth/AuthController.kt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,7 @@ class AuthController(
4141

4242
log.debug("Adding user credentials for user {}", cleanUserId)
4343
val hashedPassword = encoder.encode(rawPassword)
44-
val userCredentials = Credentials(cleanUserId, hashedPassword)
45-
this@AuthController.credentials[cleanUserId] = userCredentials
44+
this.credentials[cleanUserId] = hashedPassword
4645
}
4746

4847
fun deleteUser(userId: String) {
@@ -58,7 +57,7 @@ class AuthController(
5857
}
5958

6059
fun getAllUsers() : List<String> {
61-
return credentials.getAll()
60+
return credentials.getAllUserIds()
6261
}
6362

6463
fun textToBCrypt(text: String): String {
@@ -76,12 +75,11 @@ class AuthController(
7675

7776
private fun authenticate(userId: String, password: String): Boolean {
7877
log.debug("Authenticating user: {}", userId)
79-
val user = credentials[userId] ?: run {
78+
val hashedPassword = credentials[userId] ?: run {
8079
log.debug("User {} does not exist", userId)
8180
return false
8281
}
8382
log.trace("User {} exists", userId)
84-
val hashedPassword = user.password
8583

8684
// check if the password is correct
8785
if (!isPasswordsMatch(password, hashedPassword)) {

game_server/src/main/kotlin/com/imsproject/gameserver/business/auth/CredentialsController.kt

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,40 @@
11
package com.imsproject.gameserver.business.auth
22

3+
import com.imsproject.gameserver.dataAccess.implementations.CredentialsDAO
4+
import com.imsproject.gameserver.dataAccess.implementations.CredentialsPK
35
import org.springframework.stereotype.Component
46
import java.util.concurrent.ConcurrentHashMap
57

6-
private const val USERS_PATH = "/app/data/users/"
7-
88
@Component
9-
class CredentialsController {
9+
class CredentialsController(private val credentialsDAO: CredentialsDAO) {
1010

11-
val credentials = ConcurrentHashMap<String,Credentials>()
11+
val credentials = ConcurrentHashMap<String,String>()
1212

1313
init {
14-
credentials.put("admin",Credentials("admin", "\$2a\$10\$3Dw.gqCvW3tbdHc7qGSLr.4ry49vTMebhTKxu/J5zcNrEBKi4BuGG"))
15-
credentials.put("user",Credentials("user", "\$2a\$10\$3Dw.gqCvW3tbdHc7qGSLr.4ry49vTMebhTKxu/J5zcNrEBKi4BuGG"))
14+
credentials.put("admin", "\$2a\$10\$3Dw.gqCvW3tbdHc7qGSLr.4ry49vTMebhTKxu/J5zcNrEBKi4BuGG")
15+
credentials.put("user", "\$2a\$10\$3Dw.gqCvW3tbdHc7qGSLr.4ry49vTMebhTKxu/J5zcNrEBKi4BuGG")
1616
}
1717

18-
operator fun get(userId: String): Credentials? {
19-
return credentials[userId]
18+
operator fun get(userId: String): String? {
19+
if(!contains(userId)) return null
20+
return credentials[userId] ?: let {
21+
val selected = credentialsDAO.select(CredentialsPK(userId))
22+
credentials[userId] = selected.password
23+
selected.password
24+
}
2025
}
2126

2227
operator fun contains(userId: String): Boolean {
23-
return credentials.containsKey(userId)
28+
return credentials.containsKey(userId) || credentialsDAO.exists(CredentialsPK(userId))
2429
}
2530

26-
operator fun set(userId: String, credentials: Credentials) {
27-
if (userId == "admin") {
28-
throw IllegalArgumentException("Cannot modify admin user credentials")
29-
}
30-
this.credentials[userId] = credentials
31+
operator fun set(userId: String, password: String) {
32+
if(contains(userId)) throw UnsupportedOperationException("Updating credentials is not supported. Use remove() and set() instead.")
33+
credentialsDAO.insert(Credentials(userId,password))
34+
this.credentials[userId] = password
3135
}
3236

33-
fun getAll(): List<String>{
37+
fun getAllUserIds(): List<String>{
3438
return credentials.keys().toList().filter { it != "admin" }
3539
}
3640

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.imsproject.gameserver.dataAccess.implementations
2+
3+
import com.imsproject.common.dataAccess.CreateTableQueryBuilder
4+
import com.imsproject.common.dataAccess.DaoException
5+
import com.imsproject.common.dataAccess.OfflineResultSet
6+
import com.imsproject.common.dataAccess.abstracts.DAOBase
7+
import com.imsproject.common.dataAccess.abstracts.ExampleBase
8+
import com.imsproject.common.dataAccess.abstracts.PrimaryKey
9+
import com.imsproject.common.dataAccess.abstracts.SQLExecutor
10+
import com.imsproject.gameserver.business.auth.Credentials
11+
import org.springframework.stereotype.Component
12+
import java.sql.SQLException
13+
14+
@Component
15+
class CredentialsDAO(
16+
cursor: SQLExecutor
17+
) : DAOBase<Credentials, CredentialsPK>(cursor, "Credentials", arrayOf("user_id"), arrayOf("password")) {
18+
19+
override fun buildObjectFromResultSet(resultSet: OfflineResultSet): Credentials {
20+
return Credentials(
21+
userId = resultSet.getString("user_id")!!,
22+
password = resultSet.getString("password")!!
23+
)
24+
}
25+
26+
override fun getCreateTableQueryBuilder(): CreateTableQueryBuilder {
27+
throw UnsupportedOperationException("Not yet implemented")
28+
}
29+
30+
@Throws(DaoException::class)
31+
override fun insert(obj: Credentials, transactionId: String?): Int {
32+
val query = "INSERT INTO Credentials (user_id, password) VALUES (?, ?)"
33+
val values = arrayOf<Any>(obj.userId, obj.password)
34+
try{
35+
return cursor.executeWrite(query, values, transactionId)
36+
} catch (e: SQLException) {
37+
throw DaoException("Failed to insert credentials for user ${obj.userId}", e)
38+
}
39+
}
40+
41+
@Throws(DaoException::class)
42+
override fun update(obj: Credentials, transactionId: String?) {
43+
throw UnsupportedOperationException("Update of credentials is not supported.")
44+
}
45+
}
46+
class CredentialsPK(
47+
val userId: String
48+
) : ExampleBase("user_id"), PrimaryKey {
49+
init {
50+
setValue("user_id", userId)
51+
}
52+
}
53+

0 commit comments

Comments
 (0)