Skip to content

Commit

Permalink
0.17.0 (see NEWS)
Browse files Browse the repository at this point in the history
  • Loading branch information
nondeterministic committed Dec 14, 2024
1 parent aa3501e commit 104f51f
Show file tree
Hide file tree
Showing 47 changed files with 658 additions and 463 deletions.
4 changes: 2 additions & 2 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ before_script:

build:
script:
- ./sbt/bin/sbt ++2.13.12 compile
- ./sbt/bin/sbt ++2.13.12 dist
- ./sbt/bin/sbt ++3.5.2 compile
- ./sbt/bin/sbt ++3.5.2 dist

# Testing currently only works from within IntelliJ.
#
Expand Down
36 changes: 25 additions & 11 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,23 @@
██║ ╚████║███████╗╚███╔███╔╝███████║
╚═╝ ╚═══╝╚══════╝ ╚══╝╚══╝ ╚══════╝

v0.16.1 (development) Sun Mar 24 10:36:47 AM CET 2024
v0.17.0 Sat Dec 14 03:05:54 PM CET 2024
--------------------------------------------------------
- Minor features:
- Main features:
- Update to Play >= 3 and Scala >= 3

- Minor improvements and changes:
- Update many other library versions
- Remove remaining dependencies on unmaintained scala.rx library
- Display source version information in the disclaimer

- Bug fixes:
- Detect and delete stale cookies from a previous login
resulting in repeated notifications of network errors

v0.16.1 Sun Mar 24 10:36:47 AM CET 2024
--------------------------------------------------------
- Features:
- Protect the two main lookup pages with a cookie check against
leeching attacks
- Update to Play 2.9.2, ScalaJS 1.16.0 and Scala 2.13.13
Expand All @@ -23,20 +37,20 @@ v0.16.1 (development) Sun Mar 24 10:36:47 AM CET 2024
- Sorting in file modal dialogue broke with the removal of RX
libraries and is fixed now

