사용할 화면이 flask 서버 내에서 작성 된 것이 아닌 Vue.js에서 작성 된 것이기 때문에 flask서버에서는 api를 작성 해 주도록 할 것이다.
create table user(
id int(5) not null auto_increment,
username varchar(20) not null,
useremail varchar(100) default null,
userpwd varchar(100) not null,
bio text default null,
created_at datetime default current_timestamp,
updated_at datetime default current_timestamp on update current_timestamp,
primary Key(id,username)
)
INSERT INTO fullstack_test.`user`
(username, useremail, userpwd, bio, created_at, updated_at)
VALUES('wool', 'wool@gmail.com', 'qwerqwer123', '', CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);
mysql을 사용하고 flask-sqlalchemy를 사용 하고 있다.
flask 모델에 맞게 연동된 데이터베이스를 생성 해 주려고 한다.
flask-sqlacodegen은 모델을 생성 해 주는 툴이다. 다운받아 사용 할 것이다.
(venv)$ pip install flask-sqlacodegen
flask-sqlacodegen이라는 명령어로 실행 하면 된다.
사용법은 여러가지가 있다.
$ flask-sqlacodegen "[sql_class]://[username]:[password]@[DB_IP]/[DB_NAME]" — flask
$ flask-sqlacodegen "[sql_class]://[username]:[password]@[DB_IP]/[DB_NAME]" — flask > model.py
$ flask-sqlacodegen "[sql_class]://[username]:[password]@[DB_IP]/[DB_NAME]" — flask --table [table_name]> model.py
$ flask-sqlacodegen "mysql+pymysql://root:qwer!@#123@localhost:3306/test_db" — flask > model.py
우리가 필요한 User 모델을 뽑아보도록 하겠다.
(venv)$ flask-sqlacodegen "mysql+pymysql://wool:qwerqwer123@localhost:3306/fullstack_test" --flask
backend
├── app.py
├── back.dev.Dockerfile
├── my_model
│ ├── __init__.py
│ └── user_model.py
├── my_provider
│ ├── __init__.py
│ ├── baseball_scrapper.py
│ └── movie_scrapper.py
├── my_util
│ ├── __init__.py
│ ├── __pycache__
│ └── my_logger.py
└── requirements.txt
my_model 패키지를 만들고, user_model.py를 만들어서 방금 생성된 유저 클래스를 저장 해 주도록 하겠다
user_model.py의 코드이다
# coding: utf-8
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True, nullable=False)
username = db.Column(db.String(20), primary_key=True, nullable=False)
useremail = db.Column(db.String(100))
userpwd = db.Column(db.String(100), nullable=False)
bio = db.Column(db.Text)
created_at = db.Column(db.DateTime, server_default=db.FetchedValue())
updated_at = db.Column(db.DateTime, server_default=db.FetchedValue())
비밀번호는 문자 그대로 저장하기보다 암호화 해서 저장하는 것이 좋다
암호화를 위해서 flask-bcrypt를 설치 해 주도록 하자
(venv)$ pip install flask-bcrypt
backend/app.py
...
import os, traceback
from flask_bcrypt import Bcrypt
# instantiate the app
app = Flask(__name__)
app.secret_key = 'laksdjfoiawjewfansldkfnzcvjlzskdf'
app.config["SQLALCHEMY_DATABASE_URI"] = os.getenv("SQLALCHEMY_DATABASE_URI")
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = os.getenv("SQLALCHEMY_TRACK_MODIFICATIONS")
db = SQLAlchemy()
db.init_app(app)
# enable CORS
CORS(app, resources={r'/*': {'origins': '*'}})
bcrypt = Bcrypt(app)
...
# coding: utf-8
from flask_bcrypt import generate_password_hash, check_password_hash
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True, nullable=False)
username = db.Column(db.String(20), primary_key=True, nullable=False)
useremail = db.Column(db.String(100))
userpwd = db.Column(db.String(100), nullable=False)
bio = db.Column(db.Text)
created_at = db.Column(db.DateTime, server_default=db.FetchedValue())
updated_at = db.Column(db.DateTime, server_default=db.FetchedValue())
def has_password(self):
self.userpwd = generate_password_hash(self.userpwd).decode('utf8')
def check_password(self,password):
return check_password_hash(self.userpwd,password)
@app.route("/api/auth/signup", methods=['POST'])
def auth_signup():
my_logger.info("SignUp!")
my_logger.info(request.get_json())
data = request.get_json()
username = data.get('username')
useremail = data.get('useremail')
userpwd = data.get('userpwd')
bio = data.get('bio')
user_data = user_model.User.query.filter_by(username=username).first()
if user_data is not None:
my_logger.info("Username is Already exist")
return {"success": "username is already exist"}
try:
user = user_model.User(**data)
user.has_password()
user_model.db.session.add(user)
user_model.db.session.commit()
user_model.db.session.remove()
my_logger.info("user Save Success")
return {'success': 'user Save Success'}
except Exception as e:
my_logger.error("user Save Fail")
my_logger.debug(traceback.print_exc(e))
return {'fail': "user Save Fail"}
@app.route("/api/auth/login", methods=['POST'])
def auth_login():
my_logger.info("User auth Login")
my_logger.info(request.get_json())
username = request.get_json()['username']
useremail = request.get_json().get('useremail')
userpwd = request.get_json()['userpwd']
my_user = user_model.User()
try:
user_data = my_user.query.filter_by(username=username).first()
if user_data is not None:
my_logger.info(user_data.userpwd)
auth = user_data.check_password(userpwd)
if not auth:
my_logger.info("password validation fail!")
return {'success': 'password validation fail'}
else:
my_logger.info("login success!")
session['login'] = True
return {'success': 'user Login Success!'}
else:
my_logger.info("user information is wrong or user does not exists....")
session['login'] = False
return {'success': 'user information is wrong or user does not exists....'}
except Exception as e:
my_logger.error("login Exception...")
my_logger.debug(traceback.print_exc(e))
session['login_session'] = False
return {'fail': 'login Exception...'}
@app.route('/api/auth/logout')
def auth_logout():
session['login'] = False
return {'success': 'logout'}
생각보다 길었지만, API로 인증받은 token까지 추가 해 주는 것이 목표이다.
다음 글에서는 token을 추가 해 주도록 하려고 한다.