Customers db tables (#66)
* customers model * Add customer model migration * Added users table * Add user model migration * precommit fixes --------- Co-authored-by: Graham Williamson <graham.williamson@socfortress.co>
taylor_socfortress committed
Jul 26, 2023 at 08:34 UTC
6f3d73274b0846ab32cbc0f1373a94ef0a99ba64
5 files changed
+418
backend/app/__init__.py
+2
@@ -34,12 +34,14 @@ from app.models import agents # noqa: F401
34
from app.models import artifacts # noqa: F401
35
from app.models import cases # noqa: F401
36
from app.models import connectors # noqa: F401
37
+from app.models import customers # noqa: F401
38
from app.models import graylog # noqa: F401
39
from app.models import influxdb_alerts # noqa: F401
40
from app.models import models # noqa: F401
41
from app.models import rules # noqa: F401
42
from app.models import smtp # noqa: F401
43
from app.models import sublime_alerts # noqa: F401
44
+from app.models import users # noqa: F401
45
from app.models import wazuh_indexer # noqa: F401
46
47
migrate = Migrate(app, db)
backend/app/models/customers.py
new
+222
@@ -0,0 +1,222 @@
1
+from datetime import datetime
2
+
3
+from sqlalchemy import Column
4
+from sqlalchemy import DateTime
5
+from sqlalchemy import Integer
6
+from sqlalchemy import String
7
+
8
+from app import db
9
+from app import ma
10
+
11
+
12
+class Customers(db.Model):
13
+ """
14
+ Class for customers which stores various customer details.
15
+ This class inherits from SQLAlchemy's Model class.
16
+ """
17
+
18
+ id: Column[Integer] = db.Column(db.Integer, primary_key=True)
19
+ customerCode: Column[String] = db.Column(db.String(11), nullable=False)
20
+ parentCustomerCode: Column[String] = db.Column(db.String(11))
21
+ customerName: Column[String] = db.Column(db.String(50), nullable=False)
22
+ contactLastName: Column[String] = db.Column(db.String(50))
23
+ contactFirstName: Column[String] = db.Column(db.String(50))
24
+ phone: Column[String] = db.Column(db.String(50))
25
+ addressLine1: Column[String] = db.Column(db.String(1024))
26
+ addressLine2: Column[String] = db.Column(db.String(1024))
27
+ city: Column[String] = db.Column(db.String(50))
28
+ state: Column[String] = db.Column(db.String(50))
29
+ postalCode: Column[String] = db.Column(db.String(15))
30
+ country: Column[String] = db.Column(db.String(50))
31
+ customerType: Column[String] = db.Column(db.String(50))
32
+ logoFile: Column[String] = db.Column(db.String(64))
33
+ createdAt: Column[DateTime] = db.Column(db.DateTime, default=datetime.utcnow)
34
+
35
+ def __init__(
36
+ self,
37
+ customerCode,
38
+ customerName,
39
+ parentCustomerCode=None,
40
+ contactLastName=None,
41
+ contactFirstName=None,
42
+ phone=None,
43
+ addressLine1=None,
44
+ addressLine2=None,
45
+ city=None,
46
+ state=None,
47
+ postalCode=None,
48
+ country=None,
49
+ customerType=None,
50
+ logoFile=None,
51
+ createdAt=None,
52
+ ):
53
+ """
54
+ Initialize a new instance of the Customer class.
55
+
56
+ :param customerCode: The code of the customer used as the Wazuh-Agent Label.
57
+ :param customerName: The name of the customer.
58
+ :param parentCustomerCode: The code of the parent customer.
59
+ :param contactLastName: The last name of the contact.
60
+ :param contactFirstName: The first name of the contact.
61
+ :param phone: The phone number of the contact.
62
+ :param addressLine1: The first line of the customer's address.
63
+ :param addressLine2: The second line of the customer's address.
64
+ :param city: The city of the customer's address.
65
+ :param state: The state of the customer's address.
66
+ :param postalCode: The postal code of the customer's address.
67
+ :param country: The country of the customer's address.
68
+ :param customerType: The type of the customer.
69
+ :param logoFile: The file name of the customer's logo.
70
+ :param createdAt: The date the customer was created.
71
+ """
72
+ self.customerCode = customerCode
73
+ self.customerName = customerName
74
+ self.parentCustomerCode = parentCustomerCode
75
+ self.contactLastName = contactLastName
76
+ self.contactFirstName = contactFirstName
77
+ self.phone = phone
78
+ self.addressLine1 = addressLine1
79
+ self.addressLine2 = addressLine2
80
+ self.city = city
81
+ self.state = state
82
+ self.postalCode = postalCode
83
+ self.country = country
84
+ self.customerType = customerType
85
+ self.logoFile = logoFile
86
+ self.createdAt = createdAt
87
+
88
+ def __repr__(self) -> str:
89
+ """
90
+ Returns a string representation of the Customer instance.
91
+
92
+ :return: A string representation of the customerCode.
93
+ """
94
+ return f"<Customer {self.customerCode}>"
95
+
96
+
97
+class CustomerSchema(ma.Schema):
98
+ """
99
+ Schema for serializing and deserializing instances of the Customer class.
100
+ """
101
+
102
+ class Meta:
103
+ """
104
+ Meta class defines the fields to be serialized/deserialized.
105
+ """
106
+
107
+ fields = (
108
+ "id",
109
+ "customerCode",
110
+ "parentCustomerCode",
111
+ "customerName",
112
+ "contactLastName",
113
+ "contactFirstName",
114
+ "phone",
115
+ "addressLine1",
116
+ "addressLine2",
117
+ "city",
118
+ "state",
119
+ "postalCode",
120
+ "country",
121
+ "customerType",
122
+ "logoFile",
123
+ "createdAt",
124
+ )
125
+
126
+
127
+customer_schema: CustomerSchema = CustomerSchema()
128
+customers_schema: CustomerSchema = CustomerSchema(many=True)
129
+
130
+
131
+class CustomersMeta(db.Model):
132
+ """
133
+ Class for customermeta which stores various customer metadata.
134
+ This class inherits from SQLAlchemy's Model class.
135
+ """
136
+
137
+ id: Column[Integer] = db.Column(db.Integer, primary_key=True)
138
+ clientName: Column[String] = db.Column(db.String(255))
139
+ customerCode: Column[String] = db.Column(db.String(11), nullable=False)
140
+ customerMetaGraylogIndex: Column[String] = db.Column(db.String(1024))
141
+ customerMetaGraylogStream: Column[String] = db.Column(db.String(1024))
142
+ customerMetaInfluxOrg: Column[String] = db.Column(db.String(1024))
143
+ customerMetaGrafanaOrg: Column[String] = db.Column(db.String(1024))
144
+ customerMetaWazuhGroup: Column[String] = db.Column(db.String(1024))
145
+ indexRetention: Column[Integer] = db.Column(db.Integer)
146
+ wazuhRegistrationPort: Column[Integer] = db.Column(db.Integer)
147
+ wazuhLogIngestionPort: Column[Integer] = db.Column(db.Integer)
148
+
149
+ def __init__(
150
+ self,
151
+ customerCode,
152
+ clientName=None,
153
+ customerMetaGraylogIndex=None,
154
+ customerMetaGraylogStream=None,
155
+ customerMetaInfluxOrg=None,
156
+ customerMetaGrafanaOrg=None,
157
+ customerMetaWazuhGroup=None,
158
+ indexRetention=None,
159
+ wazuhRegistrationPort=None,
160
+ wazuhLogIngestionPort=None,
161
+ ):
162
+ """
163
+ Initialize a new instance of the CustomerMeta class.
164
+
165
+ :param customerCode: The code of the customer.
166
+ :param clientName: The name of the client.
167
+ :param customerMetaGraylogIndex: The Graylog index of the customer metadata.
168
+ :param customerMetaGraylogStream: The Graylog stream of the customer metadata.
169
+ :param customerMetaInfluxOrg: The InfluxOrg of the customer metadata.
170
+ :param customerMetaGrafanaOrg: The GrafanaOrg of the customer metadata.
171
+ :param customerMetaWazuhGroup: The WazuhGroup of the customer metadata.
172
+ :param indexRetention: The index retention of the customer metadata.
173
+ :param wazuhRegistrationPort: The Wazuh registration port of the customer's Wazuh Agents.
174
+ :param wazuhLogIngestionPort: The Wazuh log ingestion port of the customer's Wazuh Agents.
175
+ """
176
+ self.customerCode = customerCode
177
+ self.clientName = clientName
178
+ self.customerMetaGraylogIndex = customerMetaGraylogIndex
179
+ self.customerMetaGraylogStream = customerMetaGraylogStream
180
+ self.customerMetaInfluxOrg = customerMetaInfluxOrg
181
+ self.customerMetaGrafanaOrg = customerMetaGrafanaOrg
182
+ self.customerMetaWazuhGroup = customerMetaWazuhGroup
183
+ self.indexRetention = indexRetention
184
+ self.wazuhRegistrationPort = wazuhRegistrationPort
185
+ self.wazuhLogIngestionPort = wazuhLogIngestionPort
186
+
187
+ def __repr__(self) -> str:
188
+ """
189
+ Returns a string representation of the CustomerMeta instance.
190
+
191
+ :return: A string representation of the customerCode.
192
+ """
193
+ return f"<CustomerMeta {self.customerCode}>"
194
+
195
+
196
+class CustomerMetaSchema(ma.Schema):
197
+ """
198
+ Schema for serializing and deserializing instances of the CustomerMeta class.
199
+ """
200
+
201
+ class Meta:
202
+ """
203
+ Meta class defines the fields to be serialized/deserialized.
204
+ """
205
+
206
+ fields = (
207
+ "id",
208
+ "clientName",
209
+ "customerCode",
210
+ "customerMetaGraylogIndex",
211
+ "customerMetaGraylogStream",
212
+ "customerMetaInfluxOrg",
213
+ "customerMetaGrafanaOrg",
214
+ "customerMetaWazuhGroup",
215
+ "indexRetention",
216
+ "wazuhRegistrationPort",
217
+ "wazuhLogIngestionPort",
218
+ )
219
+
220
+
221
+customer_meta_schema: CustomerMetaSchema = CustomerMetaSchema()
222
+customers_meta_schema: CustomerMetaSchema = CustomerMetaSchema(many=True)
backend/app/models/users.py
new
+93
@@ -0,0 +1,93 @@
1
+from datetime import datetime
2
+
3
+from sqlalchemy import Column
4
+from sqlalchemy import DateTime
5
+from sqlalchemy import Integer
6
+from sqlalchemy import String
7
+
8
+from app import db
9
+from app import ma
10
+
11
+
12
+class Users(db.Model):
13
+ """
14
+ Class for users which stores various user details.
15
+ This class inherits from SQLAlchemy's Model class.
16
+ """
17
+
18
+ id: Column[Integer] = db.Column(db.Integer, primary_key=True)
19
+ customerCode: Column[String] = db.Column(db.String(11), nullable=False)
20
+ usersFirstName: Column[String] = db.Column(db.String(50))
21
+ usersLastName: Column[String] = db.Column(db.String(50))
22
+ usersEmail: Column[String] = db.Column(db.String(50))
23
+ usersRole: Column[String] = db.Column(db.String(100))
24
+ imageFile: Column[String] = db.Column(db.String(64))
25
+ notifications: Column[Integer] = db.Column(db.SmallInteger, nullable=False)
26
+ createdAt: Column[DateTime] = db.Column(db.DateTime, default=datetime.utcnow)
27
+
28
+ def __init__(
29
+ self,
30
+ customerCode: str,
31
+ notifications: int,
32
+ usersFirstName: str = None,
33
+ usersLastName: str = None,
34
+ usersEmail: str = None,
35
+ usersRole: str = None,
36
+ imageFile: str = None,
37
+ createdAt: datetime = None,
38
+ ):
39
+ """
40
+ Initialize a new instance of the Users class.
41
+
42
+ :param customerCode: The code of the customer.
43
+ :param usersFirstName: The first name of the user.
44
+ :param usersLastName: The last name of the user.
45
+ :param usersEmail: The email of the user.
46
+ :param usersRole: The role of the user.
47
+ :param imageFile: The file name of the user's image.
48
+ :param notifications: Whether the user has notifications enabled (1) or not (0).
49
+ :param createdAt: The date the user was created.
50
+ """
51
+ self.customerCode = customerCode
52
+ self.usersFirstName = usersFirstName
53
+ self.usersLastName = usersLastName
54
+ self.usersEmail = usersEmail
55
+ self.usersRole = usersRole
56
+ self.imageFile = imageFile
57
+ self.notifications = notifications
58
+ self.createdAt = createdAt
59
+
60
+ def __repr__(self) -> str:
61
+ """
62
+ Returns a string representation of the Users instance.
63
+
64
+ :return: A string representation of the usersEmail.
65
+ """
66
+ return f"<User {self.usersEmail}>"
67
+
68
+
69
+class UsersSchema(ma.Schema):
70
+ """
71
+ Schema for serializing and deserializing instances of the Users class.
72
+ """
73
+
74
+ class Meta:
75
+ """
76
+ Meta class defines the fields to be serialized/deserialized.
77
+ """
78
+
79
+ fields = (
80
+ "id",
81
+ "customerCode",
82
+ "usersFirstName",
83
+ "usersLastName",
84
+ "usersEmail",
85
+ "usersRole",
86
+ "imageFile",
87
+ "notifications",
88
+ "createdAt",
89
+ )
90
+
91
+
92
+users_schema: UsersSchema = UsersSchema()
93
+users_schema: UsersSchema = UsersSchema(many=True)
backend/migrations/versions/09189f03c3ee_add_users_related_models.py
new
+39
@@ -0,0 +1,39 @@
1
+"""Add Users related models
2
+
3
+Revision ID: 09189f03c3ee
4
+Revises: 9353cd02b7fc
5
+Create Date: 2023-07-27 00:14:11.238239
6
+
7
+"""
8
+import sqlalchemy as sa
9
+from alembic import op
10
+
11
+# revision identifiers, used by Alembic.
12
+revision = "09189f03c3ee"
13
+down_revision = "9353cd02b7fc"
14
+branch_labels = None
15
+depends_on = None
16
+
17
+
18
+def upgrade():
19
+ # ### commands auto generated by Alembic - please adjust! ###
20
+ op.create_table(
21
+ "users",
22
+ sa.Column("id", sa.Integer(), nullable=False),
23
+ sa.Column("customerCode", sa.String(length=11), nullable=False),
24
+ sa.Column("usersFirstName", sa.String(length=50), nullable=True),
25
+ sa.Column("usersLastName", sa.String(length=50), nullable=True),
26
+ sa.Column("usersEmail", sa.String(length=50), nullable=True),
27
+ sa.Column("usersRole", sa.String(length=100), nullable=True),
28
+ sa.Column("imageFile", sa.String(length=64), nullable=True),
29
+ sa.Column("notifications", sa.SmallInteger(), nullable=False),
30
+ sa.Column("createdAt", sa.DateTime(), nullable=True),
31
+ sa.PrimaryKeyConstraint("id"),
32
+ )
33
+ # ### end Alembic commands ###
34
+
35
+
36
+def downgrade():
37
+ # ### commands auto generated by Alembic - please adjust! ###
38
+ op.drop_table("users")
39
+ # ### end Alembic commands ###
backend/migrations/versions/9353cd02b7fc_add_customer_related_models.py
new
+62
@@ -0,0 +1,62 @@
1
+"""Add Customer related models
2
+
3
+Revision ID: 9353cd02b7fc
4
+Revises: 1ec08862d786
5
+Create Date: 2023-07-26 23:58:03.843542
6
+
7
+"""
8
+import sqlalchemy as sa
9
+from alembic import op
10
+
11
+# revision identifiers, used by Alembic.
12
+revision = "9353cd02b7fc"
13
+down_revision = "1ec08862d786"
14
+branch_labels = None
15
+depends_on = None
16
+
17
+
18
+def upgrade():
19
+ # ### commands auto generated by Alembic - please adjust! ###
20
+ op.create_table(
21
+ "customers",
22
+ sa.Column("id", sa.Integer(), nullable=False),
23
+ sa.Column("customerCode", sa.String(length=11), nullable=False),
24
+ sa.Column("parentCustomerCode", sa.String(length=11), nullable=True),
25
+ sa.Column("customerName", sa.String(length=50), nullable=False),
26
+ sa.Column("contactLastName", sa.String(length=50), nullable=True),
27
+ sa.Column("contactFirstName", sa.String(length=50), nullable=True),
28
+ sa.Column("phone", sa.String(length=50), nullable=True),
29
+ sa.Column("addressLine1", sa.String(length=1024), nullable=True),
30
+ sa.Column("addressLine2", sa.String(length=1024), nullable=True),
31
+ sa.Column("city", sa.String(length=50), nullable=True),
32
+ sa.Column("state", sa.String(length=50), nullable=True),
33
+ sa.Column("postalCode", sa.String(length=15), nullable=True),
34
+ sa.Column("country", sa.String(length=50), nullable=True),
35
+ sa.Column("customerType", sa.String(length=50), nullable=True),
36
+ sa.Column("logoFile", sa.String(length=64), nullable=True),
37
+ sa.Column("createdAt", sa.DateTime(), nullable=True),
38
+ sa.PrimaryKeyConstraint("id"),
39
+ )
40
+ op.create_table(
41
+ "customers_meta",
42
+ sa.Column("id", sa.Integer(), nullable=False),
43
+ sa.Column("clientName", sa.String(length=255), nullable=True),
44
+ sa.Column("customerCode", sa.String(length=11), nullable=False),
45
+ sa.Column("customerMetaGraylogIndex", sa.String(length=1024), nullable=True),
46
+ sa.Column("customerMetaGraylogStream", sa.String(length=1024), nullable=True),
47
+ sa.Column("customerMetaInfluxOrg", sa.String(length=1024), nullable=True),
48
+ sa.Column("customerMetaGrafanaOrg", sa.String(length=1024), nullable=True),
49
+ sa.Column("customerMetaWazuhGroup", sa.String(length=1024), nullable=True),
50
+ sa.Column("indexRetention", sa.Integer(), nullable=True),
51
+ sa.Column("wazuhRegistrationPort", sa.Integer(), nullable=True),
52
+ sa.Column("wazuhLogIngestionPort", sa.Integer(), nullable=True),
53
+ sa.PrimaryKeyConstraint("id"),
54
+ )
55
+ # ### end Alembic commands ###
56
+
57
+
58
+def downgrade():
59
+ # ### commands auto generated by Alembic - please adjust! ###
60
+ op.drop_table("customers_meta")
61
+ op.drop_table("customers")
62
+ # ### end Alembic commands ###