diff --git a/src/main/resources/org/broadinstitute/dsde/sam/liquibase/changelog.xml b/src/main/resources/org/broadinstitute/dsde/sam/liquibase/changelog.xml
index ee3db6173..a81ed7a3e 100644
--- a/src/main/resources/org/broadinstitute/dsde/sam/liquibase/changelog.xml
+++ b/src/main/resources/org/broadinstitute/dsde/sam/liquibase/changelog.xml
@@ -24,4 +24,5 @@
+
diff --git a/src/main/resources/org/broadinstitute/dsde/sam/liquibase/changesets/20230302_auth0_id.xml b/src/main/resources/org/broadinstitute/dsde/sam/liquibase/changesets/20230302_auth0_id.xml
new file mode 100644
index 000000000..7a6ad7fbe
--- /dev/null
+++ b/src/main/resources/org/broadinstitute/dsde/sam/liquibase/changesets/20230302_auth0_id.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/scala/org/broadinstitute/dsde/workbench/sam/dataAccess/DirectoryDAO.scala b/src/main/scala/org/broadinstitute/dsde/workbench/sam/dataAccess/DirectoryDAO.scala
index f8e0f2182..d7c50c6ec 100644
--- a/src/main/scala/org/broadinstitute/dsde/workbench/sam/dataAccess/DirectoryDAO.scala
+++ b/src/main/scala/org/broadinstitute/dsde/workbench/sam/dataAccess/DirectoryDAO.scala
@@ -42,6 +42,8 @@ trait DirectoryDAO {
def loadUserByGoogleSubjectId(userId: GoogleSubjectId, samRequestContext: SamRequestContext): IO[Option[SamUser]]
def loadUserByAzureB2CId(userId: AzureB2CId, samRequestContext: SamRequestContext): IO[Option[SamUser]]
def setUserAzureB2CId(userId: WorkbenchUserId, b2cId: AzureB2CId, samRequestContext: SamRequestContext): IO[Unit]
+ def loadUserByAuth0Id(userId: Auth0Id, samRequestContext: SamRequestContext): IO[Option[SamUser]]
+ def setUserAuth0Id(userId: WorkbenchUserId, auth0Id: Auth0Id, samRequestContext: SamRequestContext): IO[Unit]
def deleteUser(userId: WorkbenchUserId, samRequestContext: SamRequestContext): IO[Unit]
def listUsersGroups(userId: WorkbenchUserId, samRequestContext: SamRequestContext): IO[Set[WorkbenchGroupIdentity]]
diff --git a/src/main/scala/org/broadinstitute/dsde/workbench/sam/dataAccess/PostgresDirectoryDAO.scala b/src/main/scala/org/broadinstitute/dsde/workbench/sam/dataAccess/PostgresDirectoryDAO.scala
index 1a757474a..d1de5029b 100644
--- a/src/main/scala/org/broadinstitute/dsde/workbench/sam/dataAccess/PostgresDirectoryDAO.scala
+++ b/src/main/scala/org/broadinstitute/dsde/workbench/sam/dataAccess/PostgresDirectoryDAO.scala
@@ -341,7 +341,7 @@ class PostgresDirectoryDAO(protected val writeDbRef: DbReference, protected val
val userColumn = UserTable.column
val insertUserQuery =
- samsql"insert into ${UserTable.table} (${userColumn.id}, ${userColumn.email}, ${userColumn.googleSubjectId}, ${userColumn.enabled}, ${userColumn.azureB2cId}, ${userColumn.acceptedTosVersion}) values (${user.id}, ${user.email}, ${user.googleSubjectId}, ${user.enabled}, ${user.azureB2CId}, ${user.acceptedTosVersion})"
+ samsql"insert into ${UserTable.table} (${userColumn.id}, ${userColumn.email}, ${userColumn.googleSubjectId}, ${userColumn.enabled}, ${userColumn.azureB2cId}, ${userColumn.acceptedTosVersion}), ${userColumn.auth0Id} values (${user.id}, ${user.email}, ${user.googleSubjectId}, ${user.enabled}, ${user.azureB2CId}, ${user.acceptedTosVersion}, ${user.auth0Id})"
Try {
insertUserQuery.update().apply()
@@ -405,6 +405,35 @@ class PostgresDirectoryDAO(protected val writeDbRef: DbReference, protected val
}
}
+ override def loadUserByAuth0Id(userId: Auth0Id, samRequestContext: SamRequestContext): IO[Option[SamUser]] =
+ readOnlyTransaction("loadUserByAuth0Id", samRequestContext) { implicit session =>
+ val userTable = UserTable.syntax
+
+ val loadUserQuery = samsql"select ${userTable.resultAll} from ${UserTable as userTable} where ${userTable.auth0Id} = ${userId}"
+ loadUserQuery
+ .map(UserTable(userTable))
+ .single()
+ .apply()
+ .map(UserTable.unmarshalUserRecord)
+ }
+
+ override def setUserByAuth0Id(userId: WorkbenchUserId, auth0Id: Auth0Id, samRequestContext: SamRequestContext): IO[Unit] =
+ serializableWriteTransaction("setUserByAuth0Id", samRequestContext) { implicit session =>
+ val u = UserTable.column
+ val results =
+ samsql"update ${UserTable.table} set ${u.auth0Id} = $auth0Id where ${u.id} = $userId and (${u.auth0Id} is null or ${u.auth0Id} = $auth0Id)"
+ .update()
+ .apply()
+
+ if (results != 1) {
+ throw new WorkbenchException(
+ s"Cannot update auth0Id for user ${userId} because user does not exist or the auth0Id has already been set for this user"
+ )
+ } else {
+ ()
+ }
+ }
+
override def deleteUser(userId: WorkbenchUserId, samRequestContext: SamRequestContext): IO[Unit] =
serializableWriteTransaction("deleteUser", samRequestContext) { implicit session =>
val userTable = UserTable.syntax
diff --git a/src/main/scala/org/broadinstitute/dsde/workbench/sam/db/tables/UserTable.scala b/src/main/scala/org/broadinstitute/dsde/workbench/sam/db/tables/UserTable.scala
index aac63aa24..3903bb8ca 100644
--- a/src/main/scala/org/broadinstitute/dsde/workbench/sam/db/tables/UserTable.scala
+++ b/src/main/scala/org/broadinstitute/dsde/workbench/sam/db/tables/UserTable.scala
@@ -11,7 +11,8 @@ final case class UserRecord(
googleSubjectId: Option[GoogleSubjectId],
enabled: Boolean,
azureB2cId: Option[AzureB2CId],
- acceptedTosVersion: Option[String]
+ acceptedTosVersion: Option[String],
+ auth0Id: Option[Auth0Id]
)
object UserTable extends SQLSyntaxSupportWithDefaultSamDB[UserRecord] {
@@ -24,11 +25,20 @@ object UserTable extends SQLSyntaxSupportWithDefaultSamDB[UserRecord] {
rs.stringOpt(e.googleSubjectId).map(GoogleSubjectId),
rs.get(e.enabled),
rs.stringOpt(e.azureB2cId).map(AzureB2CId),
- rs.stringOpt(e.acceptedTosVersion)
+ rs.stringOpt(e.acceptedTosVersion),
+ rs.stringOpt(e.auth0Id).map(Auth0Id)
)
def apply(o: SyntaxProvider[UserRecord])(rs: WrappedResultSet): UserRecord = apply(o.resultName)(rs)
def unmarshalUserRecord(userRecord: UserRecord): SamUser =
- SamUser(userRecord.id, userRecord.googleSubjectId, userRecord.email, userRecord.azureB2cId, userRecord.enabled, userRecord.acceptedTosVersion)
+ SamUser(
+ userRecord.id,
+ userRecord.googleSubjectId,
+ userRecord.email,
+ userRecord.azureB2cId,
+ userRecord.enabled,
+ userRecord.acceptedTosVersion,
+ userRecord.auth0Id
+ )
}
diff --git a/src/main/scala/org/broadinstitute/dsde/workbench/sam/model/SamModel.scala b/src/main/scala/org/broadinstitute/dsde/workbench/sam/model/SamModel.scala
index 1e5385896..2cf19d99c 100644
--- a/src/main/scala/org/broadinstitute/dsde/workbench/sam/model/SamModel.scala
+++ b/src/main/scala/org/broadinstitute/dsde/workbench/sam/model/SamModel.scala
@@ -307,7 +307,8 @@ final case class SamUser(
email: WorkbenchEmail,
azureB2CId: Option[AzureB2CId],
enabled: Boolean,
- acceptedTosVersion: Option[String]
+ acceptedTosVersion: Option[String],
+ auth0Id: Option[Auth0Id]
) {
def toUserIdInfo = UserIdInfo(id, email, googleSubjectId)
}
diff --git a/src/main/scala/org/broadinstitute/dsde/workbench/sam/service/UserService.scala b/src/main/scala/org/broadinstitute/dsde/workbench/sam/service/UserService.scala
index d9f14edf6..0b240e8e1 100644
--- a/src/main/scala/org/broadinstitute/dsde/workbench/sam/service/UserService.scala
+++ b/src/main/scala/org/broadinstitute/dsde/workbench/sam/service/UserService.scala
@@ -102,6 +102,9 @@ class UserService(val directoryDAO: DirectoryDAO, val cloudExtensions: CloudExte
_ <- user.azureB2CId.traverse { azureB2CId =>
directoryDAO.setUserAzureB2CId(uid, azureB2CId, samRequestContext)
}
+ _ <- user.auth0Id.traverse { auth0Id =>
+ directoryDAO.setUserAuth0Id(uid, auth0Id, samRequestContext)
+ }
_ <- IO.fromFuture(IO(cloudExtensions.onGroupUpdate(groups, samRequestContext)))
updatedUser <- directoryDAO.loadUser(uid, samRequestContext)
} yield updatedUser.getOrElse(