v0.16.0 (development) Sa 13. Jan 14:28:21 CET 2024
v0.16.0 Sa 13. Jan 14:28:21 CET 2024
--------------------------------------------------------
- Main features:
- Update to Java 17, Play 2.9 and sbt 1.9
- Update to ScalaJS 1.15.0 and Scala 2.13.12
- Replaced unmaintained RosHTTP library with sttp
- Removed unmaintained scalatags-rx library (as we want to use
- Replace unmaintained RosHTTP library with sttp
- Remove unmaintained scalatags-rx library (as we want to use
Laminar in the future)

- Minor improvements and changes:
- Routinely updated a bunch of other library versions, where it
- Routinely update a bunch of other library versions, where it
didn't hurt or require huge code restructurings

v0.15.0 (stable) Sa 16. Sep 13:36:29 CEST 2023
v0.15.0 Sa 16. Sep 13:36:29 CEST 2023
--------------------------------------------------------
- Main features:
- Change of database schema (not a user visible one, but
Expand All @@ -61,7 +75,7 @@ v0.15.0 (stable) Sa 16. Sep 13:36:29 CEST 2023
- OOREP would often crash after any kind of network transmission
error, whereas now it fails more gracefully

v0.14.2 (stable) Mo 15. Mai 18:31:05 CEST 2023
v0.14.2 Mo 15. Mai 18:31:05 CEST 2023
--------------------------------------------------------
- Minor improvements and changes:
- Prevent anonymous users from accessing protected materia medicas
Expand All @@ -79,7 +93,7 @@ v0.14.2 (stable) Mo 15. Mai 18:31:05 CEST 2023
- Logged-in users can now access "protected" but not "private" resources
(useful for preview of resources to selected testers, etc.)

v0.14.1 (stable) Sat Jan 21 11:11:56 CET 2023
v0.14.1 Sat Jan 21 11:11:56 CET 2023
--------------------------------------------------------
- Minor improvements and changes:
- Update FAQ with example searches
Expand All @@ -90,7 +104,7 @@ v0.14.1 (stable) Sat Jan 21 11:11:56 CET 2023
search
- Sharing of search link would fail when quotation marks were used

v0.14.0 (stable) Wed Dec 28 17:39:17 CET 2022
v0.14.0 Wed Dec 28 17:39:17 CET 2022
--------------------------------------------------------
- Main features:
- Buttons for sharing repertory search results and opening them in
Expand All @@ -110,7 +124,7 @@ v0.14.0 (stable) Wed Dec 28 17:39:17 CET 2022
- Fix race condition that would prevent public link to repertory
search from loading

v0.13.0 (stable) Thu May 26 12:13:11 PM CEST 2022
v0.13.0 Thu May 26 12:13:11 PM CEST 2022
--------------------------------------------------------
- Main features:
- Not really a user-visible one: but now would require
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class Delete @Inject()(cc: ControllerComponents, dbContext: DBContext) extends A

private val Logger = play.api.Logger(this.getClass)

def apiSecDelCaseRubricsFromCaze() = Action { request: Request[AnyContent] =>
def apiSecDelCaseRubricsFromCaze() = Action { (request: Request[AnyContent]) =>
getAuthenticatedUser(request) match {
case Some(_) => {
val requestData = request.body.asFormUrlEncoded.get
Expand Down Expand Up @@ -47,7 +47,7 @@ class Delete @Inject()(cc: ControllerComponents, dbContext: DBContext) extends A
}
}

def apiSecDelCaze() = Action { request: Request[AnyContent] =>
def apiSecDelCaze() = Action { (request: Request[AnyContent]) =>
getAuthenticatedUser(request) match {
case Some(_) => {
val requestData = request.body.asFormUrlEncoded.get
Expand All @@ -70,7 +70,7 @@ class Delete @Inject()(cc: ControllerComponents, dbContext: DBContext) extends A
}
}

def apiSecDelFileAndCases() = Action { request: Request[AnyContent] =>
def apiSecDelFileAndCases() = Action { (request: Request[AnyContent]) =>
getAuthenticatedUser(request) match {
case Some(_) => {
val requestData = request.body.asFormUrlEncoded.get
Expand Down
49 changes: 27 additions & 22 deletions backend/app/org/multics/baueran/frep/backend/controllers/Get.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package org.multics.baueran.frep.backend.controllers

import javax.inject._
import io.circe.syntax._
import javax.inject.*
import io.circe.syntax.*
import io.circe.Json
import play.api.mvc._
import org.multics.baueran.frep.backend.dao.{CazeDao, EmailHistoryDao, FileDao, MMDao, MemberDao, PasswordChangeRequestDao, RepertoryDao}
import org.multics.baueran.frep.shared._
Expand Down Expand Up @@ -46,7 +47,7 @@ class Get @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
* see @logout
*/

def login() = Action { implicit request =>
def login() = Action { implicit request: Request[AnyContent] =>
getAuthenticatedUser(request) match {
case None =>
Logger.error("Get: login() not completed successfully: sending user to logout to be safe.")
Expand All @@ -73,7 +74,7 @@ class Get @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
* see @login
*/

def logout() = Action { implicit request =>
def logout() = Action { implicit request: Request[AnyContent] =>
Redirect(sys.env.get("OOREP_URL_LOGOUT").getOrElse(""))
}

Expand All @@ -94,7 +95,7 @@ class Get @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
}
}

def showMM(materiaMedica: String, symptom: String, page: Int, hideSections: Boolean, remedyString: String) = Action { implicit request: Request[AnyContent] =>
def showMM(materiaMedica: String, symptom: String, page: Int, hideSections: Boolean, remedyString: String) = Action { implicit (request: Request[AnyContent]) =>
try {
getAuthenticatedUser(request) match {
case None =>
Expand Down Expand Up @@ -148,11 +149,11 @@ class Get @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
}
}

def apiDisplayGetErrorPage(message: String) = Action { implicit request: Request[AnyContent] =>
def apiDisplayGetErrorPage(message: String) = Action { implicit (request: Request[AnyContent]) =>
BadRequest(views.html.defaultpages.badRequest("GET", request.uri, message))
}

def apiStoreCookie(name: String, value: String) = Action { request: Request[AnyContent] =>
def apiStoreCookie(name: String, value: String) = Action { (request: Request[AnyContent]) =>
if (name == CookieFields.cookiePopupAccepted.toString)
Ok.withCookies(Cookie(CookieFields.cookiePopupAccepted.toString, value, secure = true, httpOnly = false))
else if (name == CookieFields.theme.toString)
Expand All @@ -163,7 +164,7 @@ class Get @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
}
}

def apiAuthenticate() = Action { request: Request[AnyContent] =>
def apiAuthenticate() = Action { (request: Request[AnyContent]) =>
getAuthenticatedUser(request) match {
case Some(member) =>
Ok(member.member_id.toString)
Expand All @@ -174,7 +175,7 @@ class Get @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
}
}

def apiAvailableRemedies() = Action { request: Request[AnyContent] =>
def apiAvailableRemedies() = Action { (request: Request[AnyContent]) =>
getAuthenticatedUser(request) match {
case Some(member) =>
Ok(repertoryDao.getRemedies().asJson.toString())
Expand All @@ -185,7 +186,7 @@ class Get @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
}
}

def apiAvailableRepertoriesAndRemedies() = Action { request: Request[AnyContent] =>
def apiAvailableRepertoriesAndRemedies() = Action { (request: Request[AnyContent]) =>
getAuthenticatedUser(request) match {
case Some(member) =>
Ok((repertoryDao.getRepsAndRemedies(getAuthenticatedUser(request)).asJson.toString))
Expand All @@ -196,7 +197,7 @@ class Get @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
}
}

def apiAvailableMateriaMedicasAndRemedies() = Action { request: Request[AnyContent] =>
def apiAvailableMateriaMedicasAndRemedies() = Action { (request: Request[AnyContent]) =>
getAuthenticatedUser(request) match {
case Some(member) =>
Ok(mmDao.getMMsAndRemedies(getAuthenticatedUser(request)).asJson.toString())
Expand All @@ -210,7 +211,7 @@ class Get @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
/**
* Won't actually return files with associated cases, but a list of tuples, (file ID, file header, file creation date).
*/
def apiSecAvailableFiles(memberId: Int) = Action { request: Request[AnyContent] =>
def apiSecAvailableFiles(memberId: Int) = Action { (request: Request[AnyContent]) =>
getAuthenticatedUser(request) match {
case None =>
val errStr = "Get: apiSecAvailableFiles() failed: not authenticated"
Expand All @@ -228,7 +229,7 @@ class Get @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
}
}

def apiSecGetFile(fileId: String) = Action { request: Request[AnyContent] =>
def apiSecGetFile(fileId: String) = Action { (request: Request[AnyContent]) =>
getAuthenticatedUser(request) match {
case None =>
Logger.error("Get: apiSecGetFile(): not authenticated")
Expand All @@ -252,7 +253,7 @@ class Get @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
}
}

def apiSecGetCase(caseId: String) = Action { request: Request[AnyContent] =>
def apiSecGetCase(caseId: String) = Action { (request: Request[AnyContent]) =>
getAuthenticatedUser(request) match {
case Some(member) if (caseId.forall(_.isDigit)) => {
cazeDao.get(caseId.toInt) match {
Expand Down Expand Up @@ -284,7 +285,7 @@ class Get @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
* are associated.
*/
// TODO: This, unfortunately, is a super slow method and needs improvement!! (or rather, it needs improvement inside FileDao.scala)
def apiSecFileOverview(fileId: String) = Action { request: Request[AnyContent] =>
def apiSecFileOverview(fileId: String) = Action { implicit (request: Request[AnyContent]) =>
getAuthenticatedUser(request) match {
case Some(_) if (fileId.forall(_.isDigit)) =>
val files = fileDao.getFIle(fileId.toInt)
Expand All @@ -294,18 +295,18 @@ class Get @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
files
.flatMap(f =>
f.cazes match {
case Nil => List((f.description, None, None))
case cazes => cazes.map(c => (f.description, Some(c.id), Some(s"[${c.date.take(10)}] '${c.header}'")))
case Nil => List(FileOverviewRow(f.description, None, None))
case cazes => cazes.map(c => FileOverviewRow(f.description, Some(c.id), Some(s"[${c.date.take(10)}] '${c.header}'")))
}
)

if (!isUserAuthorized(request, files.head.member_id)) {
val err = s"Get: apiSecFileOverview() failed: not authorised"
Logger.error(err)
Forbidden(err)
} else {
Ok(results.asJson.toString())
}
else
Ok(results.asJson.toString())
}
else {
Logger.warn(s"Get: apiSecFileOverview(${fileId}): nothing found.")
Expand All @@ -319,11 +320,15 @@ class Get @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
}

private def isCrossSiteRequest(request: Request[AnyContent]): Boolean = {
request.session.get("id") == None && getAuthenticatedUser(request) == None
// We allow "cookie-less" look-ups from localhost for testing purposes. TODO: Is this a security problem?!
if (request.remoteAddress == "127.0.0.1")
false
else
request.session.get("id") == None && getAuthenticatedUser(request) == None
}

def apiLookupRep(repertoryAbbrev: String, symptom: String, page: Int, remedyString: String, minWeight: Int, getRemedies: Int): Action[AnyContent] =
Action { request: Request[AnyContent] =>
Action { (request: Request[AnyContent]) =>
if (isCrossSiteRequest(request)) {
val errStr = (s"ERROR: request to ${request.uri} not authorized. Make sure your browser allows cookies. (IP: ${request.remoteAddress})")
Logger.error(errStr)
Expand Down Expand Up @@ -356,7 +361,7 @@ class Get @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
}

def apiLookupMM(mmAbbrev: String, symptom: String, page: Int, remedyString: String): Action[AnyContent] =
Action { request: Request[AnyContent] =>
Action { (request: Request[AnyContent]) =>
if (isCrossSiteRequest(request)) {
val errStr = (s"ERROR: request to ${request.uri} not authorized. Make sure your browser allows cookies. (IP: ${request.remoteAddress})")
Logger.error(errStr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class Post @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abs

private val Logger = play.api.Logger(this.getClass)

def submitNewPassword() = Action { implicit request =>
def submitNewPassword() = Action { implicit request: Request[AnyContent] =>
val errorMessage = s"Update of password failed. Please go back to main page ${serverUrl(request)} and try again, if you still want to change your password."
val password = request.body.asFormUrlEncoded.get("pass1").head
val pcrId = request.body.asFormUrlEncoded.get("pcrId").head
Expand All @@ -40,7 +40,7 @@ class Post @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abs
}
}

def requestUsername() = Action { implicit request =>
def requestUsername() = Action { implicit request: Request[AnyContent] =>
val inputEmail: String =
request.body.asFormUrlEncoded.get("inputEmail").head
.replaceAll("[ ;']", "")
Expand All @@ -62,7 +62,7 @@ class Post @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abs
emailHistoryDao.insert(emailHistoryItem)

val f = Future {
send a new Mail(
send `a` new Mail(
from = ("info@" + serverDomain(request), "OOREP-Support"),
to = member.email,
subject = "Username",
Expand Down Expand Up @@ -99,7 +99,7 @@ class Post @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abs
* exists or not.
*/

def requestPasswordChange() = Action { implicit request =>
def requestPasswordChange() = Action { implicit request: Request[AnyContent] =>
def genRandomString(length: Int) = {
val chars = ('A' to 'Z').toList ::: ('a' to 'z').toList ::: (0 to 9).toList.map(_.toString).map(_.head)
scala.util.Random.shuffle(chars ::: chars).take(length).mkString
Expand Down Expand Up @@ -150,7 +150,7 @@ class Post @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abs
emailHistoryDao.insert(emailHistoryItem)

val f = Future {
send a new Mail(
send `a` new Mail(
from = ("info@" + serverDomain(request), "OOREP-Support"),
to = member.email,
subject = "Password reset",
Expand Down Expand Up @@ -184,7 +184,7 @@ class Post @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abs
* or BadRequest(error string) if something went wrong.
*/

def saveCaze() = Action { request: Request[AnyContent] =>
def saveCaze() = Action { (request: Request[AnyContent]) =>
getAuthenticatedUser(request) match {
case Some(_) => {
val requestData = request.body.asFormUrlEncoded.get
Expand Down Expand Up @@ -220,7 +220,7 @@ class Post @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abs
}
}

def addCaseRubricsToCaze() = Action { request: Request[AnyContent] =>
def addCaseRubricsToCaze() = Action { (request: Request[AnyContent]) =>
getAuthenticatedUser(request) match {
case Some(_) => {
val requestData = request.body.asFormUrlEncoded.get
Expand Down Expand Up @@ -261,7 +261,7 @@ class Post @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abs
}
}

def saveFile() = Action { request: Request[AnyContent] =>
def saveFile() = Action { (request: Request[AnyContent]) =>
getAuthenticatedUser(request) match {
case Some(_) => {
FIle.decode(request.body.asText.get) match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class Put @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
}
}

def updateCaseDescription() = Action { implicit request =>
def updateCaseDescription() = Action { implicit request: Request[AnyContent] =>
getAuthenticatedUser(request) match {
case Some(_) => {
val requestData = request.body.asFormUrlEncoded.get
Expand Down Expand Up @@ -77,7 +77,7 @@ class Put @Inject()(cc: ControllerComponents, dbContext: DBContext) extends Abst
}
}

def updateFileDescription() = Action { implicit request =>
def updateFileDescription() = Action { implicit request: Request[AnyContent] =>
getAuthenticatedUser(request) match {
case Some(_) => {
val requestData = request.body.asFormUrlEncoded.get
Expand Down
Loading

0 comments on commit 104f51f

Please sign in to comment.