We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Getting error while creating authority with lemur_cryptography plugin
I added a comment to the offending commit code here: https://github.com/Netflix/lemur/commit/d53f64890cb656765bc1c18f4b8442ee3a592f47

Upon creating an authority certificate with the lemur_cryptography plugin here, I get an error because unit is None and cannot be compared to 90. Is it reasonable to make an validation assumption that unit should be 0 if undefined?

I haven't quite been able to trace how this validation function is called, so I'm not entirely clear on what it is doing or why it's involved in the creation of an authority certificate, but not in the creation of a certificate signed by an authority.


Here's the error I get upon submitting an authority for creation.
```
2017-03-07 01:44:41,352 ERROR: Exception on /api/1/authorities [POST] [in /home/lemur/venv/lib/python3.4/site-packages/flask/app.py:1560]
Traceback (most recent call last):
  File "/home/lemur/venv/lib/python3.4/site-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/lemur/venv/lib/python3.4/site-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/lemur/venv/lib/python3.4/site-packages/flask_restful/__init__.py", line 477, in wrapper
    resp = resource(*args, **kwargs)
  File "/home/lemur/venv/lib/python3.4/site-packages/flask/views.py", line 84, in view
    return self.dispatch_request(*args, **kwargs)
  File "/home/lemur/venv/lib/python3.4/site-packages/flask_restful/__init__.py", line 587, in dispatch_request
    resp = meth(*args, **kwargs)
  File "/home/lemur/app/lemur/auth/service.py", line 110, in decorated_function
    return f(*args, **kwargs)
  File "/home/lemur/app/lemur/common/schema.py", line 150, in decorated_function
    data, errors = input_schema.load(request_data)
  File "/home/lemur/venv/lib/python3.4/site-packages/marshmallow/schema.py", line 578, in load
    result, errors = self._do_load(data, many, partial=partial, postprocess=True)
  File "/home/lemur/venv/lib/python3.4/site-packages/marshmallow/schema.py", line 658, in _do_load
    index_errors=self.opts.index_errors,
  File "/home/lemur/venv/lib/python3.4/site-packages/marshmallow/marshalling.py", line 295, in deserialize
    index=(index if index_errors else None)
  File "/home/lemur/venv/lib/python3.4/site-packages/marshmallow/marshalling.py", line 68, in call_and_store
    value = getter_func(data)
  File "/home/lemur/venv/lib/python3.4/site-packages/marshmallow/marshalling.py", line 288, in <lambda>
    data
  File "/home/lemur/venv/lib/python3.4/site-packages/marshmallow/fields.py", line 265, in deserialize
    output = self._deserialize(value, attr, data)
  File "/home/lemur/venv/lib/python3.4/site-packages/marshmallow/fields.py", line 465, in _deserialize
    data, errors = self.schema.load(value)
  File "/home/lemur/venv/lib/python3.4/site-packages/marshmallow/schema.py", line 578, in load
    result, errors = self._do_load(data, many, partial=partial, postprocess=True)
  File "/home/lemur/venv/lib/python3.4/site-packages/marshmallow/schema.py", line 658, in _do_load
    index_errors=self.opts.index_errors,
  File "/home/lemur/venv/lib/python3.4/site-packages/marshmallow/marshalling.py", line 295, in deserialize
    index=(index if index_errors else None)
  File "/home/lemur/venv/lib/python3.4/site-packages/marshmallow/marshalling.py", line 68, in call_and_store
    value = getter_func(data)
  File "/home/lemur/venv/lib/python3.4/site-packages/marshmallow/marshalling.py", line 288, in <lambda>
    data
  File "/home/lemur/venv/lib/python3.4/site-packages/marshmallow/fields.py", line 266, in deserialize
    self._validate(output)
  File "/home/lemur/venv/lib/python3.4/site-packages/marshmallow/fields.py", line 196, in _validate
    r = validator(value)
  File "/home/lemur/app/lemur/schemas.py", line 44, in validate_options
    if unit > 90:
TypeError: unorderable types: NoneType() > int()
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `lemur/schemas.py`
Content:
```
1 """
2 .. module: lemur.schemas
3     :platform: unix
4     :copyright: (c) 2015 by Netflix Inc., see AUTHORS for more
5     :license: Apache, see LICENSE for more details.
6 
7 .. moduleauthor:: Kevin Glisson <kglisson@netflix.com>
8 
9 """
10 from sqlalchemy.orm.exc import NoResultFound
11 
12 from marshmallow import fields, post_load, pre_load, post_dump
13 from marshmallow.exceptions import ValidationError
14 
15 from lemur.common import validators
16 from lemur.common.schema import LemurSchema, LemurInputSchema, LemurOutputSchema
17 from lemur.common.fields import KeyUsageExtension, ExtendedKeyUsageExtension, BasicConstraintsExtension, SubjectAlternativeNameExtension
18 
19 from lemur.plugins import plugins
20 from lemur.plugins.utils import get_plugin_option
21 from lemur.roles.models import Role
22 from lemur.users.models import User
23 from lemur.authorities.models import Authority
24 from lemur.certificates.models import Certificate
25 from lemur.destinations.models import Destination
26 from lemur.notifications.models import Notification
27 
28 
29 def validate_options(options):
30     """
31     Ensures that the plugin options are valid.
32     :param options:
33     :return:
34     """
35     interval = get_plugin_option('interval', options)
36     unit = get_plugin_option('unit', options)
37 
38     if interval == 'month':
39         unit *= 30
40 
41     elif interval == 'week':
42         unit *= 7
43 
44     if unit > 90:
45         raise ValidationError('Notification cannot be more than 90 days into the future.')
46 
47 
48 def get_object_attribute(data, many=False):
49     if many:
50         ids = [d.get('id') for d in data]
51         names = [d.get('name') for d in data]
52 
53         if None in ids:
54             if None in names:
55                 raise ValidationError('Associated object require a name or id.')
56             else:
57                 return 'name'
58         return 'id'
59     else:
60         if data.get('id'):
61             return 'id'
62         elif data.get('name'):
63             return 'name'
64         else:
65             raise ValidationError('Associated object require a name or id.')
66 
67 
68 def fetch_objects(model, data, many=False):
69     attr = get_object_attribute(data, many=many)
70 
71     if many:
72         values = [v[attr] for v in data]
73         items = model.query.filter(getattr(model, attr).in_(values)).all()
74         found = [getattr(i, attr) for i in items]
75         diff = set(values).symmetric_difference(set(found))
76 
77         if diff:
78             raise ValidationError('Unable to locate {model} with {attr} {diff}'.format(
79                 model=model,
80                 attr=attr,
81                 diff=",".join(list(diff))))
82 
83         return items
84 
85     else:
86         try:
87             return model.query.filter(getattr(model, attr) == data[attr]).one()
88         except NoResultFound:
89             raise ValidationError('Unable to find {model} with {attr}: {data}'.format(
90                 model=model,
91                 attr=attr,
92                 data=data[attr]))
93 
94 
95 class AssociatedAuthoritySchema(LemurInputSchema):
96     id = fields.Int()
97     name = fields.String()
98 
99     @post_load
100     def get_object(self, data, many=False):
101         return fetch_objects(Authority, data, many=many)
102 
103 
104 class AssociatedRoleSchema(LemurInputSchema):
105     id = fields.Int()
106     name = fields.String()
107 
108     @post_load
109     def get_object(self, data, many=False):
110         return fetch_objects(Role, data, many=many)
111 
112 
113 class AssociatedDestinationSchema(LemurInputSchema):
114     id = fields.Int()
115     name = fields.String()
116 
117     @post_load
118     def get_object(self, data, many=False):
119         return fetch_objects(Destination, data, many=many)
120 
121 
122 class AssociatedNotificationSchema(LemurInputSchema):
123     id = fields.Int()
124     name = fields.String()
125 
126     @post_load
127     def get_object(self, data, many=False):
128         return fetch_objects(Notification, data, many=many)
129 
130 
131 class AssociatedCertificateSchema(LemurInputSchema):
132     id = fields.Int()
133     name = fields.String()
134 
135     @post_load
136     def get_object(self, data, many=False):
137         return fetch_objects(Certificate, data, many=many)
138 
139 
140 class AssociatedUserSchema(LemurInputSchema):
141     id = fields.Int()
142     name = fields.String()
143 
144     @post_load
145     def get_object(self, data, many=False):
146         return fetch_objects(User, data, many=many)
147 
148 
149 class PluginInputSchema(LemurInputSchema):
150     plugin_options = fields.List(fields.Dict(), validate=validate_options)
151     slug = fields.String(required=True)
152     title = fields.String()
153     description = fields.String()
154 
155     @post_load
156     def get_object(self, data, many=False):
157         try:
158             data['plugin_object'] = plugins.get(data['slug'])
159             return data
160         except Exception:
161             raise ValidationError('Unable to find plugin: {0}'.format(data['slug']))
162 
163 
164 class PluginOutputSchema(LemurOutputSchema):
165     id = fields.Integer()
166     label = fields.String()
167     description = fields.String()
168     active = fields.Boolean()
169     options = fields.List(fields.Dict(), dump_to='pluginOptions')
170     slug = fields.String()
171     title = fields.String()
172 
173 
174 plugins_output_schema = PluginOutputSchema(many=True)
175 plugin_output_schema = PluginOutputSchema
176 
177 
178 class BaseExtensionSchema(LemurSchema):
179     @pre_load(pass_many=True)
180     def preprocess(self, data, many):
181         return self.under(data, many=many)
182 
183     @post_dump(pass_many=True)
184     def post_process(self, data, many):
185         if data:
186             data = self.camel(data, many=many)
187         return data
188 
189 
190 class AuthorityKeyIdentifierSchema(BaseExtensionSchema):
191     use_key_identifier = fields.Boolean()
192     use_authority_cert = fields.Boolean()
193 
194 
195 class CertificateInfoAccessSchema(BaseExtensionSchema):
196     include_aia = fields.Boolean()
197 
198     @post_dump
199     def handle_keys(self, data):
200         return {'includeAIA': data['include_aia']}
201 
202 
203 class SubjectKeyIdentifierSchema(BaseExtensionSchema):
204     include_ski = fields.Boolean()
205 
206     @post_dump
207     def handle_keys(self, data):
208         return {'includeSKI': data['include_ski']}
209 
210 
211 class CustomOIDSchema(BaseExtensionSchema):
212     oid = fields.String()
213     encoding = fields.String(validate=validators.encoding)
214     value = fields.String()
215     is_critical = fields.Boolean()
216 
217 
218 class NamesSchema(BaseExtensionSchema):
219     names = SubjectAlternativeNameExtension()
220 
221 
222 class ExtensionSchema(BaseExtensionSchema):
223     basic_constraints = BasicConstraintsExtension(missing={'ca': False})
224     key_usage = KeyUsageExtension()
225     extended_key_usage = ExtendedKeyUsageExtension()
226     subject_key_identifier = fields.Nested(SubjectKeyIdentifierSchema)
227     sub_alt_names = fields.Nested(NamesSchema)
228     authority_key_identifier = fields.Nested(AuthorityKeyIdentifierSchema)
229     certificate_info_access = fields.Nested(CertificateInfoAccessSchema)
230     # FIXME: Convert custom OIDs to a custom field in fields.py like other Extensions
231     # FIXME: Remove support in UI for Critical custom extensions https://github.com/Netflix/lemur/issues/665
232     custom = fields.List(fields.Nested(CustomOIDSchema))
233 
234 
235 class EndpointNestedOutputSchema(LemurOutputSchema):
236     __envelope__ = False
237     id = fields.Integer()
238     description = fields.String()
239     name = fields.String()
240     dnsname = fields.String()
241     owner = fields.Email()
242     type = fields.String()
243     active = fields.Boolean()
244
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/lemur/schemas.py b/lemur/schemas.py
--- a/lemur/schemas.py
+++ b/lemur/schemas.py
@@ -35,6 +35,9 @@
     interval = get_plugin_option('interval', options)
     unit = get_plugin_option('unit', options)
 
