Skip to content

Commit

Permalink
moved admin methods to separate service
Browse files Browse the repository at this point in the history
  • Loading branch information
blakery committed Sep 20, 2024
1 parent fe082fb commit 4deca06
Show file tree
Hide file tree
Showing 11 changed files with 204 additions and 99 deletions.
10 changes: 10 additions & 0 deletions core/src/main/scala/org/broadinstitute/dsde/rawls/Boot.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import org.broadinstitute.dsde.rawls.workspace.{
MultiCloudWorkspaceAclManager,
MultiCloudWorkspaceService,
RawlsWorkspaceAclManager,
WorkspaceAdminService,
WorkspaceRepository,
WorkspaceService,
WorkspaceSettingRepository,
Expand Down Expand Up @@ -421,6 +422,14 @@ object Boot extends IOApp with LazyLogging {
fastPassServiceConstructor
)

val workspaceAdminServiceConstructor: RawlsRequestContext => WorkspaceAdminService =
WorkspaceAdminService.constructor(
slickDataSource,
gcsDAO,
samDAO,
workbenchMetricBaseName = metricsPrefix
)

val methodConfigurationServiceConstructor: RawlsRequestContext => MethodConfigurationService =
MethodConfigurationService.constructor(
slickDataSource,
Expand Down Expand Up @@ -519,6 +528,7 @@ object Boot extends IOApp with LazyLogging {
val service = new RawlsApiServiceImpl(
multiCloudWorkspaceServiceConstructor,
workspaceServiceConstructor,
workspaceAdminServiceConstructor,
workspaceSettingServiceConstructor,
entityServiceConstructor,
userServiceConstructor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ package org.broadinstitute.dsde.rawls.billing
import akka.http.scaladsl.model.StatusCodes
import org.broadinstitute.dsde.rawls.dataaccess.SlickDataSource
import org.broadinstitute.dsde.rawls.model.CreationStatuses.CreationStatus
import org.broadinstitute.dsde.rawls.model.{ErrorReport, RawlsBillingAccountName, RawlsBillingProject, RawlsBillingProjectName}
import org.broadinstitute.dsde.rawls.model.{
ErrorReport,
RawlsBillingAccountName,
RawlsBillingProject,
RawlsBillingProjectName
}
import org.broadinstitute.dsde.rawls.{RawlsException, RawlsExceptionWithErrorReport}

import java.util.UUID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import org.broadinstitute.dsde.rawls.monitor.migration.MultiregionalBucketMigrat
import org.broadinstitute.dsde.rawls.openam.UserInfoDirectives
import org.broadinstitute.dsde.rawls.submissions.SubmissionsService
import org.broadinstitute.dsde.rawls.user.UserService
import org.broadinstitute.dsde.rawls.workspace.WorkspaceService
import org.broadinstitute.dsde.rawls.workspace.WorkspaceAdminService
import spray.json.DefaultJsonProtocol._

import scala.concurrent.ExecutionContext
Expand All @@ -28,7 +28,8 @@ trait AdminApiService extends UserInfoDirectives {
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import org.broadinstitute.dsde.rawls.model.UserAuthJsonSupport._

val workspaceServiceConstructor: RawlsRequestContext => WorkspaceService
// val workspaceServiceConstructor: RawlsRequestContext => WorkspaceService
val workspaceAdminServiceConstructor: RawlsRequestContext => WorkspaceAdminService
val submissionsServiceConstructor: RawlsRequestContext => SubmissionsService
val userServiceConstructor: RawlsRequestContext => UserService
val bucketMigrationServiceConstructor: RawlsRequestContext => BucketMigrationService
Expand Down Expand Up @@ -98,19 +99,21 @@ trait AdminApiService extends UserInfoDirectives {
parameters('attributeName.?, 'valueString.?, 'valueNumber.?, 'valueBoolean.?) {
(nameOption, stringOption, numberOption, booleanOption) =>
val resultFuture = nameOption match {
case None => workspaceServiceConstructor(ctx).listAllWorkspaces()
case None => workspaceAdminServiceConstructor(ctx).listAllWorkspaces()
case Some(attributeName) =>
val name = AttributeName.fromDelimitedName(attributeName)
(stringOption, numberOption, booleanOption) match {
case (Some(string), None, None) =>
workspaceServiceConstructor(ctx).adminListWorkspacesWithAttribute(name, AttributeString(string))
workspaceAdminServiceConstructor(ctx).adminListWorkspacesWithAttribute(name,
AttributeString(string)
)
case (None, Some(number), None) =>
workspaceServiceConstructor(ctx).adminListWorkspacesWithAttribute(
workspaceAdminServiceConstructor(ctx).adminListWorkspacesWithAttribute(
name,
AttributeNumber(number.toDouble)
)
case (None, None, Some(boolean)) =>
workspaceServiceConstructor(ctx).adminListWorkspacesWithAttribute(
workspaceAdminServiceConstructor(ctx).adminListWorkspacesWithAttribute(
name,
AttributeBoolean(boolean.toBoolean)
)
Expand Down Expand Up @@ -211,18 +214,17 @@ trait AdminApiService extends UserInfoDirectives {
path("admin" / "workspaces" / Segment / Segment / "flags") { (workspaceNamespace, workspaceName) =>
get {
complete {
workspaceServiceConstructor(ctx).adminListWorkspaceFeatureFlags(
workspaceAdminServiceConstructor(ctx).adminListWorkspaceFeatureFlags(
WorkspaceName(workspaceNamespace, workspaceName)
)
}
} ~
put {
entity(as[List[String]]) { flagNames =>
complete {
workspaceServiceConstructor(ctx).adminOverwriteWorkspaceFeatureFlags(WorkspaceName(workspaceNamespace,
workspaceName
),
flagNames
workspaceAdminServiceConstructor(ctx).adminOverwriteWorkspaceFeatureFlags(
WorkspaceName(workspaceNamespace, workspaceName),
flagNames
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ import org.broadinstitute.dsde.rawls.spendreporting.SpendReportingService
import org.broadinstitute.dsde.rawls.status.StatusService
import org.broadinstitute.dsde.rawls.submissions.SubmissionsService
import org.broadinstitute.dsde.rawls.user.UserService
import org.broadinstitute.dsde.rawls.workspace.{MultiCloudWorkspaceService, WorkspaceService, WorkspaceSettingService}
import org.broadinstitute.dsde.rawls.workspace.{
MultiCloudWorkspaceService,
WorkspaceAdminService,
WorkspaceService,
WorkspaceSettingService
}
import org.broadinstitute.dsde.workbench.oauth2.OpenIDConnectConfiguration

import java.sql.{SQLException, SQLTransactionRollbackException}
Expand Down Expand Up @@ -212,6 +217,7 @@ trait VersionApiService {

class RawlsApiServiceImpl(val multiCloudWorkspaceServiceConstructor: RawlsRequestContext => MultiCloudWorkspaceService,
val workspaceServiceConstructor: RawlsRequestContext => WorkspaceService,
val workspaceAdminServiceConstructor: RawlsRequestContext => WorkspaceAdminService,
val workspaceSettingServiceConstructor: RawlsRequestContext => WorkspaceSettingService,
val entityServiceConstructor: RawlsRequestContext => EntityService,
val userServiceConstructor: RawlsRequestContext => UserService,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package org.broadinstitute.dsde.rawls.workspace

import akka.stream.Materializer
import com.typesafe.scalalogging.LazyLogging
import org.broadinstitute.dsde.rawls.NoSuchWorkspaceException
import org.broadinstitute.dsde.rawls.dataaccess._
import org.broadinstitute.dsde.rawls.dataaccess.slick._
import org.broadinstitute.dsde.rawls.metrics.RawlsInstrumented
import org.broadinstitute.dsde.rawls.model.{AttributeName, AttributeValue,WorkspaceAttributeSpecs, ErrorReportSource, ManagedGroupRef, RawlsGroupName, RawlsRequestContext, SamResourceTypeName, SamResourceTypeNames, Workspace, WorkspaceDetails, WorkspaceFeatureFlag, WorkspaceName}
import org.broadinstitute.dsde.rawls.util._

import scala.concurrent.{ExecutionContext, Future}
import scala.language.postfixOps

object WorkspaceAdminService {
def constructor(dataSource: SlickDataSource,

gcsDAO: GoogleServicesDAO,
samDAO: SamDAO,
workbenchMetricBaseName: String,
)(
ctx: RawlsRequestContext
)(implicit materializer: Materializer, executionContext: ExecutionContext): WorkspaceAdminService =
new WorkspaceAdminService(
ctx,
dataSource,
gcsDAO,
samDAO,
workbenchMetricBaseName,
new WorkspaceRepository(dataSource),
)
}

class WorkspaceAdminService(
protected val ctx: RawlsRequestContext,
val dataSource: SlickDataSource,
protected val gcsDAO: GoogleServicesDAO,
val samDAO: SamDAO,
override val workbenchMetricBaseName: String,
val workspaceRepository: WorkspaceRepository,
) (implicit protected val executionContext: ExecutionContext)
extends LazyLogging
with RawlsInstrumented
with RoleSupport
with WorkspaceSupport {

implicit val errorReportSource: ErrorReportSource = ErrorReportSource ("rawls")

// Admin endpoint, not limited to V2 workspaces
def listAllWorkspaces(): Future[Seq[WorkspaceDetails]] =
asFCAdmin {
dataSource.inTransaction { dataAccess =>
dataAccess.workspaceQuery.listAll().map(workspaces => workspaces.map(w => WorkspaceDetails(w, Set.empty)))
}
}

// Admin endpoint, not limited to V2 workspaces
def adminListWorkspacesWithAttribute(attributeName: AttributeName,
attributeValue: AttributeValue
): Future[Seq[WorkspaceDetails]] =
asFCAdmin {
for {
workspaces <- dataSource.inTransaction { dataAccess =>
dataAccess.workspaceQuery.listWithAttribute(attributeName, attributeValue)
}
results <- Future.traverse(workspaces) { workspace =>
loadResourceAuthDomain(SamResourceTypeNames.workspace, workspace.workspaceId).map(
WorkspaceDetails(workspace, _)
)
}
} yield results
}

// Admin endpoint, not limited to V2 workspaces
def adminListWorkspaceFeatureFlags(workspaceName: WorkspaceName): Future[Seq[WorkspaceFeatureFlag]] =
asFCAdmin {
dataSource.inTransaction { dataAccess =>
withWorkspaceContext(workspaceName, dataAccess) { workspaceContext =>
dataAccess.workspaceFeatureFlagQuery.listAllForWorkspace(workspaceContext.workspaceIdAsUUID)
}
}
}

// Admin endpoint, not limited to V2 workspaces
def adminOverwriteWorkspaceFeatureFlags(workspaceName: WorkspaceName,
flagNames: List[String]
): Future[Seq[WorkspaceFeatureFlag]] =
asFCAdmin {
val flags = flagNames.map(WorkspaceFeatureFlag)

dataSource.inTransaction { dataAccess =>
withWorkspaceContext(workspaceName, dataAccess) { workspaceContext =>
for {
_ <- dataAccess.workspaceFeatureFlagQuery.deleteAllForWorkspace(workspaceContext.workspaceIdAsUUID)
_ <- dataAccess.workspaceFeatureFlagQuery.saveAll(workspaceContext.workspaceIdAsUUID, flags)
} yield flags
}
}
}

// moved out of WorkspaceSupport because the only usage was in this file,
// and it has raw datasource/dataAccess usage, which is being refactored out of WorkspaceSupport
private def withWorkspaceContext[T](workspaceName: WorkspaceName,
dataAccess: DataAccess,
attributeSpecs: Option[WorkspaceAttributeSpecs] = None
)(op: Workspace => ReadWriteAction[T]) =
dataAccess.workspaceQuery.findByName(workspaceName, attributeSpecs) flatMap {
case None => throw NoSuchWorkspaceException(workspaceName)
case Some(workspace) => op(workspace)
}

private def loadResourceAuthDomain(resourceTypeName: SamResourceTypeName,
resourceId: String
): Future[Set[ManagedGroupRef]] =
samDAO
.getResourceAuthDomain(resourceTypeName, resourceId, ctx)
.map(_.map(g => ManagedGroupRef(RawlsGroupName(g))).toSet)


}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@ import akka.http.scaladsl.model.StatusCodes
import org.broadinstitute.dsde.rawls.RawlsExceptionWithErrorReport
import org.broadinstitute.dsde.rawls.dataaccess.SlickDataSource
import org.broadinstitute.dsde.rawls.model.Attributable.AttributeMap
import org.broadinstitute.dsde.rawls.model.{ErrorReport, PendingCloneWorkspaceFileTransfer, RawlsRequestContext, Workspace, WorkspaceAttributeSpecs, WorkspaceName, WorkspaceState, WorkspaceSubmissionStats, WorkspaceTag}
import org.broadinstitute.dsde.rawls.model.{
ErrorReport,
PendingCloneWorkspaceFileTransfer,
RawlsRequestContext,
Workspace,
WorkspaceAttributeSpecs,
WorkspaceName,
WorkspaceState,
WorkspaceSubmissionStats,
WorkspaceTag
}
import org.broadinstitute.dsde.rawls.model.WorkspaceState.WorkspaceState
import org.broadinstitute.dsde.rawls.util.TracingUtils.traceDBIOWithParent
import org.joda.time.DateTime
Expand Down Expand Up @@ -111,9 +121,8 @@ class WorkspaceRepository(dataSource: SlickDataSource) {
def savePendingCloneWorkspaceFileTransfer(destWorkspace: UUID, sourceWorkspace: UUID, prefix: String): Future[Int] =
dataSource.inTransaction(_.cloneWorkspaceFileTransferQuery.save(destWorkspace, sourceWorkspace, prefix))


def listSubmissionSummaryStats(workspaceId: UUID): Future[Map[UUID, WorkspaceSubmissionStats]] =
dataSource.inTransaction { _.workspaceQuery.listSubmissionSummaryStats(Seq(workspaceId)) }
dataSource.inTransaction(_.workspaceQuery.listSubmissionSummaryStats(Seq(workspaceId)))

/**
* FIXME: This appears to be using unvalidated input from users in a query.
Expand All @@ -125,5 +134,4 @@ class WorkspaceRepository(dataSource: SlickDataSource) {
def getTags(workspaceIds: Seq[UUID], query: Option[String], limit: Option[Int] = None): Future[Seq[WorkspaceTag]] =
dataSource.inTransaction(_.workspaceQuery.getTags(query, limit, Some(workspaceIds)))


}
Loading

0 comments on commit 4deca06

Please sign in to comment.