Django-guardian: ์ „์—ญ ๊ถŒํ•œ ๋Œ€ ๊ฐœ์ฒด ๊ถŒํ•œ

์— ๋งŒ๋“  2015๋…„ 12์›” 22์ผ  ยท  16์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: django-guardian/django-guardian

์ „์—ญ ๊ถŒํ•œ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฃจํ‹ด๊ณผ ๊ฐœ์ฒด ๊ถŒํ•œ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๋ฃจํ‹ด์œผ๋กœ ์ธํ•ด ๋งŽ์€ ๋ฒ„๊ทธ๊ฐ€ ์žˆ๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ด€๋ จ ๋ฒ„๊ทธ๋ฅผ ๋‹ซ๊ณ  ์—ฌ๊ธฐ์—์„œ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.

API change Enhancement

๋ชจ๋“  16 ๋Œ“๊ธ€

์ด์— ์‘!

permission_required_or_403์—๋Š” accept_global_perms ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์žˆ์ง€๋งŒ get_obj_perms๋กœ ๋™์ผํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ๋ณด๊ธฐ์— ์—†์Šต๋‹ˆ๋‹ค.

์ „์—ญ ๊ถŒํ•œ์„ ํฌํ•จํ•˜๋Š” get_obj_perms_with_global ํƒœ๊ทธ๋ฅผ ์ œ์•ˆํ•ฉ๋‹ˆ๋‹ค.

์ด ๊ธธ์„ ์ด๋ฏธ ์‹œ์ž‘ํ–ˆ๋Š”์ง€๋Š” ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ ํŒจ์น˜ ์ž‘์—…์„ ์‹œ์ž‘ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ ์‹œ์ž‘ํ•˜์…จ๋‹ค๋ฉด ์ฃผ์ €ํ•˜์ง€ ๋งˆ์‹œ๊ณ  ์ €๋ฅผ ๋ฉˆ์ถฐ์ฃผ์„ธ์š” :)

์ถ”์‹ : ๊ธฐ๋ณธ ๋™์ž‘์ด ์ „์—ญ ๊ถŒํ•œ์„ ํฌํ•จํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ฃผ์žฅ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. "์‚ฌ์šฉ์ž X๊ฐ€ Y๋ฅผ ๊ฐœ์ฒด Z๋กœ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?"๋ผ๊ณ  ๋ฌผ์„ ๋•Œ ๋ชจ๋“  ์‚ฌ์šฉ์ž/๊ฐœ์ฒด, ๊ทธ๋ฃน/๊ฐœ์ฒด๋ฅผ ํ™•์ธํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธ , ์‚ฌ์šฉ์ž/์ „์—ญ, ๊ทธ๋ฃน/์ „์—ญ ๊ถŒํ•œ. ๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๊ฒƒ์€ ๋‹จ์ง€ ๋‚ด๊ฐ€ ๊ทธ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹ ๋•Œ๋ฌธ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  ๊ฒƒ์„ ๋งํ–ˆ์ง€๋งŒ, ์ „์—ญ ๊ถŒํ•œ์„ ๋ณ„๋„๋กœ ํ™•์ธํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค...ํ .

Pesticles: ์ด๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ํ˜ผ๋ž€์Šค๋Ÿฌ์šด์ง€์— ๋Œ€ํ•œ ์ฆ๊ฑฐ๋กœ ๊ฐ€๋””์–ธ์— ๋Œ€ํ•œ ์ถฉ๋ถ„ํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” 6๊ฐœ์›”๋งˆ๋‹ค ์กฐ๊ธˆ์”ฉ ์•Œ์•„๋ƒ…๋‹ˆ๋‹ค... ๋งŒ์•ฝ ๊ทธ๋“ค์ด ์ „์—ญ ๊ถŒํ•œ์€ ์žˆ์ง€๋งŒ ๊ฐ์ฒด ์ˆ˜์ค€ ๊ถŒํ•œ์€ ์—†๋Š” ๊ฒฝ์šฐ request.user.has_access('foo', obj)๊ฐ€ true์—ฌ์•ผ ํ•œ๋‹ค๋ฉด. ์ˆ˜ํ‘œ๋ฅผ ๋‘ ๋ฒˆ ์“ฐ๋Š” ๊ฒƒ์€ ์ข‹์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

