def verify_expired(self): appier.verify( not self.is_expired(), message = "OAuth access token is expired", code = 403, exception = appier.OperationalError )
def assert_redirect_uri(self, redirect_uri): appier.verify( redirect_uri == self.redirect_uri, message = "The provided redirect URI is not valid", exception = appier.SecurityError, code = 403 )
def verify_code(self, code, grant_type = "authorization_code"): cls = self.__class__ appier.verify(not self.authorization_code == None) appier.verify(not self.authorization_code_date == None) appier.verify(self.authorization_code == code) appier.verify(time.time() - self.authorization_code_date < cls.CODE_DURATION) appier.verify(grant_type, "authorization_code")
def assert_scope(self, scope): if not self.scope: return invalid = [token for token in scope if not token in self.scope] appier.verify(not invalid, message="The provided scope is not valid", exception=appier.SecurityError, code=403)
def assert_scope(self, scope): if not self.scope: return invalid = [token for token in scope if not token in self.scope] appier.verify( not invalid, message = "The provided scope is not valid", exception = appier.SecurityError, code = 403 )
def oauth(self): oauth_verifier = self.field("oauth_verifier") appier.verify(oauth_verifier, message="Invalid OAuth response", exception=appier.OperationalError) api = self.get_api() oauth_token, oauth_token_secret = api.oauth_access(oauth_verifier) self.tokens(oauth_token, oauth_token_secret, temporary=False) return self.redirect(self.url_for("twitter.index"))
def oauth(self): code = self.field("code") error = self.field("error") appier.verify(not error, message="Invalid OAuth response (%s)" % error, exception=appier.OperationalError) api = self.get_api() access_token = api.oauth_access(code) self.session["shopify.access_token"] = access_token return self.redirect(self.url_for("shopify.index"))
def _build_script(self, action): recaptcha_key = appier.conf("RECAPTCHA_KEY", None) appier.verify(recaptcha_key, message="No reCAPTCHA site key provided") return "<script type=\"application/javascript\" src=\"https://www.google.com/recaptcha/api.js?render=%s\"></script>" % recaptcha_key +\ "<script type=\"application/javascript\">window.genRecaptcha = function() { grecaptcha.ready(function() {" +\ "document.getElementById(\"recaptcha-token\") && grecaptcha.execute(\"%s\", {action: \"%s\"}).then(function(token) {" % (recaptcha_key, action) +\ "document.getElementById(\"recaptcha-token\").value = token;" +\ "});" +\ "});" +\ "};" +\ "window.genRecaptcha();" +\ "</script>"
def test_verify(self): result = appier.verify(1 == 1) self.assertEqual(result, None) result = appier.verify("hello" == "hello") self.assertEqual(result, None) self.assertRaises(appier.AssertionError, lambda: appier.verify(1 == 2)) self.assertRaises( appier.OperationalError, lambda: appier.verify(1 == 2, exception=appier.OperationalError))
def test_verify(self): result = appier.verify(1 == 1) self.assertEqual(result, None) result = appier.verify("hello" == "hello") self.assertEqual(result, None) self.assertRaises(appier.AssertionError, lambda: appier.verify(1 == 2)) self.assertRaises( appier.OperationalError, lambda: appier.verify(1 == 2, exception = appier.OperationalError) )
def oauth(self): oauth_verifier = self.field("oauth_verifier") appier.verify( oauth_verifier, message = "Invalid OAuth response", exception = appier.OperationalError ) api = self.get_api() oauth_token, oauth_token_secret = api.oauth_access(oauth_verifier) self.tokens(oauth_token, oauth_token_secret, temporary = False) return self.redirect( self.url_for("twitter.index") )
def oauth(self): code = self.field("code") error = self.field("error") appier.verify( not error, message = "Invalid OAuth response (%s)" % error, exception = appier.OperationalError ) api = self.get_api() access_token = api.oauth_access(code) self.session["gh.access_token"] = access_token return self.redirect( self.url_for("github.index") )
def retrieve(self, name): # ensures proper authentication for the retrieval of # the package contents self.ensure_auth() # tries to retrieve the optional version and tag fields # that if present will add an extra level of filtering version = self.field("version") branch = self.field("branch") tag = self.field("tag") # tries to retrieve the value of the current artifact # it can be either a local file tuple or remote URL result = repos.Artifact.retrieve( name = name, version = version, branch = branch, tag = tag ) # in case the resulting value is a string it's assumed # that it should be an URL and proper redirect is ensured if appier.legacy.is_string(result): return self.redirect(result) # otherwise the result should be a tuple and we must unpack # it to check for proper contents data, file_name, content_type = result appier.verify( not data == None, message = "No data available in the package", exception = appier.OperationalError ) content_type = content_type or "application/octet-stream" return self.send_file( data, name = file_name, content_type = content_type )
def issue_reference_s(self, easypay, force = False): self.logger.debug("Generating reference for order '%s'" % self.s_name) appier.verify( not hasattr(self, "entity") or not self.entity or force, message = "There's an entity already set" ) appier.verify( not hasattr(self, "reference") or not self.reference or force, message = "There's a reference already set" ) appier.verify( not hasattr(self, "reference_id") or not self.reference_id or force, message = "There's a reference ID already set" ) amount = float(self.s_total_price) reference = easypay.generate_mb(amount) self.entity = reference["entity"] self.reference = reference["reference"] self.reference_id = reference["identifier"] self.payment = Order.ISSUED self.save() self.logger.debug("Issued reference for order '%s'" % self.s_name)
def verify_g(cls, identifier, key, app=None): entity = cls.get(identifier=identifier, app=app) appier.verify(entity.key == key, message="Missmatch in key")
def verify_refresh(self, refresh_token, grant_type = "refresh_token"): appier.verify(not self.refresh_token == None) appier.verify(not self.refresh_token == None) appier.verify(self.refresh_token == refresh_token) appier.verify(grant_type, "refresh_token")
def assert_redirect_uri(self, redirect_uri): appier.verify(redirect_uri == self.redirect_uri, message="The provided redirect URI is not valid", exception=appier.SecurityError, code=403)
def ensure_valid(self): appier.verify(self.is_valid())
def _contentful_value(self, key, include=10, default=None, verify=False, *args, **kwargs): # retrieves the reference to the parent class value to be used # to access class level methods cls = self.__class__ # runs a series of assertions for the provided key, raising exceptions # in case one of the pre-conditions is not met appier.verify( "." in key, message="Malformed key '%s', must include both content type and key" % key, code=400) # splits the provided key around the dot value (namespace oriented) # to obtain the content type and the field id content_type, field_id = key.split(".", 1) # retrieves the complete set of items that meet the content type # criteria and selects the first one, default to an empty dictionary # in case no items exist for such content type try: entries = self.contentful_api.list_entries( content_type=content_type, include=include, *args, ** kwargs) or dict() except Exception as exception: self.logger.warning("Problem while accessing Contentful: %s" % exception) return default # retrieves the complete set of items and in case there's at least # one returns the first one of it otherwise returns an empty dictionary items = entries.get("items", []) item = items[0] if items else dict() # retrieves the complete set of field for the item and tries to retrieve # the requested field (by its identifier) field = item.get("fields", {}) # verifies if the requested field exists raising an exception otherwise # this should ensure that the value exists in contentful if verify: appier.verify(field_id in field, message="'%s' not found" % field_id, exception=appier.NotFoundError) # retrieves the value of the field requested with the provided identifier # defaulting to the provided default value in case it does not exists field_value = field.get(field_id, default) # tries to determine if the value of the field is a link one (wither # a dictionary or a list) if that's not the case returns immediately is_link = isinstance(field_value, (dict, list, tuple)) if not is_link: return field_value # determines if the provided field value is a sequence or a dictionary # and converts the the value from the link accordingly is_sequence = isinstance(field_value, (list, tuple)) if is_sequence: field_value = [ cls._contentful_deref(entry, entries) for entry in field_value ] else: field_value = cls._contentful_deref(field_value, entries) # returns the final dereferenced value to the caller method # this can be both a plain value or a sequence return field_value
def shopify_url(self, absolute = False): shopify_store = appier.conf("SHOPIFY_STORE", None) appier.verify(shopify_store) return "https://%s/admin/orders/%d" % (shopify_store, self.s_id)
def _prismic_objects( self, key, limit = 10, default = [], verify = False, *args, **kwargs ): # retrieves the reference to the parent class value to be used # to access class level methods cls = self.__class__ # runs a series of assertions for the provided key, raising exceptions # in case one of the pre-conditions is not met appier.verify( not "." in key, message = "Malformed key '%s', must include both document type and key" % key, code = 400 ) # filters the keyword arguments based arguments retrieving only the valid # parameters to be used in the filters extension process params = cls._filter_params(kwargs) # sets the document type value as the provided key as we're trying # to retrieve an object instead of a field document_type = key # retrieves the complete set of items that meet the document type # criteria and selects the first one, default to an empty dictionary # in case no items exist for such content type try: query = ["[[at(document.type,\"%s\")]]" % document_type] query.extend(["[[at(my.%s.%s,\"%s\")]]" % (document_type, key, value) for\ key, value in appier.legacy.iteritems(params)]) entries = self.prismic_api.search_documents( q = query, page_size = limit, *args, **kwargs ) or [] except Exception as exception: self.logger.warning("Problem while accessing prismic: %s" % exception) return default # creates the list that is going to hold the multiple entry # maps/objects that are going to store the dereferenced # prismic entries (after the filtering) entries_m = [] # iterates over the complete set of entries, to be able to # creates the map/object with the dereferenced values for entry in entries: # creates the entry object/map that is going to be # populated with the complete set of dereferenced fields entry_m = dict() # retrieves the data part of the entry and the # field itself according to the document type data = entry.get("data", {}) field = data.get(document_type, {}) # iterates over the complete set of fields identifiers # and values and dereferences the values setting them # then in the current entry map/object for field_id, field_value in appier.legacy.iteritems(field): field_value = cls._prismic_deref(field_value) entry_m[field_id] = field_value # adds the entry map/object to the current list of entries, # this list should represent a simplified structure entries_m.append(entry_m) # returns the final processed list of entry objects with # the complete set of dereferenced values return entries_m
def _contentful_value( self, key, include = 10, default = None, verify = False, *args, **kwargs ): # retrieves the reference to the parent class value to be used # to access class level methods cls = self.__class__ # runs a series of assertions for the provided key, raising exceptions # in case one of the pre-conditions is not met appier.verify( "." in key, message = "Malformed key '%s', must include both content type and key" % key, code = 400 ) # splits the provided key around the dot value (namespace oriented) # to obtain the content type and the field id content_type, field_id = key.split(".", 1) # retrieves the complete set of items that meet the content type # criteria and selects the first one, default to an empty dictionary # in case no items exist for such content type try: entries = self.contentful_api.list_entries( content_type = content_type, include = include, *args, **kwargs ) or dict() except Exception as exception: self.logger.warning("Problem while accessing Contentful: %s" % exception) return default # retrieves the complete set of items and in case there's at least # one returns the first one of it otherwise returns an empty dictionary items = entries.get("items", []) item = items[0] if items else dict() # retrieves the complete set of field for the item and tries to retrieve # the requested field (by its identifier) field = item.get("fields", {}) # verifies if the requested field exists raising an exception otherwise # this should ensure that the value exists in contentful if verify: appier.verify( field_id in field, message = "'%s' not found" % field_id, exception = appier.NotFoundError ) # retrieves the value of the field requested with the provided identifier # defaulting to the provided default value in case it does not exists field_value = field.get(field_id, default) # tries to determine if the value of the field is a link one (wither # a dictionary or a list) if that's not the case returns immediately is_link = isinstance(field_value, (dict, list, tuple)) if not is_link: return field_value # determines if the provided field value is a sequence or a dictionary # and converts the the value from the link accordingly is_sequence = isinstance(field_value, (list, tuple)) if is_sequence: field_value = [ cls._contentful_deref(entry, entries) for entry in field_value ] else: field_value = cls._contentful_deref(field_value, entries) # returns the final dereferenced value to the caller method # this can be both a plain value or a sequence return field_value
def ensure_views(cls, object, ensure_set = True, views = None, owner = None): # tries to retrieve the reference to the owner of the current # context or uses the global one otherwise (fallback) owner = owner or appier.get_app() # in case no views are explicitly provided via parameter, then # the views must be retrieved from the current session if views == None: # verifies if there are any views defined under the current # session if that's not the case returns immediately as there's # nothing left to be filtered, otherwise retrieves the views to # be used to filter the current object context if not "views" in owner.session: return object views = owner.session["views"] # iterates over the complete set of views defined under the current # session to be able to update the object accordingly, validating # the context of resolution of that object (less results) for view in views: # resolves the current view, obtaining the proper map # object, ready to be used in the update process view = cls._resolve_view(view, resolve_name = "view_l") # in case there's no view (invalid value) then continues # the loop as no validation needed for the object if not view: continue # iterates over the complete set of views elements to # make sure the associated model attributes are defined # accordingly raising exceptions otherwise for name, values in appier.legacy.iteritems(view): # in case the element is not required to be set # at the object and it's not set the skips the # current iteration loop no verification needed if not ensure_set and not name in object: continue appier.verify( name in object, message = "Attribute '%s' not set in object" % name, exception = appier.SecurityError ) # in case the defined value for the view attribute is not # a sequence converts it to be able to run normalized operations if not isinstance(values, (list, tuple)): values = [values] # computes the proper error message that is going to be sent # as part of the security error to be raised if appier.is_devel(): message = "Attribute '%s' ('%s') not valid according to view ('%s')" %\ (name, str(object[name]), str(values)) # in case the production mode is enable the message is defined # as a simpler one, avoiding confidential data leak else: message = "Attribute '%s' not valid according to view" % name # runs the verify operation that will raise a security error # in case the attribute is not valid according to the view appier.verify( object[name] in values, message = message, exception = appier.SecurityError )
def _verify_scope(self): scope_s = set(self.scope) appier.verify(len(self.scope) == len(scope_s))
def update_meta_s(self, meta = None, **kwargs): meta = kwargs if meta == None else meta appier.verify(isinstance(meta, dict)) if not self.meta: self.meta = meta else: self.meta.update(meta) self.save()
def update_meta_s(self, meta=None, **kwargs): meta = kwargs if meta == None else meta appier.verify(isinstance(meta, dict)) if not self.meta: self.meta = meta else: self.meta.update(meta) self.save()
def _prismic_value( self, key, limit = 1, default = None, verify = False, *args, **kwargs ): # retrieves the reference to the parent class value to be used # to access class level methods cls = self.__class__ # runs a series of assertions for the provided key, raising exceptions # in case one of the pre-conditions is not met appier.verify( "." in key, message = "Malformed key '%s', must include both document type and key" % key, code = 400 ) # filters the keyword arguments based arguments retrieving only the valid # parameters to be used in the filters extension process params = cls._filter_params(kwargs) # splits the provided key around the dot value (namespace oriented) # to obtain the document type and the field id document_type, field_id = key.split(".", 1) # retrieves the complete set of items that meet the document type # criteria and selects the first one, default to an empty dictionary # in case no items exist for such content type try: query = ["[[at(document.type,\"%s\")]]" % document_type] query.extend(["[[at(my.%s.%s,\"%s\")]]" % (document_type, key, value) for\ key, value in appier.legacy.iteritems(params)]) entries = self.prismic_api.search_documents( q = query, page_size = limit, *args, **kwargs ) or [] except Exception as exception: self.logger.warning("Problem while accessing prismic: %s" % exception) return default # retrieves the complete set of items and in case there's at least # one returns the first one of it otherwise returns an empty dictionary entry = entries[0] if entries else dict() # retrieves the complete set of field for the entry and tries to retrieve # the requested field (by its identifier) data = entry.get("data", {}) field = data.get(document_type, {}) # verifies if the requested field exists raising an exception otherwise # this should ensure that the value exists in prismic if verify: appier.verify( field_id in field, message = "'%s' not found" % field_id, exception = appier.NotFoundError ) # retrieves the value of the field requested with the provided identifier # defaulting to the provided default value in case it does not exists field_value = field.get(field_id, default) # runs the dereferencing process for the field value that is going to # be retrieved so the proper (expected) value may be returned to caller field_value = cls._prismic_deref(field_value) # returns the final dereferenced value to the caller method # this can be both a plain value or a sequence return field_value
def pre_save(self): base.PushiBase.pre_save(self) appier.verify(not "mid" in self.data) appier.verify(not "timestamp" in self.data)