-
Notifications
You must be signed in to change notification settings - Fork 0
Used cosmos as db #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 14 commits
6fa55e4
d8a8cb2
c35e265
3796753
0863ec1
1158785
d5e183b
8023c90
75fc439
476098e
60604a0
d2a11d5
4fe77ea
a8b1407
6ccc15f
f27e7dc
fb646a2
9834e34
166b2d6
144a8cc
5291854
fbf02c6
7d1f785
bd86c40
efe01c5
b422d27
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,68 +1,115 @@ | ||
# Flask + React + Postgres Starter | ||
# Team Standup App | ||
|
||
This is a minimal sample Flask and React starter code that demonstrates how both frameworks can be used together in a single page web Application. | ||
This is a simple single page web app that integrates the Flask and React framework. It uses Track 2 versions of the [Azure SDK for Python](https://github.com/Azure/azure-sdk-for-python), specifically [azure-cosmos](https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/cosmos/azure-cosmos) and [azure-keyvault-secrets](https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/keyvault/azure-keyvault-secrets), in addition to [azure-identity](https://github.com/Azure/azure-sdk-for-python/tree/master/sdk/identity/azure-identity) for authentication purposes. | ||
|
||
The code is based on https://github.com/dternyak/React-Redux-Flask and https://github.com/creativetimofficial/material-dashboard-react | ||
|
||
## Tutorial | ||
The code is based on https://github.com/dternyak/React-Redux-Flask and https://github.com/creativetimofficial/material-dashboard-react. | ||
|
||
## 1. Setting Up The Project | ||
## How to Run | ||
|
||
## 1. Setting up Azure Services | ||
First, sign up for a free [Azure](https://azure.microsoft.com/en-us/free/) account if you don't already have one. Sign into https://portal.azure.com. | ||
|
||
[Create a resource group](https://github.com/lilyjma/azurethings/blob/master/createResourceGroup.md) to store the resources that you'll be using here--Azure Cosmos DB and Key vault. Then follow the instructions in the links below to create each resource (remember to store them in the resource group you created): | ||
|
||
1. [Azure Cosmos DB](https://docs.microsoft.com/en-us/azure/cosmos-db/create-cosmosdb-resources-portal) | ||
1. When creating the database, name it 'team_standup'. For this app, you also need two containers named 'tasks' and 'users'. The [partition key](https://docs.microsoft.com/en-us/azure/cosmos-db/partitioning-overview#choose-partitionkey) for both is '/id'. | ||
2. [Key Vault](https://docs.microsoft.com/en-us/azure/key-vault/quick-create-portal) | ||
1. This will store the credentials for the resources this app uses. For example, it'll store the key to the cosmos database. This way, you don't reveal any key in your code. | ||
2. You'll add two secrets called 'cosmosKey' and 'cosmosURI' to Key Vault to hold the cosmos key and URI respectively. To find these, click into the Cosmos DB account created, go to 'Keys' tab and get the Primary Key and the URI. | ||
|
||
## 2. Getting Access to Key Vault | ||
To make a long story short, you need a service principal to have access to key vault. The service principal serves as an application ID, which is used during the authorization setup for access to other Azure resources via RBAC (role-based access control). We'll use a Web App instance as our service principal. To do that, we create an App Service Plan, then a Web App instance, then make that our service principal on Cloud Shell (click >_ on the top right hand corner in Portal to open). | ||
|
||
1. Create App Service Plan : | ||
|
||
```az appservice plan create --name myServicePlanName --resource-group myResourceGroup --location westus``` | ||
|
||
There are locations other than westus. A json object will pop up when the command is done. | ||
|
||
2. Create a Web App instance : (Note that the app name must be unique.) | ||
|
||
```az webapp create --name myUniqueAppName --plan myServicePlanName --resource-group myResourceGroup``` | ||
|
||
3. Make the web app a service principal : | ||
|
||
```az ad sp create-for-rbac --name http://my-applications-url --skip-assignment``` | ||
|
||
Use your web app's url. To find that, click on the app in Portal, go to the 'Overview' tab and look for 'URL' on the top right portion of the page. It looks something like https://myUniqueAppName.azurewebsites.net. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you mean use your web apps url? In the above or below? Please be explicit in everything you ask the user to do. |
||
|
||
After the above comand runs, something like this is returned: | ||
``` | ||
{ | ||
"appId": "11b855c6-43a5-415b-bd34-042a4509c179", | ||
"displayName": "myUniqueAppName.azurewebsites.net", | ||
"name": "https://myUniqueAppName.azurewebsites.net", | ||
"password": "5ad92c90-9e0b-4bcb-a3ad-a121e9076af1", | ||
"tenant": "72f998be-86f2-51ae-01af-2d5cd110db40" | ||
} | ||
``` | ||
|
||
Later when you set environment variables, you'll need this info. The tenant will be saved as 'AZURE_TENANT_ID', appId as 'AZURE_CLIENT_ID', and password as 'AZURE_CLIENT_SECRET'. | ||
|
||
|
||
|
||
## 3. Setting Up The Project | ||
|
||
1. Clone the reponsitory | ||
```bash | ||
git clone https://github.com/jeffreymew/Flask-React-Postgres.git | ||
cd flask-react-postgres | ||
``` | ||
```bash | ||
git clone https://github.com/lilyjma/Flask-React-Postgres/tree/team_standup_app_cosmos | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this path is right, but doesn't matter for now |
||
cd flask-react-postgres | ||
``` | ||
|
||
2. Create and activate a virtual environment | ||
|
||
In Bash | ||
```bash | ||
python3 -m venv venv | ||
source venv/bin/activate | ||
``` | ||
|
||
In Powershell | ||
```Powershell | ||
py -3 -m venv env | ||
env\scripts\activate | ||
``` | ||
In Bash | ||
```bash | ||
python3 -m venv venv | ||
source venv/bin/activate | ||
``` | ||
|
||
In Powershell | ||
```Powershell | ||
py -3 -m venv env | ||
env\scripts\activate | ||
``` | ||
In Powershell | ||
```Powershell | ||
py -3 -m venv env | ||
env\scripts\activate | ||
``` | ||
|
||
2. Install requirements.txt | ||
```bash | ||
pip install -r requirements.txt | ||
``` | ||
```bash | ||
pip install -r requirements.txt | ||
``` | ||
|
||
3. Import the project folder into VS Code | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you mean "Open", not "Import" |
||
```bash | ||
code . | ||
``` | ||
```bash | ||
code . | ||
``` | ||
|
||
## 2. Running The Code Locally | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please containerize each part of the app so the user just has to start the container to run it. Talk with me if you have questions. |
||
4. Create a .env file in the root directory | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typically we create a .env.tmp file in the root with the exact structure and keys required, without the secrets. And then ask the user to rename it to .env and put in the correct values. Make sure .env is in your .gitignore if you do this. |
||
1. Put these environment variables and their corresponding value in the file (you saved these in Step 2) : AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID, KEY_VAULT_URI. For example: | ||
|
||
```AZURE_CLIENT_ID="11b855c6-43a5-415b-bd34-042a4509c179"``` | ||
|
||
## 4. Running The Code Locally | ||
|
||
1. Build the react.js front-end. | ||
```bash | ||
npm install | ||
npm run build | ||
``` | ||
2. Create the SQL database | ||
```bash | ||
cd .. | ||
python manage.py create_db | ||
``` | ||
3. Start the Flask server | ||
```bash | ||
python manage.py runserver | ||
``` | ||
``` | ||
npm install | ||
``` | ||
Go into the /static folder and do | ||
|
||
``` | ||
npm run build | ||
``` | ||
|
||
|
||
|
||
2. Start the Flask server | ||
``` | ||
python manage.py runserver | ||
``` | ||
4. Check ```localhost:5000``` in your browser to view the web application. | ||
|
||
## 3. Deploying The Code To Azure | ||
## 5. Deploying The Code To Azure | ||
|
||
1. Go to the extensions tab on VS Code | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,23 @@ | ||
from flask import Flask | ||
from flask_bcrypt import Bcrypt | ||
from flask_sqlalchemy import SQLAlchemy | ||
|
||
from dotenv import load_dotenv | ||
import os | ||
from pathlib import Path | ||
|
||
|
||
APP_DIR = os.path.abspath(os.path.dirname(__file__)) | ||
STATIC_FOLDER = os.path.join(APP_DIR, '../static/build/static') # Where your webpack build output folder is | ||
TEMPLATE_FOLDER = os.path.join(APP_DIR, '../static/build') # Where your index.html file is located | ||
STATIC_FOLDER = os.path.join( | ||
APP_DIR, "../static/build/static" | ||
) # Where your webpack build output folder is | ||
TEMPLATE_FOLDER = os.path.join( | ||
APP_DIR, "../static/build" | ||
) # Where your index.html file is located | ||
|
||
dotenv_path = Path(".") / ".env" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. dotenv It looks for .env in the root by default, so you shouldn't need this line. |
||
load_dotenv(dotenv_path) | ||
|
||
app = Flask(__name__, static_folder=STATIC_FOLDER, template_folder=TEMPLATE_FOLDER) | ||
app.config.from_object('app.config.ProductionConfig') | ||
app.config.from_object("app.config.ProductionConfig") | ||
|
||
bcrypt = Bcrypt(app) | ||
|
||
db = SQLAlchemy(app) | ||
bcrypt = Bcrypt(app) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,39 @@ | ||
import os | ||
|
||
from azure.identity import DefaultAzureCredential | ||
from azure.keyvault.secrets import SecretClient | ||
|
||
class BaseConfig(object): | ||
DEBUG = False | ||
SQLALCHEMY_TRACK_MODIFICATIONS = True | ||
|
||
|
||
class TestingConfig(BaseConfig): | ||
SQLALCHEMY_DATABASE_URI = 'sqlite:///db.sqlite3' | ||
# flaskreact app service as service principal | ||
AZURE_CLIENT_ID = os.getenv("AZURE_CLIENT_ID") | ||
AZURE_TENANT_ID = os.getenv("AZURE_TENANT_ID") | ||
AZURE_CLIENT_SECRET = os.getenv("AZURE_CLIENT_SECRET") | ||
KEY_VAULT_URL = os.getenv("KEY_VAULT_URL") | ||
|
||
credential = DefaultAzureCredential() | ||
secret_client = SecretClient(vault_url=KEY_VAULT_URL, credential=credential) | ||
|
||
COSMOS_DB_URI = secret_client.get_secret("cosmosURI").value | ||
SECRET_KEY = secret_client.get_secret("cosmosKey").value # key to cosmos | ||
|
||
DEBUG = True | ||
SECRET_KEY = 'somekey' | ||
|
||
|
||
class ProductionConfig(BaseConfig): | ||
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL', TestingConfig.SQLALCHEMY_DATABASE_URI) | ||
SECRET_KEY = os.environ.get('SECRET_KEY', TestingConfig.SECRET_KEY) | ||
|
||
# this is the key to cosmos db, but also used to make token for authentication purpose | ||
# probably shouldn't use the same key for different purposes and just let this key be the key to the db | ||
SECRET_KEY = TestingConfig.SECRET_KEY | ||
COSMOS_DB_URI = TestingConfig.COSMOS_DB_URI | ||
|
||
KEY_VAULT_URL = TestingConfig.KEY_VAULT_URL | ||
# created an app service on Portal (b/c eventually want to use App Service to host app) | ||
# creds returned by making that app a service principal | ||
# also, in order to use Identity, need a Service Principal | ||
AZURE_TENANT_ID = TestingConfig.AZURE_TENANT_ID | ||
AZURE_CLIENT_ID = TestingConfig.AZURE_CLIENT_ID | ||
AZURE_CLIENT_SECRET = TestingConfig.AZURE_CLIENT_SECRET | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Anytime you use 'cosmos' it should be "Cosmos DB" to adhere to branding