Skip to content
Snippets Groups Projects
Commit aeefe48a authored by Jennifer Lindgren's avatar Jennifer Lindgren
Browse files

Backend: Database structure remake to make data handling better.

parent e9304890
No related branches found
No related tags found
No related merge requests found
......@@ -22,6 +22,8 @@ BAD_REQUEST_STATUS_CODE = 400
CONFLICT_STATUS_CODE = 409
UNAUTHORIZED_STATUS_CODE = 401
DEFAULT_EDITOR_SETTINGS = {'fontSize': 16, 'margin': 80, 'tabSize': 4}
def is_valid_credentials(usernameEmail, password):
if '@' in usernameEmail:
user = db.get_user_from_email(usernameEmail)
......@@ -46,11 +48,9 @@ def is_valid_collaborators(collaborators):
return True
acceptedPermissions = ['View-only', 'May edit']
for collaborator in collaborators:
if (not collaborator or not db.is_user(collaborator['user'])):
if (not collaborator or not db.is_user_id(collaborator['userId']) or
not collaborator['permission'] in acceptedPermissions):
return False
for permission in collaborator['permissions']:
if (not permission in acceptedPermissions):
return False
return True
@jwt.unauthorized_loader
......@@ -78,6 +78,7 @@ def refresh():
'jwt': create_access_token(identity=current_user, fresh=False)
}), OK_STATUS_CODE)
### USER ###
@app.route('/api/sign_up', methods=['POST'])
def sign_up():
email = request.json['email']
......@@ -107,9 +108,15 @@ def sign_up():
new_user = db.User(
email,
username,
flask_bcrypt.generate_password_hash(password).decode('utf-8')
)
flask_bcrypt.generate_password_hash(password).decode('utf-8'))
db.add_user(new_user)
new_editor_settings = db.EditorSettings(
new_user.id,
DEFAULT_EDITOR_SETTINGS['fontSize'],
DEFAULT_EDITOR_SETTINGS['margin'],
DEFAULT_EDITOR_SETTINGS['tabSize'])
db.add_editor_settings(new_editor_settings)
return generate_response(db.user_schema.jsonify(new_user),
OK_STATUS_CODE)
......@@ -137,8 +144,7 @@ def sign_in():
'email': db_user.email,
'username': db_user.username,
'jwt': create_access_token(identity=username),
'refreshToken': create_refresh_token(identity=username),
'editorSettings': db_user.editorSettings
'refreshToken': create_refresh_token(identity=username)
}
return generate_response(jsonify(user), OK_STATUS_CODE)
......@@ -200,50 +206,51 @@ def delete_user():
'message': 'Successfully deleted account'
}), OK_STATUS_CODE)
@app.route('/api/user', methods=['GET'])
@app.route('/api/get_users', methods=['GET'])
@jwt_required
def get_users_request():
return generate_response(db.users_schema.jsonify(db.get_users()),
OK_STATUS_CODE)
@app.route('/api/user/<id>', methods=['GET'])
@app.route('/api/get_user/<id>', methods=['GET'])
@jwt_required
def get_user_request(id):
return generate_response(db.user_schema.jsonify(db.get_user(id)),
OK_STATUS_CODE)
@app.route('/api/update_editor_settings/<id>', methods=['PUT'])
### EDITOR SETTINGS ###
@app.route('/api/get_editor_settings/<user_id>', methods=['GET'])
@jwt_required
def update_editor_settings_request(id):
user = db.get_user(id)
user.editorSettings = request.json['editorSettings']
return generate_response(db.user_schema.jsonify(db.update_user(id, user)),
OK_STATUS_CODE)
def get_editor_settings_request(user_id):
return generate_response(db.editor_settings_schema.jsonify(
db.get_editor_settings(user_id)), OK_STATUS_CODE)
@app.route('/api/project', methods=['GET'])
@app.route('/api/update_editor_settings/<user_id>', methods=['PUT'])
@jwt_required
def get_projects_request():
return generate_response(db.projects_schema.jsonify(db.get_projects()),
OK_STATUS_CODE)
@app.route('/api/project/<id>', methods=['GET'])
@jwt_required
def get_project_request(id):
return generate_response(db.project_schema.jsonify(db.get_project(id)),
OK_STATUS_CODE)
def update_editor_settings_request(user_id):
editor_settings = request.json['editorSettings']
updated_editor_settings = db.EditorSettings(
editor_settings['userId'],
editor_settings['fontSize'],
editor_settings['margin'],
editor_settings['tabSize'],
)
return generate_response(db.editor_settings_schema.jsonify(
db.update_editor_settings(updated_editor_settings)), OK_STATUS_CODE)
### PROJECT ###
@app.route('/api/add_project', methods=['POST'])
@jwt_required
def new_project():
title = request.json['title']
creator = request.json['creator']
creatorId = request.json['creatorId']
collaborators = request.json['collaborators'] if request.json['collaborators'] != [] else None
if (not title or not creator):
if (not title or not creatorId):
return generate_response(jsonify({
'success': False,
'message': 'Bad request.'
}), BAD_REQUEST_STATUS_CODE)
elif (not db.is_user(creator)):
elif (not db.is_user_id(creatorId)):
return generate_response(jsonify({
'success': False,
'message': 'User does not exist'
......@@ -254,42 +261,47 @@ def new_project():
'message': 'Invalid collaborators'
}), BAD_REQUEST_STATUS_CODE)
else:
new_project = db.Project(title, creatorId)
db.add_project(new_project)
app.logger.error(new_project.id)
if collaborators:
for collaborator in collaborators:
collaborator_user = db.get_user(collaborator['user']['id'])
collaborator['user'] = db.user_schema.dump(collaborator_user).data
creator_str = str(db.user_schema.dump(creator).data)
collaborators_str = str(db.collaborators_schema.dump(collaborators).data)
new_project = db.Project(title, creator_str, collaborators_str)
db.add_project(new_project)
new_collaborator = db.Collaborator(
project_id=new_project.id,
user_id=collaborator['userId'],
permission=collaborator['permission'])
db.add_collaborator(new_collaborator)
return generate_response(db.project_schema.jsonify(new_project), OK_STATUS_CODE)
@app.route('/api/project/<id>', methods=['POST', 'PUT'])
@app.route('/api/get_projects', methods=['GET'])
@jwt_required
def get_projects_request():
return generate_response(db.projects_schema.jsonify(db.get_projects()),
OK_STATUS_CODE)
@app.route('/api/get_project/<id>', methods=['GET'])
@jwt_required
def get_project_request(id):
return generate_response(db.project_schema.jsonify(db.get_project(id)),
OK_STATUS_CODE)
@app.route('/api/update_project/<id>', methods=['POST', 'PUT'])
@jwt_required
def update_project_request(id):
project = json.loads(request.json['project'])
project['collaborators'] = json.loads((str(project['collaborators'])).replace('\'', '"'))
collaborators_str = str(db.collaborators_schema.dump(project['collaborators']).data)
project['creator'] = json.loads((str(project['creator'])).replace('\'', '"'))
creator_str = str(db.user_schema.dump(project['creator']).data)
project['files'] = json.loads((str(project['files'])).replace('\'', '"'))
files_str = str(db.files_schema.dump(project['files']).data)
updated_project = db.Project(
title = project['title'],
creator = creator_str,
collaborators = collaborators_str,
files=files_str)
creator_id = project['creatorId'],
archived = project['archived'])
updated_project.id = project['id']
updated_project.edited = datetime.now()
return generate_response(db.project_schema.jsonify(
db.update_project(updated_project)), OK_STATUS_CODE)
@app.route('/api/project/<id>', methods=['DELETE'])
@app.route('/api/delete_project/<id>', methods=['DELETE'])
@jwt_required
def delete_project_request(id):
project = json.loads(request.json['project'])
......@@ -300,6 +312,62 @@ def delete_project_request(id):
'message': 'Successfully deleted project'
}), OK_STATUS_CODE)
### FILE ###
@app.route('/api/create_file', methods=['POST'])
@jwt_required
def create_file_request():
file = request.json['file']
new_file = db.File(
file['projectId'],
file['name'],
file['isFolder'],
file['parent'],
file['content'],
)
return generate_response(db.file_schema.jsonify(
db.add_file(new_file)), OK_STATUS_CODE)
@app.route('/api/update_file/<file_id>', methods=['PUT'])
@jwt_required
def update_file_request(file_id):
updated_file = request.json['file']
return generate_response(db.file_schema.jsonify(
db.update_file(file)), OK_STATUS_CODE)
@app.route('/api/update_files', methods=['PUT'])
@jwt_required
def update_files_request():
updated_files = request.json['files']
return generate_response(db.files_schema.jsonify(
db.update_files(updated_files)), OK_STATUS_CODE)
@app.route('/api/delete_file/<file_id>', methods=['DELETE'])
@jwt_required
def delete_file_request(file_id):
return generate_response(db.file_schema.jsonify(
db.delete_file(file_id)), OK_STATUS_CODE)
@app.route('/api/get_project_files/<project_id>', methods=['GET'])
@jwt_required
def get_project_files_request(project_id):
return generate_response(db.files_schema.jsonify(
db.get_project_files(project_id)), OK_STATUS_CODE)
### COLLABORATOR ###
@app.route('/api/get_project_collaborators/<project_id>', methods=['GET'])
@jwt_required
def get_project_collaborators_request(project_id):
return generate_response(db.collaborators_schema.jsonify(
db.get_project_collaborators(project_id)), OK_STATUS_CODE)
### MESSAGE ###
@app.route('/api/get_project_messages/<project_id>', methods=['GET'])
@jwt_required
def get_project_messages_request(project_id):
return generate_response(db.messages_schema.jsonify(
db.get_project_messages(project_id)), OK_STATUS_CODE)
if __name__ == '__main__':
#app.run(debug=True)
......
......@@ -6,7 +6,7 @@ import json
from datetime import datetime
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from flask_marshmallow import Marshmallow, fields
basedir = os.path.abspath(os.path.dirname(__file__))
......@@ -17,109 +17,148 @@ app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
ma = Marshmallow(app)
DEFAULT_EDITOR_SETTINGS = '{\'fontSize\': 16, \'margin\': 80, \'tabSize\': 4}'
# User
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(100), unique=True)
username = db.Column(db.String(50), unique=True)
password = db.Column(db.String(100))
editorSettings = db.Column(db.String(100))
email = db.Column(db.String(100), unique=True, nullable=False)
username = db.Column(db.String(50), unique=True, nullable=False)
password = db.Column(db.Text, nullable=False)
def __init__(self, email, username, password, editor_settings=DEFAULT_EDITOR_SETTINGS):
def __init__(self, email, username, password):
self.email = email
self.username = username
self.password = password
self.editorSettings = editor_settings
class UserSchema(ma.Schema):
class Meta:
fields = ('id', 'email', 'username', 'editorSettings')
model = User
fields = ('id', 'email', 'username')
user_schema = UserSchema(strict=True)
users_schema = UserSchema(many=True, strict=True)
# EditorSettings
class EditorSettings():
def __init__(self, font_size, margin, tab_size):
class EditorSettings(db.Model):
id = db.Column(db.Integer, primary_key=True)
userId = db.Column(db.Integer, db.ForeignKey(User.id), unique=True)
fontSize = db.Column(db.Integer, nullable=False)
margin = db.Column(db.Integer, nullable=False)
tabSize = db.Column(db.Integer, nullable=False)
def __init__(self, user_id, font_size, margin, tab_size):
self.userId = user_id
self.fontSize = font_size
self.margin = margin
self.tabSize = tab_size
class EditorSettingsSchema(ma.Schema):
class Meta:
fields = ('fontSize', 'margin', 'tabSize')
model = EditorSettings
fields = ('userId', 'fontSize', 'margin', 'tabSize')
editor_settings_schema = EditorSettingsSchema(strict=True)
# Collaborator
class Collaborator():
def __init__(self, user, permissions):
self.user = user
self.permissions = permissions
class CollaboratorSchema(ma.Schema):
class Meta:
fields = ('user', 'permissions')
collaborator_schema = CollaboratorSchema(strict=True)
collaborators_schema = CollaboratorSchema(many=True, strict=True)
# Project
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(50), nullable=False)
creator = db.Column(db.Text)
collaborators = db.Column(db.Text)
created = db.Column(db.String(50), nullable=False, default=datetime.now)
edited = db.Column(db.String(50))
files = db.Column(db.Text)
messages = db.Column(db.Text)
archived = db.Column(db.Boolean, default=False)
def __init__(self, title, creator, collaborators=None, created=None,
edited=None, files=None, messages=None, archived=False):
creatorId = db.Column(db.Integer, db.ForeignKey(User.id), nullable=False)
creator = db.relationship("User")
created = db.Column(db.String(50), default=datetime.now, nullable=False)
edited = db.Column(db.String(50), onupdate=datetime.now)
archived = db.Column(db.Boolean, default=False, nullable=False)
def __init__(self, title, creator_id, created=None, edited=None, archived=False):
self.title = title
self.creator = creator
self.collaborators = collaborators
self.creatorId = creator_id
self.created = created
self.edited = edited
self.files = files
self.messages = messages
self.archived = archived
class ProjectSchema(ma.Schema):
creator = ma.Nested(UserSchema)
class Meta:
fields = ('id', 'title', 'creator', 'collaborators', 'created',
'edited', 'files', 'messages', 'archived')
model = Project
fields = ('id', 'title', 'creatorId', 'creator', 'created', 'edited', 'archived')
project_schema = ProjectSchema(strict=True)
projects_schema = ProjectSchema(many=True, strict=True)
# File
class File():
def __init__(self, name, is_folder, parent, content):
class File(db.Model):
id = db.Column(db.Integer, primary_key=True)
projectId = db.Column(db.Integer, db.ForeignKey(Project.id), nullable=False)
project = db.relationship("Project")
name = db.Column(db.String(100), nullable=False)
isFolder = db.Column(db.Boolean, nullable=False)
parent = db.Column(db.String(100))
content = db.Column(db.Text)
def __init__(self, project_id, name, is_folder, parent, content):
self.projectId = project_id
self.name = name
self.isFolder = is_folder
self.parent = parent
self.content = content
class FileSchema(ma.Schema):
project = ma.Nested(ProjectSchema)
class Meta:
fields = ('name', 'isFolder', 'parent', 'content')
model = File
fields = ('id', 'projectId', 'project', 'name', 'isFolder', 'parent', 'content')
file_schema = FileSchema(strict=True)
files_schema = FileSchema(many=True, strict=True)
# Collaborator
class Collaborator(db.Model):
id = db.Column(db.Integer, primary_key=True)
projectId = db.Column(db.Integer, db.ForeignKey(Project.id), nullable=False)
project = db.relationship("Project")
userId = db.Column(db.Integer, db.ForeignKey(User.id), nullable=False)
user = db.relationship("User")
permission = db.Column(db.Text, nullable=False)
def __init__(self, project_id, user_id, permission):
self.projectId = project_id
self.userId = user_id
self.permission = permission
class CollaboratorSchema(ma.Schema):
project = ma.Nested(ProjectSchema)
user = ma.Nested(UserSchema)
class Meta:
fields = ('id', 'projectId', 'project', 'userId', 'user', 'permission')
collaborator_schema = CollaboratorSchema(strict=True)
collaborators_schema = CollaboratorSchema(many=True, strict=True)
# Message
class Message():
def __init__(self, message, authorId, time):
class Message(db.Model):
id = db.Column(db.Integer, primary_key=True)
projectId = db.Column(db.Integer, db.ForeignKey(Project.id), nullable=False)
project = db.relationship("Project")
authorId = db.Column(db.Integer, db.ForeignKey(User.id), nullable=False)
author = db.relationship("User")
message = db.Column(db.Text)
time = db.Column(db.String(50), nullable=False)
def __init__(self, project_id, author_id, message, time):
self.projectId = project_id
self.authorId = author_id
self.message = message
self.authorId = authorId
self.time = time
# Methods
class MessageSchema(ma.Schema):
project = ma.Nested(ProjectSchema)
author = ma.Nested(UserSchema)
class Meta:
fields = ('id', 'projectId', 'project', 'authorId', 'author', 'message', 'time')
message_schema = MessageSchema(strict=True)
messages_schema = MessageSchema(many=True, strict=True)
### USER ###
def add_user(new_user):
db.session.add(new_user)
db.session.commit()
......@@ -138,7 +177,6 @@ def update_user(id, updated_user):
user.email = updated_user.email
user.username = updated_user.username
user.password = updated_user.password
user.editorSettings = updated_user.editorSettings
db.session.commit()
return user
......@@ -190,6 +228,40 @@ def change_password(username, newPassword):
db.session.commit()
return user
def delete_all_users():
num_users_deleted = db.session.query(User).delete()
db.session.commit()
return num_users_deleted
### EDITORSETTINGS ###
def add_editor_settings(editor_settings):
db.session.add(editor_settings)
db.session.commit()
def get_editor_settings(user_id):
return EditorSettings.query.filter_by(userId=user_id).first()
def update_editor_settings(updated_editor_settings):
user_id = updated_editor_settings.userId
editor_settings = EditorSettings.query.filter_by(userId=user_id).first()
editor_settings.fontSize = updated_editor_settings.fontSize
editor_settings.margin = updated_editor_settings.margin
editor_settings.tabSize = updated_editor_settings.tabSize
db.session.commit()
return editor_settings
def delete_editor_settings(user_id):
editor_settings = EditorSettings.query.get(id)
db.session.delete(editor_settings)
db.session.commit()
return editor_settings
def delete_all_editor_settings():
num_editor_settings_deleted = db.session.query(EditorSettings).delete()
db.session.commit()
return num_editor_settings_deleted
### PROJECT ###
def add_project(project):
db.session.add(project)
db.session.commit()
......@@ -206,11 +278,8 @@ def get_project(id):
def update_project(updated_project):
project = Project.query.get(updated_project.id)
project.title = updated_project.title
project.creator = updated_project.creator
project.collaborators = updated_project.collaborators
project.creatorId = updated_project.creatorId
project.edited = updated_project.edited
project.files = updated_project.files
project.messages = updated_project.messages
project.archived = updated_project.archived
db.session.commit()
return project
......@@ -221,19 +290,149 @@ def delete_project(id):
db.session.commit()
return project
def delete_user_projects(id):
def delete_user_projects(user_id):
""" Deletes all projects owned by user with id. """
user = User.query.get(id)
projects = Project.query.all()
app.logger.error(projects)
for project in projects:
creatorObj = json.loads(project.creator.replace('\'', '"'))
if creatorObj['id'] == id:
db.session.delete(project)
user = User.query.get(user_id)
projects = Project.query.filter_by(creatorId=user_id).all()
db.session.delete(projects)
db.session.commit()
return projects
def delete_all_projects():
num_projects_deleted = db.session.query(Project).delete()
db.session.commit()
return num_projects_deleted
### FILE ###
def add_file(file):
db.session.add(file)
db.session.commit()
def get_file(id):
return File.query.get(id)
def get_files():
all_files = File.query.all()
result = files_schema.dump(all_files)
return result.data
def get_project_files(project_id):
project_files = File.query.filter_by(projectId=project_id).all()
result = files_schema.dump(project_files)
return result.data
def update_file(updated_file):
file = File.query.get(updated_file.id)
file.projectId = updated_file.projectId
file.name = updated_file.name
file.isFolder = updated_file.isFolder
file.parent = updated_file.parent
file.content = updated_file.content
db.session.commit()
return file
def update_files(files):
updated_files = []
for file in files:
updated_file = File(
file['projectId'],
file['name'],
file['isFolder'],
file['parent'],
file['content'])
updated_file.id = file['id']
updated_files.append(update_file(updated_file))
return updated_files
def delete_file(file_id):
file = File.query.filter_by(id=file_id).first()
db.session.delete(file)
db.session.commit()
return file
def delete_project_files(project_id):
project_files = File.query.filter_by(projectId=project_id).all()
db.session.delete(project_files)
db.session.commit()
return project_files
def delete_all_files():
num_files_deleted = db.session.query(File).delete()
db.session.commit()
return num_files_deleted
### COLLABORATOR ###
def add_collaborator(collaborator):
db.session.add(collaborator)
db.session.commit()
def get_collaborator(id):
collaborator = Collaborator.query.get(id)
return collaborator
def get_collaborators():
all_collaborators = Collaborator.query.all()
result = collaborators_schema.dump(all_collaborators)
return result.data
def get_project_collaborators(project_id):
project_collaborators = Collaborator.query.filter_by(projectId=project_id).all()
result = collaborators_schema.dump(project_collaborators)
return result.data
def update_collaborator(updated_collaborator):
collaborator = Collaborator.query.get(updated_collaborator.id)
collaborator.projectId = updated_collaborator.projectId
collaborator.userId = updated_collaborator.userId
collaborator.permission = updated_collaborator.permission
db.session.commit()
return collaborator
def delete_project_collaborators(project_id):
project_collaborators = Collaborator.query.filter_by(projectId=project_id).all()
db.session.delete(project_collaborators)
db.session.commit()
return project_collaborators
def delete_all_collaborators():
num_collaborators_deleted = db.session.query(Collaborator).delete()
db.session.commit()
return num_collaborators_deleted
### Message ###
def add_message(message):
db.session.add(message)
db.session.commit()
def get_message(id):
message = Message.query.get(id)
return message
def get_messages():
all_messages = Message.query.all()
result = messages_schema.dump(all_messages)
return result.data
def get_project_messages(project_id):
project_messages = Message.query.filter_by(projectId=project_id).all()
result = messages_schema.dump(project_messages)
return result.data
def update_message(updated_message):
message = Message.query.get(updated_message.id)
message.projectId = updated_message.projectId
message.autorId = updated_message.autorId
message.time = updated_message.time
db.session.commit()
return message
def delete_project_messages(project_id):
project_messages = Message.query.filter_by(projectId=project_id).all()
db.session.delete(project_messages)
db.session.commit()
return project_messages
def delete_all_messages():
num_messages_deleted = db.session.query(Message).delete()
db.session.commit()
return num_messages_deleted
\ No newline at end of file
No preview for this file type
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment