initial commit
This commit is contained in:
38
app.py
Normal file
38
app.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import sqlite3
|
||||
|
||||
from flask import Flask, render_template, request, url_for, flash, redirect
|
||||
from werkzeug.exceptions import abort
|
||||
|
||||
|
||||
def get_db_connection():
|
||||
conn = sqlite3.connect('database.db')
|
||||
conn.row_factory = sqlite3.Row
|
||||
return conn
|
||||
|
||||
def get_post(post_id):
|
||||
conn = get_db_connection()
|
||||
post = conn.execute('SELECT * FROM posts WHERE id = ?',
|
||||
(post_id,)).fetchone()
|
||||
conn.close()
|
||||
if post is None:
|
||||
abort(404)
|
||||
return post
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
# app.config['SECRET_KEY'] = 'hello'
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
conn = get_db_connection()
|
||||
posts = conn.execute('SELECT * FROM posts').fetchall()
|
||||
conn.close()
|
||||
|
||||
return render_template('index.html', posts=posts)
|
||||
|
||||
@app.route('/<int:event_id>')
|
||||
def post(post_id):
|
||||
post = get_post(post_id)
|
||||
return render_template('calendar.html', post=post)
|
||||
|
||||
|
||||
82
calendar_interface.py
Normal file
82
calendar_interface.py
Normal file
@@ -0,0 +1,82 @@
|
||||
|
||||
import json
|
||||
from lib2to3.pgen2.tokenize import TokenError
|
||||
import logging
|
||||
|
||||
import requests
|
||||
import msal
|
||||
|
||||
config = {
|
||||
"authority": "https://login.microsoftonline.com/propedal.at",
|
||||
"client_id": "52f192c4-875d-44a2-b28a-575e920225e5", # client public id (from azure web interface)#"da3fc28c-5fcf-4884-9477-903a4420cc3d",
|
||||
"scope": ["https://graph.microsoft.com/.default"], # scopes from api
|
||||
"secret": "irj8Q~PliZzSe7JnXEaiWKQ6v0CAg1DTZOO~Ccsf" # api secret key (from azure web interface)#"bqP8Q~SEp_AmYYDZoEykXxZdADoCOhzOOhbO3c3T"
|
||||
}
|
||||
USER_ID = "simone.profus@propedal.at" # user with calendar #"2af02ca1-77fc-46fd-90af-c754306081cb" #
|
||||
CALENDAR_ID = "AAMkADY0MDg1MTVjLTg5ZjItNGQxYS04MGQ3LWY2NjJmYjM0YmZhOQBGAAAAAADXD7SdVoWYQI4RYXbBumMEBwAf_ngZxs71RonY3GuLL8TVAAAAAAEGAAAf_ngZxs71RonY3GuLL8TVAADHFxN2AAA=" # calendar id - determined by /users/id/calendars
|
||||
|
||||
# Optional logging
|
||||
logging.basicConfig(format='%(asctime)s,%(msecs)d %(levelname)-4s [%(filename)s:%(lineno)d] %(message)s',
|
||||
datefmt='%Y-%m-%d:%H:%M:%S',
|
||||
level=logging.INFO)
|
||||
# logging.getLogger("msal").setLevel(logging.INFO) # Optionally disable MSAL DEBUG logs
|
||||
|
||||
def get_access_token():
|
||||
#with open("auth_config.json") as f:
|
||||
# config = json.load(f)
|
||||
|
||||
# Create a preferably long-lived app instance which maintains a token cache.
|
||||
app = msal.ConfidentialClientApplication(
|
||||
config["client_id"], authority=config["authority"],
|
||||
client_credential=config["secret"],
|
||||
# token_cache=... # Default cache is in memory only.
|
||||
# You can learn how to use SerializableTokenCache from
|
||||
# https:#msal-python.readthedocs.io/en/latest/#msal.SerializableTokenCache
|
||||
)
|
||||
|
||||
# The pattern to acquire a token looks like this.
|
||||
result = None
|
||||
|
||||
# Firstly, looks up a token from cache
|
||||
# Since we are looking for token for the current app, NOT for an end user,
|
||||
# notice we give account parameter as None. # TODO: token never exists in cache; make app long living
|
||||
result = app.acquire_token_silent(config["scope"], account=None)
|
||||
|
||||
if result is None:
|
||||
logging.info("No suitable token exists in cache. Let's get a new one from AAD.")
|
||||
return app.acquire_token_for_client(scopes=config["scope"])
|
||||
else:
|
||||
logging.info("Token was found in cache.")
|
||||
|
||||
if not "access_token" in result: # a final check
|
||||
logging.error(result.get("error"))
|
||||
logging.error(result.get("error_description"))
|
||||
logging.error(result.get("correlation_id")) # You may need this when reporting a bug
|
||||
raise TokenError()
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def execute_request(token: dict, endpoint:str):
|
||||
return requests.get( # Use token to call downstream service
|
||||
endpoint,
|
||||
headers={'Authorization': 'Bearer ' + token['access_token']},).json()
|
||||
|
||||
def execute_user_request(token, endpoint, user_id=USER_ID):
|
||||
return execute_request(token, "https://graph.microsoft.com/v1.0/users/" + user_id + f"/{endpoint}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Calling graph using the access token
|
||||
token = get_access_token()
|
||||
|
||||
calendars = execute_user_request(token, "calendars")
|
||||
cal_name_id = [(c["name"], c["id"]) for c in calendars["value"]]
|
||||
|
||||
print("Available calendars are:")
|
||||
print(json.dumps(cal_name_id, indent=2))
|
||||
|
||||
print("Events in selected calendar are:")
|
||||
events = execute_user_request(token, f"calendars/{CALENDAR_ID}/events").get("value")
|
||||
print(json.dumps(events, indent=2))
|
||||
|
||||
43
templates/base.html
Normal file
43
templates/base.html
Normal file
@@ -0,0 +1,43 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
|
||||
<!-- Bootstrap CSS -->
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||
|
||||
<title>{% block title %} {% endblock %}</title>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-md navbar-light bg-light">
|
||||
<a class="navbar-brand" href="{{ url_for('index')}}">FlaskBlog</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item active">
|
||||
<a class="nav-link" href="#">About</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{url_for('create')}}">New Post</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="container">
|
||||
{% for message in get_flashed_messages() %}
|
||||
<div class="alert alert-danger">{{ message }}</div>
|
||||
{% endfor %}
|
||||
{% block content %} {% endblock %}
|
||||
</div>
|
||||
|
||||
<!-- Optional JavaScript -->
|
||||
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
|
||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
||||
17
templates/index.html
Normal file
17
templates/index.html
Normal file
@@ -0,0 +1,17 @@
|
||||
<!-- {% extends 'base.html' %} -->
|
||||
|
||||
{% block content %}
|
||||
<h1>{% block title %} Welcome to FlaskBlog {% endblock %}</h1>
|
||||
{% for post in posts %}
|
||||
<a href="{{ url_for('post', post_id=post['id']) }}">
|
||||
<h2>{{ post['title'] }}</h2>
|
||||
</a>
|
||||
<span class="badge badge-primary">{{ post['created'] }}</span>
|
||||
|
||||
<a href="{{ url_for('edit', id=post['id']) }}">
|
||||
<span class="badge badge-warning">Edit</span>
|
||||
</a>
|
||||
<hr>
|
||||
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
7
templates/post.html
Normal file
7
templates/post.html
Normal file
@@ -0,0 +1,7 @@
|
||||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<h2>{% block title %} {{ post['title'] }} {% endblock %}</h2>
|
||||
<span class="badge badge-primary">{{ post['created'] }}</span>
|
||||
<p>{{ post['content'] }}</p>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user