Skip to content

Commit

Permalink
Add support for permissions (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
nhumrich authored Oct 4, 2016
1 parent dcf2427 commit 31e1708
Show file tree
Hide file tree
Showing 15 changed files with 225 additions and 159 deletions.
18 changes: 0 additions & 18 deletions .gitlab-ci.yml

This file was deleted.

44 changes: 18 additions & 26 deletions migrations/versions/21b664b587ce_create_initial_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
depends_on = None

from alembic import op
from sqlalchemy import Column, String, Integer, Boolean, ForeignKey
from sqlalchemy.dialects.postgresql import ARRAY, TIMESTAMP
from sqlalchemy import Column, String, Integer, ForeignKey
from sqlalchemy.dialects.postgresql import TIMESTAMP, JSONB


def upgrade():
Expand All @@ -23,7 +23,7 @@ def upgrade():
# squads
op.create_table(
'squads',
Column('squad_id', type_=Integer, primary_key=True),
Column('id', type_=Integer, primary_key=True, autoincrement=True),
Column('name', type_=String(50), unique=True)
)

Expand Down Expand Up @@ -55,35 +55,27 @@ def upgrade():
)
op.create_index('on_togs', 'toggles', ['feature', 'env'], unique=True)

# roles
roles_table = op.create_table(
'roles',
Column('role_id', type_=Integer, primary_key=True),
Column('name', type_=String()),
Column('is_blacklist', type_=Boolean, default=True),
Column('whitelist', type_=ARRAY(String)),
Column('blacklist', type_=ARRAY(String)),
Column('can_create', type_=Boolean)
)

# employees
op.create_table(
'employees',
Column('employee_id', Integer, primary_key=True),
Column('name', String()),
Column('username', type_=String(), unique=True),
Column('username', type_=String(25), unique=True, primary_key=True),
Column('name', String),
Column('squad_id', Integer, ForeignKey('squads.squad_id')),
Column('email', type_=String()),
Column('role_id', Integer, ForeignKey('roles.role_id'))
Column('email', type_=String),
Column('role_id', Integer)
)

