承認

□未翻訳

□翻訳中

□翻訳完了(中垣健志)

■レビュー(細田謙二)

承認

Authorization

新しいユーザーが登録されると、そのユーザーを含む新しいグループが作成されます。新しいユーザーのロールは、慣例的に"user_[id]"となります。ここで、[id]の部分は新しいユーザーのidです。自動的にグループを作成したくない場合は、以下のようにします。

Once a new user is registered, a new group is created to contain the user. The role of the new user is conventionally "user_[id]" where [id] is the id of the newly created id. The creation of the group can be disabled with

1.

auth.settings.create_user_groups = False

ただし、このような設定は推奨していません。

although we do not suggest doing so.

ユーザーはグループのメンバーシップを保持します。それぞれのグループは名前かロール名で特定されます。グループはパーミッションを保持します。従って、ユーザーも所属するグループのパーミッションを保持するになります。

Users have membership in groups. Each group is identified by a name/role. Groups have permissions. Users have permissions because of the groups they belong to.

グループの作成とグループへのメンバーシップとパーミッションの割り当ては、appadminを利用するか、以下のメソッドを使ってプログラム的に行うことができます。

You can create groups, give membership and permissions via appadmin or programmatically using the following methods:

1.

auth.add_group('role', 'description')

これは、新しく作成したグループのidを返します。

returns the id of the newly created group.

1.

auth.del_group(group_id)

これは、group_idを持つグループを削除します。

deletes the group with group_id.

1.

auth.del_group(auth.id_group('user_7'))

これは、 "user_7"のロールを持つグループ、つまり7番のユーザーに一意に関連付けられたグループを削除します。

deletes the group with role "user_7", i.e., the group uniquely associated to user number 7.

1.

auth.user_group(user_id)

これは、user_idで特定されるユーザーに一意に関連付けられたグループのidを返します。

returns the id of the group uniquely associated to the user identified by user_id.

1.

auth.add_membership(group_id, user_id)

これは、group_idグループに属するuser_id メンバーシップを与えます. user_id が指定されない場合、現在のログインユーザーが当てはめられます。

gives user_id membership of the group group_id. If the user_id is not specified, then web2py assumes the current logged-in user.

1.

auth.del_membership(group_id, user_id)

これは、group_idグループに属するuser_id メンバーシップを除きます. user_id が指定されない場合、現在のログインユーザーが当てはめられます。

revokes user_id membership of the group group_id. If the user_id is not specified, then web2py assumes the current logged-in user.

1.

auth.has_membership(group_id, user_id, role)

これは、user_id が、group_idグループ、もしくは、特定のロールを持つグループ、に属するメンバーシップがあるかどうかを確認します。group_idrole の両方ではなく、どちらかのみ指定してください。user_id が指定されない場合、現在のログインユーザーが当てはめられます。

checks whether user_id has membership of the group group_id or the group with the specified role. Only group_id or role should be passed to the function, not both. If the user_id is not specified, then web2py assumes the current logged-in user.

1.

auth.add_permission(group_id, 'name', 'object', record_id)

これは、(独自に定義した)"object"というオブジェクトに対する(独自に定義した)"name"というパーミンションを、group_idグループに属するメンバーに与えます。"object"がテーブル名だった場合、record_id がゼロならばテーブル全体に対してパーミッションが与えられ、record_id がゼロ以上の場合は特定のレコードにだけパーミッションが与えられます。パーミッションがテーブルに対して与えられた場合、('create', 'read', 'update', 'delete', 'select') の中からパーミッション名を利用するのが一般的です。これらのパーミッションは理解されていて、CRUDによって実施できるからです。

gives permission "name" (user defined) on the object "object" (also user defined) to members of the group group_id. If "object" is a tablename then the permission can refer to the entire table by setting record_id to a value of zero, or the permission can refer to a specific record by specifying a record_id value greater than zero. When giving permissions on tables, it is common to use a permission name in the set ('create', 'read', 'update', 'delete', 'select') since these permissions are understood and can be enforced by CRUD.

1.

auth.del_permission(group_id, 'name', 'object', record_id)

これは、パーミッションを無効にします。

revokes the permission.

1.

auth.has_permission('name', 'object', record_id, user_id)

これはuser_id で特定されるユーザーが、要求されたパーミッションを持つグループのメンバーかどうかを確認します。

checks whether the user identified by user_id has membership in a group with the requested permission.

1.

2.

rows = db(accessible_query('read', db.mytable, user_id))\

.select(db.mytable.ALL)

これは、"mytable"テーブルのなかで、 user_id ユーザーが"read"パーミッションを持つ行を全て返します。user_idが指定されない場合、現在のログインユーザーが当てはめられます。accessible_query(...)は他のクエリと組み合わてより複雑なものを作ることができます。accessible_query(...) はJOINを必要とする唯一のAuth のメソッドです。そのため、Google App Engineでは動作しません。

returns all rows of table "mytable" that user user_id has "read" permission on. If the user_idis not specified, then web2py assumes the current logged-in user. The accessible_query(...)can be combined with other queries to make more complex ones. accessible_query(...) is the only Auth method to require a JOIN, so it does not work on the Google App Engine.

以下の定義を前提として:

Assuming the following definitions:

1.

2.

3.

4.

5.

6.

>>> from gluon.tools import Auth

>>> auth = Auth(globals(), db)

>>> auth.define_tables()

>>> secrets = db.define_table('document', Field('body'))

>>> james_bond = db.auth_user.insert(first_name='James',

last_name='Bond')

次の例を示します。

Here is an example:

1.

2.

3.

4.

5.

6.

7.

8.

>>> doc_id = db.document.insert(body = 'top secret')

>>> agents = auth.add_group(role = 'Secret Agent')

>>> auth.add_membership(agents, james_bond)

>>> auth.add_permission(agents, 'read', secrets)

>>> print auth.has_permission('read', secrets, doc_id, james_bond)

True

>>> print auth.has_permission('update', secrets, doc_id, james_bond)

False

デコレータ

Decorators

パーミッションを確認する最も一般的な方法は、上記のメソッドを明示的に呼び出すのではなく、関数にデコレータを指定して、ログインしている訪問者に対してパーミッションをチェックするようにします。以下に幾つかの例を示します。

The most common way to check permission is not by explicit calls to the above methods, but by decorating functions so that permissions are checked relative to the logged-in visitor. Here are some examples:

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

17.

18.

19.

20.

21.

22.

23.

24.

25.

26.

27.

28.

29.

30.

31.

32.

def function_one():

return 'this is a public function'

@auth.requires_login()

def function_two():

return 'this requires login'

@auth.requires_membership('agents')

def function_three():

return 'you are a secret agent'

@auth.requires_permission('read', secrets)

def function_four():

return 'you can read secret documents'

@auth.requires_permission('delete', 'any file')

def function_five():

import os

for file in os.listdir('./'):

os.unlink(file)

return 'all files deleted'

@auth.requires(auth.user_id==1 or request.client=='127.0.0.1')

def function_six():

return 'you can read secret documents'

@auth.requires_permission('add', 'number')

def add(a, b):

return a + b

def function_six():

return add(3, 4)

最初の一つ以外の全ての関数は、訪問者がパーミッションを持っているか持っていないかに基づいて実行が制限されています。

Note that access to all functions apart from the first one is restricted based on permissions that the visitor may or may not have.

訪問者がログインしていない場合、パーミッションの確認はできません。ログインページにリダイレクトされ、ログイン後にパーミッションが必要なページに戻ります。

If the visitor is not logged in, then the permission cannot be checked; the visitor is redirected to the login page and then back to the page that requires permissions.

訪問者が指定した関数にアクセスするパーミッションを持っていない場合、以下のように定義されたURLにリダイレクトされます。

If the visitor does not have permission to access a given function, the visitor is redirect to the URL defined by

1.

2.

auth.settings.on_failed_authorization = \

URL('user',args='on_failed_authorization')

この変数を変更して、任意の場所へリダイレクトさせることが可能です。

You can change this variable and redirect the user elsewhere.

権限要求の組み合わせ

Combining Requirements

時には、権限要求を組み合わせることが必要になる場合があります。これは汎用的なrequiresデコレータによって行おうことができます。このデコレータは一つの引数、真か偽の条件、をとります。例えば、agentsにアクセス権限を与えたいが、火曜日だけにしたい場合は次のようにします:

Occasionally, it is necessary to combine requirements. This can be done via a generic requiresdecorator which takes a single argument, a true or false condition. For example, to give access to agents, but only on Tuesday:

1.

2.

3.

4.

@auth.requires(auth.has_membership(group_id=agents) \

and request.now.weekday()==1)

def function_seven():

return 'Hello agent, it must be Tuesday!'

次のような書き方もできます。

or equivalently:

1.

2.

3.

4.

@auth.requires(auth.has_membership(role='Secret Agent') \

and request.now.weekday()==1)

def function_seven():

return 'Hello agent, it must be Tuesday!'

権限とCRUD

Authorization and CRUD

デコレータ、かつ/または、明示的なチェックを用いることは、アクセス制御を実装する一つの方法です。

Using decorators and/or explicit checks provides one way to implement access control.

もう一つのアクセス制御を実装する方法は、データベースにアクセスする時に常に(SQLFORMではなく)CRUDを使う ようにして、データベースのテーブルやレコードに対するアクセス制御をCRUDから実施するようにすることです。これは、次の命令文を用いてAuthとCRUDを紐づけることで行うことができます。

Another way to implement access control is to always use CRUD (as opposed to SQLFORM) to access the database and to ask CRUD to enforce access control on database tables and records. This is done by linking Auth and CRUD with the following statement:

1.

crud.settings.auth = auth

これは、訪問者がログインしていて明示的なアクセス権を持っていない限り、いかなるCRUD関数へのアクセスも防ぎます。例えば、訪問者はコメントを投稿できるが、自分自身のコメントしか更新できないようにするには、次のようにします(crud、authおよびdb.commentが定義されているものとします):

This will prevent the visitor from accessing any of the CRUD functions unless the visitor is logged in and has explicit access. For example, to allow a visitor to post comments, but only update their own comments (assuming crud, auth and db.comment are defined):

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

17.

18.

19.

20.

21.

22.

23.

def give_create_permission(form):

group_id = auth.id_group('user_%s' % auth.user.id)

auth.add_permission(group_id, 'read', db.comment)

auth.add_permission(group_id, 'create', db.comment)

auth.add_permission(group_id, 'select', db.comment)

def give_update_permission(form):

comment_id = form.vars.id

group_id = auth.id_group('user_%s' % auth.user.id)

auth.add_permission(group_id, 'update', db.comment, comment_id)

auth.add_permission(group_id, 'delete', db.comment, comment_id)

auth.settings.register_onaccept = give_create_permission

crud.settings.auth = auth

def post_comment():

form = crud.create(db.comment, onaccept=give_update_permission)

comments = db(db.comment.id>0).select()

return dict(form=form, comments=comments)

def update_comment():

form = crud.update(db.comment, request.args(0))

return dict(form=form)

('read'権限を持つ)特定のレコードを選択することもできます。

You can also select specific records (those you have 'read' access to):

1.

2.

3.

4.

5.

def post_comment():

form = crud.create(db.comment, onaccept=give_update_permission)

query = auth.accessible_query('read', db.comment, auth.user.id)

comments = db(query).select(db.comment.ALL)

return dict(form=form, comments=comments)

以下で実施されるパーミッションの名前は

The permisions names enforced by :

1.

crud.settings.auth = auth

"read", "create", "update", "delete", "select", "impersonate"になります。

