Skip to content

Commit

Permalink
Authentication for user delete endpoints; Cascade deletes for user re…
Browse files Browse the repository at this point in the history
…moval; BIs are now unique; Remove wave functions; System console node-red logs
  • Loading branch information
MartinHeinz committed Mar 23, 2019
1 parent dd6e968 commit 73ec333
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 93 deletions.
8 changes: 5 additions & 3 deletions app/app/auth/_flask.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
from app.app_setup import db
from app.auth import login, login_aa, remote_aa, nonce_key_aa, backend_aa
from app.auth import remote as remote_app, nonce_key as nonce_key_app, backend as backend_app
from app.auth.utils import handle_authorize, token_to_hash
from app.auth.utils import handle_authorize, token_to_hash, require_api_token
from app.models.models import AttrAuthUser, User
from app.utils import http_json_response


@login_aa.route('/delete_account', methods=['POST'])
def delete_account_aa(): # TODO Check if user exists
@require_api_token("attr_auth")
def delete_account_aa():
user = AttrAuthUser.get_by_access_token(token_to_hash(request.headers.get('Authorization', "")))
db.session.delete(user)
db.session.commit()
Expand All @@ -19,7 +20,8 @@ def delete_account_aa(): # TODO Check if user exists


@login.route('/delete_account', methods=['POST'])
def delete_account(): # TODO Check if user exists
@require_api_token()
def delete_account():
user = User.get_by_access_token(token_to_hash(request.headers.get('Authorization', "")))
db.session.delete(user)
db.session.commit()
Expand Down
18 changes: 9 additions & 9 deletions app/app/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@

class UserDevice(db.Model):
__tablename__ = 'user_device'
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True)
device_id = db.Column(db.Integer, db.ForeignKey('device.id'), primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id', ondelete='CASCADE'), primary_key=True)
device_id = db.Column(db.Integer, db.ForeignKey('device.id', ondelete='CASCADE'), primary_key=True)
device_public_session_key = db.Column(db.String(250))
added = db.Column(db.DateTime(timezone=True), onupdate=datetime.datetime.now)
device = relationship("Device", back_populates="users")
Expand Down Expand Up @@ -122,7 +122,7 @@ class Device(MixinGetById, MixinAsDict, db.Model):
mqtt_creds = relationship("MQTTUser", uselist=False, back_populates="device", cascade='all,delete')

name = db.Column(db.LargeBinary, nullable=False)
name_bi = db.Column(db.String(200), unique=False, nullable=True, index=True) # Blind index for .name
name_bi = db.Column(db.String(200), unique=True, nullable=True, index=True) # Blind index for .name

correctness_hash = db.Column(db.String(200), nullable=False) # correctness_hash("name")

Expand Down Expand Up @@ -194,7 +194,7 @@ class ACL(db.Model):
__table_args__ = {'extend_existing': True}

id = db.Column(db.Integer, primary_key=True)
mqtt_user_id = db.Column(db.Integer, db.ForeignKey('mqtt_user.id'))
mqtt_user_id = db.Column(db.Integer, db.ForeignKey('mqtt_user.id', ondelete='CASCADE'))
mqtt_user = relationship("MQTTUser", back_populates="acls")
username = db.Column(db.String(200), nullable=False) # TODO make this primary key (as pair with id or remove it)
topic = db.Column(db.String(200), unique=False, nullable=True)
Expand All @@ -210,10 +210,10 @@ class DeviceData(MixinAsDict, db.Model):
added = db.Column(db.BigInteger)
num_data = db.Column(db.BigInteger)
data = db.Column(db.LargeBinary)
device_id = db.Column(db.Integer, db.ForeignKey('device.id'))
device_id = db.Column(db.Integer, db.ForeignKey('device.id', ondelete='CASCADE'))
device = relationship("Device", back_populates="data")

tid_bi = db.Column(db.String(200), unique=False, nullable=True, index=True) # Blind index for .tid
tid_bi = db.Column(db.String(200), unique=True, nullable=True, index=True) # Blind index for .tid

correctness_hash = db.Column(db.String(200), nullable=False) # correctness_hash(str(985734000), b'\\001'.decode("utf-8"), str(66988873), str(tid))

Expand All @@ -232,10 +232,10 @@ class Action(MixinGetById, db.Model):

id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.LargeBinary, nullable=False)
device_id = db.Column(db.Integer, db.ForeignKey('device.id'))
device_id = db.Column(db.Integer, db.ForeignKey('device.id', ondelete='CASCADE'))
device = relationship("Device", back_populates="actions")

name_bi = db.Column(db.String(200), unique=False, nullable=True, index=True) # Blind index for .name
name_bi = db.Column(db.String(200), unique=True, nullable=True, index=True) # Blind index for .name

correctness_hash = db.Column(db.String(200), nullable=False) # correctness_hash("name")

Expand Down Expand Up @@ -264,7 +264,7 @@ class Scene(db.Model):

correctness_hash = db.Column(db.String(200), nullable=False) # correctness_hash("name", "description")

name_bi = db.Column(db.String(200), unique=False, nullable=True, index=True) # Blind index for .name
name_bi = db.Column(db.String(200), unique=True, nullable=True, index=True) # Blind index for .name

@hybrid_property
def owner(self):
Expand Down
47 changes: 0 additions & 47 deletions client/crypto_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from passlib.hash import bcrypt
from pyope.ope import OPE, ValueRange
from scipy import signal
import numpy as np

sys.stdout = open(os.devnull, 'w')
sys.path.insert(0, './app')
Expand Down Expand Up @@ -94,51 +92,6 @@ def derive_key(key):
).derive(key)


"""
To see the lists of values:
print(list(triangle_wave()))
print(list(sawtooth_wave()))
print(list(square_wave()))
print(list(sine_wave()))
To plot:
import matplotlib.pyplot as plt
t = np.linspace(0, 100, 500)
triangle = signal.sawtooth(10 * np.pi * 5 * t, 0.5)
plt.plot(t, triangle)
plt.show()
"""


def triangle_wave():
t = np.linspace(0, 100, 500)
triangle = signal.sawtooth(10 * np.pi * 5 * t, 0.5)
yield from (int(round(x, 4)*1000) for x in triangle.tolist())


def sawtooth_wave():
t = np.linspace(0, 100, 500)
sawtooth = signal.sawtooth(10 * np.pi * 5 * t)
yield from (int(round(x, 4)*1000) for x in sawtooth.tolist())


def square_wave():
t = np.linspace(0, 100, 500)
square = signal.square(8 * np.pi * 5 * t)
yield from (int(round(x, 4)*1000) for x in square.tolist())


def sine_wave():
t = np.linspace(0, 32 * np.pi, 500)
sine = np.sin(t)
yield from (int(round(x, 4)*1000) for x in sine.tolist())


def index_function():
yield from range(1, 500)


def generate(columns, bound="upper_bound"):
"""
:param bound: whether to use lower or upper bound
Expand Down
4 changes: 2 additions & 2 deletions client/device/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@
sys.stdout = sys.__stdout__

try: # for packaged CLI (setup.py)
from client.crypto_utils import triangle_wave, sawtooth_wave, square_wave, sine_wave, generate, encrypt_row, index_function, \
from client.crypto_utils import generate, encrypt_row, \
hex_to_key, key_to_hex, hex_to_fernet, decrypt_using_fernet_hex, get_random_seed, blind_index, encrypt_using_abe_serialized_key, hex_to_ope, \
correctness_hash, pad_payload_attr, encrypt_using_fernet_hex
from client.utils import get_tinydb_table, search_tinydb_doc, is_number
except ImportError: # pragma: no un-packaged CLI cover
from crypto_utils import triangle_wave, sawtooth_wave, square_wave, sine_wave, generate, encrypt_row, index_function, \
from crypto_utils import generate, encrypt_row, \
hex_to_key, key_to_hex, hex_to_fernet, decrypt_using_fernet_hex, get_random_seed, blind_index, \
correctness_hash, pad_payload_attr, encrypt_using_fernet_hex
from utils import get_tinydb_table, search_tinydb_doc, is_number
Expand Down
8 changes: 7 additions & 1 deletion client/user/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ def register_to_broker(password, token):
@click.option('--token', envvar='ACCESS_TOKEN')
@click.option('--aa/--server')
def delete_account(token, aa):
"""Triggered by:
./cli.py -b "172.26.0.8" user delete-account --token "7jagPr4edVdghcsBNkjd23))" --aa
./cli.py -b "172.26.0.8" user delete-account --token 5c36ab84439c55a3c196f4csd9bd7b3d9291f39g --server
"""
if aa:
url = AA_URL_DELETE_ACCOUNT
else:
Expand Down Expand Up @@ -185,7 +189,7 @@ def create_device(device_type_id, device_name, password, token):
def create_scene(name, description, token):
if not is_global_bi_key_missing(init_global_keys, "Blind index key for scene name is missing"):
if len(get_tinydb_table(path, 'scene_keys')) == 0:
init_scene_keys() # TODO Test with flow (run this command 2 in row and make sure keys don't change)
init_scene_keys()
table = get_tinydb_table(path, 'scene_keys')
doc = table.all()[0]
name_ciphertext = encrypt_using_fernet_hex(doc["name"], name)
Expand Down Expand Up @@ -348,6 +352,7 @@ def revoke_user(device_id, revoke_user_id, token):
@click.argument('device_id')
@click.option('--token', envvar='ACCESS_TOKEN')
def get_devices(device_name, device_id, token):
"""Triggered using: ./cli.py -b "172.26.0.8" user get-devices test_device 46 --token 5c36ab84439c55a3c196f4csd9bd7b3d9291f39g"""
device_name_bi = blind_index(get_device_bi_key(device_id), device_name)
data = {"name_bi": device_name_bi}
r = requests.get(URL_GET_DEVICE, headers={"Authorization": token}, params=data, verify=VERIFY_CERTS)
Expand Down Expand Up @@ -582,6 +587,7 @@ def attr_auth_device_keygen(device_id, attr_list, token):
@user.command()
@click.option('--token', envvar='AA_ACCESS_TOKEN')
def attr_auth_retrieve_private_keys(token):
"""Triggered by: ./cli.py -b "172.26.0.8" user attr-auth-retrieve-private-keys --token '7jagPr4edVdgvyyBNkjdaQ))'"""
r = requests.post(AA_URL_SK_RETRIEVE, headers={"Authorization": token}, verify=VERIFY_CERTS)
click.echo(r.content.decode('unicode-escape'))

Expand Down
42 changes: 21 additions & 21 deletions node-red/flow.json
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@
"id": "3c4c1a28.5ef0e6",
"type": "exec",
"z": "f1dd4598.5b0fa8",
"command": "python3 /home/martin/Projects/diplomovka/IoT-Cloud/client/cli.py --no-debug device parse-msg ",
"command": "python3 ../client/cli.py --no-debug device parse-msg ",
"addpay": true,
"append": "",
"useSpawn": "false",
Expand All @@ -183,10 +183,10 @@
"name": "Debug",
"active": true,
"tosidebar": true,
"console": false,
"console": true,
"tostatus": false,
"complete": "true",
"x": 1010,
"x": 1020,
"y": 540,
"wires": []
},
Expand Down Expand Up @@ -226,10 +226,10 @@
"name": "Plaintext",
"active": true,
"tosidebar": true,
"console": false,
"console": true,
"tostatus": false,
"complete": "payload",
"x": 1020,
"x": 1030,
"y": 460,
"wires": []
},
Expand Down Expand Up @@ -281,10 +281,10 @@
"name": "Errors",
"active": false,
"tosidebar": true,
"console": false,
"console": true,
"tostatus": false,
"complete": "payload",
"x": 630,
"x": 640,
"y": 640,
"wires": []
},
Expand Down Expand Up @@ -336,10 +336,10 @@
"name": "Console Dump",
"active": true,
"tosidebar": true,
"console": false,
"console": true,
"tostatus": false,
"complete": "payload",
"x": 880,
"x": 890,
"y": 780,
"wires": []
},
Expand Down Expand Up @@ -421,10 +421,10 @@
"name": "Console Dump",
"active": true,
"tosidebar": true,
"console": false,
"console": true,
"tostatus": false,
"complete": "payload",
"x": 880,
"x": 890,
"y": 940,
"wires": []
},
Expand Down Expand Up @@ -531,10 +531,10 @@
"name": "get_fake_tuple_info",
"active": true,
"tosidebar": true,
"console": false,
"console": true,
"tostatus": false,
"complete": "true",
"x": 1170,
"x": 1180,
"y": 1300,
"wires": []
},
Expand Down Expand Up @@ -617,7 +617,7 @@
"name": "On",
"active": true,
"tosidebar": true,
"console": false,
"console": true,
"tostatus": false,
"complete": "payload",
"x": 850,
Expand All @@ -631,7 +631,7 @@
"name": "Off",
"active": true,
"tosidebar": true,
"console": false,
"console": true,
"tostatus": false,
"complete": "payload",
"x": 850,
Expand Down Expand Up @@ -686,10 +686,10 @@
"name": "Console Dump",
"active": true,
"tosidebar": true,
"console": false,
"console": true,
"tostatus": false,
"complete": "payload",
"x": 880,
"x": 890,
"y": 1080,
"wires": []
},
Expand Down Expand Up @@ -810,10 +810,10 @@
"name": "Console Dump",
"active": true,
"tosidebar": true,
"console": false,
"console": true,
"tostatus": false,
"complete": "payload",
"x": 1120,
"x": 1130,
"y": 1620,
"wires": []
},
Expand Down Expand Up @@ -875,10 +875,10 @@
"name": "Console Dump",
"active": true,
"tosidebar": true,
"console": false,
"console": true,
"tostatus": false,
"complete": "payload",
"x": 1120,
"x": 1130,
"y": 1760,
"wires": []
},
Expand Down
11 changes: 1 addition & 10 deletions tests/test_basic.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# -*- coding: utf-8 -*-
import base64
import json
import types
from unittest import mock
from unittest.mock import call
from uuid import UUID
Expand All @@ -26,7 +25,7 @@
from app.models.models import DeviceType, Device, User, Action, Scene, UserDevice
from app.app_setup import client as mqtt_client
from app.utils import is_valid_uuid, bytes_to_json, format_topic, validate_broker_password
from client.crypto_utils import encrypt, correctness_hash, triangle_wave, sawtooth_wave, square_wave, sine_wave, generate, \
from client.crypto_utils import encrypt, correctness_hash, generate, \
encrypt_row, instantiate_ope_cipher, decrypt_using_fernet_hex, decrypt_using_ope_hex, decrypt_using_abe_serialized_key

from .conftest import db, assert_got_error_from_post, assert_got_data_from_post, get_data_from_post, \
Expand Down Expand Up @@ -669,14 +668,6 @@ def test_correctness_hash():
assert not bcrypt.verify("ergh" + "esrge" + "wes", correctness_hash("ergh", "esrge"))


def test_wave_func():
funcs = [triangle_wave, sawtooth_wave, square_wave, sine_wave]
for f in funcs:
gen = f()
assert isinstance(gen, types.GeneratorType)
assert len(list(gen)) == 500


def test_generate_fake_tuple_and_hash():
columns = {
"added": {
Expand Down

0 comments on commit 73ec333

Please sign in to comment.