Created
December 1, 2017 12:47
-
-
Save Erezbiox1/ec835c91dfdf173572b706f4830358ab to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.erezbiox1 | |
import java.nio.charset.StandardCharsets | |
import java.security.MessageDigest | |
import java.sql.DriverManager | |
import java.sql.ResultSet | |
import java.util.* | |
import kotlin.reflect.KProperty | |
@Suppress("NullableBooleanElvis", "unused", "MemberVisibilityCanPrivate") | |
/** | |
* Created by Erezbiox1 on 30/11/2017. | |
* (C) 2017 Erez Rotem All Rights Reserved. | |
*/ | |
abstract class AbstractUser(val id: Int) { | |
var username: String by SQL() | |
var email: String by SQL() | |
var password: String | |
get() = error("Cannot access hashed password") | |
set(pass) = sql("UPDATE users SET password = ?", hash(password)) | |
companion object { | |
fun sql(query: String, vararg objects: Any, function: ((ResultSet?) -> Unit)? = null) { | |
Class.forName("com.mysql.jdbc.Driver") | |
val db = DriverManager.getConnection("jdbc:mysql://localhost:3306/main", "erez", "Pizza123") | |
val statement = db.prepareStatement(query) | |
objects.withIndex().forEach { | |
when(it.value){ | |
is Int -> statement.setInt(it.index + 1, it.value as Int) | |
is Boolean -> statement.setBoolean(it.index + 1, it.value as Boolean) | |
else -> statement.setString(it.index + 1, it.value.toString()) | |
} | |
} | |
val result = | |
if(statement.execute() && statement.resultSet.next()) | |
statement.resultSet | |
else null | |
function?.invoke(result) | |
result?.close() | |
statement.close() | |
db.close() | |
} | |
inline fun <reified T> ResultSet?.get(column: Int = 1) : T? { | |
if(this == null) | |
return null | |
return when(T::class){ | |
java.lang.Integer::class -> this.getInt(column) as T | |
java.lang.Integer::class.java -> this.getInt(column) as T | |
java.lang.Boolean::class -> this.getBoolean(column) as T | |
java.lang.Boolean::class.java -> this.getBoolean(column) as T | |
else -> this.getString(column) as T | |
} | |
} | |
private fun createHash(password: String) : String { | |
val random = UUID.randomUUID().toString() | |
return random + ":" + hash(random + password) | |
} | |
private fun matchHash(password: String, hash: String) : Boolean { | |
val split = hash.split(":") | |
val salt = split[0] | |
val hashed = split[1] | |
return hash(salt + password) == hashed | |
} | |
private fun hash(password: String): String { | |
return Base64.getEncoder().encodeToString(MessageDigest.getInstance("SHA-256").digest(password.toByteArray(StandardCharsets.UTF_8))) | |
} | |
@JvmStatic | |
protected fun registerUser(username: String, email: String, password: String) : Int { | |
var userId = -1 | |
sql("SELECT id, password FROM users WHERE username = ?", username.toLowerCase()){ | |
val pass = it?.get<String>(2) | |
if(pass != null){ | |
userId = | |
if(hash(password.toLowerCase()) == pass) | |
it.get(1)!! | |
else -2 | |
} | |
} | |
if(userId == -1){ | |
sql("INSERT INTO users (username, email, password) VALUES (?, ?, ?)", | |
username.toLowerCase(), | |
email.toLowerCase(), | |
createHash(password.toLowerCase())) | |
sql("SELECT id FROM users WHERE username = ?", username.toLowerCase()){ | |
userId = it?.get() ?: -1 // Cannot really be -1, but what the heck. | |
} | |
} | |
return userId | |
} | |
@JvmStatic | |
protected fun loginUser(username: String, password: String) : Int { | |
var userId = -1 | |
sql("SELECT id, password FROM users WHERE username = ?", username.toLowerCase()){ | |
val pass = it?.get<String>(2) | |
if(pass != null) | |
userId = if(matchHash(password.toLowerCase(), pass)) | |
it.get(1) ?: -1 | |
else -2 | |
} | |
return userId | |
} | |
} | |
inner class SQL(val name: String? = null) { | |
inline operator fun <reified T> getValue(ref: Any?, property: KProperty<*>) : T { | |
var value: T? = null | |
sql("SELECT ${name ?: property.name} FROM users where id = ?", id){ | |
value = it.get() | |
} | |
return value ?: error("Database Connection Error. value is null.") | |
} | |
operator fun <T> setValue(ref: Any?, property: KProperty<*>, value: T) { | |
sql("UPDATE users SET ${name ?: property.name} = ? WHERE id = ?", value!!, id) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment