Skip to content

Commit c600807

Browse files
authored
Merge pull request #78 from bmarsh9/gh-73-v1
Gh 73 v1
2 parents 8b16476 + b9b87f7 commit c600807

22 files changed

+574
-137
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ env/*
33
migrations
44
*pyc
55
app/files/reports/*
6+
app/files/evidence/*
67
# C extensions
78
*.so
89

WORKER.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,11 @@ from app.models import *
5151
# create tenant
5252
user = User.query.get(1)
5353
tenant = Tenant.create(user, "demo", user.email)
54+
project = tenant.create_project("sample", user)
5455
5556
# create integration and task
56-
integration = Integration(name="github", tenant_id=tenant.id)
57-
integration.add_task(name="get_users", cron="* * * * *")
57+
integration = project.add_integration(name="github")
58+
task = integration.add_task(name="get_users", cron="* * * * *")
5859
5960
# create locker
6061
Locker.add("test","value", tenant.id)
@@ -69,3 +70,14 @@ bg_app.open()
6970
[print(i) for i in BgHelper().list_jobs()]
7071
```
7172

73+
###### Testing task
74+
75+
```
76+
# create task in the import_path
77+
python3 manage.py shell
78+
from app.utils.bg_helper import BgHelper
79+
BgHelper().test_task("github:get_users")
80+
81+
# open new shell
82+
INTEGRATION_IMPORT_PATHS="app.integrations.github.tasks" AS_WORKER=yes bash run.sh
83+
```

app/__init__.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,14 @@ def internal_error(e):
6565
return render_template("layouts/errors/default.html", title="Internal error"), e.code
6666

6767
@app.errorhandler(exc.SQLAlchemyError)
68-
def handle_db_exceptions(error):
69-
app.logger.warning("Rolling back database session in app")
68+
def handle_db_exceptions(e):
69+
error = str(e)
70+
app.logger.warning(f"Rolling back database session in app: {error}")
7071
db.session.rollback()
72+
if request.path.startswith("/api/"):
73+
return jsonify({"ok":False, "message":error, "code":500}), 500
74+
return render_template("layouts/errors/default.html", title="Internal error"), 500
75+
7176

7277
def to_pretty_json(value):
7378
return json.dumps(value, sort_keys=True,

app/api_v1/views.py

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
from app.utils.bg_helper import BgHelper
1313
from app.utils.reports import Report
1414
from app.utils.authorizer import Authorizer
15+
from werkzeug.utils import secure_filename
16+
import os
1517

1618

1719
@api.route('/health', methods=['GET'])
@@ -35,8 +37,7 @@ def set_session(id):
3537
@login_required
3638
def delete_tenant(id):
3739
result = Authorizer(current_user).can_user_admin_tenant(id)
38-
db.session.delete(result["extra"]["tenant"])
39-
db.session.commit()
40+
result["extra"]["tenant"].delete()
4041
return jsonify({"message": "ok"})
4142

4243
@api.route('/questionnaires/<int:qid>', methods=['GET'])
@@ -252,6 +253,24 @@ def get_comments_for_project(pid):
252253
data = [comment.as_dict() for comment in result["extra"]["project"].comments.order_by(models.ProjectComment.id.asc()).all()]
253254
return jsonify(data)
254255

256+
@api.route('/projects/<int:pid>/findings', methods=['GET'])
257+
@login_required
258+
def get_findings_for_project(pid):
259+
result = Authorizer(current_user).can_user_manage_project(pid)
260+
data = [finding.as_dict() for finding in result["extra"]["project"].findings.all()]
261+
return jsonify(data)
262+
263+
@api.route('/projects/<int:pid>/integrations', methods=['GET'])
264+
@login_required
265+
def get_integrations_for_project(pid):
266+
result = Authorizer(current_user).can_user_manage_project(pid)
267+
# include all available integrations
268+
summary = request.args.get("summary")
269+
if summary == "yes":
270+
return jsonify(result["extra"]["project"].get_integration_summary())
271+
data = [integration.as_dict() for integration in result["extra"]["project"].integrations.all()]
272+
return jsonify(data)
273+
255274
@api.route('/projects/<int:pid>/matrix/summary', methods=['GET'])
256275
@login_required
257276
def get_resp_matrix_summary_for_project(pid):
@@ -649,33 +668,34 @@ def get_evidence(eid):
649668
@login_required
650669
def add_evidence_for_tenant(tid):
651670
result = Authorizer(current_user).can_user_manage_tenant(tid)
652-
payload = request.get_json()
653-
evidence = models.Evidence(name=payload["name"],
654-
description=payload["description"],
655-
content=payload["content"],owner_id=current_user.id,
656-
collected_on=payload["collected"] or None)
671+
evidence = models.Evidence(name=request.form.get("name"),
672+
description=request.form.get("description"),
673+
content=request.form.get("content"),owner_id=current_user.id,
674+
collected_on=request.form.get("collected") or arrow.utcnow().format("MM/DD/YYYY"))
657675
result["extra"]["tenant"].evidence.append(evidence)
658676
db.session.commit()
677+
evidence.diff_files_with_checks(request.files.getlist("file"), execute=True)
659678
return jsonify(evidence.as_dict())
660679

661680
@api.route('/evidence/<int:eid>', methods=['PUT'])
662681
@login_required
663682
def update_evidence(eid):
664683
result = Authorizer(current_user).can_user_manage_evidence(eid)
665-
payload = request.get_json()
666-
result["extra"]["evidence"].name = payload["name"]
667-
result["extra"]["evidence"].description = payload["description"]
668-
result["extra"]["evidence"].content = payload["content"]
669-
result["extra"]["evidence"].collected_on = payload["collected"]
684+
evidence = result["extra"]["evidence"]
685+
evidence.name = request.form.get("name")
686+
evidence.description = request.form.get("description")
687+
evidence.content = request.form.get("content")
688+
if request.form.get("collected"):
689+
evidence.collected_on = request.form.get("collected")
670690
db.session.commit()
671-
return jsonify(result["extra"]["evidence"].as_dict())
691+
evidence.diff_files_with_checks(request.files.getlist("file"), execute=True)
692+
return jsonify(evidence.as_dict())
672693

673694
@api.route('/evidence/<int:eid>', methods=['DELETE'])
674695
@login_required
675696
def delete_evidence(eid):
676697
result = Authorizer(current_user).can_user_manage_evidence(eid)
677-
db.session.delete(result["extra"]["evidence"])
678-
db.session.commit()
698+
result["extra"]["evidence"].delete()
679699
return jsonify({"message": "ok"})
680700

681701
@api.route('/evidence/<int:eid>/controls', methods=['PUT'])
@@ -1192,13 +1212,13 @@ def get_evidence_for_subcontrol(pid, sid):
11921212
@login_required
11931213
def add_evidence_for_subcontrol(pid, sid):
11941214
result = Authorizer(current_user).can_user_manage_project_subcontrol(sid)
1195-
data = request.get_json()
1196-
evidence = models.Evidence(name=data["name"],
1197-
content=data["content"],description=data["description"],
1215+
evidence = models.Evidence(name=request.form.get("name"),
1216+
content=request.form.get("content"),description=request.form.get("description"),
11981217
tenant_id=result["extra"]["subcontrol"].p_control.project.tenant_id,
11991218
owner_id=current_user.id)
12001219
result["extra"]["subcontrol"].evidence.append(evidence)
12011220
db.session.commit()
1221+
evidence.diff_files_with_checks(request.files.getlist("file"), execute=True)
12021222
return jsonify(evidence.as_dict())
12031223

12041224
@api.route('/projects/<int:pid>/subcontrols/<int:sid>/evidence/<int:eid>', methods=["DELETE"])

app/integrations/DEVELOPMENT.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ task.sort_results(sort="version")
3030
3131
# Get result by specific version
3232
task.get_result_by_version("1.1.1")
33+
34+
# Add finding
35+
task.add_finding(title="testing the title2",risk=7,status="in progress")
3336
```
3437

3538

app/integrations/github/tasks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from app.integrations.utils.decorators import task
22
from app.integrations.utils import shared
33
from flask import current_app
4-
from app.models import Finding
4+
from app.models import Finding, Task
55
from app import db
66

77
# integration imports

app/integrations/utils/decorators.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,15 @@ def new_func(*job_args, **job_kwargs):
1212
add the Task object and the lockers that
1313
the task has access to
1414
"""
15-
task = Task.query.get(job_kwargs["id"])
16-
lockers = task.integration.get_lockers()
17-
lock = task.get_lock()
15+
# testing a task
16+
if job_kwargs["id"] == "test":
17+
task = None
18+
lockers = []
19+
lock = "test"
20+
else:
21+
task = Task.query.get(job_kwargs["id"])
22+
lockers = task.integration.get_lockers()
23+
lock = task.get_lock()
1824

1925
logging.info(f"Starting task: {lock}")
2026
result = func(task, lockers, *job_args, **job_kwargs)

app/main/views.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ def view_framework(name):
6363
def evidence():
6464
return render_template("evidence.html")
6565

66+
@main.route('/evidence/<int:eid>/files/<string:name>', methods=['GET'])
67+
@login_required
68+
def view_file_for_evidence(eid, name):
69+
result = Authorizer(current_user).can_user_read_evidence(eid)
70+
if name.lower() not in result["extra"]["evidence"].get_files(basename=True):
71+
abort(404)
72+
return send_from_directory(directory=result["extra"]["evidence"].tenant.get_evidence_folder(),
73+
path=name, as_attachment=True)
74+
6675
@main.route('/policies', methods=['GET'])
6776
@login_required
6877
def policies():

0 commit comments

Comments
 (0)