Skip to content

Commit 8fcd697

Browse files
authored
Merge pull request #1 from msnodeve/develop
[Merge] develop->master : first release
2 parents 05b1b5d + f9d3944 commit 8fcd697

28 files changed

Lines changed: 1357 additions & 1 deletion

.DS_Store

6 KB
Binary file not shown.

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,9 @@
22
.venv
33

44
# vscode
5-
.vscode
5+
.vscode
6+
7+
# python
8+
__pycache__
9+
10+
# database

Pipfile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,23 @@ url = "https://pypi.org/simple"
44
verify_ssl = true
55

66
[dev-packages]
7+
pytest-cov = "*"
8+
pytest = "*"
9+
pylint = "*"
10+
autopep8 = "*"
711

812
[packages]
13+
flask = "*"
14+
flask-sqlalchemy = "*"
15+
flask-migrate = "*"
16+
pymysql = "*"
17+
flask-restplus = "*"
18+
flask-marshmallow = "*"
19+
marshmallow-jsonapi = "*"
20+
flask-script = "*"
21+
flask-basicauth = "*"
22+
pyjwt = "*"
23+
flask-bcrypt = "*"
924

1025
[requires]
1126
python_version = "3.7"

Pipfile.lock

Lines changed: 531 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/.DS_Store

6 KB
Binary file not shown.

