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

API: unable to delete users who have published (usernotification table) #2824

Closed
pdurbin opened this issue Dec 14, 2015 · 7 comments
Closed
Assignees
Labels
Component: Code Infrastructure formerly "Feature: Code Infrastructure" Feature: API Type: Bug a defect
Milestone

Comments

@pdurbin
Copy link
Member

pdurbin commented Dec 14, 2015

I'm in the 4.3.2 branch (e10e6fb) writing API integration tests as part of #2746 and now that I'm starting to publish dataverses and datasets via API I'm no longer able to delete the users that created them. I'm getting this:

org.postgresql.util.PSQLException: ERROR: update or delete on table "authenticateduser" violates foreign key constraint "fk_usernotification_user_id" on table "usernotification"
Detail: Key (id)=(54) is still referenced from table "usernotification".

As I mentioned on the Google Group recently at https://groups.google.com/forum/#!topic/dataverse-community/NXnVDrh1-h8 I'm not sure how much we want to support this operation of deleting users but for testing it can be useful.

@pdurbin pdurbin added Feature: API Type: Bug a defect Component: Code Infrastructure formerly "Feature: Code Infrastructure" labels Dec 14, 2015
@pdurbin pdurbin added this to the 4.2.3 milestone Dec 14, 2015
@pdurbin
Copy link
Member Author

pdurbin commented Dec 14, 2015

Fixed in ff12dfb

To test:

curl -X DELETE http://localhost:8080/api/admin/authenticatedUsers/jdoe

@kcondon
Copy link
Contributor

kcondon commented Jan 6, 2016

Getting 500 error when deleting user with published dataset:

[2016-01-06T12:32:04.730-0500] [glassfish 4.1] [INFO] [] [edu.harvard.iq.dataverse.DatasetPage] [tid: _ThreadID=52 _ThreadName=jk-connector(1)] [timeMillis: 1452101524730] [levelValue: 800] [[ retreived version: id: 60, state: RELEASED]]

[2016-01-06T12:32:35.886-0500] [glassfish 4.1] [INFO] [] [edu.harvard.iq.dataverse.authorization.AuthenticationServiceBean] [tid: _ThreadID=27 _ThreadName=http-listener-1(1)] [timeMillis: 1452101555886] [levelV
alue: 800] [[
When looking up API token for edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser@1a caught javax.persistence.NoResultException: getSingleResult() did not retrieve any entities.]]

[2016-01-06T12:32:35.914-0500] [glassfish 4.1] [WARNING] [] [org.eclipse.persistence.session.file:/usr/local/glassfish4/glassfish/domains/domain1/applications/dataverse-4.2.3/WEB-INF/classes/_VDCNet-ejbPU] [tid
: _ThreadID=27 _ThreadName=http-listener-1(1)] [timeMillis: 1452101555914] [levelValue: 900] [[

Local Exception Stack:
Exception [EclipseLink-4002](Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: update or delete on table "authenticateduser" violates foreign key constraint "fk_dvobject_releaseuser_id" on table "dvobject"
Detail: Key (id)=(26) is still referenced from table "dvobject".
Error Code: 0
Call: DELETE FROM AUTHENTICATEDUSER WHERE (ID = ?)
bind => [1 parameter bound]
Query: DeleteObjectQuery(edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser@1a)
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.processExceptionForCommError(DatabaseAccessor.java:1611)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:898)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:962)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:631)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558)
at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:2002)
at org.eclipse.persistence.sessions.server.ClientSession.executeCall(ClientSession.java:298)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228)
at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.deleteObject(DatasourceCallQueryMechanism.java:210)
at org.eclipse.persistence.internal.queries.StatementQueryMechanism.deleteObject(StatementQueryMechanism.java:104)
at org.eclipse.persistence.queries.DeleteObjectQuery.executeDatabaseQuery(DeleteObjectQuery.java:218)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899)
at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:798)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:108)
at org.eclipse.persistence.queries.DeleteObjectQuery.executeInUnitOfWorkObjectLevelModifyQuery(DeleteObjectQuery.java:119)
at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:85)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1804)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1786)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1737)
at org.eclipse.persistence.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:336)
at org.eclipse.persistence.internal.sessions.CommitManager.deleteAllObjects(CommitManager.java:290)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1444)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1531)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.issueSQLbeforeCompletion(UnitOfWorkImpl.java:3168)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.issueSQLbeforeCompletion(RepeatableWriteUnitOfWork.java:352)
at org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:158)
at org.eclipse.persistence.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:68)
at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:452)
at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:854)
at com.sun.ejb.containers.EJBContainerTransactionManager.completeNewTx(EJBContainerTransactionManager.java:719)
at com.sun.ejb.containers.EJBContainerTransactionManager.postInvokeTx(EJBContainerTransactionManager.java:503)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4566)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2074)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2044)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:220)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
at com.sun.proxy.$Proxy2030.deleteAuthenticatedUser(Unknown Source)
at edu.harvard.iq.dataverse.api.EJB31_Generated__Admin__Intf____Bean.deleteAuthenticatedUser(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.glassfish.jersey.server.model.internal.ResourceMethodInvocationHandlerFactory$1.invoke(ResourceMethodInvocationHandlerFactory.java:81)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher$1.run(AbstractJavaResourceMethodDispatcher.java:151)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.invoke(AbstractJavaResourceMethodDispatcher.java:171)
at org.glassfish.jersey.server.model.internal.JavaResourceMethodDispatcherProvider$ResponseOutInvoker.doDispatch(JavaResourceMethodDispatcherProvider.java:152)
at org.glassfish.jersey.server.model.internal.AbstractJavaResourceMethodDispatcher.dispatch(AbstractJavaResourceMethodDispatcher.java:104)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:387)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:331)
at org.glassfish.jersey.server.model.ResourceMethodInvoker.apply(ResourceMethodInvoker.java:103)
at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:271)
at org.glassfish.jersey.internal.Errors$1.call(Errors.java:267)
at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
at org.glassfish.jersey.internal.Errors.process(Errors.java:267)
at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:297)
at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:254)
at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:1028)
at org.glassfish.jersey.servlet.WebComponent.service(WebComponent.java:372)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:381)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:344)
at org.glassfish.jersey.servlet.ServletContainer.service(ServletContainer.java:221)
at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:344)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.ocpsoft.rewrite.servlet.RewriteFilter.doFilter(RewriteFilter.java:205)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at edu.harvard.iq.dataverse.api.ApiBlockingFilter.doFilter(ApiBlockingFilter.java:161)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at edu.harvard.iq.dataverse.api.ApiRouter.doFilter(ApiRouter.java:30)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.apache.catalina.core.ApplicationDispatcher.doInvoke(ApplicationDispatcher.java:873)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:739)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:575)
at org.apache.catalina.core.ApplicationDispatcher.doDispatch(ApplicationDispatcher.java:546)
at org.apache.catalina.core.ApplicationDispatcher.dispatch(ApplicationDispatcher.java:428)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:378)
at edu.harvard.iq.dataverse.api.ApiRouter.doFilter(ApiRouter.java:34)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:214)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:316)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:412)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:282)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.postgresql.util.PSQLException: ERROR: update or delete on table "authenticateduser" violates foreign key constraint "fk_dvobject_releaseuser_id" on table "dvobject"
Detail: Key (id)=(26) is still referenced from table "dvobject".
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2101)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1834)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:510)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:386)
at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:332)
at sun.reflect.GeneratedMethodAccessor7768.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.postgresql.ds.jdbc23.AbstractJdbc23PooledConnection$StatementHandler.invoke(AbstractJdbc23PooledConnection.java:453)
at com.sun.proxy.$Proxy377.executeUpdate(Unknown Source)
at com.sun.gjc.spi.base.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:125)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:890)
... 113 more

