Big refactoring #77
@@ -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())
|
||||||
|
|||||||
@@ -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()) }
|
||||||
|
|
||||||
|
|||||||
@@ -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))
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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 !")
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
Reference in New Issue
Block a user