Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Superusers to Join Organizations Unlisted #5151

Merged
merged 5 commits into from
Feb 11, 2021
Merged
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
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