This commit is contained in:
yanczi 2025-10-19 02:44:10 +02:00
parent 7d1af32688
commit f3adf19649
139 changed files with 25604 additions and 0 deletions

11
server_2.1/.gitignore vendored Normal file
View file

@ -0,0 +1,11 @@
#Katalog upload
upload/**
!upload/index.htm
#Moduły node js
node_modules
#ENV
.env
test.js

View file

@ -0,0 +1,17 @@
{
"extension": "jpg",
"type": "jpeg",
"quality": 80,
"poster": {
"width": 200,
"height": 285
},
"miniature": {
"width": 50,
"height": 70
},
"avatar": {
"width": 128,
"height": 128
}
}

35
server_2.1/index.js Normal file
View file

@ -0,0 +1,35 @@
const express = require('express');
require('dotenv').config();
const session = require('./src/session')
const cors = require('./src/cors');
const fileUpload = require('express-fileupload');
const userRoute = require('./src/UserRouting');
const animeRoute = require('./src/AnimeRouting');
const app = express();
app.use(express.json());
app.use(cors);
app.use(fileUpload({
limits: { fileSize: 1024 * 1024 }, // Ustaw limit na 1 MB
abortOnLimit: true, // Przerwij przesyłanie, jeśli plik przekracza limit
}));
app.use((req, res, next) => {
console.log(`Otrzymano żądanie: ${req.method} ${req.url}`);
next();
});
app.use(session);
app.get('/', (req, res) => {
res.send(`
Hi Mom!
`);
})
app.use('/user', userRoute);
app.use('/content', animeRoute);
app.listen(process.env.EX_PORT, () => {
console.log(`Serwer HTTP działa na http://localhost:${process.env.EX_PORT}`);
});

2830
server_2.1/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

34
server_2.1/package.json Normal file
View file

@ -0,0 +1,34 @@
{
"name": "animelista_server",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"altcha": "^2.0.5",
"altcha-lib": "^1.2.0",
"bcrypt": "^5.1.1",
"compression": "^1.8.0",
"cors": "^2.8.5",
"dotenv": "^16.4.7",
"express": "^4.21.1",
"express-fileupload": "^1.5.1",
"express-mysql-session": "^3.0.3",
"express-session": "^1.18.1",
"glob": "^11.0.0",
"html-entities": "^2.5.2",
"jsonwebtoken": "^9.0.2",
"mysql": "^2.18.1",
"mysql2": "^3.11.4",
"nodemailer": "^6.10.0",
"rimraf": "^6.0.1",
"sharp": "^0.33.5",
"uuid": "^11.0.5",
"validator": "^13.12.0"
},
"description": ""
}

View file

@ -0,0 +1,38 @@
const express = require('express');
const router = express.Router();
const anime = require('./anime');
const imm = require('./image');
//Routing
//Pobieranie anime
router.get('/', anime.GetAnime);
//Pobieranie posortowanego warunkowo anime
router.post('/result/sort', anime.GetFilteringAnime)
//Pobieranie opisu
router.get('/description', anime.GetDescription);
//Dodawanie nowego anime do bazy danych
router.post('/anime/add', anime.AddAnimeToRecord);
//Edycja
router.get('/anime/get', anime.GetAnimeRecord);
router.put('/anime/edit', anime.EditAnimeRecord);
//Dodawanie grupy
router.post('/group', anime.AddGrouptoRecord);
router.put('/group', anime.EditGroupRecord);
router.get('/group', anime.GetGroupList);
//Kasowanie rekordów
router.delete('/delete', anime.DeleteRecords);
//Aktualizacja statusów oglądania
router.put('/anime/update', anime.UpdateState);
//Przesyłanie obrazu i czyszczenie rekordu obrazu
router.post('/image/add', imm.UploadImageFromFile);
router.delete('/image/delete', imm.DeleteImage);
module.exports = router;

View file

@ -0,0 +1,23 @@
class DateTime {
constructor () {
this.date = new Date();
}
GetDateNow() {
const year = String(this.date.getFullYear());
const month = String(this.date.getMonth() + 1).padStart(2, '0'); // Poprawna nazwa zmiennej
const day = String(this.date.getDate()).padStart(2, '0'); // Poprawna metoda
return `${year}-${month}-${day}`;
}
GetTimeNow() {
const hour = String(this.date.getHours()).padStart(2, '0');
const minute = String(this.date.getMinutes()).padStart(2, '0');
const second = String(this.date.getSeconds()).padStart(2, '0');
return `${hour}:${minute}:${second}`;
}
}
module.exports = new DateTime();

View file

@ -0,0 +1,29 @@
const fs = require('node:fs');
const dt = require('./DateTime');
class LogsCapture {
constructor() {
this.path = '@/logs.log'; //Ścieżka do pliku log
this.fs = fs;
this.dt = dt;
}
async SaveLog(prefix, sufix, description) {
const date = this.dt.GetDate();
const time = this.dt.GetTime();
const content = date + '_' + time + '___' + prefix + '_' + sufix + '___: ' + description;
await this.fs.writeFile(this.path, content);
}
async CaptureError(sufix ,error) {
await this.SaveLog('ERROR', sufix, error);
}
async CaptureWarning(sufix ,error) {
await this.SaveLog('WARNING', sufix, error);
}
}
module.exports = new LogsCapture();

View file

@ -0,0 +1,18 @@
const express = require('express');
const router = express.Router();
const user = require('./user');
router.post('/login', user.LoginProcess);
router.get('/checksession', user.UserCheckSession);
router.delete('/logout', user.LogoutUser);
router.put('/preference', user.UpdateUserPreference);
router.put('/password/update', user.UpdateUserPassword);
router.put('/data/update', user.UpdateUserName);
router.put('/avatar/update', user.UpdateUserAvatar);
router.delete('/avatar/delete', user.DeleteAvatar);
router.post('/altcha', user.AltchaHumanTest);
module.exports = router;

View file

View file

@ -0,0 +1,51 @@
const fs = require('fs');
const path = require('path');
const imm = require('../image');
const AnimeRepository = require('../database/AnimeRepository');
const SegregatedRepository = require('../database/SegregatedRepository');
async function AddAnimeToRecord(req, res) {
try {
if(!req.session.isLogged) {
console.error('DESCRYPTION ERROR: Urzytkownik nie jest zalogowany');
return res.status(401).json({complete: false});
}
const data = req.body;
const group = Number(data.group);
const imgPaths = req.session.img_files;
const userId = req.session.user_id;
const userHash = req.session.user_hash;
const posterPath = imgPaths?.poster !== undefined ? imgPaths.poster : null;
const miniaturePath = imgPaths?.miniature !== undefined ? imgPaths.miniature : null;
const blob = {
poster: await imm.LoadImgToBlob(posterPath),
miniature: await imm.LoadImgToBlob(miniaturePath),
};
const animeId = await AnimeRepository.Add(data, blob, userId);
if(group != 0) {
SegregatedRepository.Add(animeId, group, userId);
}
const uploadDirectory = path.join(__dirname, '../../upload', userHash);
console.log(uploadDirectory);
if(fs.existsSync(uploadDirectory)) {
fs.rmSync(uploadDirectory, { recursive: true });
}
res.status(200).json({
mess: 'Dodano nowe anime',
complete: true
});
}
catch(e) {
console.error(`ERROR Nie udało się dodać anime do bazy danych: ${e}`);
res.status(500).json({complete: false});
}
}
module.exports = AddAnimeToRecord;

View file

@ -0,0 +1,55 @@
const GroupRepository = require('../database/GroupRepository');
async function AddGroupToRecord(req, res) {
try {
if(!req.session.isLogged) {
console.error(`ERROR: Nowa grupa nie dodana. Użytkownik nie zalogowany`);
return res.status(401).json({
mess: 'Użytkownik nie zalogowany',
complete: false,
data: null
});
}
const group = req.body.name;
if(!group) {
console.error(`ERROR: AddGroupToRecord: Zapyanie jest puste!`);
return res.status(400).json({
mess: 'Brak danych',
complete: false,
data: null
});
}
const userId = req.session.user_id;
if (!await GroupRepository.Add(group, userId)) {
console.error(`ERROR: Niepowodzenie dodania rekordu!`);
return res.status(400).json({
mess: 'Błąd wewnętrzny',
complete: false,
data: null
});
}
const data = await GroupRepository.Get(userId);
console.log(data);
res.status(200).json({
mess: 'Record dodany',
complete: true,
data: data
});
}
catch(e) {
console.error(`ERROR: Function AddGroupToRecord: ${e}`);
res.status(500).json({
mess: 'Błąd wewnętrzny',
complete: false,
data: null
});
}
}
module.exports = AddGroupToRecord;

View file

@ -0,0 +1,60 @@
const AnimeRepo = require('../database/AnimeRepository');
const GroupRepo = require('../database/GroupRepository');
const SegregatedRepo = require('../database/SegregatedRepository');
const FavoritesRepo = require('../database/FavoritesRepository');
async function DeleteAnimeRecords(anime, user) {
try {
await AnimeRepo.Delete(anime, user);
await FavoritesRepo.Delete(anime, user);
await SegregatedRepo.DeleteByAnime(anime, user);
}
catch(e) {
console.error(`ERROR: Nie udało się skasować anime: ${e}`);
}
}
async function DeleteGroupRecords(group, user) {
try {
await GroupRepo.Delete(group, user);
await SegregatedRepo.DeleteByGroup(group, user);
}
catch(e) {
console.error(`ERROR: Nie udało się skasować grupy: ${e}`);
}
}
async function DeleteRecords(req, res) {
try {
if(!req.session.isLogged) {
console.error('DESCRYPTION ERROR: Urzytkownik nie jest zalogowany');
return res.status(401).json({
mess: 'Użytkownik nie jest zalogowany',
complete: false
});
}
const group = req.query.group;
const anime = req.query.anime;
const userId = req.session.user_id;
if(group) {
await DeleteGroupRecords(group, userId);
}
if(anime) {
await DeleteAnimeRecords(anime, userId);
}
res.status(200).json({mess: 'Pomyślnie skasowano rekordy', complete: true});
}
catch(e) {
console.error(`ERROR: Nie udało się skasować anime: ${e}`);
res.status(500).json({
mess: 'Nie udało się wykoniac operacji kasowania',
complete: false
});
}
}
module.exports = DeleteRecords;

View file

@ -0,0 +1,132 @@
const AnimeRepository = require('../database/AnimeRepository');
const SegregatedRepository = require('../database/SegregatedRepository');
const imm = require('../image');
const path = require('path');
const fs = require('fs');
//Aktualizacja lub kasowanie przypisania anime do danej grupy
async function SergregateUpdate(userId, updateData) {
if(updateData.group != 0) {
const result = await SegregatedRepository.Edit(updateData.group, updateData.id, userId);
if(result === 0) {
await SegregatedRepository.Add(updateData.id, updateData.group, userId);
}
}
else {
await SegregatedRepository.DeleteByAnime(updateData.id, userId);
}
}
//Aktualizacja obrazka
async function PosterUpdater(updateData, imgPaths) {
let updateImage = false;
let poster = null;
let miniature = null;
if(updateData.newImage && !updateData.removeImage) {
const posterPath = imgPaths?.poster !== undefined ? imgPaths.poster : null;
const miniaturePath = imgPaths?.miniature !== undefined ? imgPaths.miniature : null;
poster = await imm.LoadImgToBlob(posterPath);
miniature = await imm.LoadImgToBlob(miniaturePath);
updateImage = true;
}
if(updateData.removeImage && !updateData.newImage) {
updateImage = true;
}
return {
update: updateImage,
poster: poster,
miniature: miniature
};
}
//Aktualizacja opisu
async function DescriptionUpdate(dsdata) {
if (dsdata.description || dsdata.poster) {
if (await AnimeRepository.EditDescription(dsdata) < 1) {
await AnimeRepository.AddDescription(dsdata);
}
}
else {
await AnimeRepository.DeleteDescription(dsdata.anie);
}
}
async function EditAnimeRecord(req, res) {
try {
if(!req.session.isLogged) {
console.error('ERROR: Edit anime record request. Użytkownik nie jest zalogowany');
return res.status(401).json({
mess: 'Użytkownik nie jest zalogowany',
complete: false
});
}
if(!req.body) {
console.error('ERROR: Edit anime record request. Użytkownik nie jest zalogowany');
return res.status(401).json({
mess: 'Użytkownik nie jest zalogowany',
complete: false
});
}
const updateData = req.body;
const userHash = req.session.user_hash;
const imgPaths = req.session.img_files;
const userId = req.session.user_id;
//Aktualizacja obrazu
const image = await PosterUpdater(updateData, imgPaths);
// Dane do aktualizacji tabeli anm_animes
const data = {
id: updateData.id,
user: userId,
title: updateData.title,
url: updateData.url,
episodes: updateData.episodes,
miniature: image.miniature,
updateMiniature: image.update
};
// Dane do aktualizacji tabeli anm_descriptions
const dsdata = {
anime: updateData.id,
description: updateData.description,
poster: image.poster,
posterUpdate: image.update
};
//Aktualizuj rekord
await AnimeRepository.Update(data);
//Aktualizacja lub kasowanie przypisania anime do danej grupy
await SergregateUpdate(userId, updateData);
//Aktualizacja rekordu descryption
await DescriptionUpdate(dsdata);
const uploadDirectory = path.join(__dirname, '../../upload', userHash);
if(fs.existsSync(uploadDirectory)) {
fs.rmSync(uploadDirectory, { recursive: true });
}
res.status(200).json({
mess: 'Rekord został zaktualizowany',
complete: true
});
}
catch(e) {
console.error(`ERROR: Nie udało się zaktualizować recordu: ${e}`);
res.status(500).json({
mess: 'Nie udało się zaktualizować rekordu',
complete: false
});
}
}
module.exports = EditAnimeRecord;

View file

@ -0,0 +1,33 @@
const GroupRepository = require('../database/GroupRepository');7
async function EditGroupRecord(req, res)
{
try {
if(!req.session.isLogged) {
console.error(`ERROR: Użytkownik nie jest zalogowany!`);
return res.status(401).json({
mess: 'Nie udało się edytować nazwy grupy',
complete: false
});
}
const grTitle = req.body.title;
const grId = req.body.gid;
await GroupRepository.Edit(grId, grTitle);
res.status(200).json({
mess: 'Nazwa grupy edytowana',
complete: true
});
}
catch(e) {
console.error(`ERROR: Nie udało sie edytować grupy: ${e}`);
res.status(500).json({
mess: 'Nie udało się edytować nazwy grupy',
complete: false
});
}
}
module.exports = EditGroupRecord;

View file

@ -0,0 +1,43 @@
const AnimeRepository = require('../database/AnimeRepository');
const SegregatedRepository = require('../database/SegregatedRepository');
const imageConfig = require ('../../config/image.json');
async function GetAnimeRecord(req, res) {
try {
if(!req.session.isLogged) {
console.error('ERROR: Użytkownik nie jest zalogowany');
return res.status(401).json({mess: 'Persmision Deniet!'});
}
if(!req.query.anime) {
console.error('ERROR: Nie podano ID do pobrania rekordu');
return res.status(400).json({mess: 'No data'});
}
const anime = req.query.anime;
const user = req.session.user_id;
const animeResult = await AnimeRepository.GetRecord(anime, user);
const groupIdResult = await SegregatedRepository.GetRecord(anime, user);
//Serializacja danych
const img = animeResult.ds_poster ? `data:image/${imageConfig.type};base64,${Buffer.from(animeResult.ds_poster).toString('base64')}` : null;
const data = {
title: animeResult.an_title,
url: animeResult.an_url,
description: animeResult.ds_description,
episodes: animeResult.an_episodes,
group: groupIdResult,
image: img
};
res.status(200).json(data);
}
catch(e) {
console.error(`ERROR: Nie można pobrać danych: ${e}`);
res.status(500).json({mess: 'Server Error!'});
}
}
module.exports = GetAnimeRecord;

View file

@ -0,0 +1,69 @@
const animeRepo = require('../database/AnimeRepository');
const groupsRepo = require('../database/GroupRepository');
const imageConfig = require ('../../config/image.json');
function SerializedAnime(animes) {
let img = animes.an_miniature ? `data:image/${imageConfig.type};base64,${Buffer.from(animes.an_miniature).toString('base64')}` : null;
let group = animes.st_group == null ? 0 : animes.st_group;
return {
id: animes.an_id,
title: animes.an_title,
date: animes.an_date,
url: animes.an_url,
episodes: animes.an_episodes,
img: img,
fav: {
status: animes.fv_state,
episode: animes.fv_episode
},
group: group
};
}
function PreprareAnime(animes){
let tmp = [];
for(let i=0; i < animes.length; i++){
tmp.push(SerializedAnime(animes[i]));
}
return tmp;
}
async function GetAnimesSerialized(req, res) {
if(!req.session.user_id){
return res.status(401).json({mess: 'Brak zalogowanej sessji używkownika'});
}
const groups = await groupsRepo.Get(req.session.user_id);
const animes = await animeRepo.GetAll(req.session.user_id);
const data = {
animes: PreprareAnime(animes),
groups: groups
};
res.status(200).json(data);
}
async function GetAnimesFitering(req, res) {
if(!req.session.user_id){
return res.status(401).json({mess: 'Brak zalogowanej sessji używkownika'});
}
const grid = req.body.group > 0 ? req.body.group : null;
const stid = req.body.status > -1 ? req.body.status : null;
//console.log(`rGR: ${req.body.group} ___ rST: ${req.status}`);
console.log(`GRP: ${grid} ___ STN: ${stid}`);
const raw = await animeRepo.GetAll(req.session.user_id, grid, stid);
const anime = PreprareAnime(raw);
res.status(200).json(anime);
}
module.exports = {
GetAnimesSerialized,
GetAnimesFitering,
};

View file

@ -0,0 +1,42 @@
const AnimeRepository = require('../database/AnimeRepository');
const imageConfig = require ('../../config/image.json');
async function GetDescription(req, res) {
try {
if(!req.session.isLogged) {
console.error('DESCRYPTION ERROR: Urzytkownik nie jest zalogowany');
return res.status(401).json(null);
}
const anime_id = req.query.anime;
if(isNaN(anime_id)) {
console.error('DESCRYPTION ERROR: Błędne dane wejściowe');
return res.status(400).json(null);
}
const des = await AnimeRepository.GetDescription(anime_id, req.session.user_id);
if(!des) {
console.error('DESCRYPTION ERROR: Nie pobrano danych z DB')
return res.status(500).json(null);
}
const img = des.ds_poster ? `data:image/${imageConfig.type};base64,${Buffer.from(des.ds_poster).toString('base64')}` : null;
const result = {
title: des.an_title,
episodes: des.an_episodes,
description: des.ds_description,
img: img
};
res.status(200).json(result);
}
catch(e) {
console.error(`Nie udało się pobrać opisu! ${e}`);
res.status(500).json(null);
}
}
module.exports = GetDescription;

View file

@ -0,0 +1,28 @@
const GroupRepository = require('../database/GroupRepository');
async function GetGroupList(req, res) {
try {
if(!req.session.isLogged) {
console.error(`ERROR: Użytkownik nie jest zalogowany!`);
return res.status(401).json({
mess: 'Nie jesteś zalogowany',
complete: false
});
}
const userId = req.session.user_id;
const result = await GroupRepository.Get(userId);
res.status(200).json(result);
}
catch(e) {
console.error(`ERROR: Nie udało się pobrać listy grup: ${e}`);
res.status(500).json({
mess: 'Nie udało się pobrac listy grup',
complete: false
});
}
}
module.exports = GetGroupList;

View file

@ -0,0 +1,23 @@
const faviriteRepo = require('../database/FavoritesRepository');
async function UpdateFavState(req, res) {
if(!req.session.isLogged) {
console.error('UPDATE STATUS ERROR: Użytkowanik nie jest zalogowany');
res.status(401).json({mess: 'Access Deniet'});
}
const {id, episode, status} = req.body;
if(isNaN(id) && isNaN(episode) && isNaN(status)) {
console.error('Dane nie są liczbami \n ' + id + '\n' + episode + '\n' + status);
return res.status(400).json({mess: 'Niepoprawne dane'});
}
var ep = episode !== undefined ? episode : null;
var st = status !== undefined ? status : null;
var update = await faviriteRepo.Set(ep, st, id, req.session.user_id);
res.status(200).json({mess: 'State update'});
}
module.exports = UpdateFavState;

View file

@ -0,0 +1,29 @@
//osobne pliki
const GetAnime = require('./GetAnimesSerialized').GetAnimesSerialized;
const GetFilteringAnime = require('./GetAnimesSerialized').GetAnimesFitering;
const GetDescription = require('./GetDescription');
const UpdateState = require('./UpdateState');
const GetAnimeRecord = require('./GetAnimeRecord');
const AddGrouptoRecord = require('./AddGroupToRecord');
const EditGroupRecord = require('./EditGroupRecord');
const GetGroupList = require('./GetGroupList');
const AddAnimeToRecord = require('./AddAnimeToRecord');
const EditAnimeRecord = require('./EditAnimeRecord');
const DeleteRecords = require('./DeleteRecords');
module.exports = {
GetAnime,
GetFilteringAnime,
GetDescription,
UpdateState,
GetAnimeRecord,
AddGrouptoRecord,
EditGroupRecord,
GetGroupList,
AddAnimeToRecord,
EditAnimeRecord,
DeleteRecords
};

8
server_2.1/src/cors.js Normal file
View file

@ -0,0 +1,8 @@
const cors = require('cors');
module.exports = cors({
origin: 'http://localhost:8080',
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
//allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true
})

View file

@ -0,0 +1,247 @@
const db = require('./DataBaseConnection');
const DateTime = require('../DateTime');
class AnimeRepository {
constructor() {
this.db = db.getConnection();
}
async GetAll(user, group = null, status = null) {
try {
const sql = `
SELECT
anm_animes.an_id,
anm_animes.an_title,
anm_animes.an_date,
COALESCE(anm_favorites.fv_episode, 1) AS fv_episode,
COALESCE(anm_favorites.fv_state, 0) AS fv_state,
COALESCE(anm_segregated.st_group, 0) AS st_group,
anm_animes.an_url,
anm_animes.an_episodes,
anm_animes.an_miniature
FROM anm_animes
LEFT JOIN anm_favorites ON anm_animes.an_id = anm_favorites.fv_anime AND anm_favorites.fv_user=?
LEFT JOIN anm_segregated ON anm_animes.an_id = anm_segregated.st_anime AND anm_segregated.st_user=?
WHERE anm_animes.an_user=?
AND (anm_segregated.st_group=? OR ? IS NULL)
AND (anm_favorites.fv_state=? OR ? IS NULL);
`;
const [rows] = await this.db.execute(sql, [user, user, user, group, group, status, status]);
return rows;
}
catch(e) {
console.error(e);
return null;
}
}
async GetDescription(id, user) {
try {
const sql = `
SELECT
anm_animes.an_title,
anm_animes.an_episodes,
COALESCE(anm_descriptions.ds_description, NULL) AS ds_description,
COALESCE(anm_descriptions.ds_poster, NULL) AS ds_poster
FROM anm_animes
LEFT JOIN anm_descriptions ON anm_animes.an_id = anm_descriptions.ds_anime
WHERE anm_animes.an_id=? AND anm_animes.an_user=?;
`;
const [rows] = await this.db.execute(sql, [id, user]);
return rows[0];
}
catch(e) {
console.error(e);
return null;
}
}
async Delete(anime, user) {
try {
const _anime = Array.isArray(anime) ? anime.map(Number) : [Number(anime)];
if (_anime.some(isNaN)) {
throw new Error("ANIME REPO: Nieprawidłowa wartość w anime");
}
const placeholder = _anime.map(() => '?').join(',');
const sql = `DELETE FROM anm_animes WHERE an_id IN (${placeholder}) AND an_user = ?;`;
const [result] = await this.db.execute(sql, [..._anime, user]);
return result.affectedRows;
}
catch(e) {
console.error(`ERROR: Nie można skasować rekordów Anime: ${e}`);
return -1;
}
}
async Update(data) {
try {
const sql = `
UPDATE anm_animes
SET
an_title = ?,
an_url = ?,
an_episodes = ?,
an_miniature = IF(?, ?, an_miniature)
WHERE
an_id = ?
AND
an_user = ?;
`;
const [rows] = await this.db.execute(sql, [
data.title,
data.url,
data.episodes,
//Aktualizacja miniaturki
data.updateMiniature,
data.miniature,
//Wskazanie indexu recordu
data.id,
data.user
]);
return rows;
}
catch(e) {
console.error(`ERROR QUERY ANIME UPDATE: Nie udało się zaktualizaować rekordu ${e}`);
return null;
}
}
// Dodaj nowe anime do bazydanech
async Add(anime, blob, user) {
try {
const sql = `
INSERT INTO anm_animes (
an_date,
an_title,
an_url,
an_episodes,
an_user,
an_miniature,
) VALUES (?, ?, ?, ?, ?, ?);
`;
const today = DateTime.GetDateNow();
const [result] = await this.db.execute(sql, [
today,
anime.title,
anime.url,
anime.episodes,
user,
blob.miniature
]);
return result.insertId;
}
catch(e){
console.error(`ERROR! Nie udało się dodać anime do bazy danych: ${e}`);
return null;
}
}
// Dodaj opis do bazy danych
async AddDescription(data) {
try {
const sql = `
INSERT INTO anm_descriptions (
ds_anime,
ds_description,
ds_poster
) VALUES (?, ?, ?);
`;
const [rows] = await this.db.execute(sql, [
data.anime,
data.description,
data.poster
]);
return rows[0];
}
catch(e) {
console.error(`ERROR: Nie udało się dodać opisu: ${e}`);
return null;
}
}
// Edytuj opis
async EditDescription(data) {
try {
const sql = `
UPDATE anm_descriptions
SET
ds_description = ?,
ds_poster = IF(?, ?, ds_poster)
WHERE ds_anime = ?;
`;
const [rows] = await this.db.execute(sql, [
data.description,
//Warunkowa aktualizacja grafiki
data.posterUpdate,
data.poster,
data.anime
]);
return rows[0];
}
catch(e) {
console.error(`ERROR: Nie udało się dodać opisu: ${e}`);
return null;
}
}
// Skasuj opis
async DeleteDescription(anime) {
try {
const sql = `DELETE FROM anm_descriptions WHERE ds_anime = ?;`;
const [rows] = await this.db.execute(sql, [anime]);
return rows[0];
}
catch(e) {
console.error(`ERROR: Nie udało się skasować opisu: ${e}`);
return null;
}
}
// Pobierz konkretny rekord anime
async GetRecord(id, user) {
try {
const sql = `
SELECT
anm_animes.an_title,
anm_animes.an_url,
anm_animes.an_episodes,
COALESCE(anm_descriptions.ds_description, NULL) AS ds_description,
COALESCE(anm_descriptions.ds_poster, NULL) AS ds_poster
FROM anm_animes
LEFT JOIN anm_descriptions ON anm_animes.an_id = anm_descriptions.ds_anime
WHERE anm_animes.an_id = ? AND anm_animes.an_user = ?;
`;
const [rows] = await this.db.execute(sql, [id, user]);
return rows[0];
}
catch(e) {
console.error(`ERROR: Nie udało się pobrać recordu: ${e}`);
return null;
}
}
}
module.exports = new AnimeRepository();

View file

@ -0,0 +1,29 @@
const mysql = require('mysql2/promise');
class DataBase {
constructor() {
this.con = mysql.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
dateStrings: true,
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
}
// Konektor
getConnection() {
return this.con;
}
// Wykonaj zapytanie
async Commit(sql, data) {
const [rows] = await this.con.execute(sql, data);
return rows;
}
}
module.exports = new DataBase();

View file

@ -0,0 +1,86 @@
const db = require('./DataBaseConnection');
class FavoritesRepository {
constructor() {
this.db = db.getConnection();
}
async Get(user) {
try {
const sql = `SELECT fv_anime, fv_episode, fv_state FROM anm_favorites WHERE fv_user = ?;`;
const [rows] = await this.db.query(sql, [user]);
return rows;
}
catch(e) {
console.error('Favorites Get Query ERROR: ' + e);
return null;
}
}
async Set(episode, state, anime, user) {
try {
const sql = `
UPDATE anm_favorites
SET
fv_episode = CASE WHEN ? IS NOT NULL THEN ? ELSE fv_episode END,
fv_state = CASE WHEN ? IS NOT NULL THEN ? ELSE fv_state END
WHERE
fv_user = ?
AND fv_anime = ?;
`;
const [updateRequest] = await this.db.query(sql, [episode, episode, state, state, user, anime]);
if(updateRequest.affectedRows === 0) {
return this.Add(episode, state, anime, user);
}
return true;
}
catch(e) {
console.error('Favorites Set Query ERROR: ' + e);
return false;
}
}
async Add(episode, state, anime, user) {
try {
const sql = `
INSERT INTO anm_favorites (fv_user, fv_anime, fv_episode, fv_state)
VALUES (?, ?,
COALESCE(?, DEFAULT(fv_episode)),
COALESCE(?, DEFAULT(fv_state)));
`;
await this.db.query(sql, [user, anime, episode, state]);
return true;
}
catch(e) {
console.error('Favorites Add Query ERROR: ' + e);
return false;
}
}
async Delete(anime, user) {
try {
const _anime = Array.isArray(anime) ? anime.map(Number) : [Number(anime)];
if (_anime.some(isNaN)) {
throw new Error("FAVORITES REPO: Nieprawidłowa wartość w anime");
}
const placeholder = _anime.map(() => '?').join(',');
const sql = `DELETE FROM anm_favorites WHERE fv_anime IN (${placeholder}) AND fv_user = ?;`;
const [result] = await this.db.execute(sql, [..._anime, user]);
return result.affectedRows;
}
catch(e) {
console.error('Favorites Delete Query ERROR: ' + e);
return -1;
}
}
}
module.exports = new FavoritesRepository();

View file

@ -0,0 +1,62 @@
const db = require('./DataBaseConnection');
class GroupRepository {
constructor() {
this.db = db.getConnection();
}
async Get(user) {
try {
const sql = 'SELECT gr_id, gr_title FROM anm_groups WHERE gr_user=?';
const [rows] = await this.db.query(sql, [user]);
console.log('pobieranie grupy')
return rows;
}
catch(e) {
console.error('Groups Get Query ERROR: ' + e);
return null;
}
}
async Add(title, user) {
try {
const sql = `INSERT anm_groups (gr_title, gr_user) VALUES (?, ?);`;
const [rows] = await this.db.execute(sql, [title, user]);
return rows.affectedRows;
}
catch(e) {
console.error('Groups Add Query ERROR: ' + e);
return null;
}
}
async Edit(id, title) {
try {
const sql = `UPDATE anm_groups SET gr_title = ? WHERE gr_id = ?;`;
await this.db.execute(sql, [title, id]);
}
catch(e) {
console.error('Groups Edit Query ERROR: ' + e);
}
}
async Delete(group, user) {
try {
const _group = Array.isArray(group) ? group.map(Number) : [Number(group)];
if (_group.some(isNaN)) {
throw new Error("GROUP REPO: Nieprawidłowa wartość w group");
}
const placeholder = _group.map(() => '?').join(',');
const sql = `DELETE FROM anm_groups WHERE gr_id IN (${placeholder}) AND gr_user = ?;`;
await this.db.execute(sql, [..._group, user]);
}
catch(e) {
console.error('Groups Delete Query ERROR: ' + e);
}
}
}
module.exports = new GroupRepository();

View file

@ -0,0 +1,99 @@
const db = require('./DataBaseConnection');
class SegregatedRepository {
constructor() {
this.db = db.getConnection();
}
async Get(user) {
try {
const sql = 'SELECT st_anime, st_group FROM anm_segregated WHERE st_user=?';
const [rows] = await this.db.execute(sql, [user]);
console.log('pobieranie grupy')
return rows;
}
catch(e) {
console.error('Segregated Get Query ERROR: ' + e);
return null;
}
}
async Add(anime, group, user) {
try {
const sql = `INSERT anm_segregated (st_user, st_anime, st_group) VALUES (?, ?, ?);`;
await this.db.execute(sql, [user, anime, group]);
}
catch(e) {
console.error('Segregated Add Query ERROR: ' + e);
}
}
async Edit(group, anime, user) {
try {
const sql = `UPDATE anm_segregated SET st_group = ? WHERE st_anime = ? AND st_user = ?;`;
const [result] = await this.db.execute(sql, [group, anime, user]);
return result.affectedRows;
}
catch(e) {
console.error('Segregated Edit Query ERROR: ' + e);
return -1;
}
}
async DeleteByAnime(anime, user) {
try {
const _anime = Array.isArray(anime) ? anime.map(Number) : [Number(anime)];
if (_anime.some(isNaN)) {
throw new Error("SEGREGATE REPO: Nieprawidłowa wartość w anime");
}
const placeholder = _anime.map(() => '?').join(',');
const sql = `DELETE FROM anm_segregated WHERE st_anime IN (${placeholder}) AND st_user = ?;`;
const [result] = await this.db.execute(sql, [..._anime, user]);
return result.affectedRows;
}
catch(e) {
console.error('Groups Delete Query ERROR: ' + e);
return -1;
}
}
//Group musi byc tablicą
async DeleteByGroup(group, user) {
try {
const _group = Array.isArray(group) ? group.map(Number) : [Number(group)];
if (_group.some(isNaN)) {
throw new Error("SEGREGATE REPO: Nieprawidłowa wartość w group");
}
const placeholder = _group.map(() => '?').join(',');
const sql = `DELETE FROM anm_segregated WHERE st_group IN (${placeholder}) AND st_user = ?;`;
const [result] = await this.db.execute(sql, [..._group, user]);
return result.affectedRows;
}
catch(e) {
console.error('Groups Delete Query ERROR: ' + e);
return -1;
}
}
async GetRecord(anime, user) {
try {
const sql = `SELECT st_group FROM anm_segregated WHERE st_anime = ? AND st_user = ?`;
const [rows] = await this.db.execute(sql, [anime, user]);
return rows[0] ? rows[0].st_group : 0;
}
catch(e) {
console.error(`ERROR: Nie udało się pobrać recordu: ${e}`);
return 0;
}
}
}
module.exports = new SegregatedRepository();

View file

@ -0,0 +1,149 @@
const db = require('./DataBaseConnection');
const passwd = require('../passwd');
class UserRepository {
constructor() {
this.db = db.getConnection();
}
//Test poprawności podanych danych logowania
async Valid(email, password) {
const sql = `SELECT passwd FROM users WHERE email = ?`;
const [rows] = await this.db.query(sql, [email]);
if (rows.affectedRows === 0) {
console.log("Nie znaleziono użytkowanika: " + email);
return false;
}
return await passwd.ComparePassword(password, rows[0].passwd);
}
//Test poprawności podanych danych logowania
async ValidPass(id, password) {
const sql = `SELECT passwd FROM users WHERE id = ?`;
const [rows] = await this.db.query(sql, [id]);
if (rows.affectedRows === 0) {
console.log("Nie znaleziono użytkowanika");
return false;
}
return await passwd.ComparePassword(password, rows[0].passwd);
}
//Pobieranie danych użytkowanika na podstawie adresu email
async GetForEmail(email) {
try {
const sql = `SELECT id, user, date_registration, avatar, preference FROM users WHERE email = ?`;
const [rows] = await this.db.query(sql, [email]);
if(rows.affectedRows === 0) {
console.error('Nie udało się pobrać danych użytkownika :c');
return null;
}
const avBlob = rows[0].avatar
const user = {
id: rows[0].id,
name: rows[0].user,
regdate: rows[0].date_registation,
avatar: avBlob ? avBlob.toString('base64') : null,
preference: rows[0].preference ? rows[0].preference : {}
}
return user;
}
catch(e) {
console.error('Pobieranie danych użytkownika:\n' + e);
return null;
}
}
async UpdatePreference(pref, user) {
try {
const sql = `
UPDATE users SET
preference = ?
WHERE id = ?;
`;
await this.db.execute(sql, [pref, user]);
}
catch(e) {
console.error(`ERROR: Nie udało się zaktualizować recordu preference: ${e}`);
}
}
//Aktualizacja hasła
async UpdatePassword(id, hash) {
try {
const sql = `UPDATE users SET passwd = ? WHERE id = ?`;
const [rows] = await this.db.execute(sql, [hash, id]);
return rows.affectedRows;
}
catch(e) {
console.error(`ERROR: Nie udało się zaktualizować hasła: ${e}`);
return -1;
}
}
async UpdateName(id, name) {
try {
const sql = `UPDATE users SET user = ? WHERE id = ?`;
const [rows] = await this.db.execute(sql, [name, id]);
return rows.affectedRows;
}
catch(e) {
console.error(`ERROR: Nie udało się zaktualizować nazwy użytkownika: ${e}`);
return -1;
}
}
async UpdateAvatar(id, blob) {
try {
const sql = `UPDATE users SET avatar = ? WHERE id = ?`;
const [rows] = await this.db.execute(sql, [blob, id]);
return rows.affectedRows;
}
catch(e) {
console.error(`ERROR: Nie udało się zaktualizować avatara: ${e}`);
return -1;
}
}
async DeleteAvatar(id) {
try {
const sql = `UPDATE users SET avatar = NULL WHERE id = ?`;
const [rows] = await this.db.execute(sql, [id]);
return rows.affectedRows;
}
catch(e) {
console.error(`ERROR: Nie udało się skasować avatara: ${e}`);
return -1;
}
}
async CheckEmail(email) {
try {
const sql = `SELECT NULL FROM users WHERE email = ?`;
const [rows] = this.db.execute(sql, email);
if (rows > 0) {
return true;
}
return false;
}
catch(e) {
console.error(`ERROR: Nie udało się sprawdzić email: ${e}`);
return false;
}
}
}
module.exports = new UserRepository();

View file

@ -0,0 +1,63 @@
const db = require('./DataBaseConnection');
class VariablesRepository {
constructor() {
this.db = db.getConnection();
}
async GetValue(varname) {
try {
const sql = `SELECT data FROM variables WHERE name = ?`;
const [rows] = await this.db.execute(sql, [varname]);
if (rows.afectedRows < 1) {
return null;
}
return rows[0];
}
catch(e) {
console.error(`Variables Repository: Nie udało się pobrać danych z DB: ${e}`);
return null;
}
}
async SetValue(varname, data) {
try {
const sql = `UPDATE variables SET data = ? WHERE name = ?`;
const [rows] = await this.db.execute(sql, [data, varname]);
if (rows.afectedRows < 1) {
const sql = `INSERT INTO (name, data) VALUES (?, ?)`;
const [rows] = await this.db.execute(sql, [varname, data]);
if (rows.afectedRows < 1) {
return false;
}
}
return true;
}
catch(e) {
console.error(`Variables Repository: Nie udało się zapisać danych: ${e}`);
return null;
}
}
async DeleteValue(varname) {
try {
const sql = `DELETE FROM variables WHERE name = ?`;
const [rows] = this.db.execute(sql, [varname]);
if (rows.afectedRows < 1) {
return false;
}
return true;
}
catch(e) {
console.error(`Variables Repository: Nie udało się skasować danych: ${e}`);
return false;
}
}
}

View file

@ -0,0 +1,20 @@
const fs = require('fs');
const ProcessImage = require('./ProcessImage');
const imgConfig = require('./../../config/image.json');
async function AvatarImage(raw, hash) {
try {
if (!fs.existsSync(raw)) {
console.error(`Plik wejściowy nie istnieje: ${raw}`);
return null;
}
const avatarSize = imgConfig.avatar;
return await ProcessImage(raw, hash, 'avatar', avatarSize);
}
catch(e) {
console.error(`POSTER IMAGE ERROR: ${e}`);
}
}
module.exports = AvatarImage;

View file

@ -0,0 +1,21 @@
const fs = require('fs');
const path = require('path');
async function ClearDirectory(directoryPath) {
try {
// Pobierz listę plików i folderów w katalogu
const files = fs.readdirSync(directoryPath);
// Usuń każdy plik lub folder
for (const file of files) {
const fullPath = path.join(directoryPath, file);
fs.unlinkSync(fullPath);
}
console.log(`Zawartość katalogu ${directoryPath} została usunięta.`);
} catch (error) {
console.error(`Błąd podczas usuwania zawartości katalogu: ${error.message}`);
}
}
module.exports = ClearDirectory();

View file

@ -0,0 +1,34 @@
const fs = require('fs');
const path = require('path');
async function DeleteImage(req, res) {
try {
if(!req.session.isLogged) {
console.error('DESCRYPTION ERROR: Urzytkownik nie jest zalogowany');
return res.status(401).json(null);
}
if(req.body.id) {
console.log('Ta funkcja narazie jest niedostępna!');
}
else {
try {
const userUploadPath = path.join(__dirname, '../../upload', req.session.user_hash);
console.log('Kasowanie katalogu: ' + userUploadPath);
if(fs.existsSync(userUploadPath)) {
fs.rmSync(userUploadPath, { recursive: true });
}
}
catch(e) {
console.error(`Nie udało się skasować katalogu użytkownika upload: ${e}`);
}
}
res.status(204);
}
catch(e) {
console.error(`Nie udało się skasować obrazu! ERROR: ${e}`);
}
}
module.exports = DeleteImage;

View file

@ -0,0 +1,20 @@
const fs = require('fs');
async function LoadImgToBlob(pathFile) {
try {
if(!pathFile) {
return null;
}
if(!fs.existsSync(pathFile)){
return null;
}
return fs.readFileSync(pathFile);
}
catch(e) {
console.error(`ERROR! Nie udalo się załadować pliku jako blob: ${e}`);
return null;
}
}
module.exports = LoadImgToBlob;

View file

@ -0,0 +1,25 @@
const fs = require('fs');
const ProcessImage = require('./ProcessImage');
const imgConfig = require('./../../config/image.json');
async function PosterImage(raw, hash) {
try {
if (!fs.existsSync(raw)) {
console.error(`Plik wejściowy nie istnieje: ${raw}`);
return null;
}
const posterSize = imgConfig.poster;
const miniatureSize = imgConfig.miniature;
const poster = await ProcessImage(raw, hash, 'poster', posterSize);
const miniature = await ProcessImage(raw, hash, 'miniature', miniatureSize);
return {poster: poster, miniature: miniature, format: imgConfig.format};
}
catch(e) {
console.error(`POSTER IMAGE ERROR: ${e}`);
}
}
module.exports = PosterImage;

View file

@ -0,0 +1,43 @@
const sharp = require('sharp');
const fs = require('fs');
const path = require('path');
const imgConfig = require('./../../config/image.json');
async function ImageRescale(raw, out, size) {
sharp.cache(false);
sharp.simd(false);
try {
await sharp(raw)
.resize(size)
.jpeg(imgConfig.quality)
.toFile(out);
}
catch(e) {
console.error(`ERROR IMAGE RESIZE: ${e}`);
}
}
async function ProcessImage(raw, hash, type, size) {
const dph = path.resolve(__dirname, `../../upload/${hash}/${type}`);
const out = path.join(dph, `${type}.${imgConfig.extension}`);
try {
fs.mkdirSync(dph, {recursive: true});
if (!fs.existsSync(raw)) {
console.error(`Plik wejściowy nie istnieje: ${raw}`);
return null;
}
await ImageRescale(raw, out, size);
return out;
}
catch(e) {
console.error(`ERROR PROCESSING IMAGE: ${e}`);
return null;
}
}
module.exports = ProcessImage;

View file

@ -0,0 +1,75 @@
const fs = require('fs');
const path = require('path');
const PosterImage = require('./PosterImage');
const LoadImgToBlob = require('./LoadimgToBlob');
const imageConfig = require ('../../config/image.json');
async function clearDirectory(directoryPath) {
try {
// Pobierz listę plików i folderów w katalogu
const files = fs.readdirSync(directoryPath);
// Usuń każdy plik lub folder
for (const file of files) {
const fullPath = path.join(directoryPath, file);
fs.unlinkSync(fullPath);
}
console.log(`Zawartość katalogu ${directoryPath} została usunięta.`);
} catch (error) {
if (error.code === 'ENOENT') {
console.log(`Katalog ${directoryPath} nie istnieje.`);
} else {
console.error(`Błąd podczas usuwania zawartości katalogu: ${error.message}`);
}
}
}
async function UploadImageFromFile(req, res) {
try {
if(!req.session.isLogged) {
console.error('DESCRYPTION ERROR: Urzytkownik nie jest zalogowany');
return res.status(401).json(null);
}
if (!req.files || !req.files.file) {
console.error('')
return res.status(400).json({ error: 'No file uploaded' });
}
const uploadPath = path.join(__dirname, `../../upload/${req.session.user_hash}/raw`);
console.log(uploadPath);
fs.mkdirSync(uploadPath, { recursive: true });
await clearDirectory(uploadPath);
const uploadedFile = req.files.file;
const fileExtension = path.extname(uploadedFile.name); // np. ".jpg"
const newFileName = `raw-uploaded-image${Date.now()}${fileExtension}`;
const filePath = path.join(uploadPath, newFileName);
await uploadedFile.mv(filePath);
const posterPath = await PosterImage(filePath, req.session.user_hash);
req.session.img_files = posterPath;
//Wczytaj grafikę i przekonwertuj na BASE64
const blob = await LoadImgToBlob(posterPath.poster);
const b64 = `data:image/${imageConfig.type};base64,${Buffer.from(blob).toString('base64')}`;
res.status(200).json({
message: 'File uploaded successfully',
url: b64
});
}
catch(e) {
console.error(`ERROR UPLOAD FILE #2: \n ${e}`);
res.status(500).json({
success: false,
mess: 'Nie udało się przesłać grafiki'
});
}
}
module.exports = UploadImageFromFile;

View file

@ -0,0 +1,10 @@
const UploadImageFromFile = require('./UploadImgFile');
const DeleteImage = require('./DeleteImage');
const LoadImgToBlob = require('./LoadimgToBlob');
module.exports = {
UploadImageFromFile,
DeleteImage,
LoadImgToBlob,
};

42
server_2.1/src/mail.js Normal file
View file

@ -0,0 +1,42 @@
const nodemailer = require('nodemailer');
class Mail {
constructor() {
this.transporter = nodemailer.createTransport({
host: 'localhost',
port: 25,
secure: false
});
this.mailOptions = {
from: 'noreply@server.net',
to: '',
subject: '',
text: ''
};
}
SetMail(mail) {
this.mailOptions = {
...this.mailOptions,
to: mail.to,
subject: mail.subject,
text: mail.text
};
}
async SendMail() {
try {
const info = await this.transporter.sendMail(this.mailOptions);
console.log(`Mail Został wysłany: ${info.response}`);
return true;
}
catch(e) {
console.error(`Nie udało się wysłać wiadomości email: ${e}`);
return false;
}
}
}
module.exports = new Mail();

35
server_2.1/src/passwd.js Normal file
View file

@ -0,0 +1,35 @@
const bcrypt = require('bcrypt');
function CompareNewPasswords(newPass, confirmPass) {
if (newPass === confirmPass) {
return true;
}
return false;
}
function CheckPasswodLength(newPass) {
if (newPass.length < 8) {
return false;
}
return true;
}
async function HashPassword(newPass) {
const saltRounds = 12;
const someOtherPlaintextPassword = 'not_bacon';
return await bcrypt.hash(newPass, saltRounds);
}
async function ComparePassword(pass, hash) {
return await bcrypt.compare(pass, hash);
}
module.exports = {
CompareNewPasswords,
CheckPasswodLength,
HashPassword,
ComparePassword,
}

27
server_2.1/src/session.js Normal file
View file

@ -0,0 +1,27 @@
const session = require('express-session');
const MySQLStore = require('express-mysql-session')(session);
const dbOptions = {
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
createDatabaseTable: true // Automatyczne tworzenie tabeli
};
module.exports = session({
key: 'animu_lista_cookie_session', // Nazwa ciasteczka sesji
secret: process.env.EX_KEY, // Klucz tajny używany do podpisywania ciasteczek
store: new MySQLStore(dbOptions), // Magazyn sesji
resave: false, // Unikaj zapisywania sesji, jeśli nie zmieniły się dane
saveUninitialized: false, // Nie zapisuj pustych sesji
cookie: {
maxAge: 7 * 24 * 60 * 60 * 1000, // Czas życia ciasteczka w ms (7 dni) dni/godzin/minut/sekund/ms
secure: false, // Ustaw `true` dla HTTPS
sameSite: 'lax', // `lax` dla ochrony przed atakami CSRF
},
// Funkcje serializacji i deserializacji
serialize: (session) => JSON.stringify(session), // Serializacja do JSON
unserialize: (json) => JSON.parse(json) // Deserializacja z JSON
});

View file

@ -0,0 +1,9 @@
//import { createChallenge, verifySolution } from 'altcha';
async function AltchaHumanTest(req, res) {
//const { altcha } = req.body;
console.log("Altcha na razie nie działa :c");
}
module.exports = AltchaHumanTest;

View file

@ -0,0 +1,37 @@
const userRepo = require('../database/UserRepository');
async function DeleteAvatar(req, res) {
try {
if (!req.session.isLogged) {
console.error('ERROR: Użytkownik nie jest zalogowany by usunąć avatar');
return res.status(401).json({
success: false,
mess: 'Nie jesteś zalogowany!'
});
}
const userId = req.session.user_id;
if(await userRepo.DeleteAvatar(userId) < 1) {
console.error('ERROR: Nie udało się skasować avatara z bazy danych');
return res.status(400).json({
success: false,
mess: 'Nie udało się skasować avatara'
});
}
res.status(200).json({
success: true,
mess: 'Pomyślnie skasowano avatar'
});
}
catch(e) {
console.error(`ERROR: Nie udało się skasować avatara: ${e}`);
res.status(500).json({
success: false,
mess: 'Nie udało się skasować avatara'
});
}
}
module.exports = DeleteAvatar;

View file

@ -0,0 +1,71 @@
const userRepo = require('../database/UserRepository');
const jwt = require('jsonwebtoken');
const validator = require('validator');
const crypto = require('crypto');
async function LoginProcess(req, res) {
try {
const {email, password, remember} = req.body;
if(!validator.isEmail(email) && !password || typeof remember != 'boolean') {
console.error('Process logowania: Nie prawidłowe dane logowania');
return res.status(400).json({
isLogged: false
});
}
const valid = await userRepo.Valid(email, password);
if(!valid) {
console.error('Process logowania: Nie prawidłowe dane logowania');
return res.status(401).json({
isLogged: false
});
}
const userData = await userRepo.GetForEmail(email);
if(!userData) {
console.error('Process logowania: Błąd pobierania danych');
return res.status(500).json({ isLogged: false });
}
if (!process.env.EX_KEY) {
console.error('Process logowania: Brak klucza JWT');
return res.status(500).json({ isLogged: false });
}
const token = jwt.sign(
{id: userData.id, email: email},
process.env.EX_KEY,
{ expiresIn: '1h' }
);
req.session.isLogged = true;
req.session.user_id = userData.id;
req.session.user_name = userData.name;
req.session.user_regdate = userData.regdate;
req.session.user_avatar = userData.avatar;
req.session.user_preference = JSON.parse(userData.preference);
req.session.user_hash = crypto.createHash('sha256').update(
userData.name + userData.id + userData.regdate).digest('hex');
console.log(`PREF: ${req.session.user_preference}`);
const data = {
isLogged: req.session.isLogged,
token: token,
user: req.session.user_name,
regdate: req.session.user_regdate,
avatar: req.session.user_avatar,
preference: req.session.user_preference,
};
res.status(200).json(data);
}
catch(e) {
console.error('Process logowania TRY FALSE:\n' + e);
res.status(500).json({isLogged: false});
}
}
module.exports = LoginProcess;

View file

@ -0,0 +1,12 @@
function LogoutUser(req, res) {
req.session.destroy(err => {
if (err) {
console.error(err);
return res.status(500).send({ success: false, message: 'Wylogowanie nie powiodło się.' });
}
res.clearCookie('connect.sid'); // Usunięcie ciasteczka sesji
res.send({ success: true, message: 'Wylogowano pomyślnie.' });
});
}
module.exports = LogoutUser;

View file

@ -0,0 +1,52 @@
const mailsend = require('../mail');
const validator = require('validator');
const utility = require('../utility');
async function RecorveryPassword(req, res) {
try {
if (!validator.isEmail(req.body)) {
return res.status(400).json({
mess: "Nieprawidłowy adress email",
success: false
});
}
const email = req.body;
const emailContent = await PrepareMail(email);
mailsend.SetMail(emailContent);
if (await mailsend.SendMail()) {
return res.status(400).json({
mess: "Nieudało się wysłać emaila z linkiem resetującym",
success: false
});
}
res.status(200).json({
mess: "Wysłano link do resetu hasła na adress email",
success: true
});
}
catch(e) {
console.error(`Nie można zresetować hasła: ${e}`);
res.status(500).json({
mess: "Nie można zresetować hasła",
success: false
});
}
}
async function PrepareMail(email) {
const url = '';
const to = 'noreply@server.net';
const subject = 'Recorvery Password';
const emailTemplate = '';
const content = utility.ReplacePlaceholder({RECORVERY_URL: url}, emailTemplate);
return {to: to, subject: subject, text: content};
}
module.exports = RecorveryPassword;

View file

@ -0,0 +1,100 @@
const fs = require('fs');
const path = require('path');
const AvatarImage = require('../image/AvatarImage');
const imm = require('../image');
const userRepo = require('../database/UserRepository');
async function UpdateUserAvatar(req, res) {
try {
if (!req.session.isLogged) {
console.error('ERROR: Użytkownik nie jest zalogowany by zmienić avatar');
return res.status(401).json({
success: false,
mess: 'Nie jesteś zalogowany!'
});
}
//console.log(req.files.file);
if (!req.files || !req.files.file) {
return res.status(400).json({
success: false,
mess: 'Nie udało się załadować pliku'
});
}
const userHash = req.session.user_hash;
const userId = req.session.user_id;
const uploadPath = path.join(__dirname, `../../upload/${userHash}/raw`);
fs.mkdirSync(uploadPath, { recursive: true });
await clearDirectory(uploadPath);
const uploadedFile = req.files.file;
const fileExtension = path.extname(uploadedFile.name);
const newFileName = `raw-uploaded-image${Date.now()}${fileExtension}`;
const filePath = path.join(uploadPath, newFileName);
await uploadedFile.mv(filePath);
const fileAvatar = await AvatarImage(filePath, userHash);
/*
Tutaj ma być blok kodu który przetworzy obrazek
na blob i zapisze go w bazie danych
*/
if(!fileAvatar) {
console.error('ERROR: Brak wewnętrznej ścieżki do przetworzonego pliku avatara');
return res.state(400).json({
success: false,
mess: 'Nie udało się przetworzyć pliku'
});
}
const blob = await imm.LoadImgToBlob(fileAvatar);
console.log("AVATAR DONE!")
if(await userRepo.UpdateAvatar(userId, blob) < 1) {
console.error('ERROR: Nie udało się wgrać avatara do bazy danych');
return res.status(400).json({
success: false,
mess: 'Nie udało się zaktualizować avatara'
});
}
res.status(200).json({
success: true,
mess: 'Pomyślnie zaktualizowano avatar',
avatar: blob.toString('base64')
});
}
catch(e) {
console.error(`ERROR: Nie udało się zaktualizować avatara: ${e}`);
res.status(500).json({
success: false,
mess: 'Nie udało się zaktualizować avatara'
});
}
}
async function clearDirectory(directoryPath) {
try {
// Pobierz listę plików i folderów w katalogu
const files = fs.readdirSync(directoryPath);
// Usuń każdy plik lub folder
for (const file of files) {
const fullPath = path.join(directoryPath, file);
fs.unlinkSync(fullPath);
}
console.log(`Zawartość katalogu ${directoryPath} została usunięta.`);
} catch (error) {
if (error.code === 'ENOENT') {
console.log(`Katalog ${directoryPath} nie istnieje.`);
} else {
console.error(`Błąd podczas usuwania zawartości katalogu: ${error.message}`);
}
}
}
module.exports = UpdateUserAvatar;

