Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
aborrego3 committed Jan 20, 2022
0 parents commit edf76cc
Show file tree
Hide file tree
Showing 25 changed files with 478 additions and 0 deletions.
112 changes: 112 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@

# Created by https://www.gitignore.io/api/python
# Edit at https://www.gitignore.io/?templates=python

.vscode/

### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/

# Translations
*.mo
*.pot

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# pyenv
.python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# Mr Developer
.mr.developer.cfg
.project
.pydevproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# End of https://www.gitignore.io/api/python
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Backend for the photo gallery lab project. It includes all necessary SQL files, and a basic file structure for the web app.
40 changes: 40 additions & 0 deletions settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
###############################################################################
# Project-specific settings
###############################################################################

# Shows debug messages while Silence is running
DEBUG_ENABLED = False

# Database connection details
DB_CONN = {
"host": "127.0.0.1",
"port": 3306,
"username": "iissi_user",
"password": "iissi$user",
"database": "gallery",
}

# The sequence of SQL scripts located in the sql/ folder that must
# be ran when the 'silence createdb' command is issued
SQL_SCRIPTS = [
"create_tables.sql",
"create_views.sql",
"populate_database.sql",
]

# The port in which the API and the web server will be deployed
HTTP_PORT = 8080

# The URL prefix for all API endpoints
API_PREFIX = "/api/v1"

# Table and fields that are used for both login and register
USER_AUTH_DATA = {
"table": "Users",
"identifier": "username",
"password": "password",
}

# A random string that is used for security purposes
# (this has been generated automatically upon project creation)
SECRET_KEY = "Replace with your own key"
79 changes: 79 additions & 0 deletions sql/create_tables.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
DROP TABLE IF EXISTS BadWords;
DROP TABLE IF EXISTS Votes;
DROP TABLE IF EXISTS Comments;
DROP TABLE IF EXISTS PhotosTags;
DROP TABLE IF EXISTS Tags;
DROP TABLE IF EXISTS Photos;
DROP TABLE IF EXISTS UsersFollows;
DROP TABLE IF EXISTS Users;

CREATE TABLE Users (
userId INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
firstName VARCHAR(128) NOT NULL,
lastName VARCHAR(128) NOT NULL,
telephone VARCHAR(32) NOT NULL,
email VARCHAR(128) NOT NULL,
username VARCHAR(64) UNIQUE NOT NULL,
password VARCHAR(256) NOT NULL,
avatarUrl VARCHAR(512)
);

CREATE TABLE UsersFollows (
id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
followerId INT NOT NULL,
followedId INT NOT NULL,
FOREIGN KEY (followerId) REFERENCES Users (userId),
FOREIGN KEY (followedId) REFERENCES Users (userId)
);

CREATE TABLE Photos (
photoId INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(128) NOT NULL,
description VARCHAR(512),
date DATETIME DEFAULT CURRENT_TIMESTAMP,
url VARCHAR(512) NOT NULL,
visibility VARCHAR(16) NOT NULL,
userId INT NOT NULL,
FOREIGN KEY (userId) REFERENCES Users (userId),
CONSTRAINT ValidVisibility CHECK (visibility in ('Public', 'Private'))
);

CREATE TABLE Tags (
tagId INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(128) NOT NULL UNIQUE
);

CREATE TABLE PhotosTags (
photoTagId INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
photoId INT NOT NULL,
tagId INT NOT NULL,
FOREIGN KEY (photoId) REFERENCES Photos (photoId) ON DELETE CASCADE,
FOREIGN KEY (tagId) REFERENCES Tags (tagId) ON DELETE CASCADE
);

CREATE TABLE Comments (
commentId INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
text VARCHAR(512) NOT NULL,
date DATETIME DEFAULT CURRENT_TIMESTAMP,
userId INT NOT NULL,
photoId INT NOT NULL,
FOREIGN KEY (userId) REFERENCES Users (userId),
FOREIGN KEY (photoId) REFERENCES Photos (photoId)
);

CREATE TABLE Votes (
voteId INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
value INT NOT NULL,
date DATETIME DEFAULT CURRENT_TIMESTAMP,
userId INT NOT NULL,
photoId INT NOT NULL,
FOREIGN KEY (userId) REFERENCES Users (userId),
FOREIGN KEY (photoId) REFERENCES Photos (photoId) ON DELETE CASCADE,
CONSTRAINT ValidVote CHECK (VALUE IN (-1, 1)),
CONSTRAINT OneVotePerPhoto UNIQUE (userId, photoId)
);

CREATE TABLE BadWords (
wordId INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
word VARCHAR(128) NOT NULL
);
7 changes: 7 additions & 0 deletions sql/create_views.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE OR REPLACE VIEW PhotosWithUsers AS
SELECT P.*, U.username, U.avatarUrl
FROM Photos P NATURAL JOIN Users U;

CREATE OR REPLACE VIEW CommentsWithUsers AS
SELECT C.*, U.username, U.avatarUrl
FROM Comments C NATURAL JOIN Users U;
77 changes: 77 additions & 0 deletions sql/populate_database.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
INSERT INTO Users
VALUES
(1, 'Agustín', 'Borrego', '654321987', 'agu@gallery.com', 'agu', 'pbkdf2:sha256:150000$uqfMc1rm$37b2a7fc88de0ce96f3cc0c4e47915414542eac2f98ff32e589af89f41ff5b58', 'https://github.eii.us.es/avatars/u/22?s=460'),
(2, 'David', 'Ruiz', '987654321', 'david@gallery.com', 'druiz', 'pbkdf2:sha256:150000$tbwxky0J$0d8d6c0b7a9f46d69f3c3502178d4ac3fe1b4dafa7c362ccc401e9f65106b127', 'https://github.eii.us.es/avatars/u/32?s=460'),
(3, 'Inma', 'Hernández', '456123789', 'inma@gallery.com', 'inma', 'pbkdf2:sha256:150000$RVTpLkIl$976062ffde4796faa57d73fb0abc6743fe337849589163cfe6e3334f477883d7', 'https://github.eii.us.es/avatars/u/38?s=460');

INSERT INTO Photos
VALUES
(1, 'Tortilla', 'A typical Spanish tortilla. With onion, of course.', '2012-04-23 18:25:43', 'https://comidasespanolas.com/wp-content/uploads/2019/12/Receta-de-tortilla-espa%C3%B1ola-tradicional.jpg', 'Public', 1),
(2, 'Samoyed', 'A very fluffy dog', '2013-04-23 18:21:43', 'https://www.dogsnsw.org.au/media/img/BrowseAllBreed/Samoyed-.jpg', 'Public', 2),
(3, 'Coding in C#', 'A piece of very intricate code', '2020-04-23 18:20:43', 'https://pbs.twimg.com/media/Ea4HJNaXsAEbzzF?format=jpg&name=900x900', 'Public', 3),
(4, 'The future society', 'This is what society would look like if PHP didn\'t exist', '2016-05-10 18:21:43', 'https://pbs.twimg.com/media/Eeeb3R0VAAAiVCp.jpg', 'Public', 1),
(5, 'Comfy cat', 'A drawing of a cat about to sleep', '2016-04-23 18:21:43', 'https://pbs.twimg.com/media/EZ4Z2QDUYAANA-Z?format=png', 'Public', 2),
(6, 'Seville', 'The beautiful city of Seville, Spain', '2016-04-23 18:20:43', 'https://urbansevilla.es/wp-content/uploads/2019/03/urban-sevilla-foto-ciudad.jpg', 'Public', 3),
(7, 'Mont Saint-Michel', 'An island located in Normandy, France', '2019-04-23 18:20:43', 'https://www.timetravelturtle.com/wp-content/uploads/2019/11/Mont-St-Michel-2019-356_new.jpg', 'Public', 2),
(8, 'Night operations', 'A plane flying over Toronto at night', '2020-02-28 13:33:37', 'https://www.airlive.net/wp-content/uploads/2016/09/maxresdefault-23.jpg', 'Private', 1),
(9, 'Abstract art', 'A very weird clipart', '2015-05-01 12:23:11', 'https://clipartart.com/images/worst-clipart-ever-1.jpg', 'Private', 2),
(10, 'Knitting', 'Very relaxing', '2019-01-12 21:30:00', 'https://cdn.shopify.com/s/files/1/0078/5065/5857/t/8/assets/62638885ceb5--CocoKnitsBook_Appendix_Photo5_2692.jpg?1338', 'Private', 3);

