Skip to content

Commit

Permalink
Multi-user Eclipse Che (#6441)
Browse files Browse the repository at this point in the history
Multi-user Eclipse Che (#6441)
#### How to run it.
```docker run -it -e CHE_MULTIUSER=true -e CHE_HOST=<your ip> -e CHE_KEYCLOAK_AUTH-SERVER-URL=http://<your ip>:5050/auth -v /var/run/docker.sock:/var/run/docker.sock -v ~/.che-multiuser:/data eclipse/che:nightly start --skip:pull --skip:nightly```
#### How to manage it
 - Keycloak configured with two realms. ```Master``` and ```che```. Also we have one user admin/admin in both realm. Admin user in master realm is  - super admin. 
-  Eclipse Che configured for che realm
- We enabled user registration in ```Che``` realm
#### Known limitation
 - swagger would not work. We need to upgrade a version. to support openid authentification #6015
- It's working on local docker. We are going to provide scalable version based on OpenShift on next versions.
- Invitation of non-existent users to Eclipse Che organization #6335
#### How to run it when it is in a branch


To run an multiuser Che version, the following steps are required after building the branch:
 - Rebuild init, cli and che images (in the given sequence). To do that, proceed to folder _dockerfiles/<image_name>_ and run _build.sh_
 - Run Che in a  usual way using cli, with additional parameters:  `-e CHE_MULTIUSER=true` and `--skip:pull --skip:nightly`  
   Full command example:
   `docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock -v /home/user/.che:/data -e CHE_MULTIUSER=true eclipse/che-cli:nightly start --skip:pull --skip:nightly`
 - MacOS users may need to edit _che.env_ file in the data folder, changing `CHE_HOST` and `CHE_KEYCLOAK_AUTH__SERVER__URL` values to their specific IP.
 
When start is succeeded, the following docker containers should be created:  
 - che, exposing 8080 port;
 - che_keycloak, exposing 5050 port;  
 - che_postgres, exposing 5432 port;
  • Loading branch information
skabashnyuk committed Oct 6, 2017
1 parent e15d5d1 commit 271ed79
Show file tree
Hide file tree
Showing 167 changed files with 15,413 additions and 149 deletions.
1 change: 1 addition & 0 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"angular-charts": "0.2.6",
"angular-cookies": "1.4.8",
"angular-dropdowns": "1.0.0",
"angular-gravatar": "0.2.4",
"angular-filter": "0.5.4",
"angular-material": "1.0.1",
"angular-moment": "0.9.0",
Expand Down
7 changes: 4 additions & 3 deletions gulp/proxy.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@ var serverOptions = {

var options = minimist(process.argv.slice(2), serverOptions);

var patterns = ['/api', '/ext', '/ws', '/datasource', '/java-ca', '/im', '/che', '/admin'];

var proxies = []
var patterns = ['/api', '/ext', '/ws', '/datasource', '/java-ca', '/im', '/che', '/admin', '/wsmaster'];

var proxies = [];

patterns.forEach(function(pattern) {
var proxyOptions = url.parse(options.server + pattern);
Expand All @@ -37,6 +36,8 @@ patterns.forEach(function(pattern) {
proxyOptions.route = '/admin';
} else if (pattern === '/ext') {
proxyOptions.route = '/ext';
} else if (pattern === '/wsmaster') {
proxyOptions.route = '/wsmaster';
} else {
proxyOptions.route = '/api';
}
Expand Down
5 changes: 3 additions & 2 deletions src/app/admin/admin-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@
'use strict';

import {AdminsPluginsConfig} from './plugins/plugins-config';
import {AdminsUserManagementConfig} from './user-management/user-management-config';

/**
* @author Florent Benoit
*/
export class AdminsConfig {

constructor(register) {
constructor(register: che.IRegisterService) {
new AdminsPluginsConfig(register);

new AdminsUserManagementConfig(register);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2015-2017 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
'use strict';

interface IAccountProfileScope extends ng.IScope {
profileAttributes: {
phone?: string;
country?: string;
employer?: string;
jobtitle?: string;
lastName?: string;
firstName?: string;
};
profileInformationForm: ng.IFormController;
countries?: Array<{ 'name': string, 'code': string }>;
jobs?: Array<{ 'name': string }>;
}

/**
* @ngdoc directive
* @name account.profile.directive:accountProfile
* @restrict E
* @element
*
* @description
* <account-profile profile-attributes="ctrl.profileAttributes"></account-profile>` for displaying account profile.
*
* @usage
* <account-profile profile-attributes="ctrl.profileAttributes"></account-profile>
*
* @author Florent Benoit
*/
export class AccountProfile implements ng.IDirective {
restrict = 'E';
templateUrl = 'app/account/account-profile/account-profile.html';
replace = true;
scope = {
profileAttributes: '=profileAttributes',
profileInformationForm: '=?profileInformationForm'
};

jsonCountries: string;
jsonJobs: string;

/**
* Default constructor that is using resource
* @ngInject for Dependency injection
*/
constructor(jsonCountries: string, jsonJobs: string) {
this.jsonCountries = jsonCountries;
this.jsonJobs = jsonJobs;
}

link($scope: IAccountProfileScope) {
$scope.countries = angular.fromJson(this.jsonCountries);
$scope.jobs = angular.fromJson(this.jsonJobs);
}
}
67 changes: 67 additions & 0 deletions src/app/admin/user-management/account-profile/account-profile.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<div class="account-profile">
<ng-form name="profileInformationForm">
<che-label-container che-label-name="First Name">
<che-input che-form="profileInformationForm"
che-name="firstName"
che-place-holder="First Name"
ng-model="profileAttributes.firstName"
required
ng-maxlength="128">
<div ng-message="required">A name is required.</div>
<div ng-message="maxlength">The name has to be less than 128 characters long.</div>
</che-input>
</che-label-container>

<che-label-container che-label-name="Last Name">
<che-input che-form="profileInformationForm"
che-name="lastName"
che-place-holder="Last Name"
ng-model="profileAttributes.lastName"
required
ng-maxlength="128">
<div ng-message="required">A last name is required.</div>
<div ng-message="maxlength">The name has to be less than 128 characters long.</div>
</che-input>
</che-label-container>

<che-label-container che-label-name="Phone">
<che-input che-form="profileInformationForm"
che-name="phone"
che-place-holder="phone"
che-pattern="(^[+]{0,1}[0-9-]{0,}$)"
ng-model="profileAttributes.phone"
ng-maxlength="15"
ng-minlength="7">
<div ng-message="pattern">Should be numbers and may start with a '+'.</div>
<div ng-message="minlength">The phone number has to be more than 7 characters long.</div>
<div ng-message="maxlength">The phone number has to be less than 15 characters long.</div>
</che-input>
</che-label-container>

<che-label-container che-label-name="Country">
<che-select che-form="profileInformationForm"
che-name="country"
che-option-values="countries"
che-place-holder="Select Your Country"
che-value="profileAttributes.country">
</che-select>
</che-label-container>

<che-label-container che-label-name="Company">
<che-input che-form="profileInformationForm"
che-name="department"
che-place-holder="Company"
ng-model="profileAttributes.employer"
ng-maxlength="128">
<div ng-message="maxlength">The name has to be less than 128 characters long.</div>
</che-input>
</che-label-container>

<che-label-container che-label-name="Role">
<che-select che-option-values="jobs"
che-place-holder="Select Your Role"
che-value="profileAttributes.jobtitle">
</che-select>
</che-label-container>
</ng-form>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.account-profile
padding 0 14px

.che-input-desktop
margin-top -1px

.che-select
margin-top -2px
123 changes: 123 additions & 0 deletions src/app/admin/user-management/add-user/add-user.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*
* Copyright (c) 2015-2017 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
'use strict';
import {AdminsUserManagementCtrl} from '../user-management.controller';

/**
* This class is handling the controller for the add user
* @author Oleksii Orel
*/
export class AdminsAddUserController {
private $mdDialog: ng.material.IDialogService;
private lodash: any;
private cheNotification: any;
private cheUser: any;
private callbackController: AdminsUserManagementCtrl;
private newUserName: string;
private newUserEmail: string;
private newUserPassword: string;
private organizations: Array<string>;
private organization: string;
private cheOrganization: che.api.ICheOrganization;
private chePermissions: che.api.IChePermissions;
private organizationRoles: che.resource.ICheOrganizationRoles;

/**
* Default constructor.
* @ngInject for Dependency injection
*/
constructor($mdDialog: ng.material.IDialogService,
cheUser: any,
cheNotification: any,
lodash: any,
cheOrganization: che.api.ICheOrganization,
chePermissions: che.api.IChePermissions,
resourcesService: che.service.IResourcesService) {
this.$mdDialog = $mdDialog;
this.lodash = lodash;
this.cheUser = cheUser;
this.cheNotification = cheNotification;
this.cheOrganization = cheOrganization;
this.chePermissions = chePermissions;
this.organizationRoles = resourcesService.getOrganizationRoles();

this.organizations = [];

this.cheOrganization.fetchOrganizations().then(() => {
let organizations = this.cheOrganization.getOrganizations();
let rootOrganizations = organizations.filter((organization: any) => {
return !organization.parent;
});
this.organizations = lodash.pluck(rootOrganizations, 'name');
if (this.organizations.length > 0) {
this.organization = this.organizations[0];
}
});
}

/**
* Callback of the cancel button of the dialog.
*/
abort(): void {
this.$mdDialog.hide();
}

/**
* Callback of the add button of the dialog(create new user).
*/
createUser(): void {
let promise = this.cheUser.createUser(this.newUserName, this.newUserEmail, this.newUserPassword);

promise.then((data: any) => {
if (this.organization) {
this.addUserToOrganization(data.id);
} else {
this.finish();
}
}, (error: any) => {
this.cheNotification.showError(error.data.message ? error.data.message : 'Failed to create user.');
});
}

/**
* Finish user creation.
*/
private finish(): void {
this.$mdDialog.hide();
this.callbackController.updateUsers();
this.cheNotification.showInfo('User successfully created.');
}

/**
* Adds user to chosen organization.
*
* @param userId
*/
private addUserToOrganization(userId: string): void {
let organizations = this.cheOrganization.getOrganizations();
let organization = this.lodash.find(organizations, (organization: any) => {
return organization.name === this.organization;
});

let actions = this.organizationRoles.MEMBER.actions;
let permissions = {
instanceId: organization.id,
userId: userId,
domainId: 'organization',
actions: actions
};
this.chePermissions.storePermissions(permissions).then(() => {
this.finish();
}, (error: any) => {
this.cheNotification.showError(error.data.message ? error.data.message : 'Failed to add user to organization' + this.organization + '.');
});
}
}
Loading

0 comments on commit 271ed79

Please sign in to comment.