Skip to content

Commit

Permalink
Next Minor (#550)
Browse files Browse the repository at this point in the history
* added new config helper function

* flake8

* added docstrings

* flake8

* removed need for config prefix

* Add in container (#520)

* added contains method to container

* formatted and added tests

* bumped version

* Add ability to login using multiple columns (#521)

* add list to auth class

* adds ability to set a password column

* formatted

* fixed space in exception

* Adds route redirection (#545)

* adds a new redirect route class

* flake8

* fixes issue where a json null could throw an exception (#544)

* added ability to set status code in controller (#540)

* added ability to set status code in controller

* flake8

* added better exception when passing incorrect parameter type (#539)

* added better exception when passing incorrect parameter type

* fixed view test

* fix delete method when body length is 0 (#529)

* fix docstring for secure headers middleware (#548)

* bumped version
  • Loading branch information
josephmancuso committed Jan 27, 2019
1 parent 76a43dc commit 91afa01
Show file tree
Hide file tree
Showing 15 changed files with 107 additions and 28 deletions.
4 changes: 4 additions & 0 deletions app/http/controllers/TestController.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ def change_header(self, request: Request):
request.header('Content-Type', 'application/xml')
return 'test'

def change_status(self, request: Request):
request.status(203)
return 'test'

def testing(self):
return 'test'

Expand Down
12 changes: 6 additions & 6 deletions masonite/auth/Auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ def login(self, name, password):
"""
auth_column = self.auth_model.__auth__

try:
password_column = self.auth_model.password if hasattr(self.auth_model, 'password') else self.auth_model.__password__
except AttributeError as e:
raise AttributeError('Your model does not have a password column or a designated __password__ attribute. Set the __password__ attribute to the name of your password column.') from e

try:
# Try to login multiple or statements if given an auth list
if isinstance(auth_column, list):
Expand All @@ -75,12 +80,7 @@ def login(self, name, password):
else:
model = self.auth_model.where(auth_column, name).first()

# try:
# password_column = self._get_password_value(model)
# except AttributeError as e:
# raise AttributeError('Your model does not have a password column or a designated __password__ attribute. Set the __password__ attribute to the name of your password column.') from e

if model and bcrypt.checkpw(bytes(password, 'utf-8'), bytes(model.password, 'utf-8')):
if model and bcrypt.checkpw(bytes(password, 'utf-8'), bytes(password_column, 'utf-8')):
if not self._once:
remember_token = str(uuid.uuid4())
model.remember_token = remember_token
Expand Down
4 changes: 4 additions & 0 deletions masonite/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,7 @@ class DebugException(Exception):

class DumpException(Exception):
pass


class ViewException(Exception):
pass
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.12'
VERSION = '2.1.13'
3 changes: 3 additions & 0 deletions masonite/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ def _get_standardized_value(self, value):
Returns:
string|bool
"""
if value is None:
return None

if isinstance(value, list):

# If the list contains MiniFieldStorage objects then loop through and get the values.
Expand Down
3 changes: 2 additions & 1 deletion masonite/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ def view(self, view, status=200):
Returns:
string|dict|list -- Returns the data to be returned.
"""
self.request.status(status)
if self.request.get_status() in (404,):
self.request.status(status)

if isinstance(view, dict) or isinstance(view, list):
return self.json(view)
Expand Down
26 changes: 25 additions & 1 deletion masonite/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def set_post_params(self):
if isinstance(request_body, bytes):
request_body = request_body.decode('utf-8')

return json.loads(request_body)
return json.loads(request_body or '{}')
else:
fields = cgi.FieldStorage(
fp=self.environ['wsgi.input'], environ=self.environ, keep_blank_values=1)
Expand Down Expand Up @@ -439,6 +439,30 @@ def get_response(self):
return self.request.app().make('ViewClass').render(self.template, self.dictionary).rendered_template


class Redirect(BaseHttpRoute):

def __init__(self, current_route, future_route, status=302, methods=['GET']):
"""Class used for view routes.
This class should be returned when a view is called on an HTTP route.
This is useful when returning a view that doesn't need any special logic and only needs a dictionary.
Arguments:
method_type {string} -- The method type (GET, POST, PUT etc)
route {string} -- The current route (/test/url)
template {string} -- The template to use (dashboard/user)
dictionary {dict} -- The dictionary to use to render the template.
"""
self.list_middleware = []
self.method_type = methods
self.route_url = current_route
self.status = status
self.future_route = future_route

def get_response(self):
return self.request.redirect(self.future_route, status=self.status)


class RouteGroup():
"""Class for specifying Route Groups."""

Expand Down
4 changes: 3 additions & 1 deletion masonite/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from jinja2 import ChoiceLoader, Environment, PackageLoader, select_autoescape
from jinja2.exceptions import TemplateNotFound

from masonite.exceptions import RequiredContainerBindingNotFound
from masonite.exceptions import RequiredContainerBindingNotFound, ViewException


class View:
Expand Down Expand Up @@ -49,6 +49,8 @@ def render(self, template, dictionary={}):
Returns:
self
"""
if not isinstance(dictionary, dict):
raise ViewException('Second parameter to render method needs to be a dictionary, {} passed.'.format(type(dictionary).__name__))
self.__load_environment(template)
self.dictionary = {}

Expand Down
3 changes: 2 additions & 1 deletion routes/web.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
""" Web Routes """
from masonite.helpers.routes import group
from masonite.routes import Get, Post
from masonite.routes import Get, Post, Redirect


ROUTES = [
Get().route('/test', None).middleware('auth'),
Redirect('/redirect', 'test'),
Get().domain('test').route('/test', None).middleware('auth'),
Get().domain('test').route('/unit/test', 'TestController@testing').middleware('auth'),
Get().domain('test').route('/test/route', 'TestController@testing'),
Expand Down
2 changes: 1 addition & 1 deletion tests/middleware/test_secure_headers_middleware.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
""" Test Maintenance Mode Midddleware """
""" Test Secure Headers Midddleware """
import os

from masonite.app import App
Expand Down
14 changes: 0 additions & 14 deletions tests/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,20 +77,6 @@ def test_login_user_with_list_auth_column(self):
assert isinstance(self.auth.login('testuser123', 'secret'), user)
assert self.request.get_cookie('token')

def test_auth_gets_user_login_attribute(self):
auth = Auth(self.request, ListUser())
assert auth._get_password_value(ListUser()) == 'pass123'

auth = Auth(self.request, MockUser())
assert auth._get_password_value(MockUser()) == '$2a$04$SXAMKoNuuiv7iO4g4U3ZOemyJJiKAHomUIFfGyH4hyo4LrLjcMqvS'

def test_auth_gets_user_login_attribute_column(self):
auth = Auth(self.request, ListUser())
assert auth._get_password_column(ListUser()) == 'users_password'

auth = Auth(self.request, MockUser())
assert auth._get_password_column(MockUser()) == 'password'

def test_get_user(self):
assert self.auth.login_by_id(1)
assert isinstance(self.auth.user(), MockUser)
Expand Down
16 changes: 16 additions & 0 deletions tests/test_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,22 @@ def test_redirect_compiles_url_with_http(self):
route = "http://google.com"

assert request.compile_route_to_url(route) == 'http://google.com'

def test_can_get_nully_value(self):
app = App()
app.bind('Request', self.request)
request = app.make('Request').load_app(app)

request._set_standardized_request_variables({
"gateway": "RENDIMENTO",
"request": {
"user": "data"
},
"response": None,
"description": "test only"
})

assert request.input('response') == None

def test_request_gets_correct_header(self):
app = App()
Expand Down
6 changes: 6 additions & 0 deletions tests/test_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ def setup_method(self):
self.app = App()
self.request = Request(generate_wsgi()).load_app(self.app)
self.app.bind('Request', self.request)
self.app.bind('StatusCode', '404 Not Found')
self.response = Response(self.app)

def test_can_set_json(self):
Expand Down Expand Up @@ -48,3 +49,8 @@ def test_view_can_return_integer_as_string(self):

assert self.app.make('Response') == '1'
assert self.request.is_status(200)

def test_view_can_set_own_status_code(self):

self.response.view(self.app.resolve(ControllerTest().change_status))
assert self.request.is_status(203)
29 changes: 28 additions & 1 deletion tests/test_routes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from masonite.routes import Route
from masonite.request import Request
from masonite.routes import Get, Post, Put, Patch, Delete, RouteGroup, Match
from masonite.app import App
from masonite.routes import Get, Post, Put, Patch, Delete, RouteGroup, Match, Redirect
from masonite.helpers.routes import group, flatten_routes
from masonite.testsuite.TestSuite import generate_wsgi
from masonite.exceptions import InvalidRouteCompileException, RouteException
Expand Down Expand Up @@ -188,6 +189,32 @@ def test_correctly_parses_json_with_list(self):
assert route.environ['QUERY_STRING'] == {
"options": ["foo", "bar"]
}

def test_redirect_route(self):
route = Redirect('/test1', '/test2')
request = Request(generate_wsgi())
route.load_request(request)
request.load_app(App())

route.get_response()
assert request.is_status(302)
assert request.redirect_url == '/test2'

def test_redirect_can_use_301(self):
request = Request(generate_wsgi())
route = Redirect('/test1', '/test3', status=301)

route.load_request(request)
request.load_app(App())
route.get_response()
assert request.is_status(301)
assert request.redirect_url == '/test3'

def test_redirect_can_change_method_type(self):
request = Request(generate_wsgi())
route = Redirect('/test1', '/test3', methods=['POST', 'PUT'])
assert route.method_type == ['POST', 'PUT']


class WsgiInputTestClass:

Expand Down
7 changes: 6 additions & 1 deletion tests/test_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from config import cache
from masonite.app import App
from masonite.drivers.CacheDiskDriver import CacheDiskDriver
from masonite.exceptions import RequiredContainerBindingNotFound
from masonite.exceptions import RequiredContainerBindingNotFound, ViewException
from masonite.managers.CacheManager import CacheManager
from masonite.view import View

Expand Down Expand Up @@ -283,6 +283,11 @@ def test_can_render_pubjs(self):
assert view.render(
'pug/hello.pug', {'name': 'Joe'}).rendered_template == '<p>hello Joe</p>'

def test_throws_exception_on_incorrect_type(self):
view = self.container.make('ViewClass')
with pytest.raises(ViewException):
assert view.render('test', {'', ''})


class MockAdminUser:
admin = 1

0 comments on commit 91afa01

Please sign in to comment.