Skip to content

Commit

Permalink
Allow Superusers to Join Organizations Unlisted (#5151)
Browse files Browse the repository at this point in the history
* [WIP] allow superusers to join organizations unlisted
* use isUnlisted property in scala code
* migrations guide
* adapt test db
* Merge branch 'master' into unlisted-superusers
  • Loading branch information
fm3 authored Feb 11, 2021
1 parent 1a06774 commit 20389cc
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
- The "Meshes" tab was overhauled, so that it displays generated isosurfaces and imported meshes. Generated isosurfaces can be jumped to, reloaded, downloaded and removed. [#4917](https://github.com/scalableminds/webknossos/pull/4917)
- Added an explicit `/signup` (or `/auth/signup`) route. [#5091](https://github.com/scalableminds/webknossos/pull/5091/files)
- Added the annotation option "center new nodes" to switch whether newly created nodes should be centered or not. [#4150](https://github.com/scalableminds/webknossos/pull/5112)
- For webKnossos maintenance, superUsers can now join organizations without being listed as a user there. [#5151](https://github.com/scalableminds/webknossos/pull/5151)

### Changed
- Make the isosurface feature in the meshes tab more robust. If a request fails, a retry is initiated. [#5102](https://github.com/scalableminds/webknossos/pull/5102)
Expand Down
1 change: 1 addition & 0 deletions MIGRATIONS.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ User-facing changes are documented in the [changelog](CHANGELOG.released.md).
- [062-dataset-uploader.sql](conf/evolutions/062-dataset-uploader.sql)
- [063-novelUserExperienceinfos.sql](conf/evolutions/063-novelUserExperienceinfos.sql)
- [064-experienceDomains-per-orga.sql](conf/evolutions/064-experienceDomains-per-orga.sql)
- [065-unlisted-superusers.sql](conf/evolutions/065-unlisted-superusers.sql)
1 change: 1 addition & 0 deletions app/controllers/InitialDataController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Samplecountry
userService.createLoginInfo(userId),
isAdmin = true,
isDatasetManager = true,
isUnlisted = false,
isDeactivated = false,
lastTaskTypeId = None
)
Expand Down
12 changes: 9 additions & 3 deletions app/models/user/User.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ case class User(
isAdmin: Boolean,
isDatasetManager: Boolean,
isDeactivated: Boolean,
isUnlisted: Boolean,
created: Long = System.currentTimeMillis(),
lastTaskTypeId: Option[ObjectId] = None,
isDeleted: Boolean = false
Expand Down Expand Up @@ -80,6 +81,7 @@ class UserDAO @Inject()(sqlClient: SQLClient)(implicit ec: ExecutionContext)
r.isadmin,
r.isdatasetmanager,
r.isdeactivated,
r.isunlisted,
r.created.getTime,
r.lasttasktypeid.map(ObjectId(_)),
r.isdeleted
Expand All @@ -104,7 +106,9 @@ class UserDAO @Inject()(sqlClient: SQLClient)(implicit ec: ExecutionContext)
override def findAll(implicit ctx: DBAccessContext): Fox[List[User]] =
for {
accessQuery <- readAccessQuery
r <- run(sql"select #${columns} from #${existingCollectionName} where #${accessQuery}".as[UsersRow])
r <- run(
sql"select #${columns} from #${existingCollectionName} where isUnlisted = false and #${accessQuery}"
.as[UsersRow])
parsed <- Fox.combined(r.toList.map(parse))
} yield parsed

Expand All @@ -117,6 +121,7 @@ class UserDAO @Inject()(sqlClient: SQLClient)(implicit ec: ExecutionContext)
r <- run(sql"""select #${columnsWithPrefix("u.")}
from (select #${columns} from #${existingCollectionName} where #${accessQuery}) u join webknossos.user_team_roles on u._id = webknossos.user_team_roles._user
where webknossos.user_team_roles._team in #${writeStructTupleWithQuotes(teams.map(_.id))}
and u.isUnlisted = false
and (u.isDeactivated = false or u.isDeactivated = ${includeDeactivated})
order by _id""".as[UsersRow])
parsed <- Fox.combined(r.toList.map(parse))
Expand Down Expand Up @@ -190,11 +195,12 @@ class UserDAO @Inject()(sqlClient: SQLClient)(implicit ec: ExecutionContext)
def insertOne(u: User): Fox[Unit] =
for {
_ <- run(sqlu"""insert into webknossos.users(_id, _multiUser, _organization, firstName, lastName, lastActivity,
userConfiguration, isDeactivated, isAdmin, isDatasetManager, created, isDeleted)
userConfiguration, isDeactivated, isAdmin, isDatasetManager, isUnlisted, created, isDeleted)
values(${u._id}, ${u._multiUser}, ${u._organization}, ${u.firstName}, ${u.lastName},
${new java.sql.Timestamp(u.lastActivity)}, '#${sanitize(
Json.toJson(u.userConfiguration).toString)}',
${u.isDeactivated}, ${u.isAdmin}, ${u.isDatasetManager}, ${new java.sql.Timestamp(u.created)}, ${u.isDeleted})
${u.isDeactivated}, ${u.isAdmin}, ${u.isDatasetManager}, ${u.isUnlisted}, ${new java.sql.Timestamp(
u.created)}, ${u.isDeleted})
""")
} yield ()

Expand Down
11 changes: 8 additions & 3 deletions app/models/user/UserService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ class UserService @Inject()(conf: WkConf,
isAdmin,
isDatasetManager = false,
isDeactivated = !isActive,
isUnlisted = false,
lastTaskTypeId = None
)
_ <- userDAO.insertOne(user)
Expand All @@ -128,12 +129,15 @@ class UserService @Inject()(conf: WkConf,
.findOneByOrgaAndMultiUser(organizationId, originalUser._multiUser)(GlobalAccessContext)
.futureBox
_ <- if (multiUser.isSuperUser && existingIdentity.isEmpty) {
joinOrganization(originalUser, organizationId, autoActivate = true, isAdmin = true)
joinOrganization(originalUser, organizationId, autoActivate = true, isAdmin = true, isUnlisted = true)
} else Fox.successful(())
} yield ()

def joinOrganization(originalUser: User, organizationId: ObjectId, autoActivate: Boolean, isAdmin: Boolean = false)(
implicit ctx: DBAccessContext): Fox[User] =
def joinOrganization(originalUser: User,
organizationId: ObjectId,
autoActivate: Boolean,
isAdmin: Boolean = false,
isUnlisted: Boolean = false)(implicit ctx: DBAccessContext): Fox[User] =
for {
newUserId <- Fox.successful(ObjectId.generate)
organizationTeamId <- organizationDAO.findOrganizationTeamId(organizationId)
Expand All @@ -148,6 +152,7 @@ class UserService @Inject()(conf: WkConf,
isDatasetManager = false,
isDeactivated = !autoActivate,
lastTaskTypeId = None,
isUnlisted = isUnlisted,
created = System.currentTimeMillis()
)
_ <- userDAO.insertOne(user)
Expand Down
27 changes: 27 additions & 0 deletions conf/evolutions/065-unlisted-superusers.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
-- https://github.com/scalableminds/webknossos/pull/TODO

START TRANSACTION;

DROP VIEW webknossos.userInfos;
DROP VIEW webknossos.users_;

ALTER TABLE webknossos.users ADD COLUMN isUnlisted BOOLEAN NOT NULL DEFAULT FALSE;

CREATE VIEW webknossos.users_ AS SELECT * FROM webknossos.users WHERE NOT isDeleted;


-- identical to previous (has to be dropped first because of the dependency)
CREATE VIEW webknossos.userInfos AS
SELECT
u._id AS _user, m.email, u.firstName, u.lastname, o.displayName AS organization_displayName,
u.isDeactivated, u.isDatasetManager, u.isAdmin, m.isSuperUser,
u._organization, o.name AS organization_name, u.created AS user_created,
m.created AS multiuser_created, u._multiUser, m._lastLoggedInIdentity, u.lastActivity
FROM webknossos.users_ u
JOIN webknossos.organizations_ o ON u._organization = o._id
JOIN webknossos.multiUsers_ m on u._multiUser = m._id;


UPDATE webknossos.releaseInformation SET schemaVersion = 65;

COMMIT TRANSACTION;
25 changes: 25 additions & 0 deletions conf/evolutions/reversions/065-unlisted-superusers.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
START TRANSACTION;

DROP VIEW webknossos.userInfos;
DROP VIEW webknossos.users_;

ALTER TABLE webknossos.users DROP COLUMN isUnlisted;

CREATE VIEW webknossos.users_ AS SELECT * FROM webknossos.users WHERE NOT isDeleted;


-- identical to previous (has to be dropped first because of the dependency)
CREATE VIEW webknossos.userInfos AS
SELECT
u._id AS _user, m.email, u.firstName, u.lastname, o.displayName AS organization_displayName,
u.isDeactivated, u.isDatasetManager, u.isAdmin, m.isSuperUser,
u._organization, o.name AS organization_name, u.created AS user_created,
m.created AS multiuser_created, u._multiUser, m._lastLoggedInIdentity, u.lastActivity
FROM webknossos.users_ u
JOIN webknossos.organizations_ o ON u._organization = o._id
JOIN webknossos.multiUsers_ m on u._multiUser = m._id;


UPDATE webknossos.releaseInformation SET schemaVersion = 64;

COMMIT TRANSACTION;
12 changes: 6 additions & 6 deletions test/db/users.csv
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
_id,_multiUser,_organization,firstName,lastName,lastActivity,userConfiguration,isDeactivated,isAdmin,isDatasetManager,created,isDeleted,lasttasktypeid
'570b9f4d2a7c0e4d008da6ef','8fb0c6a674d0af7b003b23ea','5ab0c6a674d0af7b003b23ac','user_A','BoyA','2016-04-11T12:57:49.053Z','{"configuration":{"sortCommentsAsc":true,"messages":[{"success":"Your configuration got updated"}],"isosurfaceDisplay":false,"moveValue":300,"rotateValue":0.01,"particleSize":5,"scale":1,"clippingDistance":50,"mouseRotateValue":0.004,"displayCrosshair":true,"crosshairSize":0.1,"sortTreesByName":false,"keyboardDelay":200,"motionsensorActive":false,"moveValue3d":300,"keyboardActive":true,"isosurfaceResolution":80,"isosurfaceBBsize":1,"mouseActive":true,"newNodeNewTree":false,"segmentationOpacity":20,"inverseY":false,"sphericalCapRadius":140,"clippingDistanceArbitrary":64,"scaleValue":0.05,"tdViewDisplayPlanes":true,"overrideNodeRadius":true,"renderComments":false,"zoom":2,"inverseX":false,"gamepadActive":false,"dynamicSpaceDirection":true,"firstVisToggle":true}}',f,t,t,'2016-04-11T12:57:49.000Z',,f
'670b9f4d2a7c0e4d008da6ef','8fb0c6a674d0af7b003b23eb','5ab0c6a674d0af7b003b23ac','user_B','BoyB','2016-04-12T12:57:49.053Z','{"configuration":{"sortCommentsAsc":true,"messages":[{"success":"Your configuration got updated"}],"isosurfaceDisplay":false,"moveValue":300,"rotateValue":0.01,"particleSize":5,"scale":1,"clippingDistance":50,"mouseRotateValue":0.004,"displayCrosshair":true,"crosshairSize":0.1,"sortTreesByName":false,"keyboardDelay":200,"motionsensorActive":false,"moveValue3d":300,"keyboardActive":true,"isosurfaceResolution":80,"isosurfaceBBsize":1,"mouseActive":true,"newNodeNewTree":false,"segmentationOpacity":20,"inverseY":false,"sphericalCapRadius":140,"clippingDistanceArbitrary":64,"scaleValue":0.05,"tdViewDisplayPlanes":true,"overrideNodeRadius":true,"renderComments":false,"zoom":2,"inverseX":false,"gamepadActive":false,"dynamicSpaceDirection":true,"firstVisToggle":true}}',f,f,t,'2016-04-11T12:57:49.000Z',,f
'770b9f4d2a7c0e4d008da6ef','8fb0c6a674d0af7b003b23ec','5ab0c6a674d0af7b003b23ac','user_C','BoyC','2016-04-13T12:57:49.053Z','{"configuration":{"sortCommentsAsc":true,"messages":[{"success":"Your configuration got updated"}],"isosurfaceDisplay":false,"moveValue":300,"rotateValue":0.01,"particleSize":5,"scale":1,"clippingDistance":50,"mouseRotateValue":0.004,"displayCrosshair":true,"crosshairSize":0.1,"sortTreesByName":false,"keyboardDelay":200,"motionsensorActive":false,"moveValue3d":300,"keyboardActive":true,"isosurfaceResolution":80,"isosurfaceBBsize":1,"mouseActive":true,"newNodeNewTree":false,"segmentationOpacity":20,"inverseY":false,"sphericalCapRadius":140,"clippingDistanceArbitrary":64,"scaleValue":0.05,"tdViewDisplayPlanes":true,"overrideNodeRadius":true,"renderComments":false,"zoom":2,"inverseX":false,"gamepadActive":false,"dynamicSpaceDirection":true,"firstVisToggle":true}}',f,f,f,'2016-04-11T12:57:49.000Z',,f
'870b9f4d2a7c0e4d008da6ef','8fb0c6a674d0af7b003b23ed','5ab0c6a674d0af7b003b23ac','user_D','BoyD','2016-04-14T12:57:49.053Z','{"configuration":{"sortCommentsAsc":true,"messages":[{"success":"Your configuration got updated"}],"isosurfaceDisplay":false,"moveValue":300,"rotateValue":0.01,"particleSize":5,"scale":1,"clippingDistance":50,"mouseRotateValue":0.004,"displayCrosshair":true,"crosshairSize":0.1,"sortTreesByName":false,"keyboardDelay":200,"motionsensorActive":false,"moveValue3d":300,"keyboardActive":true,"isosurfaceResolution":80,"isosurfaceBBsize":1,"mouseActive":true,"newNodeNewTree":false,"segmentationOpacity":20,"inverseY":false,"sphericalCapRadius":140,"clippingDistanceArbitrary":64,"scaleValue":0.05,"tdViewDisplayPlanes":true,"overrideNodeRadius":true,"renderComments":false,"zoom":2,"inverseX":false,"gamepadActive":false,"dynamicSpaceDirection":true,"firstVisToggle":true}}',f,f,f,'2016-04-11T12:57:49.000Z',,f
'970b9f4d2a7c0e4d008da6ef','8fb0c6a674d0af7b003b23ee','6bb0c6a674d0af7b003b23bd','user_E','BoyE','2016-04-06T12:57:49.053Z','{"configuration":{"sortCommentsAsc":true,"messages":[{"success":"Your configuration got updated"}],"isosurfaceDisplay":false,"moveValue":300,"rotateValue":0.01,"particleSize":5,"scale":1,"clippingDistance":50,"mouseRotateValue":0.004,"displayCrosshair":true,"crosshairSize":0.1,"sortTreesByName":false,"keyboardDelay":200,"motionsensorActive":false,"moveValue3d":300,"keyboardActive":true,"isosurfaceResolution":80,"isosurfaceBBsize":1,"mouseActive":true,"newNodeNewTree":false,"segmentationOpacity":20,"inverseY":false,"sphericalCapRadius":140,"clippingDistanceArbitrary":64,"scaleValue":0.05,"tdViewDisplayPlanes":true,"overrideNodeRadius":true,"renderComments":false,"zoom":2,"inverseX":false,"gamepadActive":false,"dynamicSpaceDirection":true,"firstVisToggle":true}}',f,t,f,'2016-04-11T12:57:49.000Z',,f
_id,_multiUser,_organization,firstName,lastName,lastActivity,userConfiguration,isDeactivated,isAdmin,isDatasetManager,created,lasttasktypeid,isUnlisted,isDeleted
'570b9f4d2a7c0e4d008da6ef','8fb0c6a674d0af7b003b23ea','5ab0c6a674d0af7b003b23ac','user_A','BoyA','2016-04-11T12:57:49.053Z','{"configuration":{"sortCommentsAsc":true,"messages":[{"success":"Your configuration got updated"}],"isosurfaceDisplay":false,"moveValue":300,"rotateValue":0.01,"particleSize":5,"scale":1,"clippingDistance":50,"mouseRotateValue":0.004,"displayCrosshair":true,"crosshairSize":0.1,"sortTreesByName":false,"keyboardDelay":200,"motionsensorActive":false,"moveValue3d":300,"keyboardActive":true,"isosurfaceResolution":80,"isosurfaceBBsize":1,"mouseActive":true,"newNodeNewTree":false,"segmentationOpacity":20,"inverseY":false,"sphericalCapRadius":140,"clippingDistanceArbitrary":64,"scaleValue":0.05,"tdViewDisplayPlanes":true,"overrideNodeRadius":true,"renderComments":false,"zoom":2,"inverseX":false,"gamepadActive":false,"dynamicSpaceDirection":true,"firstVisToggle":true}}',f,t,t,'2016-04-11T12:57:49.000Z',,f,f
'670b9f4d2a7c0e4d008da6ef','8fb0c6a674d0af7b003b23eb','5ab0c6a674d0af7b003b23ac','user_B','BoyB','2016-04-12T12:57:49.053Z','{"configuration":{"sortCommentsAsc":true,"messages":[{"success":"Your configuration got updated"}],"isosurfaceDisplay":false,"moveValue":300,"rotateValue":0.01,"particleSize":5,"scale":1,"clippingDistance":50,"mouseRotateValue":0.004,"displayCrosshair":true,"crosshairSize":0.1,"sortTreesByName":false,"keyboardDelay":200,"motionsensorActive":false,"moveValue3d":300,"keyboardActive":true,"isosurfaceResolution":80,"isosurfaceBBsize":1,"mouseActive":true,"newNodeNewTree":false,"segmentationOpacity":20,"inverseY":false,"sphericalCapRadius":140,"clippingDistanceArbitrary":64,"scaleValue":0.05,"tdViewDisplayPlanes":true,"overrideNodeRadius":true,"renderComments":false,"zoom":2,"inverseX":false,"gamepadActive":false,"dynamicSpaceDirection":true,"firstVisToggle":true}}',f,f,t,'2016-04-11T12:57:49.000Z',,f,f
'770b9f4d2a7c0e4d008da6ef','8fb0c6a674d0af7b003b23ec','5ab0c6a674d0af7b003b23ac','user_C','BoyC','2016-04-13T12:57:49.053Z','{"configuration":{"sortCommentsAsc":true,"messages":[{"success":"Your configuration got updated"}],"isosurfaceDisplay":false,"moveValue":300,"rotateValue":0.01,"particleSize":5,"scale":1,"clippingDistance":50,"mouseRotateValue":0.004,"displayCrosshair":true,"crosshairSize":0.1,"sortTreesByName":false,"keyboardDelay":200,"motionsensorActive":false,"moveValue3d":300,"keyboardActive":true,"isosurfaceResolution":80,"isosurfaceBBsize":1,"mouseActive":true,"newNodeNewTree":false,"segmentationOpacity":20,"inverseY":false,"sphericalCapRadius":140,"clippingDistanceArbitrary":64,"scaleValue":0.05,"tdViewDisplayPlanes":true,"overrideNodeRadius":true,"renderComments":false,"zoom":2,"inverseX":false,"gamepadActive":false,"dynamicSpaceDirection":true,"firstVisToggle":true}}',f,f,f,'2016-04-11T12:57:49.000Z',,f,f
'870b9f4d2a7c0e4d008da6ef','8fb0c6a674d0af7b003b23ed','5ab0c6a674d0af7b003b23ac','user_D','BoyD','2016-04-14T12:57:49.053Z','{"configuration":{"sortCommentsAsc":true,"messages":[{"success":"Your configuration got updated"}],"isosurfaceDisplay":false,"moveValue":300,"rotateValue":0.01,"particleSize":5,"scale":1,"clippingDistance":50,"mouseRotateValue":0.004,"displayCrosshair":true,"crosshairSize":0.1,"sortTreesByName":false,"keyboardDelay":200,"motionsensorActive":false,"moveValue3d":300,"keyboardActive":true,"isosurfaceResolution":80,"isosurfaceBBsize":1,"mouseActive":true,"newNodeNewTree":false,"segmentationOpacity":20,"inverseY":false,"sphericalCapRadius":140,"clippingDistanceArbitrary":64,"scaleValue":0.05,"tdViewDisplayPlanes":true,"overrideNodeRadius":true,"renderComments":false,"zoom":2,"inverseX":false,"gamepadActive":false,"dynamicSpaceDirection":true,"firstVisToggle":true}}',f,f,f,'2016-04-11T12:57:49.000Z',,f,f
'970b9f4d2a7c0e4d008da6ef','8fb0c6a674d0af7b003b23ee','6bb0c6a674d0af7b003b23bd','user_E','BoyE','2016-04-06T12:57:49.053Z','{"configuration":{"sortCommentsAsc":true,"messages":[{"success":"Your configuration got updated"}],"isosurfaceDisplay":false,"moveValue":300,"rotateValue":0.01,"particleSize":5,"scale":1,"clippingDistance":50,"mouseRotateValue":0.004,"displayCrosshair":true,"crosshairSize":0.1,"sortTreesByName":false,"keyboardDelay":200,"motionsensorActive":false,"moveValue3d":300,"keyboardActive":true,"isosurfaceResolution":80,"isosurfaceBBsize":1,"mouseActive":true,"newNodeNewTree":false,"segmentationOpacity":20,"inverseY":false,"sphericalCapRadius":140,"clippingDistanceArbitrary":64,"scaleValue":0.05,"tdViewDisplayPlanes":true,"overrideNodeRadius":true,"renderComments":false,"zoom":2,"inverseX":false,"gamepadActive":false,"dynamicSpaceDirection":true,"firstVisToggle":true}}',f,t,f,'2016-04-11T12:57:49.000Z',,f,f
3 changes: 2 additions & 1 deletion tools/postgres/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ START TRANSACTION;
CREATE TABLE webknossos.releaseInformation (
schemaVersion BIGINT NOT NULL
);
INSERT INTO webknossos.releaseInformation(schemaVersion) values(64);
INSERT INTO webknossos.releaseInformation(schemaVersion) values(65);
COMMIT TRANSACTION;

CREATE TABLE webknossos.analytics(
Expand Down Expand Up @@ -290,6 +290,7 @@ CREATE TABLE webknossos.users(
isDatasetManager BOOLEAN NOT NULL DEFAULT false,
created TIMESTAMPTZ NOT NULL DEFAULT NOW(),
lastTaskTypeId CHAR(24) DEFAULT NULL,
isUnlisted BOOLEAN NOT NULL DEFAULT FALSE,
isDeleted BOOLEAN NOT NULL DEFAULT false,
UNIQUE (_multiUser, _organization),
CONSTRAINT userConfigurationIsJsonObject CHECK(jsonb_typeof(userConfiguration) = 'object')
Expand Down

0 comments on commit 20389cc

Please sign in to comment.