This repository was archived by the owner on Nov 29, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathtypes.py
More file actions
157 lines (125 loc) · 5.1 KB
/
Copy pathtypes.py
File metadata and controls
157 lines (125 loc) · 5.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
from collections import OrderedDict
import six
from graphene.types.field import Field
from graphene.types.interface import Interface, InterfaceMeta
from graphene.types.options import Options
from graphene.types.union import Union, UnionMeta
from graphene.types.utils import get_field_as, merge, yank_fields_from_attrs
from graphene.utils.is_base_type import is_base_type
from graphene_sqlalchemy.registry import Registry, get_global_registry
from graphene_sqlalchemy.types import construct_fields
from graphene_sqlalchemy.utils import is_mapped
from pyramid.httpexceptions import HTTPUnauthorized
from pyramid.security import Everyone
from sqlalchemy.orm.exc import NoResultFound
from assembl.auth import CrudPermissions
from assembl.auth.util import get_permissions
def get_base_fields(bases, _as=None):
'''
Get all the fields in the given bases
same as graphene.types.utils.get_base_fields but with SQLAlchemyInterface
check
'''
fields = OrderedDict()
from graphene.types import AbstractType
from .types import SQLAlchemyInterface
# We allow inheritance in AbstractTypes and Interfaces but not ObjectTypes
inherited_bases = (AbstractType, Interface, SQLAlchemyInterface)
for base in bases:
if base in inherited_bases or not issubclass(base, inherited_bases):
continue
for name, field in base._meta.fields.items():
if name in fields:
continue
fields[name] = get_field_as(field, _as=_as)
return fields
class SQLAlchemyInterfaceMeta(InterfaceMeta):
@staticmethod
def __new__(cls, name, bases, attrs):
# Also ensure initialization is only performed for subclasses of
# SQLAlchemyInterface (excluding SQLAlchemyInterface class itself).
if not is_base_type(bases, SQLAlchemyInterfaceMeta):
return type.__new__(cls, name, bases, attrs)
options = Options(
attrs.pop('Meta', None),
name=name,
description=attrs.pop('__doc__', None),
model=None,
local_fields=None,
only_fields=(),
exclude_fields=(),
# id='id',
registry=None
)
if not options.registry:
options.registry = get_global_registry()
assert isinstance(options.registry, Registry), (
'The attribute registry in {}.Meta needs to be an'
' instance of Registry, received "{}".'
).format(name, options.registry)
assert is_mapped(options.model), (
'You need to pass a valid SQLAlchemy Model in '
'{}.Meta, received "{}".'
).format(name, options.model)
cls = type.__new__(cls, name, bases, dict(attrs, _meta=options))
options.base_fields = ()
options.base_fields = get_base_fields(bases, _as=Field)
if not options.local_fields:
options.local_fields = yank_fields_from_attrs(attrs, _as=Field)
# options.registry.register(cls)
options.fields = merge(
options.base_fields,
options.local_fields
)
options.sqlalchemy_fields = yank_fields_from_attrs(
construct_fields(options),
_as=Field,
)
options.fields = merge(
options.sqlalchemy_fields,
options.base_fields,
options.local_fields
)
return cls
class SQLAlchemyInterface(six.with_metaclass(
SQLAlchemyInterfaceMeta, Interface)):
pass
class SQLAlchemyUnionMeta(UnionMeta):
"""Same as original UnionMeta, but with model=None in the options
to be able to specify the model attribute for Meta in SQLAlchemyUnion
"""
def __new__(cls, name, bases, attrs):
# Also ensure initialization is only performed for subclasses of
# Union
if not is_base_type(bases, SQLAlchemyUnionMeta):
return type.__new__(cls, name, bases, attrs)
options = Options(
attrs.pop('Meta', None),
name=name,
description=attrs.get('__doc__'),
types=(),
model=None
)
assert (
isinstance(options.types, (list, tuple)) and
len(options.types) > 0
), 'Must provide types for Union {}.'.format(options.name)
return type.__new__(cls, name, bases, dict(attrs, _meta=options))
class SQLAlchemyUnion(six.with_metaclass(SQLAlchemyUnionMeta, Union)):
pass
class SecureObjectType(object):
@classmethod
def get_node(cls, id, context, info):
try:
result = cls.get_query(context).get(id)
except NoResultFound:
return None
# The user can't retrieve a content from a different discussion
discussion_id = context.matchdict['discussion_id']
if hasattr(result, 'discussion_id') and result.discussion_id != discussion_id:
raise HTTPUnauthorized()
user_id = context.authenticated_userid or Everyone
permissions = get_permissions(user_id, discussion_id)
if not result.user_can(user_id, CrudPermissions.READ, permissions):
raise HTTPUnauthorized()
return result