diff --git a/.coveragerc b/.coveragerc index 1d319ea..7ddb0cb 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,7 +1,8 @@ # Coverage configuration file [run] -source = . +source = + airtng_flask omit = */migrations/* diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..eb2de25 --- /dev/null +++ b/.env.example @@ -0,0 +1,3 @@ +TWILIO_ACCOUNT_SID=Your-Account-SID +TWILIO_AUTH_TOKEN=Your-Twilio-Auth-Token +TWILIO_NUMBER=Your-Twilio-Phone-Number diff --git a/.github/workflows/flask.yml b/.github/workflows/flask.yml new file mode 100644 index 0000000..e23ea47 --- /dev/null +++ b/.github/workflows/flask.yml @@ -0,0 +1,34 @@ +name: Flask + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + max-parallel: 4 + matrix: + python-version: [3.6, 3.7, 3.8] + + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Install Dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + pip install coveralls + - name: Set up project + run: | + python manage.py db upgrade + - name: Run Tests + run: | + coverage run manage.py test diff --git a/.gitignore b/.gitignore index 2035d83..1cecce5 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ __pycache__/ *.so # Distribution / packaging +venv .Python env/ ivr-env/ @@ -63,3 +64,5 @@ target/ .idea dev.sqlite + +.vscode diff --git a/.mergify.yml b/.mergify.yml new file mode 100644 index 0000000..0433495 --- /dev/null +++ b/.mergify.yml @@ -0,0 +1,13 @@ +pull_request_rules: + - name: automatic merge for Dependabot pull requests + conditions: + - author=dependabot-preview[bot] + - status-success=build (macos-latest, 10) + - status-success=build (macos-latest, 12) + - status-success=build (windows-latest, 10) + - status-success=build (windows-latest, 12) + - status-success=build (ubuntu-latest, 10) + - status-success=build (ubuntu-latest, 12) + actions: + merge: + method: squash diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0c7553a..0000000 --- a/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: python -python: - - '2.7' - - '3.4' -install: - - pip install -r requirements.txt - - pip install coveralls -before_script: - - python manage.py db upgrade -script: coverage run manage.py test \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..2f0727e --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,73 @@ +# Contributor Covenant 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, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, 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 open-source@twilio.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][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ad3257e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +# Contributing to Twilio + +All third party contributors acknowledge that any contributions they provide will be made under the same open source license that the open source project is provided under. diff --git a/LICENSE b/LICENSE index fb2b666..2c3cf9d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,22 +1,21 @@ -Copyright (c) 2012 Twilio, Inc. +MIT License -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: +Copyright (c) 2020 Twilio Inc. -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 931371c..458c24f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Airtng App: Part 1 - Workflow Automation with Python | Flask > We are currently in the process of updating this sample template. If you are encountering any issues with the sample, please open an issue at [github.com/twilio-labs/code-exchange/issues](https://github.com/twilio-labs/code-exchange/issues) and we'll try to help you. -[![Build Status](https://travis-ci.org/TwilioDevEd/airtng-flask.svg?branch=master)](https://travis-ci.org/TwilioDevEd/airtng-flask) +![](https://github.com/TwilioDevEd/airtng-flask/workflows/Flask/badge.svg) Learn how to automate your workflow using Twilio's REST API and Twilio SMS. This example app is a vacation rental site, where the host can confirm a reservation via SMS. @@ -17,6 +17,13 @@ Learn how to automate your workflow using Twilio's REST API and Twilio SMS. This Remember that the number where you change the _SMS webhook_ must be the same one you set on the `TwilioPhoneNumber` setting. + ![Configure Messaging](webhook.png) + + You need to expose your application to the wider internet using [ngrok](https://ngrok.com/download). + This step is important because the application won't work as expected if you run it through localhost. + + > [Learn 6 awesome reasons why to use ngrok](https://www.twilio.com/blog/2015/09/6-awesome-reasons-to-use-ngrok-when-testing-webhooks.html). + To start using `ngrok` in our project you'll have execute to the following line in the _command prompt_. ``` @@ -29,13 +36,13 @@ Learn how to automate your workflow using Twilio's REST API and Twilio SMS. This http://.ngrok.io/confirm ``` -1. Clone this repository and `cd` into it. +2. Clone this repository and `cd` into it. ``` git clone git@github.com:TwilioDevEd/airtng-flask.git ``` -1. Create a new virtual environment. +3. Create a new virtual environment. - If using vanilla [virtualenv](https://virtualenv.pypa.io/en/latest/): @@ -50,35 +57,35 @@ Learn how to automate your workflow using Twilio's REST API and Twilio SMS. This mkvirtualenv airtng-flask ``` -1. Install the requirements. +4. Install the requirements. ``` pip install -r requirements.txt ``` -1. Edit the following keys/values for the `config.py` file inside the `airtng_flask/` directory. Be sure to replace the place holders and connection string with real information. Replace the connection string preferably under development config. +5. Copy the sample configuration `.env.example` to `.env`, and then edit `.env` to match your configuration. - ``` - TWILIO_ACCOUNT_SID = 'your_twilio_account_sid' - TWILIO_AUTH_TOKEN = 'your_twilio_auth_token' - TWILIO_NUMBER = 'your_twilio_phone_number' + ```bash + cp .env.example .env + ``` - SQLALCHEMY_DATABASE_URI = 'sqlite://' - ``` + You can find your `TWILIO_ACCOUNT_SID` and `TWILIO_AUTH_TOKEN` in your + [Twilio Account Settings](https://www.twilio.com/console). + You will also need a `TWILIO_PHONE_NUMBER`, which you may find [here](https://www.twilio.com/console/phone-numbers/incoming). -1. Run the migrations. +6. Run the migrations. ``` python manage.py db upgrade ``` -1. Start the development server. +7. Start the development server. ``` python manage.py runserver ``` -1. Check it out at [http://localhost:5000](http://localhost:5000) +8. Check it out at [http://localhost:5000](http://localhost:5000) That's it! @@ -87,8 +94,6 @@ That's it! You can run the tests locally through [coverage](http://coverage.readthedocs.org/): -1. Run the tests. - ``` $ coverage run manage.py test ``` @@ -98,5 +103,6 @@ You can then view the results with `coverage report` or build an HTML report wit ## Meta * No warranty expressed or implied. Software is as is. Diggity. +* The CodeExchange repository can be found [here](https://github.com/twilio-labs/code-exchange/). * [MIT License](http://www.opensource.org/licenses/mit-license.html) * Lovingly crafted by Twilio Developer Education. diff --git a/airtng_flask/__init__.py b/airtng_flask/__init__.py index 21d0b64..5092c20 100644 --- a/airtng_flask/__init__.py +++ b/airtng_flask/__init__.py @@ -2,8 +2,8 @@ from airtng_flask.config import config_env_files from flask import Flask -from flask.ext.bcrypt import Bcrypt -from flask.ext.sqlalchemy import SQLAlchemy +from flask_bcrypt import Bcrypt +from flask_sqlalchemy import SQLAlchemy from flask_login import LoginManager db = SQLAlchemy() @@ -14,6 +14,7 @@ def create_app(config_name='development', p_db=db, p_bcrypt=bcrypt, p_login_manager=login_manager): new_app = Flask(__name__) config_app(config_name, new_app) + new_app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False p_db.init_app(new_app) p_bcrypt.init_app(new_app) diff --git a/airtng_flask/config.py b/airtng_flask/config.py index cfb1043..8fbbe7b 100644 --- a/airtng_flask/config.py +++ b/airtng_flask/config.py @@ -2,14 +2,16 @@ basedir = os.path.abspath(os.path.dirname(__file__)) +from dotenv import load_dotenv +load_dotenv() class DefaultConfig(object): SECRET_KEY = 'secret-key' DEBUG = False SQLALCHEMY_DATABASE_URI = 'sqlite://' - TWILIO_ACCOUNT_SID = 'your_twilio_account_sid' - TWILIO_AUTH_TOKEN = 'your_twilio_auth_token' - TWILIO_NUMBER = 'your_twilio_number' + TWILIO_ACCOUNT_SID = os.getenv('TWILIO_ACCOUNT_SID') + TWILIO_AUTH_TOKEN = os.getenv('TWILIO_AUTH_TOKEN') + TWILIO_NUMBER = os.getenv('TWILIO_NUMBER') class DevelopmentConfig(DefaultConfig): diff --git a/airtng_flask/forms.py b/airtng_flask/forms.py index ee692ca..452045b 100644 --- a/airtng_flask/forms.py +++ b/airtng_flask/forms.py @@ -1,4 +1,4 @@ -from flask_wtf import Form +from flask_wtf import FlaskForm as Form from wtforms import TextField, PasswordField, IntegerField, HiddenField from wtforms.validators import DataRequired, Length, Email, URL @@ -19,8 +19,7 @@ class RegisterForm(Form): ) country_code = TextField( 'Country Code:', - validators=[DataRequired("Country code is required"), - Length(min=1, max=4, message="Country code must be between 1 and 4 numbers")] + validators=[Length(min=1, max=4, message="Country code must be between 1 and 4 numbers")] ) phone_number = IntegerField( diff --git a/airtng_flask/templates/property_new.html b/airtng_flask/templates/property_new.html index f8312e3..a945377 100644 --- a/airtng_flask/templates/property_new.html +++ b/airtng_flask/templates/property_new.html @@ -12,7 +12,7 @@