๋ˆ„๊ตฐ๊ฐ€๊ฐ€ pull ์š”์ฒญ์„ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค... ์ด์ƒ์ ์œผ๋กœ๋Š” ๊ธฐ์กด ์ฝ”๋“œ๋ฅผ ์†์ƒ์‹œํ‚ค์ง€ ์•Š๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค(์ด๊ฒƒ์ด ์ œ์ •์‹ ์ด๊ณ  ์‹คํ˜„ ๊ฐ€๋Šฅํ•œ์ง€ ์—ฌ๋ถ€๋Š” ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค).

์˜ค๋ž˜๋œ ๋ฌธ์ œ์ง€๋งŒ ์•„์ง pull ์š”์ฒญ์ด ํ‘œ์‹œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์— ๋Œ€ํ•œ ์†Œ์‹์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚˜๋Š” ๊ฐ™์€ ํ–‰๋™์„ ํ•˜๊ณ  ์žˆ๋Š”๋ฐ, ๊ทธ๊ฒƒ์€ ๊ทธ๋‹ค์ง€ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋ฌด๋ฆฌ ๊ฐ์‚ฌ!

๊ฐœ์ฒด ์ˆ˜์ค€์ด ์‹คํŒจํ•  ๋•Œ ์ „์—ญ์œผ๋กœ ๋Œ€์ฒดํ• ์ง€ ์—ฌ๋ถ€์™€ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๋” ๋งŽ์€ ํ†ต์ฐฐ๋ ฅ์ด ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— #49์— ๋ช‡ ๊ฐ€์ง€ ์˜๊ฒฌ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ซํžŒ ๋ฌธ์ œ๊ฐ€ ์•Œ๋ฆผ์„ ๋ฐœ์ƒ์‹œํ‚ค๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์—ฌ๊ธฐ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

๋””์ž์ธ ๊ฒฐ์ •์— ๋”ฐ๋ผ ์ด๋Ÿฌํ•œ ๋ฌธ์ œ ์ค‘ ์ผ๋ถ€์— ๋Œ€ํ•ด ์ž‘์—…ํ•  ์˜๋„๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ๋„์™€๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

327์€ ๋‚˜์—๊ฒŒ ๊ณ ์ • ๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

