Skip to content
Open
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
2 changes: 1 addition & 1 deletion api/src/main/scala/org/scastie/api/CompilerInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ object Problem {

case class Problem(
severity: Severity,
line: Option[Int],
startLine: Option[Int],
endLine: Option[Int],
startColumn: Option[Int],
endColumn: Option[Int],
Expand Down
23 changes: 21 additions & 2 deletions api/src/main/scala/org/scastie/api/ScalaTarget.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package org.scastie.api
import org.scastie.buildinfo.BuildInfo
import io.circe.generic.semiauto._
import io.circe._
import io.circe.syntax._

sealed trait ScalaTarget {
val targetType: ScalaTargetType
Expand Down Expand Up @@ -296,7 +297,25 @@ case class ScalaCli(scalaVersion: String) extends ScalaTarget {
}

object ScalaTarget {
implicit val scalaTargetEncoder: Encoder[ScalaTarget] = deriveEncoder[ScalaTarget]
implicit val scalaTargetDecoder: Decoder[ScalaTarget] = deriveDecoder[ScalaTarget]
implicit val scalaTargetEncoder: Encoder[ScalaTarget] = Encoder.instance {
case s: Scala2 => Json.obj("Scala2" -> s.asJson)
case s: Scala3 => Json.obj("Scala3" -> s.asJson)
case s: ScalaCli => Json.obj("ScalaCli" -> s.asJson)
case s: Js => Json.obj("Js" -> s.asJson)
case s: Native => Json.obj("Native" -> s.asJson)
case s: Typelevel => Json.obj("Typelevel" -> s.asJson)
}

implicit val scalaTargetDecoder: Decoder[ScalaTarget] = Decoder.instance { cursor =>
cursor.keys.flatMap(_.headOption) match {
case Some("Scala2") => cursor.downField("Scala2").as[Scala2]
case Some("Scala3") => cursor.downField("Scala3").as[Scala3]
case Some("ScalaCli") => cursor.downField("ScalaCli").as[ScalaCli]
case Some("Js") => cursor.downField("Js").as[Js]
case Some("Native") => cursor.downField("Native").as[Native]
case Some("Typelevel") => cursor.downField("Typelevel").as[Typelevel]
case other => Left(DecodingFailure(s"Unknown ScalaTarget type: $other", cursor.history))
}
}
}

11 changes: 11 additions & 0 deletions api/src/main/scala/org/scastie/api/SnippetId.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ case class SnippetUserPart(login: String, update: Int = 0)
object SnippetId {
def empty: SnippetId = SnippetId("", None)

def fromString(s: String): SnippetId = {
s.split('/') match {
case Array(uuid) => SnippetId(uuid, None)
case Array(login, uuid) =>
SnippetId(uuid, Some(SnippetUserPart(login, 0)))
case Array(login, uuid, update) =>
SnippetId(uuid, Some(SnippetUserPart(login, update.toInt)))
case _ => throw new IllegalArgumentException(s"Invalid snippet id: $s")
}
}
Comment thread
warcholjakub marked this conversation as resolved.

implicit val snippetIdEncoder: Encoder[SnippetId] = deriveEncoder[SnippetId]
implicit val snippetIdDecoder: Decoder[SnippetId] = deriveDecoder[SnippetId]
}
Expand Down
30 changes: 4 additions & 26 deletions balancer/src/main/scala/org/scastie/balancer/DispatchActor.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.scastie.storage._
import org.scastie.storage.filesystem._
import org.scastie.storage.inmemory._
import org.scastie.storage.mongodb._
import org.scastie.storage.postgres.PostgresContainer
import org.scastie.util._
import com.typesafe.config.ConfigFactory

Expand Down Expand Up @@ -47,15 +48,6 @@ case class FetchUserSnippets(user: User)

case class ReceiveStatus(requester: ActorRef)

@deprecated("Scheduled for removal", "2023-04-30")
case class GetPrivacyPolicy(user: User)
@deprecated("Scheduled for removal", "2023-04-30")
case class SetPrivacyPolicy(user: User, status: Boolean)
@deprecated("Scheduled for removal", "2023-04-30")
case class RemovePrivacyPolicy(user: User)
@deprecated("Scheduled for removal", "2023-04-30")
case class RemoveAllUserSnippets(user: User)

case class Run(inputsWithIpAndUser: InputsWithIpAndUser, snippetId: SnippetId)

case class Done(progress: SnippetProgress, retries: Int)
Expand Down Expand Up @@ -117,7 +109,9 @@ class DispatchActor(progressActor: ActorRef, statusActor: ActorRef)
containerType match {
case "memory" => new InMemoryContainer()
case "mongo" => new MongoDBContainer()(ExecutionContext.fromExecutor(Executors.newWorkStealingPool()))
case "mongo-local" => new MongoDBContainer(defaultConfig = false)(ExecutionContext.fromExecutor(Executors.newWorkStealingPool()))
case "mongo-local" => new MongoDBContainer(defaultConfig = true)(ExecutionContext.fromExecutor(Executors.newWorkStealingPool()))
case "postgres" => new PostgresContainer()(ExecutionContext.fromExecutor(Executors.newWorkStealingPool()))
case "postgres-local" => new PostgresContainer(defaultConfig = true)(ExecutionContext.fromExecutor(Executors.newWorkStealingPool()))
case "files" => new FilesystemContainer(
Paths.get(config.getString("snippets-dir")),
Paths.get(config.getString("old-snippets-dir"))
Expand Down Expand Up @@ -198,10 +192,6 @@ class DispatchActor(progressActor: ActorRef, statusActor: ActorRef)
val sender = this.sender()
logError(container.readLatestSnippet(snippetId).map(sender ! _))

case FetchOldSnippet(id) =>
val sender = this.sender()
logError(container.readOldSnippet(id).map(sender ! _))

case FetchUserSnippets(user) =>
val sender = this.sender()
logError(container.listSnippets(UserLogin(user.login)).map(sender ! _))
Expand All @@ -217,18 +207,6 @@ class DispatchActor(progressActor: ActorRef, statusActor: ActorRef)
case FetchScalaJsSourceMap(snippetId) =>
val sender = this.sender()
logError(container.readScalaJsSourceMap(snippetId).map(sender ! _))
case GetPrivacyPolicy(user) =>
val sender = this.sender()
logError(container.getPrivacyPolicyResponse(UserLogin(user.login)).map(sender ! _))
case SetPrivacyPolicy(user, status) =>
val sender = this.sender()
logError(container.setPrivacyPolicyResponse(UserLogin(user.login), status).map(sender ! _))
case RemovePrivacyPolicy(user) =>
val sender = this.sender()
logError(container.deleteUser(UserLogin(user.login)).map(sender ! _))
case RemoveAllUserSnippets(user) =>
val sender = this.sender()
logError(container.removeUserSnippets(UserLogin(user.login)).map(sender ! _))

case x @ ReceiveStatus(requester) =>
sbtDispatcher.tell(x, sender())
Expand Down
8 changes: 7 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,13 @@ lazy val storage = project
libraryDependencies ++= Seq(
"org.mongodb.scala" %% "mongo-scala-driver" % "4.11.1",
"net.lingala.zip4j" % "zip4j" % "2.11.5",
"io.circe" %% "circe-parser" % "0.14.6"
"io.circe" %% "circe-parser" % "0.14.6",
"com.lihaoyi" %% "scalasql" % "0.2.2",
"io.scalaland" %% "chimney" % "1.8.2",
"org.postgresql" % "postgresql" % "42.7.8",
"org.flywaydb" % "flyway-core" % "11.13.2",
"org.flywaydb" % "flyway-database-postgresql" % "11.13.2",
"com.zaxxer" % "HikariCP" % "7.0.2"
)
)
.dependsOn(api.jvm(ScalaVersions.jvm), utils, instrumentation)
Expand Down
4 changes: 0 additions & 4 deletions client/src/main/scala/org/scastie/client/ModalState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ object ModalState {
def allClosed: ModalState = ModalState(
isHelpModalClosed = true,
isPrivacyPolicyModalClosed = true,
isPrivacyPolicyPromptClosed = true,
shareModalSnippetId = None,
isResetModalClosed = true,
isNewSnippetModalClosed = true,
Expand All @@ -25,7 +24,6 @@ object ModalState {
def default: ModalState = ModalState(
isHelpModalClosed = true,
isPrivacyPolicyModalClosed = true,
isPrivacyPolicyPromptClosed = true,
shareModalSnippetId = None,
isResetModalClosed = true,
isNewSnippetModalClosed = true,
Expand All @@ -38,8 +36,6 @@ object ModalState {
case class ModalState(
isHelpModalClosed: Boolean,
isPrivacyPolicyModalClosed: Boolean,
@deprecated("Scheduled for removal", "2023-04-30")
isPrivacyPolicyPromptClosed: Boolean,
shareModalSnippetId: Option[SnippetId],
isResetModalClosed: Boolean,
isNewSnippetModalClosed: Boolean,
Expand Down
16 changes: 0 additions & 16 deletions client/src/main/scala/org/scastie/client/RestApiClient.scala
Original file line number Diff line number Diff line change
Expand Up @@ -115,22 +115,6 @@ class RestApiClient(serverUrl: Option[String]) extends RestApi {
def changeUser(user: User): Future[Option[UserData]] =
post[UserData].using("/changeUser", user, async=false)

@deprecated("Scheduled for removal", "2023-04-30")
def getPrivacyPolicyStatus(): Future[Boolean] =
post[Boolean].using("/user/privacyPolicyStatus", "").map(_.getOrElse(true))

@deprecated("Scheduled for removal", "2023-04-30")
def acceptPrivacyPolicy(): Future[Boolean] =
post[Boolean].using("/user/acceptPrivacyPolicy", "", async=false).map(_.getOrElse(false))

@deprecated("Scheduled for removal", "2023-04-30")
def removeAllUserSnippets(): Future[Boolean] =
post[Boolean].using("/user/removeAllUserSnippets", "", async=false).map(_.getOrElse(false))

@deprecated("Scheduled for removal", "2023-04-30")
def removeUserFromPolicyStatus(): Future[Boolean] =
post[Boolean].using("/user/removeUserFromPolicyStatus", "", async=false).map(_.getOrElse(false))

def fetchUserSnippets(): Future[List[SnippetSummary]] =
get[List[SnippetSummary]]("/user/snippets").map(_.getOrElse(Nil))
}
41 changes: 0 additions & 41 deletions client/src/main/scala/org/scastie/client/ScastieBackend.scala
Original file line number Diff line number Diff line change
Expand Up @@ -166,12 +166,6 @@ case class ScastieBackend(scastieId: UUID, serverUrl: Option[String], scope: Bac
val closePrivacyPolicyModal: Reusable[Callback] =
Reusable.always(scope.modState(_.togglePrivacyPolicyModal))

val closePrivacyPolicyPrompt: Reusable[Callback] =
Reusable.always(scope.modState(_.setPrivacyPolicyPromptClosed(true)))

val openPrivacyPolicyPrompt: Reusable[Callback] =
Reusable.always(scope.modState(_.setPrivacyPolicyPromptClosed(false)))

val openLoginModal: Reusable[Callback] =
Reusable.always(scope.modState(_.setLoginModalClosed(false)))

Expand Down Expand Up @@ -330,37 +324,6 @@ case class ScastieBackend(scastieId: UUID, serverUrl: Option[String], scope: Bac
)
)

val acceptPolicy: Reusable[Callback] =
Reusable.always(
Callback.future {
restApiClient.acceptPrivacyPolicy().map { result =>
scope.modState(_.setPrivacyPolicyPromptClosed(result))
}
}
)

val removeUserFromPolicyStatus: Reusable[Callback] =
Reusable.always(
Callback.future {
restApiClient.removeUserFromPolicyStatus().map { result =>
scope.modState(_.setPrivacyPolicyPromptClosed(result)).map(_ => {
if (result) document.location.reload()
})
}
}
)

val removeAllUserSnippets: Reusable[Callback] =
Reusable.always(
Callback.future {
restApiClient.removeAllUserSnippets().map(Callback(_))
}
)

val refusePrivacyPolicy: Reusable[Callback] = Reusable.always(
removeAllUserSnippets >> removeUserFromPolicyStatus
)

private def saveCallback(sId: SnippetId): Callback = {
val setState = scope.modState(_.setCleanInputs.setSnippetId(sId).setLoadSnippet(false))
val page = Page.fromSnippetId(sId)
Expand Down Expand Up @@ -495,10 +458,6 @@ case class ScastieBackend(scastieId: UUID, serverUrl: Option[String], scope: Bac
restApiClient
.fetchUserData()
.map(result => scope.modState(_.setUserData(result)))
) >> Callback.future(
restApiClient
.getPrivacyPolicyStatus()
.map(result => scope.modState(_.setPrivacyPolicyPromptClosed(result)))
)

def changeUser(user: User): Callback =
Expand Down
4 changes: 0 additions & 4 deletions client/src/main/scala/org/scastie/client/ScastieState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -272,10 +272,6 @@ case class ScastieState(
modalState = modalState.copy(isPrivacyPolicyModalClosed = !modalState.isPrivacyPolicyModalClosed)
)

def setPrivacyPolicyPromptClosed(status: Boolean): ScastieState = copyAndSave(
modalState = modalState.copy(isPrivacyPolicyPromptClosed = status)
)

def setLoginModalClosed(status: Boolean): ScastieState = copyAndSave(
modalState = modalState.copy(isLoginModalClosed = status)
)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,6 @@ object Scastie {
close = scope.backend.closeLoginModal,
openPrivacyPolicyModal = scope.backend.openPrivacyPolicyModal
).render,
PrivacyPolicyPrompt(
isDarkTheme = state.isDarkTheme,
isClosed = state.modalState.isPrivacyPolicyPromptClosed,
acceptPrivacyPolicy = scope.backend.acceptPolicy,
refusePrivacyPolicy = scope.backend.refusePrivacyPolicy,
openPrivacyPolicyModal = scope.backend.openPrivacyPolicyModal
).render,
PrivacyPolicyModal(
isDarkTheme = state.isDarkTheme,
isClosed = state.modalState.isPrivacyPolicyModalClosed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ object CodeEditor {

def problemToDiagnostics(problem: Problem, doc: Text): Seq[Diagnostic] = {
val maxLine = doc.lines.toInt
val startLine = problem.line.get.max(1).min(maxLine)
val startLine = problem.startLine.get.max(1).min(maxLine)
val endLine = problem.endLine.getOrElse(startLine).max(1).min(maxLine)

val renderMessage = (_: EditorView) => {
Expand Down Expand Up @@ -156,7 +156,7 @@ object CodeEditor {
}

val to = if (isEndLine) {
if (problem.line.get > maxLine && isStartLine) {
if (problem.startLine.get > maxLine && isStartLine) {
lineInfo.to
} else {
problem.endColumn match {
Expand Down Expand Up @@ -217,7 +217,7 @@ object CodeEditor {

private def getDecorations(props: CodeEditor, doc: Text): js.Array[Diagnostic] = {
val errors = props.compilationInfos
.filter(prob => prob.line.isDefined)
.filter(prob => prob.startLine.isDefined)
.flatMap(problemToDiagnostics(_, doc))

val runtimeErrors = props.runtimeError.map(runtimeError => {
Expand Down
7 changes: 7 additions & 0 deletions deployment/postgres.template.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
org.scastie.postgres {
user=<user>
password=<password>
database=<database>
host=<host>
port=<port>
}
Loading