~sirn/fanboi2

857635ed1af899dcfa2f993bd9e5bd4858212b24 — Kridsada Thanabulpong 2 months ago b6d9420
services/post: add ident_v6 for ipv6 support
M fanboi2/models/_type.py => fanboi2/models/_type.py +1 -1
@@ 4,7 4,7 @@ from sqlalchemy.sql.sqltypes import Enum
BoardStatusEnum = Enum("open", "restricted", "locked", "archived", name="board_status")


IdentTypeEnum = Enum("none", "ident", "ident_admin", name="ident_type")
IdentTypeEnum = Enum("none", "ident", "ident_v6", "ident_admin", name="ident_type")


TopicStatusEnum = Enum("open", "locked", "archived", "expired", name="topic_status")

M fanboi2/services/post.py => fanboi2/services/post.py +13 -1
@@ 1,4 1,5 @@
import datetime
import ipaddress

from sqlalchemy.sql import func



@@ 90,10 91,21 @@ class PostCreateService(object):
        ident_type = "none"
        if board.settings["use_ident"]:
            ident_type = "ident"
            ident_addr = ip_address

            # Since it's common for IPv6 setup to delegate a /64 from ISP to a home
            # network, it makes more sense here to always generate ident based on
            # /64 network instead of individual address.
            if ipaddress.ip_address(ip_address).version == 6:
                ident_type = "ident_v6"
                ident_addr = str(
                    ipaddress.ip_network("%s/64" % (ip_address,), strict=False)
                )

            ident = self.identity_svc.identity_with_tz_for(
                self.setting_query_svc.value_from_key("app.time_zone"),
                board=topic.board.slug,
                ip_address=ip_address,
                ip_address=ident_addr,
            )

        post = Post(

M fanboi2/tests/test_services_post.py => fanboi2/tests/test_services_post.py +17 -0
@@ 52,6 52,23 @@ class TestPostCreateService(ModelSessionMixin, unittest.TestCase):
        self.assertEqual(topic_meta.post_count, 1)
        self.assertIsNotNone(topic_meta.bumped_at)

    def test_create_ipv6(self):
        from ..models import Board, Topic, TopicMeta

        board = self._make(Board(slug="foo", title="Foo"))
        topic = self._make(Topic(board=board, title="Hello", status="open"))
        self._make(TopicMeta(topic=topic, post_count=0))
        self.dbsession.commit()
        post_create_svc = self._make_one()
        post1 = post_create_svc.create(topic.id, "Hello!", True, "fe80:c9cd::1")
        self.assertEqual(post1.ip_address, "fe80:c9cd::1")
        self.assertEqual(post1.ident, "foo,fe80:c9cd::/64")
        self.assertEqual(post1.ident_type, "ident_v6")
        post2 = post_create_svc.create(topic.id, "Hello!", True, "fe80:c9cd::96f0:1111")
        self.assertEqual(post2.ip_address, "fe80:c9cd::96f0:1111")
        self.assertEqual(post2.ident, "foo,fe80:c9cd::/64")
        self.assertEqual(post2.ident_type, "ident_v6")

    def test_create_without_bumped(self):
        from ..models import Board, Topic, TopicMeta


A migration/versions/5d4ef3966456_add_ident_v6_ident_type.py => migration/versions/5d4ef3966456_add_ident_v6_ident_type.py +54 -0
@@ 0,0 1,54 @@
"""add ident_v6 ident type

Revision ID: 5d4ef3966456
Revises: 06000cefb0bb
Create Date: 2020-03-30 19:29:21.471805
"""
from alembic import op
from sqlalchemy.dialects.postgresql import ENUM
import sqlalchemy as sa


revision = "5d4ef3966456"
down_revision = "06000cefb0bb"


def alter_enum(enum_name, enum_value, fields=None):
    op.execute("ALTER TYPE %s RENAME TO %s_1" % (enum_name, enum_name))

    new_enum = sa.Enum(*enum_value, name=enum_name)
    new_enum.create(op.get_bind(), checkfirst=True)
    if fields:
        for table, column in fields:
            op.alter_column(
                table,
                column,
                type_=new_enum,
                postgresql_using="%s::text::%s" % (column, enum_name),
            )

    ENUM(name="%s_1" % enum_name).drop(op.get_bind(), checkfirst=True)


def upgrade():
    alter_enum(
        "ident_type",
        ("none", "ident", "ident_v6", "ident_admin"),
        (
            ("user", "ident_type"),
            ("post", "ident_type"),
            ("post_history", "ident_type"),
        ),
    )


def downgrade():
    alter_enum(
        "ident_type",
        ("none", "ident", "ident_admin"),
        (
            ("user", "ident_type"),
            ("post", "ident_type"),
            ("post_history", "ident_type"),
        ),
    )