INSERT INTO Tags
VALUES
(1, 'photography'),
(2, 'animals'),
(3, 'cute'),
(4, 'creative'),
(5, 'cities'),
(6, 'engineering'),
(7, 'food'),
(8, 'drawing'),
(9, 'spain'),
(10, 'flying'),
(11, 'funny'),
(12, 'futuristic'),
(13, 'videogames');

INSERT INTO PhotosTags (photoId, tagId)
VALUES
(1, 1), (1, 7), (1, 9),
(2, 1), (2, 2), (2, 3),
(3, 4), (3, 6),
(4, 1), (4, 6), (4, 12),
(5, 2), (5, 3), (5, 8),
(6, 1), (6, 5), (6, 9),
(7, 1), (7, 5),
(8, 10), (8, 6),
(9, 4), (9, 8),
(10, 1), (10, 4);

INSERT INTO Comments (text, date, userId, photoId)
VALUES
('Delicious!', '2019-01-20 19:45:00', 2, 1),
('It\'s better without onion, though...', '2019-01-21 20:01:12', 3, 1),
('You\'re clueless', '2019-01-21 22:10:02', 2, 1),
('Good boy!', '2015-08-20 19:50:00', 1, 2),
('Looks hard...', '2020-02-28 13:37:00', 2, 3),
('Ole!', '2019-12-20 14:55:34', 2, 6);

INSERT INTO Votes (value, userId, photoId)
VALUES
(+1, 1, 1), (+1, 2, 1), (+1, 3, 1),
(+1, 1, 2), (+1, 2, 2), (+1, 3, 2),
(-1, 2, 3), (-1, 1, 3),
(+1, 2, 4),
(+1, 2, 5), (+1, 3, 5),
(+1, 1, 6),
(+1, 1, 7), (-1, 3, 7),
(+1, 1, 8),
(+1, 2, 9),
(+1, 3, 10);

INSERT INTO UsersFollows (followerId, followedId)
VALUES
(2, 1), (3, 1), (1, 2), (1, 3);

INSERT INTO BadWords (word)
VALUES
('caca'), ('culo'), ('pedo'), ('pis');
6 changes: 6 additions & 0 deletions web/css/bootstrap.min.css

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions web/css/font-awesome.min.css

Large diffs are not rendered by default.

Binary file added web/fonts/fontawesome-webfont.woff
Binary file not shown.
Binary file added web/fonts/fontawesome-webfont.woff2
Binary file not shown.
Binary file added web/images/avatar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added web/images/example.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added web/images/favicon.ico
Binary file not shown.
Binary file added web/images/placeholder-img.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions web/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello, IISSI-2!
11 changes: 11 additions & 0 deletions web/js/api/common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use strict';

import { sessionManager } from '../utils/session.js';

const BASE_URL = "/api/v1";

const requestOptions = {
headers: { Token: sessionManager.getToken() },
};

export { BASE_URL, requestOptions };
2 changes: 2 additions & 0 deletions web/js/libs/axios.min.js

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions web/js/libs/bootstrap.min.js

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions web/js/libs/jquery-3.4.1.min.js

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions web/js/libs/popper.min.js

Large diffs are not rendered by default.

48 changes: 48 additions & 0 deletions web/js/renderers/messages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use strict';

import { parseHTML } from '../utils/parseHTML.js';

// Aux function to get the div in which to display messages
// It's centralized here so we can change it easily in the case its ID changes
function getErrorsDiv() {
return document.getElementById("errors");
}

const messageRenderer = {

showMessageAsAlert: function (message, bootClass, err) {
let html = `<div class="alert alert-${bootClass} alert-dismissible col-md-12 fade show">
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
${message}
</div>`;
let errorsDiv = getErrorsDiv();

if (errorsDiv === null) {
console.error("You tried to render the following message, however, a " +
`<div id="${msgsDivID}"> could not be found in your view to show it there:`);
console.error(message);
return;
}

let messageElem = parseHTML(html);
errorsDiv.appendChild(messageElem);

if(err != null) {
throw(err);
}
},

showErrorAsAlert: function (message, err = null) {
this.showMessageAsAlert(message, "danger", err);
},

showWarningAsAlert: function (message, err = null) {
this.showMessageAsAlert(message, "warning", err);
},

showSuccessAsAlert: function (message, err = null) {
this.showMessageAsAlert(message, "success", err);
},
}

export { messageRenderer };
Loading

0 comments on commit edf76cc

Please sign in to comment.