diff --git a/zanata-war/src/main/java/org/zanata/security/ZanataIdentity.java b/zanata-war/src/main/java/org/zanata/security/ZanataIdentity.java index 26b611c5ae..78b357c8f8 100644 --- a/zanata-war/src/main/java/org/zanata/security/ZanataIdentity.java +++ b/zanata-war/src/main/java/org/zanata/security/ZanataIdentity.java @@ -111,9 +111,9 @@ public void checkLoggedIn() @Observer("org.jboss.seam.preDestroyContext.SESSION") public void logout() { - if (Events.exists() && getPrincipal() != null) + if (Events.exists() && getCredentials() != null) { - Events.instance().raiseEvent(USER_LOGOUT_EVENT, getPrincipal().getName()); + Events.instance().raiseEvent(USER_LOGOUT_EVENT, getCredentials().getUsername()); } super.logout(); } diff --git a/zanata-war/src/main/java/org/zanata/webtrans/server/TranslationWorkspaceImpl.java b/zanata-war/src/main/java/org/zanata/webtrans/server/TranslationWorkspaceImpl.java index 4541d8242d..9fca9bded2 100644 --- a/zanata-war/src/main/java/org/zanata/webtrans/server/TranslationWorkspaceImpl.java +++ b/zanata-war/src/main/java/org/zanata/webtrans/server/TranslationWorkspaceImpl.java @@ -152,12 +152,20 @@ public boolean removeEditorClient(EditorClientId editorClientId) PersonSessionDetails details = sessions.remove(editorClientId); if (details != null) { - // TODO remove editorClientId from httpSessionToEditorClientId, instead of waiting until logout - log.info("Removed user {0} with editorClientId {1} from workspace {2}", details.getPerson().getId(), editorClientId, workspaceContext); - return true; + String httpSessionId = editorClientId.getHttpSessionId(); + Collection clientIds = httpSessionToEditorClientId.get(httpSessionId); + if (clientIds != null) + { + clientIds.remove(editorClientId); + log.info("Removed user {0} with editorClientId {1} from workspace {2}", details.getPerson().getId(), editorClientId, workspaceContext); + return true; + } + else + { + log.warn("Unable to remove user {0} with editorClientId {1} from workspace {2}", details.getPerson().getId(), editorClientId, workspaceContext); + } } } - return false; } diff --git a/zanata-war/src/main/java/org/zanata/webtrans/server/TranslationWorkspaceManagerImpl.java b/zanata-war/src/main/java/org/zanata/webtrans/server/TranslationWorkspaceManagerImpl.java index 18adaf676c..9fdac0550e 100644 --- a/zanata-war/src/main/java/org/zanata/webtrans/server/TranslationWorkspaceManagerImpl.java +++ b/zanata-war/src/main/java/org/zanata/webtrans/server/TranslationWorkspaceManagerImpl.java @@ -24,6 +24,7 @@ import org.zanata.common.EntityStatus; import org.zanata.common.LocaleId; import org.zanata.dao.AccountDAO; +import org.zanata.model.HAccount; import org.zanata.model.HIterationProject; import org.zanata.model.HLocale; import org.zanata.model.HPerson; @@ -82,8 +83,24 @@ public void start() public void exitWorkspace(String username) { String httpSessionId = getSessionId(); - LOGGER.info("User logout: Removing {} from all workspaces, session: {}", username, httpSessionId); - HPerson person = accountDAO.getByUsername(username).getPerson(); + if (httpSessionId == null) + { + LOGGER.debug("Logout: null session"); + return; + } + LOGGER.info("Logout: Removing user {} from all workspaces, session: {}", username, httpSessionId); + String personName = ""; + String personEmail = ""; + HAccount account = accountDAO.getByUsername(username); + if (account != null) + { + HPerson person = account.getPerson(); + if (person != null) + { + personName = person.getName(); + personEmail = person.getEmail(); + } + } ImmutableSet workspaceSet = ImmutableSet.copyOf(workspaceMap.values()); for (TranslationWorkspace workspace : workspaceSet) { @@ -92,7 +109,7 @@ public void exitWorkspace(String username) { LOGGER.info("Publishing ExitWorkspace event for user {} with editorClientId {} from workspace {}", new Object[] { username, editorClientId, workspace.getWorkspaceContext() }); // Send GWT Event to client to update the userlist - ExitWorkspace event = new ExitWorkspace(editorClientId, new Person(new PersonId(username), person.getName(), gravatarServiceImpl.getUserImageUrl(16, person.getEmail()))); + ExitWorkspace event = new ExitWorkspace(editorClientId, new Person(new PersonId(username), personName, gravatarServiceImpl.getUserImageUrl(16, personEmail))); workspace.publish(event); } } diff --git a/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/ActivateWorkspaceHandler.java b/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/ActivateWorkspaceHandler.java index 687935ce36..8e34bba24d 100644 --- a/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/ActivateWorkspaceHandler.java +++ b/zanata-war/src/main/java/org/zanata/webtrans/server/rpc/ActivateWorkspaceHandler.java @@ -77,7 +77,7 @@ public ActivateWorkspaceResult execute(ActivateWorkspaceAction action, Execution WorkspaceId workspaceId = action.getWorkspaceId(); TranslationWorkspace workspace = translationWorkspaceManager.getOrRegisterWorkspace(workspaceId); String httpSessionId = ServletContexts.instance().getRequest().getSession().getId(); - EditorClientId editorClientId = new EditorClientId(httpSessionId + ":" + generateEditorClientNum()); + EditorClientId editorClientId = new EditorClientId(httpSessionId, generateEditorClientNum()); workspace.addEditorClient(httpSessionId, editorClientId, person.getId()); // Send EnterWorkspace event to clients EnterWorkspace event = new EnterWorkspace(editorClientId, person); diff --git a/zanata-war/src/main/java/org/zanata/webtrans/shared/auth/EditorClientId.java b/zanata-war/src/main/java/org/zanata/webtrans/shared/auth/EditorClientId.java index 6c147718d9..35b8a8bff7 100644 --- a/zanata-war/src/main/java/org/zanata/webtrans/shared/auth/EditorClientId.java +++ b/zanata-war/src/main/java/org/zanata/webtrans/shared/auth/EditorClientId.java @@ -15,50 +15,83 @@ public final class EditorClientId implements Identifier, Serializable // generated private static final long serialVersionUID = 6713691712353126602L; - private String id; + private String httpSessionId; + private long editorClientNum; @SuppressWarnings("unused") private EditorClientId() { } - public EditorClientId(String id) + public EditorClientId(String httpSessionId, long editorClientNum) { - if (id == null || id.isEmpty()) + if (httpSessionId == null || httpSessionId.isEmpty()) { throw new IllegalStateException("Invalid Id"); } - this.id = id; + this.httpSessionId = httpSessionId; + this.editorClientNum = editorClientNum; } @Override public boolean equals(Object obj) { + if (this == obj) + { + return true; + } if (obj == null) + { + return false; + } + if (!(obj instanceof EditorClientId)) + { return false; - if (obj instanceof EditorClientId) + } + EditorClientId other = (EditorClientId) obj; + if (editorClientNum != other.editorClientNum) { - return ((EditorClientId) obj).id.equals(id); + return false; } - return super.equals(obj); + if (httpSessionId == null) + { + if (other.httpSessionId != null) + { + return false; + } + } + else if (!httpSessionId.equals(other.httpSessionId)) + { + return false; + } + return true; } @Override public int hashCode() { - return id.hashCode(); + final int prime = 31; + int result = 1; + result = prime * result + (int) (editorClientNum ^ (editorClientNum >>> 32)); + result = prime * result + ((httpSessionId == null) ? 0 : httpSessionId.hashCode()); + return result; + } + + public String getHttpSessionId() + { + return httpSessionId; } @Override public String toString() { - return id; + return getValue(); } @Override public String getValue() { - return id; + return httpSessionId + ":" + editorClientNum; } } diff --git a/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TranslationPresenterTest.java b/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TranslationPresenterTest.java index 2f470d4c82..6c8e554b66 100644 --- a/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TranslationPresenterTest.java +++ b/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/TranslationPresenterTest.java @@ -345,8 +345,8 @@ public void updateParticipantsOnEnterWorkspace() // expect lookup translator list Map participants = new HashMap(); - participants.put(new EditorClientId("sessionId1"), new Person(new PersonId("bob"), "Bob Smith", "http://www.gravatar.com/avatar/bob@zanata.org?d=mm&s=16")); - participants.put(new EditorClientId("sessionId2"), new Person(new PersonId("smith"), "Smith Bob", "http://www.gravatar.com/avatar/smith@zanata.org?d=mm&s=16")); + participants.put(new EditorClientId("sessionId1", 1), new Person(new PersonId("bob"), "Bob Smith", "http://www.gravatar.com/avatar/bob@zanata.org?d=mm&s=16")); + participants.put(new EditorClientId("sessionId2", 1), new Person(new PersonId("smith"), "Smith Bob", "http://www.gravatar.com/avatar/smith@zanata.org?d=mm&s=16")); capturedTranslatorListRequest = new Capture(); capturedTranslatorListRequestCallback = new Capture>(); @@ -361,13 +361,13 @@ public void updateParticipantsOnEnterWorkspace() mockWorkspaceUsersPresenter.dispatchChatAction("bob", TEST_HAS_JONINED_WORKSPACE_MESSAGE); expectLastCall(); - mockWorkspaceUsersPresenter.addTranslator(new EditorClientId("sessionId1"), new Person(new PersonId("bob"), "Bob Smith", "http://www.gravatar.com/avatar/bob@zanata.org?d=mm&s=16"), null); + mockWorkspaceUsersPresenter.addTranslator(new EditorClientId("sessionId1", 1), new Person(new PersonId("bob"), "Bob Smith", "http://www.gravatar.com/avatar/bob@zanata.org?d=mm&s=16"), null); expectLastCall(); // simulate enter workspace event EnterWorkspaceEvent event = createMock(EnterWorkspaceEvent.class); - expect(event.getEditorClientId()).andReturn(new EditorClientId("sessionId1")); + expect(event.getEditorClientId()).andReturn(new EditorClientId("sessionId1", 1)); expect(event.getPerson()).andReturn(new Person(new PersonId("bob"), "Bob Smith", "http://www.gravatar.com/avatar/bob@zanata.org?d=mm&s=16")).times(2); replay(mockDispatcher, mockDisplay, mockMessages, mockWorkspaceUsersPresenter, event); @@ -386,9 +386,9 @@ public void updateParticipantsOnExitWorkspace() // expect lookup translator list Map participants = new HashMap(); - participants.put(new EditorClientId("sessionId1"), new Person(new PersonId("john"), "John Jones", "http://www.gravatar.com/avatar/john@zanata.org?d=mm&s=16")); - participants.put(new EditorClientId("sessionId2"), new Person(new PersonId("jones"), "Jones John", "http://www.gravatar.com/avatar/jones@zanata.org?d=mm&s=16")); - participants.put(new EditorClientId("sessionId2"), new Person(new PersonId("jim"), "Jim Jones", "http://www.gravatar.com/avatar/jim@zanata.org?d=mm&s=16")); + participants.put(new EditorClientId("sessionId1", 1), new Person(new PersonId("john"), "John Jones", "http://www.gravatar.com/avatar/john@zanata.org?d=mm&s=16")); + participants.put(new EditorClientId("sessionId2", 1), new Person(new PersonId("jones"), "Jones John", "http://www.gravatar.com/avatar/jones@zanata.org?d=mm&s=16")); + participants.put(new EditorClientId("sessionId2", 1), new Person(new PersonId("jim"), "Jim Jones", "http://www.gravatar.com/avatar/jim@zanata.org?d=mm&s=16")); capturedTranslatorListRequest = new Capture(); @@ -398,13 +398,13 @@ public void updateParticipantsOnExitWorkspace() mockDisplay.setParticipantsTitle(TEST_USERS_ONLINE_MESSAGE); expectLastCall().once(); // once for now - mockWorkspaceUsersPresenter.removeTranslator(new EditorClientId("sessionId1"), new Person(new PersonId("john"), "John Jones", "http://www.gravatar.com/avatar/john@zanata.org?d=mm&s=16")); + mockWorkspaceUsersPresenter.removeTranslator(new EditorClientId("sessionId1", 1), new Person(new PersonId("john"), "John Jones", "http://www.gravatar.com/avatar/john@zanata.org?d=mm&s=16")); expectLastCall().once(); // simulate enter workspace event ExitWorkspaceEvent event = createMock(ExitWorkspaceEvent.class); - expect(event.getEditorClientId()).andReturn(new EditorClientId("sessionId1")); + expect(event.getEditorClientId()).andReturn(new EditorClientId("sessionId1", 1)); expect(event.getPerson()).andReturn(new Person(new PersonId("john"), "John Jones", "http://www.gravatar.com/avatar/john@zanata.org?d=mm&s=16")); expect(mockWorkspaceUsersPresenter.getTranslatorsSize()).andReturn(2); @@ -489,7 +489,7 @@ private void fireReadOnlyAndCheckResponse() private void setupDefaultMockExpectations() { Map people = new HashMap(); - people.put(new EditorClientId("sessionId"), new PersonSessionDetails(new Person(new PersonId("jones"), "Joey Jones", "http://www.gravatar.com/avatar/joey@zanata.org?d=mm&s=16"), null)); + people.put(new EditorClientId("sessionId", 1), new PersonSessionDetails(new Person(new PersonId("jones"), "Joey Jones", "http://www.gravatar.com/avatar/joey@zanata.org?d=mm&s=16"), null)); setupDefaultMockExpectations(people); } diff --git a/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/WorkspaceUsersPresenterTest.java b/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/WorkspaceUsersPresenterTest.java index 69b7de1c0d..60030e961d 100644 --- a/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/WorkspaceUsersPresenterTest.java +++ b/zanata-war/src/test/java/org/zanata/webtrans/client/presenter/WorkspaceUsersPresenterTest.java @@ -82,9 +82,9 @@ public void setNonEmptyUserList() Person person2 = new Person(new PersonId("person2"), "Smith John", "http://www.gravatar.com/avatar/smith@zanata.org?d=mm&s=16"); Person person3 = new Person(new PersonId("person3"), "Smohn Jith", "http://www.gravatar.com/avatar/smohn@zanata.org?d=mm&s=16"); - EditorClientId editorClientId1 = new EditorClientId("sessionId1"); - EditorClientId editorClientId2 = new EditorClientId("sessionId2"); - EditorClientId editorClientId3 = new EditorClientId("sessionId3"); + EditorClientId editorClientId1 = new EditorClientId("sessionId1", 1); + EditorClientId editorClientId2 = new EditorClientId("sessionId2", 1); + EditorClientId editorClientId3 = new EditorClientId("sessionId3", 1); HasManageUserPanel mockPanel1 = createMock(HasManageUserPanel.class); HasManageUserPanel mockPanel2 = createMock(HasManageUserPanel.class); @@ -94,9 +94,9 @@ public void setNonEmptyUserList() UserPanelSessionItem mockItem2 = new UserPanelSessionItem(mockPanel2, person2); UserPanelSessionItem mockItem3 = new UserPanelSessionItem(mockPanel3, person3); - expect(mockSessionService.getColor("sessionId1")).andReturn("color1"); - expect(mockSessionService.getColor("sessionId2")).andReturn("color2"); - expect(mockSessionService.getColor("sessionId3")).andReturn("color3"); + expect(mockSessionService.getColor(editorClientId1.getValue())).andReturn("color1"); + expect(mockSessionService.getColor(editorClientId2.getValue())).andReturn("color2"); + expect(mockSessionService.getColor(editorClientId3.getValue())).andReturn("color3"); expect(mockSessionService.getUserPanel(editorClientId1)).andReturn(mockItem1); expect(mockSessionService.getUserPanel(editorClientId2)).andReturn(mockItem2); @@ -120,9 +120,9 @@ public void setNonEmptyUserList() workspaceUsersPresenter.bind(); Map people = new HashMap(); - people.put(new EditorClientId("sessionId1"), new PersonSessionDetails(person1, null)); - people.put(new EditorClientId("sessionId2"), new PersonSessionDetails(person2, null)); - people.put(new EditorClientId("sessionId3"), new PersonSessionDetails(person3, null)); + people.put(editorClientId1, new PersonSessionDetails(person1, null)); + people.put(editorClientId2, new PersonSessionDetails(person2, null)); + people.put(editorClientId3, new PersonSessionDetails(person3, null)); workspaceUsersPresenter.initUserList(people); verify(mockDisplay, mockEventBus, mockSendButton, mockSessionService); diff --git a/zanata-war/src/test/java/org/zanata/webtrans/client/rpc/DummyActivateWorkspaceCommand.java b/zanata-war/src/test/java/org/zanata/webtrans/client/rpc/DummyActivateWorkspaceCommand.java index ff29c73178..28301ed623 100644 --- a/zanata-war/src/test/java/org/zanata/webtrans/client/rpc/DummyActivateWorkspaceCommand.java +++ b/zanata-war/src/test/java/org/zanata/webtrans/client/rpc/DummyActivateWorkspaceCommand.java @@ -30,7 +30,7 @@ public void execute() Log.info("ENTER DummyActivateWorkspaceCommand.execute()"); WorkspaceContext context = new WorkspaceContext(action.getWorkspaceId(), "Dummy Workspace", "Mock Sweedish", false); - Identity identity = new Identity(new EditorClientId("123456"), new Person(new PersonId("bob"), "Bob The Builder", "http://www.gravatar.com/avatar/bob@zanata.org?d=mm&s=16")); + Identity identity = new Identity(new EditorClientId("123456", 1), new Person(new PersonId("bob"), "Bob The Builder", "http://www.gravatar.com/avatar/bob@zanata.org?d=mm&s=16")); callback.onSuccess(new ActivateWorkspaceResult(context, identity)); Log.info("EXIT DummyActivateWorkspaceCommand.execute()"); } diff --git a/zanata-war/src/test/java/org/zanata/webtrans/client/rpc/DummyGetTranslatorListCommand.java b/zanata-war/src/test/java/org/zanata/webtrans/client/rpc/DummyGetTranslatorListCommand.java index 1e2043737d..5a61a7767e 100644 --- a/zanata-war/src/test/java/org/zanata/webtrans/client/rpc/DummyGetTranslatorListCommand.java +++ b/zanata-war/src/test/java/org/zanata/webtrans/client/rpc/DummyGetTranslatorListCommand.java @@ -28,7 +28,7 @@ public void execute() Log.info("ENTER DummyGetTranslatorListCommand.execute()"); HashMap translator = new HashMap(); - translator.put(new EditorClientId("dummySession"), new PersonSessionDetails(new Person(new PersonId("personID"), "Some Person with an Incredibly Long Name", "http://www.gravatar.com/avatar/longname@zanata.org?d=mm&s=16"), null)); + translator.put(new EditorClientId("dummySession", 1), new PersonSessionDetails(new Person(new PersonId("personID"), "Some Person with an Incredibly Long Name", "http://www.gravatar.com/avatar/longname@zanata.org?d=mm&s=16"), null)); callback.onSuccess(new GetTranslatorListResult(translator, translator.size())); Log.info("EXIT DummyGetTranslatorListCommand.execute()"); } diff --git a/zanata-war/src/test/java/org/zanata/webtrans/server/TranslationWorkspaceImplTest.java b/zanata-war/src/test/java/org/zanata/webtrans/server/TranslationWorkspaceImplTest.java index 8f8f6d1c2b..195c026a27 100644 --- a/zanata-war/src/test/java/org/zanata/webtrans/server/TranslationWorkspaceImplTest.java +++ b/zanata-war/src/test/java/org/zanata/webtrans/server/TranslationWorkspaceImplTest.java @@ -51,9 +51,9 @@ public void setUp() public void onTimeoutRemove() { ConcurrentMap sessions = new MapMaker().makeMap(); - sessions.put(new EditorClientId("a"), new PersonId("person a")); - sessions.put(new EditorClientId("b"), new PersonId("person b")); + sessions.put(new EditorClientId("a", 1), new PersonId("person a")); + sessions.put(new EditorClientId("b", 1), new PersonId("person b")); - sessions.remove(new EditorClientId("a")); + sessions.remove(new EditorClientId("a", 1)); } }