Skip to content

Commit

Permalink
copilot support
Browse files Browse the repository at this point in the history
  • Loading branch information
dataswifty committed Feb 8, 2024
1 parent 7a525e2 commit 6dc5090
Show file tree
Hide file tree
Showing 29 changed files with 320 additions and 75 deletions.
39 changes: 38 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1 +1,38 @@
FROM ghcr.io/dataswift/base:v0.3.5
FROM adoptopenjdk/openjdk11:jdk-11.0.6_10-alpine

ARG FILE_PATH
ENV FILE_PATH=$FILE_PATH
ARG STRING
ENV STRING=$STRING
ARG DELIMITER
ENV DELIMITER=$DELIMITER
ARG KEYWORD
ENV KEYWORD=$KEYWORD

ARG SBT_VERSION=1.3.10

RUN set -x \
&& apk --update add --no-cache --virtual .build-deps curl \
&& ESUM="3060065764193651aa3fe860a17ff8ea9afc1e90a3f9570f0584f2d516c34380" \
&& SBT_URL="https://github.com/sbt/sbt/releases/download/v1.3.10/sbt-1.3.10.tgz" \
&& apk add bash \
&& curl -Ls ${SBT_URL} > /tmp/sbt-${SBT_VERSION}.tgz \
&& sha256sum /tmp/sbt-${SBT_VERSION}.tgz \
&& (echo "${ESUM} /tmp/sbt-${SBT_VERSION}.tgz" | sha256sum -c -) \
&& tar -zxf /tmp/sbt-${SBT_VERSION}.tgz -C /opt/ \
&& sed -i -r 's#run \"\$\@\"#unset JAVA_TOOL_OPTIONS\nrun \"\$\@\"#g' /opt/sbt/bin/sbt \
&& apk del --purge .build-deps \
&& rm -rf /tmp/sbt-${SBT_VERSION}.tgz /var/cache/apk/*


ENV PATH="/opt/sbt/bin:$PATH" \
JAVA_OPTS="-XX:+UseContainerSupport -Dfile.encoding=UTF-8" \
SBT_OPTS="-Xmx2048M -Xss2M"

WORKDIR /app
ADD . /app

RUN ["chmod", "-R", "777", "start.sh"]

CMD ./start.sh

1 change: 1 addition & 0 deletions copilot/.workspace
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
application: hat-application
21 changes: 21 additions & 0 deletions copilot/environments/staging/manifest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# The manifest for the "staging" environment.
# Read the full specification for the "Environment" type at:
# https://aws.github.io/copilot-cli/docs/manifest/environment/

# Your environment name will be used in naming your resources like VPC, cluster, etc.
name: staging
type: Environment

# Import your own VPC and subnets or configure how they should be created.
# network:
# vpc:
# id:

# Configure the load balancers in your environment, once created.
# http:
# public:
# private:

# Configure observability for your environment resources.
observability:
container_insights: false
41 changes: 41 additions & 0 deletions copilot/hat-service/manifest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# The manifest for the "hat-service" service.
# Read the full specification for the "Load Balanced Web Service" type at:
# https://aws.github.io/copilot-cli/docs/manifest/lb-web-service/

name: hat-service
type: Load Balanced Web Service

# Distribute traffic to your service.
http:
path: '/'
healthcheck:
path: '/'
success_codes: '200,301'
healthy_threshold: 3
unhealthy_threshold: 2
interval: 30s
timeout: 10s
grace_period: 5m
deregistration_delay: 5s

image:
build: Dockerfile
port: 9000

cpu: 4096 # Number of CPU units for the task.
memory: 8192 # Amount of memory in MiB used by the task.
count: 1 # Number of tasks that should be running in your service.
exec: true # Enable running commands in your container.
network:
connect: true # Enable Service Connect for intra-environment traffic between services.

variables: # Pass environment variables as key value pairs.
LOG_LEVEL: debug


# You can override any of the values defined above by environment.
environments:
staging:
count: 1 # Number of tasks to run for the "test" environment.
deployment: # The deployment strategy for the "test" environment.
rolling: 'recreate' # Stops existing tasks before new ones are started for faster deployments.
47 changes: 42 additions & 5 deletions hat/app/org/hatdex/hat/api/controllers/Authentication.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ import java.net.{ URLDecoder, URLEncoder }
import javax.inject.Inject
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import com.mohiva.play.silhouette.api.LoginInfo
import org.checkerframework.checker.units.qual.A

class Authentication @Inject() (
components: ControllerComponents,
Expand All @@ -77,9 +79,9 @@ class Authentication @Inject() (

import HatJsonFormats._

private val indefiniteSuccessCaching: CachedBuilder = cached
.status(req => s"${req.host}${req.path}", 200)
.includeStatus(404, 600)
// private val indefiniteSuccessCaching: CachedBuilder = cached
// .status(req => s"${req.host}${req.path}", 200)
// .includeStatus(404, 600)

private val emailScheme = "https://"

Expand Down Expand Up @@ -134,12 +136,18 @@ class Authentication @Inject() (
)

def publicKey(): EssentialAction =
indefiniteSuccessCaching {
UserAwareAction.async { implicit request =>
// indefiniteSuccessCaching {
UserAwareAction.async { implicit request => {
logger.info(s"request: ${request.toString()}")
logger.info(s"dynEnv : ${request.dynamicEnvironment.toString()}")

val publicKey =
hatServerProvider.toString(request.dynamicEnvironment.publicKey)


Future.successful(Ok(publicKey))
}
// }
}

// TODO: Should this remove tokens?
Expand Down Expand Up @@ -196,21 +204,48 @@ class Authentication @Inject() (
// Trade username and password for an access_token
def accessToken(): Action[AnyContent] =
(UserAwareAction andThen limiter.UserAwareRateLimit).async { implicit request =>

// pull details from the headers
val eventuallyAuthenticatedUser = for {
usernameParam <- request.headers.get("username")
passwordParam <- request.headers.get("password")
} yield {
val username = URLDecoder.decode(usernameParam, "UTF-8")
val password = URLDecoder.decode(passwordParam, "UTF-8")

logger.info(s"Processing login request for user ${username}")
logger.info(s"Processing login request for pass ${password}")
logger.info(s"request: ${request}")

logger.info(s"About to run credentialsProvider.authenticate")
val credentials = Credentials(username, password)

val authenticated = credentialsProvider.authenticate(credentials).flatMap { (o) =>
logger.info(s"loginInfo: $o")
Future.successful("WTF")
}
logger.info(s"authenticated: ${authenticated}")

// val authenticated = Future.await (credentialsProvider.authenticate(Credentials(username, password)))
// flatMap { loginInfo: LoginInfo =>
// logger.info(s"loginInfo: $loginInfo")
// logger.info(s"loginInfo.providerID: ${loginInfo.providerID}")
// Future.failed(new IdentityNotFoundException("Broken"))
// }

credentialsProvider
.authenticate(Credentials(username, password))
.map(_.copy(request.dynamicEnvironment.id))
.flatMap { loginInfo =>

logger.info(s"User ${username} authenticated");
logger.info(s"loginInfo ${loginInfo}");

userService.getUser(loginInfo.providerKey).flatMap {
// If we find a user, create and return an access token (JWT)
case Some(user) =>
val customClaims = hatServicesService.generateUserTokenClaims(user, hatService)

for {
// JWT Authenticator
authenticator <- env.authenticatorService.create(loginInfo)
Expand Down Expand Up @@ -244,6 +279,7 @@ class Authentication @Inject() (
// AuthenticatorResult
result
}

// No user found
case None =>
Future.failed(new IdentityNotFoundException("Couldn't find user"))
Expand Down Expand Up @@ -333,6 +369,7 @@ class Authentication @Inject() (
// Store that token
tokenService.create(token).map { _ =>
mailer.passwordReset(email, passwordResetLink(request.host, token.id))

response
}
// The user was not found, but return the "If we found an email address, we'll send the link."
Expand Down
10 changes: 5 additions & 5 deletions hat/app/org/hatdex/hat/api/controllers/SystemStatus.scala
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,18 @@ class SystemStatus @Inject() (

private val logger = Logger(this.getClass)

private val indefiniteSuccessCaching = cached
.status(req => s"${req.host}${req.path}", 200)
.includeStatus(404, 600)
// private val indefiniteSuccessCaching = cached
// .status(req => s"${req.host}${req.path}", 200)
// .includeStatus(404, 600)

def update(): EssentialAction =
indefiniteSuccessCaching {
// indefiniteSuccessCaching {
UserAwareAction.async { implicit request =>
logger.debug(s"Updating HAT ${request.dynamicEnvironment.id}")
hatDatabaseProvider.update(request.dynamicEnvironment.db) map { _ =>
Ok(Json.toJson(SuccessResponse("Database updated")))
}
}
// }
}

def healthReport(): Action[AnyContent] = {
Expand Down
83 changes: 55 additions & 28 deletions hat/app/org/hatdex/hat/api/service/UserServiceImpl.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,35 +51,62 @@ class UserServiceImpl @Inject() (
override def listUsers()(implicit server: HatServer): Future[Seq[HatUser]] =
queryUser(UserUser)

override def getUser(userId: UUID)(implicit server: HatServer): Future[Option[HatUser]] =
cache
.get[HatUser](s"${server.domain}:user:$userId")
.flatMap {
case Some(cached) => Future.successful(Some(cached))
case None =>
queryUser(UserUser.filter(_.userId === userId))
.map(_.headOption)
.andThen({
case Success(Some(u)) =>
cache.set(s"${server.domain}:user:${u.userId}", u)
cache.set(s"${server.domain}:user:${u.email}", u)
})
}
override def getUser(userId: UUID)(implicit server: HatServer): Future[Option[HatUser]] = {
logger.info(s"Getting user $userId @${server.domain}")

queryUser(UserUser.filter(_.userId === userId))
.map(_.headOption)
.andThen({
case Success(Some(u)) => {
logger.info(s"setting the cache for ${u.email}")
cache.set(s"${server.domain}:user:${u.userId}", u)
cache.set(s"${server.domain}:user:${u.email}", u)
}
})

override def getUser(username: String)(implicit server: HatServer): Future[Option[HatUser]] =
cache
.get[HatUser](s"${server.domain}:user:$username")
.flatMap {
case Some(cached) => Future.successful(Some(cached))
case None =>
queryUser(UserUser.filter(_.email === username))
.map(_.headOption)
.andThen({
case Success(Some(u)) =>
cache.set(s"${server.domain}:user:${u.userId}", u)
cache.set(s"${server.domain}:user:${u.email}", u)
})
}
// cache
// .get[HatUser](s"${server.domain}:user:$userId")
// .flatMap {
// case Some(cached) => Future.successful(Some(cached))
// case None =>
// queryUser(UserUser.filter(_.userId === userId))
// .map(_.headOption)
// .andThen({
// case Success(Some(u)) => {
// logger.info(s"setting the cache for ${u.email}")
// cache.set(s"${server.domain}:user:${u.userId}", u)
// cache.set(s"${server.domain}:user:${u.email}", u)
// }
// })
// }

}

override def getUser(username: String)(implicit server: HatServer): Future[Option[HatUser]] = {
logger.info(s"Getting username $username @${server.domain}")

queryUser(UserUser.filter(_.email === username))
.map(_.headOption)
.andThen({
case Success(Some(u)) =>
cache.set(s"${server.domain}:user:${u.userId}", u)
cache.set(s"${server.domain}:user:${u.email}", u)
})

// cache
// .get[HatUser](s"${server.domain}:user:$username")
// .flatMap {
// case Some(cached) => Future.successful(Some(cached))
// case None =>
// queryUser(UserUser.filter(_.email === username))
// .map(_.headOption)
// .andThen({
// case Success(Some(u)) =>
// cache.set(s"${server.domain}:user:${u.userId}", u)
// cache.set(s"${server.domain}:user:${u.email}", u)
// })
// }
}

def getUserByRole(
role: UserRole
Expand Down
5 changes: 4 additions & 1 deletion hat/app/org/hatdex/hat/authentication/HatApiController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,11 @@ abstract class HatController[T <: HatAuthEnvironment](
silhouette.securedAction(env)
def UnsecuredAction: UnsecuredActionBuilder[T, AnyContent] =
silhouette.unsecuredAction(env)
def UserAwareAction: UserAwareActionBuilder[T, AnyContent] =
def UserAwareAction: UserAwareActionBuilder[T, AnyContent] = {
println("UserAwareAction")
// println(s"env: ${env}")
silhouette.userAwareAction(env)
}

implicit def securedRequest2User[A](
implicit request: SecuredRequest[T, A]): HatUser = request.identity
Expand Down
1 change: 1 addition & 0 deletions hat/app/org/hatdex/hat/modules/AppModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import javax.inject.{ Singleton => JSingleton }
class AppModule extends ScalaModule {

override def configure(): Unit = {
println("*** AppModule.configure() ***")
bind[UserService].to[UserServiceImpl].in(classOf[JSingleton])
bind[ContractAction].to[ContractActionImpl].in(classOf[JSingleton])
}
Expand Down
1 change: 1 addition & 0 deletions hat/app/org/hatdex/hat/modules/DataMonitoringModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import play.api.libs.concurrent.AkkaGuiceSupport
class DataMonitoringModule extends AbstractModule with ScalaModule with AkkaGuiceSupport {

override protected def configure(): Unit = {
println("*** DataMonitoringModule.configure() ***")
bindActor[HatDataStatsProcessorActor]("hatDataStatsProcessor")
bind[HatDataEventRouter].to[HatDataEventRouterImpl].asEagerSingleton()
()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ class DevHatInitializationModule extends ScalaModule with AkkaGuiceSupport {
/**
* Configures the module.
*/
override protected def configure(): Unit =
override protected def configure(): Unit = {
println("*** DevHatInitializationModule.configure() ***")
bind[DevHatInitializer].asEagerSingleton()
}
}

