Compare commits

...
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

16 Commits

Author SHA1 Message Date
Override-6 8692ed55c3 writting some tests
continuous-integration/drone/push Build is failing Details
2 years ago
Override-6 b94b4493e2 modified drone script
continuous-integration/drone/push Build is failing Details
continuous-integration/drone Build is passing Details
2 years ago
Override-6 d7c57f06fa fixing tests and added script to generate key pairs for tests
continuous-integration/drone/push Build was killed Details
2 years ago
Override-6 023f847b06 fixing tests and drone
continuous-integration/drone/push Build is failing Details
2 years ago
Override-6 708c3308d5 fix
continuous-integration/drone/push Build is passing Details
2 years ago
Override-6 01eebf9bc1 fix
continuous-integration/drone/push Build is failing Details
2 years ago
Override-6 b1380d2d5a fix
continuous-integration/drone/push Build is failing Details
2 years ago
Override-6 7b7eed885d fix
continuous-integration/drone/push Build is failing Details
2 years ago
Override-6 c4fae28f43 fix
continuous-integration/drone/push Build is failing Details
2 years ago
Override-6 87accaf7a2 fixing scripts
continuous-integration/drone/push Build is failing Details
2 years ago
Override-6 21249c1b82 triggering
continuous-integration/drone/push Build is failing Details
2 years ago
Override-6 05288f089f fixing scripts
continuous-integration/drone/push Build is failing Details
2 years ago
Override-6 a0652bb3d0 test commit
continuous-integration/drone/push Build was killed Details
continuous-integration/drone Build is failing Details
2 years ago
Override-6 2c5b54d5ff added git and docker to drone Deploy docker images pipeline
continuous-integration/drone/push Build was killed Details
2 years ago
Override-6 fb83280c79 fixing drone
continuous-integration/drone/push Build is failing Details
2 years ago
Override-6 a4196fae1b setting up docker image auto push
continuous-integration/drone/push Build was killed Details
2 years ago

@ -1,7 +1,7 @@
package org.tbasket
import org.apache.logging.log4j.LogManager
import org.tbasket.auth.Authentificator
import org.tbasket.auth.Authenticator
import org.tbasket.config.{FileServerConfig, ServerConfig}
import org.tbasket.data.Database
import org.tbasket.endpoint.Endpoint
@ -44,7 +44,7 @@ object Main extends ZIOAppDefault:
private def setupAuth(config: ServerConfig) = ZIO.attempt {
val publicKey = config.emitterCertificate.getPublicKey
val auth = new Authentificator(config.emitterURL, publicKey, config.emitterKeyAlgorithm)
val auth = new Authenticator(config.emitterURL, publicKey, config.emitterKeyAlgorithm)
ZLayer.succeed(auth)
}