View file

@ -0,0 +1,87 @@
const userRepo = require('../database/UserRepository');
const validator = require('validator');
async function UpdateUserName(req, res) {
try {
if (!req.session.isLogged) {
console.error('ERROR: Użytkownik nie jest zalogowany by zmienić nazwe')
return res.status(401).json({
success: false,
mess: 'Nie jesteś zalogowany!'
});
}
const name = req.body.name;
const userId = req.session.user_id;
const userName = req.session.user_name;
console.log(name);
if (name == userName) {
console.error('ERROR: Nazwa użytkownika jest taka sama co poprzednia');
return res.status(400).json({
success: false,
mess: 'Nazwa użytkownika jest taka sama co poprzednia'
});
}
if (!ValidGlyphs(name)) {
console.error('ERROR: Nazwa użytkownika może składać się tylko z cyfr, dużych i małych liter');
return res.status(400).json({
success: false,
mess: 'Nazwa użytkownika może składać się tylko z cyfr, dużych i małych liter bez znaków specjalnych'
});
}
if (!UserNameLength(name)) {
console.error('ERROR: Nazwa użytkownika jest za krutka');
return res.status(400).json({
success: false,
mess: 'Nazwa użytkownika jest za krutka'
});
}
//Aktualizacja nazwy w bazie danych
if (await userRepo.UpdateName(userId, name) < 1) {
console.error('ERROR: Nie udało się zaktualizować nazwy użytkownika');
return res.status(400).json({
success: false,
mess: 'Nie udało się zaktualizować nazwy użytkownika'
});
}
req.session.user_name = name; //Aktualizacja nazwy w sessji
res.status(200).json({
success: true,
username: req.session.user_name,
mess: 'Nazwa użytkownika została zmieniona pomyślnie'
});
}
catch(e) {
console.error(`ERROR: Nie udało się zaktualizować nazwy użytkownika: ${e}`);
res.status(500).json({
success: false,
mess: 'Nie udało się zaktualizować nazwy użytkownika'
});
}
}
//Sprawdza czy długość nazy jest poprawna
function UserNameLength(name) {
const len = name.length;
if(len < 56 && len > 3) {
return true;
}
return false;
}
//Sprawdzenie czy nazwa składa się tylko z liter i cyfr
function ValidGlyphs(name) {
const pattern = /^[a-zA-Z][a-zA-Z0-9_]{2,15}$/;
return pattern.test(name);
}
module.exports = UpdateUserName;