class DevHatInitializer @Inject() (
Expand All @@ -57,7 +59,8 @@ class DevHatInitializer @Inject() (
import DevHatConfig.configLoader

val devHats: Map[String, DevHatConfig] = configuration.get[Map[String, DevHatConfig]]("devhats")
val devHatMigrations: Seq[String] = configuration.get[Seq[String]]("devhatMigrations")
// val devHatMigrations: Seq[String] = configuration.get[Seq[String]]("devhatMigrations")
val devHatMigrations: Seq[String] = Seq.empty

logger.info(s"Initializing HATs: $devHats")
devHats.values.map(initializeHat)
Expand Down
1 change: 1 addition & 0 deletions hat/app/org/hatdex/hat/modules/FileManagerModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import javax.inject.{ Singleton => JSingleton }
class FileManagerModule extends ScalaModule {

override def configure(): Unit = {
println("*** FileManagerModule.configure() ***")
bind[FileUploadService].to[FileUploadServiceImpl]
bind[FileMetadataRepository].to[FileMetadataRepositorySlick]
bind[FileManager].to[FileManagerS3]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import play.api.{ Configuration, Environment }
class HatServerProviderModule extends AbstractModule with ScalaModule with AkkaGuiceSupport {

override def configure(): Unit = {
println("*** HatServerProviderModule.configure() ***")
bindActor[HatServerProviderActor]("hatServerProviderActor")
bindActorFactory[HatServerActor, HatServerActor.Factory]

Expand Down
Loading

0 comments on commit 6dc5090

Please sign in to comment.