Big refactoring #77

Merged
flecomte merged 166 commits from refactoring-component-and-immutable into master 2021-03-24 19:06:07 +01:00
7 changed files with 27 additions and 23 deletions
Showing only changes of commit 1b6549eae3 - Show all commits

View File

@@ -18,7 +18,7 @@ import fr.dcproject.component.auth.UserRepository
import fr.dcproject.component.auth.jwt.JwtConfig import fr.dcproject.component.auth.jwt.JwtConfig
import fr.dcproject.component.auth.routes.authLogin import fr.dcproject.component.auth.routes.authLogin
import fr.dcproject.component.auth.routes.authRegister import fr.dcproject.component.auth.routes.authRegister
import fr.dcproject.component.auth.routes.authSso import fr.dcproject.component.auth.routes.authPasswordless
import fr.dcproject.component.auth.user import fr.dcproject.component.auth.user
import fr.dcproject.component.citizen.routes.changeMyPassword import fr.dcproject.component.citizen.routes.changeMyPassword
import fr.dcproject.component.citizen.routes.findCitizen import fr.dcproject.component.citizen.routes.findCitizen
@@ -196,7 +196,7 @@ fun Application.module(env: Env = PROD) {
/* Auth */ /* Auth */
authLogin(get()) authLogin(get())
authRegister(get()) authRegister(get())
authSso(get()) authPasswordless(get())
/* Workgroup */ /* Workgroup */
getWorkgroups(get(), get()) getWorkgroups(get(), get())
getWorkgroup(get(), get()) getWorkgroup(get(), get())

View File

@@ -11,7 +11,7 @@ import com.rabbitmq.client.ConnectionFactory
import fr.dcproject.component.article.ArticleRepository import fr.dcproject.component.article.ArticleRepository
import fr.dcproject.component.article.ArticleViewManager import fr.dcproject.component.article.ArticleViewManager
import fr.dcproject.component.article.ArticleVoter import fr.dcproject.component.article.ArticleVoter
import fr.dcproject.component.auth.SsoManager import fr.dcproject.component.auth.PasswordlessAuth
import fr.dcproject.component.auth.UserRepository import fr.dcproject.component.auth.UserRepository
import fr.dcproject.component.citizen.CitizenRepository import fr.dcproject.component.citizen.CitizenRepository
import fr.dcproject.component.citizen.CitizenVoter import fr.dcproject.component.citizen.CitizenVoter
@@ -136,8 +136,8 @@ val KoinModule = module {
// Mailer // Mailer
single { Mailer(Configuration.sendGridKey) } single { Mailer(Configuration.sendGridKey) }
// SSO Manager for connection // Used to send a connexion link by email
single { SsoManager(get<Mailer>(), Configuration.domain, get()) } single { PasswordlessAuth(get<Mailer>(), Configuration.domain, get()) }
single { Publisher(get(), get()) } single { Publisher(get(), get()) }

View File

@@ -11,9 +11,9 @@ import fr.dcproject.messages.Mailer
import io.ktor.http.* import io.ktor.http.*
/** /**
* Send an email to the citizen with a link to automatically connect * Send a connexion link by email
*/ */
class SsoManager( class PasswordlessAuth(
private val mailer: Mailer, private val mailer: Mailer,
private val domain: String, private val domain: String,
private val citizenRepo: CitizenRepository private val citizenRepo: CitizenRepository
@@ -27,7 +27,7 @@ class SsoManager(
mailer.sendEmail { mailer.sendEmail {
val token = citizen.user.makeToken() val token = citizen.user.makeToken()
Mail( Mail(
Email("sso@$domain"), Email("passwordless-auth@$domain"),
"Connection", "Connection",
Email(citizen.email), Email(citizen.email),
Content("text/plain", generateContent(token, url)) Content("text/plain", generateContent(token, url))

View File

@@ -1,7 +1,7 @@
package fr.dcproject.component.auth.routes package fr.dcproject.component.auth.routes
import fr.dcproject.component.auth.SsoManager import fr.dcproject.component.auth.PasswordlessAuth
import fr.dcproject.component.auth.routes.SsoRequest.Input import fr.dcproject.component.auth.routes.PasswordlessRequest.Input
import io.ktor.application.* import io.ktor.application.*
import io.ktor.http.* import io.ktor.http.*
import io.ktor.locations.* import io.ktor.locations.*
@@ -11,8 +11,8 @@ import io.ktor.routing.*
import io.ktor.util.* import io.ktor.util.*
@KtorExperimentalLocationsAPI @KtorExperimentalLocationsAPI
@Location("/sso") @Location("/auth/passwordless")
class SsoRequest { class PasswordlessRequest {
data class Input(val email: String, val url: String) data class Input(val email: String, val url: String)
} }
@@ -21,12 +21,12 @@ class SsoRequest {
*/ */
@KtorExperimentalLocationsAPI @KtorExperimentalLocationsAPI
@KtorExperimentalAPI @KtorExperimentalAPI
fun Route.authSso(ssoManager: SsoManager) { fun Route.authPasswordless(passwordlessAuth: PasswordlessAuth) {
post<SsoRequest> { post<PasswordlessRequest> {
call.receive<Input>().run { call.receive<Input>().run {
try { try {
ssoManager.sendEmail(email, url) passwordlessAuth.sendEmail(email, url)
} catch (e: SsoManager.EmailNotFound) { } catch (e: PasswordlessAuth.EmailNotFound) {
call.respond(HttpStatusCode.NotFound) call.respond(HttpStatusCode.NotFound)
} }
call.respond(HttpStatusCode.NoContent) call.respond(HttpStatusCode.NoContent)

View File

@@ -37,12 +37,16 @@ paths:
text/plain: text/plain:
example: example:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJBdXRoZW50aWNhdGlvbiIsImlzcyI6ImRjLXByb2plY3QuZnIiLCJpZCI6ImQ1NDRhNmE4LWJhYjgtNDU2MC05NWIxLThhZjAyMDNkOTEwNCIsImV4cCI6MTU2NzA3Mzc0Mn0.0VTetv8fZFjVgpJ-bwJpidGNHJUOmgj8vuZcZXzwnLa7TtFwcXWvh3bDPYHqB66nmOfXyM57XnHDbmRwtipCag eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJBdXRoZW50aWNhdGlvbiIsImlzcyI6ImRjLXByb2plY3QuZnIiLCJpZCI6ImQ1NDRhNmE4LWJhYjgtNDU2MC05NWIxLThhZjAyMDNkOTEwNCIsImV4cCI6MTU2NzA3Mzc0Mn0.0VTetv8fZFjVgpJ-bwJpidGNHJUOmgj8vuZcZXzwnLa7TtFwcXWvh3bDPYHqB66nmOfXyM57XnHDbmRwtipCag
/sso: /auth/passwordless:
post: post:
summary: Send email with JWT summary: Send a connexion link by email
description: Send a connexion link by email with the token required to the connexion
externalDocs:
description: Explanation of Passwordless auth
url: https://en.wikipedia.org/wiki/Passwordless_authentication
tags: tags:
- authentification - authentification
operationId: sso operationId: passwordless
requestBody: requestBody:
content: content:
application/json: application/json:
@@ -58,7 +62,7 @@ paths:
type: string type: string
description: url tu redirect with the token description: url tu redirect with the token
example: example:
http://dc-project.fr/sso http://dc-project.fr/auth/passwordless
responses: responses:
204: 204:

View File

@@ -28,7 +28,7 @@ class MailerTest : KoinTest, AutoCloseKoinTest() {
withTestApplication({ module(TEST) }) { withTestApplication({ module(TEST) }) {
get<Mailer>().sendEmail { get<Mailer>().sendEmail {
Mail( Mail(
Email("sso@dc-project.fr"), Email("passwordless-auth@dc-project.fr"),
"Test", "Test",
Email("fabrice.lecomte.be@gmail.com"), Email("fabrice.lecomte.be@gmail.com"),
Content("text/plain", "Email Work !") Content("text/plain", "Email Work !")

View File

@@ -24,13 +24,13 @@ Feature: citizens routes
| id | 47356809-c8ef-4649-8b99-1c5cb9886d38 | | id | 47356809-c8ef-4649-8b99-1c5cb9886d38 |
@online @online
Scenario: Can be connect with SSO Scenario: Can be connect with Passwordless auth
Given I have citizen Given I have citizen
| id | c606110c-ff0e-4d09-a79e-74632d7bf7bd | | id | c606110c-ff0e-4d09-a79e-74632d7bf7bd |
| email | fabrice.lecomte.be@gmail.com | | email | fabrice.lecomte.be@gmail.com |
| firstName | Leonhard | | firstName | Leonhard |
| lastName | Euler | | lastName | Euler |
When I send a POST request to "/sso" with body: When I send a POST request to "/auth/passwordless" with body:
""" """
{ {
"url": "https://dc-project.fr/password/reset", "url": "https://dc-project.fr/password/reset",