+    if not interval and not unit:
+        return
+
     if interval == 'month':
         unit *= 30

{"golden_diff": "diff --git a/lemur/schemas.py b/lemur/schemas.py\n--- a/lemur/schemas.py\n+++ b/lemur/schemas.py\n@@ -35,6 +35,9 @@\n     interval = get_plugin_option('interval', options)\n     unit = get_plugin_option('unit', options)\n \n+    if not interval and not unit:\n+        return\n+\n     if interval == 'month':\n         unit *= 30\n", "issue": "Getting error while creating authority with lemur_cryptography plugin\nI added a comment to the offending commit code here: https://github.com/Netflix/lemur/commit/d53f64890cb656765bc1c18f4b8442ee3a592f47\r\n\r\nUpon creating an authority certificate with the lemur_cryptography plugin here, I get an error because unit is None and cannot be compared to 90. Is it reasonable to make an validation assumption that unit should be 0 if undefined?\r\n\r\nI haven't quite been able to trace how this validation function is called, so I'm not entirely clear on what it is doing or why it's involved in the creation of an authority certificate, but not in the creation of a certificate signed by an authority.\r\n\r\n\r\nHere's the error I get upon submitting an authority for creation.\r\n```\r\n2017-03-07 01:44:41,352 ERROR: Exception on /api/1/authorities [POST] [in /home/lemur/venv/lib/python3.4/site-packages/flask/app.py:1560]\r\nTraceback (most recent call last):\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/flask/app.py\", line 1612, in full_dispatch_request\r\n    rv = self.dispatch_request()\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/flask/app.py\", line 1598, in dispatch_request\r\n    return self.view_functions[rule.endpoint](**req.view_args)\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/flask_restful/__init__.py\", line 477, in wrapper\r\n    resp = resource(*args, **kwargs)\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/flask/views.py\", line 84, in view\r\n    return self.dispatch_request(*args, **kwargs)\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/flask_restful/__init__.py\", line 587, in dispatch_request\r\n    resp = meth(*args, **kwargs)\r\n  File \"/home/lemur/app/lemur/auth/service.py\", line 110, in decorated_function\r\n    return f(*args, **kwargs)\r\n  File \"/home/lemur/app/lemur/common/schema.py\", line 150, in decorated_function\r\n    data, errors = input_schema.load(request_data)\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/marshmallow/schema.py\", line 578, in load\r\n    result, errors = self._do_load(data, many, partial=partial, postprocess=True)\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/marshmallow/schema.py\", line 658, in _do_load\r\n    index_errors=self.opts.index_errors,\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/marshmallow/marshalling.py\", line 295, in deserialize\r\n    index=(index if index_errors else None)\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/marshmallow/marshalling.py\", line 68, in call_and_store\r\n    value = getter_func(data)\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/marshmallow/marshalling.py\", line 288, in <lambda>\r\n    data\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/marshmallow/fields.py\", line 265, in deserialize\r\n    output = self._deserialize(value, attr, data)\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/marshmallow/fields.py\", line 465, in _deserialize\r\n    data, errors = self.schema.load(value)\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/marshmallow/schema.py\", line 578, in load\r\n    result, errors = self._do_load(data, many, partial=partial, postprocess=True)\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/marshmallow/schema.py\", line 658, in _do_load\r\n    index_errors=self.opts.index_errors,\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/marshmallow/marshalling.py\", line 295, in deserialize\r\n    index=(index if index_errors else None)\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/marshmallow/marshalling.py\", line 68, in call_and_store\r\n    value = getter_func(data)\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/marshmallow/marshalling.py\", line 288, in <lambda>\r\n    data\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/marshmallow/fields.py\", line 266, in deserialize\r\n    self._validate(output)\r\n  File \"/home/lemur/venv/lib/python3.4/site-packages/marshmallow/fields.py\", line 196, in _validate\r\n    r = validator(value)\r\n  File \"/home/lemur/app/lemur/schemas.py\", line 44, in validate_options\r\n    if unit > 90:\r\nTypeError: unorderable types: NoneType() > int()\r\n```\n", "before_files": [{"content": "\"\"\"\n.. module: lemur.schemas\n    :platform: unix\n    :copyright: (c) 2015 by Netflix Inc., see AUTHORS for more\n    :license: Apache, see LICENSE for more details.\n\n.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>\n\n\"\"\"\nfrom sqlalchemy.orm.exc import NoResultFound\n\nfrom marshmallow import fields, post_load, pre_load, post_dump\nfrom marshmallow.exceptions import ValidationError\n\nfrom lemur.common import validators\nfrom lemur.common.schema import LemurSchema, LemurInputSchema, LemurOutputSchema\nfrom lemur.common.fields import KeyUsageExtension, ExtendedKeyUsageExtension, BasicConstraintsExtension, SubjectAlternativeNameExtension\n\nfrom lemur.plugins import plugins\nfrom lemur.plugins.utils import get_plugin_option\nfrom lemur.roles.models import Role\nfrom lemur.users.models import User\nfrom lemur.authorities.models import Authority\nfrom lemur.certificates.models import Certificate\nfrom lemur.destinations.models import Destination\nfrom lemur.notifications.models import Notification\n\n\ndef validate_options(options):\n    \"\"\"\n    Ensures that the plugin options are valid.\n    :param options:\n    :return:\n    \"\"\"\n    interval = get_plugin_option('interval', options)\n    unit = get_plugin_option('unit', options)\n\n    if interval == 'month':\n        unit *= 30\n\n    elif interval == 'week':\n        unit *= 7\n\n    if unit > 90:\n        raise ValidationError('Notification cannot be more than 90 days into the future.')\n\n\ndef get_object_attribute(data, many=False):\n    if many:\n        ids = [d.get('id') for d in data]\n        names = [d.get('name') for d in data]\n\n        if None in ids:\n            if None in names:\n                raise ValidationError('Associated object require a name or id.')\n            else:\n                return 'name'\n        return 'id'\n    else:\n        if data.get('id'):\n            return 'id'\n        elif data.get('name'):\n            return 'name'\n        else:\n            raise ValidationError('Associated object require a name or id.')\n\n\ndef fetch_objects(model, data, many=False):\n    attr = get_object_attribute(data, many=many)\n\n    if many:\n        values = [v[attr] for v in data]\n        items = model.query.filter(getattr(model, attr).in_(values)).all()\n        found = [getattr(i, attr) for i in items]\n        diff = set(values).symmetric_difference(set(found))\n\n        if diff:\n            raise ValidationError('Unable to locate {model} with {attr} {diff}'.format(\n                model=model,\n                attr=attr,\n                diff=\",\".join(list(diff))))\n\n        return items\n\n    else:\n        try:\n            return model.query.filter(getattr(model, attr) == data[attr]).one()\n        except NoResultFound:\n            raise ValidationError('Unable to find {model} with {attr}: {data}'.format(\n                model=model,\n                attr=attr,\n                data=data[attr]))\n\n\nclass AssociatedAuthoritySchema(LemurInputSchema):\n    id = fields.Int()\n    name = fields.String()\n\n    @post_load\n    def get_object(self, data, many=False):\n        return fetch_objects(Authority, data, many=many)\n\n\nclass AssociatedRoleSchema(LemurInputSchema):\n    id = fields.Int()\n    name = fields.String()\n\n    @post_load\n    def get_object(self, data, many=False):\n        return fetch_objects(Role, data, many=many)\n\n\nclass AssociatedDestinationSchema(LemurInputSchema):\n    id = fields.Int()\n    name = fields.String()\n\n    @post_load\n    def get_object(self, data, many=False):\n        return fetch_objects(Destination, data, many=many)\n\n\nclass AssociatedNotificationSchema(LemurInputSchema):\n    id = fields.Int()\n    name = fields.String()\n\n    @post_load\n    def get_object(self, data, many=False):\n        return fetch_objects(Notification, data, many=many)\n\n\nclass AssociatedCertificateSchema(LemurInputSchema):\n    id = fields.Int()\n    name = fields.String()\n\n    @post_load\n    def get_object(self, data, many=False):\n        return fetch_objects(Certificate, data, many=many)\n\n\nclass AssociatedUserSchema(LemurInputSchema):\n    id = fields.Int()\n    name = fields.String()\n\n    @post_load\n    def get_object(self, data, many=False):\n        return fetch_objects(User, data, many=many)\n\n\nclass PluginInputSchema(LemurInputSchema):\n    plugin_options = fields.List(fields.Dict(), validate=validate_options)\n    slug = fields.String(required=True)\n    title = fields.String()\n    description = fields.String()\n\n    @post_load\n    def get_object(self, data, many=False):\n        try:\n            data['plugin_object'] = plugins.get(data['slug'])\n            return data\n        except Exception:\n            raise ValidationError('Unable to find plugin: {0}'.format(data['slug']))\n\n\nclass PluginOutputSchema(LemurOutputSchema):\n    id = fields.Integer()\n    label = fields.String()\n    description = fields.String()\n    active = fields.Boolean()\n    options = fields.List(fields.Dict(), dump_to='pluginOptions')\n    slug = fields.String()\n    title = fields.String()\n\n\nplugins_output_schema = PluginOutputSchema(many=True)\nplugin_output_schema = PluginOutputSchema\n\n\nclass BaseExtensionSchema(LemurSchema):\n    @pre_load(pass_many=True)\n    def preprocess(self, data, many):\n        return self.under(data, many=many)\n\n    @post_dump(pass_many=True)\n    def post_process(self, data, many):\n        if data:\n            data = self.camel(data, many=many)\n        return data\n\n\nclass AuthorityKeyIdentifierSchema(BaseExtensionSchema):\n    use_key_identifier = fields.Boolean()\n    use_authority_cert = fields.Boolean()\n\n\nclass CertificateInfoAccessSchema(BaseExtensionSchema):\n    include_aia = fields.Boolean()\n\n    @post_dump\n    def handle_keys(self, data):\n        return {'includeAIA': data['include_aia']}\n\n\nclass SubjectKeyIdentifierSchema(BaseExtensionSchema):\n    include_ski = fields.Boolean()\n\n    @post_dump\n    def handle_keys(self, data):\n        return {'includeSKI': data['include_ski']}\n\n\nclass CustomOIDSchema(BaseExtensionSchema):\n    oid = fields.String()\n    encoding = fields.String(validate=validators.encoding)\n    value = fields.String()\n    is_critical = fields.Boolean()\n\n\nclass NamesSchema(BaseExtensionSchema):\n    names = SubjectAlternativeNameExtension()\n\n\nclass ExtensionSchema(BaseExtensionSchema):\n    basic_constraints = BasicConstraintsExtension(missing={'ca': False})\n    key_usage = KeyUsageExtension()\n    extended_key_usage = ExtendedKeyUsageExtension()\n    subject_key_identifier = fields.Nested(SubjectKeyIdentifierSchema)\n    sub_alt_names = fields.Nested(NamesSchema)\n    authority_key_identifier = fields.Nested(AuthorityKeyIdentifierSchema)\n    certificate_info_access = fields.Nested(CertificateInfoAccessSchema)\n    # FIXME: Convert custom OIDs to a custom field in fields.py like other Extensions\n    # FIXME: Remove support in UI for Critical custom extensions https://github.com/Netflix/lemur/issues/665\n    custom = fields.List(fields.Nested(CustomOIDSchema))\n\n\nclass EndpointNestedOutputSchema(LemurOutputSchema):\n    __envelope__ = False\n    id = fields.Integer()\n    description = fields.String()\n    name = fields.String()\n    dnsname = fields.String()\n    owner = fields.Email()\n    type = fields.String()\n    active = fields.Boolean()\n", "path": "lemur/schemas.py"}], "after_files": [{"content": "\"\"\"\n.. module: lemur.schemas\n    :platform: unix\n    :copyright: (c) 2015 by Netflix Inc., see AUTHORS for more\n    :license: Apache, see LICENSE for more details.\n\n.. moduleauthor:: Kevin Glisson <kglisson@netflix.com>\n\n\"\"\"\nfrom sqlalchemy.orm.exc import NoResultFound\n\nfrom marshmallow import fields, post_load, pre_load, post_dump\nfrom marshmallow.exceptions import ValidationError\n\nfrom lemur.common import validators\nfrom lemur.common.schema import LemurSchema, LemurInputSchema, LemurOutputSchema\nfrom lemur.common.fields import KeyUsageExtension, ExtendedKeyUsageExtension, BasicConstraintsExtension, SubjectAlternativeNameExtension\n\nfrom lemur.plugins import plugins\nfrom lemur.plugins.utils import get_plugin_option\nfrom lemur.roles.models import Role\nfrom lemur.users.models import User\nfrom lemur.authorities.models import Authority\nfrom lemur.certificates.models import Certificate\nfrom lemur.destinations.models import Destination\nfrom lemur.notifications.models import Notification\n\n\ndef validate_options(options):\n    \"\"\"\n    Ensures that the plugin options are valid.\n    :param options:\n    :return:\n    \"\"\"\n    interval = get_plugin_option('interval', options)\n    unit = get_plugin_option('unit', options)\n\n    if not interval and not unit:\n        return\n\n    if interval == 'month':\n        unit *= 30\n\n    elif interval == 'week':\n        unit *= 7\n\n    if unit > 90:\n        raise ValidationError('Notification cannot be more than 90 days into the future.')\n\n\ndef get_object_attribute(data, many=False):\n    if many:\n        ids = [d.get('id') for d in data]\n        names = [d.get('name') for d in data]\n\n        if None in ids:\n            if None in names:\n                raise ValidationError('Associated object require a name or id.')\n            else:\n                return 'name'\n        return 'id'\n    else:\n        if data.get('id'):\n            return 'id'\n        elif data.get('name'):\n            return 'name'\n        else:\n            raise ValidationError('Associated object require a name or id.')\n\n\ndef fetch_objects(model, data, many=False):\n    attr = get_object_attribute(data, many=many)\n\n    if many:\n        values = [v[attr] for v in data]\n        items = model.query.filter(getattr(model, attr).in_(values)).all()\n        found = [getattr(i, attr) for i in items]\n        diff = set(values).symmetric_difference(set(found))\n\n        if diff:\n            raise ValidationError('Unable to locate {model} with {attr} {diff}'.format(\n                model=model,\n                attr=attr,\n                diff=\",\".join(list(diff))))\n\n        return items\n\n    else:\n        try:\n            return model.query.filter(getattr(model, attr) == data[attr]).one()\n        except NoResultFound:\n            raise ValidationError('Unable to find {model} with {attr}: {data}'.format(\n                model=model,\n                attr=attr,\n                data=data[attr]))\n\n\nclass AssociatedAuthoritySchema(LemurInputSchema):\n    id = fields.Int()\n    name = fields.String()\n\n    @post_load\n    def get_object(self, data, many=False):\n        return fetch_objects(Authority, data, many=many)\n\n\nclass AssociatedRoleSchema(LemurInputSchema):\n    id = fields.Int()\n    name = fields.String()\n\n    @post_load\n    def get_object(self, data, many=False):\n        return fetch_objects(Role, data, many=many)\n\n\nclass AssociatedDestinationSchema(LemurInputSchema):\n    id = fields.Int()\n    name = fields.String()\n\n    @post_load\n    def get_object(self, data, many=False):\n        return fetch_objects(Destination, data, many=many)\n\n\nclass AssociatedNotificationSchema(LemurInputSchema):\n    id = fields.Int()\n    name = fields.String()\n\n    @post_load\n    def get_object(self, data, many=False):\n        return fetch_objects(Notification, data, many=many)\n\n\nclass AssociatedCertificateSchema(LemurInputSchema):\n    id = fields.Int()\n    name = fields.String()\n\n    @post_load\n    def get_object(self, data, many=False):\n        return fetch_objects(Certificate, data, many=many)\n\n\nclass AssociatedUserSchema(LemurInputSchema):\n    id = fields.Int()\n    name = fields.String()\n\n    @post_load\n    def get_object(self, data, many=False):\n        return fetch_objects(User, data, many=many)\n\n\nclass PluginInputSchema(LemurInputSchema):\n    plugin_options = fields.List(fields.Dict(), validate=validate_options)\n    slug = fields.String(required=True)\n    title = fields.String()\n    description = fields.String()\n\n    @post_load\n    def get_object(self, data, many=False):\n        try:\n            data['plugin_object'] = plugins.get(data['slug'])\n            return data\n        except Exception:\n            raise ValidationError('Unable to find plugin: {0}'.format(data['slug']))\n\n\nclass PluginOutputSchema(LemurOutputSchema):\n    id = fields.Integer()\n    label = fields.String()\n    description = fields.String()\n    active = fields.Boolean()\n    options = fields.List(fields.Dict(), dump_to='pluginOptions')\n    slug = fields.String()\n    title = fields.String()\n\n\nplugins_output_schema = PluginOutputSchema(many=True)\nplugin_output_schema = PluginOutputSchema\n\n\nclass BaseExtensionSchema(LemurSchema):\n    @pre_load(pass_many=True)\n    def preprocess(self, data, many):\n        return self.under(data, many=many)\n\n    @post_dump(pass_many=True)\n    def post_process(self, data, many):\n        if data:\n            data = self.camel(data, many=many)\n        return data\n\n\nclass AuthorityKeyIdentifierSchema(BaseExtensionSchema):\n    use_key_identifier = fields.Boolean()\n    use_authority_cert = fields.Boolean()\n\n\nclass CertificateInfoAccessSchema(BaseExtensionSchema):\n    include_aia = fields.Boolean()\n\n    @post_dump\n    def handle_keys(self, data):\n        return {'includeAIA': data['include_aia']}\n\n\nclass SubjectKeyIdentifierSchema(BaseExtensionSchema):\n    include_ski = fields.Boolean()\n\n    @post_dump\n    def handle_keys(self, data):\n        return {'includeSKI': data['include_ski']}\n\n\nclass CustomOIDSchema(BaseExtensionSchema):\n    oid = fields.String()\n    encoding = fields.String(validate=validators.encoding)\n    value = fields.String()\n    is_critical = fields.Boolean()\n\n\nclass NamesSchema(BaseExtensionSchema):\n    names = SubjectAlternativeNameExtension()\n\n\nclass ExtensionSchema(BaseExtensionSchema):\n    basic_constraints = BasicConstraintsExtension(missing={'ca': False})\n    key_usage = KeyUsageExtension()\n    extended_key_usage = ExtendedKeyUsageExtension()\n    subject_key_identifier = fields.Nested(SubjectKeyIdentifierSchema)\n    sub_alt_names = fields.Nested(NamesSchema)\n    authority_key_identifier = fields.Nested(AuthorityKeyIdentifierSchema)\n    certificate_info_access = fields.Nested(CertificateInfoAccessSchema)\n    # FIXME: Convert custom OIDs to a custom field in fields.py like other Extensions\n    # FIXME: Remove support in UI for Critical custom extensions https://github.com/Netflix/lemur/issues/665\n    custom = fields.List(fields.Nested(CustomOIDSchema))\n\n\nclass EndpointNestedOutputSchema(LemurOutputSchema):\n    __envelope__ = False\n    id = fields.Integer()\n    description = fields.String()\n    name = fields.String()\n    dnsname = fields.String()\n    owner = fields.Email()\n    type = fields.String()\n    active = fields.Boolean()\n", "path": "lemur/schemas.py"}]}