```
brandon=Person.objects.get(first_name='BRANDON')
brandon.is_superuser
๊ฑฐ์ง“

ํ•™๊ต=School.objects.get(pk=1)

get_users_with_perms(ํ•™๊ต, attach_perms=์ฐธ, with_superusers=๊ฑฐ์ง“, with_group_users=๊ฑฐ์ง“)
{}

assign_perm('add_school', ๋ธŒ๋žœ๋“ , ํ•™๊ต)

get_users_with_perms(ํ•™๊ต, attach_perms=์ฐธ, with_superusers=๊ฑฐ์ง“, with_group_users=๊ฑฐ์ง“)
{: ['ํ•™๊ต ์ถ”๊ฐ€']}

mehmet=Person.objects.get(first_name='๋ฉ”ํ๋ฉง')
mehmet.is_superuser
์ง„์‹ค

get_users_with_perms(ํ•™๊ต, attach_perms=True, with_superusers=True, with_group_users=False)
{: [],: ['ํ•™๊ต ์ถ”๊ฐ€', 'ํ•™๊ต ๋ณ€๊ฒฝ', 'ํ•™๊ต ์‚ญ์ œ']}

assign_perm('add_school', mehmet, ํ•™๊ต)

get_users_with_perms(ํ•™๊ต, attach_perms=True, with_superusers=True, with_group_users=False)
{: [],: ['ํ•™๊ต ์ถ”๊ฐ€', 'ํ•™๊ต ๋ณ€๊ฒฝ', 'ํ•™๊ต ์‚ญ์ œ']}

get_users_with_perms(ํ•™๊ต, attach_perms=์ฐธ, with_superusers=๊ฑฐ์ง“, with_group_users=๊ฑฐ์ง“)
{: ['ํ•™๊ต ์ถ”๊ฐ€'],: ['ํ•™๊ต ์ถ”๊ฐ€']}

#155:

get_obj_perms_field_choices (self) ๋‹ค์Œ ๋‘ ์ค„ ์ถ”๊ฐ€๋ฅผ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค.

        if self.exclude_default:
            choices = list(set(choices).intersection(self.obj._meta.permissions))

๋ชจ๋ธ์˜ ๊ธฐ๋ณธ ๊ถŒํ•œ์„ ์ œ์™ธํ•ฉ๋‹ˆ๋‹ค. ์ฒซ์งธ, intersection ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋˜๋Š”์ง€ ๋ช…ํ™•ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‘˜์งธ, ๊ฐœ์ฒด ๋Œ€ ๋ชจ๋ธ ๊ถŒํ•œ๊ณผ ๊ด€๋ จ์ด ์—†๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ๋ˆ„๋ฝ ๋œ ๊ฒƒ์ด ์žˆ์œผ๋ฉด ์ €๋ฅผ ์ˆ˜์ •ํ•˜์‹ญ์‹œ์˜ค.

๊ทธ๋Ÿฌ๋‚˜ ๊ทธ๊ฒƒ์„ ์กฐ์‚ฌํ•˜๋Š” ๋™์•ˆ ๋‹ค์Œ์—์„œ ๊ฐ์ฒด์™€ ๋ชจ๋ธ ๊ถŒํ•œ์„ ๋ถ„๋ฆฌํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•˜์Šต๋‹ˆ๋‹ค.

    def save_obj_perms(self):
        """
        Saves selected object permissions by creating new ones and removing
        those which were not selected but already exists.

        Should be called *after* form is validated.
        """
        perms = self.cleaned_data[self.get_obj_perms_field_name()]
        model_perms = [c[0] for c in self.get_obj_perms_field_choices()]

        to_remove = set(model_perms) - set(perms)
        for perm in to_remove:
            remove_perm(perm, self.user, self.obj)

        for perm in perms:
            assign_perm(perm, self.user, self.obj)

๊ถŒํ•œ์ด ๋ˆ„๋ฝ๋œ ๋ชจ๋“  ๊ถŒํ•œ์„ ๊ฐœ์ฒด ์ˆ˜์ค€์—์„œ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด์ง€๋งŒ ์ œ ์ƒ๊ฐ์—๋Š” ๋ชจ๋ธ ์ˆ˜์ค€์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ๊ถŒํ•œ์„ ๊ฑด๋„ˆ๋›ฐ๊ฑฐ๋‚˜ ํ•ด๋‹น ๋ชฉ์ ์— ๋Œ€ํ•œ ์˜ต์…˜์„ ์ œ๊ณตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ „์—ญ ์„ค์ • ์ƒ๊ฐ GUARDIAN_FALLBACK_TO_MODEL=False ์™€ ๊ฐ™์€ ์ ์šฉ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์ธ์ˆ˜ fallback_to_model=False ๊ฐœ์ฒด ์‚ฌ์šฉ ๊ถŒํ•œ ๋ฐ ๋ชจ๋ธ ๊ถŒํ•œ์„ ์ œ๋Œ€๋กœ ๋ฌ˜์‚ฌ์— ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’ False ์€ ์ด์ „ ๋ฒ„์ „๊ณผ์˜ ํ˜ธํ™˜์„ฑ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ์ „์—ญ ๋˜๋Š” ์ธ์ˆ˜ ์„ค์ • ์ค‘ ํ•˜๋‚˜๊ฐ€ True์ด๋ฉด ๋Œ€์ฒด๊ฐ€ ๋ฐœ์ƒํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

GUARDIAN_FALLBACK_TO_MODEL์— ๋Œ€ํ•ด +1์ž…๋‹ˆ๋‹ค.

#49์— ๋Œ€ํ•œ ํ† ๋ก ์— ๋”ฐ๋ฅด๋ฉด ์ด ์„ค์ •์€ ObjectPermissionBackend๊ฐ€ ๋ช…์‹œ์ ์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ์ œ์–ดํ•˜๋Š” โ€‹โ€‹๋ฐ๋„ ์ž˜ ์ž‘๋™ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

ํ’€ ๋ฆฌํ€˜์ŠคํŠธ(#546)๋ฅผ ์ƒ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. core.py ์˜ต์…˜์˜ ๊ฒ€์‚ฌ๊ธฐ ๊ธฐ๋Šฅ์ด ๋ชจ๋ธ ์ˆ˜์ค€ ๊ถŒํ•œ์œผ๋กœ ํด๋ฐฑ(๋˜๋Š” ํฌํ•จ)ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ชจ๋“ˆ๋„ ๊ฒ€ํ† ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋ฆฌ๋ทฐํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. ๋ˆ„๊ตฌ๋“  ๋›ฐ์–ด๋“ค๊ณ  ์‹ถ๋‹ค๋ฉด ๊ฐ€์žฅ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.

#327์ด ๋” ์ด์ƒ ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. #332๋Š” ์ˆ˜๋ฝ๋œ ๊ฒฝ์šฐ ์œ„์˜ pull ์š”์ฒญ์— ์˜ํ•ด ์ˆ˜์ •๋ฉ๋‹ˆ๋‹ค. #155(์œ„์—์„œ ์–ธ๊ธ‰)์™€ ๊ด€๋ จ๋œ ๋‹จ ํ•˜๋‚˜์˜ ์ธก๋ฉด ๋ฌธ์ œ๊ฐ€ ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ ๋˜ํ•œ ์ฒ˜๋ฆฌ๋˜์—ˆ๋‹ค๋ฉด(๋˜๋Š” ๋ณ„๋„์˜ ์ด์Šˆ๋กœ ์˜ฎ๊ฒจ์กŒ๋‹ค๋ฉด), ์ด ์ด์Šˆ๋Š” ์ข…๊ฒฐ๋  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ „์—ญ ๊ถŒํ•œ์€ ์„ค์ •๋œ ๊ฒฝ์šฐ ๊ฐœ์ฒด ์ˆ˜์ค€ ๊ถŒํ•œ์— ๋Œ€ํ•ด ์—ฌ์ „ํžˆ ์กด์ค‘๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ œ๊ฐ€ ์ž˜๋ชป ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ?

u = User.objects.get(id=1)
c = Client.objects.get(id=1)
assign_perm('core.change_client', u)
u = User.objects.get(id=1)  # reloading user for perm refresh
u.has_perm('core.change_client')  # True
u.has_perm('core.change_client', c)  # False
u.has_perm('change_client', c)  # False
get_perms(u, c)  # []

๊ทธ๋ฆฌ๊ณ  GUARDIAN_GLOBAL_PERMISSIONS_CARRY_OVER ๋˜๋Š” FALLBACK_TO_MODEL ์€ ๋ฌด์—‡์„ ํ•ฉ๋‹ˆ๊นŒ? ๋‘˜ ๋‹ค ๋ฌธ์„œํ™” ๋œ ๊ฒƒ ๊ฐ™์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์„ core.py ์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์„๊นŒ์š”?

get_user_perms:126 ๋ชจ๋“  ์‚ฌ์šฉ์ž ๊ถŒํ•œ ํ™•์ธ์˜ ์ค‘์‹ฌ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋ถ€์šธ ํ”Œ๋ž˜๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€์•ˆ์ ์œผ๋กœ ํŠธ๋ฆฌ๊ฑฐ ๊ฐ€๋Šฅ

def get_user_perms(self, obj):
    # ....
    user_global_perms = Permission.objects.filter(content_type=ctype)\
                                        .filter(user=self.user)\
                                        .values_list('codename', flat=True)
    user_object_perms = user_perms_qs.values_list("codename", flat=True)
    user_perms = list(chain(user_global_perms, user_object_perms))
    return user_perms
์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