are "read", "create", "update", "delete", "select", "impersonate".

承認とダウンロード

Authorization and Downloads

デコレータの使用やcrud.settings.auth の使用でも、通常のダウンロード関数によるファイルのダウンロードに対する承認は実施されません。

The use of decorators and the use of crud.settings.auth do not enforce authorization on files downloaded by the usual download function

1.

def download(): return response.download(request, db)

そうしたい場合は、どの"upload"フィールドがダウンロードの際のアクセス制御を要求するファイルを含んでいるかを明示的に宣言しなければなりません。以下はその例です。

If one wishes to do so, one must declare explicitly which "upload" fields contain files that need access control upon download. For example:

1.

2.

3.

4.

5.

6.

7.

db.define_table('dog',

Field('small_image', 'upload'),

Field('large_image', 'upload'))

db.dog.large_image.authorization = lambda record: \

auth.is_logged_in() and \

auth.has_permission('read', db.dog, record.id, auth.user.id)

アップロードフィールドのauthorization属性は、Noneとするか(デフォルト)、関数にすることができます。関数は、ユーザーがログインしているかどうか、そして現在の行に対する'read'パーミッションを持っているかどうかを判断します。この例では、"small_image"フィールドにリンクされた画像のダウンロードには何の制限もかけられていませんが、"large_image"フィールドにリンクされた画像にはアクセス制御がかけられています。

The attribute authorization of upload field can be None (the default) or a function that decides whether the user is logged in and has permission to 'read' the current record. In this example, there is no restriction on downloading images linked by the "small_image" field, but we require access control on images linked by the "large_image" field.

アクセス制御と基本認証

Access Control and Basic Authentication

時には、アクセス制御を必要とするデコレータを持つアクションをサービスとして公開しなければならない場合があります。すなわち、プログラムやスクリプトから呼ばれてもなお、権限のチェックをするための認証を行うことができるものです。

Occasionally, it may be necessary to expose actions that have decorators that require access control as services; i.e., to call them from a program or script and still be able to use authentication to check for authorization.

Auth によってベーシック認証によるログインを可能にすることができます。

Auth enables login via basic authentication:

1.

auth.settings.allow_basic_login = False

上記の設定とともに、以下のようなアクションを定義すると

With this set, an action like

1.

2.

3.

4.

@auth.requires_login()

def give_me_time():

import time

return time.ctime()

次のようなシェルコマンドからそのアクションを呼び出すことができます。

can be called, for example, from a shell command:

1.

2.

wget --user=[username] --password=[password]

http://.../[app]/[controller]/give_me_time

ベーシック認証によるログインは、しばしば(次章で説明する)サービスに対する唯一のオプションとなります。しかしデフォルトは無効になっています。

Basic login is often the only option for services (described in the next chapter), but it is disabled by default.

設定とメッセージ

Settings and Messages

以下に示すのは、Authに対してカスタマイズを行うことのできる全てのパラメタの一覧です。

Here is a list of all parameters that can be customized for Auth

次のパラメタには、gluon.tools.Mail オブジェクトを指定してください。これにより、auth によるメールの送信が可能になります。

The following must point to a gluon.tools.Mail object to allow auth to send emails:

1.

auth.settings.mailer = None

次のパラメタには、user のアクションを定義するコントローラの名前を指定してください。

The following must be the name of the controller that defined the user action:

1.

auth.settings.controller = 'default'

次のパラメタは、とても重要な設定です。

The following is a very important setting:

1.

auth.settings.hmac_key = None

これには、"sha512:a-pass-phrase"のような設定をしてください。 これは、auth_user テーブルの"password"フィールドに対するCRYPTバリデータへ渡されます。パスワードをハッシュ化するために使われるアルゴリズムとパスフレーズになります。

It must be set to something like "sha512:a-pass-phrase" and it will be passed to the CRYPT validator for the "password" field of the auth_user table. It will be the algorithm and a-pass-phrase used to hash the passwords.

