From ac1ac272e971e1300760e6fdcb7f8bf1c44f9c27 Mon Sep 17 00:00:00 2001 From: Joseph Mancuso Date: Thu, 23 Aug 2018 22:16:16 -0400 Subject: [PATCH 01/17] added manager contracts --- masonite/app.py | 4 ++-- masonite/contracts/__init__.py | 9 ++++++++- .../contracts/managers/BroadcastManagerContract.py | 5 +++++ .../contracts/managers/CacheManagerContract.py | 5 +++++ masonite/contracts/managers/MailManagerContract.py | 5 +++++ .../contracts/managers/QueueManagerContract.py | 5 +++++ .../contracts/managers/SessionManagerContract.py | 5 +++++ .../contracts/managers/UploadManagerContract.py | 5 +++++ masonite/managers/BroadcastManager.py | 3 ++- masonite/managers/CacheManager.py | 5 +++-- masonite/managers/MailManager.py | 5 +++-- masonite/managers/QueueManager.py | 5 +++-- masonite/managers/SessionManager.py | 5 +++-- masonite/managers/UploadManager.py | 3 ++- tests/test_managers_mail_manager.py | 14 +++++++++++--- 15 files changed, 67 insertions(+), 16 deletions(-) create mode 100644 masonite/contracts/managers/BroadcastManagerContract.py create mode 100644 masonite/contracts/managers/CacheManagerContract.py create mode 100644 masonite/contracts/managers/MailManagerContract.py create mode 100644 masonite/contracts/managers/QueueManagerContract.py create mode 100644 masonite/contracts/managers/SessionManagerContract.py create mode 100644 masonite/contracts/managers/UploadManagerContract.py diff --git a/masonite/app.py b/masonite/app.py index 3fac3bb17..04e715667 100644 --- a/masonite/app.py +++ b/masonite/app.py @@ -191,12 +191,12 @@ def _find_annotated_parameter(self, parameter): """ for dummy, provider_class in self.providers.items(): - + if parameter.annotation == provider_class or parameter.annotation == provider_class.__class__: obj = provider_class self.fire_hook('resolve', parameter, obj) return obj - elif inspect.isclass(provider_class) and issubclass(provider_class, parameter.annotation): + elif inspect.isclass(provider_class) and issubclass(provider_class, parameter.annotation) or issubclass(provider_class.__class__, parameter.annotation): obj = provider_class self.fire_hook('resolve', parameter, obj) return obj diff --git a/masonite/contracts/__init__.py b/masonite/contracts/__init__.py index 85b8fb13f..1a0fe6932 100644 --- a/masonite/contracts/__init__.py +++ b/masonite/contracts/__init__.py @@ -3,4 +3,11 @@ from .MailContract import MailContract from .QueueContract import QueueContract from .SessionContract import SessionContract -from .UploadContract import UploadContract \ No newline at end of file +from .UploadContract import UploadContract + +from .managers.BroadcastManagerContract import BroadcastManagerContract +from .managers.CacheManagerContract import CacheManagerContract +from .managers.MailManagerContract import MailManagerContract +from .managers.QueueManagerContract import QueueManagerContract +from .managers.SessionManagerContract import SessionManagerContract +from .managers.UploadManagerContract import UploadManagerContract diff --git a/masonite/contracts/managers/BroadcastManagerContract.py b/masonite/contracts/managers/BroadcastManagerContract.py new file mode 100644 index 000000000..0ffb517a3 --- /dev/null +++ b/masonite/contracts/managers/BroadcastManagerContract.py @@ -0,0 +1,5 @@ +from abc import ABC + + +class BroadcastManagerContract(ABC): + pass diff --git a/masonite/contracts/managers/CacheManagerContract.py b/masonite/contracts/managers/CacheManagerContract.py new file mode 100644 index 000000000..cea45a79f --- /dev/null +++ b/masonite/contracts/managers/CacheManagerContract.py @@ -0,0 +1,5 @@ +from abc import ABC + + +class CacheManagerContract(ABC): + pass diff --git a/masonite/contracts/managers/MailManagerContract.py b/masonite/contracts/managers/MailManagerContract.py new file mode 100644 index 000000000..89cc95f3e --- /dev/null +++ b/masonite/contracts/managers/MailManagerContract.py @@ -0,0 +1,5 @@ +from abc import ABC + + +class MailManagerContract(ABC): + pass diff --git a/masonite/contracts/managers/QueueManagerContract.py b/masonite/contracts/managers/QueueManagerContract.py new file mode 100644 index 000000000..73c04a23c --- /dev/null +++ b/masonite/contracts/managers/QueueManagerContract.py @@ -0,0 +1,5 @@ +from abc import ABC + + +class QueueManagerContract(ABC): + pass diff --git a/masonite/contracts/managers/SessionManagerContract.py b/masonite/contracts/managers/SessionManagerContract.py new file mode 100644 index 000000000..67dbb328e --- /dev/null +++ b/masonite/contracts/managers/SessionManagerContract.py @@ -0,0 +1,5 @@ +from abc import ABC + + +class SessionManagerContract(ABC): + pass diff --git a/masonite/contracts/managers/UploadManagerContract.py b/masonite/contracts/managers/UploadManagerContract.py new file mode 100644 index 000000000..f0620bfb5 --- /dev/null +++ b/masonite/contracts/managers/UploadManagerContract.py @@ -0,0 +1,5 @@ +from abc import ABC + + +class UploadManagerContract(ABC): + pass diff --git a/masonite/managers/BroadcastManager.py b/masonite/managers/BroadcastManager.py index 7ccfdc13a..8f0629474 100644 --- a/masonite/managers/BroadcastManager.py +++ b/masonite/managers/BroadcastManager.py @@ -1,9 +1,10 @@ """ Broadcast Manager Module """ +from masonite.contracts import BroadcastManagerContract from masonite.managers import Manager -class BroadcastManager(Manager): +class BroadcastManager(Manager, BroadcastManagerContract): """Manages all broadcast drivers. Arguments: diff --git a/masonite/managers/CacheManager.py b/masonite/managers/CacheManager.py index 5e480251a..f31d37df9 100644 --- a/masonite/managers/CacheManager.py +++ b/masonite/managers/CacheManager.py @@ -1,9 +1,10 @@ """ Cache Manager """ -from masonite.managers.Manager import Manager +from masonite.contracts import CacheManagerContract +from masonite.managers import Manager -class CacheManager(Manager): +class CacheManager(Manager, CacheManagerContract): """Manages all cache drivers. Arguments: diff --git a/masonite/managers/MailManager.py b/masonite/managers/MailManager.py index 380837980..87857c03f 100644 --- a/masonite/managers/MailManager.py +++ b/masonite/managers/MailManager.py @@ -1,9 +1,10 @@ """ Mail Manager Module """ -from masonite.managers.Manager import Manager +from masonite.contracts import MailManagerContract +from masonite.managers import Manager -class MailManager(Manager): +class MailManager(Manager, MailManagerContract): """Manages all mail drivers. Arguments: diff --git a/masonite/managers/QueueManager.py b/masonite/managers/QueueManager.py index f80f03626..aa40abe8e 100644 --- a/masonite/managers/QueueManager.py +++ b/masonite/managers/QueueManager.py @@ -1,9 +1,10 @@ """ Queue Manager Module """ -from masonite.managers.Manager import Manager +from masonite.contracts import QueueManagerContract +from masonite.managers import Manager -class QueueManager(Manager): +class QueueManager(Manager, QueueManagerContract): """Manages all queue drivers. Arguments: diff --git a/masonite/managers/SessionManager.py b/masonite/managers/SessionManager.py index 11ff222ea..0f0f495c9 100644 --- a/masonite/managers/SessionManager.py +++ b/masonite/managers/SessionManager.py @@ -1,9 +1,10 @@ """ Session Manager Module """ -from masonite.managers.Manager import Manager +from masonite.contracts import SessionManagerContract +from masonite.managers import Manager -class SessionManager(Manager): +class SessionManager(Manager, SessionManagerContract): """Manages all session drivers. Arguments: diff --git a/masonite/managers/UploadManager.py b/masonite/managers/UploadManager.py index bbc2d963e..da5fbe659 100644 --- a/masonite/managers/UploadManager.py +++ b/masonite/managers/UploadManager.py @@ -1,6 +1,7 @@ """ Upload Manager Module """ -from masonite.managers.Manager import Manager +from masonite.contracts import UploadManagerContract +from masonite.managers import Manager class UploadManager(Manager): diff --git a/tests/test_managers_mail_manager.py b/tests/test_managers_mail_manager.py index 3607eb9fc..835023f84 100644 --- a/tests/test_managers_mail_manager.py +++ b/tests/test_managers_mail_manager.py @@ -3,9 +3,10 @@ from masonite.app import App from masonite.exceptions import DriverNotFound -from masonite.managers.MailManager import MailManager -from masonite.drivers.MailSmtpDriver import MailSmtpDriver as MailDriver -from masonite.drivers.MailMailgunDriver import MailMailgunDriver as Mailgun +from masonite.managers import MailManager +from masonite.drivers import MailSmtpDriver as MailDriver +from masonite.drivers import MailMailgunDriver as Mailgun +from masonite.contracts import MailManagerContract from masonite.view import View @@ -34,6 +35,13 @@ def test_mail_manager_loads_container(self): mailManager = MailManager() assert mailManager.load_container(self.app) + def test_mail_manager_resolves_from_contract(self): + self.app.bind('MailManager', MailManager()) + assert self.app.resolve(self._test_resolve) == self.app.make('MailManager') + + def _test_resolve(self, mail: MailManagerContract): + return mail + def test_creates_driver(self): mailManager = MailManager() From e28c0e947cd7134203b666aa104eaf5c303616d6 Mon Sep 17 00:00:00 2001 From: Joseph Mancuso Date: Thu, 30 Aug 2018 00:25:52 -0400 Subject: [PATCH 02/17] bumped version --- masonite/info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/masonite/info.py b/masonite/info.py index d2714a406..8fe5dd15a 100644 --- a/masonite/info.py +++ b/masonite/info.py @@ -1,4 +1,4 @@ """Module for specifying the Masonite version in a central location. """ -VERSION = '2.0.16' +VERSION = '2.0.18' From 3c166ff5c545c81ebc68e934a52010d7b2412575 Mon Sep 17 00:00:00 2001 From: Tony Hammack Date: Sat, 1 Sep 2018 18:50:14 -0500 Subject: [PATCH 03/17] Raises InvalidSecretKey exception when the secret key has incorrect padding. The accompanying test is located in tests/test_signing.py --- masonite/auth/Sign.py | 15 +++++++++++---- .../facades/__pycache__/Auth.cpython-36.pyc | Bin 1687 -> 3364 bytes tests/test_signing.py | 6 ++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/masonite/auth/Sign.py b/masonite/auth/Sign.py index 95b734262..480ca7f2f 100644 --- a/masonite/auth/Sign.py +++ b/masonite/auth/Sign.py @@ -3,7 +3,7 @@ from masonite.exceptions import InvalidSecretKey - +import binascii class Sign: """Cryptographic signing class. """ @@ -38,11 +38,18 @@ def sign(self, value): Returns: string -- Returns the encrypted value. + + Raises: + InvalidSecretKey -- Thrown if the secret key has incorrect padding. """ - f = Fernet(self.key) - self.encryption = f.encrypt(bytes(value, 'utf-8')) - return self.encryption.decode('utf-8') + try: + f = Fernet(self.key) + self.encryption = f.encrypt(bytes(value, 'utf-8')) + return self.encryption.decode('utf-8') + except binascii.Error: + raise InvalidSecretKey("The encryption key passed does not have correct padding and therefore cannot be used as a secret key.") + def unsign(self, value=None): """Unsigns the value using the secret key. diff --git a/masonite/facades/__pycache__/Auth.cpython-36.pyc b/masonite/facades/__pycache__/Auth.cpython-36.pyc index ecd9b31cc0552c163127d452633d2e1f51bec5ef..1602dd0d5b27cad03820f9cdd2bb8d6e603c7c9e 100644 GIT binary patch literal 3364 zcmd^B&5ztP6t|sZCX@Z>c7dhktCm1j2dO&;5JDBI=m%RW&2)xIw27dC#k5UL$=d7z5tguD5@AnR+Y;;%X*#1VekackWs*f{)UOWI6OoT+V#4PguCC2c#RCh9LqyCz)GfU+(;u>z$l zR>c~W4Y4jRLFow#{9i6@bU%8ue;B1aG_H@MIOZM6^Hd6+DIP4=XBu_NI|25=VqxVx zR7p2FXyLH!!H{>OSb7|uo!t-kynBFWH)M#?03R2%1Ta*-5 z&lc8If<3}EVfqu7iLTO2=V7Mwwr8B6qdWQ_??VLBTk|Gt*78{{(~O_=gH$C^Cby?8 z+j~{dnBTm~_hARqcdj};8D>i}eP^W|#_F>2D%Mh~T9CfjW~WqrDX(p$JLYt;d040hYT^LYQu zrd`^pjJw)_CS5~=oxc*@fa34FtwYt9txP4u)_oOLv1{FfeYDg-CaKDGC|jY@vNa1` zs~d!YkZB8#0ZzGeeLsSj`u;l1n0jD{S7SDH*(x2anNhP5A#MgAM8F384GO-6%J9R2 z^hgf~GNJkg)L9R}yl9)So;@LtfHsc+LYZ^q>2D|*Q%Xi&L4TxA$ag>{VUOtx`jjN> zDZC+Cf(>x_KxS!$&s=LjM?B=QIyeB_MhRkj89{qNl*%*kkw1iTU>FG~F#`lY2BPAe zTJpmHXdvM=NVwEmX=q7A93=Q2`ObWWgQdyc8n$<&cd%5^RKvfq)~H}5;U&6>eU=^e<-50yHK zq`^$-z;?APoo=MltZaNS3rLe`7f!Ei%tK^wRT+drX`AgsEyeRD9;2(YMqjsVxe-*~8O$ew9>8RStci)PY%o`5tf}`#}`*KnN|nRlGkdlagr zrT-s@GIH{)d-GGh3Mky&XoP=P#CEoxE| zjkDXV!Mb4)kKuz9148PMcvfaRf}Rk!fe-d#`ZH+2#ytDLnW}&1Q z!LUGVm=EI8t4{^P?KK1~EF&0jZ!>o{YxEZc0yLnaAMXqoYVh#>()KUldn9ITFQO!y zGydUyu8fFRx>8*vw1jlLtRerFN~(34>HBz*WNMW7RJ6)qSH6x(dHF+1-lsRo~qW6Vi# ze0bxm5WEium*PEOF5jqgh-qLXrtkp775TWhWS$%FQyAU{q+$>*0IZElkVF3zt~EN% zgV^4ryUi86R3YVkzw~^(SLQL+SAG9k9>mk0y6+1W`hFGf6_`)IhUOX?j^=$dAD~%8 z)zmNy8d-ta+hk^!+3@o=-7WW;>$zK|7f$E~jx@*k#_XH(CM(^~s#V@b*+}uCX)~9( F)<5ElStkGh delta 912 zcmZuv%Wl&^6rCB59p_0XRDudxSEL6ek=uP%a55{C-nFhLznWQ8X95p}rGg>gh2U8IBwt0B@N z18YjK4PxhFz8VJG{dMd3dyQJrCAv02z|U)nLPVR!ya9Zy?|DM*Mm;t|UcwKB$w({jHlyXaFGdIVWycnE^V z!19X#ghfkwx$qIJ0cn#qJvDp%^3IE(kWzhYbGs26;g`vz!E{b~5Ti^h2M~`c*43jq;q;*TbN7<%Y_` z-L*BlsGyO=G3#|qtzK6sPo0iZ=Io;82MUCTu84KSB~<`2=6>UiR63eQ)AM%RQDSyV zrK6TPUByl648n;T=)2w))Dal}8~|Y^Wps>9M&Hc&L!6)cNSy^36-7|N1Pl@;IBGqL z?$51Qa=+^;>EGVm4li4ks`a?hv8p$(SFB29IeD#zPdC?WmZ(%0;FL`jcIc!e10;E2 zut+Y#%_xD;BJF2!^cF^xO>4FpIk| Date: Sun, 2 Sep 2018 08:15:24 -0500 Subject: [PATCH 04/17] Updated Sign.sign() method to catch not only binascii.error but also ValueError. It catches both cases of incorrect secret keys. It is also more PEP8 compliant. --- masonite/auth/Sign.py | 30 +++++++++++++++++------------- tests/test_signing.py | 2 +- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/masonite/auth/Sign.py b/masonite/auth/Sign.py index 480ca7f2f..259bf4b2c 100644 --- a/masonite/auth/Sign.py +++ b/masonite/auth/Sign.py @@ -1,20 +1,22 @@ """ Cryptographic Signing Module """ +import binascii + from cryptography.fernet import Fernet from masonite.exceptions import InvalidSecretKey -import binascii + class Sign: """Cryptographic signing class. """ def __init__(self, key=None): """Sign constructor - + Keyword Arguments: key {string} -- The secret key to use. If nothing is passed it then it will use the secret key from the config file. (default: {None}) - + Raises: InvalidSecretKey -- Thrown if the secret key does not exist. """ @@ -26,16 +28,17 @@ def __init__(self, key=None): self.key = application.KEY if not self.key: - raise InvalidSecretKey("The encryption key passed in is: None. Be sure there is a secret key present in your .env file or your config/application.py file.") + raise InvalidSecretKey( + "The encryption key passed in is: None. Be sure there is a secret key present in your .env file or your config/application.py file.") self.encryption = None def sign(self, value): """Sign a value using the secret key. - + Arguments: value {string} -- The value to be encrypted. - + Returns: string -- Returns the encrypted value. @@ -45,22 +48,23 @@ def sign(self, value): try: f = Fernet(self.key) - self.encryption = f.encrypt(bytes(value, 'utf-8')) - return self.encryption.decode('utf-8') - except binascii.Error: - raise InvalidSecretKey("The encryption key passed does not have correct padding and therefore cannot be used as a secret key.") + except (binascii.Error, ValueError): + raise InvalidSecretKey( + "You have passed an invalid secret key of: {}. Make sure you have correctly added your secret key.".format(self.key)) + self.encryption = f.encrypt(bytes(value, 'utf-8')) + return self.encryption.decode('utf-8') def unsign(self, value=None): """Unsigns the value using the secret key. - + Keyword Arguments: value {string} -- The value to be unencrypted. (default: {None}) - + Returns: string -- Returns the unencrypted value. """ - + f = Fernet(self.key) if not value: diff --git a/tests/test_signing.py b/tests/test_signing.py index c3b284a74..7abb8f4bd 100644 --- a/tests/test_signing.py +++ b/tests/test_signing.py @@ -31,6 +31,6 @@ def test_sign_without_specifying_key(self): def test_sign_incorrect_padding(self): with pytest.raises(InvalidSecretKey): - padded_secret_key = "AQAAQDhAAMAAQAAAAAAAAthAAAAJDczODFmZDM2LTNiOTYtNDVmYS04MjQ2LWRkYzJkMmViYjQ2YQ===" + padded_secret_key = "AQAAQDhAAMAAQYS04MjQ2LWRkYzJkMmViYjQ2YQ===" s = Sign(padded_secret_key) assert s.sign('value') \ No newline at end of file From eaa9675c328d3ba36c46cc444064d5911ceaf96f Mon Sep 17 00:00:00 2001 From: Joseph Mancuso Date: Sun, 2 Sep 2018 11:07:30 -0400 Subject: [PATCH 05/17] added view tests --- masonite/view.py | 8 ++++++++ resources/templates/admin_test.html | 1 + tests/test_view.py | 22 ++++++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 resources/templates/admin_test.html diff --git a/masonite/view.py b/masonite/view.py index 8706beeb2..3e126d4a7 100644 --- a/masonite/view.py +++ b/masonite/view.py @@ -45,6 +45,7 @@ def __init__(self, container): self.template = None self.environments = [] self._filters = {} + self._tests = {} def render(self, template, dictionary={}): """Get the string contents of the view. @@ -70,6 +71,9 @@ def render(self, template, dictionary={}): # Check if composers are even set for a speed improvement if self.composers: self._update_from_composers() + + if self._tests: + self.env.tests.update(self._tests) self.rendered_template = self.env.get_template(self.filename).render( self.dictionary) @@ -214,6 +218,10 @@ def filter(self, name, function): """ self._filters.update({name: function}) + + def test(self, key, obj): + self._tests.update({key: obj}) + return self def __load_environment(self, template): """Private method for loading all the environments. diff --git a/resources/templates/admin_test.html b/resources/templates/admin_test.html new file mode 100644 index 000000000..8331c6bf2 --- /dev/null +++ b/resources/templates/admin_test.html @@ -0,0 +1 @@ +{% if user is admin %}True{% else %}False{% endif %} \ No newline at end of file diff --git a/tests/test_view.py b/tests/test_view.py index a62454342..b9ea8b913 100644 --- a/tests/test_view.py +++ b/tests/test_view.py @@ -208,3 +208,25 @@ def test_cache_throws_exception_with_incorrect_cache_type(self): view( 'test_exception', {'test': 'test'} ).cache_for(1, 'monthss') + + def test_can_add_tests_to_view(self): + view = self.container.make('ViewClass') + + view.test('admin', self._is_admin) + + assert view._tests == {'admin': self._is_admin} + + user = MockAdminUser + assert view.render( + 'admin_test', {'user': user}).rendered_template == 'True' + + user.admin = 0 + + assert view.render( + 'admin_test', {'user': user}).rendered_template == 'False' + + def _is_admin(self, obj): + return obj.admin == 1 + +class MockAdminUser: + admin = 1 \ No newline at end of file From c268e904ad9a277ae948e0d4afa6750452899d8e Mon Sep 17 00:00:00 2001 From: Bjorn Theart Date: Tue, 4 Sep 2018 09:46:04 +0200 Subject: [PATCH 06/17] Added Python 3.7 support to .travis.yaml --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index 90725b3bc..a3f35d956 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,12 @@ python: - '3.5' - '3.6' +matrix: + include: + - python 3.7 + dist: xenial + sudo: true + install: - pip install masonite_cli - pip install -e . From dc203d0dbb1a0f4c18ae8f86e5d548a547cf80ae Mon Sep 17 00:00:00 2001 From: Bjorn Theart Date: Tue, 4 Sep 2018 09:57:55 +0200 Subject: [PATCH 07/17] Fixes incorrect yaml format --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a3f35d956..c588a1873 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ python: matrix: include: - - python 3.7 + - python: 3.7 dist: xenial sudo: true From 6d7f1a7bfeaa72bd469767247d1e31e926b9587f Mon Sep 17 00:00:00 2001 From: Bjorn Theart Date: Wed, 5 Sep 2018 13:37:40 +0200 Subject: [PATCH 08/17] Omit .travis.yml in .coveragerc --- .coveragerc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.coveragerc b/.coveragerc index a511879a3..db24590cf 100644 --- a/.coveragerc +++ b/.coveragerc @@ -7,4 +7,5 @@ omit = */tests/* masonite/commands/* masonite/contracts/* - masonite/snippets/* \ No newline at end of file + masonite/snippets/* + .travis.yml From 82e8649e5c33710eceb580d8eebd1ada08a263ea Mon Sep 17 00:00:00 2001 From: Vaibhav Mule Date: Sat, 8 Sep 2018 21:25:19 +0530 Subject: [PATCH 09/17] add flag for ssl remove print() --- config/mail.py | 1 + masonite/drivers/MailSmtpDriver.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/config/mail.py b/config/mail.py index 627b97724..ac2905477 100644 --- a/config/mail.py +++ b/config/mail.py @@ -58,6 +58,7 @@ 'port': os.getenv('MAIL_PORT', '465'), 'username': os.getenv('MAIL_USERNAME', 'username'), 'password': os.getenv('MAIL_PASSWORD', 'password'), + 'ssl': True }, 'mailgun': { 'secret': os.getenv('MAILGUN_SECRET', 'key-XX'), diff --git a/masonite/drivers/MailSmtpDriver.py b/masonite/drivers/MailSmtpDriver.py index 56cf69c1e..b2b3e1f38 100644 --- a/masonite/drivers/MailSmtpDriver.py +++ b/masonite/drivers/MailSmtpDriver.py @@ -39,7 +39,10 @@ def send(self, message_contents=None): message.attach(message_contents) # Send the message via our own SMTP server. - s = smtplib.SMTP('{0}:{1}'.format(config['host'], config['port'])) + if config['ssl']: + s = smtplib.SMTP_SSL('{0}:{1}'.format(config['host'], config['port'])) + else: + s = smtplib.SMTP('{0}:{1}'.format(config['host'], config['port'])) s.login(config['username'], config['password']) # s.send_message(message) From a2f4d876952523849ead1687bfa53a1776c9958d Mon Sep 17 00:00:00 2001 From: Vaibhav Mule Date: Sat, 8 Sep 2018 22:46:34 +0530 Subject: [PATCH 10/17] create CONTRIBUTING.md Closes: #301 --- CONTRIBUTING.md | 191 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..ed0a765f7 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,191 @@ +# Contributing Guide + +## Introduction + +When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners or contributors of this repository before making a change. + +Please note we have a code of conduct, please follow it in all your interactions with the project. + +## Getting Started + +The framework has three main parts. + +This `MasoniteFramework/masonite` repository is the main repository that will install when creating new projects using the `craft new` command. Not much development will be done in this repository and won't be changed unless new releases of Masonite require changes in the default installation project. + +The `MasoniteFramework/core` repository where the main `masonite` pip package lives. This is where the `from masonite ...` module lives. + +The `MasoniteFramework/craft` repository where the `craft` command lives + +### Getting the Masonite repository up and running to be edited + +[You can read about how the framework flows, works and architectural concepts here](https://masoniteframework.gitbooks.io/docs/content/request-lifecycle.html) + +This repo is simple and will be able to be installed following the installation instruction in the README. + +* Fork the `MasoniteFramework/masonite` repo. +* Clone that repo into your computer: + * `git clone http://github.com/your-username/masonite.git` +* Checkout the current release branch \(example: `develop`\) +* You should now be on a `develop` local branch. +* Run `git pull origin develop` to get the current release version. +* From there simply create your feature branches \(`change-default-orm`\) and make your desired changes. +* Push to your origin repository: + * `git push origin change-default-orm` +* Open a pull request and follow the PR process below + +### Editing the Masonite core repository + +The trick to this is that we need it to be pip installed and then quickly editable until we like it, and then pushed back to the repo for a PR. Do this only if you want to make changes to the core Masonite package + +To do this just: + +* Fork the `MasoniteFramework/core` repo, +* Clone that repo into your computer: + * `git clone http://github.com/your-username/core.git` +* Activate your masonite virtual environment \(optional\) + * Go to where you installed masonite and activate the environment +* While inside the virtual environment, cd into the directory you installed core. +* Run `pip install .` from inside the masonite-core directory. This will install masonite as a pip package. +* Any changes you make to this package just push it to your feature branch on your fork and follow the PR process below. + +{% hint style="warning" %} +This repository has a barebones skeleton of a sample project in order to aid in testing all the features of Masonite against a real project. If you install this as editable by passing the `--editable` flag then this may break your project because it will override the modules in this package with your application modules. +{% endhint %} + +### Editing the craft repository \(`craft` commands\) + +Craft commands make up a large part of the workflow for Masonite. Follow these instructions to get the masonite-cli package on your computer and editable. + +* Fork the `MasoniteFramework/craft` repo, +* Clone that repo into your computer: + * `git clone http://github.com/your-username/craft.git` +* Activate your masonite virtual environment \(optional\) + * Go to where you installed masonite and activate the environment +* While inside the virtual environment, cd into the directory you installed cli +* Run `pip install --editable .` from inside the masonite-cli directory. This will install craft \(which contains the craft commands\) as a pip package but also keep a reference to the folder so you can make changes freely to craft commands while not having to worry about continuously reinstalling it. +* Any changes you make to this package just push it to your feature branch on your fork and follow the PR process below. + +### Comments + +Comments are a vital part of any repository and should be used where needed. It is important not to overcomment something. If you find you need to constantly add comments, you're code may be too complex. Code should be self documenting \(with clearly defined variable and method names\) + +#### Types of comments to use + +There are 3 main type of comments you should use when developing for Masonite: + +**Module Docstrings** + +All modules should have a docstring at the top of every module file and should look something like: + +```python +""" This is a module to add support for Billing users """ +from masonite.request import Request +... +``` + +**Method and Function Docstrings** + +All methods and functions should also contain a docstring with a brief description of what the module does + +For example: + +```python +def some_function(self): + """ + This is a function that does x action. + Then give an exmaple of when to use it + """ + ... code ... +``` + +**Code Comments** + +If you're code MUST be complex enough that future developers will not understand it, add a `#` comment above it + +For normal code this will look something like: + +```python +# This code performs a complex task that may not be understood later on +# You can add a second line like this +complex_code = 'value' + +perform_some_complex_task() +``` + +**Flagpole Comments** + +Flag pole comments are a fantastic way to give developers an inside to what is really happening and for now should only be reserved for configuration files. A flag pole comment gets its name from how the comment looks + +```text +''' +|-------------------------------------------------------------------------- +| A Heading of The Setting Being Set +|-------------------------------------------------------------------------- +| +| A quick description +| +''' + +SETTING = 'some value' +``` + +It's important to note that there should have exactly 75 `-` above and below the header and have a trailing `|` at the bottom of the comment. + +### Pull Request Process + +1. You should open an issue before making any pull requests. Not all features will be added to the framework and some may be better off as a third party package. It wouldn't be good if you worked on a feature for several days and the pull request gets rejected for reasons that could have been discussed in an issue for several minutes. +2. Ensure any changes are well commented and any configuration files that are added have a flagpole comment on the variables it's setting. +3. Update the README.md and `MasoniteFramework/docs` repo with details of changes to the interface, this includes new environment variables, new file locations, container parameters etc. +4. You must add unit testing for any changes made. Of the three repositories listed above, only the `craft` and `core` repos require unit testing. +5. Increase the version numbers in any example files and the README.md to the new version that this Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/) for both `core` and `craft` or [RomVer](http://blog.legacyteam.info/2015/12/romver-romantic-versioning/) for the main Masonite repo. +6. The PR must pass the Travis CI build. The Pull Request can be merged in once you have a successful review from two other collaborators, or the feature maintainer for your specific feature improvement or the repo owner. + +## Code of Conduct + +### Our Pledge + +In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. + +### Our Standards + +Examples of behavior that contributes to creating a positive environment include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + + address, without explicit permission + +* Other conduct which could reasonably be considered inappropriate in a + + professional setting + +### Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. + +### Scope + +This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. + +### Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at idmann509@gmail.com. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. + +### Attribution + +This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.4, available at [http://contributor-covenant.org/version/1/4](http://contributor-covenant.org/version/1/4/) + From f9f5cf3448ddc52d0735f086c6fc0707c95d0b87 Mon Sep 17 00:00:00 2001 From: Vaibhav Mule Date: Sat, 8 Sep 2018 23:15:07 +0530 Subject: [PATCH 11/17] fix KeyError exception for 'ssl' key in config --- masonite/drivers/MailSmtpDriver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/masonite/drivers/MailSmtpDriver.py b/masonite/drivers/MailSmtpDriver.py index b2b3e1f38..0d6655bda 100644 --- a/masonite/drivers/MailSmtpDriver.py +++ b/masonite/drivers/MailSmtpDriver.py @@ -39,7 +39,7 @@ def send(self, message_contents=None): message.attach(message_contents) # Send the message via our own SMTP server. - if config['ssl']: + if 'ssl' in config and config['ssl'] is True: s = smtplib.SMTP_SSL('{0}:{1}'.format(config['host'], config['port'])) else: s = smtplib.SMTP('{0}:{1}'.format(config['host'], config['port'])) From 3dbfcbb80242b8afcb966134132845d2d3561604 Mon Sep 17 00:00:00 2001 From: Joseph Mancuso Date: Sat, 8 Sep 2018 14:28:20 -0400 Subject: [PATCH 12/17] added test and modified smtp driver --- config/mail.py | 1 - masonite/drivers/MailSmtpDriver.py | 14 ++++++++------ tests/test_managers_mail_manager.py | 21 +++++++++++++++------ 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/config/mail.py b/config/mail.py index ac2905477..627b97724 100644 --- a/config/mail.py +++ b/config/mail.py @@ -58,7 +58,6 @@ 'port': os.getenv('MAIL_PORT', '465'), 'username': os.getenv('MAIL_USERNAME', 'username'), 'password': os.getenv('MAIL_PASSWORD', 'password'), - 'ssl': True }, 'mailgun': { 'secret': os.getenv('MAILGUN_SECRET', 'key-XX'), diff --git a/masonite/drivers/MailSmtpDriver.py b/masonite/drivers/MailSmtpDriver.py index 0d6655bda..c06875c22 100644 --- a/masonite/drivers/MailSmtpDriver.py +++ b/masonite/drivers/MailSmtpDriver.py @@ -40,12 +40,14 @@ def send(self, message_contents=None): # Send the message via our own SMTP server. if 'ssl' in config and config['ssl'] is True: - s = smtplib.SMTP_SSL('{0}:{1}'.format(config['host'], config['port'])) + self.smtp = smtplib.SMTP_SSL('{0}:{1}'.format(config['host'], config['port'])) else: - s = smtplib.SMTP('{0}:{1}'.format(config['host'], config['port'])) - s.login(config['username'], config['password']) + self.smtp = smtplib.SMTP('{0}:{1}'.format( + config['host'], config['port'])) - # s.send_message(message) - s.sendmail(self.config.FROM['name'], + self.smtp.login(config['username'], config['password']) + + # self.smtp.send_message(message) + self.smtp.sendmail(self.config.FROM['name'], self.to_address, message.as_string()) - s.quit() + self.smtp.quit() diff --git a/tests/test_managers_mail_manager.py b/tests/test_managers_mail_manager.py index 835023f84..b9bbc049b 100644 --- a/tests/test_managers_mail_manager.py +++ b/tests/test_managers_mail_manager.py @@ -1,12 +1,14 @@ -from config import mail +import ssl + import pytest +from config import mail from masonite.app import App +from masonite.contracts import MailManagerContract +from masonite.drivers import MailMailgunDriver as Mailgun +from masonite.drivers import MailSmtpDriver as MailDriver from masonite.exceptions import DriverNotFound from masonite.managers import MailManager -from masonite.drivers import MailSmtpDriver as MailDriver -from masonite.drivers import MailMailgunDriver as Mailgun -from masonite.contracts import MailManagerContract from masonite.view import View @@ -54,12 +56,10 @@ def test_does_not_create_driver_with_initilization_container(self): assert mailManager.manage_driver == None def test_does_not_raise_drivernotfound_exception(self): - mailManager = MailManager(self.app) def test_manager_sets_driver(self): self.app.bind('MailMailtrapDriver', Mailgun) - mailManager = MailManager(self.app).driver('mailtrap') def test_manager_sets_driver_throws_driver_not_found_exception(self): @@ -98,3 +98,12 @@ def test_switch_mail_manager(self): mail_driver = MailManager(self.app).driver('smtp') assert isinstance(mail_driver.driver('test'), Mailgun) + + def test_mail_driver_uses_smtp_ssl(self): + self.app.bind('MailSmtpDriver', MailDriver) + self.app.make('MailConfig').DRIVERS['smtp']['ssl'] = True + + mail_driver = MailManager(self.app).driver('smtp') + + with pytest.raises(ssl.SSLError): + mail_driver.send('test') From ca1bad7569895d4fed44a4f6075b5c746b9b9716 Mon Sep 17 00:00:00 2001 From: Joseph Mancuso Date: Sat, 8 Sep 2018 14:35:15 -0400 Subject: [PATCH 13/17] fixed travis test --- tests/test_managers_mail_manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_managers_mail_manager.py b/tests/test_managers_mail_manager.py index b9bbc049b..53f6eca02 100644 --- a/tests/test_managers_mail_manager.py +++ b/tests/test_managers_mail_manager.py @@ -106,4 +106,4 @@ def test_mail_driver_uses_smtp_ssl(self): mail_driver = MailManager(self.app).driver('smtp') with pytest.raises(ssl.SSLError): - mail_driver.send('test') + mail_driver.to('test@email.com').send('test') From 6c0bcccb5c530b41c2628919778b19c8296fa4cd Mon Sep 17 00:00:00 2001 From: Joseph Mancuso Date: Sat, 8 Sep 2018 23:14:26 -0400 Subject: [PATCH 14/17] removed ssl test --- tests/test_managers_mail_manager.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/test_managers_mail_manager.py b/tests/test_managers_mail_manager.py index 53f6eca02..bcde503e7 100644 --- a/tests/test_managers_mail_manager.py +++ b/tests/test_managers_mail_manager.py @@ -98,12 +98,3 @@ def test_switch_mail_manager(self): mail_driver = MailManager(self.app).driver('smtp') assert isinstance(mail_driver.driver('test'), Mailgun) - - def test_mail_driver_uses_smtp_ssl(self): - self.app.bind('MailSmtpDriver', MailDriver) - self.app.make('MailConfig').DRIVERS['smtp']['ssl'] = True - - mail_driver = MailManager(self.app).driver('smtp') - - with pytest.raises(ssl.SSLError): - mail_driver.to('test@email.com').send('test') From 406a553a1c41cc82c5b3be6c29284833960326ed Mon Sep 17 00:00:00 2001 From: Joseph Mancuso Date: Sat, 8 Sep 2018 23:29:05 -0400 Subject: [PATCH 15/17] modularized the view class a bit --- masonite/view.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/masonite/view.py b/masonite/view.py index 8706beeb2..dfce06980 100644 --- a/masonite/view.py +++ b/masonite/view.py @@ -44,6 +44,7 @@ def __init__(self, container): self.template = None self.environments = [] + self.extension = '.html' self._filters = {} def render(self, template, dictionary={}): @@ -71,10 +72,13 @@ def render(self, template, dictionary={}): if self.composers: self._update_from_composers() - self.rendered_template = self.env.get_template(self.filename).render( - self.dictionary) + self.rendered_template = self._render() return self + + def _render(self): + return self.env.get_template(self.filename).render( + self.dictionary) def _update_from_composers(self): """Adds data into the view from specified composers. @@ -223,12 +227,12 @@ def __load_environment(self, template): """ self.template = template - self.filename = template + '.html' + self.filename = template + self.extension if template.startswith('/'): # Filter blanks strings from the split location = list(filter(None, template.split('/'))) - self.filename = location[-1] + '.html' + self.filename = location[-1] + self.extension loader = PackageLoader(location[0], '/'.join(location[1:-1])) From 797d0048eab96ec7d7541ceb53d6c56cdd22b41e Mon Sep 17 00:00:00 2001 From: Joseph Mancuso Date: Sun, 9 Sep 2018 19:55:11 -0400 Subject: [PATCH 16/17] bumped version --- masonite/info.py | 2 +- setup.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/masonite/info.py b/masonite/info.py index f6a18ea89..54ba08c92 100644 --- a/masonite/info.py +++ b/masonite/info.py @@ -1,4 +1,4 @@ """Module for specifying the Masonite version in a central location. """ -VERSION = '2.0.19' +VERSION = '2.0.20' diff --git a/setup.py b/setup.py index 5f7bde817..f9606d4b2 100644 --- a/setup.py +++ b/setup.py @@ -14,6 +14,7 @@ 'masonite.testsuite', 'masonite.queues', 'masonite.contracts', + 'masonite.contracts.managers', 'masonite.helpers', ], version=VERSION, From f0e24e740ae5f96233b515c9d3644b32981b2b98 Mon Sep 17 00:00:00 2001 From: Joseph Mancuso Date: Sun, 9 Sep 2018 20:06:20 -0400 Subject: [PATCH 17/17] fixed upload manager contract --- masonite/managers/UploadManager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/masonite/managers/UploadManager.py b/masonite/managers/UploadManager.py index da5fbe659..c43ec8b33 100644 --- a/masonite/managers/UploadManager.py +++ b/masonite/managers/UploadManager.py @@ -4,7 +4,7 @@ from masonite.managers import Manager -class UploadManager(Manager): +class UploadManager(Manager, UploadManagerContract): """Manages all upload drivers. Arguments: