Skip to content

Commit

Permalink
Merge pull request #2350 from getredash/auth
Browse files Browse the repository at this point in the history
Authentication related settings improvements
  • Loading branch information
arikfr authored Feb 28, 2018
2 parents 0e4313d + d1062ce commit bb28b2f
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 150 deletions.
1 change: 1 addition & 0 deletions bin/docker-entrypoint
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ case "$1" in
scheduler
;;
dev_server)
export FLASK_DEBUG=1
exec /app/manage.py runserver --debugger --reload -h 0.0.0.0
;;
shell)
Expand Down
75 changes: 0 additions & 75 deletions client/app/assets/less/inc/contacts.less

This file was deleted.

48 changes: 0 additions & 48 deletions client/app/assets/less/inc/todo-list.less

This file was deleted.

14 changes: 14 additions & 0 deletions client/app/assets/less/redash/redash-newstyle.less
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@ body {
clear: both;
}

.callout {
padding: 20px;
border: 1px solid #eee;
border-left-width: 5px;
border-radius: 3px;
}

.callout-warning {
border-left-color: #aa6708;
}

.callout-info {
border-left-color: #1b809e;
}

// Fixed width layout for specific pages
@media (min-width: 768px) {
Expand Down
8 changes: 8 additions & 0 deletions client/app/filters/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,11 @@ export function prettySize(bytes) {

return bytes.toFixed(3) + ' ' + units[unit];
}

export function join(arr) {
if (arr === undefined || arr === null) {
return '';
}

return arr.join(' / ');
}
50 changes: 38 additions & 12 deletions client/app/pages/settings/organization.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,38 +16,64 @@ <h3 class="m-t-0">General</h3>
<h3>Authentication</h3>
<p>
<label>
<input name="input" type="checkbox" ng-model="$ctrl.settings.auth_password_login_enabled"
ng-change="$ctrl.update('auth_password_login_enabled')" accesskey="tab">
Password Login Enabled
<input name="input" type="checkbox" ng-model="$ctrl.settings.auth_password_login_enabled" ng-change="$ctrl.update('auth_password_login_enabled')"
accesskey="tab" ng-disabled="$ctrl.disablePasswordLoginToggle()"> Password Login Enabled
<span uib-popover="Password login can be disabled only if another login method is enabled." popover-trigger="'mouseenter'"
ng-if="$ctrl.disablePasswordLoginToggle()">
<i class="fa fa-question-circle"></i>
</span>
</label>

<div class="callout callout-warning" ng-if="!$ctrl.settings.auth_password_login_enabled">
Password based login is currently disabled and users will be able to login only with the enabled SSO options.
</div>
</p>

<div ng-if="$ctrl.googleLoginEnabled">
<h4>Google Login</h4>
<label>
Allowed Google Apps Domains
</label>
<ui-select multiple tagging tagging-label="false" ng-model="$ctrl.settings.auth_google_apps_domains" tagging-tokens="SPACE|,"
title="Google Apps Domain(s)"
ng-change="$ctrl.update('auth_google_apps_domains')">
<ui-select-match placeholder="Google Apps Domain(s)">{{$item}}</ui-select-match>
<!-- the ui-select-choices is here just to make ui-select work -->
<ui-select-choices repeat="domain in $ctrl.domains">
{{domain}}
</ui-select-choices>
</ui-select>

<div class="callout callout-info m-t-5" ng-if="$ctrl.settings.auth_google_apps_domains | notEmpty">
Any user registered with a <strong>{{$ctrl.settings.auth_google_apps_domains | join}}</strong> Google Apps account will be able to login. If they don't have an existing user, a new user will be created and join the <strong>Default</strong> group.
</div>
</div>

<h4>SAML</h4>
<p>
<label>
<input name="input" type="checkbox" ng-model="$ctrl.settings.auth_saml_enabled"
ng-change="$ctrl.update('auth_saml_enabled')" accesskey="tab">
SAML Enabled
<input name="input" type="checkbox" ng-model="$ctrl.settings.auth_saml_enabled" ng-change="$ctrl.update('auth_saml_enabled')"
accesskey="tab"> SAML Enabled
</label>

<div ng-show="$ctrl.settings.auth_saml_enabled">
<div class="form-group">
<label>SAML Metadata URL</label>
<input name="input" type="string" class="form-control" ng-model="$ctrl.settings.auth_saml_metadata_url" accesskey="tab"
ng-change="$ctrl.update('auth_saml_metadata_url')" ng-model-options="{ debounce: 200 }">
<input name="input" type="string" class="form-control" ng-model="$ctrl.settings.auth_saml_metadata_url" accesskey="tab" ng-change="$ctrl.update('auth_saml_metadata_url')"
ng-model-options="{ debounce: 200 }">
</div>
<div class="form-group">
<label>SAML Entity ID</label>
<input name="input" type="string" class="form-control" ng-model="$ctrl.settings.auth_saml_entity_id" accesskey="tab"
ng-change="$ctrl.update('auth_saml_entity_id')" ng-model-options="{ debounce: 200 }">
<input name="input" type="string" class="form-control" ng-model="$ctrl.settings.auth_saml_entity_id" accesskey="tab" ng-change="$ctrl.update('auth_saml_entity_id')"
ng-model-options="{ debounce: 200 }">
</div>
<div class="form-group">
<label>SAML NameID Format</label>
<input name="input" type="string" class="form-control" ng-model="$ctrl.settings.auth_saml_nameid_format" accesskey="tab"
ng-change="$ctrl.update('auth_saml_nameid_format')" ng-model-options="{ debounce: 200 }">
ng-change="$ctrl.update('auth_saml_nameid_format')" ng-model-options="{ debounce: 200 }">
</div>
</div>
</p>
</div>
</div>
</settings-screen>
</settings-screen>
12 changes: 11 additions & 1 deletion client/app/pages/settings/organization.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import settingsMenu from '@/lib/settings-menu';
import template from './organization.html';

function OrganizationSettingsCtrl($http, toastr, Events) {
function OrganizationSettingsCtrl($http, toastr, clientConfig, Events) {
Events.record('view', 'page', 'org_settings');

this.settings = {};
Expand All @@ -13,10 +13,20 @@ function OrganizationSettingsCtrl($http, toastr, Events) {
$http.post('api/settings/organization', { [key]: this.settings[key] }).then((response) => {
this.settings = response.data.settings;
toastr.success('Settings changes saved.');

if (this.disablePasswordLoginToggle() && this.settings.auth_password_login_enabled === false) {
this.settings.auth_password_login_enabled = true;
this.update('auth_password_login_enabled');
}
}).catch(() => {
toastr.error('Failed saving changes.');
});
};

this.googleLoginEnabled = clientConfig.googleLoginEnabled;

this.disablePasswordLoginToggle = () =>
(clientConfig.googleLoginEnabled || this.settings.auth_saml_enabled) === false;
}

export default function init(ngModule) {
Expand Down
4 changes: 3 additions & 1 deletion redash/handlers/authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def render_token_login_page(template, org_slug, token):
show_saml_login=current_org.get_setting('auth_saml_enabled'),
show_remote_user_login=settings.REMOTE_USER_LOGIN_ENABLED,
show_ldap_login=settings.LDAP_LOGIN_ENABLED,
org_slug=org_slug,
user=user), status_code


Expand Down Expand Up @@ -172,7 +173,8 @@ def client_config():
'dateFormat': date_format,
'dateTimeFormat': "{0} HH:mm".format(date_format),
'mailSettingsMissing': settings.MAIL_DEFAULT_SENDER is None,
'dashboardRefreshIntervals': settings.DASHBOARD_REFRESH_INTERVALS
'dashboardRefreshIntervals': settings.DASHBOARD_REFRESH_INTERVALS,
'googleLoginEnabled': settings.GOOGLE_OAUTH_ENABLED
}

client_config.update(defaults)
Expand Down
30 changes: 23 additions & 7 deletions redash/handlers/settings.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from flask import request

from redash.models import db
from redash.handlers.base import BaseResource
from redash.models import db, Organization
from redash.handlers.base import BaseResource, record_event
from redash.permissions import require_admin
from redash.settings.organization import settings as org_settings


def get_settings_with_defaults(defaults, values):
def get_settings_with_defaults(defaults, org):
values = org.settings.get('settings', {})
settings = {}

for setting, default_value in defaults.iteritems():
Expand All @@ -19,14 +20,15 @@ def get_settings_with_defaults(defaults, values):
else:
settings[setting] = current_value

settings['auth_google_apps_domains'] = org.google_apps_domains

return settings


class OrganizationSettings(BaseResource):
@require_admin
def get(self):
current_values = self.current_org.settings.get('settings', {})
settings = get_settings_with_defaults(org_settings, current_values)
settings = get_settings_with_defaults(org_settings, self.current_org)

return {
"settings": settings
Expand All @@ -39,13 +41,27 @@ def post(self):
if self.current_org.settings.get('settings') is None:
self.current_org.settings['settings'] = {}

previous_values = {}
for k, v in new_values.iteritems():
self.current_org.set_setting(k, v)
if k == 'auth_google_apps_domains':
previous_values[k] = self.current_org.google_apps_domains
self.current_org.settings[Organization.SETTING_GOOGLE_APPS_DOMAINS] = v
else:
previous_values[k] = self.current_org.get_setting(k, raise_on_missing=False)
self.current_org.set_setting(k, v)

db.session.add(self.current_org)
db.session.commit()

settings = get_settings_with_defaults(org_settings, self.current_org.settings['settings'])
self.record_event({
'action': 'edit',
'object_id': self.current_org.id,
'object_type': 'settings',
'new_values': new_values,
'previous_values': previous_values
})

settings = get_settings_with_defaults(org_settings, self.current_org)

return {
"settings": settings
Expand Down
7 changes: 5 additions & 2 deletions redash/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,14 +341,17 @@ def set_setting(self, key, value):
self.settings['settings'][key] = value
flag_modified(self, 'settings')

def get_setting(self, key):
def get_setting(self, key, raise_on_missing=True):
if key in self.settings.get('settings', {}):
return self.settings['settings'][key]

if key in org_settings:
return org_settings[key]

raise KeyError(key)
if raise_on_missing:
raise KeyError(key)

return None

@property
def admin_group(self):
Expand Down
6 changes: 3 additions & 3 deletions redash/templates/invite.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@
{% endif %}

{% if show_saml_login %}
<a href="/saml/login" class="login-button btn btn-default btn-block">SAML Login</a>
<a href="{{ url_for('saml_auth.sp_initiated', org_slug=org_slug) }}" class="login-button btn btn-default btn-block">SAML Login</a>
{% endif %}

{% if show_remote_user_login %}
<a href="/remote_user/login" class="login-button btn btn-default btn-block">Remote User Login</a>
<a href="{{ url_for('remote_user_auth.login') }}" class="login-button btn btn-default btn-block">Remote User Login</a>
{% endif %}

{% if show_ldap_login %}
<a href="/ldap_auth/login" class="login-button btn btn-default btn-block">LDAP/SSO Login</a>
<a href="{{ url_for('ldap_auth.login') }}" class="login-button btn btn-default btn-block">LDAP/SSO Login</a>
{% endif %}

{% if show_google_openid or show_saml_login or show_remote_user_login or show_ldap_login %}
Expand Down
Loading

0 comments on commit bb28b2f

Please sign in to comment.