@ -9,7 +9,7 @@ import io.getquill.context.qzio.ZioJdbcContext
import io.getquill.context.sql.idiom.SqlIdiom
import org.apache.logging.log4j.LogManager
import org.tbasket.InternalBasketServerException
import org.tbasket.auth.Authentificator.*
import org.tbasket.auth.Authenticator.*
import org.tbasket.data.{DatabaseContext, User}
import org.tbasket.error.AuthException.*
import org.tbasket.error.ExceptionEnum
@ -31,18 +31,20 @@ import javax.sql.DataSource
import scala.collection.immutable.HashMap
case class JwtContent(uuid: UUID)
object Authentificator:
object Authenticator:
private final val LOG = LogManager.getLogger("Authentification")
private final val ValidMailPattern = "^\\w+([.-]?\\w+)*@\\w+([.-]?\\w+)*(\\.\\w{2,3})+$".r
private final val ValidPasswordPattern = ".{6,}".r
class Authentificator(url: URL, key: PublicKey, algorithm: JwtAsymmetricAlgorithm) {
case class JwtContent(uuid: UUID)
class Authenticator(url: URL, key: PublicKey, algorithm: JwtAsymmetricAlgorithm) {
private def defineCustomClaims(user: User): String = {
JwtContent(user.id).asJson.noSpaces.toString
JwtContent(user.id).asJson.noSpaces
}
private def mkRequest(user: User): Request = {

@ -5,7 +5,7 @@ import io.getquill.context.sql.idiom.SqlIdiom
import io.getquill.idiom.Idiom
import io.getquill.{Literal, NamingStrategy, SqliteDialect}
import org.apache.logging.log4j.LogManager
import org.tbasket.auth.Authentificator
import org.tbasket.auth.Authenticator
import org.tbasket.data.DatabaseContext
import org.tbasket.endpoint.Endpoint.LOG
import org.tbasket.handler.LoginPageHandler
@ -77,7 +77,7 @@ class Endpoint(port: Int):
Server.install(app).flatMap { port =>
LOG.info(s"Listening API entries on $port")
ZIO.never
}.provideSome[DatabaseContext & Authentificator & DataSource](
}.provideSome[DatabaseContext & Authenticator & DataSource](
Scope.default,
serverConfigLayer,
ConnectionPool.fixed(4),

@ -5,7 +5,7 @@ import io.getquill.context.ZioJdbc.*
import io.getquill.context.qzio.{ZioContext, ZioJdbcContext}
import io.getquill.context.sql.idiom.SqlIdiom
import org.apache.logging.log4j.LogManager
import org.tbasket.auth.Authentificator
import org.tbasket.auth.Authenticator
import org.tbasket.data.{DatabaseContext, User}
import org.tbasket.error.AuthException.*
import org.tbasket.error.ExceptionEnum
@ -17,7 +17,7 @@ import zio.http.model.{Cookie, Header, Headers, Status}
import zio.json.*
import zio.json.ast.Json.Str
import zio.json.ast.{Json, JsonCursor}
import zio.{ZEnvironment, ZIO, *}
import zio.*
import java.sql.SQLException
import java.util.UUID
@ -28,7 +28,7 @@ object LoginPageHandler extends PageHandler:
private val LOG = LogManager.getLogger("Login")
private def getUser(json: Json) =
ZIO.serviceWithZIO[Authentificator] { auth =>
ZIO.serviceWithZIO[Authenticator] { auth =>
for
mail <- HandlerUtils.parseAttribute(json, "email", JsonCursor.field("email").isString)
password <- HandlerUtils.parseAttribute(json, "password", JsonCursor.field("password").isString)
@ -49,7 +49,7 @@ object LoginPageHandler extends PageHandler:
.mapError(InvalidRequest("Invalid JSON body", _))
user <- getUser(json)
jwt <- ZIO.serviceWithZIO[Authentificator](_.requestNewJwt(user))
jwt <- ZIO.serviceWithZIO[Authenticator](_.requestNewJwt(user))
yield Response(
status = Status.Found,
headers = Headers.location("/") ++ //login successful, go back to main page

@ -1,6 +1,6 @@
package org.tbasket.handler
import org.tbasket.auth.Authentificator
import org.tbasket.auth.Authenticator
import org.tbasket.data.User
import org.tbasket.error.RegularException.InvalidRequest
import org.tbasket.handler.HandlerUtils.parseAttribute
@ -25,8 +25,8 @@ object RegisterPageHandler extends PageHandler {
mail <- parseAttribute(json, "email", JsonCursor.field("email").isString)
password <- parseAttribute(json, "password", JsonCursor.field("password").isString)
user <- ZIO.serviceWithZIO[Authentificator](_.registerUser(name, forename, mail, password))
jwt <- ZIO.serviceWithZIO[Authentificator](_.requestNewJwt(user))
user <- ZIO.serviceWithZIO[Authenticator](_.registerUser(name, forename, mail, password))
jwt <- ZIO.serviceWithZIO[Authenticator](_.requestNewJwt(user))
yield Response(
status = Status.Found,
headers = Headers.location("/") ++ //register successful, go back to main page

@ -1,6 +1,6 @@
kind: pipeline
type: docker
name: Deployment
name: "Server CI"
steps:
@ -28,3 +28,4 @@ steps:
# - ./mill Core.compile
# - chmod 777 drone/deliver.sh
# - drone/deliver.sh

@ -0,0 +1,27 @@
FILES_COMMITTED=$(git diff --name-only HEAD^)
IMAGES_COMMITTED=$(echo "$FILES_COMMITTED" | grep -E "^.*\.dockerfile$")
REPOSITORY="hub.codefirst.iut.uca.fr/maxime.batista/codefirst-docdeployer"
dockerd
push_image() ({
local IMAGE_NAME=$(basename "$1" | rev | cut -d . -f2- | rev)
cd "$(dirname "$1")"
docker login -u "$DOCKER_USERNAME" -p "$DOCKER_PASSWORD" "$REPOSITORY"
echo "Building $IMAGE_NAME..."
docker build -f "$(basename "$1")" .
docker tag "$IMAGE_NAME" "$REPOSITORY/$IMAGE_NAME:latest"
echo "Pushing $IMAGE_NAME..."
docker push "$REPOSITORY/$IMAGE_NAME"
})
echo $IMAGES_COMMITTED
for IMAGE in $IMAGES_COMMITTED; do
push_image "$IMAGE"
done

@ -1,11 +0,0 @@
# syntax=override6/tbasket-end:latest
FROM ubuntu:latest
RUN apt update &&\
apt install openjdk-11-jdk openssh-client wget unzip curl -y &&\
wget https://services.gradle.org/distributions/gradle-7.5.1-bin.zip &&\
mkdir /opt/gradle &&\
unzip -d /opt/gradle gradle-7.5.1-bin.zip &&\
export GRADLE_HOME=/opt/gradle/gradle-7.5.1 && \

@ -0,0 +1,8 @@
# syntax=override6/tbasket-end:latest
FROM ubuntu:latest
RUN apt update
RUN apt install openjdk-19-jdk -y
RUN apt install openssh-client curl wget -y

@ -1,44 +1,52 @@
{
"results": [
{
"name" : "org.tbasket.test.pages.LoginPageHandlerTests/\/login page handler/login situation tests/login with unknown account",
"name" : "Test Task name not available here/\/login page handler/login situation tests/login with unknown account",
"status" : "Success",
"durationMillis" : "3408",
"durationMillis" : "4103",
"annotations" : "",
"fullyQualifiedClassName" : "org.tbasket.test.pages.LoginPageHandlerTests",
"fullyQualifiedClassName" : "Test Task name not available here",
"labels" : ["\/login page handler", "login situation tests", "login with unknown account"]
},
{
"name" : "org.tbasket.test.pages.LoginPageHandlerTests/\/login page handler/erroned request body tests/with invalid json",
"status" : "Success",
"durationMillis" : "2403",
"name" : "Test Task name not available here/\/login page handler/login situation tests/login with known account",
"status" : "Failure",
"durationMillis" : "1",
"annotations" : "",
"fullyQualifiedClassName" : "org.tbasket.test.pages.LoginPageHandlerTests",
"labels" : ["\/login page handler", "erroned request body tests", "with invalid json"]
"fullyQualifiedClassName" : "Test Task name not available here",
"labels" : ["\/login page handler", "login situation tests", "login with known account"]
},
{
"name" : "org.tbasket.test.pages.LoginPageHandlerTests/\/login page handler/erroned request body tests/with no password attribute",
"name" : "Test Task name not available here/\/login page handler/erroned request body tests/with no password attribute",
"status" : "Success",
"durationMillis" : "2406",
"durationMillis" : "2681",
"annotations" : "",
"fullyQualifiedClassName" : "org.tbasket.test.pages.LoginPageHandlerTests",
"fullyQualifiedClassName" : "Test Task name not available here",
"labels" : ["\/login page handler", "erroned request body tests", "with no password attribute"]
},
{
"name" : "org.tbasket.test.pages.LoginPageHandlerTests/\/login page handler/erroned request body tests/with no mail attribute",
"name" : "Test Task name not available here/\/login page handler/erroned request body tests/empty packet",
"status" : "Success",
"durationMillis" : "2412",
"durationMillis" : "2697",
"annotations" : "",
"fullyQualifiedClassName" : "org.tbasket.test.pages.LoginPageHandlerTests",
"fullyQualifiedClassName" : "Test Task name not available here",
"labels" : ["\/login page handler", "erroned request body tests", "empty packet"]
},
{
"name" : "Test Task name not available here/\/login page handler/erroned request body tests/with no mail attribute",
"status" : "Success",
"durationMillis" : "2702",
"annotations" : "",
"fullyQualifiedClassName" : "Test Task name not available here",
"labels" : ["\/login page handler", "erroned request body tests", "with no mail attribute"]
},
{
"name" : "org.tbasket.test.pages.LoginPageHandlerTests/\/login page handler/erroned request body tests/empty packet",
"name" : "Test Task name not available here/\/login page handler/erroned request body tests/with invalid json",
"status" : "Success",
"durationMillis" : "2436",
"durationMillis" : "2717",
"annotations" : "",
"fullyQualifiedClassName" : "org.tbasket.test.pages.LoginPageHandlerTests",
"labels" : ["\/login page handler", "erroned request body tests", "empty packet"]
"fullyQualifiedClassName" : "Test Task name not available here",
"labels" : ["\/login page handler", "erroned request body tests", "with invalid json"]
}
]

@ -0,0 +1,27 @@
#!/usr/bin/bash
echo GENERATING TEMPORARY KEY PAIRS FOR TESTS
rm -r /tmp/keys &> /dev/null
mkdir -p /tmp/keys
cd /tmp/keys
keytool -genkey -noprompt \
-alias key \
-keyalg RSA \
-validity 2 \
-keystore test.keystore \
-storetype PKCS12 \
-dname "CN=x.y.com, OU=TB, O=TBA, L=dzqdz, S=dqzdzq, C=GB" \
-storepass 123456789 \
-keypass 123456789
keytool -noprompt -export \
-alias key \
-keystore test.keystore \
-rfc \
-file public.cert \
-keypass 123456789 \
-storepass 123456789
openssl pkcs12 -in test.keystore -nodes -nocerts -out private.pcks -passin pass:123456789
openssl pkcs12 -in test.keystore -nokeys -out public.cert -passin pass:123456789

@ -0,0 +1,3 @@
INSERT INTO user
VALUES ('1daf7878-8ede-46ed-8b3e-120d37bf6819','maximebatista18@gmail.com', 'batista', 'maxime', 1450575459)

@ -1,10 +1,13 @@
package org.tbasket.test
import org.tbasket.auth.Authentificator
import org.tbasket.auth.Authenticator
import org.tbasket.config.ServerConfig
import org.tbasket.data.Database
import zio.{Task, ZLayer}
import java.nio.file.{Files, Path}
import java.sql.{DriverManager, Statement}
/*
* Defines required test service layers
* */
@ -13,13 +16,33 @@ object TestLayers {
val auth = {
val publicKey = TestServerConfig.emitterCertificate.getPublicKey
val auth = new Authentificator(TestServerConfig.emitterURL, publicKey, TestServerConfig.emitterKeyAlgorithm)
val auth = new Authenticator(TestServerConfig.emitterURL, publicKey, TestServerConfig.emitterKeyAlgorithm)
ZLayer.succeed(auth)
}
val db = {
new Database(TestServerConfig)
//ensure that the test table is always new in order to make tests on the same dataset all the time.
Files.deleteIfExists(Path.of("/tmp/test-database.sqlite"))
//open database
val db = new Database(TestServerConfig)
//fill the test database with a test dataset
val connection = DriverManager.getConnection("jdbc:sqlite:/tmp/test-database.sqlite")
val stmnt = connection.createStatement()
executeFile(stmnt, "table_init.sql")
executeFile(stmnt, "test_dataset.sql")
stmnt.close()
connection.close()
db
}
private def executeFile(statement: Statement, url: String) =
val in = getClass.getClassLoader.getResourceAsStream(url)
val bytes = in.readAllBytes()
in.close()
val requests = new String(bytes).split(';')
requests.foreach(statement.execute)
}

@ -10,13 +10,17 @@ import java.nio.file.{Files, Path}
import java.security.cert.{Certificate, CertificateFactory}
object TestServerConfig extends ServerConfig {
new ProcessBuilder("bash", "./tests/resources/generate_keys.sh")
.inheritIO()
.start()
.waitFor()
private final val CertFactory = CertificateFactory.getInstance("X509")
override def emitterURL: URL = URL.fromString(s"http://localhost/$PORT").getOrElse(null)
override def emitterCertificate: Certificate =
CertFactory.generateCertificate(Files.newInputStream(Path.of("keys/public.cert")))
CertFactory.generateCertificate(Files.newInputStream(Path.of("/tmp/keys/public.cert")))
override def emitterKeyAlgorithm: JwtAsymmetricAlgorithm = JwtAlgorithm.RS256

@ -2,13 +2,14 @@ package org.tbasket.test.pages
import io.getquill.jdbczio.Quill
import io.getquill.{SnakeCase, SqliteZioJdbcContext}
import org.tbasket.auth.Authentificator
import org.tbasket.auth.Authenticator
import org.tbasket.data.{Database, DatabaseContext}
import org.tbasket.error.RegularException.InvalidRequest
import org.tbasket.handler.HandlerUtils.parseAttribute
import org.tbasket.handler.LoginPageHandler
import org.tbasket.handler.LoginPageHandler.post
import org.tbasket.test.TestLayers
import org.tbasket.test.pages.LoginPageHandlerTests.test
import zio.*
import zio.http.netty.client.ConnectionPool
import zio.http.*
@ -16,10 +17,11 @@ import zio.http.model.{HeaderNames, Headers}
import zio.http.model.Headers.Header
import zio.json.*
import zio.json.ast.{Json, JsonCursor}
import zio.test.{TestAspect, *}
import zio.test.*
import zio.test.Assertion.*
object LoginPageHandlerTests extends ZIOSpecDefault {
import LoginPageHandler.post
import TestLayers.*
@ -48,29 +50,38 @@ object LoginPageHandlerTests extends ZIOSpecDefault {
)
private def loginSpec = {
suite("login situation tests") (
suite("login situation tests")(
test("login with unknown account") {
for
response <- post(Request.post(Body.fromString("""{"password":"123456","email":"maximebatista18@gmail.com"}"""), URL.empty))
response <- post(Request.post(Body.fromString("""{"password":"123456","email":"unknownaccount@gmail.com"}"""), URL.empty))
json <- getJsonBody(response)
errorType <- parseAttribute(json, "error", JsonCursor.field("error").isString)
yield
//assert that the response error is of type unauthorized and headers are Location: /register
assert(errorType)(equalTo("unauthorized"))
&& assert(response)(hasField("headers", _.headers, hasSameElements(Headers.location("/register"))))
},
test("login with known account") {
for
response <- post(Request.post(Body.fromString("""{"password":"123456","email":"maximebatista18@gmail.com"}"""), URL.empty))
json <- getJsonBody(response)
//errorType <- parseAttribute(json, "error", JsonCursor.field("error").isString)
yield
assert(response)(hasField("headers", _.headers, exists(hasField("key", _.key, equalTo(HeaderNames.setCookie)))))
}
)
}
override def spec = suite("/login page handler") (
override def spec = suite("/login page handler")(
requestsSpec,
loginSpec
).provide(
db.datasourceLayer,
db.contextLayer,
auth,
ConnectionPool.fixed(1),
Scope.default,
ClientConfig.default,
Client.live)
db.datasourceLayer,
db.contextLayer,
auth,
ConnectionPool.fixed(1),
Scope.default,
ClientConfig.default,
Client.live)
}