Skip to content

Commit

Permalink
Merge pull request #640 from MasoniteFramework/master
Browse files Browse the repository at this point in the history
Next Minor
  • Loading branch information
josephmancuso authored Mar 24, 2019
2 parents c54d63a + e723e09 commit faa36f8
Show file tree
Hide file tree
Showing 20 changed files with 179 additions and 47 deletions.
13 changes: 11 additions & 2 deletions config/middleware.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
""" Middleware Configuration Settings """

from masonite.middleware import ResponseMiddleware, SecureHeadersMiddleware
from masonite.middleware import ResponseMiddleware, SecureHeadersMiddleware, CorsMiddleware

from app.http.middleware.AddAttributeMiddleware import AddAttributeMiddleware
from app.http.middleware.AuthenticationMiddleware import AuthenticationMiddleware
Expand All @@ -24,6 +23,7 @@
LoadUserMiddleware,
# todo
# CsrfMiddleware,
CorsMiddleware,
ResponseMiddleware,
SecureHeadersMiddleware,
]
Expand All @@ -46,6 +46,7 @@
ROUTE_MIDDLEWARE = {
'auth': AuthenticationMiddleware,
'test': MiddlewareTest,
'cors': CorsMiddleware,
'middleware.test': [
MiddlewareTest,
AddAttributeMiddleware,
Expand All @@ -63,3 +64,11 @@
'Cache-control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache',
}

CORS = {
'Access-Control-Allow-Origin': "*",
"Access-Control-Allow-Methods": "DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT",
"Access-Control-Allow-Headers": "Content-Type, Accept, X-Requested-With",
"Access-Control-Max-Age": "3600",
"Access-Control-Allow-Credentials": "true"
}
4 changes: 3 additions & 1 deletion masonite/commands/BaseScaffoldCommand.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ class BaseScaffoldCommand(Command):

scaffold_name = 'Example'
suffix = ''
postfix = ''
file_extension = '.py'
base_directory = 'app/example/'

template = '/masonite/snippets/scaffold/model'

def handle(self):
class_name = self.argument('name')
class_name = self.argument('name') + self.postfix
view = View(App())
class_directory = '{}{}{}{}'.format(
self.base_directory, class_name, self.suffix, self.file_extension)
Expand Down
1 change: 1 addition & 0 deletions masonite/commands/CommandCommand.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ class CommandCommand(BaseScaffoldCommand):
"""

scaffold_name = 'Command'
postfix = "Command"
template = '/masonite/snippets/scaffold/command'
base_directory = 'app/commands/'
2 changes: 1 addition & 1 deletion masonite/helpers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .static import static
from .password import password
from .validator import validate
from .misc import random_string, dot, clean_request_input, HasColoredCommands, Compact as compact
from .misc import random_string, dot, clean_request_input, HasColoredCommands, Compact as compact, deprecated
from .Extendable import Extendable
from .time import cookie_expire_time
from .optional import Optional as optional
Expand Down
14 changes: 14 additions & 0 deletions masonite/helpers/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import random
import string
import warnings

from masonite.exceptions import AmbiguousError


Expand Down Expand Up @@ -96,3 +98,15 @@ def __new__(self, *args):
if len(args) != len(self.dictionary):
raise ValueError('Could not find all variables in this')
return self.dictionary


def deprecated(message):
def deprecated_decorator(func):
def deprecated_func(*args, **kwargs):
warnings.warn("{} is a deprecated function. {}".format(func.__name__, message),
category=DeprecationWarning,
stacklevel=2)
warnings.simplefilter('default', DeprecationWarning)
return func(*args, **kwargs)
return deprecated_func
return deprecated_decorator
11 changes: 11 additions & 0 deletions masonite/helpers/routes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Helper Functions for RouteProvider."""

import re
from masonite.helpers import deprecated


def flatten_routes(routes):
Expand All @@ -24,6 +25,10 @@ def flatten_routes(routes):
return route_collection


DEPRECATION_STRING = " Please use the class based version of the route. Please visit {} for more information".format('https://docs.masoniteproject.com/prologue/deprecation#helper-functions')


@deprecated("The 'get' route helper is deprecated. {}".format(DEPRECATION_STRING))
def get(url, controller):
"""Shortcut for Get HTTP class.
Expand All @@ -39,6 +44,7 @@ def get(url, controller):
return Get().route(url, controller)


@deprecated("The 'match' route helper is deprecated. {}".format(DEPRECATION_STRING))
def match(method_type, url, controller):
"""Shortcut for Match HTTP class.
Expand All @@ -55,6 +61,7 @@ def match(method_type, url, controller):
return Match(method_type).route(url, controller)


@deprecated("The 'post' route helper is deprecated. {}".format(DEPRECATION_STRING))
def post(url, controller):
"""Shortcut for Post HTTP class.
Expand All @@ -70,6 +77,7 @@ def post(url, controller):
return Post().route(url, controller)


@deprecated("The 'delete' route helper is deprecated. {}".format(DEPRECATION_STRING))
def delete(url, controller):
"""Shortcut for Delete HTTP class.
Expand All @@ -85,6 +93,7 @@ def delete(url, controller):
return Delete().route(url, controller)


@deprecated("The 'put' route helper is deprecated. {}".format(DEPRECATION_STRING))
def put(url, controller):
"""Shortcut for Put HTTP class.
Expand All @@ -100,6 +109,7 @@ def put(url, controller):
return Put().route(url, controller)


@deprecated("The 'patch' route helper is deprecated. {}".format(DEPRECATION_STRING))
def patch(url, controller):
"""Shortcut for Patch HTTP class.
Expand All @@ -115,6 +125,7 @@ def patch(url, controller):
return Patch().route(url, controller)


@deprecated("The 'group' route helper is deprecated. {}".format(DEPRECATION_STRING))
def group(url, route_list):
"""Shortcut for GET HTTP class.
Expand Down
54 changes: 33 additions & 21 deletions masonite/helpers/structures.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
"""A Module For Manipulating Code Structures."""

import pydoc
import inspect


class Dot:

def dot(self, search, dictionary):
def dot(self, search, dictionary, default=None):
"""The search string in dot notation to look into the dictionary for.
Arguments:
search {string} -- This should be a string in dot notation like 'key.key.value'.
dictionary {dict} -- A normal dictionary which will be searched using the search string in dot notation.
Keyword Arguments:
default {string} -- The default value if nothing is found in the dictionary. (default: {None})
Returns:
string -- Returns the value found the dictionary or the default value specified above if nothing is found.
"""
if '.' not in search:
if search == '':
return dictionary
# print('search', search, 'dictionary', dictionary)
return dictionary[search]

searching = search.split('.')
while len(searching) > 0:
dic = dictionary
for search in searching:
if not dic:
return default
dic = dic.get(search)

if not isinstance(dic, dict):
Expand All @@ -36,12 +53,14 @@ def locate(self, search_path, default=''):
value = self.find(search_path, default)

if isinstance(value, dict):
return self.dict_dot('.'.join(search_path.split('.')[3:]), value)
return self.dict_dot('.'.join(search_path.split('.')[3:]), value, default)

if value is not None:
return value

def dict_dot(self, search, dictionary):
return default

def dict_dot(self, search, dictionary, default):
"""Takes a dot notation representation of a dictionary and fetches it from the dictionary.
This will take something like s3.locations and look into the s3 dictionary and fetch the locations
Expand All @@ -54,19 +73,7 @@ def dict_dot(self, search, dictionary):
Returns:
string -- The value of the dictionary element.
"""
if "." in search:
key, rest = search.split(".", 1)
try:
return self.dict_dot(dictionary[key], rest)
except (KeyError, TypeError):
pass
else:
try:
return dictionary[search]
except TypeError:
pass

return self.dict_dot(dictionary, search)
return self.dot(search, dictionary, default)

def find(self, search_path, default=''):
"""Used for finding both the uppercase and specified version.
Expand Down Expand Up @@ -96,8 +103,12 @@ def find(self, search_path, default=''):
search_path = -1

# Go backwards through the dot notation until a match is found.
while search_path < len(paths):
value = pydoc.locate('.'.join(paths[:search_path]) + '.' + paths[search_path].upper())
ran = 0
while ran < len(paths):
try:
value = pydoc.locate('.'.join(paths[:search_path]) + '.' + paths[search_path].upper())
except IndexError:
return default

if value:
break
Expand All @@ -107,10 +118,11 @@ def find(self, search_path, default=''):
if value:
break

if default:
return default

search_path -= 1
ran += 1

if not value or inspect.ismodule(value):
return default

return value

Expand Down
2 changes: 1 addition & 1 deletion masonite/info.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Module for specifying the Masonite version in a central location."""

VERSION = '2.1.22'
VERSION = '2.1.23'
27 changes: 27 additions & 0 deletions masonite/middleware/CorsMiddleware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
""" CORS Middleware """

from masonite import env
from masonite.helpers import config
from masonite.request import Request


class CorsMiddleware:
"""Appends CORS headers to HTTP response
Put any CORS middleware you need as a CORS dictionary inside your
middleware config file.
"""

def __init__(self, request: Request):
"""Inject Any Dependencies From The Service Container
Arguments:
Request {masonite.request.Request} -- The Masonite request object
"""
self.request = request

def after(self):
"""Run This Middleware After The Route Executes
"""
headers = config('middleware.cors') or {}
self.request.header(headers)
1 change: 1 addition & 0 deletions masonite/middleware/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .CsrfMiddleware import CsrfMiddleware
from .CorsMiddleware import CorsMiddleware
from .MaintenanceModeMiddleware import MaintenanceModeMiddleware
from .ResponseMiddleware import ResponseMiddleware
from .SecureHeadersMiddleware import SecureHeadersMiddleware
11 changes: 8 additions & 3 deletions masonite/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

from config import application
from masonite.auth.Sign import Sign
from masonite.exceptions import InvalidHTTPStatusCode
from masonite.exceptions import InvalidHTTPStatusCode, RouteException
from masonite.helpers import dot, clean_request_input, Dot as DictDot
from masonite.helpers.Extendable import Extendable
from masonite.helpers.routes import compile_route_to_regex
Expand Down Expand Up @@ -712,9 +712,14 @@ def route(self, name, params={}, full=False):
masonite.routes.Route|None -- Returns None if the route cannot be found.
"""
if full:
return application.URL + self._get_named_route(name, params)
route = application.URL + self._get_named_route(name, params)
else:
route = self._get_named_route(name, params)

if not route:
raise RouteException("Route with the name of '{}' was not found.".format(name))

return self._get_named_route(name, params)
return route

def reset_redirections(self):
"""Reset the redirections because of this class acting like a singleton pattern."""
Expand Down
17 changes: 13 additions & 4 deletions masonite/snippets/scaffold/controller.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
""" A {{ class }} Module """
"""A {{ class }} Module."""

from masonite.request import Request
from masonite.view import View

class {{ class }}:
"""{{ class }}
"""
"""{{ class }} Controller Class."""

def __init__(self, request: Request):
"""{{ class }} Initializer

Arguments:
request {masonite.request.Request} -- The Masonite Request class.
"""
self.request = request

def show(self):
def show(self, view: View):
pass
6 changes: 4 additions & 2 deletions masonite/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,8 @@ def __load_environment(self, template):
self.env = Environment(
loader=loader,
autoescape=select_autoescape(['html', 'xml']),
extensions=self._jinja_extensions
extensions=self._jinja_extensions,
line_statement_prefix='@'
)

else:
Expand All @@ -253,7 +254,8 @@ def __load_environment(self, template):
self.env = Environment(
loader=loader,
autoescape=select_autoescape(['html', 'xml']),
extensions=self._jinja_extensions
extensions=self._jinja_extensions,
line_statement_prefix='@'
)

self.env.filters.update(self._filters)
Expand Down
3 changes: 3 additions & 0 deletions resources/templates/line-statements.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@if test:
{{ test }}
@endif
8 changes: 7 additions & 1 deletion tests/helpers/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@ def test_config_can_get_dict_value_lowercase(self):
def test_config_can_get_dict_default(self):
assert self.config('sdff.na', 'default') == 'default'

def test_config_not_found_returns_default(self):
assert self.config('application.nothere', 'default') == 'default'

def test_dict_dot_returns_value(self):
assert Dot().dict_dot('s3.test', {'s3': {'test': 'value'}}) == 'value'
assert Dot().dict_dot('s3.test', {'s3': {'test': 'value'}}, '') == 'value'

def test_config_can_get_dict_value_inside_dict(self):
assert self.config('database.DATABASES.default') == database.DATABASES['default']
Expand All @@ -32,3 +35,6 @@ def test_config_can_get_dict_inside_dict_inside_dict(self):

def test_config_can_get_dict_inside_dict_inside_another_dict(self):
assert self.config('storage.DRIVERS.s3.test_locations.test') == 'value'

def test_dot_dict(self):
assert Dot().dict_dot('async.driver', {'async': {'driver': 'me'}}, 'you') == 'me'
Loading

0 comments on commit faa36f8

Please sign in to comment.