diff --git a/app/accounts/models.py b/app/accounts/models.py index d205226..102b02d 100644 --- a/app/accounts/models.py +++ b/app/accounts/models.py @@ -129,6 +129,13 @@ class Role(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) display_name = db.Column(db.String, unique=True) permissions = db.Column(db.ARRAY(db.String)) + created_at = db.Column(db.DateTime, + nullable=False, + default=db.func.current_timestamp()) + modified_at = db.Column(db.DateTime, + nullable=False, + default=db.func.current_timestamp(), + onupdate=db.func.current_timestamp()) def __init__(self, name, permissions): self.display_name = str(name) diff --git a/app/api/resources/device.py b/app/api/resources/device.py index 664431e..2f5c2db 100644 --- a/app/api/resources/device.py +++ b/app/api/resources/device.py @@ -24,6 +24,8 @@ class DeviceSchema(BaseResourceSchema): name = fields.Str(required=True) device_type = fields.Nested(BasicDeviceTypeSchema, dump_only=True) device_type_id = fields.Integer(load_only=True, missing=1) + created_at = fields.DateTime(dump_only=True) + modified_at = fields.DateTime(dump_only=True) class DeviceWithConfigurationSchema(DeviceSchema): diff --git a/app/devices/api.py b/app/devices/api.py index cee336d..260e2d7 100644 --- a/app/devices/api.py +++ b/app/devices/api.py @@ -1,13 +1,14 @@ import sys import hmac import urllib.parse +import datetime from .models import (Device, Recording, DeviceAssociation, DeviceType, AccessLevel) from itsdangerous import URLSafeSerializer -from app.core import app, db +from app.core import app from app.jsonql import api as jsonql @@ -335,7 +336,7 @@ def run_custom_query(device_id, request): if not Device.exists(id=device_id): raise ValueError("Device does not exist!") - def recording_field_provider(name, formatted=False): + def recording_field_provider(name): if name == 'record_value': return Recording.record_value if name == 'record_type': @@ -343,14 +344,8 @@ def run_custom_query(device_id, request): if name == 'device_id': return Recording.device_id if name == 'recorded_at': - if formatted: - return db.func.to_char( - Recording.recorded_at, 'YYYY-MM-DD"T"HH24:MI:SSOF') return Recording.recorded_at if name == 'received_at': - if formatted: - return db.func.to_char( - Recording.received_at, 'YYYY-MM-DD"T"HH24:MI:SSOF') return Recording.received_at resulting_query = jsonql.run_query_on(Recording.query.with_entities(), @@ -363,6 +358,8 @@ def run_custom_query(device_id, request): for row in result: formatted_row = {} for idx, col in enumerate(row): + if isinstance(col, datetime.datetime): + col = col.replace(tzinfo=datetime.timezone.utc).isoformat() formatted_row[resulting_columns[idx]['name']] = col formatted_result.append(formatted_row) return formatted_result diff --git a/app/devices/models.py b/app/devices/models.py index e21d9ed..dac9c1a 100644 --- a/app/devices/models.py +++ b/app/devices/models.py @@ -225,6 +225,13 @@ class DeviceAssociation(db.Model): primary_key=True) access_level = db.Column(db.Integer, db.ForeignKey('access_levels.id'), nullable=False) + created_at = db.Column(db.DateTime, + nullable=False, + default=db.func.current_timestamp()) + modified_at = db.Column(db.DateTime, + nullable=False, + default=db.func.current_timestamp(), + onupdate=db.func.current_timestamp()) access_level_data = db.relationship("AccessLevel", foreign_keys=[access_level]) @@ -279,6 +286,13 @@ class DeviceType(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String, nullable=False) + created_at = db.Column(db.DateTime, + nullable=False, + default=db.func.current_timestamp()) + modified_at = db.Column(db.DateTime, + nullable=False, + default=db.func.current_timestamp(), + onupdate=db.func.current_timestamp()) def __init__(self, name): self.name = name @@ -333,6 +347,13 @@ class AccessLevel(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String, nullable=False) permissions = db.Column(db.ARRAY(db.String), nullable=False) + created_at = db.Column(db.DateTime, + nullable=False, + default=db.func.current_timestamp()) + modified_at = db.Column(db.DateTime, + nullable=False, + default=db.func.current_timestamp(), + onupdate=db.func.current_timestamp()) def __init__(self, name, permissions=['VIEW_DEVICE']): self.name = name diff --git a/app/jsonql/api.py b/app/jsonql/api.py index 0219e41..8cf31e3 100644 --- a/app/jsonql/api.py +++ b/app/jsonql/api.py @@ -35,7 +35,7 @@ def run_query_on(query_object, field_provider, **kwargs): for selection in selections.keys(): entities.append(get_column(selections[selection], - field_provider(selection, True)).label(selection)) + field_provider(selection)).label(selection)) query_object = query_object.with_entities(*entities) diff --git a/migrations/versions/764de3c39771_.py b/migrations/versions/764de3c39771_.py new file mode 100644 index 0000000..52e5859 --- /dev/null +++ b/migrations/versions/764de3c39771_.py @@ -0,0 +1,51 @@ +"""empty message + +Revision ID: 764de3c39771 +Revises: 43e5ad1c4393 +Create Date: 2018-11-03 15:00:36.463124 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '764de3c39771' +down_revision = '43e5ad1c4393' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('access_levels', sa.Column('created_at', sa.DateTime(), + nullable=False, server_default=sa.func.current_timestamp())) + op.add_column('access_levels', sa.Column('modified_at', sa.DateTime(), + nullable=False, server_default=sa.func.current_timestamp())) + op.add_column('device_associations', sa.Column('created_at', sa.DateTime(), + nullable=False, server_default=sa.func.current_timestamp())) + op.add_column('device_associations', sa.Column('modified_at', + sa.DateTime(), nullable=False, + server_default=sa.func.current_timestamp())) + op.add_column('device_types', sa.Column('created_at', sa.DateTime(), + nullable=False, server_default=sa.func.current_timestamp())) + op.add_column('device_types', sa.Column('modified_at', sa.DateTime(), + nullable=False, server_default=sa.func.current_timestamp())) + op.add_column('roles', sa.Column('created_at', sa.DateTime(), + nullable=False, server_default=sa.func.current_timestamp())) + op.add_column('roles', sa.Column('modified_at', sa.DateTime(), + nullable=False, server_default=sa.func.current_timestamp())) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('roles', 'modified_at') + op.drop_column('roles', 'created_at') + op.drop_column('device_types', 'modified_at') + op.drop_column('device_types', 'created_at') + op.drop_column('device_associations', 'modified_at') + op.drop_column('device_associations', 'created_at') + op.drop_column('access_levels', 'modified_at') + op.drop_column('access_levels', 'created_at') + # ### end Alembic commands ###