1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
package space.anity
import io.javalin.*
import io.javalin.rendering.template.TemplateUtil.model
import org.joda.time.*
import java.util.logging.*
import kotlin.math.*
class UserHandler {
private val log = Logger.getLogger(this.javaClass.name)
/**
* Renders the login page
*/
fun renderLogin(ctx: Context) {
if (userHandler.getVerifiedUserId(ctx) > 0 || !databaseController.isSetup()) ctx.redirect("/")
else ctx.render("login.rocker.html", model("message", "", "counter", 0))
}
/**
* Checks and verifies users credentials and logs the user in
*/
fun login(ctx: Context) {
if (getVerifiedUserId(ctx) > 0 || !databaseController.isSetup()) ctx.redirect("/")
val username = ctx.formParam("username").toString()
val password = ctx.formParam("password").toString()
val requestIp = ctx.ip()
val loginAttempts = databaseController.getLoginAttempts(requestIp)
val lastAttemptDifference =
if (loginAttempts.isEmpty()) -1
else Interval(
loginAttempts[loginAttempts.indexOfLast { true }].first.toInstant(),
Instant()
).toDuration().standardSeconds.toInt()
var lastHourAttempts = 0
loginAttempts.forEach {
val difference = Interval(it.first.toInstant(), Instant()).toDuration().standardMinutes.toInt()
if (difference < 60) lastHourAttempts += 1
}
val nextThreshold = 4f.pow(lastHourAttempts + 1)
if (lastAttemptDifference > 4f.pow(lastHourAttempts) || lastHourAttempts == 0) {
if (databaseController.checkUser(username, password)) {
ctx.cookieStore("verification", databaseController.getVerificationId(username))
ctx.cookieStore("userId", databaseController.getUserId(username))
ctx.redirect("/")
} else {
databaseController.loginAttempt(DateTime(), requestIp)
ctx.render(
"login.rocker.html",
model(
"message",
"Login failed!",
"counter", if (nextThreshold / 60 > 60) 3600 else nextThreshold.toInt()
)
)
}
} else {
databaseController.loginAttempt(DateTime(), requestIp)
ctx.render(
"login.rocker.html",
model(
"message",
"Too many request.",
"counter", if (nextThreshold / 60 > 60) 3600 else nextThreshold.toInt()
)
)
}
}
/**
* Logs the user out of the system
*/
fun logout(ctx: Context) {
ctx.clearCookieStore()
ctx.removeCookie("javalin-cookie-store", "/")
ctx.redirect("/")
}
/**
* Renders the setup page
*/
fun renderSetup(ctx: Context) {
if (databaseController.isSetup()) ctx.redirect("/user/login")
else ctx.render("setup.rocker.html", model("message", ""))
}
/**
* Sets up the general settings and admin credentials
*/
fun setup(ctx: Context) {
try {
val username = ctx.formParam("username").toString()
val password = ctx.formParam("password").toString()
val verifyPassword = ctx.formParam("verifyPassword").toString()
if (password == verifyPassword) {
if (databaseController.createUser(username, password, "ADMIN")) {
databaseController.toggleSetup()
ctx.redirect("/user/login")
} else ctx.status(400).render("setup.rocker.html", model("message", "User already exists!"))
} else ctx.status(400).render("setup.rocker.html", model("message", "Passwords do not match!"))
} catch (_: Exception) {
ctx.status(400).render("setup.rocker.html", model("message", "An error occurred!"))
}
}
/**
* Renders the registration page
*/
fun renderRegistration(ctx: Context) {
val username = ctx.queryParam("username", "")
if (username.isNullOrEmpty()) ctx.status(403).result("Please provide a valid username!")
else {
if (databaseController.isUserRegistrationValid(username))
ctx.render("register.rocker.html", model("username", username, "message", ""))
else ctx.redirect("/user/login")
}
}
/**
* Registers a new user
*/
fun register(ctx: Context) {
try {
val username = ctx.formParam("username").toString()
val password = ctx.formParam("password").toString()
val verifyPassword = ctx.formParam("verifyPassword").toString()
if (password == verifyPassword) {
if (databaseController.isUserRegistrationValid(username)) {
databaseController.createUser(username, password, "USER")
databaseController.removeRegistrationIndex(username)
ctx.redirect("/user/login")
} else ctx.status(401).result("This user is not authorized to register.")
} else ctx.status(400).result("The passwords don't match!")
} catch (_: Exception) {
ctx.status(400).result("An exception occured.")
}
}
/**
* Gets the username and verifies its identity
*/
fun getVerifiedUserId(ctx: Context): Int {
return if (databaseController.getUserIdByVerificationId(ctx.cookieStore("verification") ?: "verification")
== ctx.cookieStore("userId") ?: "userId"
) ctx.cookieStore("userId")
else -1
}
}
|