New Vacation Property


{{ render_field(form.description, placeholder="Captain's Palace") }} - {{ render_field(form.image_url }} + {{ render_field(form.image_url) }}
diff --git a/airtng_flask/views.py b/airtng_flask/views.py index 54f998e..b769a90 100644 --- a/airtng_flask/views.py +++ b/airtng_flask/views.py @@ -1,6 +1,6 @@ from airtng_flask import db, bcrypt, app, login_manager from flask import session, g, request, flash, Blueprint -from flask.ext.login import login_user, logout_user, current_user, login_required +from flask_login import login_user, logout_user, current_user, login_required from twilio.twiml.voice_response import VoiceResponse from airtng_flask.forms import RegisterForm, LoginForm, VacationPropertyForm, ReservationForm, \ diff --git a/manage.py b/manage.py index a04e649..01983e8 100644 --- a/manage.py +++ b/manage.py @@ -1,5 +1,5 @@ -from flask.ext.script import Manager -from flask.ext.migrate import Migrate, MigrateCommand +from flask_script import Manager +from flask_migrate import Migrate, MigrateCommand from airtng_flask import app, db diff --git a/requirements.txt b/requirements.txt index 6d3cb79..7b149c9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,30 +1,31 @@ -alembic==0.8.4 -bcrypt==2.0.0 +alembic==1.4.1 +bcrypt==3.1.7 blinker==1.4 -cffi==1.4.2 -coverage==4.0.3 -Flask==0.10.1 +cffi==1.14.0 +coverage==5.0.4 +Flask==1.1.1 Flask-Bcrypt==0.7.1 -Flask-Login==0.3.2 -Flask-Migrate==1.7.0 -Flask-Script==2.0.5 -Flask-SQLAlchemy==2.1 -Flask-Testing==0.4.2 -Flask-WTF==0.12 -httplib2==0.9.2 -itsdangerous==0.24 -Jinja2==2.8 +Flask-Login==0.5.0 +Flask-Migrate==2.5.3 +Flask-Script==2.0.6 +Flask-SQLAlchemy==2.4.1 +Flask-Testing==0.8.0 +Flask-WTF==0.14.3 +httplib2==0.17.0 +itsdangerous==1.1.0 +Jinja2==2.11.1 linecache2==1.0.0 -Mako==1.0.3 -MarkupSafe==0.23 -pycparser==2.14 -python-editor==0.5 -pytz==2015.7 -six==1.10.0 -SQLAlchemy==1.0.11 +Mako==1.1.2 +MarkupSafe==1.1.1 +pycparser==2.20 +python-dotenv==0.12.0 +python-editor==1.0.4 +pytz==2019.3 +six==1.14.0 +SQLAlchemy==1.3.15 traceback2==1.4.0 -twilio==6.9.0 +twilio==6.37.0 unittest2==1.1.0 -Werkzeug==0.11.3 -wheel==0.24.0 -WTForms==2.1 +Werkzeug==1.0.0 +wheel==0.34.0 +WTForms==2.2.1 diff --git a/tests/base.py b/tests/base.py index 106c336..281f784 100644 --- a/tests/base.py +++ b/tests/base.py @@ -1,4 +1,4 @@ -from flask.ext.testing import TestCase +from flask_testing import TestCase from airtng_flask import app, config_app diff --git a/webhook.png b/webhook.png new file mode 100644 index 0000000..7ca8962 Binary files /dev/null and b/webhook.png differ