flask_peeweeのRestAPIで他ユーザーのデータの更新を制限する
flask_peeweeのRestAPIには他ユーザーのデータ更新を制限する機能が実装されているので
試してみたいと思います。
先日、RestAPIで返却するパラメータを制限するのにRestResourceというクラスのサブクラスを作成しました
from flaskext.rest import RestResource class UserResource(RestResource): exclude = ('password')
似たような感じでRestrictOwnerResourceというクラスを使用することによって、その名の通りの機能を
導入することができます。
RestrictOwnerResourceはRestResourceのサブクラスです。
from flaskext.rest import RestrictOwnerResource class PostResource(RestrictOwnerResource): owner_field = 'user' api.register(Post, PostResource)
user情報を保存するフィールド名をowner_fieldに文字列でもたせておきます。
あらかじめadminとadmin2という2つのユーザーを用意して試してみます。
import requests # apiからadminユーザーとしてpostで登録 res = requests.post('http://localhost:5000/api/post/', data={"data": '{"title": "test", "entry": "test_entry"}'}, auth=("admin","admin")) res # =><Response [200]> res.content # => '{\n "entry": "test_entry",\n "created": "2011-11-15 17:24:30",\n "user_id": 1,\n "id": 1,\n "title": "test"\n}' # apiからadmin2ユーザーとしてdeleteを試みる res = requests.delete('http://localhost:5000/api/post/1/', auth=("admin2","admin2")) res # => <Response [403]> res.content # => u'Forbidden' # apiからadminユーザーとしてdeleteを試みる res = requests.delete('http://localhost:5000/api/post/1/', auth=("admin","admin")) res # => <Response [200]> res.content # => '{\n "deleted": 1\n}'
登録したユーザーと別のユーザーで削除しようとすると403エラーが返されることがわかります。
全体のソース
import datetime from flask import Flask, render_template from flaskext.auth import Auth, BaseUser from flaskext.admin import Admin, ModelAdmin from flaskext.db import Database from flaskext.rest import RestAPI, UserAuthentication, RestResource,\ RestrictOwnerResource from peewee import TextField, DateTimeField, CharField, ForeignKeyField,\ BooleanField # configure our database DATABASE = { 'name': 'flask_peewee_sample.db', 'engine': 'peewee.SqliteDatabase', } DEBUG = True SECRET_KEY = '***********************' app = Flask(__name__) app.config.from_object(__name__) db = Database(app) # model class User(db.Model, BaseUser): username = CharField() password = CharField() email = CharField() active = BooleanField(default=True) admin = BooleanField(default=False) created = DateTimeField(default=datetime.datetime.now) def __unicode__(self): return self.username class Post(db.Model): user = ForeignKeyField(User) title = CharField() entry = TextField() created = DateTimeField(default=datetime.datetime.now) class PostAdmin(ModelAdmin): columns = ('title', 'entry', 'created',) class UserResource(RestResource): exclude = ('password') class PostResource(RestrictOwnerResource): owner_field = 'user' # for admin site auth = Auth(app, db, user_model=User) admin = Admin(app, auth) auth.register_admin(admin) admin.register(Post, PostAdmin) admin.setup() # for restapi user_auth = UserAuthentication(auth) api = RestAPI(app, default_auth=user_auth) api.register(Post, PostResource) api.register(User, UserResource) api.setup() if __name__ == '__main__': auth.User.create_table(fail_silently=True) Post.create_table(fail_silently=True) app.run()