@pdurbin
Copy link
Member Author

pdurbin commented Jan 6, 2016

Getting 500 error when deleting user with published dataset...

Internal Exception: org.postgresql.util.PSQLException: ERROR: update or delete on table "authenticateduser" violates foreign key constraint "fk_dvobject_releaseuser_id" on table "dvobject"

Right. Such an error is expected for now. Here's the Javadoc on the deleteAuthenticatedUser method (emphasis mine):

Use with care! This method was written primarily for developers interested in API testing who want to:

  1. Create a temporary user and get an API token.
  2. Do some work with that API token.
  3. Delete all the stuff that was created with the API token.
  4. Delete the temporary user.

Before calling this method, make sure you've deleted all the stuff tied to the user, including stuff they've created, role assignments, group assignments, etc. Longer term, the intention is to have a "disableAuthenticatedUser" method/command.

Interest in deleting users has been expressed at https://groups.google.com/forum/#!topic/dataverse-community/NXnVDrh1-h8 so maybe we should make this more real and document it? Personally, I would prioritize the "disable user" case in #2419 which is probably more common.

@scolapasta had some feedback about my fix at ff12dfb about how a cascade delete, if done carefully would be cleaner. I'll pass this to him to decide what additional changes he wants in 4.2.3 (if any) since we're now in code freeze.

My question is what should happen to the releaseuser_id (the person who published the dataset or whatever) on DvObjects when that user is deleted? Should it be changed to the id of some system account?

@pdurbin pdurbin assigned scolapasta and unassigned pdurbin Jan 6, 2016
@pdurbin
Copy link
Member Author

pdurbin commented Jan 6, 2016

My question is what should happen to the releaseuser_id (the person who published the dataset or whatever) on DvObjects when that user is deleted?

I raised this specific question about the "releaseuser" at #2825.

@scolapasta
Copy link
Contributor

We shouldn't delete users who have "done" something - created a dataset, released a dataset, etc.

Deleting user notifications and role assignments is fine. But we do need to track who created or released - in those cases, if anything, we would want to disable them as @pdurbin metioned and is tracked by #2419.

However, we should make the API call cleaner, I think, by checking for these things first and proviing a friendlier message.

@scolapasta
Copy link
Contributor

OK, #2825 is now tracking the cleaner API call, passing this one to QA.

@kcondon
Copy link
Contributor

kcondon commented Jan 8, 2016

Confirmed was able to delete user with notifications after removing created objects.
Closing.

@kcondon kcondon closed this as completed Jan 8, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: Code Infrastructure formerly "Feature: Code Infrastructure" Feature: API Type: Bug a defect
Projects
None yet
Development

No branches or pull requests

3 participants