Browse Source

Add userpage, improve private pages

JoostSijm 6 years ago
parent
commit
b1803c1521

+ 2 - 0
app/flaskr.py

@@ -9,9 +9,11 @@ from app.modules.backend import Backend
 from app.modules.auth import Auth
 from app.modules.auth import Auth
 from app.modules.backend.modules.page import Backend_Page
 from app.modules.backend.modules.page import Backend_Page
 from app.modules.backend.modules.file import Backend_File
 from app.modules.backend.modules.file import Backend_File
+from app.modules.backend.modules.user import Backend_User
 
 
 app.register_blueprint(Auth)
 app.register_blueprint(Auth)
 app.register_blueprint(Static)
 app.register_blueprint(Static)
 app.register_blueprint(Backend, url_prefix='/backend')
 app.register_blueprint(Backend, url_prefix='/backend')
 app.register_blueprint(Backend_Page, url_prefix='/backend/page')
 app.register_blueprint(Backend_Page, url_prefix='/backend/page')
 app.register_blueprint(Backend_File, url_prefix='/backend/file')
 app.register_blueprint(Backend_File, url_prefix='/backend/file')
+app.register_blueprint(Backend_User, url_prefix='/backend/user')

+ 2 - 4
app/models.py

@@ -40,6 +40,7 @@ class User(db.Model, UserMixin):
     email = db.Column(db.String(255), unique=True)
     email = db.Column(db.String(255), unique=True)
     _password = db.Column("password", db.String(255))
     _password = db.Column("password", db.String(255))
     registration_at = db.Column(db.DateTime, default=datetime.utcnow)
     registration_at = db.Column(db.DateTime, default=datetime.utcnow)
+    approved = db.Column(db.Boolean, server_default='f', default=False)
 
 
     def __init__(self, id=None):
     def __init__(self, id=None):
         self.id = id
         self.id = id
@@ -79,10 +80,7 @@ class Page(db.Model):
 
 
     def url(self):
     def url(self):
         """Generate URL for page"""
         """Generate URL for page"""
-        url = quote(self.title.strip().lower().replace(" ", "_"))
-        if self.private and not self.parent_id:
-            return 'private/' + url
-        return url
+        return quote(self.title.strip().lower().replace(" ", "_"))
 
 
 
 
     def path(self):
     def path(self):

+ 10 - 9
app/modules/auth/app.py

@@ -26,17 +26,18 @@ def login():
         email = request.form['email']
         email = request.form['email']
         password = request.form['password']
         password = request.form['password']
         user = User.query.filter(User.email == email).first()
         user = User.query.filter(User.email == email).first()
-        if user is not None:
+        if user:
+            if not user.approved:
+                flash('Account not approved yet.', 'warning')
             if user.check_password(password):
             if user.check_password(password):
                 login_user(user, remember=True)
                 login_user(user, remember=True)
-                flash('You were successfully logged in.', 'success')
-                if request.args.get("next") is not None:
-                    return redirect(request.args.get("next"))
+                flash('Successfully loggend in.', 'success')
+                if request.args.get("next"):
+                    return redirect(request.args.get('next'))
                 return redirect(url_for('backend.index'))
                 return redirect(url_for('backend.index'))
-            flash('Incorrect password.', 'danger')
-        else:
-            flash('User not found.', 'danger')
-        return redirect(url_for('auth.login'))
+            flash('Password Incorrect.', 'warning')
+            return render_template('login.j2', login_email=email)
+        flash('Email not found.', 'warning')
     return render_template('login.j2')
     return render_template('login.j2')
 
 
 
 
@@ -86,7 +87,7 @@ def register():
 
 
     if request.args.get("next") is not None:
     if request.args.get("next") is not None:
         return redirect(request.args.get("next"))
         return redirect(request.args.get("next"))
-    return redirect(url_for('backend.index'))
+    return redirect(url_for('static.index'))
 
 
 
 
 @BLUEPRINT.route("/logout")
 @BLUEPRINT.route("/logout")

