A continuación se simplifica el constructor de consultas redefinido para filtrar todas las consultas del modelo (incluidas las relaciones). Puede pasarlo como parámetro query_cls
al sessionmaker
. El parámetro ID de usuario no necesita ser global en lo que respecta a la sesión cuando ya está disponible.
class HackedQuery(Query):
def get(self, ident):
# Use default implementation when there is no condition
if not self._criterion:
return Query.get(self, ident)
# Copied from Query implementation with some changes.
if hasattr(ident, '__composite_values__'):
ident = ident.__composite_values__()
mapper = self._only_mapper_zero(
"get() can only be used against a single mapped class.")
key = mapper.identity_key_from_primary_key(ident)
if ident is None:
if key is not None:
ident = key[1]
else:
from sqlalchemy import util
ident = util.to_list(ident)
if ident is not None:
columns = list(mapper.primary_key)
if len(columns)!=len(ident):
raise TypeError("Number of values doen't match number "
'of columns in primary key')
params = {}
for column, value in zip(columns, ident):
params[column.key] = value
return self.filter_by(**params).first()
def QueryPublic(entities, session=None):
# It's not directly related to the problem, but is useful too.
query = HackedQuery(entities, session).with_polymorphic('*')
# Version for several entities needs thorough testing, so we
# don't use it yet.
assert len(entities)==1, entities
cls = _class_to_mapper(entities[0]).class_
public_condition = getattr(cls, 'public_condition', None)
if public_condition is not None:
query = query.filter(public_condition)
return query
Funciona solo para consultas de modelo único, y hay mucho trabajo para hacerlo adecuado para otros casos. Me gustaría ver una versión elaborada ya que DEBE TENER funcionalidad para la mayoría de las aplicaciones web. Utiliza una condición fija almacenada en cada clase de modelo, por lo que debe modificarla según sus necesidades.
¿Ha pensado en usar el sistema de seguridad de base de datos para lograr esto? Por ejemplo, Oracle ofrece esta funcionalidad con su función VPD (http://www.oracle.com/technology/deploy/security/database-security/virtual-private-database/index.html). También puede lograr una funcionalidad similar en otras bases de datos (por ejemplo, http://ddj.com/database/215900773 y http://technet.microsoft.com/en-gb/library/cc966395.aspx). Simplemente busca "RDBSName de seguridad a nivel de fila". – stephan
o configure vistas o reglas en todas las tablas que agreguen la limitación apropiada, y despoje a los usuarios de la capacidad de leer directamente la tabla subyacente. http://www.postgresql.org/docs/8.4/interactive/rules.html –