Skip to content

Instantly share code, notes, and snippets.

@edo0xff
Created May 26, 2020 03:51
Show Gist options
  • Save edo0xff/8907a7121022395c58080144118d484d to your computer and use it in GitHub Desktop.
Save edo0xff/8907a7121022395c58080144118d484d to your computer and use it in GitHub Desktop.
Simple RESTful API server written in Python using Flask
# https://edo0xff.me/blog/e/escribiendo_una_rest_api_con_python
import jwt
import json
from flask import Flask
from flask_restful import reqparse, abort, Api, Resource
from bson import json_util, ObjectId
from pymongo import MongoClient
app = Flask(__name__)
api = Api(app)
mongo = MongoClient("mongodb://localhost:27017/")
JWT_SIGNATURE = 'Hha78*9d9asd0_ads0!@#asd>,A'
class Endpoint(Resource):
def __init__(self):
self.db = mongo.api
self.args = reqparse.RequestParser()
def serialize(self, resource):
return json.loads(json_util.dumps(resource))
def auth_required(self):
self.args.add_argument('token')
args = self.args.parse_args()
session = Auth.verify_token(args['token'])
print(session)
return session
class Auth(Endpoint):
@staticmethod
def verify_token(token):
if not token:
abort(401, message="No access token provided")
try:
return jwt.decode(token, JWT_SIGNATURE, algorithm='HS256')
except jwt.InvalidTokenError:
abort(401, message="Invalid access token")
def get(self):
self.args.add_argument("user")
self.args.add_argument("password")
self.args.add_argument("app_id")
self.args.add_argument("privileges")
args = self.args.parse_args()
if not args['user'] or not args['password']\
or not args['app_id'] or not args['privileges']:
abort(400, message="Invalid request")
if not args['user'] == "root" and args['password'] == "r00t404":
abort(401, message="Unauthorized")
session = {
"app_id": args['app_id'],
"privileges": args['privileges']
}
token = jwt.encode(session, JWT_SIGNATURE, algorithm='HS256')
return {'token': token.decode('UTF-8')}
class Notes(Endpoint):
def get(self):
self.args.add_argument("page")
self.args.add_argument("page_size")
args = self.args.parse_args()
try:
page = int(args['page'])
page_size = int(args['page_size'])
except (ValueError, TypeError):
page = 0
page_size = 5
notes = self.db.notes.find().skip(page * page_size).limit(page_size)
return self.serialize(notes)
def post(self):
self.auth_required()
self.args.add_argument('title')
self.args.add_argument('content')
args = self.args.parse_args()
if not args['title'] or not args['content']:
abort(400, message="Invalid title or content")
note = {
'title': args['title'],
'content': args['content']
}
note_id = self.db.notes.insert_one(note).inserted_id
note['_id'] = note_id
return self.serialize(note)
class Note(Endpoint):
def get(self, note_id):
if not len(note_id) == 24:
abort(400, message="Invalid element ID")
note = self.db.notes.find_one({'_id': ObjectId(note_id)})
if not note:
return abort(404, message="Note not found")
return self.serialize(note)
def put(self, note_id):
self.auth_required()
if not len(note_id) == 24:
abort(400, message="Invalid element ID")
self.args.add_argument('title')
self.args.add_argument('content')
args = self.args.parse_args()
if not args['title'] or not args['content']:
abort(400, message="Invalid title or content")
note = {
"$set": {
'title': args['title'],
'content': args['content']
}
}
result = self.db.notes.update_one({"_id": ObjectId(note_id)}, note)
if not result.acknowledged:
abort(404, message="Invalid resource")
note = self.db.notes.find_one({'_id': ObjectId(note_id)})
return self.serialize(note)
def delete(self, note_id):
self.auth_required()
if not len(note_id) == 24:
abort(400, message="Invalid element ID")
result = self.db.notes.delete_one({"_id": ObjectId(note_id)})
if not result.acknowledged:
abort(404, message="Invalid resource")
return {'ok': True}
api.add_resource(Notes, '/api/v1.0/notes')
api.add_resource(Note, '/api/v1.0/notes/<note_id>')
api.add_resource(Auth, '/api/v1.0/auth')
if __name__ == '__main__':
app.run(debug=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment