vatsal-p-wa commited on
Commit
2dbc96c
·
verified ·
1 Parent(s): 21cd37f

Upload 9 files

Browse files
Files changed (9) hide show
  1. .env.sample +2 -0
  2. .gitignore +5 -0
  3. README.md +9 -10
  4. app.py +295 -0
  5. auth_middleware.py +39 -0
  6. models.py +181 -0
  7. requirements.txt +12 -0
  8. save_image.py +22 -0
  9. validate.py +102 -0
.env.sample ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ DATABASE_URL=
2
+ SECRET_KEY=
.gitignore ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ venv
2
+ env
3
+ .env
4
+ *.pyc
5
+ static/images/
README.md CHANGED
@@ -1,10 +1,9 @@
1
- ---
2
- title: TestingSpace
3
- emoji:
4
- colorFrom: pink
5
- colorTo: purple
6
- sdk: docker
7
- pinned: false
8
- ---
9
-
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ # Authentication with Flask and JWT
2
+
3
+ ## Development server
4
+
5
+ - Create a virtual environment, activate it and install the dependencies.
6
+ - Run `flask run` to start the development server.
7
+ - Navigate to http://localhost:5000/. The app will automatically reload if you change any of the source files.
8
+
9
+ © 2021 GitHub, Inc.
 
