Browse Source

First tests

master
Alfred 1 year ago
parent
commit
9476a46091
13 changed files with 124 additions and 46 deletions
  1. 2
    1
      .gitignore
  2. 15
    5
      app.py
  3. 3
    0
      config.py
  4. 0
    16
      database.py
  5. 1
    0
      models/__init__.py
  6. 7
    6
      models/models.py
  7. 3
    1
      requirements/dev_requirements.txt
  8. 2
    2
      run.py
  9. 3
    0
      tests/__init__.py
  10. 40
    0
      tests/initialize.py
  11. 32
    0
      tests/test_application.py
  12. 14
    12
      views/application.py
  13. 2
    3
      views/main.py

+ 2
- 1
.gitignore View File

@@ -3,4 +3,5 @@
3 3
 env
4 4
 venv
5 5
 .idea/
6
-.configs/
6
+.configs/
7
+database.db

+ 15
- 5
app.py View File

@@ -3,13 +3,23 @@
3 3
 
4 4
 
5 5
 from flask import Flask
6
+from flask_sqlalchemy import SQLAlchemy
6 7
 import os
7
-from database import init_db
8
+
8 9
 
9 10
 app = Flask(__name__)
11
+db = None
10 12
 
11
-app.config.from_object('config')
12
-if 'JAWTH_CONFIG' in os.environ.keys():
13
-    app.config.from_envvar('JAWTH_CONFIG')
14 13
 
15
-init_db()
14
+def initialize_app(config=None):
15
+    global db
16
+    if not config:
17
+        app.config.from_object('config')
18
+    else:
19
+        app.config.update(**config)
20
+    if 'JAWTH_CONFIG' in os.environ.keys():
21
+        app.config.from_envvar('JAWTH_CONFIG')
22
+    db = SQLAlchemy(app)
23
+    import models.models
24
+    db.create_all()
25
+    import views

+ 3
- 0
config.py View File

@@ -13,3 +13,6 @@ JAWTH_KEY = 'JAWTHPASSWORD'
13 13
 
14 14
 # Connect to the database
15 15
 SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'database.db')
16
+
17
+ENV = 'development'
18
+SQLALCHEMY_TRACK_MODIFICATIONS = False

+ 0
- 16
database.py View File

@@ -1,16 +0,0 @@
1
-#!/usr/bin/env python
2
-# -*- coding: utf-8 -*-
3
-
4
-from sqlalchemy import create_engine
5
-from sqlalchemy.orm import scoped_session, sessionmaker
6
-from sqlalchemy.ext.declarative import declarative_base
7
-
8
-engine = create_engine('sqlite:////tmp/test.db', convert_unicode=True)
9
-db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
10
-Base = declarative_base()
11
-Base.query = db_session.query_property()
12
-
13
-
14
-def init_db():
15
-    import models.models
16
-    Base.metadata.create_all(bind=engine)

+ 1
- 0
models/__init__.py View File

@@ -1,3 +1,4 @@
1 1
 #!/usr/bin/env python
2 2
 # -*- coding: utf-8 -*-
3 3
 
4
+from models import *

+ 7
- 6
models/models.py View File

@@ -4,34 +4,35 @@
4 4
 
5 5
 from sqlalchemy import Column, Integer, String, ForeignKey
6 6
 from sqlalchemy.orm import relationship
7
-from database import Base
7
+from app import db
8 8
 
9 9
 
10
-class Application(Base):
10
+class Application(db.Model):
11 11
     __tablename__ = 'applications'
12 12
     id = Column(Integer, primary_key=True)
13 13
     name = Column(String(50), unique=True)
14 14
     secret = Column(String(120), unique=True)
15 15
     users = relationship("User")
16 16
 
17
-    def __init__(self, name=None, email=None):
17
+    def __init__(self, name=None, secret=None):
18 18
         self.name = name
19
-        self.email = email
19
+        self.secret = secret
20 20
 
21 21
     def __repr__(self):
22 22
         return '<Application %r>' % self.name
23 23
 
24 24
 
25
-class User(Base):
25
+class User(db.Model):
26 26
     __tablename__ = 'users'
27 27
     id = Column(Integer, primary_key=True)
28 28
     app = Column(Integer, ForeignKey('applications.id'))
29 29
     username = Column(String(50))
30 30
     password = Column(String(120))
31 31
 
32
-    def __init__(self, username=None, password=None):
32
+    def __init__(self, username=None, password=None, app=None):
33 33
         self.username = username
34 34
         self.password = password
35
+        self.app = app
35 36
 
36 37
     def __repr__(self):
37 38
         return '<User %r>' % self.username

+ 3
- 1
requirements/dev_requirements.txt View File

@@ -1 +1,3 @@
1
--r base_requirements.txt
1
+-r base_requirements.txt
2
+
3
+pytest

+ 2
- 2
run.py View File

@@ -1,8 +1,8 @@
1 1
 #!/usr/bin/env python
2 2
 # -*- coding: utf-8 -*-
3 3
 
4
-from app import app
5
-import views
4
+from app import app, initialize_app
6 5
 
7 6
 if __name__ == '__main__':
7
+    initialize_app()
8 8
     app.run()

+ 3
- 0
tests/__init__.py View File

@@ -0,0 +1,3 @@
1
+#!/usr/bin/env python
2
+# -*- coding: utf-8 -*-
3
+

+ 40
- 0
tests/initialize.py View File