View file

@ -0,0 +1,87 @@
const passwd = require('../passwd');
const userRepo = require('../database/UserRepository');
async function UpdateUserPassword(req, res) {
try {
if (!req.session.isLogged) {
console.error('ERROR: Użytkownik nie jest zalogowany by zmienić hasło');
return res.status(401).json({
success: false,
mess: 'Nie jesteś zalogowany!'
});
}
const userId = req.session.user_id;
const actualPass = req.body.pass;
const newPass = req.body.newPass;
const confirmPass = req.body.confirmPass;
if (!passwd.CheckPasswodLength(newPass)) {
console.error('ERROR: Hasło nie składa się z minimów 8 znaków');
return res.status(400).json({
success: false,
mess: 'Hasło jest za ktrutkie! Musi być minimum 8 znaków.'
});
}
if (!ValidGlyphsPass(newPass)) {
console.error('ERROR: Hasło powinno zawierać conajmniej jedną Dużą i małą literę, fyfrę, znak specjalny');
return res.status(200).json({
success: false,
mess: 'Hasło powinno zawierać conajmniej jedną Dużą i małą literę, fyfrę, znak specjalny!'
});
}
if (!passwd.CompareNewPasswords(newPass, confirmPass)) {
console.error('ERROR: Podane hasła nie są takie same');
return res.status(400).json({
success: false,
mess: 'Podane hasła nie są takie same!'
});
}
if (!await userRepo.ValidPass(userId, actualPass)) {
console.error('ERROR: Niepoprawne hasło');
return res.status(401).json({
success: false,
mess: 'Niepoprawne hasło!'
});
}
if (await userRepo.ValidPass(userId, newPass)) {
console.error('ERROR: Nowe hasło jest podobne do starego');
return res.status(400).json({
success: false,
mess: 'Nowe hasło nie może być spujne ze starym haslem!'
});
}
const hash = await passwd.HashPassword(newPass);
if(await userRepo.UpdatePassword(userId, hash) < 1) {
console.error('ERROR: Nie udało się zaktualizować hasła');
return res.status(400).json({
success: false,
mess: 'Nie udało się zaktualizować hasła!'
});
}
res.status(200).json({success: true, mess: 'Hasło zaktualizowane'});
}
catch(e) {
console.error(`ERROR: Nie udało sie zaktualizować hasła: ${e}`);
res.status(500).json({success: false, mess: 'Nie udało się zaktualizować hasła!'});
}
}
//Sprawdzenie czy hasło zawiera porządane rodzaje znaków
function ValidGlyphsPass(pass) {
const hasUpperCase = /[A-Z]/.test(pass);
const hasLowerCase = /[a-z]/.test(pass);
const hasDigit = /\d/.test(pass);
const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(pass);
return hasUpperCase && hasLowerCase && hasDigit && hasSpecialChar;
}
module.exports = UpdateUserPassword;

View file

@ -0,0 +1,26 @@
const UserRepo = require('../database/UserRepository');
async function UpdateUserPreference(req, res) {
try {
if(!req.session.isLogged) {
console.error(`ERROR: Użytkownik nie jest zalogowany!`);
return res.status(401).json({
mess: 'Nie udało się edytować nazwy grupy'
});
}
const preference = req.body;
const userId = req.session.user_id;
req.session.user_preference = {...preference};
await UserRepo.UpdatePreference(preference, userId);
res.status(200).json({mess: 'Zaktualizowano'});
}
catch(e) {
console.error(`ERROR: Nie udało się zaktualizować preferencji`);
res.status(500).json({mess: 'Nie udało się zaktualizować preferencji'});
}
}
module.exports = UpdateUserPreference;

View file

@ -0,0 +1,31 @@
function UserCheckSession(req, res) {
try {
if(!req.session.isLogged) {
return res.status(401).json({
mess: 'Brak zalogowanej sessji użytkownika',
isLogged: false,
user: null,
regdate: null,
avatar: null
});
}
res.status(200).json({
mess: 'Pobrano dane użytkownika',
isLogged: req.session.isLogged,
user: req.session.user_name,
regdate: req.session.user_regdate,
preference: req.session.user_preference,
avatar: req.session.user_avatar ? req.session.user_avatar : null
});
console.log(req.session.isLogged);
}
catch(e) {
console.error(e);
res.status(500).json({mess: 'Brak aktywnej sessji', isLogged: false});
}
}
module.exports = UserCheckSession;

