Skip to content

Commit

Permalink
feat: use parsek-plugin-token v1.2.0 and add sending magic change e-mail
Browse files Browse the repository at this point in the history
  • Loading branch information
duruer committed Jun 17, 2024
1 parent b7247f5 commit dcf04ea
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 6 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ dependencies {
} else {
compileOnly("com.github.StatuParsek:Parsek:main-SNAPSHOT")
compileOnly("com.github.StatuParsek:parsek-plugin-database:main-SNAPSHOT")
compileOnly("com.github.StatuParsek:parsek-plugin-token:main-SNAPSHOT")
compileOnly("com.github.StatuParsek:parsek-plugin-token:v1.2.0")
compileOnly("com.github.StatuParsek:parsek-plugin-mail:main-SNAPSHOT")
compileOnly("com.github.StatuParsek:parsek-plugin-system-property:main-SNAPSHOT")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ class TokenEventHandler : TokenEventListener {
ConfirmDeleteAccountToken(),
MagicLoginToken(),
MagicRegisterToken(),
RegisterToken()
RegisterToken(),
MagicChangeEmailToken()
)
)
}
Expand Down
62 changes: 62 additions & 0 deletions src/main/kotlin/co/statu/rule/auth/mail/MagicChangeMail.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package co.statu.rule.auth.mail

import co.statu.parsek.api.config.PluginConfigManager
import co.statu.rule.auth.AuthConfig
import co.statu.rule.auth.db.dao.UserDao
import co.statu.rule.auth.db.impl.UserDaoImpl
import co.statu.rule.auth.token.MagicChangeEmailToken
import co.statu.rule.auth.util.OneTimeCodeGenerator
import co.statu.rule.auth.util.SecurityUtil
import co.statu.rule.database.DatabaseManager
import co.statu.rule.mail.Mail
import co.statu.rule.token.provider.TokenProvider
import io.vertx.core.json.JsonObject
import io.vertx.jdbcclient.JDBCPool
import java.util.*