+ 3 - 3
app/modules/auth/templates/login.j2

@@ -33,7 +33,7 @@
                         <form method="post">
                         <form method="post">
                             <div class="form-group">
                             <div class="form-group">
                                 <label class="text-normal text-dark">Email</label>
                                 <label class="text-normal text-dark">Email</label>
-                                <input type="email" class="form-control" name="email" placeholder="Email">
+                                <input type="email" class="form-control" name="email" placeholder="Email" value="{{ login_email }}">
                             </div>
                             </div>
                             <div class="form-group">
                             <div class="form-group">
                                 <label class="text-normal text-dark">Password</label>
                                 <label class="text-normal text-dark">Password</label>
@@ -49,11 +49,11 @@
                         <form action="{{ url_for('auth.register')}}" method="post">
                         <form action="{{ url_for('auth.register')}}" method="post">
                             <div class="form-group">
                             <div class="form-group">
                                 <label class="text-normal text-dark">Name</label>
                                 <label class="text-normal text-dark">Name</label>
-                                <input type="text" class="form-control" name="name" placeholder="Name" value="{{ name }}" required>
+                                <input type="text" class="form-control" name="name" placeholder="Name" value="{{ register_name }}" required>
                             </div>
                             </div>
                             <div class="form-group">
                             <div class="form-group">
                                 <label class="text-normal text-dark">Email</label>
                                 <label class="text-normal text-dark">Email</label>
-                                <input type="email" class="form-control" name="email" placeholder="Email" value="{{ email }}" required>
+                                <input type="email" class="form-control" name="email" placeholder="Email" value="{{ register_email }}" required>
                             </div>
                             </div>
                             <div class="form-group">
                             <div class="form-group">
                                 <label class="text-normal text-dark">Password</label>
                                 <label class="text-normal text-dark">Password</label>

+ 52 - 14
app/modules/backend/app.py

@@ -6,10 +6,11 @@ Backend
 import os
 import os
 import shutil
 import shutil
 
 
+import json
 from flask_login import login_required
 from flask_login import login_required
 from flask_menu import register_menu
 from flask_menu import register_menu
 from flask import render_template, request, redirect, url_for, flash, Blueprint
 from flask import render_template, request, redirect, url_for, flash, Blueprint
-from app.models import Page, File
+from app.models import Page, File, User
 
 
 
 
 BLUEPRINT = Blueprint(
 BLUEPRINT = Blueprint(
@@ -18,18 +19,21 @@ BLUEPRINT = Blueprint(
     template_folder='templates'
     template_folder='templates'
 )
 )
 
 
+BASE_PATH = 'app/modules/static/pages/'
 
 
 @BLUEPRINT.route('/')
 @BLUEPRINT.route('/')
 @register_menu(BLUEPRINT, 'index', 'Home')
 @register_menu(BLUEPRINT, 'index', 'Home')
 @login_required
 @login_required
 def index():
 def index():
     """Show homepage"""
     """Show homepage"""
-    pages = Page.query.all()
+    pages = Page.query.filter(Page.parent_id == None).all()
     files = File.query.all()
     files = File.query.all()
+    users = User.query.all()
     return render_template(
     return render_template(
         'site/index.j2',
         'site/index.j2',
         pages=pages,
         pages=pages,
-        files=files
+        files=files,
+        users=users
     )
     )
 
 
 
 
@@ -42,6 +46,7 @@ def render():
     menu = []
     menu = []
     for page in pages:
     for page in pages:
         menu.append(generate_menu(page))
         menu.append(generate_menu(page))
+    print_json(menu)
 
 
     path_base = 'app/modules/static/pages/'
     path_base = 'app/modules/static/pages/'
     path_public = path_base + "public"
     path_public = path_base + "public"
@@ -54,7 +59,10 @@ def render():
     os.makedirs(path_private)
     os.makedirs(path_private)
 
 
     for page in pages:
     for page in pages:
-        render_page(path_base, page, menu)
+        generate_directory('', page)
+
+    for page in pages:
+        render_page('', page, menu)
 
 
     flash('Successfully rendered pages.', 'success')
     flash('Successfully rendered pages.', 'success')
     return redirect(request.referrer, code=302)
     return redirect(request.referrer, code=302)
@@ -65,6 +73,7 @@ def generate_menu(page):
     menu_item = {}
     menu_item = {}
     menu_item['title'] = page.title
     menu_item['title'] = page.title
     menu_item['url'] = page.path()
     menu_item['url'] = page.path()
+    menu_item['private'] = page.private
     if page.children.count():
     if page.children.count():
         menu_item['children'] = []
         menu_item['children'] = []
         for child_page in page.children:
         for child_page in page.children:
@@ -72,23 +81,52 @@ def generate_menu(page):
     return menu_item
     return menu_item
 
 
 
 
+def generate_directory(path, page):
+    """Generate directories for pages"""
+    if page.children.count():
+        parent_path = path + page.url() + '/'
+        print(parent_path)
+        public_path = BASE_PATH + 'public/' + path + page.url()
+        private_path = BASE_PATH + 'private/' + path + page.url()
+        #print(public_path)
+        #print(private_path)
+        if not os.path.exists(public_path):
+            os.makedirs(public_path)
+        if not os.path.exists(private_path):
+            os.makedirs(private_path)
+        for child_page in page.children:
+            generate_directory(parent_path, child_page)
+
+
 def render_page(path, page, menu):
 def render_page(path, page, menu):
     """Function for page generation, recursive"""
     """Function for page generation, recursive"""
-    if not page.private and not page.parent_id:
-        path += 'public/' + page.url()
-    else:
-        path += page.url()
     if page.children.count():
     if page.children.count():
-        parent_path = path + '/'
-        if not os.path.exists(parent_path):
-            os.makedirs(parent_path)
+        path += page.url() + '/'
         for child_page in page.children:
         for child_page in page.children:
-            render_page(parent_path, child_page, menu)
+            render_page(path, child_page, menu)
+
+    path += page.url()
 
 
-    with open('%s.html' % path, 'w') as file:
+    # private
+    private_path = '%s%s/%s.html' % (BASE_PATH, 'private', path)
+    with open(private_path, 'w') as file:
         rendered_page = render_template(
         rendered_page = render_template(
-            'public/site.j2',
+            'public/private.j2',
             page=page,
             page=page,
             menu=menu
             menu=menu
         )
         )
         file.write(rendered_page)
         file.write(rendered_page)
+
+    public_path = '%s%s/%s.html' % (BASE_PATH, 'public', path)
+    with open(public_path, 'w') as file:
+        rendered_page = render_template(
+            'public/public.j2',
+            page=page,
+            menu=menu
+        )
+        file.write(rendered_page)
+
+
+def print_json(json_text):
+    """Print data to console"""
+    print(json.dumps(json_text, sort_keys=True, indent=4))

+ 6 - 0
app/modules/backend/modules/user/__init__.py

@@ -0,0 +1,6 @@
+
+"""
+Server static pages
+"""
+
+from .app import BLUEPRINT as Backend_User

+ 72 - 0
app/modules/backend/modules/user/app.py

@@ -0,0 +1,72 @@
+
+"""
+Backend
+"""
+
+from flask_login import login_required, current_user
+from flask_menu import register_menu
+from flask import render_template, request, redirect, url_for, flash, Blueprint
+from app import db
+from app.models import User
+
+
+BLUEPRINT = Blueprint(
+    'backend_user',
+    __name__,
+    template_folder='templates'
+)
+
+
+@BLUEPRINT.route('/edit/<int:user_id>', methods=["GET", "POST"])
+@login_required
+def edit(user_id):
+    """User editing"""
+    user = User.query.get(user_id)
+
+    if request.method == 'POST':
+        user.name = request.form['name']
+
+        db.session.add(user)
+        db.session.commit()
+
+        flash('User "%s" successfully edit' % user.name, 'success')
+
+    return render_template(
+        'user/edit.j2',
+        user=user,
+    )
+
+
+@BLUEPRINT.route('/approve/<int:user_id>')
+@login_required
+def approve(user_id):
+    """User removing"""
+    user = User.query.get(user_id)
+    user.approved = True
+
+    db.session.add(user)
+    db.session.commit()
+
+    flash('User "%s" successfully approved.' % user.name, 'success')
+    return redirect(url_for('backend.index'))
+
+
+@BLUEPRINT.route('/remove/<int:user_id>')
+@login_required
+def remove(user_id):
+    """User removing"""
+    user = User.query.get(user_id)
+
+    db.session.delete(user)
+    db.session.commit()
+
+    flash('User "%s" successfully remove' % user.name, 'success')
+    return redirect(url_for('backend.index'))
+
+
+@BLUEPRINT.route('/view/<int:user_id>')
+@login_required
+def view(user_id):
+    """Display user"""
+    user = User.query.get(user_id)
+    return render_template('user/view.j2', user=user)

+ 13 - 0
app/modules/backend/modules/user/templates/user/edit.j2

@@ -0,0 +1,13 @@
+{% extends "layout/backend.j2" %}
+{% block content %}
+<h1>User: {{ user.title }}</h1>
+<form method="post">
+    <div class="form-group">
+        <label class="text-normal text-dark">Name</label>
+        <input type="text" class="form-control" name="name" placeholder="title" value="{{ user.name }}">
+    </div>
+    <div class="form-group pull-right">
+        <button class="btn btn-primary">Save</button>
+    </div>
+</form>
+{% endblock %}

+ 4 - 0
app/modules/backend/modules/user/templates/user/view.j2

@@ -0,0 +1,4 @@
+{% extends "layout/backend.j2" %}
+{% block content %}
+<h1>User: {{ user.name }}</h1>
+{% endblock %}

+ 1 - 1
app/modules/backend/templates/layout/backend.j2

@@ -1,4 +1,3 @@
-
 <!DOCTYPE html>
 <!DOCTYPE html>
 <html>
 <html>
 <head>
 <head>
@@ -8,6 +7,7 @@
 </head>
 </head>
 <body>
 <body>
     <nav class="navbar navbar-expand-md navbar-dark bg-dark">
     <nav class="navbar navbar-expand-md navbar-dark bg-dark">
+        <a class="navbar-brand" href="/"><img src="/static/uploads/logo.png" style="height: 27px"></a>
         <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsDefault" aria-controls="navbarsDefault" aria-expanded="false" aria-label="Toggle navigation">
         <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsDefault" aria-controls="navbarsDefault" aria-expanded="false" aria-label="Toggle navigation">
             <span class="navbar-toggler-icon"></span>
             <span class="navbar-toggler-icon"></span>
         </button>
         </button>

+ 21 - 0
app/modules/backend/templates/layout/public.j2

@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>{{ page.title }} - ssg</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <script src="/static/js/main.js"></script>
+</head>
+<body>
+    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
+        <a class="navbar-brand" href="/"><img src="/static/uploads/logo.png" style="height: 27px"></a>
+        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
+            <span class="navbar-toggler-icon"></span>
+        </button>
+        <div class="collapse navbar-collapse" id="navbarSupportedContent">
+            {% block nav %}{% endblock %}
+        </div>
+    </nav>
+    <div class="container mt-3">
+        {{ page.content() }}
+    </div>
+</body>

+ 33 - 0
app/modules/backend/templates/public/private.j2

@@ -0,0 +1,33 @@
+{% extends "layout/public.j2" %}
+{% block nav %}
+<ul class="navbar-nav mr-auto">
+    {% for menu_item in menu %}
+    {% if 'children' in menu_item %}
+    <li class="nav-item dropdown">
+        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+            {{ menu_item['title'] }}
+        </a>
+        <div class="dropdown-menu" aria-labelledby="navbarDropdown">
+            <a class="dropdown-item" href="/{{ menu_item['url'] }}">{{ menu_item['title'] }}</a>
+            {%- for child_menu_item in menu_item['children'] recursive -%}
+            <a class="dropdown-item" href="/{{ child_menu_item['url'] }}">{{ '> ' * (loop.depth - 1) }}{{ child_menu_item['title'] }}</a>
+            {{ loop(child_menu_item['children']) }}
+            {%- endfor -%}
+        </div>
+    </li>
+    {% else %}
+    <li class="nav-item">
+        <a class="nav-link" href="/{{ menu_item['url'] }}">{{ menu_item['title'] }}</a>
+    </li>
+    {% endif %}
+    {% endfor %}
+</ul>
+<ul class="navbar-nav">
+	<li class="nav-item text-nowrap">
+          <a class="nav-link" href="/backend">Backend</a>
+    </li>
+    <li class="nav-item text-nowrap">
+          <a class="nav-link" href="/logout">Logout</a>
+    </li>
+</ul>
+{% endblock %}

+ 34 - 0
app/modules/backend/templates/public/public.j2

@@ -0,0 +1,34 @@
+{% extends "layout/public.j2" %}
+{% block nav %}
+<ul class="navbar-nav mr-auto">
+    {% for menu_item in menu %}
+    {% if not menu_item.private %}
+    {% if 'children' in menu_item %}
+    <li class="nav-item dropdown">
+        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+            {{ menu_item['title'] }}
+        </a>
+        <div class="dropdown-menu" aria-labelledby="navbarDropdown">
+            <a class="dropdown-item" href="/{{ menu_item['url'] }}">{{ menu_item['title'] }}</a>
+            {%- for child_menu_item in menu_item['children'] recursive -%}
+            {% if not child_menu_item.private %}
+            <a class="dropdown-item" href="/{{ child_menu_item['url'] }}">{{ '> ' * (loop.depth - 1) }}{{ child_menu_item['title'] }}</a>
+            {{ loop(child_menu_item['children']) }}
+            {% endif %}
+            {%- endfor -%}
+        </div>
+    </li>
+    {% else %}
+    <li class="nav-item">
+        <a class="nav-link" href="/{{ menu_item['url'] }}">{{ menu_item['title'] }}</a>
+    </li>
+    {% endif %}
+    {% endif %}
+    {% endfor %}
+</ul>
+<ul class="navbar-nav">
+    <li class="nav-item text-nowrap">
+          <a class="nav-link" href="/login">Login</a>
+    </li>
+</ul>
+{% endblock %}

+ 0 - 47
app/modules/backend/templates/public/site.j2

@@ -1,47 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <title>{{ page.title }} - ssg</title>
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <script src="/static/js/main.js"></script>
-</head>
-<body>
-    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
-        <a class="navbar-brand" href="/"><img src="/static/uploads/logo.png" style="height: 27px"></a>
-        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
-            <span class="navbar-toggler-icon"></span>
-        </button>
-        <div class="collapse navbar-collapse" id="navbarSupportedContent">
-            <ul class="navbar-nav mr-auto">
-                {% for menu_item in menu %}
-                {% if 'children' in menu_item %}
-                <li class="nav-item dropdown">
-                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
-                        {{ menu_item['title'] }}
-                    </a>
-                    <div class="dropdown-menu" aria-labelledby="navbarDropdown">
-                        <a class="dropdown-item" href="/{{ menu_item['url'] }}">{{ menu_item['title'] }}</a>
-                        {%- for child_menu_item in menu_item['children'] recursive -%}
-                        <a class="dropdown-item" href="/{{ child_menu_item['url'] }}">{{ '> ' * (loop.depth - 1) }}{{ child_menu_item['title'] }}</a>
-                        {{ loop(child_menu_item['children']) }}
-                        {%- endfor -%}
-                    </div>
-                </li>
-                {% else %}
-                <li class="nav-item">
-                    <a class="nav-link" href="/{{ menu_item['url'] }}">{{ menu_item['title'] }}</a>
-                </li>
-                {% endif %}
-                {% endfor %}
-            </ul>
-            <ul class="navbar-nav">
-                <li class="nav-item text-nowrap">
-                      <a class="nav-link" href="/backend">backend</a>
-                </li>
-            </ul>
-        </div>
-    </nav>
-    <div class="container mt-3">
-        {{ page.content() }}
-    </div>
-</body>

+ 45 - 0
app/modules/backend/templates/site/index.j2

@@ -97,5 +97,50 @@
             </div>
             </div>
         </div>
         </div>
     </div>
     </div>
+    <div class="col-sm">
+        <div class="card">
+            <div class="card-header">
+                Users
+            </div>
+            <div class="card-body">
+                <table class="table table-striped table-sm">
+                    <thead>
+                        <tr>
+                            <th>Action</th>
+                            <th>Name</th>
+                            <th>Approved</th>
+                            <th>Registration</th>
+                        </tr>
+                    </thead>
+                    <tbody>
+                        {% for user in users %}
+                        <tr>
+                            <td>
+                                <div class="btn-group">
+                                    <button class="btn btn-secondary btn-sm dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                                        Action
+                                    </button>
+                                    <div class="dropdown-menu">
+                                        <a class="dropdown-item" href="{{ url_for('backend_user.view', user_id=user.id) }}">View</a>
+                                        {% if not user.approved %}
+                                        <a class="dropdown-item" href="{{ url_for('backend_user.approve', user_id=user.id) }}">Approve</a>
+                                        {% endif %}
+                                    </div>
+                                </div>
+                            </td>
+                            <td>
+                                <a href="{{ url_for('backend_user.view', user_id=user.id) }}">
+                                    {{ user.name }}
+                                </a>
+                            </td>
+                            <td>{{ user.approved }}</td>
+                            <td>{{ user.registration_at }}</td>
+                        </tr>
+                        {%- endfor -%}
+                    </tbody>
+                </table>
+            </div>
+        </div>
+    </div>
 </div>
 </div>
 {% endblock %}
 {% endblock %}

+ 3 - 12
app/modules/static/app.py

@@ -5,7 +5,7 @@ Serve static content
 
 
 from flask import render_template, Blueprint, abort
 from flask import render_template, Blueprint, abort
 from jinja2 import TemplateNotFound
 from jinja2 import TemplateNotFound
-from flask_login import login_required
+from flask_login import current_user
 
 
 
 
 BLUEPRINT = Blueprint(
 BLUEPRINT = Blueprint(
@@ -14,22 +14,13 @@ BLUEPRINT = Blueprint(
     template_folder='pages'
     template_folder='pages'
 )
 )
 
 
-@BLUEPRINT.route("/private", defaults={"page": "index"})
-@BLUEPRINT.route("/private/<path:page>")
-@login_required
-def private_show(page):
-    """Display static page"""
-    try:
-        return render_template("private/%s.html" % page)
-    except TemplateNotFound:
-        abort(404)
-
-
 @BLUEPRINT.route("/", defaults={"page": "index"})
 @BLUEPRINT.route("/", defaults={"page": "index"})
 @BLUEPRINT.route("/<path:page>")
 @BLUEPRINT.route("/<path:page>")
 def show(page):
 def show(page):
     """Display static page"""
     """Display static page"""
     try:
     try:
+        if current_user.is_authenticated:
+            return render_template("private/%s.html" % page)
         return render_template("public/%s.html" % page)
         return render_template("public/%s.html" % page)
     except TemplateNotFound:
     except TemplateNotFound:
         abort(404)
         abort(404)

+ 24 - 0
migrations/versions/d692d6e1a31d_user_add_approved.py

@@ -0,0 +1,24 @@
+"""user_add_approved
+
+Revision ID: d692d6e1a31d
+Revises: 64c257f78218
+Create Date: 2019-03-01 14:04:43.327766
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = 'd692d6e1a31d'
+down_revision = '64c257f78218'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+    op.add_column('user', sa.Column('approved', sa.Boolean(), server_default='f', nullable=True))
+
+
+def downgrade():
+    op.drop_column('user', 'approved')