app/__init__.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""
2+
app init
3+
"""
4+
from flask import Flask, render_template, jsonify
5+
from flask_restplus import Resource, Api, fields, reqparse
6+
from flask_sqlalchemy import SQLAlchemy
7+
from sqlalchemy.exc import SQLAlchemyError
8+
from sqlalchemy.sql import text
9+
from flask_marshmallow import Marshmallow
10+
from app.api.database import DB
11+
from app.api import REST_API
12+
13+
SQLALCHEMY_DATABASE_URI = \
14+
("mysql+pymysql://{USER}:{PASSWORD}@{ADDR}:{PORT}/{NAME}?charset=utf8")
15+
16+
# 설명할 API에 대한 것
17+
MA = Marshmallow()
18+
19+
def create_app() -> (Flask):
20+
""" create_app() 함수를 호출해 앱을 초기화 """
21+
22+
""" app config part """
23+
# 나중에 config는 다 빼야 할 것 같다.
24+
app = Flask(__name__)
25+
app.app_context().push()
26+
app.config['SQLALCHEMY_DATABASE_URI'] = SQLALCHEMY_DATABASE_URI.format(
27+
USER="root",
28+
PASSWORD="1234",
29+
ADDR="127.0.0.1",
30+
PORT=3306,
31+
NAME="board"
32+
)
33+
app.config['SQLALCHEMY_ECHO'] = True
34+
app.config['DEBUG'] = True
35+
DB.init_app(app)
36+
REST_API.init_app(app)
37+
MA.init_app(app)
38+
39+
""" return part """
40+
return app

app/api/__init__.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from flask_restplus import Api
2+
from app.users.views import API as users_api
3+
from app.posts.views import API as posts_api
4+
from app.api.auth_type import ACCESS_TOKEN, BASIC_AUTH
5+
6+
REST_API = Api(authorizations={**ACCESS_TOKEN, **BASIC_AUTH})
7+
8+
REST_API.add_namespace(users_api, '/user')
9+
REST_API.add_namespace(posts_api, '/posts')

app/api/auth_type.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from flask import request
2+
from functools import wraps
3+
import jwt
4+
5+
SECERET_KEY = "Hello"
6+
ACCESS_TOKEN = {
7+
'Access Token': {
8+
'type': 'apiKey',
9+
'in': 'header',
10+
'name': 'Authorization'
11+
}
12+
}
13+
BASIC_AUTH = {
14+
'Basic Auth': {
15+
'type': 'basic',
16+
'in': 'header',
17+
'name': 'Authorization'
18+
},
19+
}
20+
21+
def login_required(f):
22+
@wraps(f)
23+
def decorated_function(*args, **kwargs):
24+
access_token = request.headers['Authorization']
25+
if access_token is not None:
26+
try:
27+
payload = jwt.decode(access_token, SECERET_KEY, "HS256")
28+
except jwt.InvalidTokenError:
29+
payload = None
30+
31+
# if payload is None:
32+
# return Response(status=401)
33+
34+
user_id = payload["user_id"]
35+
# g.user = get_user_info(user_id) if user_id else None
36+
else:
37+
return Response(status=401)
38+
39+
return f(*args, **kwargs)
40+
return decorated_function

app/api/database.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
from flask import jsonify
2+
from flask import make_response
3+
from flask_sqlalchemy import SQLAlchemy
4+
from sqlalchemy.exc import IntegrityError
5+
from marshmallow import ValidationError
6+
from app.constants import STATUS_CODE
7+
from flask_restplus import reqparse
8+
9+
DB = SQLAlchemy()
10+
11+
class CRUD:
12+
body = ''
13+
status_code = STATUS_CODE.NOT_IMPLEMENTED
14+
def add(self, resource, schema):
15+
try:
16+
DB.session.add(resource)
17+
DB.session.commit()
18+
query = resource.query.get(resource.id)
19+
self.body = jsonify(schema.dump(resource).data)
20+
self.status_code = STATUS_CODE.CREATED
21+
except IntegrityError as error:
22+
DB.session.rollback()
23+
error_message = str(error)
24+
self.body = jsonify({"error": error_message, "type":"IntegrityError"})
25+
if "Duplicate entry" in error_message:
26+
self.status_code = 404
27+
else:
28+
self.status_code = 400
29+
finally:
30+
response = (self.body, self.status_code.value)
31+
response = make_response(response)
32+
33+
return response
34+
35+
def update(self, args, schema):
36+
try:
37+
for key, value in args.items():
38+
setattr(self, key, value)
39+
DB.session.commit()
40+
self.body = jsonify(schema.dump(self).data)
41+
self.status_code = STATUS_CODE.OK
42+
except IntegrityError as error:
43+
DB.session.rollback()
44+
error_message = str(error)
45+
self.body = jsonify({"error": error_message, "type":"IntegrityError"})
46+
if "Duplicate entry" in error_message:
47+
self.status_code = STATUS_CODE.CONFLICT
48+
else:
49+
self.status_code = STATUS_CODE.BAD_REQUEST
50+
finally:
51+
response = (self.body, self.status_code.value)
52+
response = make_response(response)
53+
return response
54+
55+
def delete(self, resource, schema):
56+
DB.session.delete(resource)
57+
DB.session.commit()
58+
self.body = jsonify({"message":"success"})
59+
self.status_code = STATUS_CODE.OK
60+
response = (self.body, self.status_code.value)
61+
response = make_response(response)
62+
return response
63+
64+
def select(self, name, password):
65+
66+
return "test"

app/constants.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from enum import Enum
2+
3+
class STATUS_CODE(Enum):
4+
OK = 200
5+
CREATED = 201
6+
NO_CONTENT = 204
7+
BAD_REQUEST = 400
8+
UNAUTHORIZED = 401
9+
FORBIDDEN = 403
10+
NOT_FOUND = 404
11+
METHOD_NOT_ALLOWED = 405
12+
CONFLICT = 409
13+
INTERNAL_SERVER_ERROR = 500
14+
NOT_IMPLEMENTED = 501
15+
BAD_GATEWAY = 502
16+
17+
responses = {item.value: item.name for item in STATUS_CODE}
18+
19+
def support_codes(unsupport_codes):
20+
unsupport_codes = [code.value for code in unsupport_codes]
21+
return {code: name for code, name in responses.items() if code not in unsupport_codes}
22+
23+
GET = support_codes(unsupport_codes=[
24+
STATUS_CODE.CREATED, STATUS_CODE.NO_CONTENT,
25+
STATUS_CODE.CONFLICT,
26+
STATUS_CODE.METHOD_NOT_ALLOWED,
27+
STATUS_CODE.NOT_IMPLEMENTED])
28+
POST = support_codes(unsupport_codes=[
29+
STATUS_CODE.OK, STATUS_CODE.NO_CONTENT,
30+
STATUS_CODE.METHOD_NOT_ALLOWED,
31+
STATUS_CODE.NOT_IMPLEMENTED])
32+
PATCH = support_codes(unsupport_codes=[
33+
STATUS_CODE.CREATED,
34+
STATUS_CODE.NO_CONTENT,
35+
STATUS_CODE.METHOD_NOT_ALLOWED,
36+
STATUS_CODE.NOT_IMPLEMENTED])
37+
DELETE = support_codes(unsupport_codes=[
38+
STATUS_CODE.CREATED,
39+
STATUS_CODE.CONFLICT,
40+
STATUS_CODE.METHOD_NOT_ALLOWED,
41+
STATUS_CODE.NOT_IMPLEMENTED])

0 commit comments

Comments
 (0)