Skip to content

Commit

Permalink
[CE-102] Support create/update/delete user for admin
Browse files Browse the repository at this point in the history
Change-Id: I80991d9fbb8a2f521fbea1233b04d2e4ea76d787
Signed-off-by: Haitao Yue <hightall@me.com>
  • Loading branch information
hightall committed Aug 5, 2017
1 parent b2b0370 commit 4625258
Show file tree
Hide file tree
Showing 11 changed files with 21,465 additions and 7 deletions.
8 changes: 6 additions & 2 deletions src/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
from resources import bp_index, \
bp_stat_view, bp_stat_api, \
bp_cluster_view, bp_cluster_api, \
bp_host_view, bp_host_api, bp_auth_api, bp_login
bp_host_view, bp_host_api, bp_auth_api, \
bp_login, bp_user_api, bp_user_view
from resources.models import ADMIN
from mongoengine import connect
from flask_login import LoginManager, UserMixin, login_required
from resources.user import User
Expand Down Expand Up @@ -49,13 +51,15 @@
app.register_blueprint(bp_stat_api)
app.register_blueprint(bp_auth_api)
app.register_blueprint(bp_login)
app.register_blueprint(bp_user_api)
app.register_blueprint(bp_user_view)

admin = os.environ.get("ADMIN", "admin")
admin_password = os.environ.get("ADMIN_PASSWORD", "pass")
salt = app.config.get("SALT", b"")
password = bcrypt.hashpw(admin_password.encode('utf8'), bytes(salt.encode()))
try:
user = User(admin, password, is_admin=True)
user = User(admin, password, is_admin=True, role=ADMIN)
user.save()
except Exception:
pass
Expand Down
2 changes: 2 additions & 0 deletions src/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@
from .stat import bp_stat_api, bp_stat_view
from .auth_api import bp_auth_api
from .login import bp_login
from .user_api import bp_user_api
from .user_view import bp_user_view
3 changes: 1 addition & 2 deletions src/resources/auth_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,4 @@ def login():
@bp_auth_api.route('/logout', methods=['GET'])
def logout():
logout_user()
return make_ok_resp(data={'success': True,
'next': url_for('bp_login.login')})
return redirect(url_for('bp_index.show'))
9 changes: 7 additions & 2 deletions src/resources/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@
import os
import datetime
from mongoengine import Document, StringField,\
BooleanField, DateTimeField
BooleanField, DateTimeField, IntField

sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))

ADMIN = 0
OPERATOR = 1
COMMON_USER = 2


class User(Document):
username = StringField(unique=True)
password = StringField(default=True)
active = BooleanField(default=True)
isAdmin = BooleanField(default=False)
timestamp = DateTimeField(default=datetime.datetime.now())
role = IntField(default=COMMON_USER)
timestamp = DateTimeField(default=datetime.datetime.now)
7 changes: 6 additions & 1 deletion src/resources/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@

class User(UserMixin):
def __init__(self, username=None, password=None, active=True,
is_admin=False, id=None):
is_admin=False, role=None, id=None):
self.username = username
self.password = password
self.active = active
self.isAdmin = is_admin
self.role = role
self.id = None

def is_active(self):
Expand All @@ -26,10 +27,14 @@ def is_active(self):
def is_admin(self):
return self.isAdmin

def user_role(self):
return self.role

def save(self):
new_user = models.User(username=self.username,
password=self.password,
active=self.active,
role=self.role,
isAdmin=self.isAdmin)
new_user.save()
self.id = new_user.id
Expand Down
140 changes: 140 additions & 0 deletions src/resources/user_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
# Copyright IBM Corp, All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
import logging
import os
import sys
import bcrypt

from flask import Blueprint, redirect, url_for
from flask import request as r
from flask import current_app as app
from flask_login import login_required
from flask_login import login_user, logout_user

sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
from common import log_handler, LOG_LEVEL, \
request_get, make_ok_resp, make_fail_resp, \
request_debug, request_json_body, \
CODE_CREATED, CODE_NOT_FOUND
from .user import User
from .models import User as UserModel
from .models import ADMIN
import time

logger = logging.getLogger(__name__)
logger.setLevel(LOG_LEVEL)
logger.addHandler(log_handler)

bp_user_api = Blueprint('bp_user_api', __name__,
url_prefix='/{}/{}'.format("api", "user"))


@bp_user_api.route('/list', methods=['GET'])
@login_required
def list_user():
request_debug(r, logger)
f = {}
f.update(r.args.to_dict())
page = int(f.get("pageNo", 1))
per_page = int(f.get("pageSize", 10))
sort_columns = f.get("sortColumns", "")
sort_columns = sort_columns.split(" ")
sort_str = ''
if len(sort_columns) > 1:
sort_type = sort_columns[1]
sort_field = sort_columns[0]
if sort_type == "desc":
sort_str = "-%s" % sort_field
else:
sort_str = sort_field
offset = (page - 1) * per_page

user_count = UserModel.objects.all().count()
users = UserModel.objects.skip(offset).limit(per_page).order_by(sort_str)

users = [{
"id": str(user.id),
"name": user.username,
"isAdmin": user.isAdmin,
"role": user.role,
"active": user.active,
"timestamp": time.mktime(user.timestamp.timetuple())
} for user in users]

result = {
"users": {
"result": users,
"totalCount": user_count,
"pageSize": per_page,
"pageNo": page
},
}

return make_ok_resp(data=result)


@bp_user_api.route('/create', methods=['POST'])
@login_required
def create_user():
request_debug(r, logger)
if not r.form["username"] or not r.form["password"] \
or not r.form["role"]:
error_msg = "create user without enough data"
logger.warning(error_msg)
return make_fail_resp(error=error_msg, data=r.form)

username, password = r.form["username"], r.form["password"]
role, active = int(r.form["role"]), r.form["active"]
active = active == "true"
salt = app.config.get("SALT", b"")
password = bcrypt.hashpw(password.encode('utf8'), bytes(salt.encode()))

try:
user = User(username, password, is_admin=role == ADMIN,
role=role, active=active)
user.save()
return make_ok_resp(code=CODE_CREATED)
except Exception as exc:
logger.info("exc %s", exc)
return make_fail_resp(error="create user failed")


@bp_user_api.route('/update/<user_id>', methods=['PUT'])
@login_required
def update_user(user_id):
request_debug(r, logger)
if not r.form["username"] or not r.form["password"] \
or not r.form["role"]:
error_msg = "create user without enough data"
logger.warning(error_msg)
return make_fail_resp(error=error_msg, data=r.form)

username, role = r.form["username"], int(r.form["role"])
active = r.form["active"]
active = active == "true"
try:
UserModel.objects(id=user_id).update(set__username=username,
set__active=active,
set__role=role, upsert=True)
except Exception as exc:
error_msg = exc.message
logger.warning(error_msg)
return make_fail_resp(error=error_msg, data=r.form)

return make_ok_resp(data={})


@bp_user_api.route('/delete/<user_id>', methods=['DELETE'])
@login_required
def delete_user(user_id):
request_debug(r, logger)
try:
user = UserModel.objects.get(id=user_id)
except Exception:
pass
else:
user.delete()

return make_ok_resp(data={})
29 changes: 29 additions & 0 deletions src/resources/user_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

# Copyright IBM Corp, All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
import logging
import os
import sys

from flask import Blueprint, render_template

sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
from common import log_handler, LOG_LEVEL
from flask_login import login_required

logger = logging.getLogger(__name__)
logger.setLevel(LOG_LEVEL)
logger.addHandler(log_handler)


bp_user_view = Blueprint('bp_user_view', __name__,
url_prefix='/{}'.format("view"))


@bp_user_view.route('/users', methods=['GET'])
@login_required
def users():

return render_template("users.html")

0 comments on commit 4625258

Please sign in to comment.