import hashlib
from flask import Flask, render_template, request, redirect, url_for, flash
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from flask_admin import Admin, AdminIndexView
from flask_security import RoleMixin, SQLAlchemyUserDatastore, current_user, Security
from flask_admin.contrib.sqla import ModelView
from flask_login import UserMixin, login_user, login_required, logout_user, LoginManager
from werkzeug.security import check_password_hash, generate_password_hash
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SECRET_KEY'] = 'my secret is good food'
app.config['SECURITY_PASSWORD_SALT'] = 'moon909'
app.config['SECURITY_PASSWORD_HASH'] = 'sha512_crypt'
db = SQLAlchemy(app)
db.create_all()
manager = LoginManager(app)
class Article(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    intro = db.Column(db.String(300), nullable=False)
    text = db.Column(db.Text(300), nullable=False)
    date = db.Column(db.DateTime(300), default=datetime.utcnow)
    def __repr__(self):
        return '<Article %r>' % self.id
roles_users = db.Table('roles_users', db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
                       db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))
class User (db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(128), unique=True, nullable=False)
    login = db.Column(db.String(128), unique=True, nullable=False)
    password = db.Column(db.String(255), nullable=False)
    active = db.Column(db.Boolean())
    roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users'), lazy='dynamic')
class Role(db.Model, RoleMixin):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(100), unique=True)
    description = db.Column(db.String(255))
#class AdminView(ModelView):
    #def is_accessible(self):
        #return current_user.has_role('admin')
    #def inaccessible_callback(self, name, **kwargs):
        #return redirect(url_for('security.login', next=request.url))
#class HomeAdminView(AdminIndexView):
    #def is_accessible(self):
        #return current_user.has_role('admin')
    #def inaccessible_callback(self, name, **kwargs):
        #return redirect(url_for('security.login', next=request.url))
admin = Admin(app) #'FlaskApp', url='/home', index_view=HomeAdminView(name='Home'))
admin.add_view(ModelView(Article, db.session))
admin.add_view(ModelView(User, db.session))
admin.add_view(ModelView(Role, db.session))
#Flask-Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)
@manager.user_loader
def load_user(user_id):
    return User.query.get(user_id)
@app.route('/')
@app.route('/home')
def home():
    return render_template("home.html")
@app.route('/news')
def news():
    return render_template("news.html")
@app.route('/learning')
def learning():
    return render_template("learning.html")
@app.route('/profiles')
def profiles():
    return render_template("profiles.html")
@app.route('/article')
def article():
    articles = Article.query.order_by(Article.date.desc()).all()
    return render_template("article.html", articles=articles)
@app.route('/article/<int:id>')
def post_detail(id):
    article = Article.query.get(id)
    return render_template("article_detail.html", article=article)
@app.route('/article/<int:id>/update', methods=['POST', 'GET'])
@login_required
def post_update(id):
    article = Article.query.get(id)
    if request.method == 'POST':
        article.title = request.form['title']
        article.intro = request.form['intro']
        article.text = request.form['text']
        try:
            db.session.commit()
            return redirect('/article')
        except:
            return "При редактировании статьи произошла ошибка"
    else:
        return render_template("article_update.html", article=article)
@app.route('/posts', methods=['POST', 'GET'])
@login_required
def create_posts():
    if request.method == "POST":
        title = request.form['title']
        intro = request.form['intro']
        text = request.form['text']
        article = Article(title=title, intro=intro, text=text)
        try:
            db.session.add(article)
            db.session.commit()
            return redirect('/article')
        except:
            return "При добавлении статьи произошла ошибка"
    return render_template("posts.html")
@app.route('/login2', methods=['GET', 'POST'])
def login_page():
    email = request.form.get('email')
    password = request.form.get('password')
    if email and password:
        user = User.query.filter_by(email=email).first()
        if user and check_password_hash(user.password, password):
            login_user(user)
            return render_template('home.html')
        else:
            flash('Login or password is not correct')
    else:
        flash('Please fill login and password fields')
    return render_template('login.html')
@app.route('/register', methods=['GET', 'POST'])
def register():
    login = request.form.get('login')
    email = request.form.get('email')
    password = request.form.get('password')
    password2 = request.form.get('password2')
    if request.method == 'POST':
        if not (login or email or password or password2):
            flash('Please, fill all fields!')
        elif password != password2:
            flash('Passwords are not equal!')
        else:
            hash_pwd = generate_password_hash(password)
            new_user = User(login=login, email=email, password=hash_pwd)
            db.session.add(new_user)
            db.session.commit()
            return redirect(url_for('login_page'))
    return render_template('register.html')
@app.route('/logout', methods=['GET', 'POST'])
@login_required
def logout():
    logout_user()
    return redirect(url_for('home'))
@app.after_request
def redirect_to_login(response):
    if response.status_code == 401:
        return redirect(url_for('login_page') + '?next=' + request.url)
    return response
if __name__ == '__main__':
    app.run(debug=True)