You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ka...@apache.org on 2015/01/01 14:31:23 UTC
svn commit: r1648842 - in /directory/escimo/trunk:
ldap/src/main/java/org/apache/directory/scim/ldap/ ldap/src/main/resources/
schema/src/main/java/org/apache/directory/scim/schema/
server/src/main/java/org/apache/directory/scim/rest/
Author: kayyagari
Date: Thu Jan 1 13:31:23 2015
New Revision: 1648842
URL: http://svn.apache.org/r1648842
Log:
o updated interface to throw/handle EscimoException
o added more error codes based on the latest 2.0 draft spec
o added a proprty to set DN of user base
Modified:
directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/LdapResourceProvider.java
directory/escimo/trunk/ldap/src/main/resources/ldap-server.properties
directory/escimo/trunk/schema/src/main/java/org/apache/directory/scim/schema/ErrorCode.java
directory/escimo/trunk/server/src/main/java/org/apache/directory/scim/rest/ResourceService.java
Modified: directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/LdapResourceProvider.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/LdapResourceProvider.java?rev=1648842&r1=1648841&r2=1648842&view=diff
==============================================================================
--- directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/LdapResourceProvider.java (original)
+++ directory/escimo/trunk/ldap/src/main/java/org/apache/directory/scim/ldap/LdapResourceProvider.java Thu Jan 1 13:31:23 2015
@@ -53,9 +53,9 @@ import org.apache.directory.api.ldap.mod
import org.apache.directory.api.ldap.model.entry.DefaultEntry;
import org.apache.directory.api.ldap.model.entry.Entry;
import org.apache.directory.api.ldap.model.entry.Value;
-import org.apache.directory.api.ldap.model.exception.LdapAuthenticationException;
import org.apache.directory.api.ldap.model.exception.LdapEntryAlreadyExistsException;
import org.apache.directory.api.ldap.model.exception.LdapException;
+import org.apache.directory.api.ldap.model.exception.LdapNoSuchObjectException;
import org.apache.directory.api.ldap.model.filter.ExprNode;
import org.apache.directory.api.ldap.model.message.LdapResult;
import org.apache.directory.api.ldap.model.message.ModifyRequest;
@@ -82,19 +82,22 @@ import org.apache.directory.ldap.client.
import org.apache.directory.ldap.client.api.LdapConnectionConfig;
import org.apache.directory.ldap.client.api.LdapNetworkConnection;
import org.apache.directory.scim.AttributeHandler;
-import org.apache.directory.scim.AttributeNotFoundException;
import org.apache.directory.scim.ComplexAttribute;
import org.apache.directory.scim.ListResponse;
-import org.apache.directory.scim.MissingParameterException;
import org.apache.directory.scim.MultiValAttribute;
-import org.apache.directory.scim.ResourceProvider;
import org.apache.directory.scim.RequestContext;
-import org.apache.directory.scim.ResourceConflictException;
-import org.apache.directory.scim.ResourceNotFoundException;
+import org.apache.directory.scim.ResourceProvider;
import org.apache.directory.scim.ServerResource;
import org.apache.directory.scim.SimpleAttribute;
import org.apache.directory.scim.SimpleAttributeGroup;
-import org.apache.directory.scim.UnauthorizedException;
+import org.apache.directory.scim.exception.AttributeNotFoundException;
+import org.apache.directory.scim.exception.EscimoException;
+import org.apache.directory.scim.exception.InternalException;
+import org.apache.directory.scim.exception.MissingParameterException;
+import org.apache.directory.scim.exception.ResourceConflictException;
+import org.apache.directory.scim.exception.ResourceNotFoundException;
+import org.apache.directory.scim.exception.ResourceUpdateException;
+import org.apache.directory.scim.exception.UnauthorizedException;
import org.apache.directory.scim.ldap.handlers.LdapAttributeHandler;
import org.apache.directory.scim.ldap.schema.ComplexType;
import org.apache.directory.scim.ldap.schema.MultiValType;
@@ -150,7 +153,8 @@ public class LdapResourceProvider implem
private long sessionTimeout = 2 * 60 * 1000;
-
+ private String baseDn;
+
public LdapResourceProvider()
{
}
@@ -162,8 +166,10 @@ public class LdapResourceProvider implem
}
- public void init() throws Exception
+ public void init()
{
+ //TODO report the initialization error in a better way so that
+ // the app is not undeployed
LOG.info( "Initializing LDAP resource provider" );
try
@@ -260,7 +266,7 @@ public class LdapResourceProvider implem
}
- public RequestContext createCtx( UriInfo uriInfo, HttpServletRequest httpReq ) throws Exception
+ public RequestContext createCtx( UriInfo uriInfo, HttpServletRequest httpReq ) throws EscimoException
{
LdapConnection connection = getConnection( httpReq );
LdapRequestContext ctx = new LdapRequestContext( this, connection, uriInfo, httpReq );
@@ -268,7 +274,7 @@ public class LdapResourceProvider implem
}
- private void _initInternal() throws Exception
+ private void _initInternal() throws EscimoException
{
if ( initialized )
{
@@ -283,7 +289,14 @@ public class LdapResourceProvider implem
if ( adminConnection instanceof LdapNetworkConnection )
{
- ( ( LdapNetworkConnection ) adminConnection ).loadSchema();// new JarLdifSchemaLoader() );
+ try
+ {
+ ( ( LdapNetworkConnection ) adminConnection ).loadSchema();// new JarLdifSchemaLoader() );
+ }
+ catch( LdapException e )
+ {
+ throw new InternalException( e );
+ }
}
ldapSchema = adminConnection.getSchemaManager();
@@ -316,7 +329,7 @@ public class LdapResourceProvider implem
}
- private void createConnection() throws IOException, LdapException
+ private void createConnection() throws EscimoException
{
LOG.info( "Creating LDAP server connection" );
@@ -327,30 +340,38 @@ public class LdapResourceProvider implem
Properties prop = null;
InputStream in = null;
- if ( !ldapServerProps.exists() )
+ try
{
- in = this.getClass().getClassLoader().getResourceAsStream( ldapServerProps.getName() );
- FileWriter fw = new FileWriter( ldapServerProps );
-
- BufferedReader br = new BufferedReader( new InputStreamReader( in ) );
-
- String s = null;
-
- while ( ( s = br.readLine() ) != null )
+ if ( !ldapServerProps.exists() )
{
- fw.write( s + "\n" );
- }
-
- fw.close();
- br.close();
+ in = this.getClass().getClassLoader().getResourceAsStream( ldapServerProps.getName() );
+ FileWriter fw = new FileWriter( ldapServerProps );
+
+ BufferedReader br = new BufferedReader( new InputStreamReader( in ) );
+
+ String s = null;
+
+ while ( ( s = br.readLine() ) != null )
+ {
+ fw.write( s + "\n" );
+ }
+
+ fw.close();
+ br.close();
+ }
+
+ in = new FileInputStream( ldapServerProps );
+
+ prop = new Properties();
+ prop.load( in );
+
+ in.close();
+ }
+ catch( IOException e )
+ {
+ LOG.warn( "Failed to read and store the ldap server properties file {}", ldapServerProps );
+ throw new InternalException( "Failed to read and store the server properties file " + ldapServerProps, e );
}
-
- in = new FileInputStream( ldapServerProps );
-
- prop = new Properties();
- prop.load( in );
-
- in.close();
String host = prop.getProperty( "escimo.ldap.server.host" );
String portVal = prop.getProperty( "escimo.ldap.server.port" );
@@ -359,6 +380,8 @@ public class LdapResourceProvider implem
String password = prop.getProperty( "escimo.ldap.server.password" );
String tlsVal = prop.getProperty( "escimo.ldap.server.useTls" );
+ baseDn = prop.getProperty( "escimo.ldap.server.users.baseDn", "" );
+
config = new LdapConnectionConfig();
config.setLdapHost( host );
config.setLdapPort( port );
@@ -367,11 +390,20 @@ public class LdapResourceProvider implem
config.setCredentials( password );
adminConnection = new LdapNetworkConnection( config );
- adminConnection.bind();
+
+ try
+ {
+ adminConnection.bind();
+ }
+ catch( LdapException e )
+ {
+ LOG.warn( "Failed to bind the admin connection", e );
+ throw new InternalException( "Failed to bind the admin connection", e );
+ }
}
- public String authenticate( String userName, String password ) throws Exception
+ public String authenticate( String userName, String password ) throws EscimoException
{
_initInternal();
@@ -390,13 +422,17 @@ public class LdapResourceProvider implem
try
{
- cursor = adminConnection.search( "ou=system", filter, SUBTREE, "1.1" );
+ cursor = adminConnection.search( baseDn, filter, SUBTREE, "1.1" );
if ( cursor.next() )
{
userDn = cursor.get().getDn().getName();
}
}
+ catch( Exception e )
+ {
+ LOG.warn( "Failed to find the entry of user {}", userName );
+ }
finally
{
if ( cursor != null )
@@ -416,12 +452,19 @@ public class LdapResourceProvider implem
{
conn.bind( userDn, password );
}
- catch ( LdapAuthenticationException e )
+ catch ( LdapException e )
{
UnauthorizedException ue = new UnauthorizedException( "Cannot authenticate user " + userName + " : "
+ e.getMessage() );
ue.initCause( e );
- conn.close();
+ try
+ {
+ conn.close();
+ }
+ catch( Exception ex )
+ {
+ // ignore
+ }
throw ue;
}
@@ -516,7 +559,7 @@ public class LdapResourceProvider implem
}
- public ListResponse search( String scimFilter, String attributes, RequestContext ctx ) throws Exception
+ public ListResponse search( String scimFilter, String attributes, RequestContext ctx ) throws EscimoException
{
FilterNode filter = FilterParser.parse( scimFilter );
@@ -524,47 +567,54 @@ public class LdapResourceProvider implem
ExprNode ldapFilter = null;
- if ( filter != null )
+ try
{
- ldapFilter = LdapUtil._scimToLdapFilter( filter, scimSchema, ldapSchema, this );
+ if ( filter != null )
+ {
+ ldapFilter = LdapUtil._scimToLdapFilter( filter, scimSchema, ldapSchema, this );
+ }
+ else
+ {
+ ldapFilter = org.apache.directory.api.ldap.model.filter.FilterParser.parse( scimSchema.getFilter() );
+ }
+
+ LOG.debug( "LDAP filter {}", ldapFilter );
+
+ SearchRequest sr = new SearchRequestImpl();
+ sr.setBase( new Dn( scimSchema.getBaseDn() ) );
+ sr.setFilter( ldapFilter );
+ sr.setScope( SearchScope.SUBTREE );
+
+ String[] requested = getRequestedAttributes( attributes, scimSchema );
+ sr.addAttributes( requested );
+
+ LdapConnection conn = ( ( LdapRequestContext ) ctx ).getConnection();
+
+ SearchCursor cursor = conn.search( sr );
+
+ ListResponse lr = new ListResponse();
+
+ while ( cursor.next() )
+ {
+ Entry entry = cursor.getEntry();
+
+ ServerResource res = new ServerResource();
+
+ ctx.setCoreResource( res );
+
+ _loadCoreResource( ctx, entry, scimSchema );
+
+ lr.addResource( res );
+ }
+
+ cursor.close();
+
+ return lr;
}
- else
+ catch( Exception e )
{
- ldapFilter = org.apache.directory.api.ldap.model.filter.FilterParser.parse( scimSchema.getFilter() );
+ throw new InternalException( e );
}
-
- LOG.debug( "LDAP filter {}", ldapFilter );
-
- SearchRequest sr = new SearchRequestImpl();
- sr.setBase( new Dn( scimSchema.getBaseDn() ) );
- sr.setFilter( ldapFilter );
- sr.setScope( SearchScope.SUBTREE );
-
- String[] requested = getRequestedAttributes( attributes, scimSchema );
- sr.addAttributes( requested );
-
- LdapConnection conn = ( ( LdapRequestContext ) ctx ).getConnection();
-
- SearchCursor cursor = conn.search( sr );
-
- ListResponse lr = new ListResponse();
-
- while ( cursor.next() )
- {
- Entry entry = cursor.getEntry();
-
- ServerResource res = new ServerResource();
-
- ctx.setCoreResource( res );
-
- _loadCoreResource( ctx, entry, scimSchema );
-
- lr.addResource( res );
- }
-
- cursor.close();
-
- return lr;
}
@@ -622,191 +672,11 @@ public class LdapResourceProvider implem
}
- public ServerResource putResource( String userId, String jsonData, RequestContext ctx ) throws Exception
- {
- ResourceSchema resourceSchema = getResourceSchema( ctx );
- return replaceResource( userId, jsonData, ctx, resourceSchema );
- }
-
-
- public ServerResource patchResource( String userId, String jsonData, RequestContext ctx ) throws Exception
- {
- ResourceSchema resourceSchema = getResourceSchema( ctx );
- return patchResource( userId, jsonData, ctx, resourceSchema );
- }
-
-
- public InputStream getUserPhoto( String id, String atName, RequestContext ctx ) throws MissingParameterException
- {
- if ( Strings.isEmpty( id ) )
- {
- throw new MissingParameterException( "parameter 'id' cannot be null or empty" );
- }
-
- if ( Strings.isEmpty( atName ) )
- {
- throw new MissingParameterException( "parameter 'atName' cannot be null or empty" );
- }
-
- ResourceSchema resourceSchema = getResourceSchema( ctx );
- Entry entry = fetchEntryById( id, resourceSchema, ctx );
-
- if ( entry == null )
- {
- return null;
- }
-
- Attribute phtoAt = entry.get( atName );
-
- if ( phtoAt == null )
- {
- return null;
- }
-
- ByteArrayInputStream bin = new ByteArrayInputStream( phtoAt.get().getBytes() );
-
- return bin;
- }
-
-
- private void addAttributes( Entry entry, JsonObject obj, RequestContext ctx, ResourceSchema resourceSchema )
- throws Exception
- {
- //obj.remove( "schemas" );
-
- for ( java.util.Map.Entry<String, JsonElement> e : obj.entrySet() )
- {
- String name = e.getKey();
-
- if ( name.startsWith( "urn:scim:schemas:" ) )
- {
- continue;
- }
-
- BaseType bt = resourceSchema.getAttribute( name );
-
- if ( bt == null )
- {
- LOG.debug( "Unknown attribute name "
- + name
- + " is present in the JSON payload that has no corresponding mapping in the escimo-ldap-mapping.xml file" );
- continue;
- }
-
- if ( bt.isReadOnly() )
- {
- continue;
- }
-
- AttributeHandler handler = bt.getHandler();
-
- if ( handler != null )
- {
- handler.write( bt, e.getValue(), entry, ctx );
- }
- else
- {
- LdapUtil.scimToLdapAttribute( bt, e.getValue(), entry, ctx );
- }
- }
- }
-
-
- public ServerResource addResource( String json, RequestContext ctx ) throws Exception
- {
- String userName = null;
-
- try
- {
- JsonParser parser = new JsonParser();
- JsonObject obj = ( JsonObject ) parser.parse( json );
-
- Entry entry = new DefaultEntry( ldapSchema );
-
- ResourceSchema resourceSchema = getResourceSchema( ctx );
- SimpleType st = resourceSchema.getRdnType();
- String userIdName = st.getMappedTo();
-
- String dn = ctx.getReqHeaderValue( ENTRYDN_HEADER );
-
- if ( Strings.isEmpty( dn ) )
- {
- dn = null;
- }
-
- if ( dn == null )
- {
- userName = obj.get( st.getName() ).getAsString();
-
- dn = userIdName + "=" + userName + "," + resourceSchema.getBaseDn();
- }
-
- _resourceToEntry( entry, obj, ctx, resourceSchema );
-
- entry.setDn( dn );
-
- LdapConnection conn = ( ( LdapRequestContext ) ctx ).getConnection();
-
- conn.add( entry );
-
- entry = conn.lookup( entry.getDn(), SchemaConstants.ALL_ATTRIBUTES_ARRAY );
-
- ServerResource addedUser = new ServerResource();
-
- ctx.setCoreResource( addedUser );
-
- _loadCoreResource( ctx, entry, resourceSchema );
-
- return addedUser;
-
- }
- catch ( LdapEntryAlreadyExistsException e )
- {
- String message = "Resource already exists, conflicting attribute userName : " + userName;
- throw new ResourceConflictException( message );
- }
- catch ( Exception e )
- {
- LOG.warn( "Failed to create User resource", e );
- throw e;
- }
- }
-
-
- private void _resourceToEntry( Entry entry, JsonObject obj, RequestContext ctx, ResourceSchema resourceSchema )
- throws Exception
- {
-
- // add the objectClasses first so a handler will get a chance to
- // inspect what attributes can the entry hold
- // e.x it is useful for handling Groups, where the handler can
- // find if the attribute name is 'member' or 'uniqueMember'
- for ( String oc : resourceSchema.getObjectClasses() )
- {
- entry.add( SchemaConstants.OBJECT_CLASS, oc );
- }
-
- // process the core attributes first
- addAttributes( entry, obj, ctx, resourceSchema );
-
- List<String> uris = resourceSchema.getSchemaIds();
-
- for ( String u : uris )
- {
- JsonObject userAtObj = ( JsonObject ) obj.get( u );
- if ( userAtObj != null )
- {
- addAttributes( entry, userAtObj, ctx, resourceSchema );
- }
- }
-
- }
-
-
// TODO can userName be changed for a user?? likewise displayName for a Group
- public ServerResource replaceResource( String resourceId, String jsonData, RequestContext ctx,
- ResourceSchema resourceSchema ) throws Exception
+ public ServerResource putResource( String resourceId, String jsonData, RequestContext ctx ) throws EscimoException
{
+ ResourceSchema resourceSchema = getResourceSchema( ctx );
+
JsonParser parser = new JsonParser();
JsonObject obj = ( JsonObject ) parser.parse( jsonData );
@@ -820,36 +690,44 @@ public class LdapResourceProvider implem
Attribute existingPwdAt = existingEntry.get( SchemaConstants.USER_PASSWORD_AT );
Attribute newPwdAt = entry.get( SchemaConstants.USER_PASSWORD_AT );
- if ( existingPwdAt != null )
- {
- existingEntry.remove( existingPwdAt );
- }
-
- if ( newPwdAt != null )
- {
- entry.remove( newPwdAt );
- }
-
- Attribute existingUserNameAt = null;
Attribute newUserNameAt = null;
- SimpleType st = resourceSchema.getRdnType();
+ Attribute existingUserNameAt = null;
- if ( st != null )
+ try
{
- existingUserNameAt = existingEntry.get( st.getMappedTo() );
-
- if ( existingUserNameAt != null )
+ if ( existingPwdAt != null )
{
- existingEntry.remove( existingUserNameAt );
+ existingEntry.remove( existingPwdAt );
}
-
- newUserNameAt = entry.get( st.getMappedTo() );
-
- if ( newUserNameAt != null )
+
+ if ( newPwdAt != null )
+ {
+ entry.remove( newPwdAt );
+ }
+
+ SimpleType st = resourceSchema.getRdnType();
+
+ if ( st != null )
{
- entry.remove( newUserNameAt );
+ existingUserNameAt = existingEntry.get( st.getMappedTo() );
+
+ if ( existingUserNameAt != null )
+ {
+ existingEntry.remove( existingUserNameAt );
+ }
+
+ newUserNameAt = entry.get( st.getMappedTo() );
+
+ if ( newUserNameAt != null )
+ {
+ entry.remove( newUserNameAt );
+ }
}
}
+ catch( LdapException e )
+ {
+ throw new InternalException( e );
+ }
ModifyRequest modReq = new ModifyRequestImpl();
modReq.setName( existingEntry.getDn() );
@@ -899,23 +777,38 @@ public class LdapResourceProvider implem
LdapConnection conn = ( ( LdapRequestContext ) ctx ).getConnection();
- ModifyResponse modResp = conn.modify( modReq );
-
- if ( modResp.getLdapResult().getResultCode() != ResultCodeEnum.SUCCESS )
+ try
{
- throw new Exception( "Failed to replace the resource " + modResp.getLdapResult().getDiagnosticMessage() );
+ ModifyResponse modResp = conn.modify( modReq );
+
+ if ( modResp.getLdapResult().getResultCode() != ResultCodeEnum.SUCCESS )
+ {
+ throw new ResourceUpdateException( "Failed to replace the resource " + modResp.getLdapResult().getDiagnosticMessage() );
+ }
+ }
+ catch( LdapException e )
+ {
+ throw new InternalException( e );
}
- if ( newUserNameAt != null )
+ try
{
- if ( !existingUserNameAt.contains( newUserNameAt.getString() ) )
+ if ( newUserNameAt != null )
{
- // a modDN needs to be performed
- conn.rename( existingEntry.getDn().getName(),
- newUserNameAt.getUpId() + "=" + newUserNameAt.getString(), true );
+ if ( !existingUserNameAt.contains( newUserNameAt.getString() ) )
+ {
+ // a modDN needs to be performed
+ conn.rename( existingEntry.getDn().getName(),
+ newUserNameAt.getUpId() + "=" + newUserNameAt.getString(), true );
+ }
}
}
-
+ catch( LdapException e )
+ {
+ LOG.warn( "Failed to rename the resource {}", resourceId, e );
+ throw new ResourceUpdateException( "Failed to rename the resource " + resourceId, e );
+ }
+
entry = fetchEntryById( resourceId, resourceSchema, ctx );
ServerResource resource = new ServerResource();
@@ -928,9 +821,9 @@ public class LdapResourceProvider implem
}
- public ServerResource patchResource( String resourceId, String jsonData, RequestContext ctx,
- ResourceSchema resourceSchema ) throws Exception
+ public ServerResource patchResource( String resourceId, String jsonData, RequestContext ctx ) throws EscimoException
{
+ ResourceSchema resourceSchema = getResourceSchema( ctx );
JsonParser parser = new JsonParser();
JsonObject obj = ( JsonObject ) parser.parse( jsonData );
@@ -960,10 +853,22 @@ public class LdapResourceProvider implem
throw new AttributeNotFoundException( "No definition found for the attribute " + name );
}
+ if ( bt.isReadOnly() )
+ {
+ continue;
+ }
+
AttributeHandler handler = bt.getHandler();
if ( handler != null )
{
- handler.deleteAttribute( bt, existingEntry, ctx, modReq );
+ try
+ {
+ handler.deleteAttribute( bt, existingEntry, ctx, modReq );
+ }
+ catch( Exception ex )
+ {
+ throw new InternalException( ex );
+ }
continue;
}
@@ -983,7 +888,8 @@ public class LdapResourceProvider implem
LdapResult result = modResp.getLdapResult();
if ( result.getResultCode() != ResultCodeEnum.SUCCESS )
{
- throw new Exception( result.getDiagnosticMessage() );
+ LOG.debug( "Failed to patch the resource with ID {}, LDAP error result {}", resourceId, result );
+ throw new ResourceUpdateException( "Failed to patch the resource with ID " + resourceId );
}
// send attributes if requested
@@ -1005,39 +911,241 @@ public class LdapResourceProvider implem
catch ( Exception e )
{
LOG.warn( "Failed to patch the resource with ID {}", resourceId, e );
- throw e;
+ throw new ResourceUpdateException( "Failed to patch the resource with ID " + resourceId, e );
}
}
- public void deleteResource( String id, RequestContext ctx ) throws Exception
+ public InputStream getUserPhoto( String id, String atName, RequestContext ctx ) throws MissingParameterException
{
+ if ( Strings.isEmpty( id ) )
+ {
+ throw new MissingParameterException( "parameter 'id' cannot be null or empty" );
+ }
+
+ if ( Strings.isEmpty( atName ) )
+ {
+ throw new MissingParameterException( "parameter 'atName' cannot be null or empty" );
+ }
+
ResourceSchema resourceSchema = getResourceSchema( ctx );
- deleteResource( id, resourceSchema, ctx );
+ Entry entry = fetchEntryById( id, resourceSchema, ctx );
+
+ if ( entry == null )
+ {
+ return null;
+ }
+
+ Attribute phtoAt = entry.get( atName );
+
+ if ( phtoAt == null )
+ {
+ return null;
+ }
+
+ ByteArrayInputStream bin = new ByteArrayInputStream( phtoAt.get().getBytes() );
+
+ return bin;
}
- private void deleteResource( String id, ResourceSchema schema, RequestContext ctx ) throws LdapException
+ private void addAttributes( Entry entry, JsonObject obj, RequestContext ctx, ResourceSchema resourceSchema )
+ throws EscimoException
{
- Entry entry = fetchEntryById( id, schema, ctx );
- LdapConnection conn = ( ( LdapRequestContext ) ctx ).getConnection();
- conn.delete( entry.getDn() );
+ try
+ {
+ for ( java.util.Map.Entry<String, JsonElement> e : obj.entrySet() )
+ {
+ String name = e.getKey();
+
+ if ( name.startsWith( "urn:scim:schemas:" ) )
+ {
+ continue;
+ }
+
+ BaseType bt = resourceSchema.getAttribute( name );
+
+ if ( bt == null )
+ {
+ LOG.debug( "Unknown attribute name {} is present in the JSON payload that has no corresponding mapping in the escimo-ldap-mapping.xml file", name );
+ continue;
+ }
+
+ if ( bt.isReadOnly() )
+ {
+ continue;
+ }
+
+ AttributeHandler handler = bt.getHandler();
+
+ if ( handler != null )
+ {
+ handler.write( bt, e.getValue(), entry, ctx );
+ }
+ else
+ {
+ LdapUtil.scimToLdapAttribute( bt, e.getValue(), entry, ctx );
+ }
+ }
+ }
+ catch( Exception e )
+ {
+ throw new InternalException( e );
+ }
}
- private void _loadCoreResource( RequestContext ctx, Entry entry, ResourceSchema resourceSchema ) throws Exception
+ public ServerResource addResource( String json, RequestContext ctx ) throws EscimoException
{
- ServerResource resource = ctx.getCoreResource();
+ String userName = null;
- // first fill in the id, we need this for deriving location
- SimpleType idType = ( SimpleType ) resourceSchema.getCoreAttribute( "id" );
- SimpleAttribute idAttribute = getValueForSimpleType( idType, entry, ctx );
- resource.addAttribute( idType.getUri(), idAttribute );
+ try
+ {
+ JsonParser parser = new JsonParser();
+ JsonObject obj = ( JsonObject ) parser.parse( json );
- resource.setId( ( String ) idAttribute.getValue() );
+ Entry entry = new DefaultEntry( ldapSchema );
- _loadAttributes( ctx, entry, resourceSchema.getCoreTypes(), idType );
- _loadAttributes( ctx, entry, resourceSchema.getExtendedTypes(), idType );
+ ResourceSchema resourceSchema = getResourceSchema( ctx );
+ SimpleType st = resourceSchema.getRdnType();
+ String userIdName = st.getMappedTo();
+
+ String dn = ctx.getReqHeaderValue( ENTRYDN_HEADER );
+
+ if ( Strings.isEmpty( dn ) )
+ {
+ dn = null;
+ }
+
+ if ( dn == null )
+ {
+ userName = obj.get( st.getName() ).getAsString();
+
+ dn = userIdName + "=" + userName + "," + resourceSchema.getBaseDn();
+ }
+
+ _resourceToEntry( entry, obj, ctx, resourceSchema );
+
+ entry.setDn( dn );
+
+ LdapConnection conn = ( ( LdapRequestContext ) ctx ).getConnection();
+
+ conn.add( entry );
+
+ entry = conn.lookup( entry.getDn(), SchemaConstants.ALL_ATTRIBUTES_ARRAY );
+
+ ServerResource addedUser = new ServerResource();
+
+ ctx.setCoreResource( addedUser );
+
+ _loadCoreResource( ctx, entry, resourceSchema );
+
+ return addedUser;
+
+ }
+ catch ( LdapEntryAlreadyExistsException e )
+ {
+ String message = "Resource already exists, conflicting attribute userName : " + userName;
+ throw new ResourceConflictException( message );
+ }
+ catch ( Exception e )
+ {
+ LOG.warn( "Failed to create User resource", e );
+ throw new InternalException( e );
+ }
+ }
+
+
+ private void _resourceToEntry( Entry entry, JsonObject obj, RequestContext ctx, ResourceSchema resourceSchema )
+ throws EscimoException
+ {
+
+ // add the objectClasses first so a handler will get a chance to
+ // inspect what attributes can the entry hold
+ // e.x it is useful for handling Groups, where the handler can
+ // find if the attribute name is 'member' or 'uniqueMember'
+ try
+ {
+ for ( String oc : resourceSchema.getObjectClasses() )
+ {
+ entry.add( SchemaConstants.OBJECT_CLASS, oc );
+ }
+ }
+ catch( LdapException e )
+ {
+ throw new InternalException( e );
+ }
+
+ // process the core attributes first
+ addAttributes( entry, obj, ctx, resourceSchema );
+
+ List<String> uris = resourceSchema.getSchemaIds();
+
+ for ( String u : uris )
+ {
+ JsonObject userAtObj = ( JsonObject ) obj.get( u );
+ if ( userAtObj != null )
+ {
+ addAttributes( entry, userAtObj, ctx, resourceSchema );
+ }
+ }
+
+ }
+
+
+ public void deleteResource( String id, RequestContext ctx ) throws EscimoException
+ {
+ ResourceSchema resourceSchema = getResourceSchema( ctx );
+ Entry entry = fetchEntryById( id, resourceSchema, ctx );
+ if( entry == null )
+ {
+ LOG.debug( "No resource found with the id {}", id );
+ throw new ResourceNotFoundException( "Resource with id " + id + " not found" );
+ }
+
+ LdapConnection conn = ( ( LdapRequestContext ) ctx ).getConnection();
+ try
+ {
+ conn.delete( entry.getDn() );
+ }
+ catch( LdapNoSuchObjectException e )
+ {
+ LOG.debug( "No resource found with the id {}", id );
+ throw new ResourceNotFoundException( "Resource with id " + id + " not found" );
+ }
+ catch( LdapException e )
+ {
+ LOG.warn( "Failed to delete the resource with id {}", id );
+ throw new InternalException( e );
+ }
+ }
+
+
+ private void _loadCoreResource( RequestContext ctx, Entry entry, ResourceSchema resourceSchema ) throws EscimoException
+ {
+ ServerResource resource = ctx.getCoreResource();
+
+ if ( entry == null )
+ {
+ return;
+ }
+
+ try
+ {
+ // first fill in the id, we need this for deriving location
+ SimpleType idType = ( SimpleType ) resourceSchema.getCoreAttribute( "id" );
+ SimpleAttribute idAttribute = getValueForSimpleType( idType, entry, ctx );
+ resource.addAttribute( idType.getUri(), idAttribute );
+
+ resource.setId( ( String ) idAttribute.getValue() );
+
+ _loadAttributes( ctx, entry, resourceSchema.getCoreTypes(), idType );
+ _loadAttributes( ctx, entry, resourceSchema.getExtendedTypes(), idType );
+ }
+ catch( Exception e )
+ {
+ throw new InternalException( e );
+ }
}
@@ -1342,7 +1450,7 @@ public class LdapResourceProvider implem
}
- public LdapConnection getConnection( HttpServletRequest httpReq ) throws Exception
+ public LdapConnection getConnection( HttpServletRequest httpReq ) throws EscimoException
{
if ( allowAuthorizedUsers )
Modified: directory/escimo/trunk/ldap/src/main/resources/ldap-server.properties
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/ldap/src/main/resources/ldap-server.properties?rev=1648842&r1=1648841&r2=1648842&view=diff
==============================================================================
--- directory/escimo/trunk/ldap/src/main/resources/ldap-server.properties (original)
+++ directory/escimo/trunk/ldap/src/main/resources/ldap-server.properties Thu Jan 1 13:31:23 2015
@@ -20,4 +20,5 @@ escimo.ldap.server.port = 10389
escimo.ldap.server.user = uid=admin,ou=system
escimo.ldap.server.password = secret
escimo.ldap.server.useTls = false
+escimo.ldap.server.users.baseDn = ou=system
escimo.resource.provider = org.apache.directory.scim.ldap.LdapResourceProvider
Modified: directory/escimo/trunk/schema/src/main/java/org/apache/directory/scim/schema/ErrorCode.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/schema/src/main/java/org/apache/directory/scim/schema/ErrorCode.java?rev=1648842&r1=1648841&r2=1648842&view=diff
==============================================================================
--- directory/escimo/trunk/schema/src/main/java/org/apache/directory/scim/schema/ErrorCode.java (original)
+++ directory/escimo/trunk/schema/src/main/java/org/apache/directory/scim/schema/ErrorCode.java Thu Jan 1 13:31:23 2015
@@ -27,31 +27,66 @@ package org.apache.directory.scim.schema
public enum ErrorCode
{
- BAD_REQUEST(400, "Request is unparseable, syntactically incorrect, or violates schema"),
+ TEMPORARY_REDIRECT(307, null, " The client is directed to repeat the same HTTP request at the location identified."
+ + " The client SHOULD NOT use the location provided in the response as a permanent reference to the"
+ + " resource and SHOULD continue to use the original request URI"),
+
+ PERMANENT_REDIRECT(308, null, "The client is directed to repeat the same HTTP request at the location identified. The client"
+ + " SHOULD use the location provided in the response as the permanent reference to the resource"),
+
+ BAD_REQUEST(400, null, "Request is unparseable, syntactically incorrect, or violates schema"),
- UNAUTHORIZED(401, "Authorization failure"),
+ UNAUTHORIZED(401, null, "Authorization failure"),
- FORBIDDEN(403, "Server does not support requested operation"),
+ FORBIDDEN(403, null, "Server does not support requested operation"),
- NOT_FOUND(404, "Specified resource does not exist"),
+ NOT_FOUND(404, null, "Specified resource does not exist"),
- CONFLICT(409, "The specified version number does not match the resource's latest version number or a Service Provider refused to create a new, duplicate resource"),
+ CONFLICT(409, null, "The specified version number does not match the resource's latest version number or a Service Provider refused"
+ + " to create a new, duplicate resource"),
- PRECONDITION_FAILED(412, "Failed to update as Resource changed on the server since last retrieved"),
+ PRECONDITION_FAILED(412, null, "Failed to update as Resource changed on the server since last retrieved"),
- REQUEST_ENTITY_TOO_LARGE(413, "Requested entity too large"),
+ REQUEST_ENTITY_TOO_LARGE(413, null, "Requested entity too large"),
- INTERNAL_SERVER_ERROR(500, "Internal server error"),
+ INTERNAL_SERVER_ERROR(500, null, "Internal server error"),
- NOT_IMPLEMENTED(501, "Service Provider does not support the requested operation");
+ NOT_IMPLEMENTED(501, null, "Service Provider does not support the requested operation"),
+
+ BAD_REQUEST_INVALID_FILTER(400, "invalidFilter", "The specified filter syntax was invalid (does not comply with Figure 1) or the "
+ + "specified attribute and filter comparison combination is not supported."),
+
+ BAD_REQUEST_TOO_MANY(400, "tooMany", "The specified filter yields many more results than the server is willing calculate or process."
+ + " For example, a filter such as \"(userName pr)\" by itself would return all entries with a "
+ + "\"userName\" and MAY not be acceptable to the service provider."),
+
+ BAD_REQUEST_UNIQUENESS(400, "uniqueness", "One or more of attribute values is already in use or is reserved."),
+
+ BAD_REQUEST_MUTABILITY(400, "mutability", "The attempted modification is not compatible with the target attributes mutability or current"
+ + " state (e.g. modification of an immutable attribute with an existing value)."),
+
+ BAD_REQUEST_INVALID_SYNTAX(400, "invalidSyntax", "The request body message structure was invalid or did not conform to the request schema."),
+
+ BAD_REQUEST_INVALID_PATH(400, "invalidPath", "The path attribute was invalid or malformed (see Figure 7)."),
+
+ BAD_REQUEST_NOTARGET(400, "noTarget", "The specified \"path\" did not yield an attribute or attribute value that could be operated on. "
+ + "This occurs when the specified \"path\" value contains a filter that yields no match."),
+
+ BAD_REQUEST_INVALID_VALUE(400, "invalidValue", "A required value was missing, or the value specified was not compatible with the operation"
+ + " or attribute type."),
+
+ BAD_REQUEST_INVALID_VERSION(400, "invalidVers", "The specified SCIM protocol version is not supported");
private int val;
private String desc;
- private ErrorCode( int val, String desc )
+ private String scimType;
+
+ private ErrorCode( int val, String scimType, String desc )
{
this.val = val;
+ this.scimType = scimType;
this.desc = desc;
}
@@ -63,6 +98,16 @@ public enum ErrorCode
return val;
}
+
+ /**
+ * @return the scimType desc
+ */
+ String getScimType()
+ {
+ return scimType;
+ }
+
+
/**
* @return the desc
*/
Modified: directory/escimo/trunk/server/src/main/java/org/apache/directory/scim/rest/ResourceService.java
URL: http://svn.apache.org/viewvc/directory/escimo/trunk/server/src/main/java/org/apache/directory/scim/rest/ResourceService.java?rev=1648842&r1=1648841&r2=1648842&view=diff
==============================================================================
--- directory/escimo/trunk/server/src/main/java/org/apache/directory/scim/rest/ResourceService.java (original)
+++ directory/escimo/trunk/server/src/main/java/org/apache/directory/scim/rest/ResourceService.java Thu Jan 1 13:31:23 2015
@@ -120,7 +120,7 @@ public class ResourceService extends Abs
@POST
@Produces({MediaType.APPLICATION_JSON})
- public Response addUser( String jsonData, @Context UriInfo uriInfo )
+ public Response addResource( String jsonData, @Context UriInfo uriInfo )
{
ResponseBuilder rb = null;