View file

@ -0,0 +1,21 @@
const LoginProcess = require('./LoginProcess');
const UpdateUserPreference = require('./UpdateUserPreference');
const UserCheckSession = require('./UserCheckSession');
const UpdateUserPassword = require('./UpdateUserPassword');
const UpdateUserName = require('./UpdateUserName');
const UpdateUserAvatar = require('./UpdateAvatar');
const DeleteAvatar = require('./DeleteAvatar');
const AltchaHumanTest = require('./AltchaTest');
const LogoutUser = require('./LogoutUser');
module.exports = {
LoginProcess,
UpdateUserPreference,
UserCheckSession,
UpdateUserPassword,
UpdateUserName,
UpdateUserAvatar,
DeleteAvatar,
AltchaHumanTest,
LogoutUser,
};

16
server_2.1/src/utility.js Normal file
View file

@ -0,0 +1,16 @@
//Podmienia placeholder na wybrany text
/*
* {
* ZMIENNA1: nowa wartość.
* ZMIENNA2: nowa wartość jeszcze wartościowsza
* }
*/
function ReplacePlaceholder(replacements, text) {
return text.replace(/\{\{([^}]+)\}\}/g, (match, key) => {
return key in replacements ? replacements[key] : match;
});
}
module.export = {
ReplacePlaceholder,
}

View file