Created
May 20, 2014 14:00
-
-
Save xhanin/6ef3d6f76ce176ef0528 to your computer and use it in GitHub Desktop.
Secured Jongo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Module(priority = -100) | |
public class JongoModule { | |
JacksonMapper.Builder getJacksonMapperBuilder() { | |
return new JacksonMapper.Builder() | |
.registerModule(new BsonJodaTimeModule()) | |
.withView(Views.Private.class) | |
; | |
} | |
@Provides @Named("Mapper") | |
public Mapper mapper() { | |
return getJacksonMapperBuilder().build(); | |
} | |
// secured jongo, will be used for secured jongo collections which will automatically add security handling query part | |
@Provides @Named("SecuredMapper") | |
public Mapper securedMapper() { | |
SecuredQueryFactory queryFactory = new SecuredQueryFactory(); | |
Mapper mapper = getJacksonMapperBuilder() | |
.withQueryFactory(queryFactory) | |
.build(); | |
queryFactory.setMarshaller(mapper.getMarshaller()); | |
return mapper; | |
} | |
@Provides @Named("SecuredJongo") | |
public Jongo securedJongo(@Named(MongoModule.MONGO_DB_NAME) String dbName, | |
@Named(MongoModule.MONGO_CLIENT_NAME) MongoClient mongoClient, | |
@Named("SecuredMapper") final Mapper securedMapper, | |
@Named("Mapper") final Mapper mapper) { | |
// Override Jongo to be able to use SecuredFind instead of Find | |
return new Jongo(mongoClient.getDB(dbName), securedMapper) { | |
@Override | |
public MongoCollection getCollection(String name) { | |
final DBCollection dbCollection = getDatabase().getCollection(name); | |
dbCollection.setDBDecoderFactory(BsonDBDecoder.FACTORY); | |
dbCollection.setDBEncoderFactory(BsonDBEncoder.FACTORY); | |
return new MongoCollection(dbCollection, securedMapper) { | |
@Override | |
public Find find(String query, Object... parameters) { | |
return new SecuredFind(dbCollection, dbCollection.getReadPreference(), securedMapper.getUnmarshaller(), | |
mapper.getQueryFactory(), securedMapper.getQueryFactory(), query, parameters); | |
} | |
@Override | |
public FindOne findOne(String query, Object... parameters) { | |
return new SecuredFindOne(dbCollection, dbCollection.getReadPreference(), securedMapper.getUnmarshaller(), | |
mapper.getQueryFactory(), securedMapper.getQueryFactory(), query, parameters); | |
} | |
@Override | |
public FindOne findOne(ObjectId id) { | |
return new SecuredFindOne(dbCollection, dbCollection.getReadPreference(), securedMapper.getUnmarshaller(), | |
mapper.getQueryFactory(), securedMapper.getQueryFactory(), "{_id:#}", id); | |
} | |
}; | |
} | |
}; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Mostly copied from https://github.com/bguerout/jongo/blob/1.0/src/main/java/org/jongo/Find.java which has the | |
* following license : | |
* | |
* ---- | |
* Copyright (C) 2011 Benoit GUEROUT <bguerout at gmail dot com> and Yves AMSELLEM <amsellem dot yves at gmail dot com> | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
* ---- | |
* | |
* Only the constructor is modified to use different query factories for the query itself (secured) and other | |
* usages (unsecured). | |
*/ | |
package org.jongo; | |
public class SecuredFind extends Find { | |
private final DBCollection collection; | |
private final ReadPreference readPreference; | |
private final Unmarshaller unmarshaller; | |
private final QueryFactory queryFactory; | |
private final Query query; | |
private Query fields, sort, hint; | |
private Integer limit, skip; | |
public SecuredFind(DBCollection collection, ReadPreference readPreference, Unmarshaller unmarshaller, | |
QueryFactory queryFactory, QueryFactory securedQueryFactory, String query, Object... parameters) { | |
// mandatory call to super, but base class is not actually used | |
super(collection, readPreference, unmarshaller, securedQueryFactory, query, parameters); | |
this.readPreference = readPreference; | |
this.unmarshaller = unmarshaller; | |
this.collection = collection; | |
this.queryFactory = queryFactory; | |
this.query = securedQueryFactory.createQuery(query, parameters); | |
} | |
public <T> Iterable<T> as(final Class<T> clazz) { | |
return map(newMapper(clazz, unmarshaller)); | |
} | |
public <T> Iterable<T> map(ResultHandler<T> resultHandler) { | |
DBCursor cursor = new DBCursor(collection, query.toDBObject(), getFieldsAsDBObject(), readPreference); | |
addOptionsOn(cursor); | |
return new MongoIterator<T>(cursor, resultHandler); | |
} | |
private void addOptionsOn(DBCursor cursor) { | |
if (limit != null) | |
cursor.limit(limit); | |
if (skip != null) | |
cursor.skip(skip); | |
if (sort != null) { | |
cursor.sort(sort.toDBObject()); | |
} | |
if (hint != null) { | |
cursor.hint(hint.toDBObject()); | |
} | |
} | |
public Find projection(String fields) { | |
this.fields = queryFactory.createQuery(fields); | |
return this; | |
} | |
public Find projection(String fields, Object... parameters) { | |
this.fields = queryFactory.createQuery(fields, parameters); | |
return this; | |
} | |
public Find limit(int limit) { | |
this.limit = limit; | |
return this; | |
} | |
public Find skip(int skip) { | |
this.skip = skip; | |
return this; | |
} | |
public Find sort(String sort) { | |
this.sort = queryFactory.createQuery(sort); | |
return this; | |
} | |
public Find hint(final String hint) { | |
this.hint = queryFactory.createQuery(hint); | |
return this; | |
} | |
private DBObject getFieldsAsDBObject() { | |
return fields == null ? null : fields.toDBObject(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SecuredQueryFactory implements QueryFactory { | |
private Marshaller marshaller; | |
private QueryFactory delegate; | |
@Override | |
public Query createQuery(String query, Object... parameters) { | |
Query q = delegate.createQuery(query, parameters); | |
RestxSession session = RestxSession.current(); | |
if (session == null) { // session can be null, eg in queries made to load the session itself | |
return q; | |
} | |
Optional<? extends RestxPrincipal> principal = session.getPrincipal(); | |
if (!principal.isPresent()) { | |
return q; | |
} | |
QueryBuilder securityBuilder = securityQueryBuilder(principal.get()); | |
return new SecuredQuery(securityBuilder.and(q.toDBObject()).get()); | |
} | |
private QueryBuilder securityQueryBuilder(RestxPrincipal principal) { | |
// application specific security logic | |
return QueryBuilder.start() | |
.put("role").is(principal.getRole()).get(); | |
} | |
public void setMarshaller(Marshaller marshaller) { | |
this.marshaller = marshaller; | |
this.delegate = new BsonQueryFactory(marshaller); | |
} | |
public Marshaller getMarshaller() { | |
return marshaller; | |
} | |
private static class SecuredQuery implements Query { | |
private final DBObject dbo; | |
public SecuredQuery(DBObject dbo) { | |
this.dbo = dbo; | |
} | |
@Override | |
public DBObject toDBObject() { | |
return dbo; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment