diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..d4e632c --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +worker: python server.py $PORT \ No newline at end of file diff --git a/SQLEasy.py b/SQLEasy.py new file mode 100644 index 0000000..f61de44 --- /dev/null +++ b/SQLEasy.py @@ -0,0 +1,228 @@ +import sqlite3 + + +class SQLiteEasyException(Exception): + pass + + +def compareKey(DBlist, key, type_of_key=lambda x: x, hideIndex=True): + if not(type(DBlist) is list): + raise SQLiteEasyException(f"function compareKey need List object, unsupported type: {type(DBlist)}") + + if len(DBlist) > 0: + if key not in DBlist[0]: + raise SQLiteEasyException(f"key '{key}' not founded.") + DB_Dictonary = dict() + for BD in sorted(DBlist, key=lambda List: List[key]): + comparedBD = dict() + for Key in BD: + if not(Key == key) and hideIndex: + comparedBD[Key] = BD[Key] + elif not hideIndex: + comparedBD[Key] = BD[Key] + DB_Dictonary[type_of_key(BD[key])] = comparedBD + + return DB_Dictonary + + +def autoselectID_fromNew_item(DATABASE, TABLE, ID_KEY): + TABLE_DATA = DATABASE.getBase(TABLE) + TABLE_DATA = compareKey(TABLE_DATA, ID_KEY) + TABLE_DATA = [ID for ID in TABLE_DATA] + INDEX = 0 + for DATA_INDEX in TABLE_DATA: + if INDEX == DATA_INDEX: + INDEX += 1 + else: + return INDEX + return INDEX + + +class database: + def dict_factory(self, cursor, row): + dictDB = {} + for idx, col in enumerate(cursor.description): + dictDB[col[0]] = row[idx] + return dictDB + + def encodeSQLiteType(self, objectum, all_as_str=False): + if type(objectum) is str: + return "'%s'" % objectum.replace("'", "[SQLEasy_symbol:']") + elif objectum is None and all_as_str: + return "''" + elif objectum is None: + return 'NULL' + elif type(objectum) is bool and objectum and all_as_str: + return "'TRUE'" + elif type(objectum) is bool and objectum: + return 'TRUE' + elif type(objectum) is bool and not(objectum) and all_as_str: + return "'FALSE'" + elif type(objectum) is bool and not(objectum): + return 'FALSE' + elif all_as_str and True in [type(objectum) is int, type(objectum) is float]: + return "'%s'" % objectum + elif not(all_as_str) and True in [type(objectum) is int, type(objectum) is float]: + return objectum + else: + raise SQLiteEasyException(f"Unsupported type: {type(objectum)}") + + def __init__(self, PATH, DatabaseName=None): + self.ConnectedFile = sqlite3.connect(PATH, check_same_thread=False) + self.databaseChoosed = DatabaseName + self.ConnectedFile.row_factory = self.dict_factory + self.act_commit = True + + def toggleCommit(self, value=None): + if value in (False, True): + self.act_commit = value + else: + if self.act_commit: + self.act_commit = False + else: + self.act_commit = True + + def commit(self): + self.ConnectedFile.commit() + + def getBase(self, DatabaseName=None, elementsFromDB='*'): + elementsFromDB = str(elementsFromDB) + if DatabaseName is None and self.databaseChoosed is None: + raise SQLiteEasyException("Database is not choosed") + elif DatabaseName is None and not(self.databaseChoosed is None): + dbCursore = self.ConnectedFile.cursor() + dbCursore.execute(f"select {elementsFromDB} from {self.databaseChoosed}") + result = dbCursore.fetchall() + else: + dbCursore = self.ConnectedFile.cursor() + dbCursore.execute(f"select {elementsFromDB} from {DatabaseName}") + self.databaseChoosed = DatabaseName + result = dbCursore.fetchall() + + for rowID in range(len(result)): + row = result[rowID] + for cellKey in row: + if type(row[cellKey]) is str: + result[rowID][cellKey] = row[cellKey].replace('[SQLEasy_symbol:']', "'") + return result + + def pop(self, key, value, DatabaseName=None): + if type(value) is str: + # value = f"'%s'" % value.replace('\'', '\\\'') + value = f"'%s'" % value.replace("'", '[SQLEasy_symbol:']') + if DatabaseName is None and not(self.databaseChoosed is None): + DatabaseName = self.databaseChoosed + elif DatabaseName is None: + raise SQLiteEasyException("Database is not choosed") + dbCursore = self.ConnectedFile.cursor() + dbCursore.execute('DELETE FROM %s\n\nWHERE %s == %s;' % (DatabaseName, key, value)) + if self.act_commit: + self.ConnectedFile.commit() + + def setItem(self, key, newValue, indexKey, value, DatabaseName=None): + newValue = self.encodeSQLiteType(newValue) + value = self.encodeSQLiteType(value) + if DatabaseName is None and not(self.databaseChoosed is None): + DatabaseName = self.databaseChoosed + elif DatabaseName is None: + raise SQLiteEasyException("Database is not choosed") + dbCursore = self.ConnectedFile.cursor() + if value is None: + dbCursore.execute('UPDATE %s SET %s = %s WHERE %s is NULL;' % (DatabaseName, key, newValue, indexKey)) + else: + dbCursore.execute('UPDATE %s SET %s = %s WHERE %s = %s;' % (DatabaseName, key, newValue, indexKey, value)) + if self.act_commit: + self.ConnectedFile.commit() + + def add(self, values, DatabaseName=None): + if DatabaseName is None and not(self.databaseChoosed is None): + DatabaseName = self.databaseChoosed + elif DatabaseName is None: + raise SQLiteEasyException("Database is not choosed") + if DatabaseName is None and not(self.databaseChoosed is None): + DatabaseName = self.databaseChoosed + elif DatabaseName is None: + raise SQLiteEasyException("Database is not choosed") + + keys = [str(key) for key in values] + values = [self.encodeSQLiteType(values[key], all_as_str=True) for key in values] + + dbCursore = self.ConnectedFile.cursor() + try: + dbCursore.execute('INSERT INTO %s (%s) VALUES (%s)' % (DatabaseName, ', '.join(keys), ', '.join(values))) + except: + dbCursore.execute('INSERT OR IGNORE INTO %s (%s) VALUES (%s)' % (DatabaseName, ', '.join(keys), ', '.join(values))) + if self.act_commit: + self.ConnectedFile.commit() + + def uploadFiles(self, binary, DatabaseName=None): # Uwaga! Может работать с ошибками. + if not(type(binary) is bytes or type(binary) is bytearray): + raise SQLiteEasyException('You can upload only byte or bytearray types!!') + dbCursore = self.ConnectedFile.cursor() + binary = sqlite3.Binary(binary) + + if DatabaseName is None and not(self.databaseChoosed is None): + DatabaseName = self.databaseChoosed + elif DatabaseName is None: + raise SQLiteEasyException("Database is not choosed") + if DatabaseName is None and not(self.databaseChoosed is None): + DatabaseName = self.databaseChoosed + elif DatabaseName is None: + raise SQLiteEasyException("Database is not choosed") + # (!) Дописать + + def chooseDataBase(self, DatabaseName): + self.getBase(DatabaseName) + self.databaseChoosed = DatabaseName + + def currentIndex(self, key, value, DatabaseName=None): + if DatabaseName is None and not(self.databaseChoosed is None): + DatabaseName = self.databaseChoosed + elif DatabaseName is None: + raise SQLiteEasyException("Database is not choosed") + + DB = self.getBase(DatabaseName) + + ID = 0 + for Dictonary in sorted(DB, key=lambda dictonary: dictonary[key]): + if Dictonary[key] == value: + return ID + ID += 1 + + def currentValue(self, key, value, DatabaseName=None): + if DatabaseName is None and not(self.databaseChoosed is None): + DatabaseName = self.databaseChoosed + elif DatabaseName is None: + raise SQLiteEasyException("Database is not choosed") + + DB = self.getBase(DatabaseName) + + for Dictonary in sorted(DB, key=lambda dictonary: dictonary[key]): + if Dictonary[key] == value: + return Dictonary + + def createColumn(self, columnName, tableName, DatabaseName=None): + return # (!) Не реализовано!! + + def getTables(self): + dbCursore = self.ConnectedFile.cursor() + dbCursore.execute('SELECT name from sqlite_master where type= "table"') + return [item['name'] for item in dbCursore.fetchall()] + + def getDict(self): + dictonary = dict() + tables = self.getTables() + for table in tables: + dictonary[table] = self.getBase(table) + return dictonary + + def execute(self, req): + dbCursore = self.ConnectedFile.cursor() + dbCursore.execute(req) + if self.act_commit: + self.ConnectedFile.commit() + return dbCursore.fetchall() + + +def formingTable(dictonary, path): + pass # В разработке \ No newline at end of file diff --git a/database.db b/database.db new file mode 100644 index 0000000..bc79f8e Binary files /dev/null and b/database.db differ diff --git a/mailclient.py b/mailclient.py new file mode 100644 index 0000000..adee0e2 --- /dev/null +++ b/mailclient.py @@ -0,0 +1,53 @@ +import smtplib as smtp + + +class output: + def __init__(self): + self.debug = False + + def toggleDebug(self, flag=None): + if flag is None: + if self.debug: + self.debug = False + else: + self.debug = True + else: + self.debug = flag + + def printf(self, *args, sep=' ', end='\n', file=None): + if self.debug: + if file is None: + print(*args, sep=sep, end=end) + else: + print(*args, sep=sep, end=end, file=file) + + +output_tool = output() +smtp.print = output_tool.printf + + +class mail: + def __init__(self, email, password): + self.email = email + self.password = password + + def set_smtp_server(self, url): + smtp.SMTP_SSL(url) + self.SMTP_SERVER = url + + def send(self, subject, email_text, to_mail): + message = 'From: {}\nTo: {}\nSubject: {}\n\n{}'.format(self.email, + to_mail, + subject, + email_text) + server = smtp.SMTP_SSL(self.SMTP_SERVER) + server.set_debuglevel(1) + server.ehlo(self.email) + server.login(self.email, self.password) + server.auth_plain() + server.sendmail( + self.email, + to_mail, + message.encode('utf-8') + ) + server.quit() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8ab6294 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +flask \ No newline at end of file diff --git a/server.py b/server.py new file mode 100644 index 0000000..938f131 --- /dev/null +++ b/server.py @@ -0,0 +1,766 @@ +from flask import Flask, render_template, request, redirect, url_for, flash, make_response +import SQLEasy, random, mailclient, traceback, json, time, socket + +database = SQLEasy.database('database.db') + +app = Flask(__name__) + +HOST = '127.0.0.1' +HOST = socket.gethostbyname(socket.gethostname()) +PORT = 8080 + +EMAIL = '' # Введите сюда свой адрес электронной почты +EMAIL_PASSWORD = '' # Введите сюда свой пароль от электронной почты +# Рекомендуется использовать сервера Яндекса: smtp.yandex.ru +SMTP_SERVER = 'smtp.yandex.ru' # Укажите свой SMTP сервер (смотрите по сервису, обычно SMTP сервера находятся по адресу smtp.sevise.org, например: smtp.google.com) +mailObject = mailclient.mail(EMAIL, EMAIL_PASSWORD) +mailObject.set_smtp_server(SMTP_SERVER) + +file_content = '''var type = "auth"; + +function timeConverter(UNIX_timestamp){ + var a = new Date(UNIX_timestamp * 1000); + var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; + var year = a.getFullYear(); + var month = months[a.getMonth()]; + var date = a.getDate(); + var hour = a.getHours(); + var min = a.getMinutes(); + var sec = a.getSeconds(); + var time = date + ' ' + month + ' ' + year + ' ' + hour + ':' + min + ':' + sec ; + return time; +} + +function buton_regAuth(){ + if(type == "auth") type = "reg"; + else type = "auth"; + if(type == "auth") document.getElementById("authwin").innerHTML = "
\n