class MagicChangeMail(private val pluginConfigManager: PluginConfigManager<AuthConfig>) : Mail {
override val templatePath = "magic-change.hbs"
override val subject = "Yeni E-Posta'nı Onayla - ${getBrandName()}"

private val magicChangeEmailToken = MagicChangeEmailToken()

private val userDao: UserDao = UserDaoImpl()

override suspend fun parameterGenerator(
email: String,
userId: UUID,
uiAddress: String,
databaseManager: DatabaseManager,
jdbcPool: JDBCPool,
tokenProvider: TokenProvider
): JsonObject {
val parameters = JsonObject()

val code = OneTimeCodeGenerator.generate()
val formattedCode = code.replace("-", "")

val config = pluginConfigManager.config
val secretKey = config.secretKey

tokenProvider.saveToken(
formattedCode,
userId.toString(),
magicChangeEmailToken,
magicChangeEmailToken.getExpireDateFromNow(),
jdbcPool
)

val signature = SecurityUtil.encodeSha256HMAC(secretKey, email + formattedCode)

val user = userDao.getById(userId, jdbcPool)!!

parameters.put("link", "$uiAddress/auth/link?code=$code&email=$email&signature=$signature")
parameters.put("code", code)

user.additionalFields.forEach {
parameters.put(it.key, it.value)
}

return parameters
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import co.statu.rule.auth.error.InvalidEmail
import co.statu.rule.auth.error.InvalidSignature
import co.statu.rule.auth.error.InvalidSignatureOrRecaptcha
import co.statu.rule.auth.provider.AuthProvider
import co.statu.rule.auth.token.MagicChangeEmailToken
import co.statu.rule.auth.token.MagicLoginToken
import co.statu.rule.auth.token.MagicRegisterToken
import co.statu.rule.auth.token.RegisterToken
Expand Down Expand Up @@ -71,6 +72,8 @@ class VerifyMagicLinkAPI(

private val magicRegisterToken = MagicRegisterToken()

private val magicChangeEmailToken = MagicChangeEmailToken()

private val registerTokenObject = RegisterToken()

private val magicLoginToken = MagicLoginToken()
Expand Down Expand Up @@ -110,6 +113,26 @@ class VerifyMagicLinkAPI(

val jdbcPool = databaseManager.getConnectionPool()

val changeEmailToken = tokenDao.getByTokenSubjectAndType(magicCode, email, magicChangeEmailToken, jdbcPool)

if (changeEmailToken != null) {
tokenProvider.invalidateTokensBySubjectAndType(email, magicLoginToken, jdbcPool)
tokenProvider.invalidateTokensBySubjectAndType(email, magicChangeEmailToken, jdbcPool)

val userId = userDao.getUserIdFromEmail(email, jdbcPool)!!
val user = userDao.getById(userId, jdbcPool)!!

user.email = email

userDao.update(user, jdbcPool)

return Successful(
mapOf(
"magicLinkType" to MagicLinkType.CHANGE_EMAIl
)
)
}

val registerToken =
tokenDao.getByTokenSubjectAndType(magicCode, email, magicRegisterToken, jdbcPool)

Expand Down Expand Up @@ -174,6 +197,6 @@ class VerifyMagicLinkAPI(
}

enum class MagicLinkType {
REGISTER, LOGIN
REGISTER, LOGIN, CHANGE_EMAIl
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package co.statu.rule.auth.route.profile

import co.statu.parsek.annotation.Endpoint
import co.statu.parsek.api.config.PluginConfigManager
import co.statu.parsek.model.*
import co.statu.rule.auth.AuthConfig
import co.statu.rule.auth.AuthFieldManager
import co.statu.rule.auth.AuthPlugin
import co.statu.rule.auth.api.LoggedInApi
import co.statu.rule.auth.error.EmailNotAvailable
import co.statu.rule.auth.error.InvalidEmail
import co.statu.rule.auth.mail.MagicChangeMail
import co.statu.rule.auth.provider.AuthProvider
import co.statu.rule.database.DatabaseManager
import co.statu.rule.mail.MailManager
import io.vertx.core.json.JsonObject
import io.vertx.ext.web.RoutingContext
import io.vertx.ext.web.validation.RequestPredicate
Expand All @@ -19,6 +23,7 @@ import io.vertx.json.schema.SchemaParser
import io.vertx.json.schema.common.dsl.Schemas.objectSchema
import io.vertx.json.schema.common.dsl.Schemas.stringSchema
import org.apache.commons.validator.routines.EmailValidator
import java.util.*

@Endpoint
class UpdateProfileAPI(
Expand All @@ -38,6 +43,14 @@ class UpdateProfileAPI(
authPlugin.pluginBeanContext.getBean(AuthFieldManager::class.java)
}

private val pluginConfigManager by lazy {
authPlugin.pluginBeanContext.getBean(PluginConfigManager::class.java) as PluginConfigManager<AuthConfig>
}

private val mailManager by lazy {
authPlugin.pluginBeanContext.getBean(MailManager::class.java)
}

override fun getValidationHandler(schemaParser: SchemaParser): ValidationHandler =
ValidationHandlerBuilder.create(schemaParser)
.body(
Expand Down Expand Up @@ -73,10 +86,8 @@ class UpdateProfileAPI(
if (emailExists) {
throw Errors(mapOf("email" to EmailNotAvailable()))
}
}

if (email != null) {
user.email = email
sendChangeEmailLink(user.id, email)
}

val additionalFields = authFieldManager.getAdditionalFields(data)
Expand All @@ -103,4 +114,8 @@ class UpdateProfileAPI(

authFieldManager.validateFields(data, additionalFields)
}

private suspend fun sendChangeEmailLink(userId: UUID, email: String) {
mailManager.sendMail(userId, email, MagicChangeMail(pluginConfigManager))
}
}
14 changes: 14 additions & 0 deletions src/main/kotlin/co/statu/rule/auth/token/MagicChangeEmailToken.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package co.statu.rule.auth.token

import co.statu.rule.token.type.TokenType
import java.util.*

class MagicChangeEmailToken : TokenType {
override fun getExpireDateFromNow(): Long {
val calendar = Calendar.getInstance()

calendar.add(Calendar.MINUTE, 15)

return calendar.timeInMillis
}
}

0 comments on commit dcf04ea

Please sign in to comment.