Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions app/src/main/kotlin/pro/qyoga/app/QYogaApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ import pro.qyoga.core.therapy.TherapyConfig
import pro.qyoga.core.users.UsersConfig
import pro.qyoga.i9ns.calendars.google.GoogleCalendarConf
import pro.qyoga.i9ns.calendars.ical.ICalCalendarsConfig
import pro.qyoga.i9ns.email.EmailsConfig
import pro.qyoga.i9ns.email.EmailI9nsConf
import pro.qyoga.i9ns.pushes.web.WebPushesConf
import pro.qyoga.infra.auth.AuthConfig
import pro.qyoga.infra.cache.CacheConf
import pro.qyoga.infra.db.SdjConfig
import pro.qyoga.infra.email.EmailsConfig
import pro.qyoga.infra.minio.MinioConfig
import pro.qyoga.infra.timezones.TimeZonesConfig
import pro.qyoga.infra.web.ThymeleafConfig
Expand All @@ -40,7 +41,7 @@ import pro.qyoga.tech.captcha.CaptchaConf
CalendarGatewaysConf::class,

// I9ns
EmailsConfig::class,
EmailI9nsConf::class,
ICalCalendarsConfig::class,
GoogleCalendarConf::class,
WebPushesConf::class,
Expand All @@ -57,7 +58,8 @@ import pro.qyoga.tech.captcha.CaptchaConf
MinioConfig::class,
FilesStorageConfig::class,
TimeZonesConfig::class,
CacheConf::class
CacheConf::class,
EmailsConfig::class,
)
@SpringBootApplication
class QYogaApp
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
package pro.qyoga.app.publc.register

