Skip to content

Commit cc478f5

Browse files
authored
Merge pull request #41 from CESNET/bugfix/session
Bugfix/session
2 parents 52cae97 + 1da865d commit cc478f5

File tree

6 files changed

+59
-79
lines changed

6 files changed

+59
-79
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ Last part of the system is Guarda service. This systemctl service is running in
5252
* [Local database instalation notes](./docs/DB_LOCAL.md)
5353

5454
## Change Log
55-
- 0.8.0 - API keys update. **Run migration scripts to update your DB**. Keys can now have expiration date and readonly flag. Admin can create special keys for certain machinnes.
55+
- 0.8.1 application is using Flask-Session stored in DB using SQL Alchemy driver. This can be configured for other
56+
drivers, however server side session is required for the application proper function.
57+
- 0.8.0 - API keys update. **Run migration scripts to update your DB**. Keys can now have expiration date and readonly flag. Admin can create special keys for certain machines.
5658
- 0.7.3 - New possibility of external auth proxy.
5759
- 0.7.2 - Dashboard and Main menu are now customizable in config. App is ready to be packaged using setup.py.
5860
- 0.7.0 - ExaAPI now have two options - HTTP or RabbitMQ. ExaAPI process has been renamed, update of ExaBGP process value is needed for this version.

flowapp/__about__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.8.0"
1+
__version__ = "0.8.1"

flowapp/__init__.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from flask_sqlalchemy import SQLAlchemy
77
from flask_wtf.csrf import CSRFProtect
88
from flask_migrate import Migrate
9+
from flask_session import Session
910

1011
from .__about__ import __version__
1112
from .instance_config import InstanceConfig
@@ -14,30 +15,34 @@
1415
db = SQLAlchemy()
1516
migrate = Migrate()
1617
csrf = CSRFProtect()
18+
ext = SSO()
19+
sess = Session()
1720

1821

19-
def create_app():
22+
def create_app(config_object=None):
2023
app = Flask(__name__)
21-
# Map SSO attributes from ADFS to session keys under session['user']
22-
#: Default attribute map
24+
25+
# SSO configuration
2326
SSO_ATTRIBUTE_MAP = {
2427
"eppn": (True, "eppn"),
2528
"cn": (False, "cn"),
2629
}
30+
app.config.setdefault("SSO_ATTRIBUTE_MAP", SSO_ATTRIBUTE_MAP)
31+
app.config.setdefault("SSO_LOGIN_URL", "/login")
2732

28-
# db.init_app(app)
33+
# extension init
2934
migrate.init_app(app, db)
3035
csrf.init_app(app)
3136

3237
# Load the default configuration for dashboard and main menu
3338
app.config.from_object(InstanceConfig)
39+
if config_object:
40+
app.config.from_object(config_object)
3441

3542
app.config.setdefault("VERSION", __version__)
36-
app.config.setdefault("SSO_ATTRIBUTE_MAP", SSO_ATTRIBUTE_MAP)
37-
app.config.setdefault("SSO_LOGIN_URL", "/login")
3843

39-
# This attaches the *flask_sso* login handler to the SSO_LOGIN_URL,
40-
ext = SSO(app=app)
44+
# Init SSO
45+
ext.init_app(app)
4146

4247
from flowapp import models, constants, validators
4348
from .views.admin import admin
@@ -85,7 +90,7 @@ def logout():
8590

8691
@app.route("/ext-login")
8792
def ext_login():
88-
header_name = app.config.get("AUTH_HEADER_NAME", 'X-Authenticated-User')
93+
header_name = app.config.get("AUTH_HEADER_NAME", "X-Authenticated-User")
8994
if header_name not in request.headers:
9095
return render_template("errors/401.html")
9196

@@ -148,9 +153,7 @@ def internal_error(exception):
148153
def utility_processor():
149154
def editable_rule(rule):
150155
if rule:
151-
validators.editable_range(
152-
rule, models.get_user_nets(session["user_id"])
153-
)
156+
validators.editable_range(rule, models.get_user_nets(session["user_id"]))
154157
return True
155158
return False
156159

@@ -176,20 +179,19 @@ def inject_dashboard():
176179
def format_datetime(value):
177180
if value is None:
178181
return app.config.get("MISSING_DATETIME_MESSAGE", "Never")
179-
182+
180183
format = "y/MM/dd HH:mm"
181184
return babel.dates.format_datetime(value, format)
182185