app.py ADDED
@@ -0,0 +1,295 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import jwt, os
2
+ from dotenv import load_dotenv
3
+ from flask import Flask, request, jsonify
4
+ from save_image import save_pic
5
+ from validate import validate_book, validate_email_and_password, validate_user
6
+
7
+ load_dotenv()
8
+
9
+ app = Flask(__name__)
10
+ SECRET_KEY = os.environ.get('SECRET_KEY') or 'myFlask@uthApp!s$uper8'
11
+ print(SECRET_KEY)
12
+ app.config['SECRET_KEY'] = SECRET_KEY
13
+
14
+ from models import Books, User
15
+ from auth_middleware import token_required
16
+
17
+ @app.route("/")
18
+ def hello():
19
+ return "Hello World!"
20
+
21
+ @app.route("/users/", methods=["POST"])
22
+ def add_user():
23
+ try:
24
+ user = request.json
25
+ if not user:
26
+ return {
27
+ "message": "Please provide user details",
28
+ "data": None,
29
+ "error": "Bad request"
30
+ }, 400
31
+ is_validated = validate_user(**user)
32
+ if is_validated is not True:
33
+ return dict(message='Invalid data', data=None, error=is_validated), 400
34
+ user = User().create(**user)
35
+ if not user:
36
+ return {
37
+ "message": "User already exists",
38
+ "error": "Conflict",
39
+ "data": None
40
+ }, 409
41
+ return {
42
+ "message": "Successfully created new user",
43
+ "data": user
44
+ }, 201
45
+ except Exception as e:
46
+ return {
47
+ "message": "Something went wrong",
48
+ "error": str(e),
49
+ "data": None
50
+ }, 500
51
+
52
+ @app.route("/users/login", methods=["POST"])
53
+ def login():
54
+ try:
55
+ data = request.json
56
+ if not data:
57
+ return {
58
+ "message": "Please provide user details",
59
+ "data": None,
60
+ "error": "Bad request"
61
+ }, 400
62
+ # validate input
63
+ is_validated = validate_email_and_password(data.get('email'), data.get('password'))
64
+ if is_validated is not True:
65
+ return dict(message='Invalid data', data=None, error=is_validated), 400
66
+ user = User().login(
67
+ data["email"],
68
+ data["password"]
69
+ )
70
+ if user:
71
+ try:
72
+ # token should expire after 24 hrs
73
+ user["token"] = jwt.encode(
74
+ {"user_id": user["_id"]},
75
+ app.config["SECRET_KEY"],
76
+ algorithm="HS256"
77
+ )
78
+ return {
79
+ "message": "Successfully fetched auth token",
80
+ "data": user
81
+ }
82
+ except Exception as e:
83
+ return {
84
+ "error": "Something went wrong",
85
+ "message": str(e)
86
+ }, 500
87
+ return {
88
+ "message": "Error fetching auth token!, invalid email or password",
89
+ "data": None,
90
+ "error": "Unauthorized"
91
+ }, 404
92
+ except Exception as e:
93
+ return {
94
+ "message": "Something went wrong!",
95
+ "error": str(e),
96
+ "data": None
97
+ }, 500
98
+
99
+
100
+ @app.route("/users/", methods=["GET"])
101
+ @token_required
102
+ def get_current_user(current_user):
103
+ return jsonify({
104
+ "message": "successfully retrieved user profile",
105
+ "data": current_user
106
+ })
107
+
108
+ @app.route("/users/", methods=["PUT"])
109
+ @token_required
110
+ def update_user(current_user):
111
+ try:
112
+ user = request.json
113
+ if user.get("name"):
114
+ user = User().update(current_user["_id"], user["name"])
115
+ return jsonify({
116
+ "message": "successfully updated account",
117
+ "data": user
118
+ }), 201
119
+ return {
120
+ "message": "Invalid data, you can only update your account name!",
121
+ "data": None,
122
+ "error": "Bad Request"
123
+ }, 400
124
+ except Exception as e:
125
+ return jsonify({
126
+ "message": "failed to update account",
127
+ "error": str(e),
128
+ "data": None
129
+ }), 400
130
+
131
+ @app.route("/users/", methods=["DELETE"])
132
+ @token_required
133
+ def disable_user(current_user):
134
+ try:
135
+ User().disable_account(current_user["_id"])
136
+ return jsonify({
137
+ "message": "successfully disabled acount",
138
+ "data": None
139
+ }), 204
140
+ except Exception as e:
141
+ return jsonify({
142
+ "message": "failed to disable account",
143
+ "error": str(e),
144
+ "data": None
145
+ }), 400
146
+
147
+ @app.route("/books/", methods=["POST"])
148
+ @token_required
149
+ def add_book(current_user):
150
+ try:
151
+ book = dict(request.form)
152
+ if not book:
153
+ return {
154
+ "message": "Invalid data, you need to give the book title, cover image, author id,",
155
+ "data": None,
156
+ "error": "Bad Request"
157
+ }, 400
158
+ if not request.files["cover_image"]:
159
+ return {
160
+ "message": "cover image is required",
161
+ "data": None
162
+ }, 400
163
+
164
+ book["image_url"] = request.host_url+"static/books/"+save_pic(request.files["cover_image"])
165
+ is_validated = validate_book(**book)
166
+ if is_validated is not True:
167
+ return {
168
+ "message": "Invalid data",
169
+ "data": None,
170
+ "error": is_validated
171
+ }, 400
172
+ book = Books().create(**book, user_id=current_user["_id"])
173
+ if not book:
174
+ return {
175
+ "message": "The book has been created by user",
176
+ "data": None,
177
+ "error": "Conflict"
178
+ }, 400
179
+ return jsonify({
180
+ "message": "successfully created a new book",
181
+ "data": book
182
+ }), 201
183
+ except Exception as e:
184
+ return jsonify({
185
+ "message": "failed to create a new book",
186
+ "error": str(e),
187
+ "data": None
188
+ }), 500
189
+
190
+ @app.route("/books/", methods=["GET"])
191
+ @token_required
192
+ def get_books(current_user):
193
+ try:
194
+ books = Books().get_by_user_id(current_user["_id"])
195
+ return jsonify({
196
+ "message": "successfully retrieved all books",
197
+ "data": books
198
+ })
199
+ except Exception as e:
200
+ return jsonify({
201
+ "message": "failed to retrieve all books",
202
+ "error": str(e),
203
+ "data": None
204
+ }), 500
205
+
206
+ @app.route("/books/<book_id>", methods=["GET"])
207
+ @token_required
208
+ def get_book(book_id):
209
+ try:
210
+ book = Books().get_by_id(book_id)
211
+ if not book:
212
+ return {
213
+ "message": "Book not found",
214
+ "data": None,
215
+ "error": "Not Found"
216
+ }, 404
217
+ return jsonify({
218
+ "message": "successfully retrieved a book",
219
+ "data": book
220
+ })
221
+ except Exception as e:
222
+ return jsonify({
223
+ "message": "Something went wrong",
224
+ "error": str(e),
225
+ "data": None
226
+ }), 500
227
+
228
+ @app.route("/books/<book_id>", methods=["PUT"])
229
+ @token_required
230
+ def update_book(current_user, book_id):
231
+ try:
232
+ book = Books().get_by_id(book_id)
233
+ if not book or book["user_id"] != current_user["_id"]:
234
+ return {
235
+ "message": "Book not found for user",
236
+ "data": None,
237
+ "error": "Not found"
238
+ }, 404
239
+ book = request.form
240
+ if book.get('cover_image'):
241
+ book["image_url"] = request.host_url+"static/books/"+save_pic(request.files["cover_image"])
242
+ book = Books().update(book_id, **book)
243
+ return jsonify({
244
+ "message": "successfully updated a book",
245
+ "data": book
246
+ }), 201
247
+ except Exception as e:
248
+ return jsonify({
249
+ "message": "failed to update a book",
250
+ "error": str(e),
251
+ "data": None
252
+ }), 400
253
+
254
+ @app.route("/books/<book_id>", methods=["DELETE"])
255
+ @token_required
256
+ def delete_book(current_user, book_id):
257
+ try:
258
+ book = Books().get_by_id(book_id)
259
+ if not book or book["user_id"] != current_user["_id"]:
260
+ return {
261
+ "message": "Book not found for user",
262
+ "data": None,
263
+ "error": "Not found"
264
+ }, 404
265
+ Books().delete(book_id)
266
+ return jsonify({
267
+ "message": "successfully deleted a book",
268
+ "data": None
269
+ }), 204
270
+ except Exception as e:
271
+ return jsonify({
272
+ "message": "failed to delete a book",
273
+ "error": str(e),
274
+ "data": None
275
+ }), 400
276
+
277
+ @app.errorhandler(403)
278
+ def forbidden(e):
279
+ return jsonify({
280
+ "message": "Forbidden",
281
+ "error": str(e),
282
+ "data": None
283
+ }), 403
284
+
285
+ @app.errorhandler(404)
286
+ def forbidden(e):
287
+ return jsonify({
288
+ "message": "Endpoint Not Found",
289
+ "error": str(e),
290
+ "data": None
291
+ }), 404
292
+
293
+
294
+ if __name__ == "__main__":
295
+ app.run(debug=True)
auth_middleware.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from functools import wraps
2
+ import jwt
3
+ from flask import request, abort
4
+ from flask import current_app
5
+ import models
6
+
7
+ def token_required(f):
8
+ @wraps(f)
9
+ def decorated(*args, **kwargs):
10
+ token = None
11
+ if "Authorization" in request.headers:
12
+ token = request.headers["Authorization"].split(" ")[1]
13
+ if not token:
14
+ return {
15
+ "message": "Authentication Token is missing!",
16
+ "data": None,
17
+ "error": "Unauthorized"
18
+ }, 401
19
+ try:
20
+ data=jwt.decode(token, current_app.config["SECRET_KEY"], algorithms=["HS256"])
21
+ current_user=models.User().get_by_id(data["user_id"])
22
+ if current_user is None:
23
+ return {
24
+ "message": "Invalid Authentication token!",
25
+ "data": None,
26
+ "error": "Unauthorized"
27
+ }, 401
28
+ if not current_user["active"]:
29
+ abort(403)
30
+ except Exception as e:
31
+ return {
32
+ "message": "Something went wrong",
33
+ "data": None,
34
+ "error": str(e)
35
+ }, 500
36
+
37
+ return f(current_user, *args, **kwargs)
38
+
39
+ return decorated
models.py ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Application Models"""
2
+ import bson, os
3
+ from dotenv import load_dotenv
4
+ from pymongo import MongoClient
5
+ from werkzeug.security import generate_password_hash, check_password_hash
6
+
7
+ load_dotenv()
8
+
9
+ DATABASE_URL=os.environ.get('DATABASE_URL') or 'mongodb://localhost:27017/flask-auth'
10
+ print(DATABASE_URL)
11
+ client = MongoClient(DATABASE_URL)
12
+ db = client.myDatabase
13
+
14
+ class Books:
15
+ """Books Model"""
16
+ def __init__(self):
17
+ return
18
+
19
+ def create(self, title="", description="", image_url="", category="", user_id=""):
20
+ """Create a new book"""
21
+ book = self.get_by_user_id_and_title(user_id, title)
22
+ if book:
23
+ return
24
+ new_book = db.books.insert_one(
25
+ {
26
+ "title": title,
27
+ "description": description,
28
+ "image_url": image_url,
29
+ "category": category,
30
+ "user_id": user_id
31
+ }
32
+ )
33
+ return self.get_by_id(new_book.inserted_id)
34
+
35
+ def get_all(self):
36
+ """Get all books"""
37
+ books = db.books.find()
38
+ return [{**book, "_id": str(book["_id"])} for book in books]
39
+
40
+ def get_by_id(self, book_id):
41
+ """Get a book by id"""
42
+ book = db.books.find_one({"_id": bson.ObjectId(book_id)})
43
+ if not book:
44
+ return
45
+ book["_id"] = str(book["_id"])
46
+ return book
47
+
48
+ def get_by_user_id(self, user_id):
49
+ """Get all books created by a user"""
50
+ books = db.books.find({"user_id": user_id})
51
+ return [{**book, "_id": str(book["_id"])} for book in books]
52
+
53
+ def get_by_category(self, category):
54
+ """Get all books by category"""
55
+ books = db.books.find({"category": category})
56
+ return [book for book in books]
57
+
58
+ def get_by_user_id_and_category(self, user_id, category):
59
+ """Get all books by category for a particular user"""
60
+ books = db.books.find({"user_id": user_id, "category": category})
61
+ return [{**book, "_id": str(book["_id"])} for book in books]
62
+
63
+ def get_by_user_id_and_title(self, user_id, title):
64
+ """Get a book given its title and author"""
65
+ book = db.books.find_one({"user_id": user_id, "title": title})
66
+ if not book:
67
+ return
68
+ book["_id"] = str(book["_id"])
69
+ return book
70
+
71
+ def update(self, book_id, title="", description="", image_url="", category="", user_id=""):
72
+ """Update a book"""
73
+ data={}
74
+ if title: data["title"]=title
75
+ if description: data["description"]=description
76
+ if image_url: data["image_url"]=image_url
77
+ if category: data["category"]=category
78
+
79
+ book = db.books.update_one(
80
+ {"_id": bson.ObjectId(book_id)},
81
+ {
82
+ "$set": data
83
+ }
84
+ )
85
+ book = self.get_by_id(book_id)
86
+ return book
87
+
88
+ def delete(self, book_id):
89
+ """Delete a book"""
90
+ book = db.books.delete_one({"_id": bson.ObjectId(book_id)})
91
+ return book
92
+
93
+ def delete_by_user_id(self, user_id):
94
+ """Delete all books created by a user"""
95
+ book = db.books.delete_many({"user_id": bson.ObjectId(user_id)})
96
+ return book
97
+
98
+
99
+ class User:
100
+ """User Model"""
101
+ def __init__(self):
102
+ return
103
+
104
+ def create(self, name="", email="", password=""):
105
+ """Create a new user"""
106
+ user = self.get_by_email(email)
107
+ if user:
108
+ return
109
+ new_user = db.users.insert_one(
110
+ {
111
+ "name": name,
112
+ "email": email,
113
+ "password": self.encrypt_password(password),
114
+ "active": True
115
+ }
116
+ )
117
+ return self.get_by_id(new_user.inserted_id)
118
+
119
+ def get_all(self):
120
+ """Get all users"""
121
+ users = db.users.find({"active": True})
122
+ return [{**user, "_id": str(user["_id"])} for user in users]
123
+
124
+ def get_by_id(self, user_id):
125
+ """Get a user by id"""
126
+ user = db.users.find_one({"_id": bson.ObjectId(user_id), "active": True})
127
+ if not user:
128
+ return
129
+ user["_id"] = str(user["_id"])
130
+ user.pop("password")
131
+ return user
132
+
133
+ def get_by_email(self, email):
134
+ """Get a user by email"""
135
+ user = db.users.find_one({"email": email, "active": True})
136
+ if not user:
137
+ return
138
+ user["_id"] = str(user["_id"])
139
+ return user
140
+
141
+ def update(self, user_id, name=""):
142
+ """Update a user"""
143
+ data = {}
144
+ if name:
145
+ data["name"] = name
146
+ user = db.users.update_one(
147
+ {"_id": bson.ObjectId(user_id)},
148
+ {
149
+ "$set": data
150
+ }
151
+ )
152
+ user = self.get_by_id(user_id)
153
+ return user
154
+
155
+ def delete(self, user_id):
156
+ """Delete a user"""
157
+ Books().delete_by_user_id(user_id)
158
+ user = db.users.delete_one({"_id": bson.ObjectId(user_id)})
159
+ user = self.get_by_id(user_id)
160
+ return user
161
+
162
+ def disable_account(self, user_id):
163
+ """Disable a user account"""
164
+ user = db.users.update_one(
165
+ {"_id": bson.ObjectId(user_id)},
166
+ {"$set": {"active": False}}
167
+ )
168
+ user = self.get_by_id(user_id)
169
+ return user
170
+
171
+ def encrypt_password(self, password):
172
+ """Encrypt password"""
173
+ return generate_password_hash(password)
174
+
175
+ def login(self, email, password):
176
+ """Login a user"""
177
+ user = self.get_by_email(email)
178
+ if not user or not check_password_hash(user["password"], password):
179
+ return
180
+ user.pop("password")
181
+ return user
requirements.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ click==8.0.1
2
+ colorama==0.4.6
3
+ Flask==2.0.1
4
+ Flask-PyMongo==2.3.0
5
+ itsdangerous==2.0.1
6
+ Jinja2==3.0.1
7
+ MarkupSafe==2.0.1
8
+ pillow==10.3.0
9
+ PyJWT==2.1.0
10
+ pymongo==3.12.0
11
+ python-dotenv==0.19.2
12
+ Werkzeug==2.0.1
save_image.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import secrets
2
+ import os
3
+ from PIL import Image
4
+ from flask import current_app as app
5
+
6
+ def save_pic(picture):
7
+ """Saves an image to disk"""
8
+ file_name = secrets.token_hex(8) +os.path.splitext(picture.filename)[1]
9
+ if not os.path.isdir(os.path.join(app.root_path, 'static')):
10
+ os.mkdir(os.path.join(app.root_path,"static"))
11
+ os.mkdir(os.path.join(app.root_path,"static/images"))
12
+ os.mkdir(os.path.join(app.root_path,"static/images/books"))
13
+ if not os.path.isdir(os.path.join(app.root_path, 'static/images')):
14
+ os.mkdir(os.path.join(app.root_path,"static/images"))
15
+ os.mkdir(os.path.join(app.root_path,"static/images/books"))
16
+ if not os.path.isdir(os.path.join(app.root_path, 'static/images/books')):
17
+ os.mkdir(os.path.join(app.root_path,"static/images/books"))
18
+ file_path = os.path.join(app.root_path, "static/images/books", file_name)
19
+ picture = Image.open(picture)
20
+ picture.thumbnail((150, 150))
21
+ picture.save(file_path)
22
+ return file_name
validate.py ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Validator Module"""
2
+ import re
3
+ from bson.objectid import ObjectId
4
+
5
+
6
+ def validate(data, regex):
7
+ """Custom Validator"""
8
+ return True if re.match(regex, data) else False
9
+
10
+
11
+ def validate_password(password: str):
12
+ """Password Validator"""
13
+ reg = r"\b^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!#%*?&]{8,20}$\b"
14
+ return validate(password, reg)
15
+
16
+
17
+ def validate_email(email: str):
18
+ """Email Validator"""
19
+ regex = r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b'
20
+ return validate(email, regex)
21
+
22
+
23
+ def validate_book(**args):
24
+ """Book Validator"""
25
+ if not args.get('title') or not args.get('image_url') \
26
+ or not args.get('category') or not args.get('user_id'):
27
+ return {
28
+ 'title': 'Title is required',
29
+ 'image_url': 'Image URL is required',
30
+ 'category': 'Category is required',
31
+ 'user_id': 'User ID is required'
32
+ }
33
+ if args.get('category') not in ['romance', 'peotry', 'politics' 'picture book', 'science', 'fantasy', 'horror', 'thriller']:
34
+ return {
35
+ 'status': 'error',
36
+ 'message': 'Invalid category'
37
+ }
38
+ try:
39
+ ObjectId(args.get('user_id'))
40
+ except:
41
+ return {
42
+ 'user_id': 'User ID must be valid'
43
+ }
44
+ if not isinstance(args.get('title'), str) or not isinstance(args.get('description'), str) \
45
+ or not isinstance(args.get('image_url'), str):
46
+ return {
47
+ 'title': 'Title must be a string',
48
+ 'description': 'Description must be a string',
49
+ 'image_url': 'Image URL must be a string'
50
+ }
51
+ return True
52
+
53
+
54
+ def validate_user(**args):
55
+ """User Validator"""
56
+ if not args.get('email') or not args.get('password') or not args.get('name'):
57
+ return {
58
+ 'email': 'Email is required',
59
+ 'password': 'Password is required',
60
+ 'name': 'Name is required'
61
+ }
62
+ if not isinstance(args.get('name'), str) or \
63
+ not isinstance(args.get('email'), str) or not isinstance(args.get('password'), str):
64
+ return {
65
+ 'email': 'Email must be a string',
66
+ 'password': 'Password must be a string',
67
+ 'name': 'Name must be a string'
68
+ }
69
+ if not validate_email(args.get('email')):
70
+ return {
71
+ 'email': 'Email is invalid'
72
+ }
73
+ if not validate_password(args.get('password')):
74
+ return {
75
+ 'password': 'Password is invalid, Should be atleast 8 characters with \
76
+ upper and lower case letters, numbers and special characters'
77
+ }
78
+ print(len(args['name'].split(' ')))
79
+ if not 2 <= len(args['name'].split(' ')) <= 30:
80
+ return {
81
+ 'name': 'Name must be between 2 and 30 words'
82
+ }
83
+ return True
84
+
85
+
86
+ def validate_email_and_password(email, password):
87
+ """Email and Password Validator"""
88
+ if not (email and password):
89
+ return {
90
+ 'email': 'Email is required',
91
+ 'password': 'Password is required'
92
+ }
93
+ if not validate_email(email):
94
+ return {
95
+ 'email': 'Email is invalid'
96
+ }
97
+ if not validate_password(password):
98
+ return {
99
+ 'password': 'Password is invalid, Should be atleast 8 characters with \
100
+ upper and lower case letters, numbers and special characters'
101
+ }
102
+ return True