@@ -0,0 +1,40 @@
1
+#!/usr/bin/env python
2
+# -*- coding: utf-8 -*-
3
+
4
+from app import app, initialize_app
5
+
6
+
7
+test_config = {
8
+    'TESTING': True,
9
+    'SQLALCHEMY_DATABASE_URI': "sqlite://",
10
+    'SQLALCHEMY_TRACK_MODIFICATIONS': False,
11
+    'SECRET_KEY': 'JAWTHSECRETKEY',
12
+    'JAWTH_KEY': 'JAWTHPASSWORD',
13
+    'ENV': 'Test'
14
+}
15
+
16
+
17
+def create_test_data():
18
+    from app import db
19
+    from models import models as models
20
+
21
+    models.User.query.delete()
22
+    models.Application.query.delete()
23
+
24
+    app1 = models.Application(name='apptest1', secret='apptest1apptest1')
25
+    app2 = models.Application(name='apptest2', secret='apptest2apptest2')
26
+    db.session.add(app1)
27
+    db.session.add(app2)
28
+    db.session.commit()
29
+    for n in range(10):
30
+        _app = app1 if n % 2 == 1 else app2
31
+        db.session.add(models.User(username='user%d' % n, password='user%dpass' % n, app=_app.id))
32
+    db.session.commit()
33
+
34
+
35
+def initialize_testing():
36
+    initialize_app(test_config)
37
+    client = app.test_client()
38
+    with app.app_context():
39
+        create_test_data()
40
+    return client

+ 32
- 0
tests/test_application.py View File

@@ -0,0 +1,32 @@
1
+#!/usr/bin/env python
2
+# -*- coding: utf-8 -*-
3
+
4
+import unittest
5
+from tests.initialize import initialize_testing, test_config
6
+import jwt
7
+import json
8
+
9
+app = initialize_testing()
10
+
11
+
12
+class FlaskrTestCase(unittest.TestCase):
13
+    def setUp(self):
14
+        self.app = app
15
+
16
+    def tearDown(self):
17
+        pass
18
+
19
+    def test_list_users(self):
20
+        encoded = jwt.encode({'password': test_config['JAWTH_KEY']}, test_config['SECRET_KEY'], algorithm='HS256')
21
+        res = self.app.get('/users', data=None, headers={'auth': 'jwt ' + encoded.decode("utf-8")})
22
+        assert res.status_code == 200
23
+
24
+    def test_list_users_unauthorized_JAWTH_KEY(self):
25
+        encoded = jwt.encode({'password': 'IDONTKNOWJAWTH_KEY'}, test_config['SECRET_KEY'], algorithm='HS256')
26
+        res = self.app.get('/users', data=None, headers={'auth': 'jwt ' + encoded.decode("utf-8")})
27
+        assert res.status_code == 401
28
+
29
+    def test_list_users_unauthorized_SECRET_KEY(self):
30
+        encoded = jwt.encode({'password': test_config['JAWTH_KEY']}, 'IDONTKNOWSECRETKEY', algorithm='HS256')
31
+        res = self.app.get('/users', data=None, headers={'auth': 'jwt ' + encoded.decode("utf-8")})
32
+        assert res.status_code == 401

+ 14
- 12
views/application.py View File

@@ -1,23 +1,25 @@
1 1
 #!/usr/bin/env python
2 2
 # -*- coding: utf-8 -*-
3 3
 
4
-from app import app
4
+from app import app, db
5 5
 from flask import request, abort
6 6
 import jwt
7 7
 import models.models as models
8
-from database import db_session
9 8
 
10 9
 
11 10
 def check_auth():
12 11
     auth = request.headers.get('auth', None)
13 12
     if not auth or not auth.startswith('jwt '):
14 13
         abort(401)
15
-    auth = jwt.decode(auth[len('jwt '):], app.config.get('SECRET_KEY'), algorithms=['HS256'])
16
-    if auth.get('password', '') != app.config.get('JAWTH_KEY', None):
17
-        abort(401)
18
-    if request.method == 'GET':
19
-        return
20
-    if auth.get('data', None) != request.get_json():
14
+    try:
15
+        auth = jwt.decode(auth[len('jwt '):], app.config.get('SECRET_KEY'), algorithms=['HS256'])
16
+        if auth.get('password', '') != app.config.get('JAWTH_KEY', None):
17
+            abort(401)
18
+        if request.method == 'GET':
19
+            return
20
+        if auth.get('data', None) != request.get_json():
21
+            abort(401)
22
+    except jwt.exceptions.InvalidSignatureError:
21 23
         abort(401)
22 24
 
23 25
 
@@ -45,8 +47,8 @@ def users():
45 47
     if request.method == 'GET':
46 48
         return 'yeah'
47 49
     elif request.method == 'POST':
48
-        db_session.add(models.User(**request.get_json()))
49
-        db_session.commit()
50
+        db.session.add(models.User(**request.get_json()))
51
+        db.session.commit()
50 52
         return '', 201
51 53
     elif request.method == 'PATCH':
52 54
         pass
@@ -62,8 +64,8 @@ def change_password(application, username):
62 64
         abort(401)
63 65
     user = models.User.query.filter(models.User.username == username, models.User.app == app.id).first()
64 66
     user.password = request.data.get('password')
65
-    db_session.add(user)
66
-    db_session.commit()
67
+    db.session.add(user)
68
+    db.session.commit()
67 69
 
68 70
 
69 71
 def update_application():

+ 2
- 3
views/main.py View File

@@ -1,14 +1,13 @@
1 1
 #!/usr/bin/env python
2 2
 # -*- coding: utf-8 -*-
3 3
 
4
-from app import app
4
+from app import app, db
5 5
 from flask import Response
6
-from database import db_session
7 6
 
8 7
 
9 8
 @app.teardown_appcontext
10 9
 def shutdown_session(exception=None):
11
-    db_session.remove()
10
+    db.session.remove()
12 11
 
13 12
 
14 13
 @app.errorhandler(500)

Loading…
Cancel
Save