mirror of
https://github.com/valitydev/redash.git
synced 2024-11-07 17:38:54 +00:00
Load currentUser/clientConfig from server
This commit is contained in:
parent
8676eb000d
commit
4ef4f98a66
8
frontend/app/components/footer/footer.html
Normal file
8
frontend/app/components/footer/footer.html
Normal file
@ -0,0 +1,8 @@
|
||||
<div id="footer">
|
||||
<a href="http://redash.io">Redash</a> <span ng-bind="$ctrl.version"></span> <small ng-if="$ctrl.newVersionAvailable" ng-cloak class="ng-cloak"><a href="https://version.redash.io/">(New Redash version available)</a></small>
|
||||
|
||||
<ul class="f-menu">
|
||||
<li><a href="https://redash.io/help/">Documentation</a></li>
|
||||
<li><a href="http://github.com/getredash/redash">Contribute</a></li>
|
||||
</ul>
|
||||
</div>
|
@ -1,10 +1,13 @@
|
||||
function controller() {
|
||||
import template from './footer.html';
|
||||
|
||||
function controller(clientConfig, currentUser) {
|
||||
this.version = clientConfig.version;
|
||||
this.newVersionAvailable = clientConfig.newVersionAvailable && currentUser.isAdmin;
|
||||
}
|
||||
|
||||
export default function (ngModule) {
|
||||
ngModule.component('footer', {
|
||||
template: '<div>Footer</div>',
|
||||
template,
|
||||
controller,
|
||||
});
|
||||
}
|
||||
|
@ -16,3 +16,4 @@ export { default as dynamicForm } from './dynamic-form';
|
||||
export { default as rdTimer } from './rd-timer';
|
||||
export { default as rdTimeAgo } from './rd-time-ago';
|
||||
export { default as overlay } from './overlay';
|
||||
export { default as routeStatus } from './route-status';
|
||||
|
19
frontend/app/components/route-status.js
Normal file
19
frontend/app/components/route-status.js
Normal file
@ -0,0 +1,19 @@
|
||||
export default function (ngModule) {
|
||||
ngModule.component('routeStatus', {
|
||||
template: '<overlay ng-if="$ctrl.permissionDenied">You do not have permission to load this page.',
|
||||
|
||||
controller($rootScope) {
|
||||
this.permissionDenied = false;
|
||||
|
||||
$rootScope.$on('$routeChangeSuccess', () => {
|
||||
this.permissionDenied = false;
|
||||
});
|
||||
|
||||
$rootScope.$on('$routeChangeError', (event, current, previous, rejection) => {
|
||||
if (rejection.status === 403) {
|
||||
this.permissionDenied = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
@ -12,7 +12,10 @@
|
||||
<body ng-app="app">
|
||||
<section>
|
||||
<app-header></app-header>
|
||||
<route-status></route-status>
|
||||
<div ng-view></div>
|
||||
<footer>
|
||||
</footer>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -46,47 +46,6 @@ const requirements = [
|
||||
|
||||
const ngModule = angular.module('app', requirements);
|
||||
|
||||
// stub for currentUser until we have something real.
|
||||
const user = {
|
||||
name: 'Arik Fraimovich',
|
||||
gravatar_url: 'https://www.gravatar.com/avatar/ca410c2e27337c8d7075bb1b098ac70f?s=40',
|
||||
id: 1,
|
||||
groups: [
|
||||
3,
|
||||
1,
|
||||
],
|
||||
email: 'arik@redash.io',
|
||||
permissions: [
|
||||
'admin',
|
||||
'super_admin',
|
||||
'create_dashboard',
|
||||
'create_query',
|
||||
'edit_dashboard',
|
||||
'edit_query',
|
||||
'view_query',
|
||||
'view_source',
|
||||
'list_users',
|
||||
'execute_query',
|
||||
'schedule_query',
|
||||
'list_dashboards',
|
||||
'list_alerts',
|
||||
'create_alerts',
|
||||
'list_dashboards',
|
||||
'list_alerts',
|
||||
'list_data_sources',
|
||||
],
|
||||
isAdmin: true,
|
||||
};
|
||||
|
||||
user.hasPermission = () => true;
|
||||
user.canEdit = () => true;
|
||||
ngModule.constant('currentUser', user);
|
||||
ngModule.constant('clientConfig', { // TODO: make me a service.
|
||||
showPermissionsControl: true,
|
||||
allowCustomJSVisualizations: true,
|
||||
// mailSettingsMissing: true,
|
||||
});
|
||||
|
||||
function registerComponents() {
|
||||
each(components, (register) => {
|
||||
register(ngModule);
|
||||
@ -103,9 +62,14 @@ function registerPages() {
|
||||
each(pages, (registerPage) => {
|
||||
const routes = registerPage(ngModule);
|
||||
|
||||
function session(Auth) {
|
||||
return Auth.loadSession();
|
||||
}
|
||||
|
||||
ngModule.config(($routeProvider) => {
|
||||
each(routes, (route, path) => {
|
||||
logger('Route: ', path);
|
||||
route.resolve = Object.assign(route.resolve || {}, { session });
|
||||
$routeProvider.when(path, route);
|
||||
});
|
||||
});
|
||||
@ -146,4 +110,10 @@ ngModule.config(($routeProvider,
|
||||
});
|
||||
});
|
||||
|
||||
ngModule.run(($location, Auth) => {
|
||||
if (!Auth.isAuthenticated()) {
|
||||
Auth.login();
|
||||
}
|
||||
});
|
||||
|
||||
export default ngModule;
|
||||
|
@ -2,7 +2,7 @@ import moment from 'moment';
|
||||
import template from './outdated-queries.html';
|
||||
|
||||
function OutdatedQueriesCtrl($scope, NgTableParams, currentUser, Events, $http, $timeout) {
|
||||
Events.record(currentUser, 'view', 'page', 'admin/outdated_queries');
|
||||
Events.record('view', 'page', 'admin/outdated_queries');
|
||||
// $scope.$parent.pageTitle = 'Outdated Queries';
|
||||
$scope.autoUpdate = true;
|
||||
|
||||
|
@ -2,7 +2,7 @@ import template from './status.html';
|
||||
|
||||
// TODO: switch to $ctrl instead of $scope.
|
||||
function AdminStatusCtrl($scope, $http, $timeout, currentUser, Events) {
|
||||
Events.record(currentUser, 'view', 'page', 'admin/status');
|
||||
Events.record('view', 'page', 'admin/status');
|
||||
// $scope.$parent.pageTitle = 'System Status';
|
||||
|
||||
const refresh = () => {
|
||||
|
@ -20,7 +20,7 @@ function cancelQueryButton() {
|
||||
queryId = null;
|
||||
}
|
||||
|
||||
Events.record(currentUser, 'cancel_execute', 'query', queryId, { admin: true });
|
||||
Events.record('cancel_execute', 'query', queryId, { admin: true });
|
||||
$scope.inProgress = true;
|
||||
};
|
||||
},
|
||||
|
@ -3,7 +3,7 @@ import template from './tasks.html';
|
||||
import registerCancelQueryButton from './cancel-query-button';
|
||||
|
||||
function TasksCtrl($scope, $location, $http, $timeout, NgTableParams, currentUser, Events) {
|
||||
Events.record(currentUser, 'view', 'page', 'admin/tasks');
|
||||
Events.record('view', 'page', 'admin/tasks');
|
||||
// $scope.$parent.pageTitle = 'Running Queries';
|
||||
$scope.autoUpdate = true;
|
||||
|
||||
|
@ -8,9 +8,9 @@ function AlertCtrl($routeParams, $location, $sce, toastr, currentUser, Query, Ev
|
||||
this.alertId = $routeParams.alertId;
|
||||
|
||||
if (this.alertId === 'new') {
|
||||
Events.record(currentUser, 'view', 'page', 'alerts/new');
|
||||
Events.record('view', 'page', 'alerts/new');
|
||||
} else {
|
||||
Events.record(currentUser, 'view', 'alert', this.alertId);
|
||||
Events.record('view', 'alert', this.alertId);
|
||||
}
|
||||
|
||||
this.trustAsHtml = html => $sce.trustAsHtml(html);
|
||||
|
@ -2,7 +2,7 @@ import template from './alerts-list.html';
|
||||
|
||||
class AlertsListCtrl {
|
||||
constructor(NgTableParams, currentUser, Events, Alert) {
|
||||
Events.record(currentUser, 'view', 'page', 'alerts');
|
||||
Events.record('view', 'page', 'alerts');
|
||||
// $scope.$parent.pageTitle = "Alerts";
|
||||
|
||||
this.tableParams = new NgTableParams({ count: 50 }, {});
|
||||
|
@ -82,7 +82,7 @@ function DashboardCtrl($routeParams, $location, $timeout, $q, $uibModal,
|
||||
|
||||
this.loadDashboard = _.throttle((force) => {
|
||||
this.dashboard = Dashboard.get({ slug: $routeParams.dashboardSlug }, (dashboard) => {
|
||||
Events.record(currentUser, 'view', 'dashboard', dashboard.id);
|
||||
Events.record('view', 'dashboard', dashboard.id);
|
||||
renderDashboard(dashboard, force);
|
||||
}, () => {
|
||||
// error...
|
||||
@ -104,7 +104,7 @@ function DashboardCtrl($routeParams, $location, $timeout, $q, $uibModal,
|
||||
|
||||
this.archiveDashboard = () => {
|
||||
const archive = () => {
|
||||
Events.record(currentUser, 'archive', 'dashboard', this.dashboard.id);
|
||||
Events.record('archive', 'dashboard', this.dashboard.id);
|
||||
this.dashboard.$delete(() => {
|
||||
// TODO:
|
||||
// this.$parent.reloadDashboards();
|
||||
|
@ -79,7 +79,7 @@ const EditDashboardDialog = {
|
||||
'Please copy/backup your changes and reload this page.', { autoDismiss: false });
|
||||
}
|
||||
});
|
||||
Events.record(currentUser, 'edit', 'dashboard', this.dashboard.id);
|
||||
Events.record('edit', 'dashboard', this.dashboard.id);
|
||||
} else {
|
||||
$http.post('api/dashboards', {
|
||||
name: this.dashboard.name,
|
||||
@ -87,7 +87,7 @@ const EditDashboardDialog = {
|
||||
this.close();
|
||||
$location.path(`/dashboard/${response.slug}`).replace();
|
||||
});
|
||||
Events.record(currentUser, 'create', 'dashboard');
|
||||
Events.record('create', 'dashboard');
|
||||
}
|
||||
};
|
||||
},
|
||||
|
@ -41,7 +41,7 @@ function DashboardWidgetCtrl($location, $uibModal, $window, Events, currentUser)
|
||||
return;
|
||||
}
|
||||
|
||||
Events.record(currentUser, 'delete', 'widget', this.widget.id);
|
||||
Events.record('delete', 'widget', this.widget.id);
|
||||
|
||||
this.widget.$delete((response) => {
|
||||
this.dashboard.widgets =
|
||||
@ -54,7 +54,7 @@ function DashboardWidgetCtrl($location, $uibModal, $window, Events, currentUser)
|
||||
});
|
||||
};
|
||||
|
||||
Events.record(currentUser, 'view', 'widget', this.widget.id);
|
||||
Events.record('view', 'widget', this.widget.id);
|
||||
|
||||
this.reload = (force) => {
|
||||
let maxAge = $location.search().maxAge;
|
||||
@ -65,8 +65,8 @@ function DashboardWidgetCtrl($location, $uibModal, $window, Events, currentUser)
|
||||
};
|
||||
|
||||
if (this.widget.visualization) {
|
||||
Events.record(currentUser, 'view', 'query', this.widget.visualization.query.id);
|
||||
Events.record(currentUser, 'view', 'visualization', this.widget.visualization.id);
|
||||
Events.record('view', 'query', this.widget.visualization.query.id);
|
||||
Events.record('view', 'visualization', this.widget.visualization.id);
|
||||
|
||||
this.query = this.widget.getQuery();
|
||||
this.reload(false);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import template from './list.html';
|
||||
|
||||
function DataSourcesCtrl($scope, $location, currentUser, Events, DataSource) {
|
||||
Events.record(currentUser, 'view', 'page', 'admin/data_sources');
|
||||
Events.record('view', 'page', 'admin/data_sources');
|
||||
$scope.$parent.pageTitle = 'Data Sources';
|
||||
|
||||
$scope.dataSources = DataSource.query();
|
||||
|
@ -5,7 +5,7 @@ const logger = debug('redash:http');
|
||||
|
||||
function DataSourceCtrl($scope, $routeParams, $http, $location, toastr,
|
||||
currentUser, Events, DataSource) {
|
||||
Events.record(currentUser, 'view', 'page', 'admin/data_source');
|
||||
Events.record('view', 'page', 'admin/data_source');
|
||||
// $scope.$parent.pageTitle = 'Data Sources';
|
||||
|
||||
$scope.dataSourceId = $routeParams.dataSourceId;
|
||||
@ -23,7 +23,7 @@ function DataSourceCtrl($scope, $routeParams, $http, $location, toastr,
|
||||
});
|
||||
|
||||
function deleteDataSource() {
|
||||
Events.record(currentUser, 'delete', 'datasource', $scope.dataSource.id);
|
||||
Events.record('delete', 'datasource', $scope.dataSource.id);
|
||||
|
||||
$scope.dataSource.$delete(() => {
|
||||
toastr.success('Data source deleted successfully.');
|
||||
@ -35,7 +35,7 @@ function DataSourceCtrl($scope, $routeParams, $http, $location, toastr,
|
||||
}
|
||||
|
||||
function testConnection(callback) {
|
||||
Events.record(currentUser, 'test', 'datasource', $scope.dataSource.id);
|
||||
Events.record('test', 'datasource', $scope.dataSource.id);
|
||||
|
||||
DataSource.test({ id: $scope.dataSource.id }, (httpResponse) => {
|
||||
if (httpResponse.ok) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import template from './list.html';
|
||||
|
||||
function DestinationsCtrl($scope, $location, toastr, currentUser, Events, Destination) {
|
||||
Events.record(currentUser, 'view', 'page', 'admin/destinations');
|
||||
Events.record('view', 'page', 'admin/destinations');
|
||||
// $scope.$parent.pageTitle = 'Destinations';
|
||||
|
||||
$scope.destinations = Destination.query();
|
||||
|
@ -6,7 +6,7 @@ const logger = debug('redash:http');
|
||||
|
||||
function DestinationCtrl($scope, $routeParams, $http, $location, toastr,
|
||||
currentUser, Events, Destination) {
|
||||
Events.record(currentUser, 'view', 'page', 'admin/destination');
|
||||
Events.record('view', 'page', 'admin/destination');
|
||||
$scope.$parent.pageTitle = 'Destinations';
|
||||
|
||||
$scope.destinationId = $routeParams.destinationId;
|
||||
@ -24,7 +24,7 @@ function DestinationCtrl($scope, $routeParams, $http, $location, toastr,
|
||||
});
|
||||
|
||||
$scope.delete = () => {
|
||||
Events.record(currentUser, 'delete', 'destination', $scope.destination.id);
|
||||
Events.record('delete', 'destination', $scope.destination.id);
|
||||
|
||||
$scope.destination.$delete(() => {
|
||||
toastr.success('Destination deleted successfully.');
|
||||
|
@ -3,7 +3,7 @@ import template from './data-sources.html';
|
||||
|
||||
function GroupDataSourcesCtrl($scope, $routeParams, $http, $location, toastr,
|
||||
currentUser, Events, Group, DataSource) {
|
||||
Events.record(currentUser, 'view', 'group_data_sources', $scope.groupId);
|
||||
Events.record('view', 'group_data_sources', $scope.groupId);
|
||||
$scope.group = Group.get({ id: $routeParams.groupId });
|
||||
$scope.dataSources = Group.dataSources({ id: $routeParams.groupId });
|
||||
$scope.newDataSource = {};
|
||||
|
@ -2,7 +2,7 @@ import { Paginator } from '../../utils';
|
||||
import template from './list.html';
|
||||
|
||||
function GroupsCtrl($scope, $location, $uibModal, toastr, currentUser, Events, Group) {
|
||||
Events.record(currentUser, 'view', 'page', 'groups');
|
||||
Events.record('view', 'page', 'groups');
|
||||
// $scope.$parent.pageTitle = 'Groups';
|
||||
|
||||
$scope.currentUser = currentUser;
|
||||
|
@ -3,7 +3,7 @@ import template from './show.html';
|
||||
|
||||
function GroupCtrl($scope, $routeParams, $http, $location, toastr,
|
||||
currentUser, Events, Group, User) {
|
||||
Events.record(currentUser, 'view', 'group', $scope.groupId);
|
||||
Events.record('view', 'group', $scope.groupId);
|
||||
|
||||
$scope.currentUser = currentUser;
|
||||
$scope.group = Group.get({ id: $routeParams.groupId });
|
||||
|
@ -1,7 +1,7 @@
|
||||
import template from './home.html';
|
||||
|
||||
function HomeCtrl($scope, $uibModal, currentUser, Events, Dashboard, Query) {
|
||||
Events.record(currentUser, 'view', 'page', 'personal_homepage');
|
||||
Events.record('view', 'page', 'personal_homepage');
|
||||
// $scope.$parent.pageTitle = 'Home';
|
||||
|
||||
// todo: maybe this should come from some serivce as we have this logic elsewhere.
|
||||
|
@ -27,7 +27,7 @@ function QuerySearchCtrl($location, $filter, currentUser, Events, Query) {
|
||||
}
|
||||
};
|
||||
|
||||
Events.record(currentUser, 'search', 'query', '', { term: this.term });
|
||||
Events.record('search', 'query', '', { term: this.term });
|
||||
}
|
||||
|
||||
export default function (ngModule) {
|
||||
|
@ -9,7 +9,7 @@ function QuerySourceCtrl(Events, toastr, $controller, $scope, $location, $http,
|
||||
// Obviously it shouldn't be repeated, but we got bigger fish to fry.
|
||||
const DEFAULT_TAB = 'table';
|
||||
|
||||
Events.record(currentUser, 'view_source', 'query', $scope.query.id);
|
||||
Events.record('view_source', 'query', $scope.query.id);
|
||||
|
||||
const isNewQuery = !$scope.query.id;
|
||||
let queryText = $scope.query.query;
|
||||
@ -74,7 +74,7 @@ function QuerySourceCtrl(Events, toastr, $controller, $scope, $location, $http,
|
||||
};
|
||||
|
||||
$scope.duplicateQuery = () => {
|
||||
Events.record(currentUser, 'fork', 'query', $scope.query.id);
|
||||
Events.record('fork', 'query', $scope.query.id);
|
||||
$scope.query.name = `Copy of (#${$scope.query.id}) ${$scope.query.name}`;
|
||||
$scope.query.id = null;
|
||||
$scope.query.schedule = null;
|
||||
@ -95,7 +95,7 @@ function QuerySourceCtrl(Events, toastr, $controller, $scope, $location, $http,
|
||||
const confirm = { class: 'btn-danger', title: 'Delete' };
|
||||
|
||||
AlertDialog.open(title, message, confirm).then(() => {
|
||||
Events.record(currentUser, 'delete', 'visualization', vis.id);
|
||||
Events.record('delete', 'visualization', vis.id);
|
||||
|
||||
Visualization.delete(vis, () => {
|
||||
if ($scope.selectedTab === vis.id) {
|
||||
|
@ -90,7 +90,7 @@ function QueryViewCtrl($scope, Events, $route, $routeParams, $http, $location, $
|
||||
$scope.showPermissionsControl = clientConfig.showPermissionsControl;
|
||||
|
||||
|
||||
Events.record(currentUser, 'view', 'query', $scope.query.id);
|
||||
Events.record('view', 'query', $scope.query.id);
|
||||
if ($scope.query.hasResult() || $scope.query.paramsRequired()) {
|
||||
getQueryResult();
|
||||
}
|
||||
@ -156,12 +156,12 @@ function QueryViewCtrl($scope, Events, $route, $routeParams, $http, $location, $
|
||||
};
|
||||
|
||||
$scope.saveDescription = () => {
|
||||
Events.record(currentUser, 'edit_description', 'query', $scope.query.id);
|
||||
Events.record('edit_description', 'query', $scope.query.id);
|
||||
$scope.saveQuery(undefined, { description: $scope.query.description });
|
||||
};
|
||||
|
||||
$scope.saveName = () => {
|
||||
Events.record(currentUser, 'edit_name', 'query', $scope.query.id);
|
||||
Events.record('edit_name', 'query', $scope.query.id);
|
||||
$scope.saveQuery(undefined, { name: $scope.query.name });
|
||||
};
|
||||
|
||||
@ -177,7 +177,7 @@ function QueryViewCtrl($scope, Events, $route, $routeParams, $http, $location, $
|
||||
getQueryResult(0);
|
||||
$scope.lockButton(true);
|
||||
$scope.cancelling = false;
|
||||
Events.record(currentUser, 'execute', 'query', $scope.query.id);
|
||||
Events.record('execute', 'query', $scope.query.id);
|
||||
|
||||
Notifications.getPermissions();
|
||||
};
|
||||
@ -185,7 +185,7 @@ function QueryViewCtrl($scope, Events, $route, $routeParams, $http, $location, $
|
||||
$scope.cancelExecution = () => {
|
||||
$scope.cancelling = true;
|
||||
$scope.queryResult.cancelExecution();
|
||||
Events.record(currentUser, 'cancel_execute', 'query', $scope.query.id);
|
||||
Events.record('cancel_execute', 'query', $scope.query.id);
|
||||
};
|
||||
|
||||
$scope.archiveQuery = () => {
|
||||
@ -206,7 +206,7 @@ function QueryViewCtrl($scope, Events, $route, $routeParams, $http, $location, $
|
||||
};
|
||||
|
||||
$scope.updateDataSource = () => {
|
||||
Events.record(currentUser, 'update_data_source', 'query', $scope.query.id);
|
||||
Events.record('update_data_source', 'query', $scope.query.id);
|
||||
localStorage.lastSelectedDataSourceId = $scope.query.data_source_id;
|
||||
|
||||
$scope.query.latest_query_data = null;
|
||||
|
@ -4,7 +4,7 @@ import template from './edit.html';
|
||||
function SnippetCtrl($routeParams, $http, $location, toastr, currentUser, Events, QuerySnippet) {
|
||||
// $scope.$parent.pageTitle = 'Query Snippets';
|
||||
this.snippetId = $routeParams.snippetId;
|
||||
Events.record(currentUser, 'view', 'query_snippet', this.snippetId);
|
||||
Events.record('view', 'query_snippet', this.snippetId);
|
||||
|
||||
this.editorOptions = {
|
||||
mode: 'snippets',
|
||||
|
@ -2,7 +2,7 @@ import { Paginator } from '../../utils';
|
||||
import template from './list.html';
|
||||
|
||||
function SnippetsCtrl($location, currentUser, Events, QuerySnippet) {
|
||||
Events.record(currentUser, 'view', 'page', 'query_snippets');
|
||||
Events.record('view', 'page', 'query_snippets');
|
||||
// $scope.$parent.pageTitle = 'Query Snippets';
|
||||
|
||||
this.snippets = new Paginator([], { itemsPerPage: 20 });
|
||||
|
@ -2,7 +2,7 @@ import { Paginator } from '../../utils';
|
||||
import template from './list.html';
|
||||
|
||||
function UsersCtrl($location, toastr, currentUser, Events, User) {
|
||||
Events.record(currentUser, 'view', 'page', 'users');
|
||||
Events.record('view', 'page', 'users');
|
||||
// $scope.$parent.pageTitle = 'Users';
|
||||
|
||||
this.currentUser = currentUser;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import template from './new.html';
|
||||
|
||||
function NewUserCtrl($scope, $location, toastr, currentUser, Events, User) {
|
||||
Events.record(currentUser, 'view', 'page', 'users/new');
|
||||
Events.record('view', 'page', 'users/new');
|
||||
|
||||
$scope.user = new User({});
|
||||
$scope.saveUser = () => {
|
||||
|
@ -13,7 +13,7 @@ function UserCtrl($scope, $routeParams, $http, $location, toastr,
|
||||
$scope.userId = currentUser.id;
|
||||
}
|
||||
|
||||
Events.record(currentUser, 'view', 'user', $scope.userId);
|
||||
Events.record('view', 'user', $scope.userId);
|
||||
$scope.canEdit = currentUser.hasPermission('admin') || currentUser.id === parseInt($scope.userId, 10);
|
||||
$scope.showSettings = false;
|
||||
$scope.showPasswordSettings = false;
|
||||
|
56
frontend/app/services/auth.js
Normal file
56
frontend/app/services/auth.js
Normal file
@ -0,0 +1,56 @@
|
||||
function getLocalSessionData() {
|
||||
const sessionData = window.sessionStorage.getItem('session');
|
||||
if (sessionData) {
|
||||
return JSON.parse(sessionData);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function AuthService($window, $location, $q, $http) {
|
||||
const Auth = {
|
||||
isAuthenticated() {
|
||||
return getLocalSessionData() !== null;
|
||||
},
|
||||
login() {
|
||||
// const next = encodeURI($location.url());
|
||||
console.log('do the login manually!');
|
||||
// $window.location.href = `http://localhost:5000/default/login?next=${next}`;
|
||||
},
|
||||
loadSession() {
|
||||
const sessionData = getLocalSessionData();
|
||||
if (sessionData) {
|
||||
return $q.resolve(sessionData);
|
||||
}
|
||||
|
||||
return $http.get('/api/session').then((response) => {
|
||||
window.sessionStorage.setItem('session', JSON.stringify(response.data));
|
||||
return response.data;
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
return Auth;
|
||||
}
|
||||
|
||||
function CurrentUserService() {
|
||||
Object.assign(this, getLocalSessionData().user);
|
||||
|
||||
this.canEdit = (object) => {
|
||||
const userId = object.user_id || (object.user && object.user.id);
|
||||
return this.hasPermission('admin') || (userId && (userId === this.id));
|
||||
};
|
||||
|
||||
this.hasPermission = permission => this.permissions.indexOf(permission) !== -1;
|
||||
|
||||
this.isAdmin = this.hasPermission('admin');
|
||||
}
|
||||
|
||||
function ClientConfigService() {
|
||||
Object.assign(this, getLocalSessionData().client_config);
|
||||
}
|
||||
|
||||
export default function (ngModule) {
|
||||
ngModule.factory('Auth', AuthService);
|
||||
ngModule.service('currentUser', CurrentUserService);
|
||||
ngModule.service('clientConfig', ClientConfigService);
|
||||
}
|
@ -10,9 +10,8 @@ function Events($http) {
|
||||
$http.post('api/events', events);
|
||||
}, 1000);
|
||||
|
||||
this.record = function record(user, action, objectType, objectId, additionalProperties) {
|
||||
this.record = function record(action, objectType, objectId, additionalProperties) {
|
||||
const event = {
|
||||
user_id: user.id,
|
||||
action,
|
||||
object_type: objectType,
|
||||
object_id: objectId,
|
||||
|
@ -13,3 +13,4 @@ export { default as QuerySnippet } from './query-snippet';
|
||||
export { default as Notifications } from './notifications';
|
||||
export { default as KeyboardShortcuts } from './keyboard-shortcuts';
|
||||
export { default as AlertDialog } from './alert-dialog';
|
||||
export { default as Auth } from './auth';
|
||||
|
@ -70,7 +70,7 @@ function Notifications(currentUser, Events) {
|
||||
notification.onclick = function onClick() {
|
||||
window.focus();
|
||||
this.close();
|
||||
Events.record(currentUser, 'click', 'notification');
|
||||
Events.record('click', 'notification');
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -47,9 +47,9 @@ const EditVisualizationDialog = {
|
||||
|
||||
this.submit = () => {
|
||||
if (this.visualization.id) {
|
||||
Events.record(currentUser, 'update', 'visualization', this.visualization.id, { type: this.visualization.type });
|
||||
Events.record('update', 'visualization', this.visualization.id, { type: this.visualization.type });
|
||||
} else {
|
||||
Events.record(currentUser, 'create', 'visualization', null, { type: this.visualization.type });
|
||||
Events.record('create', 'visualization', null, { type: this.visualization.type });
|
||||
}
|
||||
|
||||
this.visualization.query_id = this.query.id;
|
||||
|
@ -11,7 +11,6 @@
|
||||
|
||||
<!-- build:css /styles/main.css -->
|
||||
<link rel="stylesheet" href="/bower_components/pace/themes/pace-theme-minimal.css">
|
||||
<link rel="stylesheet" href="/styles/redash.css">
|
||||
<!-- endbuild -->
|
||||
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.png">
|
||||
@ -72,20 +71,7 @@
|
||||
|
||||
<script>
|
||||
// TODO: move currentUser & features to be an Angular service
|
||||
var clientConfig = {{ client_config|safe }};
|
||||
var basePath = "{{base_href}}";
|
||||
var currentUser = {{ user|safe }};
|
||||
|
||||
currentUser.canEdit = function(object) {
|
||||
var user_id = object.user_id || (object.user && object.user.id);
|
||||
return this.hasPermission('admin') || (user_id && (user_id == currentUser.id));
|
||||
};
|
||||
|
||||
currentUser.hasPermission = function(permission) {
|
||||
return this.permissions.indexOf(permission) != -1;
|
||||
};
|
||||
|
||||
currentUser.isAdmin = currentUser.hasPermission('admin');
|
||||
</script>
|
||||
{% include '_includes/tail.html' %}
|
||||
|
||||
|
@ -1,32 +0,0 @@
|
||||
(function () {
|
||||
var dateFormatter = function (value) {
|
||||
if (!value) {
|
||||
return "-";
|
||||
}
|
||||
|
||||
return value.format(clientConfig.dateTimeFormat);
|
||||
};
|
||||
|
||||
var MainCtrl = function ($scope, $location, Dashboard) {
|
||||
$scope.$on("$routeChangeSuccess", function (event, current, previous, rejection) {
|
||||
if ($scope.showPermissionError) {
|
||||
$scope.showPermissionError = false;
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$on("$routeChangeError", function (event, current, previous, rejection) {
|
||||
if (rejection.status === 403) {
|
||||
$scope.showPermissionError = true;
|
||||
}
|
||||
});
|
||||
|
||||
$scope.location = String(document.location);
|
||||
$scope.version = clientConfig.version;
|
||||
$scope.newVersionAvailable = clientConfig.newVersionAvailable && currentUser.hasPermission("admin");
|
||||
};
|
||||
|
||||
angular.module('redash.controllers', [])
|
||||
.controller('IndexCtrl', ['$scope', 'Events', 'Dashboard', 'Query', IndexCtrl])
|
||||
.controller('MainCtrl', ['$scope', '$location', 'Dashboard', MainCtrl])
|
||||
.controller('QuerySearchCtrl', ['$scope', '$location', '$filter', 'Events', 'Query', QuerySearchCtrl])
|
||||
})();
|
@ -1,18 +1,13 @@
|
||||
import json
|
||||
from flask import current_app
|
||||
from flask_login import login_required
|
||||
|
||||
from flask_login import login_required
|
||||
from redash import models, redis_connection
|
||||
from redash.utils import json_dumps
|
||||
from redash.handlers import routes
|
||||
from redash.handlers.base import json_response
|
||||
from redash.permissions import require_super_admin
|
||||
from redash.tasks.queries import QueryTaskTracker
|
||||
|
||||
|
||||
def json_response(response):
|
||||
return current_app.response_class(json_dumps(response), mimetype='application/json')
|
||||
|
||||
|
||||
@routes.route('/api/admin/queries/outdated', methods=['GET'])
|
||||
@require_super_admin
|
||||
@login_required
|
||||
@ -45,4 +40,3 @@ def queries_tasks():
|
||||
}
|
||||
|
||||
return json_response(response)
|
||||
|
||||
|
@ -1,12 +1,16 @@
|
||||
import hashlib
|
||||
import logging
|
||||
from flask import render_template, request, redirect, url_for, flash
|
||||
from flask_login import current_user, login_user, logout_user
|
||||
|
||||
from redash import models, settings, limiter
|
||||
from redash.handlers import routes
|
||||
from redash.handlers.base import org_scoped_rule
|
||||
from flask import flash, redirect, render_template, request, url_for
|
||||
from flask_login import current_user, login_user, logout_user
|
||||
from redash import __version__, models, settings, limiter
|
||||
from redash.authentication import current_org, get_login_url
|
||||
from redash.authentication.account import validate_token, BadSignature, SignatureExpired, send_password_reset_email
|
||||
from redash.authentication.account import (BadSignature, SignatureExpired,
|
||||
send_password_reset_email,
|
||||
validate_token)
|
||||
from redash.handlers import routes
|
||||
from redash.handlers.base import json_response, org_scoped_rule
|
||||
from redash.version_check import get_latest_version
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -125,3 +129,31 @@ def login(org_slug=None):
|
||||
def logout(org_slug=None):
|
||||
logout_user()
|
||||
return redirect(get_login_url(next=None))
|
||||
|
||||
|
||||
@routes.route(org_scoped_rule('/api/session'), methods=['GET'])
|
||||
def session(org_slug=None):
|
||||
email_md5 = hashlib.md5(current_user.email.lower()).hexdigest()
|
||||
gravatar_url = "https://www.gravatar.com/avatar/%s?s=40" % email_md5
|
||||
|
||||
user = {
|
||||
'gravatar_url': gravatar_url,
|
||||
'id': current_user.id,
|
||||
'name': current_user.name,
|
||||
'email': current_user.email,
|
||||
'groups': current_user.groups,
|
||||
'permissions': current_user.permissions
|
||||
}
|
||||
|
||||
client_config = {
|
||||
'newVersionAvailable': get_latest_version(),
|
||||
'version': __version__
|
||||
}
|
||||
|
||||
client_config.update(settings.COMMON_CLIENT_CONFIG)
|
||||
|
||||
return json_response({
|
||||
'user': user,
|
||||
'org_slug': current_org.slug,
|
||||
'client_config': client_config
|
||||
})
|
||||
|
@ -1,13 +1,14 @@
|
||||
import time
|
||||
from flask import request, Blueprint
|
||||
from flask_restful import Resource, abort
|
||||
from flask_login import current_user, login_required
|
||||
from peewee import DoesNotExist
|
||||
|
||||
from flask import Blueprint, current_app, request
|
||||
from flask_login import current_user, login_required
|
||||
from flask_restful import Resource, abort
|
||||
from peewee import DoesNotExist
|
||||
from redash import settings
|
||||
from redash.tasks import record_event as record_event_task
|
||||
from redash.models import ApiUser
|
||||
from redash.authentication import current_org
|
||||
from redash.models import ApiUser
|
||||
from redash.tasks import record_event as record_event_task
|
||||
from redash.utils import json_dumps
|
||||
|
||||
routes = Blueprint('redash', __name__, template_folder=settings.fix_assets_path('templates'))
|
||||
|
||||
@ -99,3 +100,7 @@ def org_scoped_rule(rule):
|
||||
return "/<org_slug:org_slug>{}".format(rule)
|
||||
|
||||
return rule
|
||||
|
||||
|
||||
def json_response(response):
|
||||
return current_app.response_class(json_dumps(response), mimetype='application/json')
|
||||
|
@ -117,10 +117,6 @@ class QueryResource(BaseResource):
|
||||
except models.ConflictDetectedError:
|
||||
abort(409)
|
||||
|
||||
# old_query = copy.deepcopy(query.to_dict())
|
||||
# new_change = query.update_instance_tracked(changing_user=self.current_user, old_object=old_query, **query_def)
|
||||
# abort(409) # HTTP 'Conflict' status code
|
||||
|
||||
result = query.to_dict(with_visualizations=True)
|
||||
return result
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user