Skip to content

Commit

Permalink
WIP: support for MULTI_ORG mode (getredash#1447)
Browse files Browse the repository at this point in the history
  • Loading branch information
arikfr authored and alison985 committed Jun 13, 2017
1 parent a3b5c73 commit 0b2a102
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 40 deletions.
19 changes: 19 additions & 0 deletions client/app/multi_org.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html ng-app="app">
<head lang="en">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="UTF-8">
<base href="{{base_href}}">
<title>Redash</title>

<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/images/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.png">
</head>

<body>
<section>
<div ng-view></div>
</section>
</body>
</html>
4 changes: 2 additions & 2 deletions client/app/services/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ function AuthService($window, $location, $q, $http) {
login() {
const next = encodeURI($location.url());
logger('Calling login with next = %s', next);
window.location.href = `/login?next=${next}`;
window.location.href = `login?next=${next}`;
},
logout() {
logger('Logout.');
window.sessionStorage.removeItem(SESSION_ITEM);
$window.location.href = '/logout';
$window.location.href = 'logout';
},
loadSession() {
logger('Loading session');
Expand Down
13 changes: 8 additions & 5 deletions redash/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import os
import logging
import urlparse
import redis
from flask import Flask
from flask import Flask, safe_join
from flask_sslify import SSLify
from werkzeug.contrib.fixers import ProxyFix
from werkzeug.routing import BaseConverter, ValidationError
Expand Down Expand Up @@ -72,9 +73,11 @@ def create_redis_connection():

class SlugConverter(BaseConverter):
def to_python(self, value):
# This is an ugly workaround for when we enable multi-org and some files are being called by the index rule:
if value in ('google_login.png', 'favicon.ico', 'robots.txt', 'views'):
raise ValidationError()
# This is ay workaround for when we enable multi-org and some files are being called by the index rule:
for path in settings.STATIC_ASSETS_PATHS:
full_path = safe_join(path, value)
if os.path.isfile(full_path):
raise ValidationError()

return value

Expand All @@ -90,7 +93,7 @@ def create_app(load_admin=True):
from redash.metrics.request import provision_app

app = Flask(__name__,
template_folder=settings.STATIC_ASSETS_PATHS[-1],
template_folder=settings.STATIC_ASSETS_PATHS[0],
static_folder=settings.STATIC_ASSETS_PATHS[-1],
static_path='/static')

Expand Down
12 changes: 6 additions & 6 deletions redash/handlers/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@
import logging

from flask import flash, redirect, render_template, request, url_for
from flask_login import current_user, login_required, login_user, logout_user

from sqlalchemy.orm.exc import NoResultFound

from flask_login import current_user, login_required, login_user, logout_user
from redash import __version__, limiter, models, settings
from redash.authentication import current_org, get_login_url
from redash.authentication.account import (BadSignature, SignatureExpired,
Expand All @@ -14,6 +12,7 @@
from redash.handlers import routes
from redash.handlers.base import json_response, org_scoped_rule
from redash.version_check import get_latest_version
from sqlalchemy.orm.exc import NoResultFound

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -94,9 +93,9 @@ def forgot_password(org_slug=None):
def login(org_slug=None):
# We intentionally use == as otherwise it won't actually use the proxy. So weird :O
# noinspection PyComparisonWithNone
if current_org == None and not settings.MULTI_ORG:
if current_org is None and not settings.MULTI_ORG:
return redirect('/setup')
elif current_org == None:
elif current_org is None:
return redirect('/')

index_url = url_for("redash.index", org_slug=org_slug)
Expand Down Expand Up @@ -177,7 +176,8 @@ def config(org_slug=None):
})


@routes.route(org_scoped_rule('/api/session'), methods=['GET'])
# @routes.route(org_scoped_rule('/api/session'), methods=['GET'])
@routes.route('/api/session', methods=['GET'])
@login_required
def session(org_slug=None):
if not isinstance(current_user._get_current_object(), models.ApiUser):
Expand Down
48 changes: 26 additions & 22 deletions redash/handlers/setup.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from flask import redirect, request, render_template, url_for, g
from flask_login import login_user
from wtforms import Form, PasswordField, StringField, BooleanField, validators
from wtforms.fields.html5 import EmailField
from flask import g, redirect, render_template, request, url_for

from flask_login import login_user
from redash import settings
from redash.tasks.general import subscribe
from redash.handlers.base import routes
from redash.models import Organization, Group, User, db
from redash.authentication.org_resolving import current_org
from redash.handlers.base import routes
from redash.models import Group, Organization, User, db
from redash.tasks.general import subscribe
from wtforms import BooleanField, Form, PasswordField, StringField, validators
from wtforms.fields.html5 import EmailField


class SetupForm(Form):
Expand All @@ -19,28 +19,34 @@ class SetupForm(Form):
newsletter = BooleanField()


def create_org(org_name, user_name, email, password):
default_org = Organization(name=org_name, slug='default', settings={})
admin_group = Group(name='admin', permissions=['admin', 'super_admin'], org=default_org, type=Group.BUILTIN_GROUP)
default_group = Group(name='default', permissions=Group.DEFAULT_PERMISSIONS, org=default_org, type=Group.BUILTIN_GROUP)

db.session.add_all([default_org, admin_group, default_group])
db.session.commit()

user = User(org=default_org, name=user_name, email=email, group_ids=[admin_group.id, default_group.id])
user.hash_password(password)

db.session.add(user)
db.session.commit()

return default_org, user


@routes.route('/setup', methods=['GET', 'POST'])
def setup():
if current_org != None or settings.MULTI_ORG:
if current_org is not None or settings.MULTI_ORG:
return redirect('/')

form = SetupForm(request.form)
form.newsletter.data = True
form.security_notifications.data = True

if request.method == 'POST' and form.validate():
default_org = Organization(name=form.org_name.data, slug='default', settings={})
admin_group = Group(name='admin', permissions=['admin', 'super_admin'], org=default_org, type=Group.BUILTIN_GROUP)
default_group = Group(name='default', permissions=Group.DEFAULT_PERMISSIONS, org=default_org, type=Group.BUILTIN_GROUP)

db.session.add_all([default_org, admin_group, default_group])
db.session.commit()

user = User(org=default_org, name=form.name.data, email=form.email.data, group_ids=[admin_group.id, default_group.id])
user.hash_password(form.password.data)

db.session.add(user)
db.session.commit()
default_org, user = create_org(form.org_name.data, form.name.data, form.email.data, form.password.data)

g.org = default_org
login_user(user)
Expand All @@ -52,5 +58,3 @@ def setup():
return redirect(url_for('redash.index', org_slug=None))

return render_template('setup.html', form=form)


15 changes: 11 additions & 4 deletions redash/handlers/static.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import os

from flask import current_app, safe_join, send_file
from flask import current_app, render_template, safe_join, send_file
from werkzeug.exceptions import NotFound

from flask_login import login_required
from redash import settings
from redash.handlers import routes
from redash.handlers.authentication import base_href
from redash.handlers.base import org_scoped_rule
from werkzeug.exceptions import NotFound


@routes.route('/<path:filename>')
Expand All @@ -26,8 +28,13 @@ def send_static(filename):

@login_required
def index(**kwargs):
full_path = safe_join(settings.STATIC_ASSETS_PATHS[-2], 'index.html')
return send_file(full_path, **dict(cache_timeout=0, conditional=True))
if settings.MULTI_ORG:
response = render_template("multi_org.html", base_href=base_href())
else:
full_path = safe_join(settings.STATIC_ASSETS_PATHS[-2], 'index.html')
response = send_file(full_path, **dict(cache_timeout=0, conditional=True))

return response


def register_static_routes(rules):
Expand Down
6 changes: 5 additions & 1 deletion webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var config = {
// path: process.env.NODE_ENV === 'production' ? './dist' : './dev',
path: './client/dist',
filename: '[name].[chunkhash].js',
publicPath: '/'
},

plugins: [
Expand Down Expand Up @@ -44,9 +45,12 @@ var config = {
chunks: ['vendor']
}),
new HtmlWebpackPlugin({
// template: __dirname + '/app/' + 'index.html'
template: './client/app/index.html'
}),
new HtmlWebpackPlugin({
template: './client/app/multi_org.html',
filename: 'multi_org.html'
}),
new ExtractTextPlugin('styles.[chunkhash].css')
],

Expand Down

0 comments on commit 0b2a102

Please sign in to comment.