アクションを無効にするのは、その名前を以下のリストに追加します。

To disabled an action append its name to this list:

1.

auth.settings.actions_disabled = []

その例です。

For example:

1.

auth.settings.actions_disabled.append('register')

これは、登録を無効にしています。

will disable registration.

登録の検証のためのメールを受け取りたい場合は、次をTrueにします。

If you want to receive an email to verify registration set this to True:

1.

auth.settings.registration_requires_verification = False

新規登録において承認を待ってからログインできるようにするには場合は、次をTrueにします

If new registrants must wait for approval before being able to login set this to True:

1.

auth.settings.registration_requires_approval = False

承認を行うためには、appadminまたはプログラムから registration_key=='' と設定します。

Approval consists of setting registration_key=='' via appadmin or programmatically.

各新規ユーザーに対して新規グループを作成しないようにするには、次をFalseにします

If you do not want a new group for each new user set the following to False:

1.

auth.settings.create_user_groups = True

次の設定は、前述したように、代替のログイン方法とログインフォームを決定します。

The following settings determine alternative login methods and login forms, as discussed previously:

1.

2.

auth.settings.login_methods = [auth]

auth.settings.login_form = auth

ベーシック認証を許可したいですか?

Do you want to allow basic login?

1.

auth.settings.allows_basic_login = False

login アクション用のURLです。

The following is the URL of the login action:

1.

auth.settings.login_url = URL('user', args='login')

既にログインしている状態でユーザー登録用のページを開こうとした場合には、次のURLにリダイレクトされます。

If the user tried to access the register page but is already logged in, he will be redirected to this URL:

1.

auth.settings.logged_url = URL('user', args='profile')

プロフィールにイメージがある場合には、ダウンロード用のURLを指定してください

This must point to the URL of the download action, in case the profile contains images:

1.

auth.settings.download_url = URL('download')

以下のURLには様々な authアクションが実行された後にリダイレクトされるURLを指定してください(参照先が無い場合に)。

These must point to the URL you want to redirect your users to after the various possible authactions (in case there is no referrer):

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

auth.settings.login_next = URL('index')

auth.settings.logout_next = URL('index')

auth.settings.profile_next = URL('index')

auth.settings.register_next = URL('user', args='login')

auth.settings.retrieve_username_next = URL('index')

auth.settings.retrieve_password_next = URL('index')

auth.settings.change_password_next = URL('index')

auth.settings.request_reset_password_next = URL('user', args='login')

auth.settings.reset_password_next = URL('user', args='login')

auth.settings.verify_email_next = URL('user', args='login')

認証に失敗した場合にリダイレクトされるURLです。

This is the URL you want to be redirect to on failed authorization:

1.

2.

auth.settings.on_failed_authorization = \

URL('user',args='on_failed_authorization')

以下は、対応する各アクションに対する検証の後でかつ、どのデータベースのIO処理の前に実行されるコールバックのリストです。

These are lists of callbacks that should be executed after form validation for each of the corresponding action before any database IO:

1.

2.

3.

4.

5.

auth.settings.login_onvalidation = []

auth.settings.register_onvalidation = []

auth.settings.profile_onvalidation = []

auth.settings.retrieve_password_onvalidation = []

auth.settings.reset_password_onvalidation = []

各コールバックはform オブジェクトを引数として取る必要があります。それにより、データベースのIO処理が行われる前に、そのフォームオブジェクトの属性を修正することができます。

Each callback must be a function that takes the form object and it can modify the attributes of the form object before database IO is performed.

以下は、データベースのIO処理の後でかつ、リダイレクトが行われる前に実行されるコールバック関数の一覧です。

These are lists of callbacks that should be executed after the database IO is performed and before redirection:

1.

2.

3.

4.

auth.settings.login_onaccept = []

auth.settings.register_onaccept = []

auth.settings.profile_onaccept = []

