@Test public void validateOriginAndExternalIDDuringCreateAndUpdate() { String origin = "test"; String externalId = "testId"; ScimUser user = new ScimUser(null, "*****@*****.**", "Jo", "User"); user.setOrigin(origin); user.setExternalId(externalId); user.addEmail("*****@*****.**"); ScimUser created = db.createUser(user, "j7hyqpassX"); assertEquals("*****@*****.**", created.getUserName()); assertNotNull(created.getId()); assertNotSame(user.getId(), created.getId()); Map<String, Object> map = template.queryForMap("select * from users where id=?", created.getId()); assertEquals(user.getUserName(), map.get("userName")); assertEquals(user.getUserType(), map.get(UaaAuthority.UAA_USER.getUserType())); assertNull(created.getGroups()); assertEquals(origin, created.getOrigin()); assertEquals(externalId, created.getExternalId()); String origin2 = "test2"; String externalId2 = "testId2"; created.setOrigin(origin2); created.setExternalId(externalId2); ScimUser updated = db.update(created.getId(), created); assertEquals(origin2, updated.getOrigin()); assertEquals(externalId2, updated.getExternalId()); }
@Override public ScimUser create(final ScimUser user) { validate(user); logger.debug("Creating new user: "******"userName eq \"" + user.getUserName() + "\" and origin eq \"" + (StringUtils.hasText(user.getOrigin()) ? user.getOrigin() : OriginKeys.UAA) + "\"") .get(0); Map<String, Object> userDetails = new HashMap<>(); userDetails.put("active", existingUser.isActive()); userDetails.put("verified", existingUser.isVerified()); userDetails.put("user_id", existingUser.getId()); throw new ScimResourceAlreadyExistsException( "Username already in use: " + existingUser.getUserName(), userDetails); } return retrieve(id); }
@Test public void test_can_delete_provider_users_in_other_zone() throws Exception { String id = generator.generate(); IdentityZone zone = MultitenancyFixture.identityZone(id, id); IdentityZoneHolder.set(zone); ScimUser user = new ScimUser(null, "*****@*****.**", "Jo", "User"); user.addEmail("*****@*****.**"); user.setOrigin(LOGIN_SERVER); ScimUser created = db.createUser(user, "j7hyqpassX"); assertEquals("*****@*****.**", created.getUserName()); assertNotNull(created.getId()); assertEquals(LOGIN_SERVER, created.getOrigin()); assertEquals(zone.getId(), created.getZoneId()); assertThat( jdbcTemplate.queryForObject( "select count(*) from users where origin=? and identity_zone_id=?", new Object[] {LOGIN_SERVER, zone.getId()}, Integer.class), is(1)); addApprovalAndMembership(created.getId(), created.getOrigin()); assertThat( jdbcTemplate.queryForObject( "select count(*) from authz_approvals where user_id=?", new Object[] {created.getId()}, Integer.class), is(1)); assertThat( jdbcTemplate.queryForObject( "select count(*) from group_membership where member_id=?", new Object[] {created.getId()}, Integer.class), is(1)); IdentityProvider loginServer = new IdentityProvider().setOriginKey(LOGIN_SERVER).setIdentityZoneId(zone.getId()); db.onApplicationEvent(new EntityDeletedEvent<>(loginServer)); assertThat( jdbcTemplate.queryForObject( "select count(*) from users where origin=? and identity_zone_id=?", new Object[] {LOGIN_SERVER, zone.getId()}, Integer.class), is(0)); assertThat( jdbcTemplate.queryForObject( "select count(*) from authz_approvals where user_id=?", new Object[] {created.getId()}, Integer.class), is(0)); assertThat( jdbcTemplate.queryForObject( "select count(*) from group_membership where member_id=?", new Object[] {created.getId()}, Integer.class), is(0)); }
@Test public void test_cannot_delete_uaa_zone_users() throws Exception { ScimUser user = new ScimUser(null, "*****@*****.**", "Jo", "User"); user.addEmail("*****@*****.**"); user.setOrigin(UAA); ScimUser created = db.createUser(user, "j7hyqpassX"); assertEquals("*****@*****.**", created.getUserName()); assertNotNull(created.getId()); assertEquals(UAA, created.getOrigin()); assertThat( jdbcTemplate.queryForObject( "select count(*) from users where origin=? and identity_zone_id=?", new Object[] {UAA, IdentityZone.getUaa().getId()}, Integer.class), is(3)); IdentityProvider loginServer = new IdentityProvider().setOriginKey(UAA).setIdentityZoneId(IdentityZone.getUaa().getId()); db.onApplicationEvent(new EntityDeletedEvent<>(loginServer)); assertThat( jdbcTemplate.queryForObject( "select count(*) from users where origin=? and identity_zone_id=?", new Object[] {UAA, IdentityZone.getUaa().getId()}, Integer.class), is(3)); }
@Override public ScimUser update(final String id, final ScimUser user) throws InvalidScimResourceException { validate(user); logger.debug("Updating user " + user.getUserName()); final String origin = StringUtils.hasText(user.getOrigin()) ? user.getOrigin() : OriginKeys.UAA; final String zoneId = IdentityZoneHolder.get().getId(); int updated = jdbcTemplate.update( UPDATE_USER_SQL, new PreparedStatementSetter() { @Override public void setValues(PreparedStatement ps) throws SQLException { int pos = 1; Timestamp t = new Timestamp(new Date().getTime()); ps.setInt(pos++, user.getVersion() + 1); ps.setTimestamp(pos++, t); ps.setString(pos++, user.getUserName()); ps.setString(pos++, user.getPrimaryEmail()); ps.setString(pos++, user.getName().getGivenName()); ps.setString(pos++, user.getName().getFamilyName()); ps.setBoolean(pos++, user.isActive()); ps.setString(pos++, extractPhoneNumber(user)); ps.setBoolean(pos++, user.isVerified()); ps.setString(pos++, origin); ps.setString( pos++, StringUtils.hasText(user.getExternalId()) ? user.getExternalId() : null); ps.setString(pos++, user.getSalt()); ps.setString(pos++, id); ps.setInt(pos++, user.getVersion()); ps.setString(pos++, zoneId); } }); ScimUser result = retrieve(id); if (updated == 0) { throw new OptimisticLockingFailureException( String.format( "Attempt to update a user (%s) with wrong version: expected=%d but found=%d", id, result.getVersion(), user.getVersion())); } if (updated > 1) { throw new IncorrectResultSizeDataAccessException(1); } return result; }
@Test public void canCreateUser() { ScimUser user = new ScimUser(null, "*****@*****.**", "Jo", "User"); user.addEmail("*****@*****.**"); ScimUser created = db.createUser(user, "j7hyqpassX"); assertEquals("*****@*****.**", created.getUserName()); assertNotNull(created.getId()); assertNotSame(user.getId(), created.getId()); Map<String, Object> map = template.queryForMap("select * from users where id=?", created.getId()); assertEquals(user.getUserName(), map.get("userName")); assertEquals(user.getUserType(), map.get(UaaAuthority.UAA_USER.getUserType())); assertNull(created.getGroups()); assertEquals(Origin.UAA, created.getOrigin()); }
@Test public void canCreateUserInOtherIdentityZone() { String otherZoneId = "my-zone-id"; createOtherIdentityZone(otherZoneId); String idpId = createOtherIdentityProvider(OriginKeys.UAA, otherZoneId); ScimUser user = new ScimUser(null, "*****@*****.**", "Jo", "User"); user.addEmail("*****@*****.**"); ScimUser created = db.createUser(user, "j7hyqpassX"); assertEquals("*****@*****.**", created.getUserName()); assertNotNull(created.getId()); assertNotSame(user.getId(), created.getId()); Map<String, Object> map = jdbcTemplate.queryForMap("select * from users where id=?", created.getId()); assertEquals(user.getUserName(), map.get("userName")); assertEquals(user.getUserType(), map.get(UaaAuthority.UAA_USER.getUserType())); assertNull(created.getGroups()); assertEquals(OriginKeys.UAA, created.getOrigin()); assertEquals("my-zone-id", map.get("identity_zone_id")); }
@Test public void canCreateUserInDefaultIdentityZone() { ScimUser user = new ScimUser(null, "*****@*****.**", "Jo", "User"); user.addEmail("*****@*****.**"); ScimUser created = db.createUser(user, "j7hyqpassX"); assertEquals("*****@*****.**", created.getUserName()); assertNotNull(created.getId()); assertNotSame(user.getId(), created.getId()); Map<String, Object> map = jdbcTemplate.queryForMap("select * from users where id=?", created.getId()); assertEquals(user.getUserName(), map.get("userName")); assertEquals(user.getUserType(), map.get(UaaAuthority.UAA_USER.getUserType())); assertNull(created.getGroups()); assertEquals(OriginKeys.UAA, created.getOrigin()); assertEquals("uaa", map.get("identity_zone_id")); assertNull(user.getPasswordLastModified()); assertNotNull(created.getPasswordLastModified()); assertEquals( (created.getMeta().getCreated().getTime() / 1000l) * 1000l, created.getPasswordLastModified().getTime()); }
@RequestMapping( value = "/invite_users", method = RequestMethod.POST, consumes = "application/json") public ResponseEntity<InvitationsResponse> inviteUsers( @RequestBody InvitationsRequest invitations, @RequestParam(value = "client_id", required = false) String clientId, @RequestParam(value = "redirect_uri") String redirectUri) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication instanceof OAuth2Authentication) { OAuth2Authentication oAuth2Authentication = (OAuth2Authentication) authentication; if (clientId == null) { clientId = oAuth2Authentication.getOAuth2Request().getClientId(); } } InvitationsResponse invitationsResponse = new InvitationsResponse(); DomainFilter filter = new DomainFilter(); List<IdentityProvider> activeProviders = providers.retrieveActive(IdentityZoneHolder.get().getId()); ClientDetails client = clients.loadClientByClientId(clientId); for (String email : invitations.getEmails()) { try { List<IdentityProvider> providers = filter.filter(activeProviders, client, email); if (providers.size() == 1) { ScimUser user = findOrCreateUser(email, providers.get(0).getOriginKey()); String accountsUrl = UaaUrlUtils.getUaaUrl("/invitations/accept"); Map<String, String> data = new HashMap<>(); data.put(InvitationConstants.USER_ID, user.getId()); data.put(InvitationConstants.EMAIL, user.getPrimaryEmail()); data.put(CLIENT_ID, clientId); data.put(REDIRECT_URI, redirectUri); data.put(ORIGIN, user.getOrigin()); Timestamp expiry = new Timestamp( System.currentTimeMillis() + (INVITATION_EXPIRY_DAYS * 24 * 60 * 60 * 1000)); ExpiringCode code = expiringCodeStore.generateCode(JsonUtils.writeValueAsString(data), expiry, null); String invitationLink = accountsUrl + "?code=" + code.getCode(); try { URL inviteLink = new URL(invitationLink); invitationsResponse .getNewInvites() .add( InvitationsResponse.success( user.getPrimaryEmail(), user.getId(), user.getOrigin(), inviteLink)); } catch (MalformedURLException mue) { invitationsResponse .getFailedInvites() .add( InvitationsResponse.failure( email, "invitation.exception.url", String.format("Malformed url", invitationLink))); } } else if (providers.size() == 0) { invitationsResponse .getFailedInvites() .add( InvitationsResponse.failure( email, "provider.non-existent", "No authentication provider found.")); } else { invitationsResponse .getFailedInvites() .add( InvitationsResponse.failure( email, "provider.ambiguous", "Multiple authentication providers found.")); } } catch (ScimResourceConflictException x) { invitationsResponse .getFailedInvites() .add( InvitationsResponse.failure( email, "user.ambiguous", "Multiple users with the same origin matched to the email address.")); } catch (UaaException uaae) { invitationsResponse .getFailedInvites() .add(InvitationsResponse.failure(email, "invitation.exception", uaae.getMessage())); } } return new ResponseEntity<>(invitationsResponse, HttpStatus.OK); }