You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by jf...@apache.org on 2016/09/30 16:56:46 UTC
svn commit: r1762935 - in /vcl/trunk/web: .ht-inc/addomain.php
.ht-inc/image.php .ht-inc/resource.php .ht-inc/states.php .ht-inc/utils.php
css/vcl.css js/resources/addomain.js js/resources/image.js
themes/dropdownmenus/css/theme.css
Author: jfthomps
Date: Fri Sep 30 16:56:45 2016
New Revision: 1762935
URL: http://svn.apache.org/viewvc?rev=1762935&view=rev
Log:
VCL-277 - Add support for images to join Active Directory domains
VCL-867 - Active Directory Authentication for Windows VM's
incorporated patches from Junaid Ali attached to VCL-867; the VCL resource code has been largely rewritten since the patches were generated, so that part needed to be rewritten as well; shortened some of the names of fields and tables
addomain.php: initial add; definition of ADdomain class which inherits from Resource class
image.php:
-modified fieldWidth: added os, addomain, baseOU, adauthenabled
-modified fieldDisplayName: added adauthenabled, addomain, baseOU
-modified addEditDialogHTML: added fieldset and fields for AD authentication; added tooltip for baseOU
-modified AJsaveResource: added section that inserts/deletes/updates imageaddomain table as appropriate
-modified addResource: added section to insert into imageaddomain table as appropriate
-modified validateResourceData: added array keys and validation for adauthendabled, addomainid, baseou
resource.php:
-modified resource: added case statement for addomain
-modified viewResources and fieldWidth: added conditional for Edge browser for setting widths (unrelated to these JIRAs)
-added checkExistingField
states.php:
-added addomain to $actions["entry"]
-added addomain to $actions['mode'], $actions['args'], and $actions['pages']
utils.php:
-modified initGlobals: added case for addomain in section that require_once's resource.php
-modified getImages: added addomainid, addomain, and baseOU to query and returned data; added adauthenabled to returned data
-modified getResourceGroupMembers: added conditional for $type == addomain; added addomain to $names, $joins, and $orders
-added getADdomains
-modified labeledFormItem: added case for password to go along with text case; changed hard coded 'text' for input type to be $type so it matches the passed in type to be either text or password
-added validateHostname
-modified getNavMenuData: added AD Domains menu entry for users with addomainAdmin
-modified getDojoHTML: added addomain case statement to include addomain.js to switch statement in groupMapHTML, viewResources, and editConfigMap case statements
image.js:
-modified Image.prototype.colformatter: added adauthenabled for true/false part; added addomain and baseOU to (unset) part
-modified inlineEditResourceCB: added showing/hiding of imageadauthbox; added setting of adauthenable, addomainid, and baseou
-modified resetEditResource: added resets for adauthenable, addomainid, and baseou
-modified saveResource: added for validation of baseou; added adauthenabled, addomainid, and baseou to submitted data
-modified saveResourceCB: added setting for adauthenabled, addomainid, addomain, and baseOU fields in store object
-modified startImageCB: added resetting of adauthenable, addomainid, and baseou and showing/hiding of imageauthbox based on OS type
-added toggleADauth
vcl.css:
-added:
#addomaindlgcontent label
#addomaindlgcontent .labeledform
dropdownmenus/css/theme.css:
-added:
#renameDialog tbody tr:hover td
#renameDialog tbody tr td
div.dijitDialog h2
div.dijitDialog h3
#confdelcontent h3
#groupbyresourcediv table.dojoxGridRowTable tbody tr:hover td
#groupbyresourcediv div.dojoxGridRowSelected table.dojoxGridRowTable tbody tr td
#imageadauthbox label
#imageadauthbox .labeledform
Added:
vcl/trunk/web/.ht-inc/addomain.php
vcl/trunk/web/js/resources/addomain.js
Modified:
vcl/trunk/web/.ht-inc/image.php
vcl/trunk/web/.ht-inc/resource.php
vcl/trunk/web/.ht-inc/states.php
vcl/trunk/web/.ht-inc/utils.php
vcl/trunk/web/css/vcl.css
vcl/trunk/web/js/resources/image.js
vcl/trunk/web/themes/dropdownmenus/css/theme.css
Added: vcl/trunk/web/.ht-inc/addomain.php
URL: http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/addomain.php?rev=1762935&view=auto
==============================================================================
--- vcl/trunk/web/.ht-inc/addomain.php (added)
+++ vcl/trunk/web/.ht-inc/addomain.php Fri Sep 30 16:56:45 2016
@@ -0,0 +1,653 @@
+<?php
+/*
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \class ADdomain
+///
+/// \brief extends Resource class to add things specific to resources of the
+/// addomain type
+///
+////////////////////////////////////////////////////////////////////////////////
+class ADdomain extends Resource {
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn __construct()
+ ///
+ /// \brief calls parent constructor; initializes things for Schedule class
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function __construct() {
+ parent::__construct();
+ $this->restype = 'addomain';
+ $this->restypename = 'AD Domain';
+ $this->namefield = 'name';
+ $this->basecdata['obj'] = $this;
+ $this->deletable = 1;
+ $this->deletetoggled = 0;
+ $this->defaultGetDataArgs = array('rscid' => 0);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn getData($args)
+ ///
+ /// \param $args - array of arguments that determine what data gets returned;
+ /// must include:\n
+ /// \b rscid - only return data for resource with this id; pass 0 for all
+ /// (from addomain table)
+ ///
+ /// \return array of data as returned from getADdomains
+ ///
+ /// \brief wrapper for calling getADdomains
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function getData($args) {
+ return getADdomains($args['rscid']);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn fieldWidth($field)
+ ///
+ /// \param $field - name of a resource field
+ ///
+ /// \return string for setting width of field (includes width= part)
+ ///
+ /// \brief generates the required width for the field; can return an empty
+ /// string if field should default to auto width
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function fieldWidth($field) {
+ switch($field) {
+ case 'name':
+ $w = 17;
+ break;
+ case 'owner':
+ $w = 11;
+ break;
+ case 'domaindnsname':
+ $w = 12;
+ break;
+ case 'domainnetbiosname':
+ $w = 12;
+ break;
+ case 'username':
+ $w = 9;
+ break;
+ case 'dnsservers':
+ $w = 12;
+ break;
+ case 'domaincontrollers':
+ $w = 17;
+ break;
+ case 'logindescription':
+ $w = 12;
+ break;
+ default:
+ return '';
+ }
+ if(preg_match('/MSIE/i', $_SERVER['HTTP_USER_AGENT']) ||
+ preg_match('/Trident/i', $_SERVER['HTTP_USER_AGENT']) ||
+ preg_match('/Edge/i', $_SERVER['HTTP_USER_AGENT']))
+ $w = round($w * 11.5) . 'px';
+ else
+ $w = "{$w}em";
+ return "width=\"$w\"";
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn fieldDisplayName($field)
+ ///
+ /// \param $field - name of a resource field
+ ///
+ /// \return display value for $field
+ ///
+ /// \brief generates the display value for $field
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function fieldDisplayName($field) {
+ switch($field) {
+ case 'domaindnsname':
+ return 'Domain DNS Name';
+ case 'domainnetbiosname':
+ return 'Domain NetBIOS Name';
+ case 'dnsservers':
+ return 'DNS Server(s)';
+ case 'domaincontrollers':
+ return 'Domain Controller(s)';
+ case 'logindescription':
+ return 'Login Description';
+ }
+ return ucfirst($field);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn AJsaveResource()
+ ///
+ /// \brief saves changes to a resource; must be implemented by inheriting
+ /// class
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function AJsaveResource() {
+ global $user;
+ $add = getContinuationVar('add', 0);
+ $data = $this->validateResourceData();
+ if($data['error']) {
+ $ret = array('status' => 'error', 'msg' => $data['errormsg']);
+ sendJSON($ret);
+ return;
+ }
+
+ if($add) {
+ $esc_name = mysql_real_escape_string($data['name']);
+ $query = "SELECT id FROM addomain WHERE name = '$esc_name'";
+ $qh = doQuery($query);
+ if($row = mysql_fetch_assoc($qh)) {
+ sendJSON(array('status' => 'adderror',
+ 'errormsg' => wordwrap(i('An AD Domain with this name already exists.'), 75, '<br>')));
+ return;
+ }
+ if(! $data['rscid'] = $this->addResource($data)) {
+ sendJSON(array('status' => 'adderror',
+ 'errormsg' => wordwrap(i('Error encountered while trying to create new AD domain. Please contact an admin for assistance.'), 75, '<br>')));
+ return;
+ }
+ }
+ else {
+ $olddata = getContinuationVar('olddata');
+ $updates = array();
+ # name
+ if($data['name'] != $olddata['name'])
+ $updates[] = "name = '{$data['name']}'";
+ # ownerid
+ $ownerid = getUserlistID($data['owner']);
+ if($ownerid != $olddata['ownerid'])
+ $updates[] = "ownerid = $ownerid";
+ # domaindnsname
+ if($data['domaindnsname'] != $olddata['domaindnsname'])
+ $updates[] = "domainDNSName = '{$data['domaindnsname']}'";
+ # domainnetbiosname
+ if($data['domainnetbiosname'] != $olddata['domainnetbiosname'])
+ $updates[] = "domainNetBIOSName = '{$data['domainnetbiosname']}'";
+ # username
+ if($data['username'] != $olddata['username'])
+ $updates[] = "username = '{$data['username']}'";
+ # password
+ if(strlen($data['password'])) {
+ $esc_pass = mysql_real_escape_string($data['password']);
+ $updates[] = "password = '$esc_pass'";
+ }
+ # dnsservers
+ if($data['dnsservers'] != $olddata['dnsservers'])
+ $updates[] = "dnsServers = '{$data['dnsservers']}'";
+ # domaincontrollers
+ if($data['domaincontrollers'] != $olddata['domaincontrollers'])
+ $updates[] = "domainControllers = '{$data['domaincontrollers']}'";
+ # logindescription
+ if($data['logindescription'] != $olddata['logindescription']) {
+ $esc_desc = mysql_real_escape_string($data['logindescription']);
+ $updates[] = "logindescription = '$esc_desc'";
+ }
+ if(count($updates)) {
+ $query = "UPDATE addomain SET "
+ . implode(', ', $updates)
+ . " WHERE id = {$data['rscid']}";
+ doQuery($query);
+ }
+ }
+
+ # clear user resource cache for this type
+ $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 1, 0, 0));
+ unset($_SESSION['userresources'][$key]);
+ $key = getKey(array(array($this->restype . "Admin"), array("administer"), 0, 0, 0, 0));
+ unset($_SESSION['userresources'][$key]);
+ $key = getKey(array(array($this->restype . "Admin"), array("manageGroup"), 0, 1, 0, 0));
+ unset($_SESSION['userresources'][$key]);
+ $key = getKey(array(array($this->restype . "Admin"), array("manageGroup"), 0, 0, 0, 0));
+ unset($_SESSION['userresources'][$key]);
+
+ $tmp = $this->getData(array('rscid' => $data['rscid']));
+ $data = $tmp[$data['rscid']];
+ $arr = array('status' => 'success');
+ $arr['data'] = $data;
+ if($add) {
+ $arr['action'] = 'add';
+ $arr['nogroups'] = 0;
+ $groups = getUserResources(array($this->restype . 'Admin'), array('manageGroup'), 1);
+ if(count($groups[$this->restype]))
+ $arr['groupingHTML'] = $this->groupByResourceHTML();
+ else
+ $arr['nogroups'] = 1;
+ }
+ else
+ $arr['action'] = 'edit';
+ sendJSON($arr);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn AJeditResource()
+ ///
+ /// \brief sends data for editing a resource
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function AJeditResource() {
+ $rscid = processInputVar('rscid', ARG_NUMERIC);
+ $resources = getUserResources(array($this->restype . 'Admin'), array('administer'), 0, 1);
+ if(! array_key_exists($rscid, $resources[$this->restype])) {
+ $ret = array('status' => 'noaccess');
+ sendJSON($ret);
+ return;
+ }
+ $args = $this->defaultGetDataArgs;
+ $args['rscid'] = $rscid;
+ $tmp = $this->getData($args);
+ $data = $tmp[$rscid];
+ $login = preg_replace("/<br>/", "\n", $data['logindescription']);
+ $data['logindescription'] = htmlspecialchars_decode($login);
+ $cdata = $this->basecdata;
+ $cdata['rscid'] = $rscid;
+ $cdata['olddata'] = $data;
+
+ # save continuation
+ $cont = addContinuationsEntry('AJsaveResource', $cdata);
+
+ $ret = $this->jsondata;
+ $ret['title'] = "Edit {$this->restypename}";
+ $ret['cont'] = $cont;
+ $ret['resid'] = $rscid;
+ $ret['data'] = $data;
+ $ret['status'] = 'success';
+ sendJSON($ret);
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn addResource($data)
+ ///
+ /// \param $data - array of needed data for adding a new resource
+ ///
+ /// \return id of new resource
+ ///
+ /// \brief handles all parts of adding a new resource to the database; should
+ /// be implemented by inheriting class, but not required since it is only
+ /// called by functions in the inheriting class (nothing in this base class
+ /// calls it directly)
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function addResource($data) {
+ global $user;
+
+ $ownerid = getUserlistID($data['owner']);
+ $esc_pass = mysql_real_escape_string($data['password']);
+ $esc_desc = mysql_real_escape_string($data['logindescription']);
+
+ $query = "INSERT INTO addomain"
+ . "(name,"
+ . "ownerid,"
+ . "domainDNSName,"
+ . "domainNetBIOSName,"
+ . "username,"
+ . "password,"
+ . "dnsServers,"
+ . "domainControllers,"
+ . "logindescription)"
+ . "VALUES ('{$data['name']}',"
+ . "$ownerid,"
+ . "'{$data['domaindnsname']}',"
+ . "'{$data['domainnetbiosname']}',"
+ . "'{$data['username']}',"
+ . "'$esc_pass',"
+ . "'{$data['dnsservers']}',"
+ . "'{$data['domaincontrollers']}',"
+ . "'$esc_desc')";
+ doQuery($query);
+
+ $rscid = dbLastInsertID();
+ if($rscid == 0) {
+ return 0;
+ }
+ // add entry in resource table
+ $query = "INSERT INTO resource "
+ . "(resourcetypeid, "
+ . "subid) "
+ . "VALUES (19, "
+ . "$rscid)";
+ doQuery($query);
+ return $rscid;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn addEditDialogHTML($add)
+ ///
+ /// \param $add - unused for this class
+ ///
+ /// \brief handles generating HTML for dialog used to edit resource
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function addEditDialogHTML($add=0) {
+ global $user, $days;
+ # dialog for on page editing
+ $h = '';
+ $h .= "<div dojoType=dijit.Dialog\n";
+ $h .= " id=\"addeditdlg\"\n";
+ $h .= " title=\"Edit {$this->restypename}\"\n";
+ $h .= " duration=250\n";
+ #$h .= " style=\"width: 70%;\"\n";
+ $h .= " draggable=true>\n";
+ $h .= "<div id=\"addeditdlgcontent\">\n";
+ $h .= "<div id=\"addomaindlgcontent\">\n";
+ # id
+ $h .= "<input type=\"hidden\" id=\"editresid\">\n";
+
+ # todo consider adding help icons with popups
+
+ $h .= "<div style=\"text-align: center;\">\n";
+ # name
+ $errmsg = i("Name cannot contain single (') or double (") quotes, less than (<), or greater than (>) and can be from 2 to 30 characters long");
+ $h .= labeledFormItem('name', i('Name'), 'text', '^([A-Za-z0-9-!@#$%^&\*\(\)_=\+\[\]{}\\\|:;,\./\?~` ]){2,30}$',
+ 1, '', $errmsg, '', '', '200px');
+ # owner
+ $extra = array('onKeyPress' => 'setOwnerChecking');
+ $h .= labeledFormItem('owner', i('Owner'), 'text', '', 1,
+ "{$user['unityid']}@{$user['affiliation']}", i('Unknown user'),
+ 'checkOwner', $extra, '200px');
+ $cont = addContinuationsEntry('AJvalidateUserid');
+ $h .= "<input type=\"hidden\" id=\"valuseridcont\" value=\"$cont\">\n";
+ # domain dns name
+ $hostbase = '([A-Za-z0-9]{1,63})(\.[A-Za-z0-9-_]+)*(\.?[A-Za-z0-9])';
+ $errmsg = i("Domain DNS Name should be in the format domain.tld and can only contain letters, numbers, dashes(-), periods(.), and underscores(_) (e.g. myuniversity.edu)");
+ $h .= labeledFormItem('domaindnsname', i('Domain DNS Name'), 'text', "^$hostbase$",
+ 1, '', $errmsg, '', '', '200px');
+ # domain netbios name
+ $errmsg = i("Domain NetBIOS Name can only contain letters, numbers, dashes(-), periods(.), and underscores(_) and can be up to 15 characters long");
+ $h .= labeledFormItem('domainnetbiosname', i('Domain NetBIOS Name'), 'text', '^[a-zA-Z0-9_][-a-zA-Z0-9_\.]{0,14}$',
+ 1, '', $errmsg, '', '', '200px');
+ $h .= "<br>\n";
+ # username
+ $errmsg = i("Username cannot contain single (') or double (") quotes, less than (<), or greater than (>) and can be from 2 to 64 characters long");
+ $h .= labeledFormItem('username', i('Username'), 'text', '^([A-Za-z0-9-!@#$%^&\*\(\)_=\+\[\]{}\\\|:;,\./\?~` ]){2,30}$',
+ 1, '', $errmsg, '', '', '200px');
+ # password
+ # todo make required for adding
+ $errmsg = i("Password must be at least 4 characters long");
+ $h .= labeledFormItem('password', i('Password'), 'password', '^.{4,256}$', 0, '', $errmsg, '', '', '200px');
+ # confirm password
+ $h .= labeledFormItem('password2', i('Confirm Password'), 'password', '', 0, '', '', '', '', '200px');
+ $h .= "<br>\n";
+ # dns server list
+ $ipreg = '(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)';
+ $reg = "^($ipreg,)*($ipreg)$";
+ $errmsg = i("Invalid IP address specified - must be a valid IPV4 address");
+ $h .= labeledFormItem('dnsservers', i('DNS Server(s)'), 'text', $reg, 0, '', $errmsg,
+ '', '', '300px');
+ # domain controllers list
+ $reg = "$hostbase(,$hostbase){0,4}";
+ $errmsg = i("Invalid Domain Controller specified. Must be comma delimited list of hostnames or IP addresses, with up to 5 allowed");
+ $h .= labeledFormItem('domaincontrollers', i('Domain Controller(s)'), 'text', $reg, 0, '', $errmsg,
+ '', '', '300px');
+ # login description
+ $h .= labeledFormItem('logindescription', i('Login Description'), 'textarea', '',
+ 1, '', '', '', '', '300px');
+
+ $h .= "</div>\n"; # center
+ $h .= "</div>\n"; # addomaindlgcontent
+ $h .= "</div>\n"; # addeditdlgcontent
+
+ $h .= "<div id=\"addeditdlgerrmsg\" class=\"nperrormsg\"></div>\n";
+ $h .= "<div id=\"editdlgbtns\" align=\"center\">\n";
+ $h .= dijitButton('addeditbtn', "Confirm", "saveResource();");
+ $h .= dijitButton('', "Cancel", "dijit.byId('addeditdlg').hide();");
+ $h .= "</div>\n"; # editdlgbtns
+ $h .= "</div>\n"; # addeditdlg
+
+ $h .= "<div dojoType=dijit.Dialog\n";
+ $h .= " id=\"groupingnote\"\n";
+ $h .= " title=\"AD Domain Grouping\"\n";
+ $h .= " duration=250\n";
+ $h .= " draggable=true>\n";
+ $msg = i("Each AD Domain should be a member of an AD Domain resource group. The following dialog will allow you to add the new AD Domain to a group.");
+ $h .= wordwrap($msg, 75, '<br>');
+ $h .= "<br><br>\n";
+ $h .= "<div align=\"center\">\n";
+ $h .= dijitButton('', "Close", "dijit.byId('groupingnote').hide();");
+ $h .= "</div>\n"; # btn div
+ $h .= "</div>\n"; # groupingnote
+
+ $h .= "<div dojoType=dijit.Dialog\n";
+ $h .= " id=\"groupdlg\"\n";
+ $h .= " title=\"AD Domain Grouping\"\n";
+ $h .= " duration=250\n";
+ $h .= " draggable=true>\n";
+ $h .= "<div id=\"groupdlgcontent\"></div>\n";
+ $h .= "<div align=\"center\">\n";
+ $script = " dijit.byId('groupdlg').hide();\n";
+ $script .= " checkFirstAdd();\n";
+ $h .= dijitButton('', "Close", $script);
+ $h .= "</div>\n"; # btn div
+ $h .= "</div>\n"; # groupdlg
+
+ return $h;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn validateResourceData()
+ ///
+ /// \return array with these fields:\n
+ /// \b rscid - id of resource (from addomain table)\n
+ /// \b name\n
+ /// \b owner\n
+ /// \b times - array of arrays, each having 2 keys: start and end, each in
+ /// unix timestamp format\n
+ /// \b error - 0 if submitted data validates; 1 if anything is invalid\n
+ /// \b errormsg - if error = 1; string of error messages separated by html
+ /// break tags
+ ///
+ /// \brief validates form input from editing or adding an AD domain
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function validateResourceData() {
+ global $user;
+
+ $return = array('error' => 0);
+ $errormsg = array();
+
+ $return['rscid'] = getContinuationVar('rscid', 0);
+ $return["name"] = processInputVar("name", ARG_STRING);
+ $return["owner"] = processInputVar("owner", ARG_STRING, "{$user["unityid"]}@{$user['affiliation']}");
+ $return["domaindnsname"] = processInputVar("domaindnsname", ARG_STRING);
+ $return["domainnetbiosname"] = processInputVar("domainnetbiosname", ARG_STRING);
+ $return["username"] = processInputVar("username", ARG_STRING);
+ $return["password"] = processInputVar("password", ARG_STRING);
+ $return["password2"] = processInputVar("password2", ARG_STRING);
+ $return["dnsservers"] = processInputVar("dnsservers", ARG_STRING);
+ $return["domaincontrollers"] = processInputVar("domaincontrollers", ARG_STRING);
+ $return["logindescription"] = processInputVar("logindescription", ARG_STRING);
+
+ $return['logindescription'] = preg_replace("/[\n\s]*$/", '', $return['logindescription']);
+ $return['logindescription'] = preg_replace("/\r/", '', $return['logindescription']);
+ $return['logindescription'] = htmlspecialchars($return['logindescription']);
+ $return['logindescription'] = preg_replace("/\n/", '<br>', $return['logindescription']);
+
+ if(! preg_match("/^([A-Za-z0-9-!@#$%^&\*\(\)_=\+\[\]{}\\\|:;,\.\/\?~` ]){2,30}$/", $return['name'])) {
+ $return['error'] = 1;
+ $errormsg[] = i("Name cannot contain single (') or double (") quotes, less than (<), or greater than (>) and can be from 2 to 30 characters long");
+ }
+ elseif($this->checkExistingField('name', $return['name'], $return['rscid'])) {
+ $return['error'] = 1;
+ $errormsg[] = i("An AD domain already exists with this name.");
+ }
+ if(! validateUserid($return['owner'])) {
+ $return['error'] = 1;
+ $errormsg[] = i("Submitted owner is not valid");
+ }
+
+ if(! preg_match('/^([A-Za-z0-9]{1,63})(\.[A-Za-z0-9-_]+)*(\.?[A-Za-z0-9])$/', $return['domaindnsname'])) {
+ $return['error'] = 1;
+ $errormsg[] = i("Domain DNS Name should be in the format domain.tld and can only contain letters, numbers, dashes(-), periods(.), and underscores(_) (e.g. myuniversity.edu)");
+ }
+ if(! preg_match('/^[a-zA-Z0-9_][-a-zA-Z0-9_\.]{0,14}$/', $return['domainnetbiosname'])) {
+ $return['error'] = 1;
+ $errormsg[] = i("Domain NetBIOS Name can only contain letters, numbers, dashes(-), periods(.), and underscores(_) and can be up to 15 characters long");
+ }
+
+ if(! preg_match('/^([A-Za-z0-9-!@#$%^&\*\(\)_=\+\[\]{}\\\|:;,\.\/\?~` ]){2,30}$/', $return['username'])) {
+ $return['error'] = 1;
+ $errormsg[] = i("Username cannot contain single (') or double (") quotes, less than (<), or greater than (>) and can be from 2 to 64 characters long");
+ }
+
+ if((! empty($return['password']) ||
+ ! empty($return['password2'])) &&
+ ! preg_match('/^.{4,256}$/', $return['password'])) {
+ $return['error'] = 1;
+ $errormsg[] = i("Password must be at least 4 characters long");
+ }
+ elseif($return['password'] != $return['password2']) {
+ $return['error'] = 1;
+ $errormsg[] = i("Passwords do not match");
+ }
+
+ $ips = explode(',', $return['dnsservers']);
+ foreach($ips as $ip) {
+ if(! validateIPv4addr($ip)) {
+ $return['error'] = 1;
+ $errormsg[] = i("Invalid IP address specified for DNS Server - must be a valid IPV4 address");
+ break;
+ }
+ }
+
+ $dcs = explode(',', $return['domaincontrollers']);
+ if(count($dcs) > 5) {
+ $return['error'] = 1;
+ $errormsg[] = i("Too many Domain Controllers specified, up to 5 are allowed");
+ }
+ else {
+ foreach($dcs as $dc) {
+ if(! validateHostname($dc) && ! validateIPv4addr($dc)) {
+ $return['error'] = 1;
+ $errormsg[] = i("Invalid Domain Controller specified. Must be comman delimited list of hostnames or IP addresses, with up to 5 allowed");
+ }
+ }
+ }
+
+ /*if(! preg_match('/^$/', $return['logindescription'])) {
+ $return['error'] = 1;
+ $errormsg[] = i("");
+ }*/
+
+ if($return['error'])
+ $return['errormsg'] = implode('<br>', $errormsg);
+
+ return $return;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn checkResourceInUse($rscid)
+ ///
+ /// \param $rscid - id of AD domain
+ ///
+ /// \return empty string if not being used; string of where resource is
+ /// being used if being used
+ ///
+ /// \brief checks to see if AD domain is being used
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function checkResourceInUse($rscid) {
+ $msg = '';
+
+ $query = "SELECT i.prettyname "
+ . "FROM imageaddomain ia, "
+ . "image i "
+ . "WHERE ia.addomainid = $rscid AND "
+ . "ia.imageid = i.id";
+ $qh = doQuery($query);
+ $images = array();
+ while($row = mysql_fetch_assoc($qh))
+ $images[] = $row['prettyname'];
+ if(count($images))
+ $msg = "This AD Domain cannot be deleted because the following <strong>images</strong> are using it:<br><br>\n" . implode("<br>\n", $images);
+
+ return $msg;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
+ /// \fn checkResourceInUse($rscid)
+ ///
+ /// \param $rscid - id of resource
+ ///
+ /// \return empty string if not being used; string of where resource is
+ /// being used if being used
+ ///
+ /// \brief checks to see if resource is being used
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function checkResourceInUse($rscid) {
+ $msgs = array();
+
+ /*
+ # check reservations
+ $query = "SELECT rq.end "
+ . "FROM request rq, "
+ . "reservation rs "
+ . "WHERE rs.requestid = rq.id AND "
+ . "rs.imageid = $rscid AND "
+ . "rq.stateid NOT IN (1, 12) AND "
+ . "rq.end > NOW() "
+ . "ORDER BY rq.end DESC "
+ . "LIMIT 1";
+ $qh = doQuery($query);
+ if($row = mysql_fetch_assoc($qh))
+ $msgs[] = sprintf(i("There is at least one <strong>reservation</strong> for this image. The latest end time is %s."), prettyDatetime($row['end'], 1));;
+
+ # check blockComputers
+ $query = "SELECT br.name, "
+ . "bt.end "
+ . "FROM blockRequest br, "
+ . "blockTimes bt, "
+ . "blockComputers bc "
+ . "WHERE bc.imageid = $rscid AND "
+ . "bc.blockTimeid = bt.id AND "
+ . "bt.blockRequestid = br.id AND "
+ . "bt.end > NOW() AND "
+ . "bt.skip = 0 AND "
+ . "br.status = 'accepted' "
+ . "ORDER BY bt.end DESC "
+ . "LIMIT 1";
+ $qh = doQuery($query);
+ if($row = mysql_fetch_assoc($qh))
+ $msgs[] = sprintf(i("There is at least one <strong>Block Allocation</strong> with computers currently allocated with this image. Block Allocation %s has the latest end time which is %s."), $row['name'], prettyDatetime($row['end'], 1));
+
+ if(empty($msgs))
+ return '';
+
+ $msg = i("The selected AD Domain is currently being used in the following ways and cannot be deleted at this time.") . "<br><br>\n";
+ $msg .= implode("<br><br>\n", $msgs) . "<br><br>\n";
+ return $msg;
+ */
+ return '';
+ }
+}
+
+?>
Modified: vcl/trunk/web/.ht-inc/image.php
URL: http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/image.php?rev=1762935&r1=1762934&r2=1762935&view=diff
==============================================================================
--- vcl/trunk/web/.ht-inc/image.php (original)
+++ vcl/trunk/web/.ht-inc/image.php Fri Sep 30 16:56:45 2016
@@ -87,13 +87,23 @@ class Image extends Resource {
$w = 12;
break;
case 'os':
- $w = 7;
+ $w = 8;
+ break;
+ case 'addomain':
+ $w = 10;
+ break;
+ case 'baseOU':
+ $w = 12;
+ break;
+ case 'adauthenabled':
+ $w = 9;
break;
default:
return '';
}
if(preg_match('/MSIE/i', $_SERVER['HTTP_USER_AGENT']) ||
- preg_match('/Trident/i', $_SERVER['HTTP_USER_AGENT']))
+ preg_match('/Trident/i', $_SERVER['HTTP_USER_AGENT']) ||
+ preg_match('/Edge/i', $_SERVER['HTTP_USER_AGENT']))
$w = round($w * 11.5) . 'px';
else
$w = "{$w}em";
@@ -143,6 +153,12 @@ class Image extends Resource {
return i("Admin. Access");
case 'sethostname':
return i("Set Hostname");
+ case 'adauthenabled':
+ return i("Use AD Authentication");
+ case 'addomain':
+ return i("AD Domain");
+ case 'baseOU':
+ return i("Base OU");
}
return i(ucfirst($field));
}
@@ -434,6 +450,25 @@ class Image extends Resource {
$h .= "id=\"connectmethodids\">\n";
}
$h .= "</div>\n"; #labeledform
+
+ # AD authentication
+ $h .= "<div class=\"boxedoptions hidden\" id=\"imageadauthbox\">\n";
+ # enable toggle
+ $vals = getUserResources(array('addomainAdmin'), array("manageGroup"));
+ $extra = array();
+ if(count($vals['addomain']) == 0)
+ $extra['disabled'] = 'true';
+ $extra['onChange'] = 'toggleADauth();';
+ $h .= labeledFormItem('adauthenable', i('Use AD Authentication'), 'check', '', '', '', '', '', $extra);
+ # AD domain
+ $disabled = array('disabled' => 'true');
+ $h .= labeledFormItem('addomainid', i('AD Domain'), 'select', $vals['addomain'], '', '', '', '', $disabled);
+ # base OU
+ $reg = '^([Oo][Uu])=[^,]+(,([Oo][Uu])=[^,]+)*$';
+ $errmsg = i("Invalid base OU; do not include DC components");
+ $h .= labeledFormItem('baseou', i('Base OU'), 'text', $reg, 0, '', $errmsg, '', $disabled, '230px', helpIcon('baseouhelp'));
+ $h .= "</div>\n"; # boxedoptions
+
# subimages
if(! $add) {
$h .= "<br>\n";
@@ -488,6 +523,8 @@ class Image extends Resource {
$h .= dijitButton('', i("Cancel"), $script);
$h .= " </div>\n";
$h .= "</div>\n"; # autoconfirmdlg
+
+ $h .= helpTooltip('baseouhelp', i('OU where nodes deployed with this image will be registered. Do not enter the domain component (ex OU=Computers,OU=VCL)'));
return $h;
}
@@ -758,6 +795,41 @@ class Image extends Resource {
. " WHERE id = {$data['imageid']}";
doQuery($query);
}
+
+ # ad authentication
+ if($olddata['ostype'] == 'windows') {
+ if($data['adauthenabled'] != $olddata['adauthenabled']) {
+ if($data['adauthenabled']) {
+ $esc_baseou = mysql_real_escape_string($data['baseou']);
+ $query = "INSERT INTO imageaddomain "
+ . "(imageid, "
+ . "addomainid, "
+ . "baseOU) "
+ . "VALUES "
+ . "({$data['imageid']}, "
+ . "{$data['addomainid']}, "
+ . "'$esc_baseou')";
+ doQuery($query);
+ }
+ else {
+ $query = "DELETE FROM imageaddomain "
+ . "WHERE imageid = {$data['imageid']}";
+ doQuery($query);
+ }
+ }
+ elseif($data['adauthenabled'] &&
+ ($data['addomainid'] != $olddata['addomainid'] ||
+ $data['baseou'] != $olddata['baseOU'])) {
+ $esc_baseou = mysql_real_escape_string($data['baseou']);
+ $query = "UPDATE imageaddomain "
+ . "SET addomainid = {$data['addomainid']}, "
+ . "baseOU = '$esc_baseou' "
+ . "WHERE imageid = {$data['imageid']}";
+ doQuery($query);
+ }
+ }
+
+ # imagemeta
if(empty($olddata['imagemetaid']) &&
($data['checkuser'] == 0 || $data['rootaccess'] == 0 ||
($olddata['ostype'] == 'windows' && $data['sethostname'] == 1) ||
@@ -1148,6 +1220,20 @@ class Image extends Resource {
. "{$data['basedoffrevisionid']})";
doQuery($query, 205);
$imageid = dbLastInsertID();
+
+ # ad authentication
+ if($data['adauthenabled']) {
+ $esc_baseou = mysql_real_escape_string($data['baseou']);
+ $query = "INSERT INTO imageaddomain "
+ . "(imageid, "
+ . "addomainid, "
+ . "baseOU) "
+ . "VALUES "
+ . "($imageid, "
+ . "{$data['addomainid']}, "
+ . "'$esc_baseou')";
+ doQuery($query);
+ }
// possibly add entry to imagemeta table
$imagemetaid = 0;
@@ -1530,6 +1616,9 @@ class Image extends Resource {
$return["sethostname"] = processInputVar("sethostname", ARG_NUMERIC);
$return["sysprep"] = processInputVar("sysprep", ARG_NUMERIC); # only in add
$return["connectmethodids"] = processInputVar("connectmethodids", ARG_STRING); # only in add
+ $return["adauthenabled"] = processInputVar("adauthenabled", ARG_NUMERIC);
+ $return["addomainid"] = processInputVar("addomainid", ARG_NUMERIC);
+ $return["baseou"] = processInputVar("baseou", ARG_STRING);
$return['requestid'] = getContinuationVar('requestid'); # only in add
$return["imageid"] = getContinuationVar('imageid');
@@ -1636,6 +1725,27 @@ class Image extends Resource {
$return['error'] = 1;
$errormsg[] = i("Use Sysprep must be Yes or No");
}
+ if($return['adauthenabled'] != 0 && $return['adauthenabled'] != 1)
+ $return['adauthenabled'] = 0;
+ if($return['adauthenabled'] == 1) {
+ $vals = getUserResources(array('addomainAdmin'), array("manageGroup"));
+ if(! array_key_exists($return['addomainid'], $vals['addomain'])) {
+ $return['error'] = 1;
+ $errormsg[] = i("Invalid AD Domain submitted");
+ }
+ if(! preg_match('/^([Oo][Uu])=[^,]+(,([Oo][Uu])=[^,]+)*$/', $return['baseou'])) {
+ $return['error'] = 1;
+ $errormsg[] = i("Invalid Base OU submitted, must start with OU=");
+ }
+ if(preg_match('/DC=.+(,DC=.+)*$/', $return['baseou'])) {
+ $return['error'] = 1;
+ $errormsg[] = i("Base OU must not contain DC= components");
+ }
+ }
+ else {
+ $return['addomainid'] = 0;
+ $return['baseou'] = NULL;
+ }
if(empty($return['desc'])) {
$return['error'] = 1;
$errormsg[] = i("You must include a description of the image") . "<br>";
@@ -1659,6 +1769,7 @@ class Image extends Resource {
$return['connectmethodids'] = implode(',', array_keys($ids));
}
}
+
if($return['error'])
$return['errormsg'] = implode('<br>', $errormsg);
return $return;
Modified: vcl/trunk/web/.ht-inc/resource.php
URL: http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/resource.php?rev=1762935&r1=1762934&r2=1762935&view=diff
==============================================================================
--- vcl/trunk/web/.ht-inc/resource.php (original)
+++ vcl/trunk/web/.ht-inc/resource.php Fri Sep 30 16:56:45 2016
@@ -43,6 +43,9 @@ function resource($type) {
case 'schedule':
$obj = new Schedule();
break;
+ case 'addomain':
+ $obj = new ADdomain();
+ break;
}
$html = $obj->selectionText();
@@ -69,7 +72,7 @@ class Resource {
var $deletetoggled;
var $errmsg;
var $namefield;
- var $noadd;
+ var $addable;
var $jsondata;
/////////////////////////////////////////////////////////////////////////////
@@ -288,7 +291,7 @@ class Resource {
if($this->deletetoggled) {
$h .= "<label for=\"showdeleted\"><strong>";
$h .= i("Include Deleted {$this->restypename}s:");
- $h .= "</strong>:</label>\n";
+ $h .= "</strong></label>\n";
$h .= "<input type=\"checkbox\" dojoType=\"dijit.form.CheckBox\" ";
$h .= "id=\"showdeleted\" onChange=\"resource.GridFilter();\">\n";
}
@@ -306,7 +309,8 @@ class Resource {
$h .= "<thead>\n";
$h .= "<tr>\n";
if(preg_match('/MSIE/i', $_SERVER['HTTP_USER_AGENT']) ||
- preg_match('/Trident/i', $_SERVER['HTTP_USER_AGENT']))
+ preg_match('/Trident/i', $_SERVER['HTTP_USER_AGENT']) ||
+ preg_match('/Edge/i', $_SERVER['HTTP_USER_AGENT']))
$w = array('64px', '38px', '200px');
else
$w = array('5em', '3.5em', '17em');
@@ -442,7 +446,8 @@ class Resource {
return '';
}
if(preg_match('/MSIE/i', $_SERVER['HTTP_USER_AGENT']) ||
- preg_match('/Trident/i', $_SERVER['HTTP_USER_AGENT']))
+ preg_match('/Trident/i', $_SERVER['HTTP_USER_AGENT']) ||
+ preg_match('/Edge/i', $_SERVER['HTTP_USER_AGENT']))
$w = round($w * 11.5) . 'px';
else
$w = "{$w}em";
@@ -1602,6 +1607,34 @@ class Resource {
/////////////////////////////////////////////////////////////////////////////
///
+ /// \fn checkExistingField($field, $value, $id=0)
+ ///
+ /// \param $field - database field name
+ /// \param $value - value for $field
+ /// \param $id - (optional, default=0) if nonzero, ignore resource with this
+ /// id
+ ///
+ /// \return 1 if existing resource with $field set to $value, 0 if not
+ ///
+ /// \brief checks to see if there is already a record in the database with
+ /// $field set to $value
+ ///
+ /////////////////////////////////////////////////////////////////////////////
+ function checkExistingField($field, $value, $id=0) {
+ $query = "SELECT id FROM {$this->restype} "
+ . "WHERE `$field` = '$value'";
+ if($this->deletetoggled)
+ $query .= " AND deleted = 0";
+ if($id)
+ $query .= " AND id != $id";
+ $qh = doQuery($query);
+ if(mysql_num_rows($qh))
+ return 1;
+ return 0;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ ///
/// \fn extraSelectAdminOptions()
///
/// \return html
@@ -1617,6 +1650,8 @@ class Resource {
///
/// \fn checkResourceInUse($rscid)
///
+ /// \param $rscid - id of resource
+ ///
/// \return empty string if not being used; string of where resource is
/// being used if being used
///
Modified: vcl/trunk/web/.ht-inc/states.php
URL: http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/states.php?rev=1762935&r1=1762934&r2=1762935&view=diff
==============================================================================
--- vcl/trunk/web/.ht-inc/states.php (original)
+++ vcl/trunk/web/.ht-inc/states.php Fri Sep 30 16:56:45 2016
@@ -56,6 +56,7 @@ $actions["entry"] = array('main',
'computer',
'managementnode',
'schedule',
+ 'addomain',
'RESTresourceBasic',
'RESTresourceDetail',
#'testDojoREST',
@@ -596,6 +597,8 @@ $actions['mode']['managementnode'] = "re
$actions['args']['managementnode'] = 'managementnode';
$actions['mode']['schedule'] = "resource";
$actions['args']['schedule'] = 'schedule';
+$actions['mode']['addomain'] = "resource";
+$actions['args']['addomain'] = 'addomain';
$actions['mode']['viewResources'] = "viewResources";
$actions['mode']['jsonResourceStore'] = "jsonResourceStore";
$actions['mode']['AJpromptToggleDeleteResource'] = "AJpromptToggleDeleteResource";
@@ -656,6 +659,7 @@ $actions['pages']['image'] = "image";
$actions['pages']['computer'] = "computer";
$actions['pages']['managementnode'] = "managementnode";
$actions['pages']['schedule'] = "schedule";
+$actions['pages']['addomain'] = "addomain";
$actions['pages']['viewResources'] = "resource";
$actions['pages']['jsonResourceStore'] = "resource";
$actions['pages']['AJpromptToggleDeleteResource'] = "resource";
Modified: vcl/trunk/web/.ht-inc/utils.php
URL: http://svn.apache.org/viewvc/vcl/trunk/web/.ht-inc/utils.php?rev=1762935&r1=1762934&r2=1762935&view=diff
==============================================================================
--- vcl/trunk/web/.ht-inc/utils.php (original)
+++ vcl/trunk/web/.ht-inc/utils.php Fri Sep 30 16:56:45 2016
@@ -300,6 +300,7 @@ function initGlobals() {
case 'computer':
case 'managementnode':
case 'schedule':
+ case 'addomain':
require_once(".ht-inc/resource.php");
break;
case 'storebackend':
@@ -1326,15 +1327,20 @@ function getImages($includedeleted=0, $i
. "i.lastupdate, "
. "i.forcheckout, "
. "i.maxinitialtime, "
- . "i.imagemetaid "
- . "FROM image i, "
- . "platform p, "
+ . "i.imagemetaid, "
+ . "ad.id AS addomainid, "
+ . "ad.name AS addomain, "
+ . "iadd.baseOU "
+ . "FROM platform p, "
. "OS o, "
. "OStype ot, "
. "resource r, "
. "resourcetype t, "
. "user u, "
- . "affiliation a "
+ . "affiliation a, "
+ . "image i "
+ . "LEFT JOIN imageaddomain iadd ON (i.id = iadd.imageid) "
+ . "LEFT JOIN addomain ad ON (iadd.addomainid = ad.id) "
. "WHERE i.platformid = p.id AND "
. "r.resourcetypeid = t.id AND "
. "t.name = 'image' AND "
@@ -1357,6 +1363,9 @@ function getImages($includedeleted=0, $i
$imagelist[$includedeleted][$row['id']]['sethostname'] = 0;
else
$imagelist[$includedeleted][$row['id']]['sethostname'] = 1;
+ $imagelist[$includedeleted][$row['id']]['adauthenabled'] = 0;
+ if($row['addomainid'] != NULL)
+ $imagelist[$includedeleted][$row['id']]['adauthenabled'] = 1;
if($row["imagemetaid"] != NULL) {
if(array_key_exists($row['imagemetaid'], $allmetadata)) {
$metaid = $row['imagemetaid'];
@@ -2998,22 +3007,31 @@ function getResourceGroupMembers($type="
$orders = "m.hostname";
$types = "'managementnode'";
}
+ elseif($type == "addomain") {
+ $names = "ad.name AS addomain ";
+ $joins = "LEFT JOIN addomain ad ON (r.subid = ad.id AND r.resourcetypeid = 19) ";
+ $orders = "ad.name";
+ $types = "'addomain'";
+ }
else {
$names = "c.hostname AS computer, "
. "c.deleted, "
. "i.prettyname AS image, "
. "i.deleted AS deleted2, "
. "s.name AS schedule, "
- . "m.hostname AS managementnode ";
+ . "m.hostname AS managementnode, "
+ . "ad.name AS addomain ";
$joins = "LEFT JOIN computer c ON (r.subid = c.id AND r.resourcetypeid = 12) "
. "LEFT JOIN image i ON (r.subid = i.id AND r.resourcetypeid = 13) "
. "LEFT JOIN schedule s ON (r.subid = s.id AND r.resourcetypeid = 15) "
- . "LEFT JOIN managementnode m ON (r.subid = m.id AND r.resourcetypeid = 16) ";
+ . "LEFT JOIN managementnode m ON (r.subid = m.id AND r.resourcetypeid = 16) "
+ . "LEFT JOIN addomain ad ON (r.subid = ad.id AND r.resourcetypeid = 19) ";
$orders = "c.hostname, "
. "i.prettyname, "
. "s.name, "
- . "m.hostname";
- $types = "'computer','image','schedule','managementnode'";
+ . "m.hostname, "
+ . "ad.name";
+ $types = "'computer','image','schedule','managementnode','addomain'";
}
$query = "SELECT rgm.resourcegroupid, "
@@ -8813,6 +8831,60 @@ function getNATports($resid) {
////////////////////////////////////////////////////////////////////////////////
///
+/// \fn getADdomains($addomainid=0)
+///
+/// \param $addomainid - (optional) id of an AD domain
+///
+/// \return array of available AD domains with the following keys:\n
+/// \b id\n
+/// \b resourceid\n
+/// \b name\n
+/// \b ownerid\n
+/// \b owner\n
+/// \b domaindnsname\n
+/// \b domainnetbiosname\n
+/// \b username\n
+/// \b dnsservers\n
+/// \b domaincontrollers\n
+/// \b logindescription
+///
+/// \brief builds an array of AD domains
+///
+////////////////////////////////////////////////////////////////////////////////
+function getADdomains($addomainid=0) {
+ $query = "SELECT ad.id, "
+ . "r.id AS resourceid, "
+ . "ad.name, "
+ . "ad.ownerid, "
+ . "CONCAT(u.unityid, '@', a.name) AS owner, "
+ . "ad.domainDNSName AS domaindnsname, "
+ . "ad.domainNetBIOSName AS domainnetbiosname, "
+ . "ad.username, "
+ . "ad.dnsServers AS dnsservers, "
+ . "ad.domainControllers AS domaincontrollers, "
+ . "ad.logindescription "
+ . "FROM addomain ad, "
+ . "affiliation a, "
+ . "user u, "
+ . "resource r, "
+ . "resourcetype rt "
+ . "WHERE ad.ownerid = u.id AND "
+ . "u.affiliationid = a.id AND "
+ . "r.subid = ad.id AND "
+ . "r.resourcetypeid = rt.id AND "
+ . "rt.name = 'addomain'";
+ if($addomainid)
+ $query .= " AND ad.id = $addomainid";
+
+ $qh = doQuery($query);
+ $addomainlist = array();
+ while($row = mysql_fetch_assoc($qh))
+ $addomainlist[$row['id']] = $row;
+ return $addomainlist;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
/// \fn getBlockTimeData($start, $end)
///
/// \param $start - (optional) start time of blockTimes to get in unix timestamp
@@ -9098,11 +9170,12 @@ function labeledFormItem($id, $label, $t
$required = 'false';
switch($type) {
case 'text':
+ case 'password':
if($width == '')
$width = '300px';
$h .= "<label for=\"$id\">$label:</label>\n";
$h .= "<span class=\"labeledform\">\n";
- $h .= "<input type=\"text\" ";
+ $h .= "<input type=\"$type\" ";
$h .= "dojoType=\"dijit.form.ValidationTextBox\" ";
$h .= "required=\"$required\" ";
if($constraints != '')
@@ -11891,6 +11964,26 @@ function validateIPv4addr($ip) {
////////////////////////////////////////////////////////////////////////////////
///
+/// \fn validateHostname($name)
+///
+/// \param $name the hostname to validate
+///
+/// \return 1 if valid hostname else 0
+///
+/// \brief validates a given hostname
+///
+////////////////////////////////////////////////////////////////////////////////
+function validateHostname($name) {
+ if(strlen($name) > 255)
+ return 0;
+ // return 0 if dotted numbers only
+ if(preg_match('/^[0-9]+(\.[0-9]+){3}$/', $name))
+ return 0;
+ return preg_match('/^([A-Za-z0-9]{1,63})(\.[A-Za-z0-9-_]+)*(\.?[A-Za-z0-9])$/', $name);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
/// \fn validateEmailAddress($addr)
///
/// \param $addr - an email address
@@ -12714,6 +12807,12 @@ function getNavMenuData($homeurl=HOMEURL
$menudata['vm']['selected'] = checkMenuItemSelected('vm');
}
+ if(in_array("addomainAdmin", $user["privileges"])) {
+ $menudata['addomain']['url'] = BASEURL . SCRIPT . "?mode=addomain";
+ $menudata['addomain']['title'] = i('AD Domains');
+ $menudata['addomain']['selected'] = checkMenuItemSelected('addomain');
+ }
+
if(checkUserHasPerm('Schedule Site Maintenance')) {
$menudata['sitemaintenance']['url'] = BASEURL . SCRIPT . "?mode=siteMaintenance";
$menudata['sitemaintenance']['title'] = i('Site Maintenance');
@@ -13277,6 +13376,9 @@ function getDojoHTML($refresh) {
case 'computer':
$jsfile = 'resources/computer.js';
break;
+ case 'addomain':
+ $jsfile = 'resources/addomain.js';
+ break;
}
if(isset($jsfile))
$rt .= "<script type=\"text/javascript\" src=\"js/$jsfile?v=$v\"></script>\n";
@@ -13366,6 +13468,9 @@ function getDojoHTML($refresh) {
case 'computer':
$jsfile = 'resources/computer.js';
break;
+ case 'addomain':
+ $jsfile = 'resources/addomain.js';
+ break;
}
$rt .= "<script type=\"text/javascript\" src=\"js/resources.js?v=$v\"></script>\n";
if(isset($jsfile))
Modified: vcl/trunk/web/css/vcl.css
URL: http://svn.apache.org/viewvc/vcl/trunk/web/css/vcl.css?rev=1762935&r1=1762934&r2=1762935&view=diff
==============================================================================
--- vcl/trunk/web/css/vcl.css (original)
+++ vcl/trunk/web/css/vcl.css Fri Sep 30 16:56:45 2016
@@ -591,6 +591,14 @@ body {
width: 16.5em;
}
+#addomaindlgcontent label {
+ width: 14.5em;
+}
+
+#addomaindlgcontent .labeledform {
+ margin-left: 15em;
+}
+
#cfgvartypelbl {
margin-top: 6px;
}
Added: vcl/trunk/web/js/resources/addomain.js
URL: http://svn.apache.org/viewvc/vcl/trunk/web/js/resources/addomain.js?rev=1762935&view=auto
==============================================================================
--- vcl/trunk/web/js/resources/addomain.js (added)
+++ vcl/trunk/web/js/resources/addomain.js Fri Sep 30 16:56:45 2016
@@ -0,0 +1,145 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements. See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+function ADdomain() {
+ Resource.apply(this, Array.prototype.slice.call(arguments));
+ this.restype = 'addomain';
+}
+ADdomain.prototype = new Resource();
+
+ADdomain.prototype.colformatter = function(value, rowIndex, obj) {
+ if(obj.field == 'logindescription') {
+ var str = value.replace(/<br>/g, '<br>');
+ str = str.replace(/&/g, '&');
+ return str;
+ }
+ return value;
+}
+
+var resource = new ADdomain();
+
+function addNewResource(title) {
+ dijit.byId('addeditdlg').set('title', title);
+ dijit.byId('addeditbtn').set('label', title);
+ dojo.byId('editresid').value = 0;
+ resetEditResource();
+ dijit.byId('addeditdlg').show();
+}
+
+function inlineEditResourceCB(data, ioArgs) {
+ if(data.items.status == 'success') {
+ dojo.byId('saveresourcecont').value = data.items.cont;
+ dijit.byId('addeditdlg').set('title', data.items.title);
+ dijit.byId('addeditbtn').set('label', 'Save Changes');
+ dojo.byId('editresid').value = data.items.rscid;
+ dijit.byId('name').set('value', data.items.data.name);
+ dijit.byId('owner').set('value', data.items.data.owner);
+
+ dijit.byId('domaindnsname').set('value', data.items.data.domaindnsname);
+ dijit.byId('domainnetbiosname').set('value', data.items.data.domainnetbiosname);
+ dijit.byId('username').set('value', data.items.data.username);
+ dijit.byId('dnsservers').set('value', data.items.data.dnsservers);
+ dijit.byId('domaincontrollers').set('value', data.items.data.domaincontrollers);
+ dijit.byId('logindescription').set('value', data.items.data.logindescription);
+
+ dojo.byId('addeditdlgerrmsg').innerHTML = '';
+ dijit.byId('addeditdlg').show();
+ }
+ else if(data.items.status == 'noaccess') {
+ alert('Access denied to edit this item');
+ }
+}
+
+function resetEditResource() {
+ var fields = ['name', 'owner', 'domaindnsname', 'domainnetbiosname', 'username', 'password', 'password2', 'dnsservers', 'domaincontrollers', 'logindescription'];
+ for(var i = 0; i < fields.length; i++) {
+ dijit.byId(fields[i]).reset();
+ }
+ dojo.byId('addeditdlgerrmsg').innerHTML = '';
+}
+
+function saveResource() {
+ var errobj = dojo.byId('addeditdlgerrmsg');
+ var fields = ['name', 'owner', 'domaindnsname', 'domainnetbiosname', 'username', 'password', 'password2', 'dnsservers', 'domaincontrollers', 'logindescription'];
+
+ if(dojo.byId('editresid').value == 0)
+ var data = {continuation: dojo.byId('addresourcecont').value};
+ else
+ var data = {continuation: dojo.byId('saveresourcecont').value};
+
+ for(var i = 0; i < fields.length; i++) {
+ if(! checkValidatedObj(fields[i], errobj))
+ return;
+ data[fields[i]] = dijit.byId(fields[i]).get('value');
+ }
+ if(dijit.byId('password').get('value') != dijit.byId('password2').get('value')) {
+ dojo.byId('addeditdlgerrmsg').innerHTML = _('Passwords do not match');
+ return;
+ }
+
+ dijit.byId('addeditbtn').set('disabled', true);
+ RPCwrapper(data, saveResourceCB, 1);
+}
+
+function saveResourceCB(data, ioArgs) {
+ if(data.items.status == 'error') {
+ dojo.byId('addeditdlgerrmsg').innerHTML = '<br>' + data.items.msg;
+ dijit.byId('addeditbtn').set('disabled', false);
+ return;
+ }
+ else if(data.items.status == 'adderror') {
+ alert(data.items.errormsg);
+ }
+ else if(data.items.status == 'success') {
+ if(data.items.action == 'add') {
+ if(typeof resourcegrid !== 'undefined') {
+ resourcegrid.store.newItem(data.items.data);
+ resourcegrid.sort();
+ }
+ dojo.forEach(dijit.findWidgets(dojo.byId('groupdlgcontent')), function(w) {
+ w.destroyRecursive();
+ });
+ if(data.items.nogroups == 0) {
+ dojo.byId('groupdlgcontent').innerHTML = data.items.groupingHTML;
+ AJdojoCreate('groupdlgcontent');
+ dojo.byId('resources').value = data.items.data.id;
+ populateLists('resources', 'ingroups', 'inresourcename', 'outresourcename', 'resgroupinggroupscont');
+ dijit.byId('groupdlg').show();
+ dijit.byId('groupingnote').show();
+ }
+ }
+ else {
+ resourcegrid.store.fetch({
+ query: {id: data.items.data.id},
+ onItem: function(item) {
+ var fields = ['name', 'owner', 'domaindnsname', 'domainnetbiosname', 'username','dnsservers', 'domaincontrollers', 'logindescription'];
+ for(var i = 0; i < fields.length; i++) {
+ dijit.byId(fields[i]).reset();
+ resourcegrid.store.setValue(item, fields[i], data.items.data[fields[i]]);
+ }
+ },
+ onComplete: function(items, result) {
+ // when call resourcegrid.sort directly, the table contents disappear; not sure why
+ setTimeout(function() {resourcegrid.sort();}, 10);
+ }
+ });
+ }
+ dijit.byId('addeditdlg').hide();
+ resetEditResource();
+ setTimeout(function() {dijit.byId('addeditbtn').set('disabled', false);}, 250);
+ }
+}
Modified: vcl/trunk/web/js/resources/image.js
URL: http://svn.apache.org/viewvc/vcl/trunk/web/js/resources/image.js?rev=1762935&r1=1762934&r2=1762935&view=diff
==============================================================================
--- vcl/trunk/web/js/resources/image.js (original)
+++ vcl/trunk/web/js/resources/image.js Fri Sep 30 16:56:45 2016
@@ -29,13 +29,16 @@ Image.prototype.colformatter = function(
obj.field == 'forcheckout' ||
obj.field == 'checkuser' ||
obj.field == 'rootaccess' ||
- obj.field == 'sethostname') {
+ obj.field == 'sethostname' ||
+ obj.field == 'adauthenabled') {
if(value == "0")
return '<span class="rederrormsg">' + _('false') + '</span>';
if(value == "1")
return '<span class="ready">' + _('true') + '</span>';
}
- if(obj.field == 'maxinitialtime' && value == 0)
+ if((obj.field == 'maxinitialtime' && value == 0) ||
+ (obj.field == 'addomain' && value == null) ||
+ (obj.field == 'baseOU' && value == null))
return '(unset)';
return value;
}
@@ -70,6 +73,25 @@ function inlineEditResourceCB(data, ioAr
dojo.addClass('sethostnamediv', 'hidden');
dojo.byId('connectmethodlist').innerHTML = data.items.data.connectmethods.join('<br>');
dijit.byId('connectmethodttd').set('href', data.items.data.connectmethodurl);
+ if(data.items.data.ostype == 'windows') {
+ dojo.removeClass('imageadauthbox', 'hidden');
+ if(data.items.data.adauthenabled) {
+ dijit.byId('adauthenable').set('checked', true);
+ dijit.byId('addomainid').set('value', data.items.data.addomainid);
+ dijit.byId('baseou').set('value', data.items.data.baseOU);
+ }
+ else {
+ dijit.byId('adauthenable').set('checked', false);
+ dijit.byId('addomainid').reset();
+ dijit.byId('baseou').reset();
+ }
+ }
+ else {
+ dojo.addClass('imageadauthbox', 'hidden');
+ dijit.byId('adauthenable').set('checked', false);
+ dijit.byId('addomainid').reset();
+ dijit.byId('baseou').reset();
+ }
dijit.byId('subimagedlg').set('href', data.items.data.subimageurl);
dojo.byId('revisiondiv').innerHTML = data.items.data.revisionHTML;
dojo.byId('addeditdlgerrmsg').innerHTML = '';
@@ -111,6 +133,9 @@ function resetEditResource() {
dijit.byId('advancedoptions').toggle();
dojo.byId('connectmethodlist').innerHTML = '';
dojo.byId('addeditdlgerrmsg').innerHTML = '';
+ dijit.byId('adauthenable').reset();
+ dijit.byId('addomainid').reset();
+ dijit.byId('baseou').reset();
}
function saveResource() {
@@ -168,6 +193,12 @@ function saveResource() {
setTimeout(function() {dijit.byId('reload').focus();}, 300);
return;
}
+ if(dijit.byId('adauthenable').checked && ! checkValidatedObj('baseou', errobj)) {
+ if(! dijit.byId('advancedoptions').open)
+ dijit.byId('advancedoptions').toggle();
+ setTimeout(function() {dijit.byId('baseou').focus();}, 300);
+ return;
+ }
if(dojo.byId('editresid').value == 0)
var data = {continuation: dojo.byId('addresourcecont').value};
@@ -234,6 +265,16 @@ function saveResource() {
data['cpuspeed'] = dijit.byId('cpuspeed').get('value');
if(dijit.byId('reload'))
data['reload'] = dijit.byId('reload').get('value');
+ if(dijit.byId('adauthenable').checked) {
+ data['adauthenabled'] = 1;
+ data['addomainid'] = dijit.byId('addomainid').get('value');
+ data['baseou'] = dijit.byId('baseou').get('value');
+ }
+ else {
+ data['adauthenabled'] = 0;
+ data['addomainid'] = 0;
+ data['baseou'] = '';
+ }
submitbtn.set('disabled', true);
RPCwrapper(data, saveResourceCB, 1);
@@ -287,6 +328,10 @@ function saveResourceCB(data, ioArgs) {
resourcegrid.store.setValue(item, 'rootaccess', parseInt(data.items.data.rootaccess));
resourcegrid.store.setValue(item, 'sethostname', parseInt(data.items.data.sethostname));
resourcegrid.store.setValue(item, 'reloadtime', data.items.data.reloadtime);
+ resourcegrid.store.setValue(item, 'adauthenabled', data.items.data.adauthenabled);
+ resourcegrid.store.setValue(item, 'addomainid', data.items.data.addomainid);
+ resourcegrid.store.setValue(item, 'addomain', data.items.data.addomain);
+ resourcegrid.store.setValue(item, 'baseOU', data.items.data.baseOU);
},
onComplete: function(items, result) {
// when call resourcegrid.sort directly, the table contents disappear; not sure why
@@ -663,10 +708,17 @@ function startImageCB(data, ioArgs) {
}
else
dojo.addClass('sethostnamediv', 'hidden');
- if(data.items.ostype == 'windows')
+ dijit.byId('adauthenable').set('checked', false);
+ dijit.byId('addomainid').reset();
+ dijit.byId('baseou').reset();
+ if(data.items.ostype == 'windows') {
dojo.removeClass('sysprepdiv', 'hidden');
- else
+ dojo.removeClass('imageadauthbox', 'hidden');
+ }
+ else {
dojo.addClass('sysprepdiv', 'hidden');
+ dojo.addClass('imageadauthbox', 'hidden');
+ }
if(data.items.checkpoint) {
dojo.addClass('imageendrescontent', 'hidden');
@@ -763,3 +815,14 @@ function submitUpdateImageClickthroughCB
dijit.byId('clickthroughDlgBtn').set('disabled', false);
resRefresh();
}
+
+function toggleADauth() {
+ if(dijit.byId('adauthenable').checked) {
+ dijit.byId('addomainid').set('disabled', false);
+ dijit.byId('baseou').set('disabled', false);
+ }
+ else {
+ dijit.byId('addomainid').set('disabled', true);
+ dijit.byId('baseou').set('disabled', true);
+ }
+}
Modified: vcl/trunk/web/themes/dropdownmenus/css/theme.css
URL: http://svn.apache.org/viewvc/vcl/trunk/web/themes/dropdownmenus/css/theme.css?rev=1762935&r1=1762934&r2=1762935&view=diff
==============================================================================
--- vcl/trunk/web/themes/dropdownmenus/css/theme.css (original)
+++ vcl/trunk/web/themes/dropdownmenus/css/theme.css Fri Sep 30 16:56:45 2016
@@ -144,6 +144,27 @@ div.dijitDialog h3 {
background-color: black;
color: white;
}
+#renameDialog tbody tr:hover td,
+#renameDialog tbody tr td {
+ background-color: transparent;
+ border-top: none;
+ padding: 0.2em;
+}
+div.dijitDialog h2,
+div.dijitDialog h3 {
+ margin-top: 0.1em;
+}
+#confdelcontent h3 {
+ font-size: 1.4em;
+ font-weight: bold;
+}
+#groupbyresourcediv table.dojoxGridRowTable tbody tr:hover td {
+ background-color: transparent;
+}
+#groupbyresourcediv div.dojoxGridRowSelected table.dojoxGridRowTable tbody tr td {
+ background-color: black;
+ color: white;
+}
#addeditdlg tbody tr td.dijitButtonNode {
border: 1px solid #c0c0c0;
}
@@ -416,6 +437,12 @@ h1.site-title {
#advancedoptions .labeledform {
margin-left: 21.5em;
}
+#imageadauthbox label {
+ width: 16em;
+}
+#imageadauthbox .labeledform {
+ margin-left: 16.5em;
+}
#mgmtnodedlgcontent label {
width: 24.5em;
}