Skip to content

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

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 93 additions & 46 deletions README.md
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.
Copy link
Collaborator

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


## 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.
Copy link
Collaborator

Choose a reason for hiding this comment

The 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
Copy link
Collaborator

Choose a reason for hiding this comment

The 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
Copy link
Collaborator

Choose a reason for hiding this comment

The 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
Copy link
Collaborator

Choose a reason for hiding this comment

The 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
Copy link
Collaborator

Choose a reason for hiding this comment

The 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

Expand Down
22 changes: 15 additions & 7 deletions app/__init__.py
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"
Copy link
Collaborator

Choose a reason for hiding this comment

The 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)
33 changes: 27 additions & 6 deletions app/config.py
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

Loading