Авторизация

\n

e-mail:

\n

password:

\n

\n
\n " + else document.getElementById("authwin").innerHTML = "
\n

Регистрация

\n

e-mail:

\n

повторите e-mail:

\n

password:

\n

повторите password:

\n

\n
\n " +} + +function confirmation_mail(mail_adress) { + var codeConfirmation = "
\n
\n

Введите код

\n

\n

Если письмо не пришло, то проверьте папку \"Спам\", проверьте ваш чёрный список на наличие почтового адреса бота, проверьте правильность введённых данных при регистрации.

\n

\n
\n
" + + var GET_Request = new XMLHttpRequest(); + GET_Request.open("GET", "http://127.0.0.1:8080/api/confirmation/start?email=" + mail_adress, true); + GET_Request.onload = function (){ + var content = GET_Request.responseText; + document.getElementById("authwin").innerHTML = codeConfirmation; + } + GET_Request.send(null); +} + +function get_cookies(){ + var cookie_f = document.cookie; + var cookies = cookie_f.split('; '); + // alert(cookie_f); + var returnCookie = {}; + + cookies.forEach(function(item, i, cookies) { + console.log(item); + ItemArray = item.split('='); + console.log(ItemArray); + console.log(ItemArray[0]); + console.log(ItemArray[1]); + returnCookie[ItemArray[0]] = ItemArray[1]; + }); + console.log(returnCookie) + + return returnCookie; +} + +function update(){ + var cookies = get_cookies(); + var xhr = new XMLHttpRequest(); + + xhr.open('GET', "http://127.0.0.1:8080/api/user/get_pages?autogroup=1&token=" + cookies.token, false); + // alert('ok'); + + xhr.send(); + if (xhr.status != 200) { + var ok = 'ok'; + } else { + var values = JSON.parse(xhr.responseText); + // alert(xhr.responseText); + var groups = values.response; + var retV = ''; + groups.forEach(function(group, i, groups) { + var item = ''; + var clocker = 0; + group.forEach(function(cellContent, i, group) { + clocker += 1; + item += `
${cellContent.title}
Создано:
${timeConverter(cellContent.created)}
Отредактирован:
${timeConverter(cellContent.edited)}
\n`; + }); + retV += `
${item}
\n`; + }); + retV += "
Добавить страницу
\n
Выйти
"; + document.getElementById("field").innerHTML = retV; + } +}''' + +for codePath in ('static/button.js', 'static/script.js', 'static/scripts.js', 'static/source_test_20.js', 'static/scripts/button.js'): + content = file_content + + content = content.replace('127.0.0.1:8080', f"{HOST}:{PORT}") + + jsCodeObj = open(codePath, 'wt', encoding='utf-8') + jsCodeObj.write(content) + jsCodeObj.close() + + +def formatMail(mail): + servise = mail.split('@')[-1] + domain = mail.split('@')[0] + if servise in ('ya.ru', 'yandex.ru', 'yandex.by', 'yandex.ua', 'yandex.kz'): + servise = 'yandex.ru' + elif servise in ('mail.ru', 'inbox.ru', 'internet.ru', 'bk.ru', 'list.ru'): + servise = 'mail.ru' + + return f"{domain}@{servise}" + + +def genToken(LEN=32): + TOKEN = '' + for _ in range(LEN): + TOKEN += '0123456789abcdef'[random.randint(0, 15)] + return TOKEN + + +def checkToken(TOKEN): + if not(TOKEN): + return False + data = database.getBase('auths') + data = [DATA['token'] for DATA in data] + if not(TOKEN in data): + return False + + data = SQLEasy.compareKey(database.getBase('auths'), 'token')[TOKEN] + return bool(data['active']) + + +def checkMail(MAIL): + MAIL = formatMail(MAIL) + if not(MAIL): + return False + data = database.getBase('Users') + data = [formatMail(DATA['email']) for DATA in data] + + return MAIL in data + + +def checkPassword(PASS): + if not(PASS): + return False + data = database.getBase('Users') + data = [DATA['password'] for DATA in data] + + return PASS in data + + +def getUserData(TOKEN): + UserID = SQLEasy.compareKey(database.getBase('auths'), 'token')[TOKEN]['UserID'] + return SQLEasy.compareKey(database.getBase('Users'), 'ID', hideIndex=False)[UserID] + + +def validData_check(MAIL, PASSWORD): + userData = SQLEasy.compareKey(database.getBase('Users'), 'email')[MAIL] + return userData['password'] == PASSWORD + + +@app.route('/') +def index(): + if not(checkToken(request.cookies.get('token'))): + errorCode = '' + if request.args.get('error', default=False): + errorCode = '
Ошибка: %s
' % request.args.get('error') + + retPage = ''' + + Блокнот онлайн + + + + + + + + + ERROM_MSG +
+
+

Авторизация

+

e-mail:

+

password:

+

+
+ +
+ +''' + retPage = retPage.replace('ERROM_MSG', errorCode) + return retPage + else: + return redirect("/note/menu", code=302) + + +@app.route('/logout') +def logout(): + res = redirect("/", code=302) + res.set_cookie('token', 'NULL', max_age=1) + return res + +@app.route('/note/id/') +def pageView(PageID): + if checkToken(request.cookies.get('token')): + try: + PageID = int(PageID) + except: + return redirect("/", code=302) + pageData = SQLEasy.compareKey(database.getBase('Pages'), 'ID', hideIndex=False)[PageID] + title = pageData['title'] + content = pageData['content'] + + if getUserData(request.cookies.get('token'))['ID'] != pageData['ownerID']: + return redirect("/?error=Отказано в доступе.", code=302) + + if request.args.get('act') != 'edit': + HTMLcontent = ''' + + NOTETITLE + + + + + + +

NOTETITLE

+
+
+ NOTECONTENT +
+

+ +

+ +
+

+
+ +''' + HTMLcontent = HTMLcontent.replace('HOSTPORTION', f"{HOST}:{PORT}") + HTMLcontent = HTMLcontent.replace('NOTETITLE', title) + HTMLcontent = HTMLcontent.replace('NOTECONTENT', content) + return HTMLcontent + else: + HTMLcontent = ''' + + NOTETITLE + + + + + + +

Редактирование NOTECONTENT

+
+
+

Заголовок: + + +

+

Содержание:

+

+

+
+
+ +''' + HTMLcontent = HTMLcontent.replace('HOSTPORTION', f"{HOST}:{PORT}") + HTMLcontent = HTMLcontent.replace('NOTETITLE', title) + HTMLcontent = HTMLcontent.replace('PAGE_ID', str(PageID)) + HTMLcontent = HTMLcontent.replace('NOTECONTENT', content) + return HTMLcontent + else: + return redirect("/", code=302) + +@app.route('/note/') +def main_menu(menu_ind): + if not(checkToken(request.cookies.get('token'))): + return redirect("/", code=302) + + if menu_ind == 'menu': + HTMLcontent = ''' + + Главная страница + + + + + + + + +

Ваши заметки

+
+
+
Добавить страницу
+
+
+ + +''' + HTMLcontent = HTMLcontent.replace('HOSTPORTION', f"{HOST}:{PORT}") + return HTMLcontent + elif menu_ind == 'add': + HTMLcontent = ''' + + Новая запись + + + + + + +

Создать заметку

+
+
+

Заголовок: + +

+

Содержание:

+

+

+
+
+ +''' + HTMLcontent = HTMLcontent.replace('HOSTPORTION', f"{HOST}:{PORT}") + return HTMLcontent + +@app.route('/file_api//') +def file_api(method): + print('METHOD:', method) + + if not checkToken(request.cookies.get('token')): + return redirect("/?error=Для использования файлового API нужно авторизоваться.", code=302) + + if method == 'add': + userObj = SQLEasy.compareKey(database.getBase('auths'), 'token')[request.cookies.get('token')]['UserID'] + userObj = SQLEasy.compareKey(database.getBase('Users'), 'ID', hideIndex=False)[userObj] + + title = request.args.get('title') + if len(title) < 3: + return redirect("/note/add", code=302) + color = request.args.get('color') + if len(color) < 3: + return redirect("/note/add", code=302) + content = request.args.get('content') + if len(content) == 0: + return redirect("/note/add", code=302) + + newID = SQLEasy.autoselectID_fromNew_item(database, 'Pages', 'ID') + database.add({ + 'ID': newID, + 'ownerID': userObj['ID'], + 'title': title, + 'content': content, + 'color': f"#{color}", + 'created': int(time.time()), + 'edited': int(time.time()) + }, 'Pages') + return redirect("/note/id/%s" % newID, code=302) + if method == 'edit': + print('FUCK1488!!!') + try: + noteID = int(request.args.get('id')) + except: + return redirect("/", code=302) + + userObj = SQLEasy.compareKey(database.getBase('auths'), 'token')[request.cookies.get('token')]['UserID'] + userObj = SQLEasy.compareKey(database.getBase('Users'), 'ID', hideIndex=False)[userObj] + + title = request.args.get('title') + if len(title) < 3: + return redirect("/note/id/%s" % noteID, code=302) + color = request.args.get('color') + if len(color) < 3: + return redirect("/note/id/%s" % noteID, code=302) + content = request.args.get('content') + if len(content) == 0: + return redirect("/note/id/%s" % noteID, code=302) + + database.setItem( + 'title', + title, + 'ID', + noteID, + DatabaseName='Pages' + ) + database.setItem( + 'content', + content, + 'ID', + noteID, + DatabaseName='Pages' + ) + database.setItem( + 'color', + f"#{color}", + 'ID', + noteID, + DatabaseName='Pages' + ) + database.setItem( + 'edited', + int(time.time()), + 'ID', + noteID, + DatabaseName='Pages' + ) + + return redirect("/note/id/%s" % noteID, code=302) + +@app.route('/oauth/') +def oauth(method): + if method == 'auth': + email = request.args.get('email', default=None) + if email is None: + return redirect("/?error=Не введён адрес электронной почты.", code=302) + if not checkMail(email): + return redirect("/?error=Неверный адрес электронной почты или пароль.", code=302) + email = formatMail(email) + + password = request.args.get('password', default=None) + if password is None: + return redirect("/?error=Не введён пароль", code=302) + if len(password) < 8: + return redirect("/?error=Поле \"Пароль\" должно содержать не менее 8 символов!", code=302) + if not checkPassword(password): + return redirect("/?error=Неверный адрес электронной почты или пароль.", code=302) + if not validData_check(email, password): + return redirect("/?error=Неверный адрес электронной почты или пароль.", code=302) + + while True: + token = genToken() + if token not in [item['token'] for item in database.getBase('auths')]: + break + + database.add({ + 'token': token, + 'UserID': SQLEasy.compareKey(database.getBase('Users'), 'email')[email]['ID'], + 'active': 1 + }, 'auths') + + res = redirect("/", code=302) + res.set_cookie('token', token, max_age=60*60*24*365*2) + + return res + elif method == 'register': + email = request.args.get('email', default=None) + if email is None: + return redirect("/?error=Не введён адрес электронной почты.", code=302) + + foward_email = request.args.get('fowardemail', default=None) + if email != foward_email: + print({"foward_email": foward_email, "email": email}) + return redirect("/?error=Адреса почтовых ящиков не совпадают.", code=302) + del foward_email + + if email in SQLEasy.compareKey(database.getBase('Users'), 'email'): + return redirect("/?error=Этот ящик уже зарегистрирован.", code=302) + + password = request.args.get('password', default=None) + if password is None: + return redirect("/?error=Не введён пароль", code=302) + if len(password) < 8: + return redirect("/?error=Поле \"Пароль\" должно содержать не менее 8 символов!", code=302) + + foward_password = request.args.get('fowardpassword', default=None) + if password != foward_password: + return redirect("/?error=Пароли не совподают.", code=302) + del foward_password + + database.add({ + 'ID': SQLEasy.autoselectID_fromNew_item(database, 'Users', 'ID'), + 'email': formatMail(email), + 'password': password, + 'verif_code': genToken(8).upper(), + 'mail_confirm': 0 + }, 'Users') + return redirect("/oauth/confirmation?mail=%s" % formatMail(email), code=302) + elif method == 'confirmation': + mail = request.args.get('mail', default=None) + finish_code = request.args.get('finish_code', default=None) + if mail is None and finish_code is None: + return redirect("/?error=Не задан ни почтовый ящик, ни код подтверждения при передаче параметров oauth/confirmation", code=302) + + if mail: + codeHTML = ''' + + Подтвердите почтовый адрес + + + + + + + + +
+
+

Подтвердите почтовый адрес

+

На ваш почтовый адрес: MAIL_ADRES придёт код активации.

+

Письмо придёт от адреса: BOT_MAIL_ADRES лучше сразу добавьте его в белый список.

+ +
+
+ +''' + + codeHTML = codeHTML.replace('HOSTPORTION', f"{HOST}:{PORT}") + codeHTML = codeHTML.replace('BOT_MAIL_ADRES', EMAIL) + codeHTML = codeHTML.replace('MAIL_ADRES', mail) + + return codeHTML + if finish_code: + finish_code = finish_code.upper() + + if finish_code not in [code for code in SQLEasy.compareKey(database.getBase('Users'), 'verif_code')]: + return redirect("/?error=Неверный код подтверждения.", code=302) + else: + userObj = SQLEasy.compareKey(database.getBase('Users'), 'verif_code')[finish_code] + database.setItem( + 'mail_confirm', + 1, + 'ID', + userObj['ID'], + DatabaseName='Users' + ) + + token = genToken() + database.add({ + 'token': token, + 'UserID': userObj['ID'], + 'active': 1 + }, 'auths') + + res = redirect("/", code=302) + res.set_cookie('token', token, max_age=60*60*24*365*2) + + return res + + return redirect("/?error=Неизвестный ранее метод oauth", code=302) + +@app.route('/api//') +def API(method_group, method): + if method_group == 'user': + if method == 'get_pages': + token = request.args.get('token', default=None) + autogroup = bool(request.args.get('autogroup', default=False)) + if not checkToken(token): + return '{"error": "invalid token"}' + session = SQLEasy.compareKey(database.getBase('auths'), 'token')[token] + userID = session['UserID'] + del session + userData = SQLEasy.compareKey(database.getBase('Users'), 'ID', hideIndex=False)[userID] + mypages = list() + + for page in database.getBase('Pages'): + if page['ownerID'] == userData['ID']: + mypages.append(page) + ret_mypages = mypages.copy() + if autogroup: + ret_mypages = list() + + MaxIndex = len(mypages) - 1 + Index = 0 + for page in mypages: + pageGr = list() + for _ in range(6): + if Index <= MaxIndex: + pageGr.append(mypages[Index]) + Index += 1 + ret_mypages.append(pageGr) + return json.dumps({ + "response": ret_mypages + }, indent="\t", ensure_ascii=False) + + if method_group == 'confirmation': + if method == 'start': + email = request.args.get('email', default=None) + code = 1 + warn_text = 'null' + if email is None: + return '{"error": "email address has been missed"}' + if email not in [mail for mail in SQLEasy.compareKey(database.getBase('Users'), 'email')]: + return '{"error": "this email not founded"}' + if SQLEasy.compareKey(database.getBase('Users'), 'email')[email]['mail_confirm']: + return '{"error": "this email was been activated"}' + if SQLEasy.compareKey(database.getBase('Users'), 'email')[email]['sended']: + code = 2 + warn_text = '"Message was been sended, please, check your mailbox"' + + verificationCode = SQLEasy.compareKey(database.getBase('Users'), 'email')[email]['verif_code'] + try: + mailObject.send('Код подтверждения', f"Код подтверждения: {verificationCode}", str(email)) + print('sended to %s' % email) + database.setItem( + 'sended', + 1, + 'email', + email, + DatabaseName='Users' + ) + return '{"response": 1, "warning": %s}' % warn_text + except Exception as exc: + print('FAILED:\n %s' % traceback.format_exc()) + return '{"error": "failed send message"}' + + return '{"error": "unknown method"}' + return '{"error": "unknown method group"}' + +@app.route('/index.') +def trueINDEX(jap): + return redirect("/", code=302) + +@app.route('/index') +def trueINDEX_noRasz(): + return redirect("/", code=302) + + + +if __name__ == '__main__': + app.run(port=PORT, host=HOST) # Сменить хост \ No newline at end of file diff --git a/static/button.js b/static/button.js new file mode 100644 index 0000000..efcaa44 --- /dev/null +++ b/static/button.js @@ -0,0 +1,58 @@ +var type = "auth"; +function buton_regAuth(){ + if(type == "auth") type = "reg"; + else type = "auth"; + if(type == "auth") document.getElementById("authwin").innerHTML = "
\n

Авторизация

\n

e-mail:

\n

password:

\n

\n
\n " + else document.getElementById("authwin").innerHTML = "
\n

Регистрация

\n

e-mail:

\n

повторите e-mail:

\n

password:

\n

повторите password:

\n

\n
\n " +} + +function confirmation_mail(mail_adress) { + var codeConfirmation = "
\n
\n

Введите код

\n

\n

Если письмо не пришло, то проверьте папку \"Спам\", проверьте ваш чёрный список на наличие почтового адреса бота, проверьте правильность введённых данных при регистрации.

\n

\n
\n
" + + var GET_Request = new XMLHttpRequest(); + GET_Request.open("GET", "http://127.0.0.1:8080/api/confirmation/start?email=" + mail_adress, true); + GET_Request.onload = function (){ + var content = GET_Request.responseText; + document.getElementById("authwin").innerHTML = codeConfirmation; + } + GET_Request.send(null); +} + +function get_cookies(){ + var cookie_f = document.cookie; + cookies = cookie_f.split('; '); + returnCookie = {}; + + cookies.forEach(function(item, i, cookies) { + ItemArray = item.split('='); + returnCookie[ItemArray[0]] = returnCookie[ItemArray[1]]; + }); + + return returnCookie; +} + +function update(){ + var cookies = get_cookies(); + var xhr = new XMLHttpRequest(); + + xhr.open('GET', "http://127.0.0.1:8080/api/user/get_pages?autogroup=1&token=" + + cookies.token, false); + + xhr.send(); + if (xhr.status != 200) { + var ok = 'ok'; + } else { + var values = JSON.parse(xhr.responseText); + var groups = values.response; + var retV = ''; + groups.forEach(function(group, i, groups) { + var item = ''; + group.forEach(function(cellContent, i, group) { + item += `
${cellContent.title}
\n`; + }); + retV += `
${item}
\n`; + }); + document.getElementById("field").innerHTML = retV; + + } +} \ No newline at end of file diff --git a/static/icon.ico b/static/icon.ico new file mode 100644 index 0000000..aa0133f Binary files /dev/null and b/static/icon.ico differ diff --git a/static/script.js b/static/script.js new file mode 100644 index 0000000..a045157 --- /dev/null +++ b/static/script.js @@ -0,0 +1,23 @@ +var type = "auth"; +function buton_regAuth(){ + if(type == "auth") type = "reg"; + else type = "auth"; + if(type == "auth") document.getElementById("authwin").innerHTML = "
\n

Авторизация

\n

e-mail:

\n

password:

\n

\n
\n " + else document.getElementById("authwin").innerHTML = "
\n

Регистрация

\n

e-mail:

\n

повторите e-mail:

\n

password:

\n

повторите password:

\n

\n
\n " +} + +function confirmation_mail(mail_adress) { + var codeConfirmation = "
\n
\n

Введите код

\n

\n

Если письмо не пришло, то проверьте папку \"Спам\", проверьте ваш чёрный список на наличие почтового адреса бота, проверьте правильность введённых данных при регистрации.

\n

\n
\n
" + + var GET_Request = new XMLHttpRequest(); + GET_Request.open("GET", "http://127.0.0.1:8080/api/confirmation/start?email=" + mail_adress, true); + GET_Request.onload = function (){ + var content = GET_Request.responseText; + document.getElementById("authwin").innerHTML = codeConfirmation; + } + GET_Request.send(null); + + +} + +function off_pass(){} \ No newline at end of file diff --git a/static/scripts.js b/static/scripts.js new file mode 100644 index 0000000..a045157 --- /dev/null +++ b/static/scripts.js @@ -0,0 +1,23 @@ +var type = "auth"; +function buton_regAuth(){ + if(type == "auth") type = "reg"; + else type = "auth"; + if(type == "auth") document.getElementById("authwin").innerHTML = "
\n

Авторизация

\n

e-mail:

\n

password:

\n

\n
\n " + else document.getElementById("authwin").innerHTML = "
\n

Регистрация

\n

e-mail:

\n

повторите e-mail:

\n

password:

\n

повторите password:

\n

\n
\n " +} + +function confirmation_mail(mail_adress) { + var codeConfirmation = "
\n
\n

Введите код

\n

\n

Если письмо не пришло, то проверьте папку \"Спам\", проверьте ваш чёрный список на наличие почтового адреса бота, проверьте правильность введённых данных при регистрации.

\n

\n
\n
" + + var GET_Request = new XMLHttpRequest(); + GET_Request.open("GET", "http://127.0.0.1:8080/api/confirmation/start?email=" + mail_adress, true); + GET_Request.onload = function (){ + var content = GET_Request.responseText; + document.getElementById("authwin").innerHTML = codeConfirmation; + } + GET_Request.send(null); + + +} + +function off_pass(){} \ No newline at end of file diff --git a/static/scripts/button.js b/static/scripts/button.js new file mode 100644 index 0000000..18837b2 --- /dev/null +++ b/static/scripts/button.js @@ -0,0 +1,9 @@ +var type = "auth"; +function buton_regAuth(){ + console.log("Poszel nahui") + if(type == "auth") type = "reg"; + else type = "auth"; + + if(type == "auth") document.getElementById("authwin").innerHTML = "
\n

Авторизация

\n

e-mail:

\n

password:

\n

\n
\n " + else document.getElementById("authwin").innerHTML = "
\n

Регистрация

\n

e-mail:

\n

повторите e-mail:

\n

password:

\n

повторите password:

\n

\n
\n " +} \ No newline at end of file diff --git a/static/source_test_20.js b/static/source_test_20.js new file mode 100644 index 0000000..67433d1 --- /dev/null +++ b/static/source_test_20.js @@ -0,0 +1,81 @@ +var type = "auth"; + +function timeConverter(UNIX_timestamp){ + var a = new Date(UNIX_timestamp * 1000); + var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; + var year = a.getFullYear(); + var month = months[a.getMonth()]; + var date = a.getDate(); + var hour = a.getHours(); + var min = a.getMinutes(); + var sec = a.getSeconds(); + var time = date + ' ' + month + ' ' + year + ' ' + hour + ':' + min + ':' + sec ; + return time; +} + +function buton_regAuth(){ + if(type == "auth") type = "reg"; + else type = "auth"; + if(type == "auth") document.getElementById("authwin").innerHTML = "
\n

Авторизация

\n

e-mail:

\n

password:

\n

\n
\n " + else document.getElementById("authwin").innerHTML = "
\n

Регистрация

\n

e-mail:

\n

повторите e-mail:

\n

password:

\n

повторите password:

\n

\n
\n " +} + +function confirmation_mail(mail_adress) { + var codeConfirmation = "
\n
\n

Введите код

\n

\n

Если письмо не пришло, то проверьте папку \"Спам\", проверьте ваш чёрный список на наличие почтового адреса бота, проверьте правильность введённых данных при регистрации.

\n

\n
\n
" + + var GET_Request = new XMLHttpRequest(); + GET_Request.open("GET", "http://127.0.0.1:8080/api/confirmation/start?email=" + mail_adress, true); + GET_Request.onload = function (){ + var content = GET_Request.responseText; + document.getElementById("authwin").innerHTML = codeConfirmation; + } + GET_Request.send(null); +} + +function get_cookies(){ + var cookie_f = document.cookie; + var cookies = cookie_f.split('; '); + // alert(cookie_f); + var returnCookie = {}; + + cookies.forEach(function(item, i, cookies) { + console.log(item); + ItemArray = item.split('='); + console.log(ItemArray); + console.log(ItemArray[0]); + console.log(ItemArray[1]); + returnCookie[ItemArray[0]] = ItemArray[1]; + }); + console.log(returnCookie) + + return returnCookie; +} + +function update(){ + var cookies = get_cookies(); + var xhr = new XMLHttpRequest(); + + xhr.open('GET', "http://127.0.0.1:8080/api/user/get_pages?autogroup=1&token=" + cookies.token, false); + // alert('ok'); + + xhr.send(); + if (xhr.status != 200) { + var ok = 'ok'; + } else { + var values = JSON.parse(xhr.responseText); + // alert(xhr.responseText); + var groups = values.response; + var retV = ''; + groups.forEach(function(group, i, groups) { + var item = ''; + var clocker = 0; + group.forEach(function(cellContent, i, group) { + clocker += 1; + item += `
${cellContent.title}
Создано:
${timeConverter(cellContent.created)}
Отредактирован:
${timeConverter(cellContent.edited)}
\n`; + }); + retV += `
${item}
\n`; + }); + retV += "
Добавить страницу
\n
Выйти
"; + document.getElementById("field").innerHTML = retV; + } +} \ No newline at end of file diff --git a/static/sources/icon.ico b/static/sources/icon.ico new file mode 100644 index 0000000..aa0133f Binary files /dev/null and b/static/sources/icon.ico differ