import org.slf4j.LoggerFactory
import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component
import pro.azhidkov.platform.errors.DomainError
import pro.azhidkov.platform.kotlin.mapFailure
import pro.qyoga.core.users.auth.UsersFactory
import pro.qyoga.core.users.auth.UsersRepo
import pro.azhidkov.platform.secrets.SecretChars
import pro.qyoga.core.users.auth.errors.DuplicatedEmailException
import pro.qyoga.core.users.therapists.CreateTherapistUserOp
import pro.qyoga.core.users.therapists.RegisterTherapistRequest
import pro.qyoga.core.users.therapists.Therapist
import pro.qyoga.core.users.therapists.TherapistsRepo
import pro.qyoga.core.users.therapists.createTherapistUser
import pro.qyoga.i9ns.email.Email
import pro.qyoga.i9ns.email.EmailSender
import pro.qyoga.i9ns.email.NewUserRegisteredMessageChannel
import pro.qyoga.i9ns.email.WelcomeMessageChannel
import pro.qyoga.tech.captcha.CaptchaService
import java.awt.image.BufferedImage
import java.util.*
Expand Down Expand Up @@ -53,28 +50,15 @@ class RegistrationException(

@Component
class RegisterTherapistOp(
private val usersRepo: UsersRepo,
private val therapistsRepo: TherapistsRepo,
private val usersFactory: UsersFactory,
private val emailSender: EmailSender,
private val createTherapistUser: CreateTherapistUserOp,
private val captchaService: CaptchaService,
@Value("\${spring.mail.username}") private val fromEmail: String,
@Value("\${trainer-advisor.admin.email}") private val adminEmail: String
) : (RegisterTherapistRequest) -> Therapist {
private val welcomeMessageChannel: WelcomeMessageChannel,
private val newUserRegisteredMessageChannel: NewUserRegisteredMessageChannel,
) {

private val log = LoggerFactory.getLogger(javaClass)

private val createTherapistUser = { registerTherapistRequest: RegisterTherapistRequest, password: CharSequence ->
createTherapistUser(
usersRepo,
therapistsRepo,
usersFactory,
registerTherapistRequest,
password
)
}

override fun invoke(registerTherapistRequest: RegisterTherapistRequest): Therapist {
operator fun invoke(registerTherapistRequest: RegisterTherapistRequest): Therapist {
if (captchaService.isInvalid(registerTherapistRequest.captchaAnswer)) {
log.info("Register therapist with invalid captcha request terminated")
throw RegistrationException.invalidCaptcha(newCaptcha = captchaService.generateCaptcha())
Expand All @@ -93,43 +77,19 @@ class RegisterTherapistOp(
}
.getOrThrow()

emailSender.sendEmail(
welcomeEmail(to = registerTherapistRequest.email, password = password)
welcomeMessageChannel.sendWelcomeMessage(
therapistEmail = registerTherapistRequest.email,
password = password
)
newUserRegisteredMessageChannel.sendNewUserRegisteredMessage(
therapistEmail = registerTherapistRequest.email
)
emailSender.sendEmail(newRegistrationEmail(to = adminEmail, therapistEmail = registerTherapistRequest.email))

log.info("Therapist for {} registered", registerTherapistRequest.email)

return therapist
}

private fun welcomeEmail(to: String, password: String) =
Email(
fromEmail,
to,
"Добро пожаловать в Trainer Advisor",
"""
Здравствуйте!

Вы зарегистрировались в Trainer Advisor.
Логин от вашего аккаунта: $to.
Пароль от вашего аккаунта: $password.

Теперь вы можете войти в систему на странице https://trainer-advisor.pro/login используя email и пароль из этого письма.

С уважением, команда Trainer Advisor.
""".trimIndent()
)

private fun newRegistrationEmail(to: String, therapistEmail: String) = Email(
fromEmail,
to,
"Новый терапевт добавлен в систему",
"""
Email: $therapistEmail
""".trimIndent()
)

}

private val passwordChars = ('a'..'z').toList() + ('A'..'Z').toList() + ('0'..'9').toList()
Expand All @@ -142,4 +102,4 @@ private fun generateRandomPassword() =
append(passwordChars[Random.nextInt(passwordChars.size)])
}
}

.let { SecretChars(it.toCharArray()) }
19 changes: 0 additions & 19 deletions app/src/main/kotlin/pro/qyoga/core/users/auth/UsersFactory.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package pro.qyoga.core.users.therapists

import org.slf4j.LoggerFactory
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.stereotype.Component
import pro.azhidkov.platform.secrets.SecretChars
import pro.qyoga.core.users.auth.UsersRepo
import pro.qyoga.core.users.auth.model.Role
import pro.qyoga.core.users.auth.model.User

@Component
class CreateTherapistUserOp(
private val usersRepo: UsersRepo,
private val therapistsRepo: TherapistsRepo,
private val passwordEncoder: PasswordEncoder
) {
private val log = LoggerFactory.getLogger("createTherapistUser")

operator fun invoke(
registerTherapistRequest: RegisterTherapistRequest,
password: SecretChars
): Therapist {
log.info("Creating new therapist user for {}", registerTherapistRequest.email)

var user = createUser(registerTherapistRequest.email, password, setOf(Role.ROLE_THERAPIST))
user = usersRepo.save(user)

var therapist = Therapist(registerTherapistRequest.firstName, registerTherapistRequest.lastName, user.id)
therapist = therapistsRepo.save(therapist)

log.info("Therapist user created, id = {}", user.id)

return therapist
}

private fun createUser(email: String, plainPassword: SecretChars, roles: Set<Role>): User {
val passwordHash = passwordEncoder.encode(plainPassword.show())!!
return User(email, passwordHash, roles.toTypedArray(), enabled = true)
}

}

This file was deleted.

9 changes: 9 additions & 0 deletions app/src/main/kotlin/pro/qyoga/i9ns/email/EmailI9nsConf.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package pro.qyoga.i9ns.email

import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration


@Configuration
@ComponentScan
class EmailI9nsConf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package pro.qyoga.i9ns.email

import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component
import pro.qyoga.infra.email.Email
import pro.qyoga.infra.email.EmailSender


@Component
class NewUserRegisteredMessageChannel(
private val emailSender: EmailSender,
@Value("\${spring.mail.username}") private val fromEmail: String,
@Value("\${trainer-advisor.admin.email}") private val adminEmail: String
) {

fun sendNewUserRegisteredMessage(therapistEmail: String) {
emailSender.sendEmail(newRegistrationEmail(adminEmail, therapistEmail))
}

private fun newRegistrationEmail(to: String, therapistEmail: String) = Email(
from = fromEmail,
to = to,
subject = "Новый терапевт добавлен в систему",
text = "Email: $therapistEmail"
)

}
41 changes: 41 additions & 0 deletions app/src/main/kotlin/pro/qyoga/i9ns/email/WelcomeMessageChannel.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package pro.qyoga.i9ns.email

import org.springframework.beans.factory.annotation.Value
import org.springframework.stereotype.Component
import pro.azhidkov.platform.secrets.SecretChars
import pro.qyoga.infra.email.Email
import pro.qyoga.infra.email.EmailSender


@Component
class WelcomeMessageChannel(
private val emailSender: EmailSender,
@Value("\${spring.mail.username}") private val fromEmail: String,
) {

fun sendWelcomeMessage(
therapistEmail: String,
password: SecretChars
) {
emailSender.sendEmail(welcomeEmail(therapistEmail, password.show()))
}

private fun welcomeEmail(to: String, password: String) =
Email(
fromEmail,
to,
"Добро пожаловать в Trainer Advisor",
"""
Здравствуйте!

Вы зарегистрировались в Trainer Advisor.
Логин от вашего аккаунта: $to.
Пароль от вашего аккаунта: $password.

Теперь вы можете войти в систему на странице https://trainer-advisor.pro/login используя email и пароль из этого письма.

С уважением, команда Trainer Advisor.
""".trimIndent()
)

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package pro.qyoga.i9ns.email
package pro.qyoga.infra.email

data class Email(
val from: String,
val to: String,
val subject: String,
val text: String
)
)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package pro.qyoga.i9ns.email
package pro.qyoga.infra.email

import org.slf4j.LoggerFactory
import org.springframework.mail.javamail.JavaMailSender
Expand All @@ -25,4 +25,4 @@ class EmailSender(
mailSender.send(mail)
}

}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package pro.qyoga.i9ns.email
package pro.qyoga.infra.email

import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration

@ComponentScan
@Configuration
class EmailsConfig
class EmailsConfig
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class CreateClientPageTest : QYogaAppIntegrationBaseTest() {
fun `System should allow to create client with existing phone number for another therapist`() {
// Given
val thePhone = randomPhoneNumber().toUIFormat()
val anotherTherapistId = backgrounds.users.registerNewTherapist().id
val anotherTherapistId = backgrounds.users.createNewTherapist().id
backgrounds.clients.createClient(phone = thePhone, therapistId = anotherTherapistId)
val duplicatedClient = ClientsObjectMother.createClientCardDto(phone = thePhone)
val therapist = TherapistClient.loginAsTheTherapist()
Expand All @@ -105,4 +105,4 @@ class CreateClientPageTest : QYogaAppIntegrationBaseTest() {
clients.forAny { it shouldMatch duplicatedClient }
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class EditClientCardPageTest : QYogaAppIntegrationBaseTest() {
fun `должна сохранять телефон, указанный для другого клиента другого терапевта`() {
// Сетап
val thePhone = randomPhoneNumber().toUIFormat()
val anotherTherapistId = backgrounds.users.registerNewTherapist().id
val anotherTherapistId = backgrounds.users.createNewTherapist().id
backgrounds.clients.createClient(phone = thePhone, therapistId = anotherTherapistId)
val targetClient = backgrounds.clients.createClient()
val updatePhoneDto = targetClient.toDto().copy(phoneNumber = thePhone)
Expand All @@ -153,4 +153,4 @@ class EditClientCardPageTest : QYogaAppIntegrationBaseTest() {
clients.forAny { it shouldMatch updatePhoneDto }
}

}
}
Loading
Loading