Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add all tables #8

Merged
merged 12 commits into from
Nov 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .bsp/sbt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"name":"sbt","version":"1.9.7","bspVersion":"2.1.0-M1","languages":["scala"],"argv":["/usr/lib/jvm/java-17-amazon-corretto/bin/java","-Xms100m","-Xmx100m","-classpath","/home/jcole/.cache/sbt/boot/sbt-launch/1.9.7/sbt-launch-1.9.7.jar","-Dsbt.script=/usr/bin/sbt","xsbt.boot.Boot","-bsp"]}
18 changes: 7 additions & 11 deletions app/com/coleji/neptune/API/CacheableResult.scala
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,10 @@ trait CacheableResult[T <: ParamsObject, U] {
CacheableResult.resultMap.remove(cacheKey)
}
})
p.future.onFailure({
case _: Throwable => {
CacheableResult.waiting(cacheKey) -= p
if (CacheableResult.waiting(cacheKey).isEmpty) {
CacheableResult.resultMap.remove(cacheKey)
}
p.future.failed.foreach(e => {
CacheableResult.waiting(cacheKey) -= p
if (CacheableResult.waiting(cacheKey).isEmpty) {
CacheableResult.resultMap.remove(cacheKey)
}
})
p.future
Expand All @@ -129,11 +127,9 @@ trait CacheableResult[T <: ParamsObject, U] {
println("done son; completing all queued")
result
}))
p.future.onFailure({
case _: Throwable => {
println("Failure detected; cleaning up")
CacheableResult.inUse.remove(cacheKey)
}
p.future.failed.foreach(e => {
println("Failure detected; cleaning up")
CacheableResult.inUse.remove(cacheKey)
})
p.future
}
Expand Down
4 changes: 2 additions & 2 deletions app/com/coleji/neptune/API/ResultError.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ case class ResultError (
case class ParseError(
code: String,
message: String,
parseErrors: Seq[(String, Seq[String])]
parseErrors: collection.Seq[(String, collection.Seq[String])]
) {
implicit val format = Json.format[ParseError]
def asJsObject: JsObject = JsObject(Map("error" -> Json.toJson(this)))
Expand All @@ -37,7 +37,7 @@ object ResultError {
message="JSON parameters were not correct."
)

val PARSE_FAILURE: Seq[(JsPath, Seq[JsonValidationError])] => JsObject = (errors: Seq[(JsPath, Seq[JsonValidationError])]) => ParseError(
val PARSE_FAILURE: collection.Seq[(JsPath, collection.Seq[JsonValidationError])] => JsObject = (errors: collection.Seq[(JsPath, collection.Seq[JsonValidationError])]) => ParseError(
code="parse_failure",
message="Request was not valid.",
parseErrors=errors.map(t => (t._1.toString(), t._2.flatMap(errs => errs.messages)))
Expand Down
4 changes: 2 additions & 2 deletions app/com/coleji/neptune/Core/Boot/ServerBootLoader.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package com.coleji.neptune.Core.Boot

import com.coleji.neptune.Core._
import com.coleji.neptune.Util.PropertiesWrapper
import com.redis.RedisClientPool
import play.api.inject.ApplicationLifecycle
import redis.clients.jedis.JedisPool

import scala.concurrent.Future

Expand Down Expand Up @@ -62,7 +62,7 @@ object ServerBootLoader {
println("Using DB Driver: " + dbDriver)

val dbConnection = getDBPools(dbDriver)
val redisPool = new RedisClientPool(paramFile.getOptionalString("RedisHost").getOrElse("localhost"), 6379)
val redisPool = new JedisPool(paramFile.getOptionalString("RedisHost").getOrElse("localhost"), 6379)
lifecycle match {
case Some(lc) => lc.addStopHook(() => Future.successful({
println("**************************** Stop hook: closing pools **********************")
Expand Down
2 changes: 1 addition & 1 deletion app/com/coleji/neptune/Core/CacheableFactory.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ abstract class CacheableFactory[T_KeyConfig, T_Result] {
} catch {
case e: InvalidClassException => {
val rte = new RuntimeException("****** Deserialization failed for cache key " + key, e)
Sentry.capture(rte)
Sentry.captureException(rte)
rte.printStackTrace()
populate(rc, config)
}
Expand Down
2 changes: 1 addition & 1 deletion app/com/coleji/neptune/Core/ParsedRequest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ object ParsedRequest {
} catch {
case e: Throwable => {
PA.logger.error("Failure to parse request", e)
Sentry.capture(e)
Sentry.captureException(e)
throw e
}}

Expand Down
14 changes: 7 additions & 7 deletions app/com/coleji/neptune/Core/PermissionsAuthority.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import com.coleji.neptune.Exception.{CORSException, MuteEmailException, PostBody
import com.coleji.neptune.IO.PreparedQueries.{PreparedQueryForSelect, PreparedQueryForUpdateOrDelete}
import com.coleji.neptune.Storable.{ResultSetWrapper, StorableClass, StorableObject}
import com.coleji.neptune.Util.{Initializable, PropertiesWrapper}
import com.redis.RedisClientPool
import io.sentry.Sentry
import play.api.libs.json.{JsResultException, JsValue}
import play.api.mvc.{Result, Results}
import redis.clients.jedis.JedisPool

import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
Expand All @@ -25,7 +25,7 @@ class PermissionsAuthority private[Core] (
val systemParams: SystemServerParameters,
val customParams: PropertiesWrapper,
dbGateway: DatabaseGateway,
redisPool: RedisClientPool,
redisPool: JedisPool,
paPostBoot: PropertiesWrapper => Unit,
) {
println(s"inside PermissionsAuthority constructor: test mode: ${systemParams.isTestMode}, readOnlyDatabase: ${systemParams.readOnlyDatabase}")
Expand Down Expand Up @@ -88,28 +88,28 @@ class PermissionsAuthority private[Core] (
case Success(r: Result) => Success(r)
case Failure(e: Throwable) => {
logger.error(e.getMessage, e)
Sentry.capture(e)
Sentry.captureException(e)
Success(Results.Status(400)(ResultError.UNKNOWN.asJsObject))
}
})
} catch {
case _: UnauthorizedAccessException => Future(Results.Status(400)(ResultError.UNAUTHORIZED.asJsObject))
case _: CORSException => Future(Results.Status(400)(ResultError.UNAUTHORIZED.asJsObject))
case e: PostBodyNotJSONException => {
Sentry.capture(e)
Sentry.captureException(e)
Future(Results.Status(400)(ResultError.NOT_JSON.asJsObject))
}
case e: JsResultException => {
Sentry.capture(e)
Sentry.captureException(e)
Future(Results.Status(400)(ResultError.PARSE_FAILURE(e.errors)))
}
case e: MuteEmailException => {
Sentry.capture(e)
Sentry.captureException(e)
Future(Results.Status(400)(ResultError.UNKNOWN.asJsObject))
}
case e: Throwable => {
logger.error(e.getMessage, e)
Sentry.capture(e)
Sentry.captureException(e)
Future(Results.Status(400)(ResultError.UNKNOWN.asJsObject))
}
}
Expand Down
21 changes: 15 additions & 6 deletions app/com/coleji/neptune/Core/RedisBroker.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
package com.coleji.neptune.Core

import com.redis.RedisClientPool
import redis.clients.jedis.{Jedis, JedisPool}

class RedisBroker private[Core](val clientPool: RedisClientPool) extends CacheBroker {
override def set(key: String, value: String): Unit = clientPool.withClient(c => c.set(key, value))
import scala.util.Using

override def get(key: String): Option[String] = clientPool.withClient(c => c.get(key))
class RedisBroker private[Core](val clientPool: JedisPool) extends CacheBroker {
override def set(key: String, value: String): Unit = withResource(c => c.set(key, value))

override def peek(key: String): Boolean = clientPool.withClient(c => c.strlen(key).exists(_ > 0))
override def get(key: String): Option[String] = withResource(c => Option(c.get(key)))

override def delete(key: String): Unit = clientPool.withClient(c => c.del(key))
override def peek(key: String): Boolean = withResource(c => Option(c.strlen(key)).exists(_ > 0))

override def delete(key: String): Unit = withResource(c => c.del(key))

private def withResource[T](cmd: Jedis => T): T = {
val t = Using (clientPool.getResource) { jedis =>
cmd(jedis)
}
t.get
}
}
8 changes: 4 additions & 4 deletions app/com/coleji/neptune/Core/RequestCache.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import com.coleji.neptune.Storable.Fields.DatabaseField
import com.coleji.neptune.Storable.StorableQuery.{QueryBuilder, QueryBuilderResultRow}
import com.coleji.neptune.Storable.{Filter, StorableClass, StorableObject}
import com.coleji.neptune.Util.PropertiesWrapper
import com.redis.RedisClientPool
import redis.clients.jedis.JedisPool

// TODO: Some sort of security on the CacheBroker so arbitrary requests can't see the authentication tokens
// TODO: mirror all PB methods on RC so the RC can either pull from redis or dispatch to oracle etc
sealed abstract class RequestCache private[Core](
val userName: String,
serverParams: PropertiesWrapper,
dbGateway: DatabaseGateway,
redisPool: RedisClientPool
redisPool: JedisPool
)(implicit val PA: PermissionsAuthority) {
def companion: RequestCacheObject[_]

Expand Down Expand Up @@ -94,7 +94,7 @@ abstract class LockedRequestCache(
override val userName: String,
serverParams: PropertiesWrapper,
dbGateway: DatabaseGateway,
redisPool: RedisClientPool,
redisPool: JedisPool,
) extends RequestCache(userName, serverParams, dbGateway, redisPool) {

}
Expand All @@ -103,7 +103,7 @@ abstract class UnlockedRequestCache(
override val userName: String,
serverParams: PropertiesWrapper,
dbGateway: DatabaseGateway,
redisPool: RedisClientPool,
redisPool: JedisPool,
) extends RequestCache(userName, serverParams, dbGateway, redisPool) {
def getObjectById[T <: StorableClass](obj: StorableObject[T], id: Int, fieldShutter: Set[DatabaseField[_]]): Option[T] =
pb.getObjectById(obj, id, fieldShutter)
Expand Down
4 changes: 2 additions & 2 deletions app/com/coleji/neptune/Core/RequestCacheObject.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ package com.coleji.neptune.Core

import com.coleji.neptune.Exception.UserTypeMismatchException
import com.coleji.neptune.Util.PropertiesWrapper
import com.redis.RedisClientPool
import redis.clients.jedis.JedisPool

abstract class RequestCacheObject[T <: RequestCache] {
val EMPTY_NONCE = "$EMPTY_AUTH_NONCE$"
val SEC_COOKIE_NAME_PUBLIC = "CBIDB-SEC"
val SEC_COOKIE_NAME_STAFF = "CBIDB-SEC-STAFF"

def create(userName: String, serverParams: PropertiesWrapper, dbGateway: DatabaseGateway, redisPool: RedisClientPool): T
def create(userName: String, serverParams: PropertiesWrapper, dbGateway: DatabaseGateway, redisPool: JedisPool): T

def test(allowed: Set[RequestCacheObject[_]]): Unit = {
if (!allowed.contains(this)) throw new UserTypeMismatchException()
Expand Down
8 changes: 4 additions & 4 deletions app/com/coleji/neptune/Core/RootRequestCache.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.coleji.neptune.Core

import com.coleji.neptune.Util.PropertiesWrapper
import com.redis.RedisClientPool
import redis.clients.jedis.JedisPool


class RootRequestCache(override val userName: String, serverParams: PropertiesWrapper, dbGateway: DatabaseGateway, redisPool: RedisClientPool)(implicit PA: PermissionsAuthority)
class RootRequestCache(override val userName: String, serverParams: PropertiesWrapper, dbGateway: DatabaseGateway, redisPool: JedisPool)(implicit PA: PermissionsAuthority)
extends UnlockedRequestCache(userName, serverParams, dbGateway, redisPool) {
override def companion: RequestCacheObject[RootRequestCache] = RootRequestCache
}
Expand All @@ -13,10 +13,10 @@ object RootRequestCache extends RequestCacheObject[RootRequestCache] {
val uniqueUserName = "ROOT"
val ROOT_AUTH_HEADER = "origin-root"

override def create(userName: String, serverParams: PropertiesWrapper, dbGateway: DatabaseGateway, redisPool: RedisClientPool): RootRequestCache =
override def create(userName: String, serverParams: PropertiesWrapper, dbGateway: DatabaseGateway, redisPool: JedisPool): RootRequestCache =
new RootRequestCache(userName, serverParams, dbGateway, redisPool)

def create(serverParams: PropertiesWrapper, dbGateway: DatabaseGateway, redisPool: RedisClientPool): RootRequestCache = create(uniqueUserName, serverParams, dbGateway, redisPool)
def create(serverParams: PropertiesWrapper, dbGateway: DatabaseGateway, redisPool: JedisPool): RootRequestCache = create(uniqueUserName, serverParams, dbGateway, redisPool)

override def getAuthenticatedUsernameInRequest(
request: ParsedRequest,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class DoubleFieldValue(instance: StorableClass, @transient fieldInner: DoubleDat
override def asJSValue: JsValue = JsNumber(super.get)

override def updateFromJsValue(v: JsValue): Boolean = v match {
case n: JsNumber => update(n.value.doubleValue())
case n: JsNumber => update(n.value.doubleValue)
case JsNull => throw new Exception("JsNull provided to nonnull field " + field.getRuntimeFieldName)
case _ => false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class NullableDoubleFieldValue(instance: StorableClass, @transient fieldInner: N
}

override def updateFromJsValue(v: JsValue): Boolean = v match {
case n: JsNumber => update(Some(n.value.doubleValue()))
case n: JsNumber => update(Some(n.value.doubleValue))
case JsNull => update(None)
case _ => false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ import com.coleji.neptune.Storable.{Filter, StorableClass, StorableObject}
case class BooleanColumnAlias(override val table: TableAlias[_ <: StorableObject[_ <: StorableClass]], override val field: BooleanDatabaseField)
extends ColumnAlias[DatabaseField[Boolean]](table, field) {

def equals(b: Boolean): Filter = Filter(s"${table.name}.${field.persistenceFieldName} = '${if (b) "Y" else "N"}'", List.empty)
def equalsConstant(b: Boolean): Filter = Filter(s"${table.name}.${field.persistenceFieldName} = '${if (b) "Y" else "N"}'", List.empty)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import com.coleji.neptune.Core.PermissionsAuthority
import com.coleji.neptune.Core.PermissionsAuthority.{PERSISTENCE_SYSTEM_MYSQL, PERSISTENCE_SYSTEM_ORACLE}
import com.coleji.neptune.Storable.Fields.{DatabaseField, DateTimeDatabaseField}
import com.coleji.neptune.Storable.{Filter, StorableClass, StorableObject}
import com.coleji.neptune.Util.{DATE_<, DATE_<=, DATE_=, DATE_>, DATE_>=, DateComparison}

import java.time.format.DateTimeFormatter
import java.time.{LocalDate, LocalDateTime}

case class DateTimeColumnAlias(override val table: TableAlias[_ <: StorableObject[_ <: StorableClass]], override val field: DateTimeDatabaseField)
extends ColumnAlias[DatabaseField[LocalDateTime]](table, field) {
extends ColumnAlias[DatabaseField[LocalDateTime]](table, field) {
val localDatePattern: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd")

def isYearConstant(year: Int)(implicit PA: PermissionsAuthority): Filter = PA.systemParams.persistenceSystem match {
case PERSISTENCE_SYSTEM_MYSQL => {
Expand All @@ -21,14 +23,23 @@ case class DateTimeColumnAlias(override val table: TableAlias[_ <: StorableObjec
case PERSISTENCE_SYSTEM_ORACLE => Filter(s"TO_CHAR(${table.name}.${field.persistenceFieldName}, 'YYYY') = $year", List.empty)
}

def isDateConstant(date: LocalDate)(implicit PA: PermissionsAuthority): Filter = PA.systemParams.persistenceSystem match {
case PERSISTENCE_SYSTEM_MYSQL =>
Filter(
s"${table.name}.${field.persistenceFieldName} >= '${date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))}' AND " +
s"${table.name}.${field.persistenceFieldName} < '${date.plusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))}'",
List.empty
)
case PERSISTENCE_SYSTEM_ORACLE =>
Filter(s"TRUNC(${table.name}.${field.persistenceFieldName}) = TO_DATE('${date.format(DateTimeFormatter.ofPattern("MM/dd/yyyy"))}','MM/DD/YYYY')", List.empty)
private def dateComparison(date: LocalDate, comp: DateComparison)(implicit PA: PermissionsAuthority): Filter = {
val comparator: String = comp.comparator
PA.systemParams.persistenceSystem match {
case PERSISTENCE_SYSTEM_MYSQL =>
Filter(s"${table.name}.${field.persistenceFieldName} $comparator '${date.format(localDatePattern)}'", List.empty)
case PERSISTENCE_SYSTEM_ORACLE =>
Filter(s"TRUNC(${table.name}.${field.persistenceFieldName}) $comparator TO_DATE('${date.format(DateTimeFormatter.ofPattern("MM/dd/yyyy"))}','MM/DD/YYYY')", List.empty)
}
}

def isDateConstant(date: LocalDate): Filter = dateComparison(date, DATE_=)

def greaterThanConstant(date: LocalDate): Filter = dateComparison(date, DATE_>)

def lessThanConstant(date: LocalDate): Filter = dateComparison(date, DATE_<)

def greaterEqualConstant(date: LocalDate): Filter = dateComparison(date, DATE_>=)

def lessEqualConstant(date: LocalDate): Filter = dateComparison(date, DATE_<=)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import com.coleji.neptune.Storable.{Filter, StorableClass, StorableObject}
case class NullableBooleanColumnAlias(override val table: TableAlias[_ <: StorableObject[_ <: StorableClass]], override val field: NullableBooleanDatabaseField)
extends ColumnAlias[DatabaseField[Option[Boolean]]](table, field) {

def equals(b: Option[Boolean]): Filter = b match {
def equalsConstant(b: Option[Boolean]): Filter = b match {
case Some(x) => Filter(s"${table.name}.${field.persistenceFieldName} = '${if (x) "Y" else "N"}'", List.empty)
case None => Filter(s"${table.name}.${field.persistenceFieldName} IS NULL", List.empty)
}
Expand Down
2 changes: 2 additions & 0 deletions app/com/coleji/neptune/Util/Currency.scala
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ object Currency {
override def toDouble(x: Currency): Double = x.cents.toDouble

override def compare(x: Currency, y: Currency): Int = if (x.cents > y.cents) 1 else if (x.cents < y.cents) -1 else 0

override def parseString(str: String): Option[Currency] = None
}

}
13 changes: 13 additions & 0 deletions app/com/coleji/neptune/Util/Initializable.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,18 @@ class Initializable[T] extends Serializable {
def forEach(f: T => Unit): Unit = {
if (isInitialized) f(this.get)
}

def findOneInCollection(collection: Traversable[T], find: T => Boolean): T = value match {
case None => {
collection.find(find) match {
case Some(t) => {
value = Some(t)
t
}
case None => throw new Exception("No match found in collection")
}
}
case Some(t) => t
}
}

This file was deleted.

This file was deleted.

Loading
Loading