auth.settings.verify_email_onaccept = []

その例です。

Here is an example:

1.

2.

3.

auth.settings.register_onaccept.append(lambda form:\

mail.send(to='you@example.com',subject='new user',

message="new user email is %s'%form.vars.email))

全てのauth アクションに対して、キャプチャを有効にできます。

You can enable capcha for any of the auth actions:

1.

2.

3.

4.

5.

auth.settings.captcha = None

auth.settings.login_captcha = None

auth.settings.register_captcha = None

auth.settings.retrieve_username_captcha = None

auth.settings.retrieve_password_captcha = None

.captchagluon.tools.Recaptchaを指すように設定されている場合、(.login_captchaのような)対応するオプションがNone に設定されている全てのフォームは、キャプチャを持ちます。一方、False に設定されていたらキャプチャを持ちません。代わりにもし、.captcha がNoneに設定されている場合、対応するオプションに gluon.tools.Recapcha オブジェクトが設定されているフォームのみがキャプチャを持ち、それ以外では持ちません。

If the .captcha settings points to a gluon.tools.Recaptcha, all forms for which the corresponding option (like .login_captcha) is set to None will have a captcha, while those for which the corresponding option is set to False will not. If, instead, .capcha is set to None, only those form who have a corresponding option set to a gluon.tools.Recapcha object will have catcha and the others will not.

次は、ログインセッションの失効時間です。

This is the login session expiration time:

1.

auth.settings.expiration = 3600 # seconds

パスワードフィールドの名前は変更することができます(例えばFirebirdでは"password"はキーワードであり、フィールドの名前として利用できません)。:

You can change the name of the password field (in Firebrid for example "password" is a keyword and cannot be used to name a field):

1.

auth.settings.password_field = 'password'

通常は、ログインフォームはメールアドレスのバリデーションを試みます。以下の設定でこれを無効にできます。

Normally the login form tries to validate an email. This can be disabled by changing this setting:

1.

auth.settings.login_email_validate = True

プロフィールの編集ページでレコードIDを表示したいですか?

Do you want to show the record id in the edit profile page?

1.

auth.settings.showid = False

フォームのカスタマイズにおいて、自動的なエラー通知を行いたくない場合は次のようにします。

For custom forms you may want to disable automatic error notification in forms:

1.

auth.settings.hideerror = False

また、フォームのカスタマイズにおいて、スタイルを変更したい場合は次のようにします。

Also for custom forms you can change the style:

1.

auth.settings.formstyle = 'table3cols'

("table2cols"、"divs"、"ul"が設定可能です)

デフォルトでは、"remember me"オプションによるログインを拡張するためのオプションがフォームに与えられています。以下の設定によって、その有効期限や、そのオプション自体を無効にすることができます。

By default the login form gives the option to extend the login via "remember me" option. The expiration time can be changed or the option disabled via these settings:

1.

2.

auth.settings.long_expiration = 3600*24*30 # one month

auth.settings.remember_me_form = True

次のメッセージをカスタマイズすることができます。その用途や場面は明らかでしょう。

You can also customize the following messages whose use and context should be obvious:

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

16.

17.

18.

19.

20.

21.

22.

23.

24.

25.

26.

27.

28.

29.

30.

31.

32.

33.

34.

35.

36.

37.

38.

39.

40.

41.

42.

43.

44.

45.

46.

47.

48.

49.

50.

51.

52.

53.

54.

55.

56.

57.

58.

59.

60.

61.

62.

63.

64.

65.

66.

67.

68.

69.

70.

71.

72.

73.

auth.messages.submit_button = 'Submit'

auth.messages.verify_password = 'Verify Password'

auth.messages.delete_label = 'Check to delete:'

auth.messages.function_disabled = 'Function disabled'

auth.messages.access_denied = 'Insufficient privileges'

auth.messages.registration_verifying = 'Registration needs verification'

auth.messages.registration_pending = 'Registration is pending approval'

auth.messages.login_disabled = 'Login disabled by administrator'

auth.messages.logged_in = 'Logged in'

auth.messages.email_sent = 'Email sent'

auth.messages.unable_to_send_email = 'Unable to send email'

auth.messages.email_verified = 'Email verified'

auth.messages.logged_out = 'Logged out'

auth.messages.registration_successful = 'Registration successful'

auth.messages.invalid_email = 'Invalid email'

auth.messages.unable_send_email = 'Unable to send email'

auth.messages.invalid_login = 'Invalid login'

auth.messages.invalid_user = 'Invalid user'

auth.messages.is_empty = "Cannot be empty"

auth.messages.mismatched_password = "Password fields don't match"

auth.messages.verify_email = ...

auth.messages.verify_email_subject = 'Password verify'

auth.messages.username_sent = 'Your username was emailed to you'

auth.messages.new_password_sent = 'A new password was emailed to you'

auth.messages.password_changed = 'Password changed'

auth.messages.retrieve_username = 'Your username is: %(username)s'

auth.messages.retrieve_username_subject = 'Username retrieve'

auth.messages.retrieve_password = 'Your password is: %(password)s'

auth.messages.retrieve_password_subject = 'Password retrieve'

auth.messages.reset_password = ...

auth.messages.reset_password_subject = 'Password reset'

auth.messages.invalid_reset_password = 'Invalid reset password'

auth.messages.profile_updated = 'Profile updated'

auth.messages.new_password = 'New password'

auth.messages.old_password = 'Old password'

auth.messages.group_description = \

'Group uniquely assigned to user %(id)s'

auth.messages.register_log = 'User %(id)s Registered'

auth.messages.login_log = 'User %(id)s Logged-in'

auth.messages.logout_log = 'User %(id)s Logged-out'

auth.messages.profile_log = 'User %(id)s Profile updated'

auth.messages.verify_email_log = 'User %(id)s Verification email sent'

auth.messages.retrieve_username_log = 'User %(id)s Username retrieved'

auth.messages.retrieve_password_log = 'User %(id)s Password retrieved'

auth.messages.reset_password_log = 'User %(id)s Password reset'

auth.messages.change_password_log = 'User %(id)s Password changed'

auth.messages.add_group_log = 'Group %(group_id)s created'

auth.messages.del_group_log = 'Group %(group_id)s deleted'

auth.messages.add_membership_log = None

auth.messages.del_membership_log = None

auth.messages.has_membership_log = None

auth.messages.add_permission_log = None

auth.messages.del_permission_log = None

auth.messages.has_permission_log = None

auth.messages.label_first_name = 'First name'

auth.messages.label_last_name = 'Last name'

auth.messages.label_username = 'Username'

auth.messages.label_email = 'E-mail'

auth.messages.label_password = 'Password'

auth.messages.label_registration_key = 'Registration key'

auth.messages.label_reset_password_key = 'Reset Password key'

auth.messages.label_registration_id = 'Registration identifier'

auth.messages.label_role = 'Role'

auth.messages.label_description = 'Description'

auth.messages.label_user_id = 'User ID'

auth.messages.label_group_id = 'Group ID'

auth.messages.label_name = 'Name'

auth.messages.label_table_name = 'Table name'

auth.messages.label_record_id = 'Record ID'

auth.messages.label_time_stamp = 'Timestamp'

auth.messages.label_client_ip = 'Client IP'

auth.messages.label_origin = 'Origin'

auth.messages.label_remember_me = "Remember me (for 30 days)"

add|del|has membershipのログには、"%(user_id)s" と"%(group_id)s"が使用できます。add|del|has permission ログには "%(user_id)s", "%(name)s", "%(table_name)s", "%(record_id)s"が使用できます。

add|del|has membership logs allow the use of "%(user_id)s" and "%(group_id)s".add|del|has permission logs allow the use of "%(user_id)s", "%(name)s", "%(table_name)s", and "%(record_id)s".