[
  {
    "path": ".github/workflows/maven.yml",
    "content": "name: Run tests\non:\n  pull_request:\n    branches:\n      - main\n  workflow_dispatch:\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    env:\n      RAILS_ENV: test\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v3\n\n      - uses: satackey/action-docker-layer-caching@v0.0.11\n        continue-on-error: true\n\n      - name: Start docker containers\n        run: |\n          docker-compose -f docker-compose-ci.yml up --build --detach\n          sleep 10  # wait for database to be ready          \n\n      - name: Run unit tests\n        run: docker-compose -f docker-compose-ci.yml run mc-authentication-service-test ./mvnw test -Punittest -Dspring.profiles.active=ci\n\n      - name: Run integration tests\n        run: docker-compose -f docker-compose-ci.yml run mc-authentication-service-test ./mvnw test -Pintegrationtest -Dspring.profiles.active=ci\n"
  },
  {
    "path": ".gitignore",
    "content": "HELP.md\ntarget/\n!.mvn/wrapper/maven-wrapper.jar\n!**/src/main/**/target/\n!**/src/test/**/target/\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n.sts4-cache\n\n### IntelliJ IDEA ###\n.idea\n*.iws\n*.iml\n*.ipr\n\n### NetBeans ###\n/nbproject/private/\n/nbbuild/\n/dist/\n/nbdist/\n/.nb-gradle/\nbuild/\n!**/src/main/**/build/\n!**/src/test/**/build/\n\n### VS Code ###\n.vscode/\n.DS_Store\n"
  },
  {
    "path": ".mvn/wrapper/MavenWrapperDownloader.java",
    "content": "/*\n * Copyright 2007-present the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *      https://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport java.net.*;\nimport java.io.*;\nimport java.nio.channels.*;\nimport java.util.Properties;\n\npublic class MavenWrapperDownloader {\n\n    private static final String WRAPPER_VERSION = \"0.5.6\";\n    /**\n     * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.\n     */\n    private static final String DEFAULT_DOWNLOAD_URL = \"https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/\"\n        + WRAPPER_VERSION + \"/maven-wrapper-\" + WRAPPER_VERSION + \".jar\";\n\n    /**\n     * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to\n     * use instead of the default one.\n     */\n    private static final String MAVEN_WRAPPER_PROPERTIES_PATH =\n            \".mvn/wrapper/maven-wrapper.properties\";\n\n    /**\n     * Path where the maven-wrapper.jar will be saved to.\n     */\n    private static final String MAVEN_WRAPPER_JAR_PATH =\n            \".mvn/wrapper/maven-wrapper.jar\";\n\n    /**\n     * Name of the property which should be used to override the default download url for the wrapper.\n     */\n    private static final String PROPERTY_NAME_WRAPPER_URL = \"wrapperUrl\";\n\n    public static void main(String args[]) {\n        System.out.println(\"- Downloader started\");\n        File baseDirectory = new File(args[0]);\n        System.out.println(\"- Using base directory: \" + baseDirectory.getAbsolutePath());\n\n        // If the maven-wrapper.properties exists, read it and check if it contains a custom\n        // wrapperUrl parameter.\n        File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);\n        String url = DEFAULT_DOWNLOAD_URL;\n        if(mavenWrapperPropertyFile.exists()) {\n            FileInputStream mavenWrapperPropertyFileInputStream = null;\n            try {\n                mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);\n                Properties mavenWrapperProperties = new Properties();\n                mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);\n                url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);\n            } catch (IOException e) {\n                System.out.println(\"- ERROR loading '\" + MAVEN_WRAPPER_PROPERTIES_PATH + \"'\");\n            } finally {\n                try {\n                    if(mavenWrapperPropertyFileInputStream != null) {\n                        mavenWrapperPropertyFileInputStream.close();\n                    }\n                } catch (IOException e) {\n                    // Ignore ...\n                }\n            }\n        }\n        System.out.println(\"- Downloading from: \" + url);\n\n        File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);\n        if(!outputFile.getParentFile().exists()) {\n            if(!outputFile.getParentFile().mkdirs()) {\n                System.out.println(\n                        \"- ERROR creating output directory '\" + outputFile.getParentFile().getAbsolutePath() + \"'\");\n            }\n        }\n        System.out.println(\"- Downloading to: \" + outputFile.getAbsolutePath());\n        try {\n            downloadFileFromURL(url, outputFile);\n            System.out.println(\"Done\");\n            System.exit(0);\n        } catch (Throwable e) {\n            System.out.println(\"- Error downloading\");\n            e.printStackTrace();\n            System.exit(1);\n        }\n    }\n\n    private static void downloadFileFromURL(String urlString, File destination) throws Exception {\n        if (System.getenv(\"MVNW_USERNAME\") != null && System.getenv(\"MVNW_PASSWORD\") != null) {\n            String username = System.getenv(\"MVNW_USERNAME\");\n            char[] password = System.getenv(\"MVNW_PASSWORD\").toCharArray();\n            Authenticator.setDefault(new Authenticator() {\n                @Override\n                protected PasswordAuthentication getPasswordAuthentication() {\n                    return new PasswordAuthentication(username, password);\n                }\n            });\n        }\n        URL website = new URL(urlString);\n        ReadableByteChannel rbc;\n        rbc = Channels.newChannel(website.openStream());\n        FileOutputStream fos = new FileOutputStream(destination);\n        fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);\n        fos.close();\n        rbc.close();\n    }\n\n}\n"
  },
  {
    "path": ".mvn/wrapper/maven-wrapper.properties",
    "content": "distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip\nwrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar\n"
  },
  {
    "path": "1-init.sql",
    "content": "create user mcuser with superuser;\nalter user mcuser with password 'mcuser';\ncreate database mc_authentication with owner mcuser;\ncreate extension \"uuid-ossp\";\n"
  },
  {
    "path": "Dockerfile",
    "content": "FROM amazoncorretto:11 as base\nWORKDIR /app\nCOPY .mvn/ .mvn\nCOPY mvnw pom.xml ddd_common-v1.0.0.jar ./\nRUN ./mvnw deploy:deploy-file -Durl=file:./src/main/resources/repo -Dfile=ddd_common-v1.0.0.jar -DgroupId=org.tomo -DartifactId=ddd_common -Dpackaging=jar -Dversion=1.0.0\nRUN ./mvnw dependency:resolve\n\n\nFROM base as test\nRUN ./mvnw dependency:resolve-plugins -Punittest,integrationtest\nCOPY src ./src\nADD \"https://www.random.org/cgi-bin/randbyte?nbytes=10&format=h\" skipcache\nCMD tail -f /dev/null\n\nFROM base as build\nCOPY src ./src\nRUN ./mvnw package\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 Tomislav Landeka\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Microservice for authentication with Domain-Driven Design\nFull Spring Boot authentication microservice with Domain-Driven Design approach.\n\n### 1. Introduction\n\n#### 1.1. Purpose of this Repository\n\nThis is a list of the main goals of this repository:\n\n* Showing how you can implement a Domain-Drive design\n* Showing how you can implement a CQRS\n* Presentation of the full implementation of an application\n  * This is not another proof of concept (PoC)\n  * The goal is to present the implementation of an application that would be ready to run in production\n* Showing the application of best practices and object-oriented programming principles\n* Presentation of the use of design patterns. When, how and why they can be used\n* Presentation of the implementation using Domain-Driven Design approach (tactical patterns)\n* Presentation of the implementation of Unit Tests for Domain Model (Testable Design in mind)\n* Presentation of the implementation of Integration Tests\n* Presentation of the implementation of testing Web-Layer only\n\n#### 1.2 Your contribution\n* Give it a star\n* Share it\n* Become a contributor\n\n### 2. Domain\n#### 2.1. Business logic of the repository\nThe main idea of this repository is to create small microservice for authentication that provides next functionalities:\n* Form Registration\n* Form Login, Google Login, Facebook Login\n* Password recovery\n* Email notifications\n* Session identification and authentication\n#### 2.2. How to run\n* Run database docker container first: `docker-compose up -d`\n* Run application locally with `local` profile\n* Plan is to dockerize the application in order to run it easy \n#### 2.3. How to run tests\n* Run database docker container first: `docker-compose up -d`. Plan is to add testdb for testing purposes.\n* Run Integration test separately\n* Run Unit test separately\n* Run Web-Layer (tests that are testing Spring Boot implementation and Rest Controller) tests separately\n\n\n### 3. Desired TODO List to complete the application:\n* Clean the code from inconsistencies\n* Add more session details\n* Implement a tool like ELK\n* Caching if/when needed\n* More tests\n* CI\n* Pull out 'ddd' folder and create a library\n* Pull out 'CQRS' folders (contracts and configuration) and create a library\n* Finish SpringBoot security and CSFR token\n* Dockerize\n\n### 4. The main idea is to create a reusable microservice network that consists of the next microservices:\n* Service discovery (probably with K8s).\n* Create a microservice for authentication (current repository).\n* Create a microservice for authorization - simple implementation of RBAC.\n* Create a microservice for sending emails.\n* Create a microservice for localization - the idea is to provide UI for translating the application to various languages as a common part of most applications.\n* Create a microservice for asynchronous communication (AC) - the idea is to create a microservice that distributes the messages between microservices. The microservice should work over DB (e.g. Redis) and RMQ to provide asynchrony. The microservice should provide the REST API for accessing it. In this way, we should have RMQ in only one place and communication with this microservice should go over REST API.\n  The microservice should provide these routes:\n  * route for registering messages by other microservices. E.g. Email-Microservice could register message **send-email** with _required properties_, _endpoint_, and _version_. That configuration should be saved into a DB.\n  * sending messages - E.g. Authentication microservice should send a message after registering a user with the name **send-email** and _required properties_. The AC microservice will receive that message, validate the required properties, enrich the message body with an endpoint (which is saved in DB) and publish a message to RMQ. The RMQ consumer will consume the message and distribute it to the endpoint.\n\n### 5. License\nThe project is under [MIT license](https://opensource.org/licenses/MIT).\n\n### 6. Inspiration\n#### 6.1. Domain-Driven Design\n- [\"Domain-Driven Design: Tackling Complexity in the Heart of Software\"](https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215) book, Eric Evans\n- [\"Implementing Domain-Driven Design\"](https://www.amazon.com/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/0321834577) book, Vaughn Vernon\n- [\"Domain-Driven Design in PHP\"](https://www.amazon.com/dp/1787284948) book, by Carlos Buenosvinos, Christian Soronellas, Keyvan Akbary\n- [\"IDDD_Samples\"](https://github.com/VaughnVernon/IDDD_Samples) GH repository, Vaughn Vernon\n- [\"Blog CQRS\"](https://github.com/dddshelf/blog-cqrs) GH repository, by Carlos Buenosvinos, Christian Soronellas, Keyvan Akbary\n- [\"DDD example - Last Wishes\"](https://github.com/dddshelf/last-wishes) GH repository, by Carlos Buenosvinos, Christian Soronellas, Keyvan Akbary\n- [\"Modular Monolith with DDD\"](https://github.com/kgrzybek/modular-monolith-with-ddd) GH repository, by Kamil Grzybek\n- [\"Mediator implementation\"](https://github.com/jbogard/MediatR) GH repository, by Jimmy Bogard\n\n#### 6.2 Application Architecture\n- [\"Patterns of Enterprise Application Architecture\"](https://martinfowler.com/books/eaa.html) book, Martin Fowler\n- [\"Clean Architecture: A Craftsman's Guide to Software Structure and Design (Robert C. Martin Series\"](https://www.amazon.com/Clean-Architecture-Craftsmans-Software-Structure/dp/0134494164) book, Robert C. Martin\n- [\"The Clean Architecture\"](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) article, Robert C. Martin\n- [\"DDD, Hexagonal, Onion, Clean, CQRS, … How I put it all together\"](https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-clean-cqrs-how-i-put-it-all-together/) article, Herberto Graca\n\n#### 6.2. System Architecture\n- [\"Building Microservices: Designing Fine-Grained Systems\"](https://www.amazon.com/Building-Microservices-Designing-Fine-Grained-Systems/dp/1491950358) book, Sam Newman\n\n#### 6.3. Design\n- [\"Clean Code: A Handbook of Agile Software Craftsmanship\"](https://www.amazon.com/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882) book, Robert C. Martin\n- [\"Design Patterns: Elements of Reusable Object-Oriented Software\"](https://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612) book, Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides\n\n"
  },
  {
    "path": "docker-compose-ci.yml",
    "content": "version: '3.7'\n\nservices:\n\n  mc-authentication-db-test:\n    container_name: mc-authentication-db-test\n    image: postgres:12\n    restart: always\n    ports:\n      - 127.0.0.1:5432:5432\n    networks:\n      - mc-network-test\n    environment:\n      POSTGRES_PASSWORD: postgres\n      POSTGRES_USER: postgres\n    volumes:\n      - mc-authentication-db-test:/var/lib/postgresql\n      - ./1-init.sql:/docker-entrypoint-initdb.d/1-init.sql\n\n  mc-authentication-service-test:\n    container_name: mc-authentication-service-test\n    depends_on:\n      - mc-authentication-db-test\n    build:\n      context: ./\n      dockerfile: Dockerfile\n      target: test\n    ports:\n      - 127.0.0.1:8080:8080\n    networks:\n      - mc-network-test\n\nvolumes:\n  mc-authentication-db-test:\n\nnetworks:\n  mc-network-test:\n    driver: bridge\n"
  },
  {
    "path": "docker-compose.yml",
    "content": "version: '3.7'\n\nservices:\n\n  mc-authentication_db:\n    container_name: mc-authentication_db\n    image: postgres:12\n    restart: always\n    ports:\n      - 127.0.0.1:5432:5432\n    environment:\n      POSTGRES_PASSWORD: postgres\n      POSTGRES_USER: postgres\n    volumes:\n      - mc-authentication-db:/var/lib/postgresql\n      - ./1-init.sql:/docker-entrypoint-initdb.d/1-init.sql\n\nvolumes:\n  mc-authentication-db:\n\nnetworks:\n  mc-network:\n    driver: bridge\n"
  },
  {
    "path": "mvnw",
    "content": "#!/bin/sh\n# ----------------------------------------------------------------------------\n# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the NOTICE file\n# distributed with this work for additional information\n# regarding copyright ownership.  The ASF licenses this file\n# to you under the Apache License, Version 2.0 (the\n# \"License\"); you may not use this file except in compliance\n# with the License.  You may obtain a copy of the License at\n#\n#    https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing,\n# software distributed under the License is distributed on an\n# \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n# KIND, either express or implied.  See the License for the\n# specific language governing permissions and limitations\n# under the License.\n# ----------------------------------------------------------------------------\n\n# ----------------------------------------------------------------------------\n# Maven Start Up Batch script\n#\n# Required ENV vars:\n# ------------------\n#   JAVA_HOME - location of a JDK home dir\n#\n# Optional ENV vars\n# -----------------\n#   M2_HOME - location of maven2's installed home dir\n#   MAVEN_OPTS - parameters passed to the Java VM when running Maven\n#     e.g. to debug Maven itself, use\n#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000\n#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files\n# ----------------------------------------------------------------------------\n\nif [ -z \"$MAVEN_SKIP_RC\" ] ; then\n\n  if [ -f /etc/mavenrc ] ; then\n    . /etc/mavenrc\n  fi\n\n  if [ -f \"$HOME/.mavenrc\" ] ; then\n    . \"$HOME/.mavenrc\"\n  fi\n\nfi\n\n# OS specific support.  $var _must_ be set to either true or false.\ncygwin=false;\ndarwin=false;\nmingw=false\ncase \"`uname`\" in\n  CYGWIN*) cygwin=true ;;\n  MINGW*) mingw=true;;\n  Darwin*) darwin=true\n    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home\n    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html\n    if [ -z \"$JAVA_HOME\" ]; then\n      if [ -x \"/usr/libexec/java_home\" ]; then\n        export JAVA_HOME=\"`/usr/libexec/java_home`\"\n      else\n        export JAVA_HOME=\"/Library/Java/Home\"\n      fi\n    fi\n    ;;\nesac\n\nif [ -z \"$JAVA_HOME\" ] ; then\n  if [ -r /etc/gentoo-release ] ; then\n    JAVA_HOME=`java-config --jre-home`\n  fi\nfi\n\nif [ -z \"$M2_HOME\" ] ; then\n  ## resolve links - $0 may be a link to maven's home\n  PRG=\"$0\"\n\n  # need this for relative symlinks\n  while [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n      PRG=\"$link\"\n    else\n      PRG=\"`dirname \"$PRG\"`/$link\"\n    fi\n  done\n\n  saveddir=`pwd`\n\n  M2_HOME=`dirname \"$PRG\"`/..\n\n  # make it fully qualified\n  M2_HOME=`cd \"$M2_HOME\" && pwd`\n\n  cd \"$saveddir\"\n  # echo Using m2 at $M2_HOME\nfi\n\n# For Cygwin, ensure paths are in UNIX format before anything is touched\nif $cygwin ; then\n  [ -n \"$M2_HOME\" ] &&\n    M2_HOME=`cygpath --unix \"$M2_HOME\"`\n  [ -n \"$JAVA_HOME\" ] &&\n    JAVA_HOME=`cygpath --unix \"$JAVA_HOME\"`\n  [ -n \"$CLASSPATH\" ] &&\n    CLASSPATH=`cygpath --path --unix \"$CLASSPATH\"`\nfi\n\n# For Mingw, ensure paths are in UNIX format before anything is touched\nif $mingw ; then\n  [ -n \"$M2_HOME\" ] &&\n    M2_HOME=\"`(cd \"$M2_HOME\"; pwd)`\"\n  [ -n \"$JAVA_HOME\" ] &&\n    JAVA_HOME=\"`(cd \"$JAVA_HOME\"; pwd)`\"\nfi\n\nif [ -z \"$JAVA_HOME\" ]; then\n  javaExecutable=\"`which javac`\"\n  if [ -n \"$javaExecutable\" ] && ! [ \"`expr \\\"$javaExecutable\\\" : '\\([^ ]*\\)'`\" = \"no\" ]; then\n    # readlink(1) is not available as standard on Solaris 10.\n    readLink=`which readlink`\n    if [ ! `expr \"$readLink\" : '\\([^ ]*\\)'` = \"no\" ]; then\n      if $darwin ; then\n        javaHome=\"`dirname \\\"$javaExecutable\\\"`\"\n        javaExecutable=\"`cd \\\"$javaHome\\\" && pwd -P`/javac\"\n      else\n        javaExecutable=\"`readlink -f \\\"$javaExecutable\\\"`\"\n      fi\n      javaHome=\"`dirname \\\"$javaExecutable\\\"`\"\n      javaHome=`expr \"$javaHome\" : '\\(.*\\)/bin'`\n      JAVA_HOME=\"$javaHome\"\n      export JAVA_HOME\n    fi\n  fi\nfi\n\nif [ -z \"$JAVACMD\" ] ; then\n  if [ -n \"$JAVA_HOME\"  ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n      # IBM's JDK on AIX uses strange locations for the executables\n      JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n      JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n  else\n    JAVACMD=\"`which java`\"\n  fi\nfi\n\nif [ ! -x \"$JAVACMD\" ] ; then\n  echo \"Error: JAVA_HOME is not defined correctly.\" >&2\n  echo \"  We cannot execute $JAVACMD\" >&2\n  exit 1\nfi\n\nif [ -z \"$JAVA_HOME\" ] ; then\n  echo \"Warning: JAVA_HOME environment variable is not set.\"\nfi\n\nCLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher\n\n# traverses directory structure from process work directory to filesystem root\n# first directory with .mvn subdirectory is considered project base directory\nfind_maven_basedir() {\n\n  if [ -z \"$1\" ]\n  then\n    echo \"Path not specified to find_maven_basedir\"\n    return 1\n  fi\n\n  basedir=\"$1\"\n  wdir=\"$1\"\n  while [ \"$wdir\" != '/' ] ; do\n    if [ -d \"$wdir\"/.mvn ] ; then\n      basedir=$wdir\n      break\n    fi\n    # workaround for JBEAP-8937 (on Solaris 10/Sparc)\n    if [ -d \"${wdir}\" ]; then\n      wdir=`cd \"$wdir/..\"; pwd`\n    fi\n    # end of workaround\n  done\n  echo \"${basedir}\"\n}\n\n# concatenates all lines of a file\nconcat_lines() {\n  if [ -f \"$1\" ]; then\n    echo \"$(tr -s '\\n' ' ' < \"$1\")\"\n  fi\n}\n\nBASE_DIR=`find_maven_basedir \"$(pwd)\"`\nif [ -z \"$BASE_DIR\" ]; then\n  exit 1;\nfi\n\n##########################################################################################\n# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central\n# This allows using the maven wrapper in projects that prohibit checking in binary data.\n##########################################################################################\nif [ -r \"$BASE_DIR/.mvn/wrapper/maven-wrapper.jar\" ]; then\n    if [ \"$MVNW_VERBOSE\" = true ]; then\n      echo \"Found .mvn/wrapper/maven-wrapper.jar\"\n    fi\nelse\n    if [ \"$MVNW_VERBOSE\" = true ]; then\n      echo \"Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ...\"\n    fi\n    if [ -n \"$MVNW_REPOURL\" ]; then\n      jarUrl=\"$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar\"\n    else\n      jarUrl=\"https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar\"\n    fi\n    while IFS=\"=\" read key value; do\n      case \"$key\" in (wrapperUrl) jarUrl=\"$value\"; break ;;\n      esac\n    done < \"$BASE_DIR/.mvn/wrapper/maven-wrapper.properties\"\n    if [ \"$MVNW_VERBOSE\" = true ]; then\n      echo \"Downloading from: $jarUrl\"\n    fi\n    wrapperJarPath=\"$BASE_DIR/.mvn/wrapper/maven-wrapper.jar\"\n    if $cygwin; then\n      wrapperJarPath=`cygpath --path --windows \"$wrapperJarPath\"`\n    fi\n\n    if command -v wget > /dev/null; then\n        if [ \"$MVNW_VERBOSE\" = true ]; then\n          echo \"Found wget ... using wget\"\n        fi\n        if [ -z \"$MVNW_USERNAME\" ] || [ -z \"$MVNW_PASSWORD\" ]; then\n            wget \"$jarUrl\" -O \"$wrapperJarPath\"\n        else\n            wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD \"$jarUrl\" -O \"$wrapperJarPath\"\n        fi\n    elif command -v curl > /dev/null; then\n        if [ \"$MVNW_VERBOSE\" = true ]; then\n          echo \"Found curl ... using curl\"\n        fi\n        if [ -z \"$MVNW_USERNAME\" ] || [ -z \"$MVNW_PASSWORD\" ]; then\n            curl -o \"$wrapperJarPath\" \"$jarUrl\" -f\n        else\n            curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o \"$wrapperJarPath\" \"$jarUrl\" -f\n        fi\n\n    else\n        if [ \"$MVNW_VERBOSE\" = true ]; then\n          echo \"Falling back to using Java to download\"\n        fi\n        javaClass=\"$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java\"\n        # For Cygwin, switch paths to Windows format before running javac\n        if $cygwin; then\n          javaClass=`cygpath --path --windows \"$javaClass\"`\n        fi\n        if [ -e \"$javaClass\" ]; then\n            if [ ! -e \"$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class\" ]; then\n                if [ \"$MVNW_VERBOSE\" = true ]; then\n                  echo \" - Compiling MavenWrapperDownloader.java ...\"\n                fi\n                # Compiling the Java class\n                (\"$JAVA_HOME/bin/javac\" \"$javaClass\")\n            fi\n            if [ -e \"$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class\" ]; then\n                # Running the downloader\n                if [ \"$MVNW_VERBOSE\" = true ]; then\n                  echo \" - Running MavenWrapperDownloader.java ...\"\n                fi\n                (\"$JAVA_HOME/bin/java\" -cp .mvn/wrapper MavenWrapperDownloader \"$MAVEN_PROJECTBASEDIR\")\n            fi\n        fi\n    fi\nfi\n##########################################################################################\n# End of extension\n##########################################################################################\n\nexport MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-\"$BASE_DIR\"}\nif [ \"$MVNW_VERBOSE\" = true ]; then\n  echo $MAVEN_PROJECTBASEDIR\nfi\nMAVEN_OPTS=\"$(concat_lines \"$MAVEN_PROJECTBASEDIR/.mvn/jvm.config\") $MAVEN_OPTS\"\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin; then\n  [ -n \"$M2_HOME\" ] &&\n    M2_HOME=`cygpath --path --windows \"$M2_HOME\"`\n  [ -n \"$JAVA_HOME\" ] &&\n    JAVA_HOME=`cygpath --path --windows \"$JAVA_HOME\"`\n  [ -n \"$CLASSPATH\" ] &&\n    CLASSPATH=`cygpath --path --windows \"$CLASSPATH\"`\n  [ -n \"$MAVEN_PROJECTBASEDIR\" ] &&\n    MAVEN_PROJECTBASEDIR=`cygpath --path --windows \"$MAVEN_PROJECTBASEDIR\"`\nfi\n\n# Provide a \"standardized\" way to retrieve the CLI args that will\n# work with both Windows and non-Windows executions.\nMAVEN_CMD_LINE_ARGS=\"$MAVEN_CONFIG $@\"\nexport MAVEN_CMD_LINE_ARGS\n\nWRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain\n\nexec \"$JAVACMD\" \\\n  $MAVEN_OPTS \\\n  -classpath \"$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar\" \\\n  \"-Dmaven.home=${M2_HOME}\" \"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}\" \\\n  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG \"$@\"\n"
  },
  {
    "path": "mvnw.cmd",
    "content": "@REM ----------------------------------------------------------------------------\n@REM Licensed to the Apache Software Foundation (ASF) under one\n@REM or more contributor license agreements.  See the NOTICE file\n@REM distributed with this work for additional information\n@REM regarding copyright ownership.  The ASF licenses this file\n@REM to you under the Apache License, Version 2.0 (the\n@REM \"License\"); you may not use this file except in compliance\n@REM with the License.  You may obtain a copy of the License at\n@REM\n@REM    https://www.apache.org/licenses/LICENSE-2.0\n@REM\n@REM Unless required by applicable law or agreed to in writing,\n@REM software distributed under the License is distributed on an\n@REM \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n@REM KIND, either express or implied.  See the License for the\n@REM specific language governing permissions and limitations\n@REM under the License.\n@REM ----------------------------------------------------------------------------\n\n@REM ----------------------------------------------------------------------------\n@REM Maven Start Up Batch script\n@REM\n@REM Required ENV vars:\n@REM JAVA_HOME - location of a JDK home dir\n@REM\n@REM Optional ENV vars\n@REM M2_HOME - location of maven2's installed home dir\n@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands\n@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending\n@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven\n@REM     e.g. to debug Maven itself, use\n@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000\n@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files\n@REM ----------------------------------------------------------------------------\n\n@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'\n@echo off\n@REM set title of command window\ntitle %0\n@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'\n@if \"%MAVEN_BATCH_ECHO%\" == \"on\"  echo %MAVEN_BATCH_ECHO%\n\n@REM set %HOME% to equivalent of $HOME\nif \"%HOME%\" == \"\" (set \"HOME=%HOMEDRIVE%%HOMEPATH%\")\n\n@REM Execute a user defined script before this one\nif not \"%MAVEN_SKIP_RC%\" == \"\" goto skipRcPre\n@REM check for pre script, once with legacy .bat ending and once with .cmd ending\nif exist \"%HOME%\\mavenrc_pre.bat\" call \"%HOME%\\mavenrc_pre.bat\"\nif exist \"%HOME%\\mavenrc_pre.cmd\" call \"%HOME%\\mavenrc_pre.cmd\"\n:skipRcPre\n\n@setlocal\n\nset ERROR_CODE=0\n\n@REM To isolate internal variables from possible post scripts, we use another setlocal\n@setlocal\n\n@REM ==== START VALIDATION ====\nif not \"%JAVA_HOME%\" == \"\" goto OkJHome\n\necho.\necho Error: JAVA_HOME not found in your environment. >&2\necho Please set the JAVA_HOME variable in your environment to match the >&2\necho location of your Java installation. >&2\necho.\ngoto error\n\n:OkJHome\nif exist \"%JAVA_HOME%\\bin\\java.exe\" goto init\n\necho.\necho Error: JAVA_HOME is set to an invalid directory. >&2\necho JAVA_HOME = \"%JAVA_HOME%\" >&2\necho Please set the JAVA_HOME variable in your environment to match the >&2\necho location of your Java installation. >&2\necho.\ngoto error\n\n@REM ==== END VALIDATION ====\n\n:init\n\n@REM Find the project base dir, i.e. the directory that contains the folder \".mvn\".\n@REM Fallback to current working directory if not found.\n\nset MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%\nIF NOT \"%MAVEN_PROJECTBASEDIR%\"==\"\" goto endDetectBaseDir\n\nset EXEC_DIR=%CD%\nset WDIR=%EXEC_DIR%\n:findBaseDir\nIF EXIST \"%WDIR%\"\\.mvn goto baseDirFound\ncd ..\nIF \"%WDIR%\"==\"%CD%\" goto baseDirNotFound\nset WDIR=%CD%\ngoto findBaseDir\n\n:baseDirFound\nset MAVEN_PROJECTBASEDIR=%WDIR%\ncd \"%EXEC_DIR%\"\ngoto endDetectBaseDir\n\n:baseDirNotFound\nset MAVEN_PROJECTBASEDIR=%EXEC_DIR%\ncd \"%EXEC_DIR%\"\n\n:endDetectBaseDir\n\nIF NOT EXIST \"%MAVEN_PROJECTBASEDIR%\\.mvn\\jvm.config\" goto endReadAdditionalConfig\n\n@setlocal EnableExtensions EnableDelayedExpansion\nfor /F \"usebackq delims=\" %%a in (\"%MAVEN_PROJECTBASEDIR%\\.mvn\\jvm.config\") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a\n@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%\n\n:endReadAdditionalConfig\n\nSET MAVEN_JAVA_EXE=\"%JAVA_HOME%\\bin\\java.exe\"\nset WRAPPER_JAR=\"%MAVEN_PROJECTBASEDIR%\\.mvn\\wrapper\\maven-wrapper.jar\"\nset WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain\n\nset DOWNLOAD_URL=\"https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar\"\n\nFOR /F \"tokens=1,2 delims==\" %%A IN (\"%MAVEN_PROJECTBASEDIR%\\.mvn\\wrapper\\maven-wrapper.properties\") DO (\n    IF \"%%A\"==\"wrapperUrl\" SET DOWNLOAD_URL=%%B\n)\n\n@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central\n@REM This allows using the maven wrapper in projects that prohibit checking in binary data.\nif exist %WRAPPER_JAR% (\n    if \"%MVNW_VERBOSE%\" == \"true\" (\n        echo Found %WRAPPER_JAR%\n    )\n) else (\n    if not \"%MVNW_REPOURL%\" == \"\" (\n        SET DOWNLOAD_URL=\"%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar\"\n    )\n    if \"%MVNW_VERBOSE%\" == \"true\" (\n        echo Couldn't find %WRAPPER_JAR%, downloading it ...\n        echo Downloading from: %DOWNLOAD_URL%\n    )\n\n    powershell -Command \"&{\"^\n\t\t\"$webclient = new-object System.Net.WebClient;\"^\n\t\t\"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {\"^\n\t\t\"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');\"^\n\t\t\"}\"^\n\t\t\"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')\"^\n\t\t\"}\"\n    if \"%MVNW_VERBOSE%\" == \"true\" (\n        echo Finished downloading %WRAPPER_JAR%\n    )\n)\n@REM End of extension\n\n@REM Provide a \"standardized\" way to retrieve the CLI args that will\n@REM work with both Windows and non-Windows executions.\nset MAVEN_CMD_LINE_ARGS=%*\n\n%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% \"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%\" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*\nif ERRORLEVEL 1 goto error\ngoto end\n\n:error\nset ERROR_CODE=1\n\n:end\n@endlocal & set ERROR_CODE=%ERROR_CODE%\n\nif not \"%MAVEN_SKIP_RC%\" == \"\" goto skipRcPost\n@REM check for post script, once with legacy .bat ending and once with .cmd ending\nif exist \"%HOME%\\mavenrc_post.bat\" call \"%HOME%\\mavenrc_post.bat\"\nif exist \"%HOME%\\mavenrc_post.cmd\" call \"%HOME%\\mavenrc_post.cmd\"\n:skipRcPost\n\n@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'\nif \"%MAVEN_BATCH_PAUSE%\" == \"on\" pause\n\nif \"%MAVEN_TERMINATE_CMD%\" == \"on\" exit %ERROR_CODE%\n\nexit /B %ERROR_CODE%\n"
  },
  {
    "path": "pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n    <groupId>com.tomo</groupId>\n    <artifactId>mc-authentication</artifactId>\n    <version>0.0.1-SNAPSHOT</version>\n    <name>mc-authentication</name>\n    <description>API for Authentication</description>\n\n    <parent>\n        <groupId>org.springframework.boot</groupId>\n        <artifactId>spring-boot-starter-parent</artifactId>\n        <version>2.6.2</version>\n        <relativePath/> <!-- lookup parent from repository -->\n    </parent>\n\n    <!--https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-apache-maven-registry#authenticating-to-github-packages&ndash;&gt;-->\n\n    <properties>\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>\n        <java.version>11</java.version>\n        <junit.version>4.13.2</junit.version>\n        <junit-vintage-engine>4.12.1</junit-vintage-engine>\n        <junit-jupiter.version>5.8.2</junit-jupiter.version>\n        <junit-platform.version>1.0.1</junit-platform.version>\n    </properties>\n\n    <repositories>\n        <repository>\n            <id>project.local</id>\n            <name>project</name>\n            <url>file:${project.basedir}/src/main/resources/repo</url>\n        </repository>\n    </repositories>\n\n    <dependencies>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-data-jpa</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-web</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.security</groupId>\n            <artifactId>spring-security-test</artifactId>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.boot</groupId>\n            <artifactId>spring-boot-starter-security</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.security</groupId>\n            <artifactId>spring-security-oauth2-client</artifactId>\n        </dependency>\n\n        <!-- JWT library -->\n        <dependency>\n            <groupId>io.jsonwebtoken</groupId>\n            <artifactId>jjwt-api</artifactId>\n            <version>0.11.2</version>\n        </dependency>\n        <dependency>\n            <groupId>io.jsonwebtoken</groupId>\n            <artifactId>jjwt-impl</artifactId>\n            <version>0.11.2</version>\n            <scope>runtime</scope>\n        </dependency>\n        <dependency>\n            <groupId>io.jsonwebtoken</groupId>\n            <artifactId>jjwt-jackson</artifactId>\n            <version>0.11.2</version>\n            <scope>runtime</scope>\n        </dependency>\n\n        <!-- Lombok -->\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n            <version>1.18.22</version>\n            <scope>provided</scope>\n        </dependency>\n\n        <!-- PipelineR -->\n        <dependency>\n            <groupId>net.sizovs</groupId>\n            <artifactId>pipelinr</artifactId>\n            <version>0.7</version>\n        </dependency>\n\n        <!-- Postgres -->\n        <dependency>\n            <groupId>org.postgresql</groupId>\n            <artifactId>postgresql</artifactId>\n            <scope>runtime</scope>\n        </dependency>\n\n        <dependency>\n            <groupId>org.flywaydb</groupId>\n            <artifactId>flyway-core</artifactId>\n            <version>8.4.3</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.codehaus.mojo</groupId>\n            <artifactId>exec-maven-plugin</artifactId>\n            <version>1.2.1</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-lang3</artifactId>\n            <version>3.12.0</version>\n        </dependency>\n\n        <!--\t\tValidation annotation-->\n        <dependency>\n            <groupId>javax.validation</groupId>\n            <artifactId>validation-api</artifactId>\n            <version>2.0.1.Final</version>\n        </dependency>\n\n        <!--\t\tEntity to DTO-->\n        <dependency>\n            <groupId>org.modelmapper</groupId>\n            <artifactId>modelmapper</artifactId>\n            <version>2.4.5</version>\n        </dependency>\n\n        <!--\t\tJava Faker-->\n        <dependency>\n            <groupId>com.github.javafaker</groupId>\n            <artifactId>javafaker</artifactId>\n            <version>1.0.2</version>\n        </dependency>\n\n        <!--\t\tmailgun lib for ddd folder-->\n        <dependency>\n            <groupId>net.sargue</groupId>\n            <artifactId>mailgun</artifactId>\n            <version>1.10.0</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.glassfish.jersey.inject</groupId>\n            <artifactId>jersey-hk2</artifactId>\n            <version>2.28</version>\n        </dependency>\n\n        <dependency>\n            <groupId>com.google.code.gson</groupId>\n            <artifactId>gson</artifactId>\n            <version>2.8.5</version>\n        </dependency>\n\n        <!--\t\tswagger 2.0 with spring boot-->\n        <dependency>\n            <groupId>io.springfox</groupId>\n            <artifactId>springfox-boot-starter</artifactId>\n            <version>3.0.0</version>\n        </dependency>\n\n        <dependency>\n            <groupId>org.mockito</groupId>\n            <artifactId>mockito-inline</artifactId>\n            <version>3.8.0</version>\n            <scope>test</scope>\n        </dependency>\n        <dependency>\n            <groupId>org.tomo</groupId>\n            <artifactId>ddd_common</artifactId>\n            <version>v1.0.0</version>\n        </dependency>\n        <dependency>\n            <groupId>org.tomo</groupId>\n            <artifactId>ddd_common</artifactId>\n            <version>1.0.0</version>\n        </dependency>\n    </dependencies>\n    <!--\t<build>-->\n    <!--\t\t<plugins>-->\n    <!--\t\t\t<plugin>-->\n    <!--\t\t\t\t<groupId>org.codehaus.mojo</groupId>-->\n    <!--\t\t\t\t<artifactId>exec-maven-plugin</artifactId>-->\n    <!--\t\t\t\t<version>1.2.1</version>-->\n    <!--\t\t\t\t<configuration>-->\n    <!--\t\t\t\t\t<mainClass>com.tomo.mcauthentication.McAuthenticationApplication</mainClass>-->\n    <!--\t\t\t\t</configuration>-->\n    <!--\t\t\t</plugin>-->\n    <!--\t\t</plugins>-->\n    <!--\t</build>-->\n    <profiles>\n        <profile>\n            <id>flyway</id>\n            <build>\n                <plugins>\n                    <plugin>\n                        <groupId>org.flywaydb</groupId>\n                        <artifactId>flyway-maven-plugin</artifactId>\n                        <version>8.4.3</version>\n                        <executions>\n                            <execution>\n                                <phase>generate-sources</phase>\n                                <goals>\n                                    <goal>migrate</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                        <configuration>\n                            <driver>org.postgresql.Driver</driver>\n                            <user>mcuser</user>\n                            <password>mcuser</password>\n                            <url>jdbc:postgresql://localhost:5432/mc_authentication</url>\n                            <placeholderReplacement>false</placeholderReplacement>\n                            <baselineOnMigrate>true</baselineOnMigrate>\n                            <schemas>\n                                <schema>public</schema>\n                            </schemas>\n                        </configuration>\n                    </plugin>\n                </plugins>\n            </build>\n        </profile>\n        <profile>\n            <id>unittest</id>\n            <build>\n                <plugins>\n                    <plugin>\n                        <artifactId>maven-surefire-plugin</artifactId>\n                        <version>2.19.1</version> <!-- matters until now-->\n                        <configuration>\n                            <includes>\n                                <include>com.tomo.mcauthentication.unit.**</include>\n                            </includes>\n                        </configuration>\n                        <dependencies>\n                            <!-- to let surefire to run JUnit 4 but also JUnit 5 tests -->\n                            <dependency>\n                                <groupId>org.junit.platform</groupId>\n                                <artifactId>junit-platform-surefire-provider</artifactId>\n                                <version>${junit-platform.version}</version>\n                            </dependency>\n                            <!-- JUnit vintage engine to run JUnit 3 or JUnit 4 tests -->\n                            <dependency>\n                                <groupId>org.junit.vintage</groupId>\n                                <artifactId>junit-vintage-engine</artifactId>\n                                <version>${junit-vintage-engine}</version>\n                            </dependency>\n                            <!-- JUnit 5 engine to run JUnit 5 tests -->\n                            <dependency>\n                                <groupId>org.junit.jupiter</groupId>\n                                <artifactId>junit-jupiter-engine</artifactId>\n                                <version>${junit-jupiter.version}</version>\n                            </dependency>\n                        </dependencies>\n                    </plugin>\n                </plugins>\n            </build>\n        </profile>\n        <profile>\n            <id>integrationtest</id>\n            <build>\n                <plugins>\n                    <plugin>\n                        <groupId>org.springframework.boot</groupId>\n                        <artifactId>spring-boot-maven-plugin</artifactId>\n                    </plugin>\n                    <plugin>\n                        <groupId>org.flywaydb</groupId>\n                        <artifactId>flyway-maven-plugin</artifactId>\n                        <version>8.4.3</version>\n                        <executions>\n                            <execution>\n                                <phase>generate-sources</phase>\n                                <goals>\n                                    <goal>migrate</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                        <configuration>\n                            <driver>org.postgresql.Driver</driver>\n                            <user>mcuser</user>\n                            <password>mcuser</password>\n                            <url>jdbc:postgresql://mc-authentication-db-test:5432/mc_authentication</url>\n                            <placeholderReplacement>false</placeholderReplacement>\n                            <baselineOnMigrate>true</baselineOnMigrate>\n                            <schemas>\n                                <schema>public</schema>\n                            </schemas>\n                        </configuration>\n                    </plugin>\n                    <plugin>\n                        <groupId>org.apache.maven.plugins</groupId>\n                        <artifactId>maven-failsafe-plugin</artifactId>\n                        <configuration>\n                            <includes>\n                                <include>com.tomo.mcauthentication.integration.*</include>\n                            </includes>\n                        </configuration>\n                        <executions>\n                            <execution>\n                                <phase>integration-test</phase>\n                                <goals>\n                                    <goal>integration-test</goal>\n                                    <goal>verify</goal>\n                                </goals>\n                            </execution>\n                        </executions>\n                    </plugin>\n                    <plugin>\n                        <artifactId>maven-surefire-plugin</artifactId>\n                        <version>2.19.1</version> <!-- matters until now-->\n                        <configuration>\n                            <excludes>\n                                <exclude>com.tomo.mcauthentication.unit.**</exclude>\n                            </excludes>\n                        </configuration>\n                        <dependencies>\n                            <!-- to let surefire to run JUnit 4 but also JUnit 5 tests -->\n                            <dependency>\n                                <groupId>org.junit.platform</groupId>\n                                <artifactId>junit-platform-surefire-provider</artifactId>\n                                <version>${junit-platform.version}</version>\n                            </dependency>\n                            <!-- JUnit vintage engine to run JUnit 3 or JUnit 4 tests -->\n                            <dependency>\n                                <groupId>org.junit.vintage</groupId>\n                                <artifactId>junit-vintage-engine</artifactId>\n                                <version>${junit-vintage-engine}</version>\n                            </dependency>\n                            <!-- JUnit 5 engine to run JUnit 5 tests -->\n                            <dependency>\n                                <groupId>org.junit.jupiter</groupId>\n                                <artifactId>junit-jupiter-engine</artifactId>\n                                <version>${junit-jupiter.version}</version>\n                            </dependency>\n                        </dependencies>\n                    </plugin>\n                </plugins>\n            </build>\n        </profile>\n    </profiles>\n</project>\n\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/McAuthenticationApplication.java",
    "content": "package com.tomo.mcauthentication;\n\nimport com.tomo.mcauthentication.infrastructure.springboot.configuration.AppProperties;\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.autoconfigure.domain.EntityScan;\nimport org.springframework.boot.context.properties.EnableConfigurationProperties;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.EnableAspectJAutoProxy;\nimport org.springframework.data.jpa.repository.config.EnableJpaRepositories;\nimport org.springframework.web.servlet.config.annotation.EnableWebMvc;\n\nimport springfox.documentation.swagger2.annotations.EnableSwagger2;\n\n@EnableWebMvc\n@EnableSwagger2\n@SpringBootApplication\n@EnableConfigurationProperties(AppProperties.class)\n@EnableAspectJAutoProxy(proxyTargetClass=true)\n@ComponentScan(basePackages = { \"com.tomo.*\" })\n@EntityScan(\"com.tomo.*\")\npublic class McAuthenticationApplication {\n\n\tpublic static void main(String[] args) {\n\t\tSpringApplication.run(McAuthenticationApplication.class, args);\n\t}\n\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/BaseMapper.java",
    "content": "package com.tomo.mcauthentication.application;\n\nimport org.modelmapper.ModelMapper;\n\npublic class BaseMapper {\n    protected ModelMapper modelMapper;\n\n    public BaseMapper() {}\n\n    public BaseMapper(ModelMapper modelMapper) {\n        this.modelMapper = modelMapper;\n    }\n\n    protected <T, E> T toDto(E source, Class<T> destinationType) {\n        return modelMapper.map(source, destinationType);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/McAuthenticationEventHandler.java",
    "content": "package com.tomo.mcauthentication.application;\n\nimport com.tomo.ddd.domain.DomainEvent;\nimport com.tomo.ddd.domain.DomainEventPublisher;\nimport com.tomo.ddd.domain.DomainEventSubscriber;\nimport com.tomo.ddd.event.EventStore;\n\nimport org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.annotation.Before;\nimport org.springframework.stereotype.Component;\n\n@Aspect\n@Component\npublic class McAuthenticationEventHandler {\n\n    private EventStore eventStore;\n\n    public McAuthenticationEventHandler(EventStore eventStore) {\n        this.eventStore = eventStore;\n    }\n\n    @Before(value = \"execution(* *(..)) && within(com.tomo.mcauthentication.application..*)\")\n    public void listen() {\n        DomainEventPublisher\n            .instance()\n            .subscribe(new DomainEventSubscriber<DomainEvent>() {\n\n                public void handleEvent(DomainEvent aDomainEvent) {\n                    store(aDomainEvent);\n                }\n\n                public Class<DomainEvent> subscribedToEventType() {\n                    return DomainEvent.class; // all domain events\n                }\n            });\n    }\n\n    /**\n     * Stores aDomainEvent to the event store.\n     * @param aDomainEvent the DomainEvent to store\n     */\n    private void store(DomainEvent aDomainEvent) {\n        this.eventStore().append(aDomainEvent);\n    }\n\n    /**\n     * Answers my EventStore.\n     * @return EventStore\n     */\n    private EventStore eventStore() {\n        return this.eventStore;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/authentication/BaseLoginCommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.authentication;\n\nimport com.tomo.mcauthentication.application.BaseMapper;\nimport com.tomo.mcauthentication.application.authentication.dto.SessionDto;\nimport com.tomo.mcauthentication.domain.session.Session;\nimport com.tomo.mcauthentication.domain.session.SessionRepository;\nimport com.tomo.mcauthentication.domain.session.TokenProvider;\n\nimport org.modelmapper.ModelMapper;\n\npublic class BaseLoginCommandHandler extends BaseMapper {\n    protected SessionRepository sessionRepository;\n    protected TokenProvider tokenProvider;\n\n    public BaseLoginCommandHandler() {\n    }\n\n    public BaseLoginCommandHandler(ModelMapper modelMapper, TokenProvider tokenProvider) {\n        super(modelMapper);\n        this.tokenProvider = tokenProvider;\n    }\n\n    public BaseLoginCommandHandler(\n            ModelMapper modelMapper,\n            SessionRepository sessionRepository,\n            TokenProvider tokenProvider) {\n        super(modelMapper);\n        this.sessionRepository = sessionRepository;\n        this.tokenProvider = tokenProvider;\n    }\n\n    protected SessionDto toDto(Session session) {\n        return SessionDto.create(session, this.modelMapper);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/authentication/EmailLoginCommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.authentication;\n\nimport com.tomo.mcauthentication.application.authentication.command.EmailLoginCommand;\nimport com.tomo.mcauthentication.application.authentication.dto.SessionDto;\nimport com.tomo.mcauthentication.application.configuration.CommandHandler;\nimport com.tomo.mcauthentication.domain.session.Session;\nimport com.tomo.mcauthentication.domain.session.SessionRepository;\nimport com.tomo.mcauthentication.domain.session.TokenProvider;\nimport com.tomo.mcauthentication.domain.registration.EmailAuthenticationService;\nimport com.tomo.mcauthentication.domain.users.User;\n\nimport org.modelmapper.ModelMapper;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class EmailLoginCommandHandler extends BaseLoginCommandHandler implements CommandHandler<EmailLoginCommand, SessionDto> {\n\n    EmailAuthenticationService authenticationService;\n\n    public EmailLoginCommandHandler(\n            EmailAuthenticationService emailAuthenticationService,\n            @Qualifier(\"sessionRepositoryJpaAdapter\") SessionRepository sessionRepository,\n            @Qualifier(\"jwtTokenProvider\") TokenProvider tokenProvider,\n            ModelMapper modelMapper) {\n        super(modelMapper, sessionRepository, tokenProvider);\n        this.authenticationService = emailAuthenticationService;\n        this.tokenProvider = tokenProvider;\n    }\n\n    @Override\n    public SessionDto handle(EmailLoginCommand command) {\n        User user = authenticationService.authenticate(command.getEmail(), command.getPassword());\n        Session session = new Session(\n                sessionRepository.nextIdentity(),\n                user,tokenProvider,\n                command.getRememberMe(),\n                command.getUserAgent(), command.getIpAddress());\n\n        sessionRepository.save(session);\n        return toDto(session);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/authentication/FacebookLoginCommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.authentication;\n\nimport com.tomo.mcauthentication.application.authentication.command.FacebookLoginCommand;\nimport com.tomo.mcauthentication.application.configuration.CommandHandler;\nimport com.tomo.mcauthentication.application.users.dto.BaseUserDto;\nimport com.tomo.mcauthentication.domain.oauth2.OAuth2Service;\nimport com.tomo.mcauthentication.domain.session.Session;\nimport com.tomo.mcauthentication.domain.session.SessionRepository;\nimport com.tomo.mcauthentication.domain.session.TokenProvider;\nimport com.tomo.mcauthentication.domain.users.User;\n\nimport org.modelmapper.ModelMapper;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class FacebookLoginCommandHandler extends BaseLoginCommandHandler implements CommandHandler<FacebookLoginCommand, BaseUserDto> {\n\n    OAuth2Service oAuth2Service;\n\n    public FacebookLoginCommandHandler(\n            @Qualifier(\"facebookOAuth2Service\") OAuth2Service oAuth2Service,\n            @Qualifier(\"jwtTokenProvider\") TokenProvider tokenProvider,\n            @Qualifier(\"sessionRepositoryJpaAdapter\") SessionRepository sessionRepository,\n            ModelMapper modelMapper) {\n        super(modelMapper, sessionRepository, tokenProvider);\n        this.oAuth2Service = oAuth2Service;\n        this.tokenProvider = tokenProvider;\n    }\n\n    @Override\n    public BaseUserDto handle(FacebookLoginCommand command) {\n        User user = oAuth2Service.registerAuthenticate(command.getAccessCode());\n\n        Session session = new Session(\n                sessionRepository.nextIdentity(),\n                user,tokenProvider,\n                command.getRememberMe(),\n                command.getUserAgent(), command.getIpAddress());\n        sessionRepository.save(session);\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/authentication/GoogleLoginCommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.authentication;\n\nimport com.tomo.mcauthentication.application.authentication.command.GoogleLoginCommand;\nimport com.tomo.mcauthentication.application.configuration.CommandHandler;\nimport com.tomo.mcauthentication.application.users.dto.BaseUserDto;\nimport com.tomo.mcauthentication.domain.oauth2.OAuth2Service;\nimport com.tomo.mcauthentication.domain.session.Session;\nimport com.tomo.mcauthentication.domain.session.SessionRepository;\nimport com.tomo.mcauthentication.domain.session.TokenProvider;\nimport com.tomo.mcauthentication.domain.users.User;\n\nimport org.modelmapper.ModelMapper;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class GoogleLoginCommandHandler extends BaseLoginCommandHandler implements CommandHandler<GoogleLoginCommand, BaseUserDto> {\n\n    OAuth2Service oAuth2Service;\n\n    public GoogleLoginCommandHandler(\n            @Qualifier(\"googleOAuth2Service\") OAuth2Service oAuth2Service,\n            @Qualifier(\"jwtTokenProvider\") TokenProvider tokenProvider,\n            @Qualifier(\"sessionRepositoryJpaAdapter\") SessionRepository sessionRepository,\n            ModelMapper modelMapper) {\n        super(modelMapper, sessionRepository, tokenProvider);\n        this.oAuth2Service = oAuth2Service;\n        this.tokenProvider = tokenProvider;\n    }\n\n    @Override\n    public BaseUserDto handle(GoogleLoginCommand command) {\n        User user = oAuth2Service.registerAuthenticate(command.getAccessCode());\n        Session session = new Session(\n                sessionRepository.nextIdentity(),\n                user,tokenProvider,\n                command.getRememberMe(),\n                command.getUserAgent(), command.getIpAddress());\n        sessionRepository.save(session);\n        return null;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/authentication/LogoutCommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.authentication;\n\nimport com.tomo.mcauthentication.application.authentication.command.LogoutCommand;\nimport com.tomo.mcauthentication.application.configuration.AbstractVoidyCommandHandler;\nimport com.tomo.mcauthentication.domain.session.SessionAuthenticationService;\n\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class LogoutCommandHandler extends AbstractVoidyCommandHandler<LogoutCommand> {\n\n    SessionAuthenticationService sessionAuthenticationService;\n\n    public LogoutCommandHandler(SessionAuthenticationService sessionAuthenticationService) {\n        this.sessionAuthenticationService = sessionAuthenticationService;\n    }\n\n    @Override\n    protected void abstractHandle(LogoutCommand aCommand) {\n        sessionAuthenticationService.logout(aCommand.getAuthToken());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/authentication/SessionAuthenticationCommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.authentication;\n\nimport com.tomo.mcauthentication.application.BaseMapper;\nimport com.tomo.mcauthentication.application.authentication.command.SessionAuthenticationCommand;\nimport com.tomo.mcauthentication.application.authentication.dto.SessionDto;\nimport com.tomo.mcauthentication.application.configuration.CommandHandler;\nimport com.tomo.mcauthentication.domain.session.Session;\nimport com.tomo.mcauthentication.domain.session.SessionAuthenticationService;\n\nimport org.modelmapper.ModelMapper;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class SessionAuthenticationCommandHandler extends BaseMapper implements CommandHandler<SessionAuthenticationCommand, SessionDto> {\n\n    SessionAuthenticationService sessionAuthenticationService;\n\n    public SessionAuthenticationCommandHandler(\n            SessionAuthenticationService sessionAuthenticationService,\n            ModelMapper modelMapper) {\n        super(modelMapper);\n        this.sessionAuthenticationService = sessionAuthenticationService;\n    }\n\n    @Override\n    public SessionDto handle(SessionAuthenticationCommand command) {\n        Session session = sessionAuthenticationService.authenticate(command.getAuthToken());\n        return SessionDto.create(session, this.modelMapper);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/authentication/command/BaseLoginCommand.java",
    "content": "package com.tomo.mcauthentication.application.authentication.command;\n\nimport com.tomo.mcauthentication.application.contracts.BaseCommand;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n@Getter\n@Setter\npublic class BaseLoginCommand extends BaseCommand {\n    private Boolean rememberMe;\n    private String userAgent;\n    private String ipAddress;\n\n    public BaseLoginCommand() {\n        super();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/authentication/command/EmailLoginCommand.java",
    "content": "package com.tomo.mcauthentication.application.authentication.command;\n\nimport javax.validation.constraints.Email;\nimport javax.validation.constraints.NotBlank;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n@Setter\n@Getter\npublic class EmailLoginCommand extends BaseLoginCommand {\n\n    @NotBlank\n    @Email\n    private String email;\n    @NotBlank\n    private String password;\n    private Boolean rememberMe;\n    private String userAgent;\n    private String ipAddress;\n\n    public EmailLoginCommand() {\n        super();\n    }\n\n    public EmailLoginCommand(String email, String password) {\n        super();\n        this.email = email;\n        this.password = password;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/authentication/command/FacebookLoginCommand.java",
    "content": "package com.tomo.mcauthentication.application.authentication.command;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Setter\n@Getter\n@NoArgsConstructor\npublic class FacebookLoginCommand extends BaseLoginCommand {\n    private String accessCode;\n\n    public FacebookLoginCommand(String accessCode) {\n        this.accessCode = accessCode;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/authentication/command/GoogleLoginCommand.java",
    "content": "package com.tomo.mcauthentication.application.authentication.command;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Setter\n@Getter\n@NoArgsConstructor\npublic class GoogleLoginCommand extends BaseLoginCommand {\n    private String accessCode;\n\n    public GoogleLoginCommand(String accessCode) {\n        this.accessCode = accessCode;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/authentication/command/LogoutCommand.java",
    "content": "package com.tomo.mcauthentication.application.authentication.command;\n\nimport com.tomo.mcauthentication.application.contracts.security.AbstractAuthenticateCommand;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Setter\n@Getter\n@NoArgsConstructor\npublic class LogoutCommand extends AbstractAuthenticateCommand {\n\n    public LogoutCommand(String authToken) {\n        super(authToken);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/authentication/command/SessionAuthenticationCommand.java",
    "content": "package com.tomo.mcauthentication.application.authentication.command;\n\nimport com.tomo.mcauthentication.application.contracts.security.AbstractAuthenticateCommand;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class SessionAuthenticationCommand extends AbstractAuthenticateCommand {\n\n    public SessionAuthenticationCommand(String authToken) {\n        super(authToken);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/authentication/dto/RecoveryPasswordDto.java",
    "content": "package com.tomo.mcauthentication.application.authentication.dto;\n\nimport com.tomo.mcauthentication.application.contracts.Response;\n\nimport lombok.Getter;\n\n@Getter\npublic class RecoveryPasswordDto implements Response {\n\n    String recoveryCode;\n\n    public RecoveryPasswordDto(String recoveryCode) {\n        this.recoveryCode = recoveryCode;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/authentication/dto/SessionDto.java",
    "content": "package com.tomo.mcauthentication.application.authentication.dto;\n\nimport com.tomo.mcauthentication.application.users.dto.BaseUserDto;\nimport com.tomo.mcauthentication.domain.session.Session;\nimport com.tomo.mcauthentication.domain.session.SessionId;\nimport com.tomo.mcauthentication.domain.users.UserId;\n\nimport org.modelmapper.ModelMapper;\n\nimport java.time.LocalDateTime;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class SessionDto extends BaseUserDto {\n    private String sessionId;\n    private String accessToken;\n    private LocalDateTime expirationDate;\n    int expirationDateMilis;\n    private String tokenType;\n    private String refreshToken;\n    private String userAgent;\n    private String ipAddress;\n    private LocalDateTime lastActivity;\n    private String userId;\n\n    public static SessionDto create(Session session, ModelMapper mapper) {\n        SessionDto dto = mapper.map(session, SessionDto.class);\n        dto.setTokenType(session.getTokenType());\n        dto.setUserId(session.getUserId());\n        return dto;\n    }\n\n    public void setSessionId(SessionId sessionId) {\n        this.sessionId = sessionId.toString();\n    }\n\n    public void setTokenType(Session.TokenType tokenType) {\n        this.tokenType = tokenType.toString();\n    }\n\n    public void setUserId(UserId userId) {\n        this.userId = userId.id().toString();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/configuration/AbstractVoidyCommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.configuration;\n\nimport com.tomo.mcauthentication.application.contracts.Command;\nimport com.tomo.mcauthentication.application.contracts.Voidy;\n\nimport javax.transaction.Transactional;\n\npublic abstract class AbstractVoidyCommandHandler<T extends Command> implements CommandHandler<T, Voidy> {\n\n    @Override\n    @Transactional\n    public Voidy handle(T aCommand) {\n        abstractHandle(aCommand);\n        return new Voidy();\n    }\n\n    abstract protected void abstractHandle(T aCommand);\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/configuration/CommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.configuration;\n\nimport com.tomo.mcauthentication.application.contracts.Command;\nimport com.tomo.mcauthentication.application.contracts.Response;\n\npublic interface CommandHandler<T extends Command, R extends Response> extends RequestHandler {\n    R handle(T aCommand);\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/configuration/QueryHandler.java",
    "content": "package com.tomo.mcauthentication.application.configuration;\n\nimport com.tomo.mcauthentication.application.contracts.Query;\nimport com.tomo.mcauthentication.application.contracts.Response;\n\npublic interface QueryHandler<T extends Query, R extends Response> extends RequestHandler {\n    R handle(T query);\n}\n\n\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/configuration/RequestHandler.java",
    "content": "package com.tomo.mcauthentication.application.configuration;\n\nimport com.tomo.mcauthentication.application.contracts.Request;\nimport com.tomo.mcauthentication.application.contracts.Response;\n\npublic interface RequestHandler<T extends Request, R extends Response> {\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/BaseCommand.java",
    "content": "package com.tomo.mcauthentication.application.contracts;\n\npublic class BaseCommand extends BaseRequest implements Command {\n\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/BaseQuery.java",
    "content": "package com.tomo.mcauthentication.application.contracts;\n\npublic class BaseQuery extends BaseRequest implements Query {}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/BaseRequest.java",
    "content": "package com.tomo.mcauthentication.application.contracts;\n\nimport java.util.UUID;\n\npublic class BaseRequest implements Request {\n\n    private UUID id;\n\n    public BaseRequest() {\n        setId(UUID.randomUUID());\n    }\n\n    public BaseRequest(UUID anId) {\n        this.id = anId;\n    }\n\n    @Override\n    public UUID id() {\n        return this.id;\n    }\n\n    protected void setId(UUID anId) {\n        this.id = anId;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/Command.java",
    "content": "package com.tomo.mcauthentication.application.contracts;\n\npublic interface Command extends Request {\n}\n\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/Identifiable.java",
    "content": "package com.tomo.mcauthentication.application.contracts;\n\nimport java.util.UUID;\n\npublic interface Identifiable {\n\n    UUID id();\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/McAuthenticationModule.java",
    "content": "package com.tomo.mcauthentication.application.contracts;\n\nimport org.springframework.stereotype.Component;\n\n@Component\npublic interface McAuthenticationModule {\n        Response executeCommand(Command command);\n\n        Response executeQuery(Query query);\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/Query.java",
    "content": "package com.tomo.mcauthentication.application.contracts;\n\npublic interface Query extends Request {\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/Request.java",
    "content": "package com.tomo.mcauthentication.application.contracts;\n\npublic interface Request extends Identifiable {\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/Response.java",
    "content": "package com.tomo.mcauthentication.application.contracts;\n\npublic interface Response {\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/Voidy.java",
    "content": "package com.tomo.mcauthentication.application.contracts;\n\npublic class Voidy implements Response {\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/security/AbstractAuthenticateCommand.java",
    "content": "package com.tomo.mcauthentication.application.contracts.security;\n\nimport com.tomo.mcauthentication.application.contracts.Command;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic abstract class AbstractAuthenticateCommand extends AbstractAuthenticateRequest implements Command {\n\n    public AbstractAuthenticateCommand(String authToken) {\n        super(authToken);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/security/AbstractAuthenticateQuery.java",
    "content": "package com.tomo.mcauthentication.application.contracts.security;\n\nimport com.tomo.mcauthentication.application.contracts.BaseRequest;\nimport com.tomo.mcauthentication.application.contracts.Command;\nimport com.tomo.mcauthentication.application.contracts.Query;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic abstract class AbstractAuthenticateQuery extends AbstractAuthenticateRequest implements Query {\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/security/AbstractAuthenticateRequest.java",
    "content": "package com.tomo.mcauthentication.application.contracts.security;\n\nimport com.tomo.mcauthentication.application.contracts.BaseRequest;\nimport com.tomo.mcauthentication.application.contracts.Command;\nimport com.tomo.mcauthentication.application.contracts.Request;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic abstract class AbstractAuthenticateRequest extends BaseRequest implements Authenticate, Request {\n\n    String authToken;\n\n    public AbstractAuthenticateRequest(String authToken) {\n        this.authToken = authToken;\n    }\n\n    @Override\n    public String authToken() {\n        return this.authToken;\n    }\n\n    @Override\n    public void setAuthToken(String authToken) {\n        this.authToken = authToken;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/security/AbstractAuthorizeCommand.java",
    "content": "package com.tomo.mcauthentication.application.contracts.security;\n\nimport com.tomo.mcauthentication.application.contracts.Command;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic abstract class AbstractAuthorizeCommand extends AbstractAuthorizeRequest implements Command {\n\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/security/AbstractAuthorizeQuery.java",
    "content": "package com.tomo.mcauthentication.application.contracts.security;\n\nimport com.tomo.mcauthentication.application.contracts.Command;\nimport com.tomo.mcauthentication.application.contracts.Query;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic abstract class AbstractAuthorizeQuery extends AbstractAuthorizeRequest implements Query {\n\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/security/AbstractAuthorizeRequest.java",
    "content": "package com.tomo.mcauthentication.application.contracts.security;\n\nimport com.tomo.mcauthentication.application.contracts.Command;\nimport com.tomo.mcauthentication.application.contracts.Request;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic abstract class AbstractAuthorizeRequest extends AbstractAuthenticateRequest implements Request, Authorize {\n\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/security/Authenticate.java",
    "content": "package com.tomo.mcauthentication.application.contracts.security;\n\npublic interface Authenticate {\n\n    String authToken();\n\n    void setAuthToken(String authToken);\n\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/contracts/security/Authorize.java",
    "content": "package com.tomo.mcauthentication.application.contracts.security;\n\nimport java.util.List;\n\npublic interface Authorize extends Authenticate {\n\n    default List<String> getAuthorities() {\n        return List.of(\"USER\");\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/recovery/CreatePasswordRecoveryCodeCommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.recovery;\n\nimport com.tomo.mcauthentication.application.recovery.command.CreatePasswordRecoveryCodeCommand;\nimport com.tomo.mcauthentication.application.authentication.dto.RecoveryPasswordDto;\nimport com.tomo.mcauthentication.application.configuration.CommandHandler;\nimport com.tomo.mcauthentication.domain.registration.EmailAuthenticationService;\n\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class CreatePasswordRecoveryCodeCommandHandler implements CommandHandler<CreatePasswordRecoveryCodeCommand, RecoveryPasswordDto> {\n\n    EmailAuthenticationService emailAuthenticationService;\n\n    public CreatePasswordRecoveryCodeCommandHandler(EmailAuthenticationService emailAuthenticationService) {\n        this.emailAuthenticationService = emailAuthenticationService;\n    }\n\n    @Override\n    public RecoveryPasswordDto handle(CreatePasswordRecoveryCodeCommand aCommand) {\n        return new RecoveryPasswordDto(\n                emailAuthenticationService\n                        .createPasswordRecoveryCode(aCommand.getEmail())\n        );\n\n        //todo send recovery code\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/recovery/GetUserRegistrationWithRecoveryCodeQueryHandler.java",
    "content": "package com.tomo.mcauthentication.application.recovery;\n\nimport com.tomo.mcauthentication.application.BaseMapper;\nimport com.tomo.mcauthentication.application.configuration.QueryHandler;\nimport com.tomo.mcauthentication.application.registration.dto.UserRegistrationDto;\nimport com.tomo.mcauthentication.application.recovery.dto.GetUserRegistrationWithRecoveryCodeQuery;\nimport com.tomo.mcauthentication.domain.EncryptionService;\nimport com.tomo.mcauthentication.domain.registration.UserRegistration;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationRepository;\n\nimport org.modelmapper.ModelMapper;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class GetUserRegistrationWithRecoveryCodeQueryHandler extends BaseMapper implements QueryHandler<GetUserRegistrationWithRecoveryCodeQuery, UserRegistrationDto> {\n\n    private UserRegistrationRepository userRegistrationRepository;\n    private EncryptionService encryptionService;\n\n    public GetUserRegistrationWithRecoveryCodeQueryHandler(\n            UserRegistrationRepository aUserRegistrationRepository,\n            EncryptionService anEncryptionService,\n            ModelMapper modelMapper) {\n        super(modelMapper);\n        this.userRegistrationRepository = aUserRegistrationRepository;\n        this.encryptionService = anEncryptionService;\n    }\n\n    @Override\n    public UserRegistrationDto handle(GetUserRegistrationWithRecoveryCodeQuery query) {\n        UserRegistration userRegistration = userRegistrationRepository\n                .findByRecoveryCode(encryptionService.encryptedValue(query.getRecoveryCode()));\n\n        if (userRegistration == null) {\n            throw new IllegalStateException(String.format(\"User with recovery code %s doesn't exists.\", query.getRecoveryCode()));\n        }\n\n        UserRegistrationDto dto = toDto(\n                userRegistration,\n                UserRegistrationDto.class\n        );\n        return dto;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/recovery/PasswordRecoveryCodeCreatedEventHandler.java",
    "content": "package com.tomo.mcauthentication.application.recovery;\n\nimport com.tomo.mcauthentication.application.contracts.McAuthenticationModule;\nimport com.tomo.mcauthentication.application.recovery.command.SendPasswordRecoveryEmailCommand;\nimport com.tomo.ddd.domain.DomainEventPublisher;\nimport com.tomo.ddd.domain.DomainEventSubscriber;\nimport com.tomo.mcauthentication.domain.registration.events.PasswordRecoveryCodeCreated;\n\nimport org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.annotation.Before;\nimport org.springframework.stereotype.Component;\n\n@Aspect\n@Component\npublic class PasswordRecoveryCodeCreatedEventHandler {\n\n    private McAuthenticationModule module;\n\n    /**\n     * In order to not mix business logic with plugins like a GUI..\n     * baseUrl + URI + queryString eg. localhost/reset-passwrod/?recoveryCode=\n     */\n    private String recoveryLink;\n\n    public PasswordRecoveryCodeCreatedEventHandler(McAuthenticationModule authenticationModule, String recoveryLink) {\n        this.module = authenticationModule;\n        this.recoveryLink = recoveryLink;\n    }\n\n    @Before(\"execution(\" +\n                    \"public * com.tomo.mcauthentication.application.configuration.CommandHandler.*(..)) && \" +\n                    \"target(com.tomo.mcauthentication.application.recovery.CreatePasswordRecoveryCodeCommandHandler))\")\n    public void listen() {\n        DomainEventPublisher\n            .instance()\n            .subscribe(new DomainEventSubscriber<PasswordRecoveryCodeCreated>() {\n\n                public void handleEvent(PasswordRecoveryCodeCreated aDomainEvent) {\n                    module.executeCommand(new SendPasswordRecoveryEmailCommand(\n                            aDomainEvent.getEmail(),\n                            aDomainEvent.getRecoveryCode(),\n                            recoveryLink,\n                            aDomainEvent.getRecoveryCodeExpirationDate()));\n                }\n\n                public Class<PasswordRecoveryCodeCreated> subscribedToEventType() {\n                    return PasswordRecoveryCodeCreated.class;\n                }\n            });\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/recovery/SendPasswordRecoveryEmailCommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.recovery;\n\nimport com.tomo.mcauthentication.application.configuration.AbstractVoidyCommandHandler;\nimport com.tomo.mcauthentication.application.recovery.command.SendPasswordRecoveryEmailCommand;\nimport com.tomo.ddd.email.EmailSender;\nimport com.tomo.ddd.port.adapter.message.email.EmailMessage;\n\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class SendPasswordRecoveryEmailCommandHandler extends AbstractVoidyCommandHandler<SendPasswordRecoveryEmailCommand> {\n\n    EmailSender emailMessageSender;\n\n    public SendPasswordRecoveryEmailCommandHandler(EmailSender emailMessageSender) {\n        this.emailMessageSender = emailMessageSender;\n    }\n\n    @Override\n    protected void abstractHandle(SendPasswordRecoveryEmailCommand aCommand) {\n        //todo maybe validate if exist\n        this.emailMessageSender.send(new EmailMessage(\n                aCommand.getEmail(), \"\"\n                , \" Recovery code\",\n                \"To reset your password, visit the following link: \" + aCommand.getRecoveryLink() + aCommand.getRecoveryCode()));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/recovery/UpdatePasswordWithRecoveryCodeCommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.recovery;\n\nimport com.tomo.mcauthentication.application.recovery.command.UpdatePasswordWithRecoveryCodeCommand;\nimport com.tomo.mcauthentication.application.configuration.AbstractVoidyCommandHandler;\nimport com.tomo.mcauthentication.domain.registration.EmailAuthenticationService;\n\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class UpdatePasswordWithRecoveryCodeCommandHandler extends AbstractVoidyCommandHandler<UpdatePasswordWithRecoveryCodeCommand> {\n\n    EmailAuthenticationService emailAuthenticationService;\n\n    public UpdatePasswordWithRecoveryCodeCommandHandler(EmailAuthenticationService emailAuthenticationService) {\n        this.emailAuthenticationService = emailAuthenticationService;\n    }\n\n    @Override\n    protected void abstractHandle(UpdatePasswordWithRecoveryCodeCommand aCommand) {\n        emailAuthenticationService.recoverPasswordWithRecoveryCode(\n                aCommand.getRecoveryCode(),\n                aCommand.getNewPassword(),\n                aCommand.getNewPasswordRepeated());\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/recovery/command/CreatePasswordRecoveryCodeCommand.java",
    "content": "package com.tomo.mcauthentication.application.recovery.command;\n\nimport com.tomo.mcauthentication.application.contracts.BaseCommand;\n\nimport javax.validation.constraints.NotNull;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class CreatePasswordRecoveryCodeCommand extends BaseCommand {\n\n    @NotNull\n    private String email;\n\n    public CreatePasswordRecoveryCodeCommand(String email) {\n        this.email = email;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/recovery/command/SendPasswordRecoveryEmailCommand.java",
    "content": "package com.tomo.mcauthentication.application.recovery.command;\n\nimport com.tomo.mcauthentication.application.contracts.BaseCommand;\n\nimport java.time.LocalDateTime;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class SendPasswordRecoveryEmailCommand extends BaseCommand {\n\n    String email;\n    String recoveryCode;\n    String recoveryLink;\n    LocalDateTime recoveryCodeExpirationDate;\n\n    public SendPasswordRecoveryEmailCommand(String email, String recoveryCode, String recoveryLink, LocalDateTime recoveryCodeExpirationDate) {\n        this.email = email;\n        this.recoveryCode = recoveryCode;\n        this.recoveryLink = recoveryLink;\n        this.recoveryCodeExpirationDate = recoveryCodeExpirationDate;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/recovery/command/UpdatePasswordWithRecoveryCodeCommand.java",
    "content": "package com.tomo.mcauthentication.application.recovery.command;\n\nimport com.tomo.mcauthentication.application.contracts.BaseCommand;\n\nimport javax.validation.constraints.NotNull;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class UpdatePasswordWithRecoveryCodeCommand extends BaseCommand {\n\n    @NotNull\n    private String newPassword;\n\n    @NotNull\n    private String newPasswordRepeated;\n\n    @NotNull\n    private String recoveryCode;\n\n    public UpdatePasswordWithRecoveryCodeCommand(String newPassword, String newPasswordRepeated, String recoveryCode) {\n        this.newPassword = newPassword;\n        this.newPasswordRepeated = newPasswordRepeated;\n        this.recoveryCode = recoveryCode;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/recovery/dto/GetUserRegistrationWithRecoveryCodeQuery.java",
    "content": "package com.tomo.mcauthentication.application.recovery.dto;\n\nimport com.tomo.mcauthentication.application.contracts.BaseQuery;\n\nimport javax.validation.constraints.NotNull;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class GetUserRegistrationWithRecoveryCodeQuery extends BaseQuery {\n\n    @NotNull\n    String recoveryCode;\n\n    public GetUserRegistrationWithRecoveryCodeQuery(String recoveryCode) {\n        this.recoveryCode = recoveryCode;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/registration/ChangePasswordCommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.registration;\n\nimport com.tomo.mcauthentication.application.configuration.AbstractVoidyCommandHandler;\nimport com.tomo.mcauthentication.application.registration.command.ChangePasswordCommand;\nimport com.tomo.mcauthentication.domain.registration.EmailAuthenticationService;\nimport com.tomo.mcauthentication.domain.registration.UserRegistration;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationRepository;\nimport com.tomo.mcauthentication.domain.session.Session;\nimport com.tomo.mcauthentication.domain.session.SessionAuthenticationService;\n\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class ChangePasswordCommandHandler extends AbstractVoidyCommandHandler<ChangePasswordCommand> {\n\n    EmailAuthenticationService emailAuthenticationService;\n    SessionAuthenticationService sessionAuthenticationService;\n    UserRegistrationRepository userRegistrationRepository;\n\n    public ChangePasswordCommandHandler(\n            EmailAuthenticationService emailAuthenticationService,\n            SessionAuthenticationService aSessionAuthenticationService,\n            UserRegistrationRepository anUserRegistrationRepository) {\n        this.emailAuthenticationService = emailAuthenticationService;\n        this.sessionAuthenticationService = aSessionAuthenticationService;\n        this.userRegistrationRepository = anUserRegistrationRepository;\n    }\n\n    @Override\n    protected void abstractHandle(ChangePasswordCommand aCommand) {\n        Session session = sessionAuthenticationService.authenticate(aCommand.getAccessToken());\n\n        UserRegistration userRegistration = userRegistrationRepository.findByUserId(session.getUserId());\n\n        if (userRegistration == null) {\n            throw new IllegalStateException(String.format(\"User with id %s doesn't exist.\", session.getUserId().id()));\n        }\n\n        userRegistration.changePassword(aCommand.getOldPassword(), aCommand.getNewPassword(), aCommand.getNewPasswordRepeated());\n        userRegistrationRepository.save(userRegistration);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/registration/ConfirmUserRegistrationCommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.registration;\n\nimport com.tomo.mcauthentication.application.configuration.CommandHandler;\nimport com.tomo.mcauthentication.application.registration.command.ConfirmUserRegistrationCommand;\nimport com.tomo.mcauthentication.application.users.dto.BaseUserDto;\nimport com.tomo.mcauthentication.domain.registration.UserRegistration;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationRepository;\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\n\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class ConfirmUserRegistrationCommandHandler implements CommandHandler<ConfirmUserRegistrationCommand, BaseUserDto> {\n\n    UserRegistrationRepository userRegistrationRepository;\n    UserRepository userRepository;\n\n    public ConfirmUserRegistrationCommandHandler(\n            UserRegistrationRepository userRegistrationRepository,\n            UserRepository userRepository) {\n        this.userRegistrationRepository = userRegistrationRepository;\n        this.userRepository = userRepository;\n    }\n\n    @Override\n    public BaseUserDto handle(ConfirmUserRegistrationCommand command) {\n        UserRegistration userRegistration = userRegistrationRepository.findByConfirmationCode(command.getConfirmationLink());\n\n        if (userRegistration == null) {\n            throw new IllegalStateException(\n                    String.format(\"UserRegistration with confirmation link %s cannot be found.\", command.getConfirmationLink())\n            );\n        }\n\n        User user = userRegistration.createUser(userRepository);\n        userRegistration.setUserId(user.getUserId());\n\n        userRepository.save(user);\n        userRegistrationRepository.save(userRegistration);\n        return null;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/registration/GetUserRegistrationQueryHandler.java",
    "content": "package com.tomo.mcauthentication.application.registration;\n\nimport com.tomo.mcauthentication.application.configuration.QueryHandler;\nimport com.tomo.mcauthentication.application.registration.dto.UserRegistrationDto;\nimport com.tomo.mcauthentication.application.registration.query.GetUserRegistrationQuery;\n\npublic class GetUserRegistrationQueryHandler implements QueryHandler<GetUserRegistrationQuery, UserRegistrationDto> {\n\n    @Override public UserRegistrationDto handle(GetUserRegistrationQuery request) {\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/registration/NewUserRegisteredEventHandler.java",
    "content": "package com.tomo.mcauthentication.application.registration;\n\nimport com.tomo.mcauthentication.application.contracts.McAuthenticationModule;\nimport com.tomo.mcauthentication.application.registration.command.SendRegistrationConfirmationEmailCommand;\nimport com.tomo.ddd.domain.DomainEventPublisher;\nimport com.tomo.ddd.domain.DomainEventSubscriber;\nimport com.tomo.mcauthentication.domain.registration.events.UserRegistrationRequested;\n\nimport org.aspectj.lang.annotation.Aspect;\nimport org.aspectj.lang.annotation.Before;\nimport org.springframework.stereotype.Component;\n\n@Aspect\n@Component\npublic class NewUserRegisteredEventHandler {\n\n    private McAuthenticationModule authenticationModule;\n\n    /**\n     * In order to not mix business logic with plugins like a GUI..\n     * baseUrl + URI + queryString eg. localhost/register/confirm/?confirmationCode=\n     */\n    private String confirmationLink;\n\n    public NewUserRegisteredEventHandler(McAuthenticationModule authenticationModule, String confirmationLink) {\n        this.authenticationModule = authenticationModule;\n        this.confirmationLink = confirmationLink;\n    }\n\n    @Before(value = \"execution(public * com.tomo.mcauthentication.application.configuration.AbstractVoidyCommandHandler.*(..)) && target(com.tomo.mcauthentication.application.registration.RegisterNewUserCommandHandler))\")\n    public void listen() {\n        DomainEventPublisher\n            .instance()\n            .subscribe(new DomainEventSubscriber<UserRegistrationRequested>() {\n\n                public void handleEvent(UserRegistrationRequested aDomainEvent) {\n                    authenticationModule.executeCommand(new SendRegistrationConfirmationEmailCommand(\n                            aDomainEvent.getEmail(),\n                            confirmationLink,\n                            aDomainEvent.getConfirmationCode()));\n                }\n\n                public Class<UserRegistrationRequested> subscribedToEventType() {\n                    return UserRegistrationRequested.class; // all domain events\n                }\n            });\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/registration/RegisterNewUserCommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.registration;\n\nimport com.tomo.mcauthentication.application.configuration.AbstractVoidyCommandHandler;\nimport com.tomo.mcauthentication.application.registration.command.RegisterNewUserCommand;\nimport com.tomo.mcauthentication.domain.registration.UserRegistration;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationRepository;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\n\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class RegisterNewUserCommandHandler extends AbstractVoidyCommandHandler<RegisterNewUserCommand> {\n\n    UserRegistrationRepository userRegistrationRepository;\n    UserRepository userRepository;\n\n    public RegisterNewUserCommandHandler(\n            UserRegistrationRepository userRegistrationRepository,\n            UserRepository userRepository) {\n        this.userRegistrationRepository = userRegistrationRepository;\n        this.userRepository = userRepository;\n    }\n\n    @Override\n    protected void abstractHandle(RegisterNewUserCommand aCommand) {\n        UserRegistration userRegistration = UserRegistration.registerNewUser(\n                aCommand.getPassword(),\n                aCommand.getEmail(),\n                aCommand.getFirstName(),\n                aCommand.getLastName()\n        );\n\n        userRegistrationRepository.save(userRegistration);\n        //todo send email\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/registration/SendRegistrationConfirmationEmailCommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.registration;\n\nimport com.tomo.mcauthentication.application.configuration.AbstractVoidyCommandHandler;\nimport com.tomo.mcauthentication.application.registration.command.SendRegistrationConfirmationEmailCommand;\nimport com.tomo.ddd.email.EmailSender;\nimport com.tomo.ddd.port.adapter.message.email.EmailMessage;\n\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class SendRegistrationConfirmationEmailCommandHandler extends AbstractVoidyCommandHandler<SendRegistrationConfirmationEmailCommand> {\n\n    EmailSender emailMessageSender;\n\n    public SendRegistrationConfirmationEmailCommandHandler(EmailSender emailMessageSender) {\n        this.emailMessageSender = emailMessageSender;\n    }\n\n    @Override\n    protected void abstractHandle(SendRegistrationConfirmationEmailCommand aCommand) {\n        //todo maybe validate if exist\n        this.emailMessageSender.send(new EmailMessage(\n                aCommand.getEmail(), \"\"\n                , \"Confirm registration\",\n                \"Click on this confirmation link \" + aCommand.getConfirmLink() + aCommand.getConfirmationCode()));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/registration/command/ChangePasswordCommand.java",
    "content": "package com.tomo.mcauthentication.application.registration.command;\n\nimport com.tomo.mcauthentication.application.contracts.BaseCommand;\n\nimport javax.validation.constraints.NotNull;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class ChangePasswordCommand extends BaseCommand {\n\n    String accessToken;\n\n    @NotNull\n    private String oldPassword;\n\n    @NotNull\n    private String newPassword;\n\n    @NotNull\n    private String newPasswordRepeated;\n\n    public ChangePasswordCommand(String accessToken, String oldPassword, String newPassword, String newPasswordRepeated) {\n        this.accessToken = accessToken;\n        this.oldPassword = oldPassword;\n        this.newPassword = newPassword;\n        this.newPasswordRepeated = newPasswordRepeated;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/registration/command/ConfirmUserRegistrationCommand.java",
    "content": "package com.tomo.mcauthentication.application.registration.command;\n\nimport com.tomo.mcauthentication.application.contracts.BaseCommand;\n\nimport java.util.UUID;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Setter\n@Getter\n@NoArgsConstructor\npublic class ConfirmUserRegistrationCommand extends BaseCommand {\n\n    private String confirmationLink;\n\n    public ConfirmUserRegistrationCommand(String confirmLink) {\n        this.confirmationLink = confirmLink;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/registration/command/RegisterNewUserCommand.java",
    "content": "package com.tomo.mcauthentication.application.registration.command;\n\nimport com.tomo.mcauthentication.application.contracts.BaseCommand;\n\nimport javax.validation.constraints.NotNull;\nimport java.util.UUID;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class RegisterNewUserCommand extends BaseCommand {\n\n    @NotNull\n    String firstName;\n\n    @NotNull\n    String lastName;\n\n    @NotNull\n    String email;\n\n    @NotNull\n    String password;\n\n    public RegisterNewUserCommand(String firstName, String lastName, String email, String password) {\n        this.firstName = firstName;\n        this.lastName = lastName;\n        this.email = email;\n        this.password = password;\n    }\n\n    public String getPassword() {\n        return password;\n    }\n\n    public void setPassword(String password) {\n        this.password = password;\n    }\n\n    public String getEmail() {\n        return email;\n    }\n\n    public void setEmail(String email) {\n        this.email = email;\n    }\n\n    public String getFirstName() {\n        return firstName;\n    }\n\n    public void setFirstName(String firstName) {\n        this.firstName = firstName;\n    }\n\n    public String getLastName() {\n        return lastName;\n    }\n\n    public void setLastName(String lastName) {\n        this.lastName = lastName;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/registration/command/SendRegistrationConfirmationEmailCommand.java",
    "content": "package com.tomo.mcauthentication.application.registration.command;\n\nimport com.tomo.mcauthentication.application.contracts.BaseCommand;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class SendRegistrationConfirmationEmailCommand extends BaseCommand {\n    String email;\n    String confirmLink;\n    String confirmationCode;\n\n    public SendRegistrationConfirmationEmailCommand(String email, String confirmLink, String confirmationCode) {\n        this.email = email;\n        this.confirmLink = confirmLink;\n        this.confirmationCode = confirmationCode;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/registration/dto/UserRegistrationDto.java",
    "content": "package com.tomo.mcauthentication.application.registration.dto;\n\nimport com.tomo.mcauthentication.application.contracts.Response;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationId;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationStatus;\n\nimport java.time.LocalDateTime;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class UserRegistrationDto implements Response {\n\n    private String email;\n    private String firstName;\n    private String lastName;\n    private LocalDateTime registerDate;\n    private UserRegistrationStatus status;\n\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/registration/query/GetUserRegistrationQuery.java",
    "content": "package com.tomo.mcauthentication.application.registration.query;\n\nimport com.tomo.mcauthentication.application.contracts.BaseQuery;\n\nimport java.util.UUID;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class GetUserRegistrationQuery extends BaseQuery {\n\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/users/ChangeUserDetailsCommandHandler.java",
    "content": "package com.tomo.mcauthentication.application.users;\n\nimport com.tomo.mcauthentication.application.configuration.AbstractVoidyCommandHandler;\nimport com.tomo.mcauthentication.application.users.command.ChangeUserDetailsCommand;\nimport com.tomo.mcauthentication.domain.registration.EmailAuthenticationService;\nimport com.tomo.mcauthentication.domain.session.TokenProvider;\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserId;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\n\nimport org.springframework.stereotype.Service;\n\nimport lombok.AllArgsConstructor;\n\n@Service\n@AllArgsConstructor\npublic class ChangeUserDetailsCommandHandler extends AbstractVoidyCommandHandler<ChangeUserDetailsCommand> {\n\n    EmailAuthenticationService emailAuthenticationService;\n    TokenProvider tokenProvider;\n    UserRepository userRepository;\n\n    @Override\n    public void abstractHandle(ChangeUserDetailsCommand aCommand) {\n        UserId userId = tokenProvider.getUserIdFromToken(aCommand.getAuthToken());\n\n        if (!aCommand.getUserId().equals(userId.id())) {\n            throw new IllegalArgumentException(String.format(\"Forbidden access. User with ID %s cannot change user details for user with ID: %s\", userId.id(), aCommand.getUserId()));\n        }\n\n        User user = userRepository.findById(new UserId(aCommand.getUserId()));\n        user.updateDetails(aCommand.getFirstName(), aCommand.getLastName());\n\n        userRepository.save(user);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/users/GetUserQueryHandler.java",
    "content": "package com.tomo.mcauthentication.application.users;\n\nimport com.tomo.mcauthentication.application.BaseMapper;\nimport com.tomo.mcauthentication.application.configuration.QueryHandler;\nimport com.tomo.mcauthentication.application.users.dto.BaseUserDto;\nimport com.tomo.mcauthentication.application.users.query.GetUserQuery;\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\n\nimport org.modelmapper.ModelMapper;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class GetUserQueryHandler extends BaseMapper implements QueryHandler<GetUserQuery, BaseUserDto> {\n\n    private UserRepository userRepository;\n\n    public GetUserQueryHandler(\n            UserRepository userRepository,\n            ModelMapper modelMapper) {\n        super(modelMapper);\n        this.userRepository = userRepository;\n    }\n\n    @Override\n    public BaseUserDto handle(GetUserQuery query) {\n        User user = userRepository.findById(query.getUserId());\n\n        if (user == null) {\n            throw new IllegalStateException(String.format(\"User with id %s doesn't exists.\", query.getUserId().toString()));\n        }\n\n        return toDto(user);\n    }\n\n    private BaseUserDto toDto(User user) {\n        return modelMapper.map(user, BaseUserDto.class);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/users/command/ChangeUserDetailsCommand.java",
    "content": "package com.tomo.mcauthentication.application.users.command;\n\nimport com.tomo.mcauthentication.application.contracts.security.AbstractAuthorizeCommand;\n\nimport java.util.List;\nimport java.util.UUID;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class ChangeUserDetailsCommand extends AbstractAuthorizeCommand {\n\n    private UUID userId;\n    private String firstName;\n    private String lastName;\n\n    public ChangeUserDetailsCommand(UUID userId, String firstName, String lastName) {\n        this.userId = userId;\n        this.firstName = firstName;\n        this.lastName = lastName;\n    }\n\n    @Override\n    public List<String> getAuthorities() {\n        List<String> authorities = super.getAuthorities();\n        authorities.add(\"ADMIN\");\n        return authorities;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/users/dto/BaseUserDto.java",
    "content": "package com.tomo.mcauthentication.application.users.dto;\n\nimport com.tomo.mcauthentication.application.contracts.Response;\nimport com.tomo.mcauthentication.domain.users.UserId;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class BaseUserDto implements Response {\n    private String userId;\n    String firstName;\n    String lastName;\n\n    public void setUserId(UserId userId) {\n        this.userId = userId.id().toString();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/application/users/query/GetUserQuery.java",
    "content": "package com.tomo.mcauthentication.application.users.query;\n\nimport com.tomo.mcauthentication.application.contracts.security.AbstractAuthenticateQuery;\nimport com.tomo.mcauthentication.domain.users.UserId;\n\nimport javax.validation.constraints.NotNull;\nimport java.util.UUID;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\n@Getter\n@Setter\npublic class GetUserQuery extends AbstractAuthenticateQuery {\n\n    @NotNull\n    String userId;\n\n    public GetUserQuery(String userId) {\n        this.userId = userId;\n    }\n\n    public UserId getUserId() {\n        return new UserId(UUID.fromString(this.userId));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/DomainRegistry.java",
    "content": "package com.tomo.mcauthentication.domain;\n\nimport com.tomo.mcauthentication.domain.registration.PasswordService;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationRepository;\nimport com.tomo.mcauthentication.domain.registration.rules.UserRegistrationMustBeUnique;\nimport com.tomo.mcauthentication.domain.session.TokenProvider;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\nimport com.tomo.mcauthentication.domain.users.rules.UserEmailMustBeUnique;\n\nimport org.modelmapper.ModelMapper;\nimport org.springframework.beans.BeansException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class DomainRegistry implements ApplicationContextAware {\n\n    private static ApplicationContext applicationContext;\n\n    public static EncryptionService encryptionService() {\n        return (EncryptionService) applicationContext.getBean(\"MD5EncryptionService\");\n    }\n\n    public static PasswordService passwordService() {\n        return (PasswordService) applicationContext.getBean(\"passwordService\");\n    }\n\n    public static TokenProvider tokenProvider() {\n        return (TokenProvider) applicationContext.getBean(\"jwtTokenProvider\");\n    }\n\n    public static ModelMapper modelMapper() {\n        return (ModelMapper) applicationContext.getBean(\"modelMapper\");\n    }\n\n    public static UserRepository userRepository() {\n        return (UserRepository) applicationContext.getBean(\"userRepository\");\n    }\n\n    public static UserRegistrationRepository userRegistrationRepository() {\n        return (UserRegistrationRepository) applicationContext.getBean(\"userRegistrationRepository\");\n    }\n\n    public static UserEmailMustBeUnique userEmailMustBeUnique(String anEmail) {\n        return new UserEmailMustBeUnique(userRepository(), anEmail);\n    }\n\n    public static UserRegistrationMustBeUnique userRegistrationMustBeUnique(String anEmail) {\n        return new UserRegistrationMustBeUnique(userRegistrationRepository(), anEmail);\n    }\n\n    @Override\n    public void setApplicationContext(ApplicationContext anApplicationContext) throws BeansException {\n//        if (DomainRegistry.applicationContext == null) {\n//            DomainRegistry.applicationContext = anApplicationContext;\n//        }\n\n            DomainRegistry.applicationContext = anApplicationContext;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/EncryptionService.java",
    "content": "package com.tomo.mcauthentication.domain;\n\npublic interface EncryptionService {\n\n    String encryptedValue(String aPlainTextValue);\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/oauth2/OAuth2Authentication.java",
    "content": "package com.tomo.mcauthentication.domain.oauth2;\n\npublic interface OAuth2Authentication {\n     OAuth2Principal authenticate(String anAccessCode);\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/oauth2/OAuth2Principal.java",
    "content": "package com.tomo.mcauthentication.domain.oauth2;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\n\n@Getter\n@NoArgsConstructor\npublic class OAuth2Principal {\n    private String id;\n    private String email;\n    private String firstName;\n    private String lastName;\n    private String imageUrl;\n    private String provider;\n\n    public OAuth2Principal(String id, String email, String firstName, String lastName, String imageUrl, String provider) {\n        this.id = id;\n        this.email = email;\n        this.firstName = firstName;\n        this.lastName = lastName;\n        this.imageUrl = imageUrl;\n        this.provider = provider;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/oauth2/OAuth2Service.java",
    "content": "package com.tomo.mcauthentication.domain.oauth2;\n\nimport com.tomo.ddd.domain.BusinessRuleValidationException;\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\nimport com.tomo.mcauthentication.domain.users.rules.UserEmailMustBeUnique;\n\npublic class OAuth2Service {\n\n    private OAuth2Authentication oAuth2Authentication;\n    private UserRepository userRespository;\n\n    public OAuth2Service(OAuth2Authentication oAuth2Authentication, UserRepository userRespository) {\n        this.oAuth2Authentication = oAuth2Authentication;\n        this.userRespository = userRespository;\n    }\n\n    public User registerAuthenticate(String anAccessCode) {\n        OAuth2Principal principal = oAuth2Authentication.authenticate(anAccessCode);\n        User user;\n        try {\n            user = authenticateAndRegister(principal);\n        } catch (BusinessRuleValidationException exception) {\n            if (UserEmailMustBeUnique.class == exception.getBrokenRule().getClass()) {\n                user = userRespository.findByEmail(principal.getEmail());\n                if (!User.AuthProvider.valueOf(principal.getProvider()).equals(user.getProvider())) {\n                    throw exception;\n                }\n            } else {\n                throw exception;\n            }\n        }\n\n        return user;\n    }\n\n    protected User authenticateAndRegister(OAuth2Principal principal) {\n       User user = new User(\n                userRespository.nextIdentity(),\n                principal.getFirstName(),\n                principal.getLastName(),\n                principal.getEmail(),\n                User.AuthProvider.valueOf(principal.getProvider()));\n\n       return userRespository.save(user);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/EmailAuthenticationService.java",
    "content": "package com.tomo.mcauthentication.domain.registration;\n\nimport com.tomo.ddd.domain.BusinessRuleValidator;\nimport com.tomo.mcauthentication.domain.EncryptionService;\nimport com.tomo.mcauthentication.domain.registration.rules.PasswordsMustMatch;\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\n\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class EmailAuthenticationService extends BusinessRuleValidator {\n\n    UserRegistrationRepository userRegistrationRepository;\n    UserRepository userRepository;\n    EncryptionService encryptionService;\n\n    public EmailAuthenticationService(\n            UserRegistrationRepository userRegistrationRepository,\n            UserRepository userRepository,\n            EncryptionService encryptionService) {\n        this.userRegistrationRepository = userRegistrationRepository;\n        this.userRepository = userRepository;\n        this.encryptionService = encryptionService;\n    }\n\n    public User authenticate(\n            String anEmail,\n            String aPassword) {\n        this.assertArgumentNotEmpty(anEmail, \"Email must be provided.\");\n        this.assertArgumentNotEmpty(aPassword, \"Password must be provided.\");\n\n        UserRegistration userRegistration = userRegistrationRepository.findByEmail(anEmail);\n\n        if (userRegistration == null) {\n            throw new IllegalStateException(String.format(\"User with email %s doesn't exists.\", anEmail));\n        }\n\n        this.checkRule(new PasswordsMustMatch(userRegistration.getPassword(), encryptionService.encryptedValue(aPassword)));\n\n        return userRepository.findByEmail(anEmail);\n    }\n\n    public String createPasswordRecoveryCode(String anEmail) {\n        this.assertArgumentNotEmpty(anEmail, \"Email must be provided.\");\n\n        UserRegistration userRegistration = userRegistrationRepository.findByEmail(anEmail);\n\n        if (userRegistration == null) {\n            throw new IllegalStateException(String.format(\"User with email %s doesn't exists.\", anEmail));\n        }\n\n        return userRegistration.createRecoveryCode();\n    }\n\n    public void recoverPasswordWithRecoveryCode(String aRecoveryCode, String aNewPassword, String aNewPasswordRepeated) {\n        this.assertArgumentNotNull(aRecoveryCode, \"Recovery code is missing.\");\n\n        UserRegistration userRegistration = userRegistrationRepository\n                .findByRecoveryCode(encryptionService.encryptedValue(aRecoveryCode));\n\n        if (userRegistration == null) {\n            throw new IllegalStateException(String.format(\"User with recovery code %s doesn't exists.\", aRecoveryCode));\n        }\n\n        userRegistration.changePasswordWithRecoveryCode(aRecoveryCode, aNewPassword, aNewPasswordRepeated);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/PasswordService.java",
    "content": "package com.tomo.mcauthentication.domain.registration;\n\nimport com.tomo.ddd.AssertionConcern;\n\nimport org.springframework.stereotype.Component;\n\nimport java.util.Random;\n\n@Component\npublic final class PasswordService extends AssertionConcern {\n\n    private static final String DIGITS = \"0123456789\";\n    private static final String LETTERS = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n    private static final int STRONG_THRESHOLD = 20;\n    private static final String SYMBOLS = \"\\\"`!?$?%^&*()_-+={[}]:;@'~#|\\\\<,>.?/\";\n    private static final int VERY_STRONG_THRESHOLD = 40;\n\n    public PasswordService() {\n        super();\n    }\n\n    public String generateStrongPassword() {\n        String generatedPassword = null;\n\n        StringBuffer password = new StringBuffer();\n\n        Random random = new Random();\n\n        boolean isStrong = false;\n\n        int index = 0;\n\n        while (!isStrong) {\n\n            int opt = random.nextInt(4);\n\n            switch (opt) {\n            case 0:\n                index = random.nextInt(LETTERS.length());\n                password.append(LETTERS.substring(index, index+1));\n                break;\n            case 1:\n                index = random.nextInt(LETTERS.length());\n                password.append(LETTERS.substring(index, index+1).toLowerCase());\n                break;\n            case 2:\n                index = random.nextInt(DIGITS.length());\n                password.append(DIGITS.substring(index, index+1));\n                break;\n            case 3:\n                index = random.nextInt(SYMBOLS.length());\n                password.append(SYMBOLS.substring(index, index+1));\n                break;\n            }\n\n            generatedPassword = password.toString();\n\n            if (generatedPassword.length() >= 7) {\n                isStrong = this.isStrong(generatedPassword);\n            }\n        }\n\n        return generatedPassword;\n    }\n\n    public boolean isStrong(String aPlainTextPassword) {\n        return this.calculatePasswordStrength(aPlainTextPassword) >= STRONG_THRESHOLD;\n    }\n\n    public boolean isVeryStrong(String aPlainTextPassword) {\n        return this.calculatePasswordStrength(aPlainTextPassword) >= VERY_STRONG_THRESHOLD;\n    }\n\n    public boolean isWeak(String aPlainTextPassword) {\n        return this.calculatePasswordStrength(aPlainTextPassword) < STRONG_THRESHOLD;\n    }\n\n    private int calculatePasswordStrength(String aPlainTextPassword) {\n        this.assertArgumentNotNull(aPlainTextPassword, \"Password strength cannot be tested on null.\");\n\n        int strength = 0;\n\n        int length = aPlainTextPassword.length();\n\n        if (length > 7) {\n            strength += 10;\n            // bonus: one point each additional\n            strength += (length - 7);\n        }\n\n        int digitCount = 0;\n        int letterCount = 0;\n        int lowerCount = 0;\n        int upperCount = 0;\n        int symbolCount = 0;\n\n        for (int idx = 0; idx < length; ++idx) {\n\n            char ch = aPlainTextPassword.charAt(idx);\n\n            if (Character.isLetter(ch)) {\n                ++letterCount;\n                if (Character.isUpperCase(ch)) {\n                    ++upperCount;\n                } else {\n                    ++lowerCount;\n                }\n            } else if (Character.isDigit(ch)) {\n                ++digitCount;\n            } else {\n                ++symbolCount;\n            }\n        }\n\n        strength += (upperCount + lowerCount + symbolCount);\n\n        // bonus: letters and digits\n        if (letterCount >= 2 && digitCount >= 2) {\n            strength += (letterCount + digitCount);\n        }\n\n        return strength;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/UserRegistration.java",
    "content": "package com.tomo.mcauthentication.domain.registration;\n\nimport com.tomo.ddd.domain.ConcurrencySafeEntity;\nimport com.tomo.ddd.domain.DomainEvent;\nimport com.tomo.ddd.domain.DomainEventPublisher;\nimport com.tomo.mcauthentication.domain.DomainRegistry;\nimport com.tomo.mcauthentication.domain.registration.events.PasswordChanged;\nimport com.tomo.mcauthentication.domain.registration.events.PasswordRecovered;\nimport com.tomo.mcauthentication.domain.registration.events.PasswordRecoveryCodeCreated;\nimport com.tomo.mcauthentication.domain.registration.events.UserRegistrationConfirmed;\nimport com.tomo.mcauthentication.domain.registration.events.UserRegistrationRequested;\nimport com.tomo.mcauthentication.domain.registration.rules.PasswordRecoveryCodeShouldBeExpiredOrNull;\nimport com.tomo.mcauthentication.domain.registration.rules.PasswordRecoveryCodeShouldNotExpired;\nimport com.tomo.mcauthentication.domain.registration.rules.PasswordsMustMatch;\nimport com.tomo.mcauthentication.domain.registration.rules.RecoveryCodeMustMatch;\nimport com.tomo.mcauthentication.domain.registration.rules.UserRegistrationCannotBeConfirmedAfterExpiration;\nimport com.tomo.mcauthentication.domain.registration.rules.UserRegistrationCannotBeConfirmedMoreThanOnce;\nimport com.tomo.mcauthentication.domain.registration.rules.UserRegistrationMustBeConfirmed;\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserId;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\n\nimport javax.persistence.AttributeOverride;\nimport javax.persistence.Column;\nimport javax.persistence.Embedded;\nimport javax.persistence.Entity;\nimport javax.persistence.EnumType;\nimport javax.persistence.Enumerated;\nimport javax.persistence.GeneratedValue;\nimport javax.persistence.GenerationType;\nimport javax.persistence.Id;\nimport java.time.LocalDateTime;\nimport java.time.temporal.ChronoField;\nimport java.util.UUID;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Entity\n@NoArgsConstructor\n@Getter\n@Setter\npublic class UserRegistration extends ConcurrencySafeEntity {\n\n    public static Long RECOVERY_CODE_EXPIREATION_MSEC = 172800000L;\n\n    @Id\n    @GeneratedValue(strategy = GenerationType.IDENTITY)\n    private long id;\n    private String password;\n    private String email;\n    private String firstName;\n    private String lastName;\n    private String confirmationCode;\n    private LocalDateTime registerDate;\n    @Enumerated(EnumType.STRING)\n    private UserRegistrationStatus status;\n    private String recoveryCode;\n    private LocalDateTime recoveryCodeExpirationDate;\n\n    @Embedded\n    @AttributeOverride(name=\"id\", column = @Column(name=\"user_id\"))\n    private UserId userId;\n\n    public static UserRegistration registerNewUser(\n            String password,\n            String email,\n            String firstName,\n            String lastName)\n    {\n        return new UserRegistration(password, email, firstName, lastName);\n    }\n\n    private UserRegistration(\n            String aPassword,\n            String anEmail,\n            String aFirstName,\n            String aLastName) {\n        this.checkRule(DomainRegistry.userRegistrationMustBeUnique(anEmail));\n        this.checkRule(DomainRegistry.userEmailMustBeUnique(anEmail));\n        this.email = anEmail;\n        this.firstName = aFirstName;\n        this.lastName = aLastName;\n        this.confirmationCode = UUID.randomUUID().toString();\n        this.registerDate = LocalDateTime.now();\n        this.status = UserRegistrationStatus.WaitingForConfirmation;\n\n        this.protectPassword(\"\", aPassword);\n\n        this.publishEvent(new UserRegistrationRequested(\n                this.email,\n                this.confirmationCode,\n                this.firstName,\n                this.lastName,\n                this.registerDate,\n                this.status\n        ));\n    }\n\n    public User createUser(UserRepository userRespository) {\n        this.checkRule(new UserRegistrationCannotBeConfirmedMoreThanOnce(this.status));\n        this.checkRule(new UserRegistrationCannotBeConfirmedAfterExpiration(this.registerDate));\n\n        this.setStatus(UserRegistrationStatus.Confirmed);\n\n        UserId userId = userRespository.nextIdentity();\n        this.setUserId(userId);\n\n        this.publishEvent(new UserRegistrationConfirmed(this.id, this.getStatus(), this.getUserId()));\n\n        return new User(userId, getFirstName(), getLastName(), getEmail(), User.AuthProvider.EMAIL);\n    }\n\n    public String createRecoveryCode() {\n        this.checkRule(new UserRegistrationMustBeConfirmed(this.getStatus()));\n        this.checkRule(new PasswordRecoveryCodeShouldBeExpiredOrNull(this));\n\n        String recoveryCode = UUID.randomUUID().toString();\n        this.recoveryCodeExpirationDate = LocalDateTime.now().plus(RECOVERY_CODE_EXPIREATION_MSEC, ChronoField.MILLI_OF_DAY.getBaseUnit());\n\n        this.setRecoveryCodeExpirationDate(recoveryCodeExpirationDate);\n        this.setRecoveryCode(this.asEncryptedValue(recoveryCode));\n\n        this.publishEvent(new PasswordRecoveryCodeCreated(\n                this.id,\n                this.email,\n                recoveryCode,\n                this.recoveryCodeExpirationDate));\n\n        return recoveryCode;\n    }\n\n    public boolean isRecoveryCodeUnexpired() {\n        return recoveryCodeExpirationDate != null && recoveryCodeExpirationDate.isAfter(LocalDateTime.now());\n    }\n\n    public boolean isRecoveryCodeExpired() {\n        return recoveryCodeExpirationDate != null && recoveryCodeExpirationDate.isBefore(LocalDateTime.now());\n    }\n\n    public void changePassword(String anOldPassword, String aNewPassword, String aNewPasswordRepeated) {\n        this.assertArgumentNotNull(anOldPassword, \"Old password is missing.\");\n        this.assertNewPassword(aNewPassword, aNewPasswordRepeated);\n\n        this.checkRule(new PasswordsMustMatch(this.getPassword(), this.asEncryptedValue(anOldPassword)));\n\n        this.protectPassword(this.getPassword(), aNewPassword);\n\n        this.publishEvent(new PasswordChanged(this.id, this.password));\n    }\n\n    public void changePasswordWithRecoveryCode(String aRecoveryCode, String aNewPassword, String aNewPasswordRepeated) {\n        this.assertArgumentNotNull(aNewPassword, \"New password is missing.\");\n        this.assertNewPassword(aNewPassword, aNewPasswordRepeated);\n\n        this.checkRule(new RecoveryCodeMustMatch(this.asEncryptedValue(aRecoveryCode), this.getRecoveryCode()));\n        this.checkRule(new PasswordRecoveryCodeShouldNotExpired(this));\n\n        this.protectPassword(this.getPassword(), aNewPassword);\n        this.setRecoveryCodeExpirationDate(LocalDateTime.now());\n\n        this.publishEvent(new PasswordRecovered(\n                this.id,\n                this.getPassword(),\n                this.getRecoveryCode()\n        ));\n    }\n\n    protected void assertNewPassword(String aNewPassword, String aNewPasswordRepeated) {\n        this.assertArgumentNotNull(aNewPassword, \"New password is missing.\");\n        this.assertArgumentNotNull(aNewPasswordRepeated, \"Repeated password is missing.\");\n        this.assertArgumentEquals(aNewPassword, aNewPasswordRepeated, \"Provided passwords must be equal.\");\n    }\n\n    protected void protectPassword(String aCurrentPassword, String aChangedPassword) {\n        this.assertPasswordsNotSame(aCurrentPassword, this.asEncryptedValue(aChangedPassword));\n        this.assertPasswordNotWeak(aChangedPassword);\n        this.assertUsernamePasswordNotSame(aChangedPassword);\n        this.setPassword(this.asEncryptedValue(aChangedPassword));\n    }\n\n    protected void assertPasswordsNotSame(String aCurrentPassword, String aChangedPassword) {\n        this.assertArgumentNotEquals(\n                aCurrentPassword,\n                aChangedPassword,\n                \"The password is unchanged.\");\n    }\n\n    protected void assertPasswordNotWeak(String aPlainTextPassword) {\n        this.assertArgumentFalse(\n                DomainRegistry.passwordService().isWeak(aPlainTextPassword),\n                \"The password must be stronger.\");\n    }\n\n    protected void assertUsernamePasswordNotSame(String aPlainTextPassword) {\n        this.assertArgumentNotEquals(\n                this.getEmail(),\n                aPlainTextPassword,\n                \"The username and password must not be the same.\");\n    }\n\n    protected String asEncryptedValue(String aPlainTextPassword) {\n        String encryptedValue =\n                DomainRegistry\n                        .encryptionService()\n                        .encryptedValue(aPlainTextPassword);\n\n        return encryptedValue;\n    }\n\n    protected void setPassword(String aPassword) {\n        this.password = aPassword;\n    }\n\n    private void publishEvent(DomainEvent domainEvent) {\n        DomainEventPublisher.instance().publish(domainEvent);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/UserRegistrationId.java",
    "content": "package com.tomo.mcauthentication.domain.registration;\n\nimport com.tomo.ddd.domain.AbstractId;\n\nimport javax.persistence.Embeddable;\nimport java.util.UUID;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Embeddable\n@Getter\n@Setter\n@NoArgsConstructor\npublic class UserRegistrationId extends AbstractId {\n\n    public UserRegistrationId(UUID anId) {\n        super(anId);\n    }\n\n    @Override\n    protected int hashPrimeValue() {\n        return 0;\n    }\n\n    @Override\n    protected int hashOddValue() {\n        return 0;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/UserRegistrationRepository.java",
    "content": "package com.tomo.mcauthentication.domain.registration;\n\nimport com.tomo.ddd.domain.BaseRepository;\nimport com.tomo.mcauthentication.domain.users.UserId;\n\nimport java.util.List;\n\npublic interface UserRegistrationRepository extends BaseRepository<UserRegistration, Long> {\n    List<UserRegistration> findAllByEmail(List<String> emails);\n    UserRegistration findByEmail(String anEmail);\n    long countByEmailAndStatus(String email, UserRegistrationStatus status);\n    UserRegistration findByConfirmationCode(String confirmationCode);\n    UserRegistration findByRecoveryCode(String aRecoveryCode);\n    UserRegistration findByUserId(UserId anUserId);\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/UserRegistrationStatus.java",
    "content": "package com.tomo.mcauthentication.domain.registration;\npublic enum\nUserRegistrationStatus {\n    WaitingForConfirmation(\"WaitingForConfirmation\"),\n    Confirmed(\"Confirmed\"),\n    Expired(\"Expired\");\n\n    String value;\n\n    UserRegistrationStatus(String value) {\n        this.value = value;\n    }\n\n    @Override\n    public String toString() {\n        return this.value;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/UsersCounter.java",
    "content": "package com.tomo.mcauthentication.domain.registration;\n\npublic interface UsersCounter {\n    int countUsersWithLogin();\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/events/PasswordChanged.java",
    "content": "package com.tomo.mcauthentication.domain.registration.events;\n\nimport com.tomo.ddd.domain.BaseDomainEvent;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class PasswordChanged extends BaseDomainEvent  {\n    private long userRegistrationId;\n    private String password; //encrypted\n\n    public PasswordChanged(long userRegistrationId, String password) {\n        this.userRegistrationId = userRegistrationId;\n        this.password = password;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/events/PasswordRecovered.java",
    "content": "package com.tomo.mcauthentication.domain.registration.events;\n\nimport com.tomo.ddd.domain.BaseDomainEvent;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class PasswordRecovered extends BaseDomainEvent  {\n    private long userRegistrationId;\n    private String password; //encrypted\n    private String recoveryCode; //encrypted\n\n    public PasswordRecovered(long userRegistrationId, String password, String recoveryCode) {\n        this.userRegistrationId = userRegistrationId;\n        this.password = password;\n        this.recoveryCode = recoveryCode;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/events/PasswordRecoveryCodeCreated.java",
    "content": "package com.tomo.mcauthentication.domain.registration.events;\n\nimport com.tomo.ddd.domain.BaseDomainEvent;\n\nimport java.time.LocalDateTime;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class PasswordRecoveryCodeCreated extends BaseDomainEvent  {\n    long userRegistrationId;\n    private String email;\n    private String recoveryCode;\n    private LocalDateTime recoveryCodeExpirationDate;\n\n    public PasswordRecoveryCodeCreated(long userRegistrationId, String email, String recoveryCode, LocalDateTime recoveryCodeExpirationDate) {\n        this.userRegistrationId = userRegistrationId;\n        this.email = email;\n        this.recoveryCode = recoveryCode;\n        this.recoveryCodeExpirationDate = recoveryCodeExpirationDate;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/events/UserRegistrationConfirmed.java",
    "content": "package com.tomo.mcauthentication.domain.registration.events;\n\nimport com.tomo.ddd.domain.BaseDomainEvent;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationStatus;\nimport com.tomo.mcauthentication.domain.users.UserId;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class UserRegistrationConfirmed extends BaseDomainEvent  {\n    private long userRegistrationId;\n    private UserRegistrationStatus status;\n    private UserId userId;\n\n    public UserRegistrationConfirmed(long userRegistrationId, UserRegistrationStatus status, UserId userId) {\n        this.userRegistrationId = userRegistrationId;\n        this.status = status;\n        this.userId = userId;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/events/UserRegistrationRequested.java",
    "content": "package com.tomo.mcauthentication.domain.registration.events;\n\nimport com.tomo.ddd.domain.BaseDomainEvent;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationStatus;\n\nimport java.time.LocalDateTime;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class UserRegistrationRequested extends BaseDomainEvent  {\n    private long userRegistrationId;\n    private String email;\n    private String confirmationCode;\n    private String firstName;\n    private String lastName;\n    private LocalDateTime registerDate;\n    private UserRegistrationStatus status;\n\n    public UserRegistrationRequested(\n            String email,\n            String confirmationCode,\n            String firstName,\n            String lastName,\n            LocalDateTime registerDate,\n            UserRegistrationStatus status) {\n        this.email = email;\n        this.confirmationCode = confirmationCode;\n        this.firstName = firstName;\n        this.lastName = lastName;\n        this.registerDate = registerDate;\n        this.status = status;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/rules/PasswordRecoveryCodeShouldBeExpiredOrNull.java",
    "content": "package com.tomo.mcauthentication.domain.registration.rules;\n\nimport com.tomo.ddd.domain.BusinessRule;\nimport com.tomo.mcauthentication.domain.registration.UserRegistration;\n\npublic class PasswordRecoveryCodeShouldBeExpiredOrNull implements BusinessRule {\n\n    private UserRegistration userRegistration;\n\n    public PasswordRecoveryCodeShouldBeExpiredOrNull(UserRegistration aUserRegistration) {\n        this.userRegistration = aUserRegistration;\n    }\n\n    @Override\n    public Boolean isRuleComplied() {\n        return userRegistration.isRecoveryCodeExpired() || userRegistration.getRecoveryCode() == null;\n    }\n\n    @Override\n    public String message() {\n        return \"User recovery code is not expired yet. You can't get new one after the current code expire.\";\n    }\n}\n\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/rules/PasswordRecoveryCodeShouldNotExpired.java",
    "content": "package com.tomo.mcauthentication.domain.registration.rules;\n\nimport com.tomo.ddd.domain.BusinessRule;\nimport com.tomo.mcauthentication.domain.registration.UserRegistration;\n\npublic class PasswordRecoveryCodeShouldNotExpired implements BusinessRule {\n\n    private UserRegistration userRegistration;\n\n    public PasswordRecoveryCodeShouldNotExpired(UserRegistration aUserRegistration) {\n        this.userRegistration = aUserRegistration;\n    }\n\n    @Override\n    public Boolean isRuleComplied() {\n        return userRegistration.isRecoveryCodeUnexpired();\n    }\n\n    @Override\n    public String message() {\n        return \"User recovery code is not expired yet. You can't get new one after the current code expire.\";\n    }\n}\n\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/rules/PasswordsMustMatch.java",
    "content": "package com.tomo.mcauthentication.domain.registration.rules;\n\nimport com.tomo.ddd.domain.BusinessRule;\n\npublic class PasswordsMustMatch implements BusinessRule {\n\n    private String providedPassoword;\n    private String storedPassword;\n\n    public PasswordsMustMatch(String storedPassword, String providedPassoword) {\n        this.storedPassword = storedPassword;\n        this.providedPassoword = providedPassoword;\n    }\n\n    @Override\n    public Boolean isRuleComplied() {\n        return providedPassoword.equals(storedPassword);\n    }\n\n    @Override\n    public String message() {\n        return \"Passwords dont match.\";\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/rules/RecoveryCodeMustMatch.java",
    "content": "package com.tomo.mcauthentication.domain.registration.rules;\n\nimport com.tomo.ddd.domain.BusinessRule;\n\npublic class RecoveryCodeMustMatch implements BusinessRule {\n\n    private String providedCode;\n    private String storedCode;\n\n    public RecoveryCodeMustMatch(String aStoredCode, String aProvidedCode) {\n        this.storedCode = aStoredCode;\n        this.providedCode = aProvidedCode;\n    }\n\n    @Override\n    public Boolean isRuleComplied() {\n        return providedCode.equals(storedCode);\n    }\n\n    @Override\n    public String message() {\n        return \"Passwords dont match.\";\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/rules/UserRegistrationCannotBeConfirmedAfterExpiration.java",
    "content": "package com.tomo.mcauthentication.domain.registration.rules;\n\nimport com.tomo.ddd.domain.BusinessRule;\n\nimport java.time.LocalDateTime;\n\npublic class UserRegistrationCannotBeConfirmedAfterExpiration implements BusinessRule {\n\n    public static final int CONFIRMATION_LINK_DURATION = 8;\n\n    LocalDateTime registerDate;\n\n    public UserRegistrationCannotBeConfirmedAfterExpiration(LocalDateTime aRegisterDate) {\n        this.registerDate = aRegisterDate;\n    }\n\n    @Override\n    public Boolean isRuleComplied() {\n        return LocalDateTime.now().isBefore(this.registerDate.plusDays(CONFIRMATION_LINK_DURATION));\n    }\n\n    @Override\n    public String message() {\n        return null;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/rules/UserRegistrationCannotBeConfirmedMoreThanOnce.java",
    "content": "package com.tomo.mcauthentication.domain.registration.rules;\n\nimport com.tomo.ddd.domain.BusinessRule;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationStatus;\n\npublic class UserRegistrationCannotBeConfirmedMoreThanOnce implements BusinessRule {\n\n    UserRegistrationStatus status;\n\n    public UserRegistrationCannotBeConfirmedMoreThanOnce(UserRegistrationStatus aStatus) {\n        this.status = aStatus;\n    }\n\n    @Override\n    public Boolean isRuleComplied() {\n        return !this.status.equals(UserRegistrationStatus.Confirmed);\n    }\n\n    @Override\n    public String message() {\n        return \"User Registration cannot be confirmed more than once\";\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/rules/UserRegistrationMustBeConfirmed.java",
    "content": "package com.tomo.mcauthentication.domain.registration.rules;\n\nimport com.tomo.ddd.domain.BusinessRule;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationStatus;\n\npublic class UserRegistrationMustBeConfirmed implements BusinessRule {\n\n    private UserRegistrationStatus userRegistrationStatus;\n\n    public UserRegistrationMustBeConfirmed(UserRegistrationStatus anUserRegistrationStatus) {\n        this.userRegistrationStatus = anUserRegistrationStatus;\n    }\n\n    @Override\n    public Boolean isRuleComplied() {\n        return userRegistrationStatus.equals(UserRegistrationStatus.Confirmed);\n    }\n\n    @Override\n    public String message() {\n        return \"User registration is not confirmed yet.\";\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/registration/rules/UserRegistrationMustBeUnique.java",
    "content": "package com.tomo.mcauthentication.domain.registration.rules;\n\nimport com.tomo.ddd.domain.BusinessRule;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationRepository;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationStatus;\n\npublic class UserRegistrationMustBeUnique implements BusinessRule {\n\n    private UserRegistrationRepository repository;\n    private String email;\n\n    public UserRegistrationMustBeUnique(UserRegistrationRepository usersCounter, String email) {\n        this.repository = usersCounter;\n        this.email = email;\n    }\n\n    @Override\n    public Boolean isRuleComplied() {\n        return repository.countByEmailAndStatus(email, UserRegistrationStatus.Confirmed) < 1;\n    }\n\n    @Override\n    public String message() {\n        return \"User login must be unique\";\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/session/JwtTokenProvider.java",
    "content": "package com.tomo.mcauthentication.domain.session;\n\nimport com.tomo.mcauthentication.domain.session.Session.TokenType;\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserId;\nimport com.tomo.mcauthentication.infrastructure.springboot.configuration.AppProperties;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.stereotype.Service;\n\nimport javax.crypto.SecretKey;\nimport java.util.Date;\n\nimport io.jsonwebtoken.Claims;\nimport io.jsonwebtoken.ExpiredJwtException;\nimport io.jsonwebtoken.Jwts;\nimport io.jsonwebtoken.MalformedJwtException;\nimport io.jsonwebtoken.UnsupportedJwtException;\nimport io.jsonwebtoken.io.Decoders;\nimport io.jsonwebtoken.security.Keys;\n\n@Service\n@Qualifier(\"jwtTokenProvider\")\npublic class JwtTokenProvider implements TokenProvider {\n\n    private static final Logger logger = LoggerFactory.getLogger(TokenProvider.class);\n\n    private AppProperties appProperties;\n\n    public JwtTokenProvider(AppProperties appProperties) {\n        this.appProperties = appProperties;\n    }\n\n    @Override public String createToken(User user) {\n        Date now = new Date();\n        Date expiryDate = new Date(now.getTime() + appProperties.getAuth().getTokenExpirationMsec());\n\n        return Jwts.builder()\n                .setSubject(user.getUserId().id().toString())\n                .setIssuedAt(new Date())\n                .setExpiration(expiryDate)\n                .signWith(secretKey())\n                .compact();\n    }\n\n    @Override\n    public UserId getUserIdFromToken(String anAuthToken) {\n        Claims claims = Jwts.parserBuilder()\n                .setSigningKey(secretKey())\n                .build()\n                .parseClaimsJws(anAuthToken)\n                .getBody();\n\n        return new UserId(claims.getSubject());\n    }\n\n    @Override\n    public boolean validateToken(String anAuthToken) {\n        try {\n            Jwts.parserBuilder()\n                    .setSigningKey(secretKey())\n                    .build()\n                    .parseClaimsJws(anAuthToken);\n            return true;\n        } catch (SecurityException ex) {\n            logger.error(\"Invalid JWT signature\");\n        } catch (MalformedJwtException ex) {\n            logger.error(\"Invalid JWT token\");\n        } catch (ExpiredJwtException ex) {\n            logger.error(\"Expired JWT token\");\n            throw ex;\n        } catch (UnsupportedJwtException ex) {\n            logger.error(\"Unsupported JWT token\");\n        } catch (IllegalArgumentException ex) {\n            logger.error(\"JWT claims string is empty.\");\n        }\n        return false;\n    }\n\n\n    @Override\n    public TokenType getTokenType() {\n        return TokenType.CLIENT_SECRET_JWT;\n    }\n\n    @Override public String createRefreshToken(User user) {\n        return null;\n    }\n\n    private SecretKey secretKey() {\n        return Keys.hmacShaKeyFor(Decoders.BASE64.decode(appProperties.getAuth().getTokenSecret()));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/session/Session.java",
    "content": "package com.tomo.mcauthentication.domain.session;\n\nimport com.tomo.ddd.domain.DomainEventPublisher;\nimport com.tomo.ddd.domain.RootEntity;\nimport com.tomo.mcauthentication.domain.DomainRegistry;\nimport com.tomo.mcauthentication.domain.session.events.SessionCreated;\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserId;\n\nimport javax.persistence.AttributeOverride;\nimport javax.persistence.Column;\nimport javax.persistence.Embedded;\nimport javax.persistence.EmbeddedId;\nimport javax.persistence.Entity;\nimport javax.persistence.EnumType;\nimport javax.persistence.Enumerated;\nimport java.time.LocalDateTime;\nimport java.time.temporal.ChronoField;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Entity\n@NoArgsConstructor\n@Getter\n@Setter\npublic class Session extends RootEntity {\n\n    public static Long EXPIRATION_MSEC = 15000L;\n\n    public enum TokenType {\n        CLIENT_SECRET_JWT,\n        PRIVATE_KEY_JWT,\n        BASIC,\n        API_KEY\n    }\n\n    @EmbeddedId\n    private SessionId sessionId;\n    private String accessToken;\n    private LocalDateTime expirationDate;\n\n    @Enumerated(EnumType.STRING)\n    private TokenType tokenType;\n    private String refreshToken;\n    private String userAgent;\n    private String ipAddress;\n    private LocalDateTime lastActivity;\n\n    @Embedded\n    @AttributeOverride(name=\"id\", column = @Column(name=\"user_id\"))\n    private UserId userId;\n\n    public Session(SessionId sessionId, User user, TokenProvider tokenProvider, Boolean rememberMe, String userAgent, String ipAddress)\n    {\n        this.sessionId = sessionId;\n        this.ipAddress = ipAddress;\n        this.userAgent = userAgent;\n        this.tokenType = tokenProvider.getTokenType();\n        this.userId = user.getUserId();\n        this.expirationDate = LocalDateTime.now().plus(EXPIRATION_MSEC, ChronoField.MILLI_OF_DAY.getBaseUnit());\n        this.accessToken = tokenProvider.createToken(user);\n\n        if (Boolean.TRUE.equals(rememberMe)) {\n            this.refreshToken = tokenProvider.createRefreshToken(user);\n        }\n\n        DomainEventPublisher.instance().publish(\n                new SessionCreated(this.getSessionId(), this.getUserId())\n        );\n    }\n\n    public boolean isExpired() {\n        return !expirationDate.isAfter(LocalDateTime.now());\n    }\n\n    private void protectedAccessToken(String anToken) {\n        this.assertArgumentNotEmpty(anToken, \"Access token cannot be empty.\");\n        this.setAccessToken(DomainRegistry.encryptionService().encryptedValue(anToken));\n    }\n\n    private void protectedRefreshToken(String anToken) {\n        this.assertArgumentNotEmpty(anToken, \"Refresh token cannot be empty.\");\n        this.setRefreshToken(DomainRegistry.encryptionService().encryptedValue(anToken));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/session/SessionAuthenticationService.java",
    "content": "package com.tomo.mcauthentication.domain.session;\n\nimport com.tomo.ddd.domain.BusinessRuleValidator;\nimport com.tomo.mcauthentication.domain.session.rule.SessionCannotBeExpiredWhenRefreshTokenIsMissing;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\n\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.stereotype.Service;\n\nimport java.time.LocalDateTime;\n\n@Service\npublic class SessionAuthenticationService extends BusinessRuleValidator {\n\n    TokenProvider tokenProvider;\n    SessionRepository sessionRepository;\n    UserRepository userRepository;\n\n    public SessionAuthenticationService(\n            TokenProvider tokenProvider,\n            SessionRepository sessionRepository,\n            @Qualifier(\"userRepositoryJpaAdapter\") UserRepository userRepository) {\n        this.tokenProvider = tokenProvider;\n        this.sessionRepository = sessionRepository;\n        this.userRepository = userRepository;\n    }\n\n    public Session authenticate(String anAccessToken) {\n        assertArgumentNotEmpty(anAccessToken, \"Session token cannot be empty.\");\n\n        Session session = sessionRepository.findByAccessToken(anAccessToken);\n        if (session == null) {\n            throw new IllegalStateException(String.format(\"Session with access code %s doesn't exist.\", anAccessToken));\n        }\n\n        checkRule(new SessionCannotBeExpiredWhenRefreshTokenIsMissing(session));\n\n        if (session.isExpired()) {\n            return new Session(\n                    sessionRepository.nextIdentity(),\n                    userRepository.findById(session.getUserId()),\n                    tokenProvider,\n                    true,\n                    session.getUserAgent(),\n                    session.getIpAddress());\n        }\n\n        session.setLastActivity(LocalDateTime.now());\n        return session;\n    }\n\n    public Session logout(String anAccessToken) {\n        assertArgumentNotEmpty(anAccessToken, \"Session token cannot be empty.\");\n\n        Session session = sessionRepository.findByAccessToken(anAccessToken);\n        if (session == null) {\n            throw new IllegalStateException(String.format(\"Session with access code %s doesn't exist.\", anAccessToken));\n        }\n\n        session.setExpirationDate(LocalDateTime.now());\n        session.setRefreshToken(null);\n\n        return sessionRepository.save(session);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/session/SessionId.java",
    "content": "package com.tomo.mcauthentication.domain.session;\n\nimport com.tomo.ddd.domain.AbstractId;\n\nimport javax.persistence.Embeddable;\nimport java.util.UUID;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Embeddable\n@Getter\n@Setter\n@NoArgsConstructor\npublic class SessionId extends AbstractId {\n\n    public SessionId(UUID id) {\n        super(id);\n    }\n\n    @Override\n    protected int hashOddValue() {\n        return 5785;\n    }\n\n    @Override\n    protected int hashPrimeValue() {\n        return 31;\n    }\n}\n\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/session/SessionRepository.java",
    "content": "package com.tomo.mcauthentication.domain.session;\n\nimport com.tomo.ddd.domain.BaseRepository;\nimport com.tomo.mcauthentication.domain.users.UserId;\n\nimport java.util.List;\n\npublic interface SessionRepository extends BaseRepository<Session, SessionId> {\n    SessionId nextIdentity();\n    List<Session> findByUserId(UserId userId);\n    Session findByAccessToken(String anAccessToken);\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/session/TokenProvider.java",
    "content": "package com.tomo.mcauthentication.domain.session;\n\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserId;\n\npublic interface TokenProvider {\n    String createToken(User user);\n    String createRefreshToken(User user);\n    UserId getUserIdFromToken(String anAuthToken);\n    boolean validateToken(String anAuthToken);\n    Session.TokenType getTokenType();\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/session/events/SessionCreated.java",
    "content": "package com.tomo.mcauthentication.domain.session.events;\n\nimport com.tomo.ddd.domain.BaseDomainEvent;\nimport com.tomo.mcauthentication.domain.session.SessionId;\nimport com.tomo.mcauthentication.domain.users.UserId;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class SessionCreated extends BaseDomainEvent  {\n    private SessionId sessionId;\n    private UserId userId;\n\n    public SessionCreated(SessionId sessionId, UserId userId) {\n        this.sessionId = sessionId;\n        this.userId = userId;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/session/rule/SessionCannotBeExpiredWhenRefreshTokenIsMissing.java",
    "content": "package com.tomo.mcauthentication.domain.session.rule;\n\nimport com.tomo.ddd.domain.BusinessRule;\nimport com.tomo.mcauthentication.domain.session.Session;\n\npublic class SessionCannotBeExpiredWhenRefreshTokenIsMissing implements BusinessRule {\n\n    Session session;\n\n    public SessionCannotBeExpiredWhenRefreshTokenIsMissing(Session session) {\n        this.session = session;\n    }\n\n    @Override\n    public Boolean isRuleComplied() {\n        return (!session.isExpired()) || (session.isExpired() && session.getRefreshToken() != null);\n    }\n\n    @Override\n    public String message() {\n        return String.format(\"Session token is expired and refresh token is missing.\");\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/users/EmailLogin.java",
    "content": "package com.tomo.mcauthentication.domain.users;\n\npublic class EmailLogin {\n    User user;\n    String username;\n    String password;\n\n\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/users/User.java",
    "content": "package com.tomo.mcauthentication.domain.users;\n\nimport com.tomo.ddd.domain.ConcurrencySafeEntity;\nimport com.tomo.ddd.domain.DomainEvent;\nimport com.tomo.ddd.domain.DomainEventPublisher;\nimport com.tomo.mcauthentication.domain.DomainRegistry;\nimport com.tomo.mcauthentication.domain.users.events.UserCreated;\nimport com.tomo.mcauthentication.domain.users.events.UserNameChanged;\n\nimport javax.persistence.EmbeddedId;\nimport javax.persistence.Entity;\nimport javax.persistence.EnumType;\nimport javax.persistence.Enumerated;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\n\n@Entity(name = \"mcuser\")\n@Getter\n@NoArgsConstructor\npublic class User extends ConcurrencySafeEntity {\n\n    public enum AuthProvider {\n        EMAIL,\n        FACEBOOK,\n        GOOGLE\n    }\n\n    @EmbeddedId\n    UserId userId;\n    String firstName;\n    String lastName;\n    String email;\n\n    @Enumerated(EnumType.STRING)\n    AuthProvider provider;\n\n    public User(\n            UserId anId,\n            String aFirstName,\n            String aLastName,\n            String anEmail,\n            AuthProvider aProvider) {\n        this.checkRule(DomainRegistry.userEmailMustBeUnique(anEmail));\n        this.userId = anId;\n        this.firstName = aFirstName;\n        this.lastName = aLastName;\n        this.email = anEmail;\n        this.provider = aProvider;\n\n        this.publish(new UserCreated(\n                this.getUserId(),\n                this.getFirstName(),\n                this.getLastName(),\n                this.getEmail(),\n                this.getProvider()\n        ));\n    }\n\n    public void updateDetails(String aFirstName, String aLastName) {\n        this.setFirstName(aFirstName);\n        this.setLastName(aLastName);\n\n        publish(new UserNameChanged(\n                this.getEmail(),\n                this.getFirstName(),\n                this.getLastName()));\n    }\n\n    public void setLastName(String aLastName) {\n        assertArgumentNotEmpty(lastName, \"Last name cannot be empty.\");\n        this.lastName = aLastName;\n    }\n\n    public void setFirstName(String aFirstName) {\n        assertArgumentNotEmpty(aFirstName, \"First name cannot be empty.\");\n        this.firstName = aFirstName;\n    }\n\n    private void publish(DomainEvent event) {\n        DomainEventPublisher.instance().publish(event);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/users/UserId.java",
    "content": "package com.tomo.mcauthentication.domain.users;\n\nimport com.tomo.ddd.domain.AbstractId;\n\nimport javax.persistence.Embeddable;\n\nimport java.util.UUID;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Embeddable\n@Getter\n@Setter\n@NoArgsConstructor\npublic class UserId extends AbstractId {\n\n    public UserId(UUID id) {\n        super(id);\n    }\n\n    public UserId(String id) {\n        super(UUID.fromString(id));\n    }\n\n    @Override\n    protected int hashOddValue() {\n        return 83811;\n    }\n\n    @Override\n    protected int hashPrimeValue() {\n        return 263;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/users/UserRepository.java",
    "content": "package com.tomo.mcauthentication.domain.users;\n\nimport com.tomo.ddd.domain.BaseRepository;\n\npublic interface UserRepository extends BaseRepository<User, UserId> {\n    UserId nextIdentity();\n    User findByEmail(String anEmail);\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/users/events/UserCreated.java",
    "content": "package com.tomo.mcauthentication.domain.users.events;\n\nimport com.tomo.ddd.domain.BaseDomainEvent;\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserId;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class UserCreated extends BaseDomainEvent  {\n    UserId userId;\n    String firstName;\n    String lastName;\n    String email;\n    User.AuthProvider provider;\n\n    public UserCreated(UserId userId, String firstName, String lastName, String email, User.AuthProvider provider) {\n        this.userId = userId;\n        this.firstName = firstName;\n        this.lastName = lastName;\n        this.email = email;\n        this.provider = provider;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/users/events/UserNameChanged.java",
    "content": "package com.tomo.mcauthentication.domain.users.events;\n\nimport com.tomo.ddd.domain.BaseDomainEvent;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class UserNameChanged extends BaseDomainEvent  {\n    String email;\n    String firstName;\n    String lastName;\n\n    public UserNameChanged(String email, String firstName, String lastName) {\n        this.email = email;\n        this.firstName = firstName;\n        this.lastName = lastName;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/domain/users/rules/UserEmailMustBeUnique.java",
    "content": "package com.tomo.mcauthentication.domain.users.rules;\n\nimport com.tomo.ddd.domain.BusinessRule;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\n\npublic class UserEmailMustBeUnique implements BusinessRule {\n\n    UserRepository userRespository;\n    String email;\n\n    public UserEmailMustBeUnique(UserRepository userRespository, String email) {\n        this.userRespository = userRespository;\n        this.email = email;\n    }\n\n    @Override\n    public Boolean isRuleComplied() {\n        return userRespository.findByEmail(this.email) == null;\n    }\n\n    @Override\n    public String message() {\n        return \"User with this email already exists.\";\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/McAuthenticationModuleExecutor.java",
    "content": "package com.tomo.mcauthentication.infrastructure;\n\nimport com.tomo.mcauthentication.application.configuration.CommandHandler;\nimport com.tomo.mcauthentication.application.configuration.QueryHandler;\nimport com.tomo.mcauthentication.application.contracts.Command;\nimport com.tomo.mcauthentication.application.contracts.McAuthenticationModule;\nimport com.tomo.mcauthentication.application.contracts.Query;\nimport com.tomo.mcauthentication.application.contracts.Response;\nimport com.tomo.mcauthentication.infrastructure.processing.builder.CommandHandlerPipelineBuilder;\nimport com.tomo.mcauthentication.infrastructure.processing.builder.QueryHandlerPipelineBuilder;\n\nimport org.springframework.stereotype.Component;\n\n@Component\npublic class McAuthenticationModuleExecutor implements McAuthenticationModule {\n\n    CommandHandlerPipelineBuilder commandHandlerPipelineBuilder;\n    QueryHandlerPipelineBuilder queryHandlerPipelineBuilder;\n\n\n    public McAuthenticationModuleExecutor(\n            CommandHandlerPipelineBuilder commandHandlerPipelineBuilder,\n            QueryHandlerPipelineBuilder queryHandlerPipelineBuilder) {\n        this.commandHandlerPipelineBuilder = commandHandlerPipelineBuilder;\n        this.queryHandlerPipelineBuilder = queryHandlerPipelineBuilder;\n    }\n\n    @Override\n    public Response executeCommand(Command command) {\n        CommandHandler commandHandler = commandHandlerPipelineBuilder\n                .with(command)\n                .build();\n\n        return commandHandler.handle(command);\n    }\n\n    @Override\n    public Response executeQuery(Query query) {\n        QueryHandler queryHandler = queryHandlerPipelineBuilder\n                .with(query)\n                .build();\n\n        return queryHandler.handle(query);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/http/oauth2/AbstractOAuth2Authentication.java",
    "content": "package com.tomo.mcauthentication.infrastructure.http.oauth2;\n\nimport com.tomo.mcauthentication.domain.oauth2.OAuth2Principal;\nimport com.tomo.mcauthentication.infrastructure.http.oauth2.user.OAuth2UserInfo;\nimport com.tomo.mcauthentication.infrastructure.http.oauth2.user.OAuth2UserInfoFactory;\n\nimport org.springframework.security.oauth2.client.registration.ClientRegistration;\nimport org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;\nimport org.springframework.security.oauth2.core.OAuth2AccessToken;\nimport org.springframework.security.oauth2.core.user.OAuth2User;\n\nimport java.time.Instant;\n\npublic abstract class AbstractOAuth2Authentication {\n\n    ClientRegistration clientRegistration;\n    CustomOAuth2UserService customOAuth2UserService;\n\n    public AbstractOAuth2Authentication(ClientRegistration clientRegistration,\n            CustomOAuth2UserService customOAuth2UserService) {\n        this.clientRegistration = clientRegistration;\n        this.customOAuth2UserService = customOAuth2UserService;\n    }\n\n    protected OAuth2Principal authenticateUser(String anAccessCode) {\n        OAuth2UserRequest oAuth2UserRequest = new OAuth2UserRequest(clientRegistration, new OAuth2AccessToken(\n                OAuth2AccessToken.TokenType.BEARER,\n                anAccessCode,\n                Instant.now(), Instant.now().plusSeconds(10000L)));\n        OAuth2User oAuth2User = customOAuth2UserService.loadUser(oAuth2UserRequest);\n        OAuth2UserInfo userInfo = OAuth2UserInfoFactory\n                .getOAuth2UserInfo(clientRegistration.getRegistrationId(), oAuth2User.getAttributes());\n        return new OAuth2Principal(\n                userInfo.getId(),\n                userInfo.getEmail(),\n                userInfo.getName(),\n                userInfo.getName(),\n                userInfo.getImageUrl(),\n                clientRegistration.getRegistrationId());\n\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/http/oauth2/CustomOAuth2UserService.java",
    "content": "package com.tomo.mcauthentication.infrastructure.http.oauth2;\n\nimport org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;\nimport org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;\nimport org.springframework.security.oauth2.core.OAuth2AuthenticationException;\nimport org.springframework.security.oauth2.core.user.OAuth2User;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class CustomOAuth2UserService extends DefaultOAuth2UserService {\n\n    public OAuth2User loadUser(OAuth2UserRequest oAuth2UserRequest) throws OAuth2AuthenticationException {\n        return super.loadUser(oAuth2UserRequest);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/http/oauth2/FacebookOAuth2Authentication.java",
    "content": "package com.tomo.mcauthentication.infrastructure.http.oauth2;\n\nimport com.tomo.mcauthentication.domain.oauth2.OAuth2Authentication;\nimport com.tomo.mcauthentication.domain.oauth2.OAuth2Principal;\nimport com.tomo.mcauthentication.infrastructure.http.oauth2.user.FacebookOAuth2UserInfo;\nimport com.tomo.mcauthentication.infrastructure.http.oauth2.user.OAuth2UserInfoFactory;\n\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.security.oauth2.client.registration.ClientRegistration;\nimport org.springframework.security.oauth2.core.user.OAuth2User;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class FacebookOAuth2Authentication extends AbstractOAuth2Authentication implements OAuth2Authentication {\n\n    public FacebookOAuth2Authentication(\n            @Qualifier(\"facebookClientRegistration\") ClientRegistration clientRegistration,\n            CustomOAuth2UserService customOAuth2UserService) {\n        super(clientRegistration, customOAuth2UserService);\n    }\n\n    @Override\n    public OAuth2Principal authenticate(String anAccessCode) {\n        return super.authenticateUser(anAccessCode);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/http/oauth2/GoogleOAuth2Authentication.java",
    "content": "package com.tomo.mcauthentication.infrastructure.http.oauth2;\n\nimport com.tomo.mcauthentication.domain.oauth2.OAuth2Authentication;\nimport com.tomo.mcauthentication.domain.oauth2.OAuth2Principal;\nimport com.tomo.mcauthentication.infrastructure.http.oauth2.user.FacebookOAuth2UserInfo;\nimport com.tomo.mcauthentication.infrastructure.http.oauth2.user.OAuth2UserInfoFactory;\n\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.security.oauth2.client.registration.ClientRegistration;\nimport org.springframework.security.oauth2.core.user.OAuth2User;\nimport org.springframework.stereotype.Service;\n\n@Service\npublic class GoogleOAuth2Authentication extends AbstractOAuth2Authentication implements OAuth2Authentication {\n\n    public GoogleOAuth2Authentication(\n            @Qualifier(\"googleClientRegistration\") ClientRegistration clientRegistration,\n            CustomOAuth2UserService customOAuth2UserService) {\n        super(clientRegistration, customOAuth2UserService);\n    }\n\n    @Override\n    public OAuth2Principal authenticate(String anAccessCode) {\n        return super.authenticateUser(anAccessCode);\n    }\n}\n\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/http/oauth2/user/FacebookOAuth2UserInfo.java",
    "content": "package com.tomo.mcauthentication.infrastructure.http.oauth2.user;\n\nimport java.util.Map;\n\npublic class FacebookOAuth2UserInfo extends OAuth2UserInfo {\n    public FacebookOAuth2UserInfo(Map<String, Object> attributes) {\n        super(attributes);\n    }\n\n    @Override\n    public String getId() {\n        return (String) attributes.get(\"id\");\n    }\n\n    @Override\n    public String getName() {\n        return (String) attributes.get(\"name\");\n    }\n\n    @Override\n    public String getEmail() {\n        return (String) attributes.get(\"email\");\n    }\n\n    @Override\n    public String getImageUrl() {\n        if(attributes.containsKey(\"picture\")) {\n            Map<String, Object> pictureObj = (Map<String, Object>) attributes.get(\"picture\");\n            if(pictureObj.containsKey(\"data\")) {\n                Map<String, Object>  dataObj = (Map<String, Object>) pictureObj.get(\"data\");\n                if(dataObj.containsKey(\"url\")) {\n                    return (String) dataObj.get(\"url\");\n                }\n            }\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/http/oauth2/user/GoogleOAuth2UserInfo.java",
    "content": "package com.tomo.mcauthentication.infrastructure.http.oauth2.user;\n\nimport java.util.Map;\n\npublic class GoogleOAuth2UserInfo extends OAuth2UserInfo {\n\n    public GoogleOAuth2UserInfo(Map<String, Object> attributes) {\n        super(attributes);\n    }\n\n    @Override\n    public String getId() {\n        return (String) attributes.get(\"sub\");\n    }\n\n    @Override\n    public String getName() {\n        return (String) attributes.get(\"name\");\n    }\n\n    @Override\n    public String getEmail() {\n        return (String) attributes.get(\"email\");\n    }\n\n    @Override\n    public String getImageUrl() {\n        return (String) attributes.get(\"picture\");\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/http/oauth2/user/OAuth2UserInfo.java",
    "content": "package com.tomo.mcauthentication.infrastructure.http.oauth2.user;\n\nimport java.util.Map;;\n\npublic abstract class OAuth2UserInfo {\n    protected Map<String, Object> attributes;\n\n    public OAuth2UserInfo(Map<String, Object> attributes) {\n        this.attributes = attributes;\n    }\n\n    public Map<String, Object> getAttributes() {\n        return attributes;\n    }\n\n    public abstract String getId();\n\n    public abstract String getName();\n\n    public abstract String getEmail();\n\n    public abstract String getImageUrl();\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/http/oauth2/user/OAuth2UserInfoFactory.java",
    "content": "package com.tomo.mcauthentication.infrastructure.http.oauth2.user;\n\nimport com.tomo.mcauthentication.domain.users.User;\n\nimport java.util.Map;\n\npublic class OAuth2UserInfoFactory {\n\n    public static OAuth2UserInfo getOAuth2UserInfo(String registrationId, Map<String, Object> attributes) {\n        if(registrationId.equalsIgnoreCase(User.AuthProvider.GOOGLE.toString().toLowerCase())) {\n            return new GoogleOAuth2UserInfo(attributes);\n        } else if (registrationId.equalsIgnoreCase(User.AuthProvider.FACEBOOK.toString().toLowerCase())) {\n            return new FacebookOAuth2UserInfo(attributes);\n        } else {\n            throw new IllegalArgumentException(\"Sorry! Login with \" + registrationId + \" is not supported yet.\");\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/persistence/BaseJpaAdapter.java",
    "content": "package com.tomo.mcauthentication.infrastructure.persistence;\n\nimport com.tomo.ddd.domain.BaseRepository;\nimport com.tomo.ddd.infrastructure.persistence.springdata.jpa.McCrudRepository;\n\nimport java.util.List;\nimport java.util.Optional;\n\n//https://github.com/benthurley82/generic-type-resolver-test/blob/main/src/main/java/com/example/test/AbstractFoo.java\npublic class BaseJpaAdapter<T, ID, E extends McCrudRepository> implements BaseRepository<T, ID> {\n\n    protected E jpaRepository;\n\n    public BaseJpaAdapter(E jpaRepository) {\n        this.jpaRepository = jpaRepository;\n    }\n\n    @Override\n    public T save(T entity) {\n        return (T) jpaRepository.save(entity);\n    }\n\n    @Override\n    public T findById(ID id) {\n        Optional<T> entity = jpaRepository.findById(id);\n        return entity.isPresent() ? entity.get() : null;\n    }\n\n    @Override\n    public List<T> findAll() {\n        return jpaRepository.findAll();\n    }\n\n    @Override\n    public void saveAll(List<T> entities) {\n        jpaRepository.saveAll(entities);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/persistence/SessionJpaRepository.java",
    "content": "package com.tomo.mcauthentication.infrastructure.persistence;\n\nimport com.tomo.ddd.infrastructure.persistence.springdata.jpa.McCrudRepository;\nimport com.tomo.mcauthentication.domain.session.Session;\nimport com.tomo.mcauthentication.domain.session.SessionId;\nimport com.tomo.mcauthentication.domain.users.UserId;\n\nimport org.springframework.stereotype.Repository;\n\nimport java.util.List;\n\n@Repository\npublic interface SessionJpaRepository extends McCrudRepository<Session, SessionId> {\n\n    List<Session> findAllByUserId(UserId userId);\n\n    Session findSessionByAccessToken(String accessToken);\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/persistence/SessionRepositoryJpaAdapter.java",
    "content": "package com.tomo.mcauthentication.infrastructure.persistence;\n\nimport com.tomo.mcauthentication.domain.session.Session;\nimport com.tomo.mcauthentication.domain.session.SessionId;\nimport com.tomo.mcauthentication.domain.session.SessionRepository;\nimport com.tomo.mcauthentication.domain.users.UserId;\n\nimport org.springframework.stereotype.Repository;\n\nimport java.util.List;\nimport java.util.UUID;\n\n@Repository\npublic class SessionRepositoryJpaAdapter extends BaseJpaAdapter<Session, SessionId, SessionJpaRepository> implements SessionRepository {\n\n    public SessionRepositoryJpaAdapter(SessionJpaRepository jpaRepository) {\n        super(jpaRepository);\n    }\n\n    @Override\n    public SessionId nextIdentity() {\n        return new SessionId(UUID.randomUUID());\n    }\n\n    @Override\n    public List<Session> findByUserId(UserId userId) {\n        return jpaRepository.findAllByUserId(userId);\n    }\n\n    @Override\n    public Session findByAccessToken(String anAccessToken) {\n        return jpaRepository.findSessionByAccessToken(anAccessToken);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/persistence/UserJpaRepository.java",
    "content": "package com.tomo.mcauthentication.infrastructure.persistence;\n\nimport com.tomo.ddd.infrastructure.persistence.springdata.jpa.McCrudRepository;\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserId;\n\nimport org.springframework.stereotype.Repository;\n\n@Repository\npublic interface UserJpaRepository extends McCrudRepository<User, UserId> {\n\n    User findUserByEmail(String email);\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/persistence/UserRegistrationJpaRepository.java",
    "content": "package com.tomo.mcauthentication.infrastructure.persistence;\n\nimport com.tomo.ddd.infrastructure.persistence.springdata.jpa.McCrudRepository;\nimport com.tomo.mcauthentication.domain.registration.UserRegistration;\nimport com.tomo.mcauthentication.domain.users.UserId;\n\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.stereotype.Repository;\n\nimport java.util.List;\n\n@Repository\n@Qualifier(\"UserRegistrationJpaRepository\")\npublic interface UserRegistrationJpaRepository extends McCrudRepository <UserRegistration, Long> {\n\n    long countByEmail(String email);\n\n    List<UserRegistration> findAllByEmailIn(List<String> email);\n\n    UserRegistration findUserRegistrationByConfirmationCode(String confirmLink);\n\n    UserRegistration findUserRegistrationByEmail(String email);\n\n    UserRegistration findUserRegistrationByRecoveryCode(String recoveryCode);\n\n    UserRegistration findUserRegistrationByUserId(UserId userId);\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/persistence/UserRegistrationJpaRepositoryAdapter.java",
    "content": "package com.tomo.mcauthentication.infrastructure.persistence;\n\nimport com.tomo.mcauthentication.domain.registration.UserRegistration;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationRepository;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationStatus;\nimport com.tomo.mcauthentication.domain.users.UserId;\n\nimport java.util.List;\n\npublic class UserRegistrationJpaRepositoryAdapter\n        extends BaseJpaAdapter<UserRegistration, Long, UserRegistrationJpaRepository>\n        implements UserRegistrationRepository {\n\n    public UserRegistrationJpaRepositoryAdapter(UserRegistrationJpaRepository jpaRepository) {\n        super(jpaRepository);\n    }\n\n    @Override\n    public long countByEmailAndStatus(String email, UserRegistrationStatus status) {\n        return jpaRepository.countByEmail(email);\n    }\n\n    @Override\n    public List<UserRegistration> findAllByEmail(List<String> emails) {\n        return jpaRepository.findAllByEmailIn(emails);\n    }\n\n    @Override\n    public UserRegistration findByEmail(String anEmail) {\n        return jpaRepository.findUserRegistrationByEmail(anEmail);\n    }\n\n    @Override public UserRegistration findByConfirmationCode(String confirmationCode) {\n        return jpaRepository.findUserRegistrationByConfirmationCode(confirmationCode);\n    }\n\n    @Override\n    public UserRegistration findByRecoveryCode(String aRecoveryCode) {\n        return jpaRepository.findUserRegistrationByRecoveryCode(aRecoveryCode);\n    }\n\n    @Override public UserRegistration findByUserId(UserId anUserId) {\n        return jpaRepository.findUserRegistrationByUserId(anUserId);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/persistence/UserRepositoryJpaAdapter.java",
    "content": "package com.tomo.mcauthentication.infrastructure.persistence;\n\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserId;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\n\nimport org.springframework.stereotype.Component;\n\nimport java.util.UUID;\n\n@Component\npublic class UserRepositoryJpaAdapter extends BaseJpaAdapter<User, UserId, UserJpaRepository> implements UserRepository {\n\n    public UserRepositoryJpaAdapter(UserJpaRepository userJpaRepository) {\n        super(userJpaRepository);\n    }\n\n    @Override\n    public UserId nextIdentity() {\n        return new UserId(UUID.randomUUID());\n    }\n\n    @Override\n    public User findByEmail(String anEmail) {\n        return jpaRepository.findUserByEmail(anEmail);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/processing/ErrorCommandHandlerDecorator.java",
    "content": "package com.tomo.mcauthentication.infrastructure.processing;\n\nimport com.tomo.mcauthentication.application.configuration.AbstractVoidyCommandHandler;\nimport com.tomo.mcauthentication.application.configuration.CommandHandler;\nimport com.tomo.mcauthentication.application.contracts.Command;\n\npublic class ErrorCommandHandlerDecorator<T extends Command> extends AbstractVoidyCommandHandler<T> {\n\n    CommandHandler commandHandler;\n\n    public ErrorCommandHandlerDecorator(CommandHandler commandHandler) {\n        this.commandHandler = commandHandler;\n    }\n\n    @Override\n    protected void abstractHandle(T aCommand) {\n\n        commandHandler.handle(aCommand);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/processing/LoggingCommandHandlerDecorator.java",
    "content": "package com.tomo.mcauthentication.infrastructure.processing;\n\nimport com.tomo.mcauthentication.application.configuration.CommandHandler;\nimport com.tomo.mcauthentication.application.contracts.Command;\nimport com.tomo.mcauthentication.application.contracts.Response;\n\npublic class LoggingCommandHandlerDecorator implements CommandHandler<Command, Response> {\n\n    CommandHandler commandHandler;\n\n    public LoggingCommandHandlerDecorator(CommandHandler commandHandler) {\n        this.commandHandler = commandHandler;\n    }\n\n    @Override\n    public Response handle(Command aCommand) {\n        //todo log\n        return commandHandler.handle(aCommand);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/processing/LoggingQueryHandlerDecorator.java",
    "content": "package com.tomo.mcauthentication.infrastructure.processing;\n\nimport com.tomo.mcauthentication.application.configuration.QueryHandler;\nimport com.tomo.mcauthentication.application.contracts.Query;\nimport com.tomo.mcauthentication.application.contracts.Response;\n\npublic class LoggingQueryHandlerDecorator implements QueryHandler {\n\n    QueryHandler queryHandler;\n\n    public LoggingQueryHandlerDecorator(QueryHandler queryHandler) {\n        this.queryHandler = queryHandler;\n    }\n\n    @Override\n    public Response handle(Query query) {\n        return queryHandler.handle(query);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/processing/PipelineBuilder.java",
    "content": "package com.tomo.mcauthentication.infrastructure.processing;\n\npublic interface PipelineBuilder<C, R> {\n    PipelineBuilder with(C aRequest);\n    R build();\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/processing/builder/AbstractPipelineBuilder.java",
    "content": "package com.tomo.mcauthentication.infrastructure.processing.builder;\n\nimport com.tomo.mcauthentication.application.configuration.RequestHandler;\nimport com.tomo.mcauthentication.application.contracts.Request;\nimport com.tomo.mcauthentication.infrastructure.processing.PipelineBuilder;\n\nimport org.springframework.beans.BeansException;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\n\npublic abstract class AbstractPipelineBuilder<E extends Request, S extends RequestHandler> implements PipelineBuilder<E, S>, ApplicationContextAware {\n\n    protected E request;\n    protected S handler;\n\n    protected ApplicationContext applicationContext;\n\n    @Override\n    public PipelineBuilder with(E aRequest) {\n        this.request = aRequest;\n        this.handler = this.getHandler();\n        return this;\n    }\n\n    @Override\n    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {\n        this.applicationContext = applicationContext;\n    }\n\n    protected S getHandler() {\n        String beanName = this.getHandlerName();\n        return (S) applicationContext.getBean(beanName);\n    }\n\n    protected String getHandlerName() {\n        String fullHandlerName = this.request.getClass().getSimpleName() + \"Handler\";\n        return Character.toLowerCase(fullHandlerName.charAt(0)) + fullHandlerName.substring(1);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/processing/builder/CommandHandlerPipelineBuilder.java",
    "content": "package com.tomo.mcauthentication.infrastructure.processing.builder;\n\nimport com.tomo.mcauthentication.application.configuration.CommandHandler;\nimport com.tomo.mcauthentication.application.contracts.Command;\nimport com.tomo.mcauthentication.infrastructure.processing.LoggingCommandHandlerDecorator;\nimport com.tomo.mcauthentication.infrastructure.processing.PipelineBuilder;\n\npublic class CommandHandlerPipelineBuilder extends AbstractPipelineBuilder<Command, CommandHandler> {\n\n    public CommandHandlerPipelineBuilder() {}\n\n    @Override\n    public CommandHandlerPipelineBuilder with(Command aRequest) {\n        return (CommandHandlerPipelineBuilder) super.with(aRequest);\n    }\n\n    @Override\n    public CommandHandler build() {\n        return new LoggingCommandHandlerDecorator(handler);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/processing/builder/QueryHandlerPipelineBuilder.java",
    "content": "package com.tomo.mcauthentication.infrastructure.processing.builder;\n\nimport com.tomo.mcauthentication.application.configuration.QueryHandler;\nimport com.tomo.mcauthentication.application.contracts.Query;\nimport com.tomo.mcauthentication.infrastructure.processing.LoggingQueryHandlerDecorator;\nimport com.tomo.mcauthentication.infrastructure.processing.PipelineBuilder;\n\npublic class QueryHandlerPipelineBuilder extends AbstractPipelineBuilder<Query, QueryHandler> {\n\n    public QueryHandlerPipelineBuilder() {\n    }\n\n    @Override\n    public QueryHandlerPipelineBuilder with(Query aRequest) {\n        return (QueryHandlerPipelineBuilder) super.with(aRequest);\n    }\n\n    @Override\n    public QueryHandler build() {\n        return new LoggingQueryHandlerDecorator(handler);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/service/MD5EncryptionService.java",
    "content": "package com.tomo.mcauthentication.infrastructure.service;\n\nimport com.tomo.ddd.AssertionConcern;\nimport com.tomo.mcauthentication.domain.EncryptionService;\n\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.stereotype.Service;\n\nimport java.math.BigInteger;\nimport java.security.MessageDigest;\n\n@Service\n@Qualifier(\"MD5EncryptionService\")\npublic class MD5EncryptionService extends AssertionConcern implements EncryptionService {\n\n    public MD5EncryptionService() {\n        super();\n    }\n\n    @Override\n    public String encryptedValue(String aPlainTextValue) {\n        this.assertArgumentNotEmpty(\n                aPlainTextValue,\n                \"Plain text value to encrypt must be provided.\");\n\n        String encryptedValue = null;\n\n        try {\n\n            MessageDigest messageDigest = MessageDigest.getInstance(\"MD5\");\n\n            messageDigest.update(aPlainTextValue.getBytes(\"UTF-8\"));\n\n            BigInteger bigInt = new BigInteger(1, messageDigest.digest());\n\n            encryptedValue = bigInt.toString(16);\n\n        } catch (Exception e) {\n            throw new IllegalStateException(e);\n        }\n\n        return encryptedValue;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/configuration/AppConfig.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.configuration;\n\nimport com.tomo.mcauthentication.application.contracts.McAuthenticationModule;\nimport com.tomo.ddd.email.EmailSender;\nimport com.tomo.ddd.event.EventStore;\nimport com.tomo.ddd.infrastructure.persistence.springdata.jpa.EventStoreJpaRepositoryAdapter;\nimport com.tomo.ddd.infrastructure.persistence.springdata.jpa.StoredEventJpaRepository;\nimport com.tomo.ddd.port.adapter.message.email.MailGunMessageSender;\nimport com.tomo.mcauthentication.domain.oauth2.OAuth2Service;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationRepository;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\nimport com.tomo.mcauthentication.infrastructure.McAuthenticationModuleExecutor;\nimport com.tomo.mcauthentication.infrastructure.http.oauth2.FacebookOAuth2Authentication;\nimport com.tomo.mcauthentication.infrastructure.http.oauth2.GoogleOAuth2Authentication;\nimport com.tomo.mcauthentication.infrastructure.persistence.UserJpaRepository;\nimport com.tomo.mcauthentication.infrastructure.persistence.UserRegistrationJpaRepository;\nimport com.tomo.mcauthentication.infrastructure.persistence.UserRegistrationJpaRepositoryAdapter;\nimport com.tomo.mcauthentication.infrastructure.persistence.UserRepositoryJpaAdapter;\nimport com.tomo.mcauthentication.infrastructure.processing.builder.CommandHandlerPipelineBuilder;\nimport com.tomo.mcauthentication.infrastructure.processing.builder.QueryHandlerPipelineBuilder;\nimport com.tomo.mcauthentication.infrastructure.springboot.filter.TokenAuthenticationFilter;\n\nimport org.modelmapper.ModelMapper;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Qualifier;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.env.Environment;\nimport org.springframework.data.jpa.repository.config.EnableJpaRepositories;\nimport org.springframework.security.config.oauth2.client.CommonOAuth2Provider;\nimport org.springframework.security.oauth2.client.registration.ClientRegistration;\n\n@Configuration\n@EnableJpaRepositories({\n        \"com.tomo.ddd.infrastructure.persistence.springdata.jpa\",\n        \"com.tomo.mcauthentication.infrastructure.persistence\"\n})\npublic class AppConfig {\n\n    @Autowired\n    UserRegistrationJpaRepository userRegistrationJpaRepository;\n\n    @Autowired\n    UserJpaRepository userJpaRepository;\n\n    @Autowired\n    private Environment env;\n\n    @Autowired\n    AppProperties appProperties;\n\n    @Autowired\n    StoredEventJpaRepository storedEventJpaRepository;\n\n    @Bean\n    EventStore eventStore() {\n        return new EventStoreJpaRepositoryAdapter(storedEventJpaRepository);\n    }\n\n    @Bean\n    String recoveryLink() {\n        return appProperties.getGui().getRecoveryRoute();\n    }\n\n    @Bean\n    String confirmationLink() {\n        return appProperties.getGui().getConfirmationRoute();\n    }\n\n    @Bean\n    net.sargue.mailgun.Configuration mailGunConfiguration() {\n        MessageProperties.Email.MailGun mailGun = appProperties.getMessage().getEmail().getMailGun();\n        net.sargue.mailgun.Configuration configuration = new net.sargue.mailgun.Configuration()\n                .domain(mailGun.getDomains())\n                .apiUrl(mailGun.getApiUrl())\n                .apiKey(mailGun.getApiKey())\n                .from(mailGun.getFrom().getName(), mailGun.getFrom().getEmail());\n\n        return configuration;\n    }\n\n    @Bean\n    EmailSender emailMessageSender(net.sargue.mailgun.Configuration mailGunConfiguration) {\n        return new MailGunMessageSender(mailGunConfiguration);\n    }\n\n    @Bean\n    public ModelMapper modelMapper() {\n        return new ModelMapper();\n    }\n\n    @Bean\n    public TokenAuthenticationFilter tokenAuthenticationFilter() {\n        return new TokenAuthenticationFilter();\n    }\n\n    @Bean\n    McAuthenticationModule authenticationModule(CommandHandlerPipelineBuilder commandHandlerPipelineBuilder,\n            QueryHandlerPipelineBuilder queryHandlerPipelineBuilder) {\n        return new McAuthenticationModuleExecutor(commandHandlerPipelineBuilder, queryHandlerPipelineBuilder);\n    }\n\n    @Bean\n    CommandHandlerPipelineBuilder commandHandlerPipelineBuilder() {\n        return new CommandHandlerPipelineBuilder();\n    }\n\n    @Bean\n    QueryHandlerPipelineBuilder queryHandlerPipelineBuilder() {\n        return new QueryHandlerPipelineBuilder();\n    }\n\n    @Bean\n    UserRegistrationRepository userRegistrationRepository(){\n        return new UserRegistrationJpaRepositoryAdapter(userRegistrationJpaRepository);\n    }\n\n    @Bean\n    UserRepository userRepository() {\n        return new UserRepositoryJpaAdapter(userJpaRepository);\n    }\n\n    @Bean\n    @Qualifier(\"facebookClientRegistration\")\n    ClientRegistration facebookClientRegistration() {\n        String clientRootProperty = \"spring.security.oauth2.client.registration.facebook\";\n        String clientId = env.getProperty(clientRootProperty + \".client-id\");\n        String clientSecret = env.getProperty(clientRootProperty + \".client-secret\");\n        return CommonOAuth2Provider.FACEBOOK.getBuilder(\"facebook\")\n                .clientId(clientId).clientSecret(clientSecret).build();\n    }\n\n    @Bean\n    @Qualifier(\"googleClientRegistration\")\n    ClientRegistration googleClientRegistration() {\n        String clientRootProperty = \"spring.security.oauth2.client.registration.facebook\";\n        String clientId = env.getProperty(clientRootProperty + \".client-id\");\n        String clientSecret = env.getProperty(clientRootProperty + \".client-secret\");\n        return CommonOAuth2Provider.FACEBOOK.getBuilder(\"facebook\")\n                .clientId(clientId).clientSecret(clientSecret).build();\n    }\n\n    @Bean\n    @Qualifier(\"facebookOAuth2Service\")\n    OAuth2Service facebookOAuth2Service(\n            FacebookOAuth2Authentication facebookOAuth2Authentication,\n            UserRepository userRepository) {\n        return new OAuth2Service(facebookOAuth2Authentication, userRepository);\n    }\n\n    @Bean\n    @Qualifier(\"googleOAuth2Service\")\n    OAuth2Service googleOAuth2Service(\n            GoogleOAuth2Authentication googleOAuth2Authentication,\n            UserRepository userRepository) {\n        return new OAuth2Service(googleOAuth2Authentication, userRepository);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/configuration/AppProperties.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.configuration;\n\nimport org.springframework.boot.context.properties.ConfigurationProperties;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n@ConfigurationProperties(prefix = \"app\")\npublic class AppProperties {\n    private final Auth auth = new Auth();\n    private final OAuth2 oauth2 = new OAuth2();\n    private final MessageProperties message = new MessageProperties();\n    private String baseUrl;\n    private final GUIProperties gui = new GUIProperties();\n\n    public static class Auth {\n        private String tokenSecret;\n        private String sessionAuthTokenName;\n        private long tokenExpirationMsec;\n\n        public String getTokenSecret() {\n            return tokenSecret;\n        }\n\n        public void setTokenSecret(String tokenSecret) {\n            this.tokenSecret = tokenSecret;\n        }\n\n        public long getTokenExpirationMsec() {\n            return tokenExpirationMsec;\n        }\n\n        public void setTokenExpirationMsec(long tokenExpirationMsec) {\n            this.tokenExpirationMsec = tokenExpirationMsec;\n        }\n\n        public String getSessionAuthTokenName() {\n            return sessionAuthTokenName;\n        }\n\n        public void setSessionAuthTokenName(String sessionAuthTokenName) {\n            this.sessionAuthTokenName = sessionAuthTokenName;\n        }\n    }\n\n    public static final class OAuth2 {\n        private List<String> authorizedRedirectUris = new ArrayList<>();\n\n        public List<String> getAuthorizedRedirectUris() {\n            return authorizedRedirectUris;\n        }\n\n        public OAuth2 authorizedRedirectUris(List<String> authorizedRedirectUris) {\n            this.authorizedRedirectUris = authorizedRedirectUris;\n            return this;\n        }\n    }\n\n    public Auth getAuth() {\n        return auth;\n    }\n\n    public OAuth2 getOauth2() {\n        return oauth2;\n    }\n\n    public MessageProperties getMessage() {\n        return message;\n    }\n\n    public GUIProperties getGui() {\n        return gui;\n    }\n\n    public String getBaseUrl() {\n        return baseUrl;\n    }\n\n    public void setBaseUrl(String baseUrl) {\n        this.baseUrl = baseUrl;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/configuration/GUIProperties.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.configuration;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class GUIProperties {\n    String baseUrl;\n    String recoveryRoute;\n    String confirmationRoute;\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/configuration/MessageProperties.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.configuration;\n\nimport lombok.Getter;\nimport lombok.NoArgsConstructor;\nimport lombok.Setter;\n\n@Getter\n@Setter\n@NoArgsConstructor\npublic class MessageProperties {\n\n    private Email email = new Email();\n\n    @Getter\n    @Setter\n    @NoArgsConstructor\n    public static class Email {\n        MailGun mailGun = new MailGun();\n        String fakeEmail = \"tomo.landeka02@gmail.com\";\n\n        @Getter\n        @Setter\n        @NoArgsConstructor\n        public static class MailGun {\n            String domains;\n            String apiUrl;\n            String apiKey;\n            From from;\n\n            @Getter\n            @Setter\n            @NoArgsConstructor\n            public static class From {\n                String name;\n                String email;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/configuration/SecurityConfig.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.configuration;\n\nimport com.tomo.mcauthentication.infrastructure.springboot.security.OAuth2AuthenticationFailureHandler;\nimport com.tomo.mcauthentication.infrastructure.springboot.security.OAuth2AuthenticationSuccessHandler;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\nimport org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;\nimport org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;\nimport org.springframework.security.config.http.SessionCreationPolicy;\n\n@Configuration\n@EnableWebSecurity\n@EnableGlobalMethodSecurity(\n        securedEnabled = true,\n        jsr250Enabled = true,\n        prePostEnabled = true\n)\npublic class SecurityConfig extends WebSecurityConfigurerAdapter {\n\n    @Autowired\n    private OAuth2AuthenticationSuccessHandler oAuth2AuthenticationSuccessHandler;\n\n    @Autowired\n    private OAuth2AuthenticationFailureHandler oAuth2AuthenticationFailureHandler;\n\n    @Override\n    protected void configure(HttpSecurity http) throws Exception {\n        http.csrf().disable()\n                .authorizeRequests()\n                .anyRequest().permitAll()\n                .and()\n                .sessionManagement()\n                .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)\n                .and()\n                .oauth2Login()\n                .successHandler(oAuth2AuthenticationSuccessHandler)\n                .failureHandler(oAuth2AuthenticationFailureHandler);\n    }\n\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/configuration/SwaggerConfig.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.configuration;\n\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\n\nimport springfox.documentation.builders.PathSelectors;\nimport springfox.documentation.builders.RequestHandlerSelectors;\nimport springfox.documentation.spi.DocumentationType;\nimport springfox.documentation.spring.web.plugins.Docket;\n\n@Configuration\npublic class SwaggerConfig {\n    @Bean\n    public Docket api() {\n        return new Docket(DocumentationType.SWAGGER_2)\n                .select()\n                .apis(RequestHandlerSelectors.any())\n                .paths(PathSelectors.any())\n                .build();\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/configuration/SwaggerUiWebMvcConfigurer.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.configuration;\n\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.StringUtils;\nimport org.springframework.web.servlet.config.annotation.CorsRegistry;\nimport org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;\nimport org.springframework.web.servlet.config.annotation.ViewControllerRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurer;\n\n@Component\npublic class SwaggerUiWebMvcConfigurer implements WebMvcConfigurer {\n    private final String baseUrl;\n\n    public SwaggerUiWebMvcConfigurer(@Value(\"${app.base-url:}\") String baseUrl) {\n        this.baseUrl = baseUrl;\n    }\n\n    @Override\n    public void addResourceHandlers(ResourceHandlerRegistry registry) {\n        String baseUrl = StringUtils.trimTrailingCharacter(this.baseUrl, '/');\n        registry.\n                addResourceHandler(baseUrl + \"/swagger-ui/**\")\n                .addResourceLocations(\"classpath:/META-INF/resources/webjars/springfox-swagger-ui/\")\n                .resourceChain(false);\n    }\n\n    @Override\n    public void addViewControllers(ViewControllerRegistry registry) {\n        registry.addViewController(baseUrl + \"/swagger-ui/\")\n                .setViewName(\"forward:\" + baseUrl + \"/swagger-ui/index.html\");\n    }\n\n    @Override\n    public void addCorsMappings(CorsRegistry registry) {\n        registry\n                .addMapping(\"/api/pet\")\n                .allowedOrigins(\"http://editor.swagger.io\");\n        registry\n                .addMapping(\"/v2/api-docs.*\")\n                .allowedOrigins(\"http://editor.swagger.io\");\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/controller/AbstractController.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.controller;\n\nimport com.tomo.mcauthentication.application.contracts.Command;\nimport com.tomo.mcauthentication.application.contracts.McAuthenticationModule;\nimport com.tomo.mcauthentication.application.contracts.Query;\nimport com.tomo.mcauthentication.application.contracts.Request;\nimport com.tomo.mcauthentication.application.contracts.Response;\nimport com.tomo.mcauthentication.application.contracts.security.Authenticate;\nimport com.tomo.mcauthentication.domain.session.TokenProvider;\nimport com.tomo.mcauthentication.infrastructure.springboot.configuration.AppProperties;\nimport com.tomo.mcauthentication.infrastructure.util.CookieUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.util.StringUtils;\n\nimport javax.servlet.http.HttpServletRequest;\n\npublic abstract class AbstractController {\n\n    @Autowired\n    protected McAuthenticationModule authenticationModule;\n\n    @Autowired\n    protected AppProperties properties;\n\n    @Autowired\n    protected HttpServletRequest request;\n\n    @Autowired\n    protected TokenProvider tokenProvider;\n\n    protected Response executeCommand(Command command) {\n        this.setAuthToken(command);\n        return authenticationModule.executeCommand(command);\n    }\n\n    protected <T extends Response> T executeCommand(Command command, Class<T> tclass) {\n        this.setAuthToken(command);\n        return tclass.cast(authenticationModule.executeCommand(command));\n    }\n\n    protected <T extends Response> T executeQuery(Query query, Class<T> tclass) {\n        this.setAuthToken(query);\n        return tclass.cast(authenticationModule.executeQuery(query));\n    }\n\n    private void setAuthToken(Request request) {\n        if (request instanceof Authenticate) {\n            String jwt = getJwtFromRequest();\n            if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {\n                ((Authenticate) request).setAuthToken(jwt);\n            }\n        }\n    }\n\n    private String getJwtFromRequest() {\n        return CookieUtils.getCookie(request, properties.getAuth().getSessionAuthTokenName())\n                .map(cookie -> CookieUtils.deserialize(cookie, String.class))\n//                .filter(cookie -> StringUtils.hasText(cookie) && cookie.startsWith(\"Bearer \"))\n//                .map(cookie -> cookie.substring(7))\n                .orElse(null);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/controller/AuthenticationController.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.controller;\n\nimport com.tomo.mcauthentication.application.authentication.command.EmailLoginCommand;\nimport com.tomo.mcauthentication.application.authentication.command.FacebookLoginCommand;\nimport com.tomo.mcauthentication.application.authentication.command.GoogleLoginCommand;\nimport com.tomo.mcauthentication.application.authentication.command.LogoutCommand;\nimport com.tomo.mcauthentication.application.authentication.dto.SessionDto;\nimport com.tomo.mcauthentication.application.contracts.Command;\nimport com.tomo.mcauthentication.infrastructure.springboot.controller.RestApiRoutes.AuthRoutes;\nimport com.tomo.mcauthentication.infrastructure.springboot.security.CurrentUser;\nimport com.tomo.mcauthentication.infrastructure.springboot.security.UserAuthPrincipal;\nimport com.tomo.mcauthentication.infrastructure.util.CookieUtils;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.validation.annotation.Validated;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.ResponseStatus;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport javax.servlet.http.HttpServletResponse;\nimport java.util.concurrent.TimeUnit;\n\n@RestController\n@RequestMapping(path = \"/\")\npublic class AuthenticationController extends AbstractController {\n\n    @Autowired\n    private HttpServletResponse response;\n\n    @RequestMapping(method = RequestMethod.POST, path = AuthRoutes.FORM_LOGIN)\n    @ResponseStatus(HttpStatus.CREATED)\n    public ResponseEntity formLogin(@CurrentUser UserAuthPrincipal user,\n            @RequestBody @Validated EmailLoginCommand command) {\n        return ResponseEntity.ok(this.executeCommand(command, user));\n    }\n\n    @RequestMapping(method = RequestMethod.POST, path = AuthRoutes.FACEBOOK_LOGIN)\n    @ResponseStatus(HttpStatus.CREATED)\n    public ResponseEntity facebookLogin(@CurrentUser UserAuthPrincipal user,\n            @RequestBody @Validated FacebookLoginCommand command){\n        return ResponseEntity.ok(this.executeCommand(command, user));\n    }\n\n    @RequestMapping(method = RequestMethod.POST, path = AuthRoutes.GOOGLE_LOGIN)\n    @ResponseStatus(HttpStatus.CREATED)\n    public ResponseEntity googleLogin(@CurrentUser UserAuthPrincipal user,\n            @RequestBody @Validated GoogleLoginCommand command) {\n        return ResponseEntity.ok(this.executeCommand(command, user));\n    }\n\n    @RequestMapping(method = RequestMethod.PATCH, path = AuthRoutes.LOGOUT)\n    public ResponseEntity logout(@CurrentUser UserAuthPrincipal user,\n            @RequestBody @Validated LogoutCommand command) {\n        if (user == null) {\n            return ResponseEntity.badRequest().body(\"Missing session cookie.\");\n        }\n\n        command.setAuthToken(user.getSession().getAccessToken());\n        authenticationModule.executeCommand(command);\n\n        return ResponseEntity.ok().build();\n    }\n\n    protected SessionDto executeCommand(Command command, UserAuthPrincipal user) {\n        if (user != null) {\n            return user.getSession();\n        }\n\n        SessionDto session = super.executeCommand(command, SessionDto.class);\n        addAccessTokenToCookie(session.getAccessToken());\n\n        return session;\n    }\n\n    private void addAccessTokenToCookie(String accessToken) {\n        CookieUtils.addCookie(\n                response,\n                properties.getAuth().getSessionAuthTokenName(),\n                CookieUtils.serialize(accessToken),\n                (int) TimeUnit.MILLISECONDS.toSeconds(properties.getAuth().getTokenExpirationMsec()));\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/controller/RegistrationController.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.controller;\n\nimport com.tomo.mcauthentication.application.recovery.command.CreatePasswordRecoveryCodeCommand;\nimport com.tomo.mcauthentication.application.recovery.command.UpdatePasswordWithRecoveryCodeCommand;\nimport com.tomo.mcauthentication.application.registration.command.ConfirmUserRegistrationCommand;\nimport com.tomo.mcauthentication.application.registration.command.RegisterNewUserCommand;\nimport com.tomo.mcauthentication.infrastructure.springboot.controller.RestApiRoutes.RegistrationRoutes;\n\nimport org.springframework.http.HttpStatus;\nimport org.springframework.validation.annotation.Validated;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.ResponseStatus;\nimport org.springframework.web.bind.annotation.RestController;\n\n@RestController\n@RequestMapping(path = \"/\")\npublic class RegistrationController extends AbstractController {\n\n    @RequestMapping(method = RequestMethod.POST, path = RegistrationRoutes.FORM_REGISTRATION)\n    @ResponseStatus(HttpStatus.CREATED)\n    public void formRegister(@RequestBody @Validated RegisterNewUserCommand command){\n         this.executeCommand(command);\n    }\n\n    @RequestMapping(method = RequestMethod.POST, path = RegistrationRoutes.CONFIRM_REGISTRATION)\n    @ResponseStatus(HttpStatus.OK)\n    public void formRegisterConfirmation(@RequestParam String confirmationCode){\n        this.executeCommand(new ConfirmUserRegistrationCommand(confirmationCode));\n    }\n\n    @RequestMapping(method = RequestMethod.PATCH, path = RegistrationRoutes.CREATE_PASSWORD_RECOVERY_CODE)\n    @ResponseStatus(HttpStatus.OK)\n    public void formRegisterRecovery(@RequestBody @Validated CreatePasswordRecoveryCodeCommand command){\n        this.executeCommand(command);\n    }\n\n    @RequestMapping(method = RequestMethod.PATCH, path = RegistrationRoutes.PASSWORD_RESET)\n    @ResponseStatus(HttpStatus.OK)\n    public void passwordReset(@RequestBody @Validated UpdatePasswordWithRecoveryCodeCommand command) {\n        this.executeCommand(command);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/controller/RestApiRoutes.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.controller;\n\npublic class RestApiRoutes {\n    public static final String REST = \"/rest\";\n    public static final String PUBLIC = REST + \"/public\";\n    public static final String PRIVATE = REST + \"/private\";\n\n    public static class RegistrationRoutes {\n        public static final String FORM_REGISTRATION = PUBLIC + \"/register/form\";\n        public static final String CONFIRM_REGISTRATION = PUBLIC + \"/register/confirm/\";\n        public static final String CREATE_PASSWORD_RECOVERY_CODE = PUBLIC + \"/register/password/recovery-code\";\n        public static final String PASSWORD_RESET = PUBLIC + \"/register/password/reset\";\n    }\n\n    public static class AuthRoutes {\n        public static final String FORM_LOGIN = PUBLIC + \"/login/form\";\n        public static final String FACEBOOK_LOGIN = PUBLIC + \"/login/facebook\";\n        public static final String GOOGLE_LOGIN = PUBLIC + \"/login/google\";\n        public static final String LOGOUT = PRIVATE + \"/logout\";\n    }\n\n    public static class User {\n        public static final String USER = PRIVATE + \"/user\";\n        public static final String USER_DETAILS = USER + \"/{userId}\";\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/controller/UserController.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.controller;\n\nimport com.tomo.mcauthentication.application.users.command.ChangeUserDetailsCommand;\nimport com.tomo.mcauthentication.application.users.dto.BaseUserDto;\nimport com.tomo.mcauthentication.application.users.query.GetUserQuery;\nimport com.tomo.mcauthentication.infrastructure.springboot.controller.RestApiRoutes.User;\n\nimport org.springframework.http.HttpStatus;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.validation.annotation.Validated;\nimport org.springframework.web.bind.annotation.PathVariable;\nimport org.springframework.web.bind.annotation.RequestBody;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestMethod;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport java.util.UUID;\n\n@RestController\n@RequestMapping(path = \"/\")\npublic class UserController extends AbstractController {\n\n    @RequestMapping(method = RequestMethod.GET, path = User.USER_DETAILS)\n    public ResponseEntity user(@PathVariable(value = \"userId\") String userId){\n        BaseUserDto dto = this.executeQuery(new GetUserQuery(userId), BaseUserDto.class);\n\n        return ResponseEntity.ok(dto);\n    }\n\n    @RequestMapping(method = RequestMethod.PATCH, path = User.USER_DETAILS)\n    public ResponseEntity user(\n            @PathVariable(value = \"userId\") UUID userId,\n            @RequestBody @Validated ChangeUserDetailsCommand command){\n        command.setUserId(userId);\n        this.executeCommand(command);\n        return new ResponseEntity(HttpStatus.OK);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/filter/TokenAuthenticationFilter.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.filter;\n\nimport com.tomo.mcauthentication.application.authentication.command.SessionAuthenticationCommand;\nimport com.tomo.mcauthentication.application.authentication.dto.SessionDto;\nimport com.tomo.mcauthentication.application.contracts.McAuthenticationModule;\nimport com.tomo.mcauthentication.domain.session.TokenProvider;\nimport com.tomo.mcauthentication.domain.users.UserId;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\nimport com.tomo.mcauthentication.infrastructure.springboot.configuration.AppProperties;\nimport com.tomo.mcauthentication.infrastructure.springboot.security.UserAuthPrincipal;\nimport com.tomo.mcauthentication.infrastructure.springboot.security.UserAuthToken;\nimport com.tomo.mcauthentication.infrastructure.util.CookieUtils;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.core.context.SecurityContextHolder;\nimport org.springframework.util.StringUtils;\nimport org.springframework.web.filter.OncePerRequestFilter;\n\nimport javax.servlet.FilterChain;\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.concurrent.TimeUnit;\n\npublic class TokenAuthenticationFilter extends OncePerRequestFilter {\n\n    @Autowired\n    private TokenProvider tokenProvider;\n\n    @Autowired\n    McAuthenticationModule mcAuthenticationModuleExecutor;\n\n    @Autowired\n    protected AppProperties properties;\n\n    private static final Logger logger = LoggerFactory.getLogger(TokenAuthenticationFilter.class);\n\n    @Override\n    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {\n        try {\n            String jwt = getJwtFromRequest(request);\n\n            if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {\n                //maybe set authentication, UserId, SessionId, AccessToken\n                //But only if the intention is to use hasRole, isAuthenticate on RestController\n\n                SessionDto sessionDetails = (SessionDto) mcAuthenticationModuleExecutor.executeCommand(new SessionAuthenticationCommand(jwt));\n                jwt = sessionDetails.getAccessToken();\n\n                if (!sessionDetails.getAccessToken().equals(jwt)) {\n                    CookieUtils.updateCookie(\n                            request,\n                            response,\n                            properties.getAuth().getSessionAuthTokenName(),\n                            CookieUtils.serialize(sessionDetails.getAccessToken()),\n                            (int) TimeUnit.MILLISECONDS.toSeconds(properties.getAuth().getTokenExpirationMsec()));\n                }\n\n                setAuthentication(sessionDetails);\n            }\n        } catch (Exception ex) {\n            logger.error(\"Could not set user authentication in security context\", ex);\n            SecurityContextHolder.getContext().setAuthentication(null);\n        }\n\n        filterChain.doFilter(request, response);\n    }\n\n    private void setAuthentication(SessionDto sessionDetails) {\n        UserAuthToken currentAuthentication = null;\n\n        try {\n            currentAuthentication = (UserAuthToken) SecurityContextHolder.getContext().getAuthentication();\n        } catch (Exception e) {\n            currentAuthentication = null;\n        }\n\n        UserAuthToken newAuthentication = null;\n\n        if (currentAuthentication == null) {\n            newAuthentication = new UserAuthToken(new UserAuthPrincipal(sessionDetails));\n        } else {\n            UserAuthPrincipal principal = (UserAuthPrincipal) currentAuthentication.getPrincipal();\n            if (!principal.getSession().getAccessToken().equals(sessionDetails.getAccessToken())) {\n                newAuthentication = new UserAuthToken(new UserAuthPrincipal(sessionDetails));\n            }\n        }\n\n        if (newAuthentication != null) {\n            SecurityContextHolder.getContext().setAuthentication(newAuthentication);\n        }\n    }\n\n    private String getJwtFromRequest(HttpServletRequest request) {\n        return CookieUtils.getCookie(request, properties.getAuth().getSessionAuthTokenName())\n                .map(cookie -> CookieUtils.deserialize(cookie, String.class))\n//                .filter(cookie -> StringUtils.hasText(cookie) && cookie.startsWith(\"Bearer \"))\n//                .map(cookie -> cookie.substring(7))\n                .orElse(null);\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/security/CurrentUser.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.security;\n\nimport org.springframework.security.core.annotation.AuthenticationPrincipal;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n@Target({ElementType.PARAMETER, ElementType.TYPE})\n@Retention(RetentionPolicy.RUNTIME)\n@Documented\n@AuthenticationPrincipal\npublic @interface CurrentUser {\n\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/security/OAuth2AuthenticationFailureHandler.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.security;\n\nimport org.springframework.security.core.AuthenticationException;\nimport org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;\nimport org.springframework.stereotype.Component;\n\nimport javax.servlet.ServletException;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\n\n@Component\npublic class OAuth2AuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {\n\n    @Override\n    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {\n        int a = 1;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/security/OAuth2AuthenticationSuccessHandler.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.security;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.security.core.Authentication;\nimport org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;\nimport org.springframework.stereotype.Component;\nimport org.springframework.web.util.UriComponentsBuilder;\n\nimport javax.servlet.ServletException;\nimport javax.servlet.http.Cookie;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.io.IOException;\nimport java.net.URI;\nimport java.util.Optional;\n\n@Component\npublic class OAuth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {\n\n    @Override\n    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)\n            throws IOException, ServletException {\n        String targetUrl = determineTargetUrl(request, response, authentication);\n\n        if (response.isCommitted()) {\n            logger.debug(\"Response has already been committed. Unable to redirect to \" + targetUrl);\n            return;\n        }\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/security/UserAuthPrincipal.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.security;\n\nimport com.tomo.mcauthentication.application.authentication.dto.SessionDto;\nimport com.tomo.mcauthentication.domain.users.User;\n\nimport org.springframework.security.core.GrantedAuthority;\nimport org.springframework.security.core.userdetails.UserDetails;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.UUID;\n\npublic class UserAuthPrincipal implements UserDetails {\n\n    private SessionDto session;\n\n    private final Collection<GrantedAuthority> authorities;\n\n    private boolean enabled = true;\n\n    public UserAuthPrincipal(SessionDto session) {\n        this.session = session;\n        this.authorities = new ArrayList<>();\n    }\n\n    public SessionDto getSession() {\n        return session;\n    }\n\n    @Override\n    public Collection<? extends GrantedAuthority> getAuthorities() {\n        return new ArrayList<>();\n    }\n\n    @Override\n    public String getPassword() {\n        return null;\n    }\n\n    @Override\n    public String getUsername() {\n        return session.getUserId();\n    }\n\n    @Override\n    public boolean isAccountNonExpired() {\n        return this.enabled;\n    }\n\n    @Override\n    public boolean isAccountNonLocked() {\n        return this.enabled;\n    }\n\n    @Override\n    public boolean isCredentialsNonExpired() {\n        return this.enabled;\n    }\n\n    @Override\n    public boolean isEnabled() {\n        return this.enabled;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/springboot/security/UserAuthToken.java",
    "content": "package com.tomo.mcauthentication.infrastructure.springboot.security;\n\nimport com.tomo.mcauthentication.domain.users.User;\n\nimport org.springframework.security.authentication.AbstractAuthenticationToken;\nimport org.springframework.security.core.GrantedAuthority;\nimport org.springframework.security.core.authority.SimpleGrantedAuthority;\n\nimport java.util.Collection;\n\npublic class UserAuthToken extends AbstractAuthenticationToken {\n\n    private UserAuthPrincipal userPrincipal;\n\n    public UserAuthToken(UserAuthPrincipal userPrincipal) {\n        super(userPrincipal.getAuthorities());\n        super.setAuthenticated(true);\n        this.userPrincipal = userPrincipal;\n    }\n\n    public UserAuthToken(String authToken, Collection<? extends GrantedAuthority> authorities) {\n        super(authorities);\n        this.setAuthenticated(true);\n    }\n\n    @Override\n    public Object getCredentials() {\n        return null;\n    }\n\n    @Override\n    public Object getPrincipal() {\n        return userPrincipal;\n    }\n}\n"
  },
  {
    "path": "src/main/java/com/tomo/mcauthentication/infrastructure/util/CookieUtils.java",
    "content": "package com.tomo.mcauthentication.infrastructure.util;\n\nimport org.springframework.util.SerializationUtils;\n\nimport javax.servlet.http.Cookie;\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\nimport java.util.Base64;\nimport java.util.Optional;\n\npublic class CookieUtils {\n\n    public static Optional<Cookie> getCookie(HttpServletRequest request, String name) {\n        Cookie[] cookies = request.getCookies();\n\n        if (cookies != null && cookies.length > 0) {\n            for (Cookie cookie : cookies) {\n                if (cookie.getName().equals(name)) {\n                    return Optional.of(cookie);\n                }\n            }\n        }\n\n        return Optional.empty();\n    }\n\n    public static void addCookie(HttpServletResponse response, String name, String value, int maxAge) {\n        Cookie cookie = new Cookie(name, value);\n        cookie.setPath(\"/\");\n        cookie.setMaxAge(5000);\n        response.addCookie(cookie);\n    }\n\n    public static void updateCookie(HttpServletRequest request, HttpServletResponse response, String name, String value, int maxAge) {\n        Cookie[] cookies = request.getCookies();\n        if (cookies != null && cookies.length > 0) {\n            for (Cookie cookie: cookies) {\n                if (cookie.getName().equals(name)) {\n                    cookie.setValue(value);\n                    cookie.setPath(\"/\");\n                    cookie.setMaxAge(maxAge);\n                    response.addCookie(cookie);\n                }\n            }\n        }\n    }\n\n    public static void deleteCookie(HttpServletRequest request, HttpServletResponse response, String name) {\n        Cookie[] cookies = request.getCookies();\n        if (cookies != null && cookies.length > 0) {\n            for (Cookie cookie: cookies) {\n                if (cookie.getName().equals(name)) {\n                    cookie.setValue(\"\");\n                    cookie.setPath(\"/\");\n                    cookie.setMaxAge(0);\n                    response.addCookie(cookie);\n                }\n            }\n        }\n    }\n\n    public static String serialize(Object object) {\n        return Base64.getUrlEncoder()\n                .encodeToString(SerializationUtils.serialize(object));\n    }\n\n    public static <T> T deserialize(Cookie cookie, Class<T> cls) {\n        return cls.cast(SerializationUtils.deserialize(\n                        Base64.getUrlDecoder().decode(cookie.getValue())));\n    }\n\n\n}\n"
  },
  {
    "path": "src/main/resources/application.yml",
    "content": "server:\n  port: 8080\ndebug: true\n\nspring:\n  datasource:\n    url: jdbc:postgresql://localhost:5432/mc_authentication\n    username: mcuser\n    password: mcuser\n    driver-class-name: org.postgresql.Driver\n\n  jpa:\n    show-sql: true\n    hibernate:\n      ddl-auto: none\n      naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy\n    properties:\n      hibernate:\n        dialect: org.hibernate.dialect.PostgreSQL9Dialect\n\n  flyway:\n    enabled: true\n    baselineOnMigrate: true\n    schemas: public\n\n  security:\n    oauth2:\n      client:\n        registration:\n          google:\n            clientId: your-client-id.apps.googleusercontent.com\n            clientSecret: your-client-secret\n            scope:\n              - email\n              - profile\n          facebook:\n            clientId: your-client-id\n            clientSecret: your-client-secret\n            scope:\n              - email\n              - public_profile\n        provider:\n          facebook:\n            authorizationUri: https://www.facebook.com/v3.0/dialog/oauth\n            tokenUri: https://graph.facebook.com/v3.0/oauth/access_token\n            userInfoUri: https://graph.facebook.com/v3.0/me?fields=id,first_name,middle_name,last_name,name,email,verified,is_verified,picture.width(250).height(250)\napp:\n  base-url: http://localhost:8080\n  auth:\n    tokenSecret: 04ca023b39512e46d0c2cf4b48d5aac61d34302994c87ed4eff225dcf3b0a218739f3897051a057f9b846a69ea2927a587044164b7bae5e1306219d50b588cb1\n    tokenExpirationMsec: 864000000\n    sessionAuthTokenName: \"dei-www\"\n  cors:\n    allowedOrigins: http://localhost:3000,http://localhost:8080\n\n  message:\n    email:\n      mailgun:\n        domains: \"[your-sandbox].mailgun.org\"\n        api-url: \"https://api.mailgun.net/v3/\"\n        api-key: \"[mailgun-api-key]\"\n        from:\n          name: \"mc team\"\n          email: \"tomo.landeka02@gmail.com\"\n  gui:\n    base-url: \"localhost:3000\"\n    recovery-route: \"${app.gui.base-url}/reset-password/?recoveryCode=\"\n    confirmation-route: \"${app.gui.base-url}/register/confirm/?confirmationCode=\""
  },
  {
    "path": "src/main/resources/db/migration/V2022_02_02_1124__initial_structure.sql",
    "content": "CREATE TABLE mcuser (\n    id                  UUID PRIMARY KEY NOT NULL,\n    first_name          VARCHAR(255),\n    last_name           VARCHAR(255),\n    provider            VARCHAR(50)      NOT NULL,\n    email               VARCHAR(255)     NOT NULL\n        CONSTRAINT mcuser_email_unique unique,\n    concurrency_version BIGINT,\n    created             TIMESTAMP        NOT NULL DEFAULT Now(),\n    modified            TIMESTAMP\n);\n\nCREATE TABLE user_registration (\n    id                  BIGSERIAL PRIMARY KEY,\n    first_name          VARCHAR(255),\n    last_name           VARCHAR(255),\n    email               VARCHAR(255)            NOT NULL,\n    password            VARCHAR(255)            NOT NULL,\n    confirmation_code   VARCHAR(255)            NOT NULL,\n    status              VARCHAR(255)            NOT NULL,\n    register_date       TIMESTAMP,\n    recovery_code       VARCHAR(255),\n    recovery_code_expiration_date TIMESTAMP,\n    user_id             UUID\n        CONSTRAINT user_registration_mcuser_id_fk REFERENCES mcuser,\n    concurrency_version BIGINT,\n    created             TIMESTAMP DEFAULT now() NOT NULL,\n    modified            TIMESTAMP\n);\n\ncreate table session (\n    id                  UUID PRIMARY KEY,\n    user_id             UUID NOT NULL CONSTRAINT session_mcuser_id_fk REFERENCES mcuser,\n    access_token        TEXT NOT NULL,\n    expiration_date      TIMESTAMP,\n    token_type          TEXT NOT NULL,\n    refresh_token       TEXT,\n    user_agent          TEXT,\n    ip_address          VARCHAR(45),\n    last_activity       TIMESTAMP,\n    created             TIMESTAMP DEFAULT now() NOT NULL,\n    modified            TIMESTAMP\n);\n\nCREATE UNIQUE INDEX user_registration_user_id_uindex ON user_registration(user_id);\n\nCREATE TABLE stored_event (\n    event_id BIGSERIAL PRIMARY KEY,\n    event_body TEXT NOT NULL,\n    occurred_on TIMESTAMP NOT NULL,\n    type_name VARCHAR (200) NOT NULL\n);\n"
  },
  {
    "path": "src/main/resources/repo/org/tomo/ddd_common/1.0.0/ddd_common-1.0.0.jar.md5",
    "content": "d6f732badc879e635745ef1ee13673d3"
  },
  {
    "path": "src/main/resources/repo/org/tomo/ddd_common/1.0.0/ddd_common-1.0.0.jar.sha1",
    "content": "49221e5069bd616ba23339076cad6478d3762710"
  },
  {
    "path": "src/main/resources/repo/org/tomo/ddd_common/1.0.0/ddd_common-1.0.0.pom",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd\" xmlns=\"http://maven.apache.org/POM/4.0.0\"\n    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n  <modelVersion>4.0.0</modelVersion>\n  <groupId>org.tomo</groupId>\n  <artifactId>ddd_common</artifactId>\n  <version>1.0.0</version>\n</project>\n"
  },
  {
    "path": "src/main/resources/repo/org/tomo/ddd_common/1.0.0/ddd_common-1.0.0.pom.md5",
    "content": "5238d5a53bcbfbe70a6cb87ed493d6f3"
  },
  {
    "path": "src/main/resources/repo/org/tomo/ddd_common/1.0.0/ddd_common-1.0.0.pom.sha1",
    "content": "423681301f4b73b38060c3c069f0141c0b54c660"
  },
  {
    "path": "src/main/resources/repo/org/tomo/ddd_common/maven-metadata.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<metadata>\n  <groupId>org.tomo</groupId>\n  <artifactId>ddd_common</artifactId>\n  <versioning>\n    <release>1.0.0</release>\n    <versions>\n      <version>1.0.0</version>\n    </versions>\n    <lastUpdated>20221113150911</lastUpdated>\n  </versioning>\n</metadata>\n"
  },
  {
    "path": "src/main/resources/repo/org/tomo/ddd_common/maven-metadata.xml.md5",
    "content": "2dfb0c4eb83fb0e21037e00e71ab51cb"
  },
  {
    "path": "src/main/resources/repo/org/tomo/ddd_common/maven-metadata.xml.sha1",
    "content": "b984353efb5206ed31336cb8a1508c6453122adb"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/integration/BaseIntegrationTest.java",
    "content": "package com.tomo.mcauthentication.integration;\n\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)\npublic abstract class BaseIntegrationTest { }\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/integration/application/AbstractApplicationServiceTest.java",
    "content": "package com.tomo.mcauthentication.integration.application;\n\nimport com.tomo.ddd.email.EmailSender;\nimport com.tomo.mcauthentication.application.authentication.EmailLoginCommandHandler;\nimport com.tomo.mcauthentication.application.authentication.FacebookLoginCommandHandler;\nimport com.tomo.mcauthentication.application.authentication.GoogleLoginCommandHandler;\nimport com.tomo.mcauthentication.application.authentication.dto.SessionDto;\nimport com.tomo.mcauthentication.application.recovery.SendPasswordRecoveryEmailCommandHandler;\nimport com.tomo.mcauthentication.application.registration.ConfirmUserRegistrationCommandHandler;\nimport com.tomo.mcauthentication.application.registration.RegisterNewUserCommandHandler;\nimport com.tomo.mcauthentication.application.registration.SendRegistrationConfirmationEmailCommandHandler;\nimport com.tomo.mcauthentication.application.registration.command.ConfirmUserRegistrationCommand;\nimport com.tomo.mcauthentication.domain.oauth2.OAuth2Principal;\nimport com.tomo.mcauthentication.domain.registration.UserRegistration;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationRepository;\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\nimport com.tomo.mcauthentication.infrastructure.http.oauth2.FacebookOAuth2Authentication;\nimport com.tomo.mcauthentication.infrastructure.http.oauth2.GoogleOAuth2Authentication;\nimport com.tomo.mcauthentication.integration.BaseIntegrationTest;\nimport com.tomo.mcauthentication.testdata.CommandObjectMother;\nimport com.tomo.mcauthentication.testdata.StaticFields;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.mock.mockito.MockBean;\nimport org.springframework.boot.test.mock.mockito.SpyBean;\n\nimport java.util.Arrays;\nimport java.util.Optional;\n\nimport static org.mockito.ArgumentMatchers.anyString;\nimport static org.mockito.Mockito.when;\n\npublic abstract class AbstractApplicationServiceTest extends BaseIntegrationTest {\n\n    @Autowired\n    protected FacebookLoginCommandHandler facebookLoginCommandHandler;\n\n    @Autowired\n    protected GoogleLoginCommandHandler googleLoginCommandHandler;\n\n    @Autowired\n    protected EmailLoginCommandHandler emailLoginCommandHandler;\n\n    @MockBean\n    protected FacebookOAuth2Authentication facebookOAuth2Authentication;\n\n    @MockBean\n    protected GoogleOAuth2Authentication googleOAuth2Authentication;\n\n    @Autowired\n    protected ConfirmUserRegistrationCommandHandler confirmUserRegistrationCommandHandler;\n\n    @Autowired\n    protected RegisterNewUserCommandHandler registerNewUserCommandHandler;\n\n    @Autowired\n    protected UserRegistrationRepository userRegistrationRepository;\n\n    @Autowired\n    protected UserRepository userRepository;\n\n    @SpyBean\n    protected SendRegistrationConfirmationEmailCommandHandler sendRegistrationConfirmationEmailCommandHandler;\n\n    @SpyBean\n    protected SendPasswordRecoveryEmailCommandHandler sendPasswordRecoveryEmailCommandHandler;\n\n    @MockBean\n    protected EmailSender emailMessageSender;\n\n    protected User createFormUser() {\n        confirmUserRegistrationCommandHandler.handle(\n                new ConfirmUserRegistrationCommand(\n                        createUserRegistration().getConfirmationCode()\n                ));\n        return userRepository.findByEmail(StaticFields.USER_EMAIL);\n    }\n\n    protected UserRegistration createUserRegistration() {\n        registerNewUserCommandHandler.handle(CommandObjectMother.registerNewUserCommand());\n        Optional<UserRegistration> userRegistration = userRegistrationRepository\n                .findAllByEmail(Arrays.asList(StaticFields.USER_EMAIL))\n                .stream()\n                .findFirst();\n\n        return userRegistration.get();\n    }\n\n    protected SessionDto formLogin(){\n        createFormUser();\n        return emailLoginCommandHandler.handle(CommandObjectMother.emailLoginCommand());\n    }\n\n    protected User createFacbookUser() {\n        when(facebookOAuth2Authentication.authenticate(anyString()))\n                .thenReturn(oAuth2Principal(User.AuthProvider.FACEBOOK.toString()));\n\n        facebookLoginCommandHandler.handle(CommandObjectMother.facebookLoginCommand());\n        return userRepository.findByEmail(StaticFields.USER_EMAIL);\n    }\n\n    protected User createGoogleUser() {\n        when(googleOAuth2Authentication.authenticate(anyString()))\n                .thenReturn(oAuth2Principal(User.AuthProvider.GOOGLE.toString()));\n\n       googleLoginCommandHandler.handle(CommandObjectMother.googleLoginCommand());\n        return userRepository.findByEmail(StaticFields.USER_EMAIL);\n    }\n\n    private OAuth2Principal oAuth2Principal(String anProvider) {\n        return new OAuth2Principal(\n                StaticFields.USER_OAUTH_ID,\n                StaticFields.USER_EMAIL,\n                StaticFields.USER_FIRST_NAME,\n                StaticFields.USER_LAST_NAME,\n                \"img\",\n                anProvider);\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/integration/application/authentication/EmailLoginCommandHandlerTest.java",
    "content": "package com.tomo.mcauthentication.integration.application.authentication;\n\nimport com.tomo.ddd.domain.BusinessRuleValidationException;\nimport com.tomo.mcauthentication.integration.application.AbstractApplicationServiceTest;\nimport org.junit.Test;\n\nimport javax.transaction.Transactional;\n\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertThrows;\n\npublic class EmailLoginCommandHandlerTest extends AbstractApplicationServiceTest {\n\n    @Test\n    @Transactional\n    public void testUserFormLogin() {\n        assertNotNull(formLogin());\n    }\n\n    @Test\n    @Transactional\n    public void testNewFormUserFailedWhenGoogleUserExists() {\n        createGoogleUser();\n        assertThrows(BusinessRuleValidationException.class, this::createFormUser);\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/integration/application/authentication/FacebookLoginCommandHandlerTest.java",
    "content": "package com.tomo.mcauthentication.integration.application.authentication;\n\nimport com.tomo.ddd.domain.BusinessRuleValidationException;\nimport com.tomo.mcauthentication.integration.application.AbstractApplicationServiceTest;\nimport org.junit.Test;\n\nimport javax.transaction.Transactional;\n\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertThrows;\n\npublic class FacebookLoginCommandHandlerTest extends AbstractApplicationServiceTest {\n\n    @Test\n    @Transactional\n    public void testNewFacebookUserCreated() {\n        assertNotNull(createFacbookUser());\n    }\n\n    @Test\n    @Transactional\n    public void testNewFacebookUserFailedWhenGoogleUserExists() {\n        createGoogleUser();\n        assertThrows(BusinessRuleValidationException.class, this::createFacbookUser);\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/integration/application/authentication/GoogleLoginCommandHandlerTest.java",
    "content": "package com.tomo.mcauthentication.integration.application.authentication;\n\nimport com.tomo.ddd.domain.BusinessRuleValidationException;\nimport com.tomo.mcauthentication.integration.application.AbstractApplicationServiceTest;\nimport org.junit.Test;\n\nimport javax.transaction.Transactional;\n\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertThrows;\n\npublic class GoogleLoginCommandHandlerTest extends AbstractApplicationServiceTest {\n\n    @Test\n    @Transactional\n    public void testNewGoogleUserCreated() {\n        assertNotNull(createGoogleUser());\n    }\n\n    @Test\n    @Transactional\n    public void testNewGoogleUserFailedWhenFacebookUserExists() {\n        createFacbookUser();\n        assertThrows(BusinessRuleValidationException.class, this::createGoogleUser);\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/integration/application/authentication/LogoutCommandHandlerTest.java",
    "content": "package com.tomo.mcauthentication.integration.application.authentication;\n\nimport com.tomo.ddd.domain.BusinessRuleValidationException;\nimport com.tomo.mcauthentication.application.authentication.LogoutCommandHandler;\nimport com.tomo.mcauthentication.application.authentication.command.LogoutCommand;\nimport com.tomo.mcauthentication.application.authentication.dto.SessionDto;\nimport com.tomo.mcauthentication.domain.session.SessionAuthenticationService;\nimport com.tomo.mcauthentication.integration.application.AbstractApplicationServiceTest;\nimport org.junit.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport javax.transaction.Transactional;\n\nimport static org.junit.Assert.assertThrows;\n\npublic class LogoutCommandHandlerTest extends AbstractApplicationServiceTest {\n\n    @Autowired\n    LogoutCommandHandler logoutCommandHandler;\n\n    @Autowired\n    SessionAuthenticationService sessionAuthenticationService;\n\n    @Test\n    @Transactional\n    public void testLogout() {\n        SessionDto sessionDto = formLogin();\n        logoutCommandHandler.handle(new LogoutCommand(sessionDto.getAccessToken()));\n        assertThrows(BusinessRuleValidationException.class, () -> sessionAuthenticationService.authenticate(sessionDto.getAccessToken()));\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/integration/application/authentication/SessionAuthenticationCommandHandlerTest.java",
    "content": "package com.tomo.mcauthentication.integration.application.authentication;\n\nimport com.tomo.mcauthentication.application.authentication.SessionAuthenticationCommandHandler;\nimport com.tomo.mcauthentication.application.authentication.command.SessionAuthenticationCommand;\nimport com.tomo.mcauthentication.application.authentication.dto.SessionDto;\nimport com.tomo.mcauthentication.domain.session.SessionAuthenticationService;\nimport com.tomo.mcauthentication.integration.application.AbstractApplicationServiceTest;\nimport org.junit.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport javax.transaction.Transactional;\n\nimport static org.junit.Assert.assertEquals;\n\npublic class SessionAuthenticationCommandHandlerTest extends AbstractApplicationServiceTest {\n\n    @Autowired\n    SessionAuthenticationCommandHandler commandHandler;\n\n    @Autowired\n    SessionAuthenticationService sessionAuthenticationService;\n\n    @Test\n    @Transactional\n    public void testAuthenticateSession() {\n        SessionDto initialSessionDto = formLogin();\n        SessionDto sessionDto = commandHandler.handle(new SessionAuthenticationCommand(initialSessionDto.getAccessToken()));\n        assertEquals(initialSessionDto.getAccessToken(), sessionDto.getAccessToken());\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/integration/application/recovery/CreatePasswordRecoveryCodeCommandHandlerTest.java",
    "content": "package com.tomo.mcauthentication.integration.application.recovery;\n\nimport com.tomo.mcauthentication.application.authentication.dto.RecoveryPasswordDto;\nimport com.tomo.mcauthentication.application.recovery.CreatePasswordRecoveryCodeCommandHandler;\nimport com.tomo.mcauthentication.integration.application.AbstractApplicationServiceTest;\nimport com.tomo.mcauthentication.testdata.CommandObjectMother;\nimport org.junit.Test;\nimport org.mockito.Mockito;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport javax.transaction.Transactional;\n\nimport static org.junit.Assert.assertNotNull;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.verify;\n\npublic class CreatePasswordRecoveryCodeCommandHandlerTest extends AbstractApplicationServiceTest {\n\n    @Autowired\n    CreatePasswordRecoveryCodeCommandHandler commandHandler;\n\n    @Test\n    @Transactional\n    public void testRecoveryCodeCreated() {\n        formLogin();\n        RecoveryPasswordDto recoveryPasswordDto = commandHandler.handle(CommandObjectMother.createPasswordRecoveryCodeCommand());\n        assertNotNull(recoveryPasswordDto);\n        verify(this.sendPasswordRecoveryEmailCommandHandler, Mockito.times(1)).handle(any());\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/integration/application/recovery/GetUserRegistrationWithRecoveryCodeQueryHandlerTest.java",
    "content": "package com.tomo.mcauthentication.integration.application.recovery;\n\nimport com.tomo.mcauthentication.application.authentication.dto.RecoveryPasswordDto;\nimport com.tomo.mcauthentication.application.recovery.CreatePasswordRecoveryCodeCommandHandler;\nimport com.tomo.mcauthentication.application.recovery.GetUserRegistrationWithRecoveryCodeQueryHandler;\nimport com.tomo.mcauthentication.application.recovery.dto.GetUserRegistrationWithRecoveryCodeQuery;\nimport com.tomo.mcauthentication.application.registration.dto.UserRegistrationDto;\nimport com.tomo.mcauthentication.integration.application.AbstractApplicationServiceTest;\nimport com.tomo.mcauthentication.testdata.CommandObjectMother;\nimport org.junit.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport javax.transaction.Transactional;\n\nimport static org.junit.Assert.assertNotNull;\n\npublic class GetUserRegistrationWithRecoveryCodeQueryHandlerTest extends AbstractApplicationServiceTest {\n\n    @Autowired\n    GetUserRegistrationWithRecoveryCodeQueryHandler queryHandler;\n\n    @Autowired\n    CreatePasswordRecoveryCodeCommandHandler commandHandler;\n\n    @Test\n    @Transactional\n    public void testGetUserRegistrationWithRecoveryCode() {\n        formLogin();\n        RecoveryPasswordDto recoveryPasswordDto = commandHandler.handle(CommandObjectMother.createPasswordRecoveryCodeCommand());\n        UserRegistrationDto userRegistrationDto = queryHandler.handle(new GetUserRegistrationWithRecoveryCodeQuery(recoveryPasswordDto.getRecoveryCode()));\n        assertNotNull(userRegistrationDto.getEmail());\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/integration/application/recovery/UpdatePasswordWithRecoveryCodeCommandHandlerTest.java",
    "content": "package com.tomo.mcauthentication.integration.application.recovery;\n\nimport com.tomo.mcauthentication.application.authentication.command.EmailLoginCommand;\nimport com.tomo.mcauthentication.application.authentication.dto.RecoveryPasswordDto;\nimport com.tomo.mcauthentication.application.authentication.dto.SessionDto;\nimport com.tomo.mcauthentication.application.contracts.Voidy;\nimport com.tomo.mcauthentication.application.recovery.CreatePasswordRecoveryCodeCommandHandler;\nimport com.tomo.mcauthentication.application.recovery.UpdatePasswordWithRecoveryCodeCommandHandler;\nimport com.tomo.mcauthentication.application.recovery.command.UpdatePasswordWithRecoveryCodeCommand;\nimport com.tomo.mcauthentication.integration.application.AbstractApplicationServiceTest;\nimport com.tomo.mcauthentication.testdata.CommandObjectMother;\nimport com.tomo.mcauthentication.testdata.StaticFields;\nimport org.junit.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport javax.transaction.Transactional;\n\nimport static org.junit.Assert.assertEquals;\n\npublic class UpdatePasswordWithRecoveryCodeCommandHandlerTest extends AbstractApplicationServiceTest {\n\n    @Autowired\n    CreatePasswordRecoveryCodeCommandHandler createPasswordRecoveryCodeCommandHandler;\n\n    @Autowired\n    UpdatePasswordWithRecoveryCodeCommandHandler commandHandler;\n\n    @Test\n    @Transactional\n    public void testUpdatePasswordWithRecoveryCode() {\n        formLogin();\n        RecoveryPasswordDto recoveryPasswordDto = createPasswordRecoveryCodeCommandHandler.handle(CommandObjectMother.createPasswordRecoveryCodeCommand());\n        assertEquals(commandHandler.handle(new UpdatePasswordWithRecoveryCodeCommand(\n                StaticFields.NEW_PASS,\n                StaticFields.NEW_PASS,\n                recoveryPasswordDto.getRecoveryCode())).getClass(),\n                Voidy.class);\n\n        assertEquals(\n                emailLoginCommandHandler.handle(new EmailLoginCommand(StaticFields.USER_EMAIL, StaticFields.NEW_PASS)).getClass(),\n                SessionDto.class\n        );\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/integration/application/registration/ChangePasswordCommandHandlerTest.java",
    "content": "package com.tomo.mcauthentication.integration.application.registration;\n\nimport com.tomo.ddd.domain.BusinessRuleValidationException;\nimport com.tomo.mcauthentication.application.authentication.command.EmailLoginCommand;\nimport com.tomo.mcauthentication.application.authentication.dto.SessionDto;\nimport com.tomo.mcauthentication.application.contracts.Voidy;\nimport com.tomo.mcauthentication.application.registration.ChangePasswordCommandHandler;\nimport com.tomo.mcauthentication.application.registration.command.ChangePasswordCommand;\nimport com.tomo.mcauthentication.integration.application.AbstractApplicationServiceTest;\nimport com.tomo.mcauthentication.testdata.StaticFields;\nimport org.junit.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport javax.transaction.Transactional;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertThrows;\n\npublic class ChangePasswordCommandHandlerTest extends AbstractApplicationServiceTest {\n\n    @Autowired\n    ChangePasswordCommandHandler commandHandler;\n\n    @Test\n    @Transactional\n    public void testChangePassword() {\n        SessionDto sessionDto = formLogin();\n\n        assertEquals(commandHandler.handle(new ChangePasswordCommand(\n                sessionDto.getAccessToken(),\n                        StaticFields.PASSWORD,\n                        StaticFields.NEW_PASS,\n                        StaticFields.NEW_PASS)).getClass(),\n                Voidy.class);\n\n\n        assertThrows(BusinessRuleValidationException.class, () -> emailLoginCommandHandler.handle(new EmailLoginCommand(StaticFields.USER_EMAIL, StaticFields.PASSWORD)));\n\n        assertEquals(\n                emailLoginCommandHandler.handle(new EmailLoginCommand(StaticFields.USER_EMAIL, StaticFields.NEW_PASS)).getClass(),\n                SessionDto.class\n        );\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/integration/application/registration/ConfirmUserRegistrationCommandHandlerTest.java",
    "content": "package com.tomo.mcauthentication.integration.application.registration;\n\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.integration.application.AbstractApplicationServiceTest;\nimport org.junit.Test;\n\nimport javax.transaction.Transactional;\n\nimport static org.junit.Assert.assertNotNull;\n\npublic class ConfirmUserRegistrationCommandHandlerTest extends AbstractApplicationServiceTest {\n\n    @Test\n    @Transactional\n    public void testConfirmUserRegistration() {\n        User user = createFormUser();\n        assertNotNull(user);\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/integration/application/registration/RegisterNewUserCommandHandlerTest.java",
    "content": "package com.tomo.mcauthentication.integration.application.registration;\n\nimport com.tomo.mcauthentication.application.registration.ConfirmUserRegistrationCommandHandler;\nimport com.tomo.mcauthentication.application.registration.NewUserRegisteredEventHandler;\nimport com.tomo.mcauthentication.application.registration.RegisterNewUserCommandHandler;\nimport com.tomo.mcauthentication.domain.registration.UserRegistration;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationRepository;\nimport com.tomo.mcauthentication.integration.application.AbstractApplicationServiceTest;\nimport org.junit.Test;\nimport org.mockito.Mockito;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport javax.transaction.Transactional;\n\nimport static org.junit.Assert.assertNotNull;\nimport static org.junit.Assert.assertThrows;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.verify;\n\npublic class RegisterNewUserCommandHandlerTest extends AbstractApplicationServiceTest {\n\n    @Autowired\n    RegisterNewUserCommandHandler commandHandler;\n\n    @Autowired\n    ConfirmUserRegistrationCommandHandler confirmUserRegistrationCommandHandler;\n\n    @Autowired\n    UserRegistrationRepository userRegistrationRepository;\n\n    @Autowired\n    NewUserRegisteredEventHandler newUserRegisteredEventHandler;\n\n    @Test\n    @Transactional\n    public void testNewUserRegistrationCreated() {\n        UserRegistration userRegistration = createUserRegistration();\n        assertNotNull(userRegistration);\n        verify(this.sendRegistrationConfirmationEmailCommandHandler, Mockito.times(1)).handle(any());\n    }\n\n    @Test\n    @Transactional\n    public void testNewUserRegistrationFailedWhenUserExists() {\n        createFormUser();\n\n        assertThrows(RuntimeException.class, () -> {\n            createUserRegistration();\n        });\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/integration/application/users/ChangeUserDetailsCommandHandlerTest.java",
    "content": "package com.tomo.mcauthentication.integration.application.users;\n\nimport com.tomo.mcauthentication.application.authentication.dto.SessionDto;\nimport com.tomo.mcauthentication.application.users.ChangeUserDetailsCommandHandler;\nimport com.tomo.mcauthentication.application.users.command.ChangeUserDetailsCommand;\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\nimport com.tomo.mcauthentication.integration.application.AbstractApplicationServiceTest;\nimport com.tomo.mcauthentication.testdata.CommandObjectMother;\nimport org.junit.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport javax.transaction.Transactional;\n\nimport static org.junit.Assert.assertEquals;\n\npublic class ChangeUserDetailsCommandHandlerTest extends AbstractApplicationServiceTest {\n\n    @Autowired\n    ChangeUserDetailsCommandHandler commandHandler;\n\n    @Autowired\n    UserRepository userRepository;\n\n    @Test\n    @Transactional\n    public void testChangeUserDetails() {\n        User user = createFormUser();\n        SessionDto sessionDto = emailLoginCommandHandler.handle(CommandObjectMother.emailLoginCommand());\n\n        ChangeUserDetailsCommand command = new ChangeUserDetailsCommand(\n                user.getUserId().id(),\n                \"first name\",\n                \"last name\");\n        command.setAuthToken(sessionDto.getAccessToken());\n\n        commandHandler.handle(command);\n        User userFromDb = userRepository.findById(user.getUserId());\n        assertEquals(userFromDb.getFirstName(), \"first name\");\n        assertEquals(userFromDb.getLastName(), \"last name\");\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/integration/application/users/GetUserQueryHandlerTest.java",
    "content": "package com.tomo.mcauthentication.integration.application.users;\n\nimport com.tomo.mcauthentication.application.authentication.dto.SessionDto;\nimport com.tomo.mcauthentication.application.users.GetUserQueryHandler;\nimport com.tomo.mcauthentication.application.users.query.GetUserQuery;\nimport com.tomo.mcauthentication.integration.application.AbstractApplicationServiceTest;\nimport org.junit.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport javax.transaction.Transactional;\n\nimport static org.junit.Assert.assertNotNull;\n\npublic class GetUserQueryHandlerTest extends AbstractApplicationServiceTest {\n\n    @Autowired\n    GetUserQueryHandler getUserQueryHandler;\n\n    @Test\n    @Transactional\n    public void testGetUser() {\n        SessionDto sessionDto = formLogin();\n\n        GetUserQuery query = new GetUserQuery(sessionDto.getUserId());\n        assertNotNull(getUserQueryHandler.handle(query));\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/smoke/McAuthenticationApplicationSmokeTest.java",
    "content": "package com.tomo.mcauthentication.smoke;\n\nimport com.tomo.mcauthentication.infrastructure.springboot.controller.UserController;\n\nimport org.junit.jupiter.api.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.context.SpringBootTest;\n\nimport static org.assertj.core.api.Assertions.assertThat;\n\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)\nclass McAuthenticationApplicationSmokeTest {\n\n\t@Autowired\n\tUserController userController;\n\n\t@Test\n\tvoid contextLoads() {\n\t\tassertThat(userController).isNotNull();\n\t}\n\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/testdata/CommandObjectMother.java",
    "content": "package com.tomo.mcauthentication.testdata;\n\nimport com.github.javafaker.Faker;\nimport com.tomo.mcauthentication.application.authentication.command.EmailLoginCommand;\nimport com.tomo.mcauthentication.application.authentication.command.FacebookLoginCommand;\nimport com.tomo.mcauthentication.application.authentication.command.GoogleLoginCommand;\nimport com.tomo.mcauthentication.application.recovery.command.CreatePasswordRecoveryCodeCommand;\nimport com.tomo.mcauthentication.application.registration.command.RegisterNewUserCommand;\n\npublic class CommandObjectMother extends StaticFields {\n\n    private static Faker faker = new Faker();\n\n    private CommandObjectMother() {\n    }\n\n    public static RegisterNewUserCommand registerNewUserCommand() {\n        return new RegisterNewUserCommand(USER_FIRST_NAME, USER_LAST_NAME, USER_EMAIL, PASSWORD);\n    }\n\n    public static RegisterNewUserCommand registerNewUserCommandWithFakerEmail() {\n        return new RegisterNewUserCommand(USER_FIRST_NAME, USER_LAST_NAME, faker.internet().emailAddress(), PASSWORD);\n    }\n\n    public static EmailLoginCommand emailLoginCommand() {\n        return new EmailLoginCommand(USER_EMAIL, PASSWORD);\n    }\n\n    public static FacebookLoginCommand facebookLoginCommand() {\n        return new FacebookLoginCommand(ACCESS_CODE);\n    }\n\n    public static GoogleLoginCommand googleLoginCommand() {\n        return new GoogleLoginCommand(ACCESS_CODE);\n    }\n\n    public static CreatePasswordRecoveryCodeCommand createPasswordRecoveryCodeCommand() {\n        return new CreatePasswordRecoveryCodeCommand(USER_EMAIL);\n    }\n\n\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/testdata/StaticFields.java",
    "content": "package com.tomo.mcauthentication.testdata;\n\npublic class StaticFields {\n\n    public static final String ACCESS_CODE = \"anAccessCode\";\n    public static final String USER_OAUTH_ID = \"anAccessCode\";\n    public static final String USER_FIRST_NAME = \"Tom\";\n    public static final String USER_LAST_NAME = \"Land\";\n    public static final String USER_EMAIL = \"random@email.com\";\n    public static final String PASSWORD = \"AA123bb##\";\n    public static final String NEW_PASS = \"randomNewPass123\";\n    public static final String RECOVERY_CODE = \"randomNewPass123\";\n\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/unit/application/registration/UserRegistrationCommandHandlerTest.java",
    "content": "package com.tomo.mcauthentication.unit.application.registration;\n\nimport com.tomo.mcauthentication.domain.DomainRegistry;\nimport com.tomo.mcauthentication.domain.EncryptionService;\nimport com.tomo.mcauthentication.domain.registration.PasswordService;\nimport com.tomo.mcauthentication.domain.registration.UserRegistration;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationRepository;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationStatus;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\nimport org.junit.jupiter.api.BeforeEach;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockitoSession;\nimport org.mockito.Spy;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.test.context.ActiveProfiles;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertNotEquals;\nimport static org.mockito.Mockito.any;\nimport static org.mockito.Mockito.when;\n\n@ExtendWith(MockitoExtension.class)\n@ActiveProfiles(profiles = { \"unit\" })\npublic class UserRegistrationCommandHandlerTest {\n\n    @Spy\n    DomainRegistry domainRegistry;\n\n    @Mock\n    UserRegistrationRepository userRegistrationRepository;\n\n    @Mock\n    UserRepository userRepository;\n\n    @Mock\n    EncryptionService encryptionService;\n\n    @Mock\n    ApplicationContext applicationContext;\n\n    protected MockitoSession mockito;\n\n//    @BeforeAll\n//    public void setup() {\n//        mockito = Mockito.mockitoSession()\n//                .initMocks(this)\n//                          .strictness(Strictness.STRICT_STUBS)\n//                .startMocking();\n//    }\n//\n//    @AfterAll\n//    public void tearDown() {\n//        mockito.finishMocking();\n//    }\n\n    @BeforeEach\n    public void setUp(){\n        domainRegistry.setApplicationContext(applicationContext);\n\n//        when(encryptionService.encryptedValue(any())).thenReturn(\"randomString\");\n        when(applicationContext.getBean(\"passwordService\")).thenReturn(new PasswordService());\n        when(applicationContext.getBean(\"MD5EncryptionService\")).thenReturn(encryptionService);\n        when(applicationContext.getBean(\"userRepository\")).thenReturn(userRepository);\n        when(applicationContext.getBean(\"userRegistrationRepository\")).thenReturn(userRegistrationRepository);\n        DomainRegistry.encryptionService();\n        int a = 5;\n    }\n\n    @Test\n    public void testCreateUserRegister() {\n        when(userRegistrationRepository.countByEmailAndStatus(any(), any())).thenReturn(Long.valueOf(0));\n        when(userRepository.findByEmail(any())).thenReturn(null);\n        UserRegistration ur = UserRegistration.registerNewUser(\"AA123bb##\", \"email\", \"firstName\", \"lastName\");\n\n        assertEquals(ur.getEmail(), \"email\");\n        assertEquals(ur.getStatus(), UserRegistrationStatus.WaitingForConfirmation);\n        assertNotEquals(ur.getEmail(), \"email1\");\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/unit/domain/AbstractUnitTest.java",
    "content": "package com.tomo.mcauthentication.unit.domain;\n\nimport org.junit.jupiter.api.TestInstance;\nimport org.junit.runner.RunWith;\nimport org.mockito.MockitoSession;\nimport org.mockito.junit.MockitoJUnitRunner;\nimport org.springframework.test.context.ActiveProfiles;\n\n@RunWith(MockitoJUnitRunner.StrictStubs.class)\n@TestInstance(TestInstance.Lifecycle.PER_CLASS)\n@ActiveProfiles(profiles = { \"unit\" })\npublic abstract class AbstractUnitTest {\n\n    protected MockitoSession mockito;\n\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/unit/domain/registration/UserRegistrationTest.java",
    "content": "package com.tomo.mcauthentication.unit.domain.registration;\n\nimport com.tomo.ddd.domain.DomainEventPublisher;\nimport com.tomo.mcauthentication.domain.DomainRegistry;\nimport com.tomo.mcauthentication.domain.EncryptionService;\nimport com.tomo.mcauthentication.domain.registration.PasswordService;\nimport com.tomo.mcauthentication.domain.registration.UserRegistration;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationRepository;\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationStatus;\nimport com.tomo.mcauthentication.domain.registration.events.*;\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserId;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\nimport com.tomo.mcauthentication.testdata.StaticFields;\nimport org.junit.jupiter.api.*;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.MockedConstruction;\nimport org.mockito.MockedStatic;\nimport org.mockito.Mockito;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport org.mockito.junit.jupiter.MockitoSettings;\nimport org.mockito.quality.Strictness;\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.test.context.ActiveProfiles;\n\nimport java.time.LocalDateTime;\nimport java.util.UUID;\n\nimport static org.junit.Assert.*;\nimport static org.mockito.ArgumentMatchers.*;\nimport static org.mockito.Mockito.*;\n\n@ExtendWith(MockitoExtension.class)\n@MockitoSettings(strictness = Strictness.LENIENT)\n@TestInstance(TestInstance.Lifecycle.PER_CLASS)\n@ActiveProfiles(profiles = { \"unit\" })\npublic class UserRegistrationTest {\n\n    private static boolean setUpIsDone = false;\n\n    private static final String WEAK_PASS = \"abc\";\n\n    DomainRegistry domainRegistry;\n\n    @Mock\n    UserRegistrationRepository userRegistrationRepository;\n\n    @Mock\n    UserRepository userRepository;\n\n    @Mock\n    EncryptionService encryptionService;\n\n    @Mock\n    ApplicationContext applicationContext;\n\n    @Mock\n    DomainEventPublisher domainEventPublisher;\n\n    MockedStatic<DomainEventPublisher> publisher;\n\n    MockedConstruction<User> mockedUser;\n\n    @BeforeEach\n    public void setUp() {\n        publisher = Mockito.mockStatic(DomainEventPublisher.class);\n        publisher.when(DomainEventPublisher::instance).thenReturn(domainEventPublisher);\n        mockedUser = Mockito.mockConstruction(User.class);\n\n        domainRegistry = new DomainRegistry();\n        domainRegistry.setApplicationContext(applicationContext);\n\n        when(applicationContext.getBean(\"passwordService\")).thenReturn(new PasswordService());\n        when(applicationContext.getBean(\"MD5EncryptionService\")).thenReturn(encryptionService);\n        when(applicationContext.getBean(\"userRepository\")).thenReturn(userRepository);\n        when(applicationContext.getBean(\"userRegistrationRepository\")).thenReturn(userRegistrationRepository);\n\n        when(encryptionService.encryptedValue(anyString())).thenReturn(\"randomEncrypted\");\n        when(encryptionService.encryptedValue(WEAK_PASS)).thenReturn(\"weekPassEncrypted\");\n        when(encryptionService.encryptedValue(StaticFields.PASSWORD)).thenReturn(\"currentPassEncrypted\");\n        when(encryptionService.encryptedValue(StaticFields.NEW_PASS)).thenReturn(\"newPassEncrypted\");\n\n        when(userRegistrationRepository.countByEmailAndStatus(any(), any())).thenReturn(Long.valueOf(0));\n        when(userRepository.findByEmail(any())).thenReturn(null);\n\n        setUpIsDone = true;\n    }\n\n    @AfterEach\n    public void after() {\n        mockedUser.close();\n        publisher.close();\n        Mockito.reset(domainEventPublisher);\n    }\n\n    @Order(1)\n    @Test\n    public void testCreateUserRegistration() {\n        UserRegistration ur = userRegistration();\n\n        assertEquals(ur.getEmail(), StaticFields.USER_EMAIL);\n        assertEquals(ur.getFirstName(), StaticFields.USER_FIRST_NAME);\n        assertEquals(ur.getLastName(), StaticFields.USER_LAST_NAME);\n        assertEquals(ur.getStatus(), UserRegistrationStatus.WaitingForConfirmation);\n        assertNotEquals(ur.getPassword(), StaticFields.PASSWORD);\n        assertNotNull(ur.getConfirmationCode());\n\n        verify(domainEventPublisher, times(1)).publish(isA(UserRegistrationRequested.class));\n    }\n\n    @Test\n    @Order(2)\n    public void testCreateUserFromUserRegistration() {\n        UserId userId = new UserId(UUID.randomUUID());\n        when(userRepository.nextIdentity()).thenReturn(userId);\n\n        UserRegistration ur = userRegistration();\n        ur.createUser(userRepository);\n\n        assertEquals(ur.getStatus(), UserRegistrationStatus.Confirmed);\n        assertEquals(ur.getUserId(), userId);\n        verify(domainEventPublisher, times(1)).publish(isA(UserRegistrationConfirmed.class));\n    }\n\n    @Test\n    @Order(3)\n    public void testCreateRecoveryCodeAndRecoverPassword() {\n        UserId userId = new UserId(UUID.randomUUID());\n        when(userRepository.nextIdentity()).thenReturn(userId);\n\n        UserRegistration ur = userRegistration();\n        ur.createUser(userRepository);\n\n        String recoveryCode = ur.createRecoveryCode();\n\n        assertNotNull(ur.getRecoveryCode());\n        assertTrue(ur.getRecoveryCode().length() > 0);\n        assertNotNull(ur.getRecoveryCodeExpirationDate());\n        assertTrue(ur.getRecoveryCodeExpirationDate().isAfter(LocalDateTime.now()));\n\n        verify(domainEventPublisher, times(1)).publish(isA(PasswordRecoveryCodeCreated.class));\n\n        assertThrows(RuntimeException.class, () -> {\n            ur.changePasswordWithRecoveryCode(recoveryCode, StaticFields.NEW_PASS, StaticFields.PASSWORD); //repeted pass not equal\n        });\n\n        assertThrows(RuntimeException.class, () -> {\n            ur.changePasswordWithRecoveryCode(recoveryCode, StaticFields.PASSWORD, StaticFields.PASSWORD); //same pass\n        });\n\n        assertThrows(RuntimeException.class, () -> {\n            ur.changePasswordWithRecoveryCode(recoveryCode, WEAK_PASS, WEAK_PASS); //weak pass\n        });\n\n        assertThrows(RuntimeException.class, () -> {\n            ur.changePasswordWithRecoveryCode(recoveryCode, StaticFields.USER_EMAIL, StaticFields.USER_EMAIL); //pass not equal to email\n        });\n\n        ur.changePasswordWithRecoveryCode(recoveryCode, StaticFields.NEW_PASS, StaticFields.NEW_PASS);\n        verify(domainEventPublisher, times(1)).publish(isA(PasswordRecovered.class));\n    }\n\n    @Test\n    @Order(4)\n    public void testChangePassword() {\n        UserId userId = new UserId(UUID.randomUUID());\n        when(userRepository.nextIdentity()).thenReturn(userId);\n\n        UserRegistration ur = userRegistration();\n        ur.createUser(userRepository);\n\n        String oldPassword = ur.getPassword();\n\n        assertThrows(RuntimeException.class, () -> {\n            ur.changePassword(StaticFields.PASSWORD, StaticFields.NEW_PASS, StaticFields.PASSWORD); //repeted pass not equal\n        });\n\n        assertThrows(RuntimeException.class, () -> {\n            ur.changePassword(StaticFields.PASSWORD, StaticFields.PASSWORD, StaticFields.PASSWORD); //same pass\n        });\n\n        assertThrows(RuntimeException.class, () -> {\n            ur.changePassword(StaticFields.PASSWORD, WEAK_PASS, WEAK_PASS); //weak pass\n        });\n\n        assertThrows(RuntimeException.class, () -> {\n            ur.changePassword(StaticFields.PASSWORD, StaticFields.USER_EMAIL, StaticFields.USER_EMAIL); //pass not equal to email\n        });\n\n        ur.changePassword(StaticFields.PASSWORD, StaticFields.NEW_PASS, StaticFields.NEW_PASS);\n\n        assertNotEquals(oldPassword, ur.getPassword());\n        assertEquals(this.encryptionService.encryptedValue(StaticFields.NEW_PASS), ur.getPassword());\n\n        verify(domainEventPublisher, times(1)).publish(isA(PasswordChanged.class));\n    }\n\n    private UserRegistration userRegistration() {\n        return UserRegistration.registerNewUser(\n                StaticFields.PASSWORD,\n                StaticFields.USER_EMAIL,\n                StaticFields.USER_FIRST_NAME,\n                StaticFields.USER_LAST_NAME);\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/unit/domain/registration/rules/PasswordRecoveryCodeShouldBeExpiredOrNullTest.java",
    "content": "package com.tomo.mcauthentication.unit.domain.registration.rules;\n\nimport com.tomo.mcauthentication.domain.registration.UserRegistration;\nimport com.tomo.mcauthentication.domain.registration.rules.PasswordRecoveryCodeShouldBeExpiredOrNull;\nimport com.tomo.mcauthentication.unit.domain.AbstractUnitTest;\nimport org.junit.Test;\n\nimport java.time.LocalDateTime;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\npublic class PasswordRecoveryCodeShouldBeExpiredOrNullTest extends AbstractUnitTest {\n\n    @Test\n    public void testRuleIsNotBroken() {\n        UserRegistration userRegistration = new UserRegistration();\n        userRegistration.setRecoveryCodeExpirationDate(LocalDateTime.now().minusSeconds(60));\n\n        assertTrue((new PasswordRecoveryCodeShouldBeExpiredOrNull(userRegistration)).isRuleComplied());\n        assertTrue((new PasswordRecoveryCodeShouldBeExpiredOrNull(new UserRegistration())).isRuleComplied());\n    }\n\n    @Test\n    public void testRuleIsBroken() {\n        UserRegistration userRegistration = new UserRegistration();\n        userRegistration.setRecoveryCodeExpirationDate(LocalDateTime.now().plusSeconds(60));\n        userRegistration.setRecoveryCode(\"123\");\n\n        assertFalse((new PasswordRecoveryCodeShouldBeExpiredOrNull(userRegistration)).isRuleComplied());\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/unit/domain/registration/rules/PasswordRecoveryCodeShouldNotExpiredTest.java",
    "content": "package com.tomo.mcauthentication.unit.domain.registration.rules;\n\nimport com.tomo.mcauthentication.domain.registration.UserRegistration;\nimport com.tomo.mcauthentication.domain.registration.rules.PasswordRecoveryCodeShouldNotExpired;\nimport com.tomo.mcauthentication.unit.domain.AbstractUnitTest;\nimport org.junit.Test;\n\nimport java.time.LocalDateTime;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\npublic class PasswordRecoveryCodeShouldNotExpiredTest extends AbstractUnitTest {\n\n    @Test\n    public void testRuleIsNotBroken() {\n        UserRegistration userRegistration = new UserRegistration();\n        userRegistration.setRecoveryCodeExpirationDate(LocalDateTime.now().plusSeconds(60));\n        assertTrue((new PasswordRecoveryCodeShouldNotExpired(userRegistration)).isRuleComplied());\n    }\n\n    @Test\n    public void testRuleIsBroken() {\n        UserRegistration userRegistration = new UserRegistration();\n        userRegistration.setRecoveryCodeExpirationDate(LocalDateTime.now());\n\n        assertFalse((new PasswordRecoveryCodeShouldNotExpired(userRegistration)).isRuleComplied());\n        assertFalse((new PasswordRecoveryCodeShouldNotExpired(new UserRegistration())).isRuleComplied());\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/unit/domain/registration/rules/PasswordsMustMatchTest.java",
    "content": "package com.tomo.mcauthentication.unit.domain.registration.rules;\n\nimport com.tomo.mcauthentication.domain.registration.rules.PasswordsMustMatch;\nimport com.tomo.mcauthentication.unit.domain.AbstractUnitTest;\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\npublic class PasswordsMustMatchTest extends AbstractUnitTest {\n\n    @Test\n    public void testRuleIsNotBroken() {\n        assertTrue((new PasswordsMustMatch(\"abc\", \"abc\")).isRuleComplied());\n    }\n\n    @Test\n    public void testRuleIsBroken() {\n        assertFalse((new PasswordsMustMatch(\"abc1\", \"abc\")).isRuleComplied());\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/unit/domain/registration/rules/RecoveryCodeMustMatchTest.java",
    "content": "package com.tomo.mcauthentication.unit.domain.registration.rules;\n\nimport com.tomo.mcauthentication.domain.registration.rules.RecoveryCodeMustMatch;\nimport com.tomo.mcauthentication.unit.domain.AbstractUnitTest;\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\npublic class RecoveryCodeMustMatchTest extends AbstractUnitTest {\n\n    @Test\n    public void testRuleIsNotBroken() {\n        assertTrue((new RecoveryCodeMustMatch(\"abc\", \"abc\")).isRuleComplied());\n    }\n\n    @Test\n    public void testRuleIsBroken() {\n        assertFalse((new RecoveryCodeMustMatch(\"abc1\", \"abc\")).isRuleComplied());\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/unit/domain/registration/rules/UserRegistrationCannotBeConfirmedAfterExpirationTest.java",
    "content": "package com.tomo.mcauthentication.unit.domain.registration.rules;\n\nimport com.tomo.mcauthentication.domain.registration.rules.UserRegistrationCannotBeConfirmedAfterExpiration;\nimport com.tomo.mcauthentication.unit.domain.AbstractUnitTest;\nimport org.junit.Test;\n\nimport java.time.LocalDateTime;\n\nimport static com.tomo.mcauthentication.domain.registration.rules.UserRegistrationCannotBeConfirmedAfterExpiration.CONFIRMATION_LINK_DURATION;\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\npublic class UserRegistrationCannotBeConfirmedAfterExpirationTest extends AbstractUnitTest {\n\n    @Test\n    public void testRuleIsNotBroken() {\n        LocalDateTime registerDate1 = LocalDateTime.now();\n        assertTrue((new UserRegistrationCannotBeConfirmedAfterExpiration(registerDate1)).isRuleComplied());\n\n        LocalDateTime registerDate2 = LocalDateTime.now().minusDays(CONFIRMATION_LINK_DURATION).plusSeconds(5);\n        assertTrue((new UserRegistrationCannotBeConfirmedAfterExpiration(registerDate2)).isRuleComplied());\n    }\n\n    @Test\n    public void testRuleIsBroken() {\n        LocalDateTime registerDate1 = LocalDateTime.now().minusDays(CONFIRMATION_LINK_DURATION);\n        assertFalse((new UserRegistrationCannotBeConfirmedAfterExpiration(registerDate1)).isRuleComplied());\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/unit/domain/registration/rules/UserRegistrationCannotBeConfirmedMoreThanOnceTest.java",
    "content": "package com.tomo.mcauthentication.unit.domain.registration.rules;\n\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationStatus;\nimport com.tomo.mcauthentication.domain.registration.rules.UserRegistrationCannotBeConfirmedMoreThanOnce;\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\npublic class UserRegistrationCannotBeConfirmedMoreThanOnceTest {\n    @Test\n    public void testRuleIsNotBroken() {\n        assertTrue((new UserRegistrationCannotBeConfirmedMoreThanOnce(UserRegistrationStatus.WaitingForConfirmation)).isRuleComplied());\n        assertTrue((new UserRegistrationCannotBeConfirmedMoreThanOnce(UserRegistrationStatus.Expired)).isRuleComplied());\n    }\n\n    @Test\n    public void testRuleIsBroken() {\n        assertFalse((new UserRegistrationCannotBeConfirmedMoreThanOnce(UserRegistrationStatus.Confirmed)).isRuleComplied());\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/unit/domain/registration/rules/UserRegistrationMustBeConfirmedTest.java",
    "content": "package com.tomo.mcauthentication.unit.domain.registration.rules;\n\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationStatus;\nimport com.tomo.mcauthentication.domain.registration.rules.UserRegistrationMustBeConfirmed;\nimport org.junit.Test;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\npublic class UserRegistrationMustBeConfirmedTest {\n\n    @Test\n    public void testRuleIsNotBroken() {\n        assertTrue((new UserRegistrationMustBeConfirmed(UserRegistrationStatus.Confirmed)).isRuleComplied());\n    }\n\n    @Test\n    public void testRuleIsBroken() {\n        assertFalse((new UserRegistrationMustBeConfirmed(UserRegistrationStatus.WaitingForConfirmation)).isRuleComplied());\n        assertFalse((new UserRegistrationMustBeConfirmed(UserRegistrationStatus.Expired)).isRuleComplied());\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/unit/domain/registration/rules/UserRegistrationMustBeUniqueTest.java",
    "content": "package com.tomo.mcauthentication.unit.domain.registration.rules;\n\nimport com.tomo.mcauthentication.domain.registration.UserRegistrationRepository;\nimport com.tomo.mcauthentication.domain.registration.rules.UserRegistrationMustBeUnique;\nimport com.tomo.mcauthentication.unit.domain.AbstractUnitTest;\nimport org.junit.Test;\nimport org.mockito.Mockito;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\nimport static org.mockito.Mockito.any;\nimport static org.mockito.Mockito.when;\n\npublic class UserRegistrationMustBeUniqueTest extends AbstractUnitTest {\n\n    UserRegistrationRepository repository = Mockito.mock(UserRegistrationRepository.class);\n\n    @Test\n    public void testRuleIsNotBroken() {\n        when(repository.countByEmailAndStatus(any(), any())).thenReturn(0L);\n        assertTrue((new UserRegistrationMustBeUnique(repository, \"\")).isRuleComplied());\n    }\n\n    @Test\n    public void testRuleIsBroken() {\n        when(repository.countByEmailAndStatus(any(), any())).thenReturn(1L);\n        assertFalse((new UserRegistrationMustBeUnique(repository, \"\")).isRuleComplied());\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/unit/domain/session/rules/SessionCannotBeExpiredWhenRefreshTokenIsMissingTest.java",
    "content": "package com.tomo.mcauthentication.unit.domain.session.rules;\n\nimport com.tomo.mcauthentication.domain.session.Session;\nimport com.tomo.mcauthentication.domain.session.rule.SessionCannotBeExpiredWhenRefreshTokenIsMissing;\nimport com.tomo.mcauthentication.unit.domain.AbstractUnitTest;\nimport org.junit.Test;\n\nimport java.time.LocalDateTime;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\n\npublic class SessionCannotBeExpiredWhenRefreshTokenIsMissingTest extends AbstractUnitTest {\n\n    @Test\n    public void testRuleIsNotBroken() {\n        Session session1 = new Session();\n        session1.setExpirationDate(LocalDateTime.now().plusDays(2));\n\n\n        Session session2 = new Session();\n        session2.setExpirationDate(LocalDateTime.now().minusDays(2));\n        session2.setRefreshToken(\"randomToken\");\n\n        assertTrue((new SessionCannotBeExpiredWhenRefreshTokenIsMissing(session1)).isRuleComplied());\n        assertTrue((new SessionCannotBeExpiredWhenRefreshTokenIsMissing(session2)).isRuleComplied());\n    }\n\n    @Test\n    public void testRuleIsBroken() {\n        Session session1 = new Session();\n        session1.setExpirationDate(LocalDateTime.now().minusDays(2));\n\n        assertFalse((new SessionCannotBeExpiredWhenRefreshTokenIsMissing(session1)).isRuleComplied());\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/unit/domain/user/rules/UserEmailMustBeUniqueTest.java",
    "content": "package com.tomo.mcauthentication.unit.domain.user.rules;\n\nimport com.tomo.mcauthentication.domain.users.User;\nimport com.tomo.mcauthentication.domain.users.UserRepository;\nimport com.tomo.mcauthentication.domain.users.rules.UserEmailMustBeUnique;\nimport com.tomo.mcauthentication.unit.domain.AbstractUnitTest;\nimport org.junit.Test;\nimport org.mockito.Mockito;\n\nimport static org.junit.Assert.assertFalse;\nimport static org.junit.Assert.assertTrue;\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.when;\n\npublic class UserEmailMustBeUniqueTest extends AbstractUnitTest {\n\n    UserRepository repository = Mockito.mock(UserRepository.class);\n\n    @Test\n    public void testRuleIsNotBroken() {\n        when(repository.findByEmail(any())).thenReturn(null);\n        assertTrue((new UserEmailMustBeUnique(repository, \"random@email.com\")).isRuleComplied());\n    }\n\n    @Test\n    public void testRuleIsBroken() {\n        when(repository.findByEmail(any())).thenReturn(new User());\n        assertFalse((new UserEmailMustBeUnique(repository, \"random@email.com\")).isRuleComplied());\n    }\n\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/weblayer/BaseWebLayerTest.java",
    "content": "package com.tomo.mcauthentication.weblayer;\n\nimport org.junit.runner.RunWith;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.context.annotation.Profile;\nimport org.springframework.test.context.TestPropertySource;\nimport org.springframework.test.context.junit4.SpringRunner;\n\n@RunWith(SpringRunner.class)\n@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)\npublic abstract class BaseWebLayerTest { }\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/weblayer/springboot/controller/AbstractControllerTest.java",
    "content": "package com.tomo.mcauthentication.weblayer.springboot.controller;\n\nimport com.tomo.ddd.email.EmailSender;\n\nimport com.tomo.mcauthentication.weblayer.BaseWebLayerTest;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;\nimport org.springframework.boot.test.mock.mockito.MockBean;\nimport org.springframework.boot.web.server.LocalServerPort;\nimport org.springframework.http.HttpHeaders;\nimport org.springframework.test.web.servlet.MockMvc;\n\nimport java.net.URI;\nimport java.net.URISyntaxException;\n\n@AutoConfigureMockMvc\npublic abstract class AbstractControllerTest extends BaseWebLayerTest {\n\n    @MockBean\n    protected EmailSender emailMessageSender;\n\n    @LocalServerPort\n    protected int randomServerPort;\n\n    @Autowired\n    protected MockMvc mockMvc;\n\n    protected URI url(String uri) throws URISyntaxException {\n        final String baseUrl = \"http://localhost:\" + randomServerPort+ uri;\n        return new URI(baseUrl);\n    }\n\n    protected HttpHeaders baseHeaders() {\n        HttpHeaders headers =  new org.springframework.http.HttpHeaders();\n        headers.set(\"X-COM-PERSIST\", \"true\");\n        return headers;\n    }\n}\n"
  },
  {
    "path": "src/test/java/com/tomo/mcauthentication/weblayer/springboot/controller/RegistrationControllerTest.java",
    "content": "package com.tomo.mcauthentication.weblayer.springboot.controller;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.tomo.mcauthentication.application.registration.command.RegisterNewUserCommand;\nimport com.tomo.mcauthentication.infrastructure.springboot.controller.RestApiRoutes.RegistrationRoutes;\nimport com.tomo.mcauthentication.testdata.CommandObjectMother;\n\nimport org.junit.Test;\nimport org.springframework.beans.factory.annotation.Autowired;\n\nimport javax.transaction.Transactional;\n\nimport static org.springframework.http.MediaType.APPLICATION_JSON;\nimport static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;\nimport static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\n\npublic class RegistrationControllerTest extends AbstractControllerTest {\n\n    @Autowired\n    private ObjectMapper objectMapper;\n\n    @Test\n    @Transactional\n    public void shouldCreateUserRegistration() throws Exception {\n        RegisterNewUserCommand command = CommandObjectMother.registerNewUserCommandWithFakerEmail();\n        this.mockMvc.perform(\n                post(RegistrationRoutes.FORM_REGISTRATION)\n                        .contentType(APPLICATION_JSON)\n                        .content(objectMapper.writeValueAsString(command)))\n                .andDo(print())\n                .andExpect(status().isCreated());\n    }\n}\n"
  },
  {
    "path": "src/test/resources/application-ci.yml",
    "content": "debug: true\n\nspring:\n  datasource:\n    url: jdbc:postgresql://mc-authentication-db-test:5432/mc_authentication"
  }
]