183186
def _register_user_to_session(uuid: str):
187+
print(f"Registering user {uuid} to session")
184188
user = db.session.query(models.User).filter_by(uuid=uuid).first()
185189
session["user_uuid"] = user.uuid
186190
session["user_email"] = user.uuid
187191
session["user_name"] = user.name
188192
session["user_id"] = user.id
189193
session["user_roles"] = [role.name for role in user.role.all()]
190-
session["user_orgs"] = ", ".join(
191-
org.name for org in user.organization.all()
192-
)
194+
session["user_orgs"] = ", ".join(org.name for org in user.organization.all())
193195
session["user_role_ids"] = [role.id for role in user.role.all()]
194196
session["user_org_ids"] = [org.id for org in user.organization.all()]
195197
roles = [i > 1 for i in session["user_role_ids"]]

flowapp/views/rules.py

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,7 @@ def reactivate_rule(rule_type, rule_id):
7373
form.net_ranges = get_user_nets(session["user_id"])
7474

7575
if rule_type > 2:
76-
form.action.choices = [
77-
(g.id, g.name) for g in db.session.query(Action).order_by("name")
78-
]
76+
form.action.choices = [(g.id, g.name) for g in db.session.query(Action).order_by("name")]
7977
form.action.data = model.action_id
8078

8179
if rule_type == 1:
@@ -256,9 +254,7 @@ def group_delete():
256254
"{} / {}".format(session["user_email"], session["user_orgs"]),
257255
)
258256

259-
db.session.query(model_name).filter(model_name.id.in_(to_delete)).delete(
260-
synchronize_session=False
261-
)
257+
db.session.query(model_name).filter(model_name.id.in_(to_delete)).delete(synchronize_session=False)
262258
db.session.commit()
263259

264260
flash("Rules {} deleted".format(to_delete), "alert-success")
@@ -309,9 +305,7 @@ def group_update():
309305
form = form_name(request.form)
310306
form.net_ranges = get_user_nets(session["user_id"])
311307
if rule_type_int > 2:
312-
form.action.choices = [
313-
(g.id, g.name) for g in db.session.query(Action).order_by("name")
314-
]
308+
form.action.choices = [(g.id, g.name) for g in db.session.query(Action).order_by("name")]
315309
if rule_type_int == 1:
316310
form.community.choices = get_user_communities(session["user_role_ids"])
317311

@@ -429,9 +423,7 @@ def ipv4_rule():
429423

