# -*- coding: utf-8 -*-
"""advanced_permissions

Revision: 0120
Revision ID: 5555e993377c
Revises: 537252d4f3d3
Create Date: 2017-01-31 15:23:33.777168

"""

# revision identifiers, used by Alembic.
revision = '5555e993377c'
down_revision = '537252d4f3d3'
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

def upgrade():
    conn = op.get_bind()

    op.create_table('roles',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('created_at', sa.DateTime(), nullable=True),
        sa.Column('updated_at', sa.DateTime(), nullable=True),
        sa.Column('created_by_id', sa.Integer(), nullable=True),
        sa.Column('owner_id', sa.Integer(), nullable=True),
        sa.Column('name', sa.String(), nullable=True),
        sa.Column('description', sa.Text(), nullable=True),
        sa.Column('cache_id', sa.String(), nullable=True),
        sa.Column('builtin', sa.String(), nullable=True),
        sa.ForeignKeyConstraint(['created_by_id'], ['users.id'], ondelete='SET NULL'),
        sa.ForeignKeyConstraint(['owner_id'], ['organizations.id'], ondelete='CASCADE'),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_roles_owner_id'), 'roles', ['owner_id'], unique=False)

    role_permissions = op.create_table('role_permissions',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('role_id', sa.Integer(), nullable=True),
        sa.Column('project_id', sa.Integer(), nullable=True),
        sa.Column('object_type', sa.String(), nullable=True),
        sa.Column('object_id', sa.Integer(), nullable=True),
        sa.Column('actions', postgresql.ARRAY(sa.String()), nullable=False),
        sa.ForeignKeyConstraint(['project_id'], ['projects.id'], ondelete='CASCADE'),
        sa.ForeignKeyConstraint(['role_id'], ['roles.id'], ondelete='CASCADE'),
        sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_role_permissions_project_id'), 'role_permissions', ['project_id'], unique=False)
    op.create_index(op.f('ix_role_permissions_role_id'), 'role_permissions', ['role_id'], unique=False)

    op.add_column('project_members', sa.Column('role_id', sa.Integer(), nullable=True))
    op.create_index(op.f('ix_project_members_role_id'), 'project_members', ['role_id'], unique=False)
    op.create_foreign_key('project_members_role_id_fkey', 'project_members', 'roles', ['role_id'], ['id'], ondelete='CASCADE')

    op.add_column('organizations', sa.Column('default_org_member_role_id', sa.Integer(), nullable=True))
    op.create_foreign_key('default_org_member_role_id_fkey', 'organizations', 'roles', ['default_org_member_role_id'], ['id'], ondelete='SET NULL')

    op.add_column('projects', sa.Column('default_org_member_role_id', sa.Integer(), nullable=True))
    op.create_foreign_key('default_org_member_role_id_fkey', 'projects', 'roles', ['default_org_member_role_id'], ['id'], ondelete='SET NULL')

    # ADMIN
    r = conn.execute("""
        INSERT INTO roles (created_at, created_by_id, owner_id, name, description, builtin, cache_id)
        SELECT now(), o.created_by_id, o.id, 'Admin', 'Member who can manage project settings', 'ADMIN', uuid_generate_v4()
        FROM organizations o, users u WHERE o.created_by_id = u.id AND (u.locale != 'fr' OR u.locale IS NULL) RETURNING id
    """)
    r2 = conn.execute("""
        INSERT INTO roles (created_at, created_by_id, owner_id, name, description, builtin, cache_id)
        SELECT now(), o.created_by_id, o.id, 'Admin', 'Membre qui peut gérer les paramètres du projet', 'ADMIN', uuid_generate_v4()
        FROM organizations o, users u WHERE o.created_by_id = u.id AND u.locale = 'fr' RETURNING id
    """)

    perms = []
    for r_infos in (r, r2):
        for r_info in r_infos:
            role_id = r_info[0]
            perms.extend([
                {'role_id': role_id, 'object_type': 'project', 'actions': ['MANAGE_SUB_BOARDS','OPTIONS','ACCESS','MANAGE_ATTRIBUTES','MANAGE_SHARED_VIEWS','MANAGE_RECURRING']},
                {'role_id': role_id, 'object_type': 'card', 'actions': ['CREATE','EDIT','DELETE','SWITCH_MODEL','ARCHIVE']},
                {'role_id': role_id, 'object_type': 'card_model', 'actions': ['CREATE','EDIT','DELETE']},
                {'role_id': role_id, 'object_type': 'card_group_type', 'actions': ['CREATE','EDIT','DELETE']},
                {'role_id': role_id, 'object_type': 'card_log_type', 'actions': ['CREATE','EDIT','DELETE']},
                {'role_id': role_id, 'object_type': 'card_group', 'actions': ['CREATE','EDIT','MOVE_CARDS','DELETE']},
                {'role_id': role_id, 'object_type': 'request_form', 'actions': ['CREATE','EDIT','DELETE']},
                {'role_id': role_id, 'object_type': 'card_comment', 'actions': ['CREATE','EDIT','DELETE','DELETE_MINE']},
                {'role_id': role_id, 'object_type': 'card_log', 'actions': ['CREATE','EDIT','DELETE','DELETE_MINE']},
                {'role_id': role_id, 'object_type': 'attribute', 'actions': ['EDIT']}
            ])
    op.bulk_insert(role_permissions, perms)

    # MEMBER
    r = conn.execute("""
        INSERT INTO roles (created_at, created_by_id, owner_id, name, description, builtin, cache_id)
        SELECT now(), o.created_by_id, o.id, 'Member', 'Create, edit and collaborate with cards and groups', 'MEMBER', uuid_generate_v4()
        FROM organizations o, users u WHERE o.created_by_id = u.id AND (u.locale != 'fr' OR u.locale IS NULL) RETURNING id
    """)
    r2 = conn.execute("""
        INSERT INTO roles (created_at, created_by_id, owner_id, name, description, builtin, cache_id)
        SELECT now(), o.created_by_id, o.id, 'Membre', 'Peut créer, modifier et collaborer sur les cartes et les groupes', 'MEMBER', uuid_generate_v4()
        FROM organizations o, users u WHERE o.created_by_id = u.id AND u.locale = 'fr' RETURNING id
    """)
    perms = []
    for r_infos in (r, r2):
        for r_info in r_infos:
            role_id = r_info[0]
            perms.extend([
                {'role_id': role_id, 'object_type': 'card', 'actions': ['CREATE','EDIT','DELETE','SWITCH_MODEL','ARCHIVE']},
                {'role_id': role_id, 'object_type': 'attribute', 'actions': ['EDIT']},
                {'role_id': role_id, 'object_type': 'card_group', 'actions': ['MOVE_CARDS']},
                {'role_id': role_id, 'object_type': 'card_comment', 'actions': ['CREATE','DELETE_MINE']},
                {'role_id': role_id, 'object_type': 'card_log', 'actions': ['CREATE','DELETE_MINE']}
            ])
    op.bulk_insert(role_permissions, perms)
    conn.execute("UPDATE organizations o SET default_org_member_role_id = (SELECT id FROM roles WHERE owner_id = o.id AND builtin = 'MEMBER')")

    # OBSERVER CAN COMMENT
    r = conn.execute("""
        INSERT INTO roles (created_at, created_by_id, owner_id, name, description, builtin, cache_id)
        SELECT now(), o.created_by_id, o.id, 'Observer allowed to comment', 'Read-only access but can comment on cards', 'OBSERVER ALLOWED TO COMMENT', uuid_generate_v4()
        FROM organizations o, users u WHERE o.created_by_id = u.id AND (u.locale != 'fr' OR u.locale IS NULL) RETURNING id
    """)
    r2 = conn.execute("""
        INSERT INTO roles (created_at, created_by_id, owner_id, name, description, builtin, cache_id)
        SELECT now(), o.created_by_id, o.id, 'Observateur autorisé à commenter', 'Accès en lecture seule mais peut commenter', 'OBSERVER ALLOWED TO COMMENT', uuid_generate_v4()
        FROM organizations o, users u WHERE o.created_by_id = u.id AND u.locale = 'fr' RETURNING id
    """)
    perms = []
    for r_infos in (r, r2):
        for r_info in r_infos:
            role_id = r_info[0]
            perms.append({'role_id': role_id, 'object_type': 'card_comment', 'actions': ['CREATE','DELETE_MINE']})
    op.bulk_insert(role_permissions, perms)

    #OBSERVER
    r = conn.execute("""
        INSERT INTO roles (created_at, created_by_id, owner_id, name, description, builtin, cache_id)
        SELECT now(), o.created_by_id, o.id, 'Observer', 'Read-only access', 'OBSERVER', uuid_generate_v4()
        FROM organizations o, users u WHERE o.created_by_id = u.id AND (u.locale != 'fr' OR u.locale IS NULL) RETURNING id
    """)
    r2 = conn.execute("""
        INSERT INTO roles (created_at, created_by_id, owner_id, name, description, builtin, cache_id)
        SELECT now(), o.created_by_id, o.id, 'Observateur', 'Accès en lecture seule', 'OBSERVER', uuid_generate_v4()
        FROM organizations o, users u WHERE o.created_by_id = u.id AND u.locale = 'fr' RETURNING id
    """)

    # Set default org member role

    conn.execute("""UPDATE projects SET default_org_member_role_id = (
        SELECT id FROM roles WHERE owner_id = projects.owner_id AND builtin = 'ADMIN'
    ) WHERE default_org_member_permission = 4""")

    conn.execute("""UPDATE projects SET default_org_member_role_id = (
        SELECT id FROM roles WHERE owner_id = projects.owner_id AND builtin = 'MEMBER'
    ) WHERE default_org_member_permission = 3""")

    conn.execute("""UPDATE projects SET default_org_member_role_id = (
        SELECT id FROM roles WHERE owner_id = projects.owner_id AND builtin = 'OBSERVER ALLOWED TO COMMENT'
    ) WHERE default_org_member_permission = 2""")

    conn.execute("""UPDATE projects SET default_org_member_role_id = (
        SELECT id FROM roles WHERE owner_id = projects.owner_id AND builtin = 'OBSERVER'
    ) WHERE default_org_member_permission = 1""")

    # update member roles

    conn.execute("""UPDATE project_members SET role_id = (
        SELECT roles.id FROM roles, projects WHERE project_members.project_id = projects.id
        AND roles.owner_id = projects.owner_id AND roles.builtin = 'ADMIN'
    ) WHERE permission = 4""")

    conn.execute("""UPDATE project_members SET role_id = (
        SELECT roles.id FROM roles, projects WHERE project_members.project_id = projects.id
        AND roles.owner_id = projects.owner_id AND roles.builtin = 'MEMBER'
    ) WHERE permission = 3""")

    conn.execute("""UPDATE project_members SET role_id = (
        SELECT roles.id FROM roles, projects WHERE project_members.project_id = projects.id
        AND roles.owner_id = projects.owner_id AND roles.builtin = 'OBSERVER ALLOWED TO COMMENT'
    ) WHERE permission = 2""")

    conn.execute("""UPDATE project_members SET role_id = (
        SELECT roles.id FROM roles, projects WHERE project_members.project_id = projects.id
        AND roles.owner_id = projects.owner_id AND roles.builtin = 'OBSERVER'
    ) WHERE permission = 1""")

    conn.execute('UPDATE organizations SET cache_id = uuid_generate_v4()')
    conn.execute('UPDATE projects SET members_cache_id = uuid_generate_v4()')

def downgrade():
    op.drop_constraint('default_org_member_role_id_fkey', 'projects', type_='foreignkey')
    op.drop_column('projects', 'default_org_member_role_id')

    op.drop_constraint('project_members_role_id_fkey', 'project_members', type_='foreignkey')
    op.drop_index(op.f('ix_project_members_role_id'), table_name='project_members')
    op.drop_column('project_members', 'role_id')

    op.drop_index(op.f('ix_role_permissions_role_id'), table_name='role_permissions')
    op.drop_index(op.f('ix_role_permissions_project_id'), table_name='role_permissions')
    op.drop_table('role_permissions')
    op.drop_index(op.f('ix_roles_owner_id'), table_name='roles')
    op.drop_table('roles')