# Seed
op.bulk_insert(
roles_table,
[
{'name': 'admin', 'can_create': True}
]
# auditing
op.create_table(
'auditing',
Column('id', Integer, autoincrement=True, primary_key=True),
Column('event', String(length=50), nullable=False, index=True),
Column('user', String(), nullable=True),
Column('date', TIMESTAMP),
Column('event_data', JSONB, nullable=True)
)

# Seed
op.bulk_insert(
envs_table,
[
Expand All @@ -96,8 +88,8 @@ def upgrade():

def downgrade():
op.drop_table('employees')
op.drop_table('roles')
op.drop_table('toggles')
op.drop_table('features')
op.drop_table('environments')
op.drop_table('squads')
op.drop_table('auditing')
32 changes: 0 additions & 32 deletions migrations/versions/795cfbb52a87_add_auditing_table.py

This file was deleted.

2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ asyncpgsa
aiohttp
sqlalchemy
alembic
aiogithubauth
aiohttp_auth
aiohttp_autoreload
psycopg2
uvloop
Expand Down
2 changes: 1 addition & 1 deletion run.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
app = core.init()

if __name__ == '__main__':
core.main()
core.main(app)
6 changes: 6 additions & 0 deletions tests/api/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
- config:
- testset: 'app tests'

- test:
- name: 'hit main page'
- url: '/'
- curl_option_followlocation: True
- curl_option_maxredirs: 5

- test:
- name: 'test get envs'
- url: '/api/envs'
Expand Down
83 changes: 28 additions & 55 deletions tmeister/core.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import os
import json

import aiogithubauth
import aiohttp_oauth
from aiohttp import web
from aiohttp_index import IndexMiddleware
from asyncpgsa import pg
from raven import Client
from raven_aiohttp import AioHttpTransport

from . import toggles, features, environments, auditing
from . import toggles, features, environments, auditing, employees
from .errorhandling import error_middleware

DEBUG = os.getenv('DEBUG', 'false').lower() == 'true'
LOCAL_DEV = os.getenv('IS_LOCAL', 'false').lower() == 'true'
GH_ID = os.getenv('GITHUB_ID')
GH_SECRET = os.getenv('GITHUB_SECRET')
GH_ORG = os.getenv('GITHUB_ORG')
COOKIE_NAME = os.getenv('COOKIE_NAME', 's3githubauth')
COOKIE_NAME = os.getenv('COOKIE_NAME', 'tmeister-auth')
COOKIE_KEY = os.getenv('COOKIE_KEY')
POSTGRES_URL = os.getenv('DATABASE_URL', 'localhost')
POSTGRES_USERNAME = os.getenv('DATABASE_USER', 'postgres')
Expand All @@ -32,43 +32,6 @@
' environment variables are missing')


async def error_middleware(app, handler):
async def middleware_handler(request: web.Request):
try:
response = await handler(request)
except json.decoder.JSONDecodeError as e:
return web.json_response(data={'Message': e.msg}, status=400)
except Exception as e:
if app.raven:
data = {
'request': {
'method': request.method,
'data': None,
'query_string': request.query_string,
'url': request.path
},
# 'user': {
# # put user data here
# 'id': 3,
# 'username': 'myuser',
# }
}
tags = {
# Put things you want to filter by in sentry here
}
extra_data = {
# Put extra data here
}
if request.has_body:
data['request']['data'] = await request.text()

app.raven.captureException(extra=extra_data,
tags=tags, data=data)
raise
return response
return middleware_handler


async def async_setup(app):

await pg.init(
Expand All @@ -85,21 +48,30 @@ def init():
app = web.Application(middlewares=[
IndexMiddleware(),
error_middleware,
])
])

app.on_startup.append(async_setup)

if not LOCAL_DEV:
aiogithubauth.add_github_auth_middleware(
app,
github_id=GH_ID,
github_secret=GH_SECRET,
github_org=GH_ORG,
cookie_name=COOKIE_NAME,
cookie_key=COOKIE_KEY,
whitelist_handlers=[toggles.get_toggle_states_for_env],
api_unauthorized=True
)
oauth_kwargs = dict(
github_id=GH_ID,
github_secret=GH_SECRET,
github_org=GH_ORG,
cookie_name=COOKIE_NAME,
cookie_key=COOKIE_KEY,
whitelist_handlers=[toggles.get_toggle_states_for_env],
oauth_url='/oauth_callback/github',
auth_callback=employees.check_employee,
cookie_is_secure=True
)
if LOCAL_DEV:
oauth_kwargs['dummy'] = True
oauth_kwargs['cookie_is_secure'] = False

aiohttp_oauth.add_oauth_middleware(
app,
**oauth_kwargs
)

app.router.add_get('/api/envs/{name}/toggles',
toggles.get_toggle_states_for_env)
app.router.add_get('/api/toggles', toggles.get_all_toggle_states)
Expand All @@ -124,9 +96,10 @@ def init():
return app


def main():
def main(app=None):
# setup
app = init()
if app is None:
app = init()

if DEBUG:
import aiohttp_autoreload
Expand Down
31 changes: 10 additions & 21 deletions tmeister/dataaccess/db.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from sqlalchemy import Table, Column, Integer, String, \
Boolean, ForeignKey
from sqlalchemy.dialects.postgresql import ARRAY, TIMESTAMP, JSONB
ForeignKey
from sqlalchemy.dialects.postgresql import TIMESTAMP, JSONB
import sqlalchemy as sa

METADATA = sa.MetaData()
Expand Down Expand Up @@ -31,34 +31,23 @@
auditing = Table(
'auditing', METADATA,
Column('id', Integer, autoincrement=True, primary_key=True),
Column('event', String(50), index=True),
Column('user', String),
Column('event', String(50), index=True, nullable=False),
Column('user', String, nullable=True),
Column('date', TIMESTAMP),
Column('event_data', JSONB)
Column('event_data', JSONB, nullable=True)
)

squads = Table(
'squads', METADATA,
Column('squad_id', type_=Integer, primary_key=True),
Column('squad_id', type_=Integer, primary_key=True, autoincrement=True),
Column('name', type_=String(50), unique=True),
)

employees = Table(
'employees', METADATA,
Column('employee_id', Integer, primary_key=True),
Column('name', String()),
Column('username', type_=String(), unique=True),
Column('username', type_=String(), primary_key=True, unique=True),
Column('name', String),
Column('squad_id', Integer, ForeignKey('squads.squad_id')),
Column('email', type_=String()),
Column('role_id', Integer, ForeignKey('roles.role_id'))
)

roles = Table(
'roles', METADATA,
Column('role_id', type_=Integer, primary_key=True),
Column('name', type_=String()),
Column('is_blacklist', type_=Boolean, default=True),
Column('whitelist', type_=ARRAY(String)),
Column('blacklist', type_=ARRAY(String)),
Column('can_create', type_=Boolean)
Column('email', type_=String),
Column('role_id', Integer)
)
30 changes: 30 additions & 0 deletions tmeister/dataaccess/employeeda.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from asyncpgsa import pg
import sqlalchemy as sa
from . import db


async def get_employee(username):
query = db.employees.select().where(db.employees.c.username == username)
employee = await pg.fetchrow(query)
return employee


async def get_employee_usernames(employee_list=None):
query = sa.select([db.employees.c.username])
if employee_list:
query = query.where(db.employees.c.username.in_(employee_list))

results = await pg.fetch(query)

return [r.username for r in results]


async def add_employee(username: str, *,
email: str = None, name: str = None,
squad_id: int = None, role_id: int = None):
query = db.employees.insert()\
.values(username=username, name=name, squad_id=squad_id,
email=email, role_id=role_id)

employee_id = await pg.fetchval(query)
return employee_id
Loading

0 comments on commit 31e1708

Please sign in to comment.