430424
if model:
431425
model.expires = round_to_ten_minutes(form.expires.data)
432-
flash_message = (
433-
"Existing IPv4 Rule found. Expiration time was updated to new value."
434-
)
426+
flash_message = "Existing IPv4 Rule found. Expiration time was updated to new value."
435427
else:
436428
model = Flowspec4(
437429
source=form.source.data,
@@ -473,17 +465,12 @@ def ipv4_rule():
473465
else:
474466
for field, errors in form.errors.items():
475467
for error in errors:
476-
print(
477-
"Error in the %s field - %s"
478-
% (getattr(form, field).label.text, error)
479-
)
468+
print("Error in the %s field - %s" % (getattr(form, field).label.text, error))
480469

481470
default_expires = datetime.now() + timedelta(days=7)
482471
form.expires.data = default_expires
483472

484-
return render_template(
485-
"forms/ipv4_rule.html", form=form, action_url=url_for("rules.ipv4_rule")
486-
)
473+
return render_template("forms/ipv4_rule.html", form=form, action_url=url_for("rules.ipv4_rule"))
487474

488475

489476
@rules.route("/add_ipv6_rule", methods=["GET", "POST"])
@@ -507,9 +494,7 @@ def ipv6_rule():
507494

508495
if model:
509496
model.expires = round_to_ten_minutes(form.expires.data)
510-
flash_message = (
511-
"Existing IPv4 Rule found. Expiration time was updated to new value."
512-
)
497+
flash_message = "Existing IPv4 Rule found. Expiration time was updated to new value."
513498
else:
514499
model = Flowspec6(
515500
source=form.source.data,
@@ -550,17 +535,12 @@ def ipv6_rule():
550535
else:
551536
for field, errors in form.errors.items():
552537
for error in errors:
553-
print(
554-
"Error in the %s field - %s"
555-
% (getattr(form, field).label.text, error)
556-
)
538+
print("Error in the %s field - %s" % (getattr(form, field).label.text, error))
557539

558540
default_expires = datetime.now() + timedelta(days=7)
559541
form.expires.data = default_expires
560542

561-
return render_template(
562-
"forms/ipv6_rule.html", form=form, action_url=url_for("rules.ipv6_rule")
563-
)
543+
return render_template("forms/ipv6_rule.html", form=form, action_url=url_for("rules.ipv6_rule"))
564544

565545

566546
@rules.route("/add_rtbh_rule", methods=["GET", "POST"])
@@ -586,9 +566,7 @@ def rtbh_rule():
586566

587567
if model:
588568
model.expires = round_to_ten_minutes(form.expires.data)
589-
flash_message = (
590-
"Existing RTBH Rule found. Expiration time was updated to new value."
591-
)
569+
flash_message = "Existing RTBH Rule found. Expiration time was updated to new value."
592570
else:
593571
model = RTBH(
594572
ipv4=form.ipv4.data,
@@ -622,17 +600,12 @@ def rtbh_rule():
622600
else:
623601
for field, errors in form.errors.items():
624602
for error in errors:
625-
print(
626-
"Error in the %s field - %s"
627-
% (getattr(form, field).label.text, error)
628-
)
603+
print("Error in the %s field - %s" % (getattr(form, field).label.text, error))
629604

630605
default_expires = datetime.now() + timedelta(days=7)
631606
form.expires.data = default_expires
632607

633-
return render_template(
634-
"forms/rtbh_rule.html", form=form, action_url=url_for("rules.rtbh_rule")
635-
)
608+
return render_template("forms/rtbh_rule.html", form=form, action_url=url_for("rules.rtbh_rule"))
636609

637610

638611
@rules.route("/export")

requirements.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1-
Flask>=2.0.2
1+
Flask<3
22
Flask-SQLAlchemy>=2.2
33
Flask-SSO>=0.4.0
44
Flask-WTF>=1.0.0
55
Flask-Migrate>=3.0.0
66
Flask-Script>=2.0.0
7+
Flask-Session
78
PyJWT>=2.4.0
89
PyMySQL>=1.0.0
910
pytest>=7.0.0
1011
requests>=2.20.0
1112
babel>=2.7.0
12-
mysqlclient>=2.0.0
1313
email_validator>=1.1
1414
pika>=1.3.0
15+
mysqlclient>=2.0.0

run.example.py

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,42 @@
22
This is an example of how to run the application.
33
First copy the file as run.py (or whatever you want)
44
Then edit the file to match your needs.
5+
6+
From version 0.8.1 the application is using Flask-Session
7+
stored in DB using SQL Alchemy driver. This can be configured for other
8+
drivers, however server side session is required for the application.
9+
510
In general you should not need to edit this example file.
611
Only if you want to configure the application main menu and
7-
dashboard. Or in case that you want to add extensions etc.
12+
dashboard.
13+
14+
Or in case that you want to add extensions etc.
815
"""
916

1017
from os import environ
1118

12-
from flowapp import create_app, db
19+
from flowapp import create_app, db, sess
1320
import config
1421

1522

16-
# Call app factory
17-
app = create_app()
18-
1923
# Configurations
20-
env = environ.get('EXAFS_ENV', 'Production')
24+
env = environ.get("EXAFS_ENV", "Production")
2125

22-
if env == 'devel':
23-
app.config.from_object(config.DevelopmentConfig)
24-
app.config.update(
25-
DEVEL=True
26-
)
26+
# Call app factory
27+
if env == "devel":
28+
app = create_app(config.DevelopmentConfig)
2729
else:
28-
app.config.from_object(config.ProductionConfig)
29-
app.config.update(
30-
SESSION_COOKIE_SECURE=True,
31-
SESSION_COOKIE_HTTPONLY=True,
32-
SESSION_COOKIE_SAMESITE='Lax',
33-
DEVEL=False
34-
)
30+
app = create_app(config.ProductionConfig)
3531

3632
# init database object
3733
db.init_app(app)
3834

35+
# init session
36+
app.config.update(SESSION_TYPE="sqlalchemy")
37+
app.config.update(SESSION_SQLALCHEMY=db)
38+
sess.init_app(app)
39+
40+
3941
# run app
40-
if __name__ == '__main__':
41-
app.run(host='::', port=8080, debug=True)
42+
if __name__ == "__main__":
43+
app.run(host="127.0.0.1", port=8000, debug=True)

0 commit comments

Comments
 (0)