diff --git a/apt/APT_Profile.pm.in b/apt/APT_Profile.pm.in index 8886ffe8571d54fd3c054a2459a42216c30078ba..c1131bd2d8527629c2eb086c4170e2fa6ef6613e 100644 --- a/apt/APT_Profile.pm.in +++ b/apt/APT_Profile.pm.in @@ -406,7 +406,7 @@ sub NewVersion($$) " parent_profileid,parent_version,rspec, ". " script,paramdefs) ". "select name,profileid,'$newvers',pid,pid_idx, ". - " '$uid','$uid_idx',now(),uuid(),parent_profileid, ". + " '$uid','$uid_idx',now(),uuid(),'$profileid', ". " '$version',rspec,script,paramdefs ". "from apt_profile_versions as v ". "where v.profileid='$profileid' and ". @@ -517,8 +517,7 @@ sub Delete($$) } else { # Set deleted on all of the versions. - DBQueryWarn("update apt_profile_versions set ". - " deleted=now(),locked=null,locker_pid=0 ". + DBQueryWarn("update apt_profile_versions set deleted=now() ". "where profileid='$profileid'") or goto bad; # Delete any leftover webtasks. @@ -557,19 +556,18 @@ sub DeleteVersion($) my $version = $self->version(); # - # Only the "head" version can be deleted + # Need to know what profile becomes the head version. This will + # always be the highest numbered undeleted profile. # my $query_result = DBQueryWarn("select max(version) from apt_profile_versions ". - "where profileid='$profileid'"); + "where profileid='$profileid' and version!=${version} ". + " and deleted is null"); goto bad if (!$query_result || !$query_result->numrows); - my ($head) = $query_result->fetchrow_array(); - if ($head != $version) { - print STDERR "Profile::DeleteVersion: not the head version of $self\n"; - goto bad; - } + my ($newhead) = $query_result->fetchrow_array(); + # Delete leftover webtask. DBQueryWarn("delete web_tasks from apt_profile_versions ". "left join web_tasks on ". @@ -578,12 +576,12 @@ sub DeleteVersion($) " apt_profile_versions.version='$version'"); goto bad - if (!DBQueryWarn("delete from apt_profile_versions ". + if (!DBQueryWarn("update apt_profile_versions set deleted=now() ". "where profileid='$profileid' and ". " version='$version'")); goto bad - if (!DBQueryWarn("update apt_profiles set version=version-1 ". + if (!DBQueryWarn("update apt_profiles set version=$newhead ". "where profileid='$profileid' and ". " version='$version'")); DBQueryWarn("unlock tables"); @@ -1158,7 +1156,7 @@ sub IsHead($) my $query_result = DBQueryWarn("select max(version) from apt_profile_versions ". - "where profileid='$profileid'"); + "where profileid='$profileid' and deleted is null"); return -1 if (!$query_result || !$query_result->numrows); diff --git a/apt/manage_profile.in b/apt/manage_profile.in index 29f450b09306630b6a941ad32b07396c4ae08ead..19a75661f56fd55a94ca0924568cd640debcb838 100644 --- a/apt/manage_profile.in +++ b/apt/manage_profile.in @@ -36,20 +36,23 @@ use POSIX qw(setsid); # sub usage() { - print("Usage: manage_profile create [-s uuid] \n"); + print("Usage: manage_profile create [-s uuid | -c uuid] \n"); print("Usage: manage_profile update \n"); print("Usage: manage_profile publish \n"); print("Usage: manage_profile delete \n"); exit(-1); } -my $optlist = "ds:t:"; +my $optlist = "ds:t:c:"; my $debug = 0; my $update = 0; my $snap = 0; +my $copy = 0; +my $copyuuid; my $uuid; my $rspec; my $script; my $profile; +my $parent_profile; my $instance; my $aggregate; my $node_id; @@ -128,7 +131,11 @@ if (defined($options{"d"})) { } if (defined($options{"s"})) { $snap = 1; - $uuid = $options{"s"}; + $copyuuid = $options{"s"}; +} +if (defined($options{"c"})) { + $copy = 1; + $copyuuid = $options{"c"}; } if (defined($options{"t"})) { $webtask_id = $options{"t"}; @@ -345,9 +352,9 @@ if (defined($script) && $script ne "") { # sanity check to make sure there is just one node. # if ($snap) { - $instance = APT_Instance->Lookup($uuid); + $instance = APT_Instance->Lookup($copyuuid); if (!defined($instance)) { - fatal("Could not look up instance $uuid"); + fatal("Could not look up instance $copyuuid"); } if ($instance->status() ne "ready") { $errors{"error"} = "Instance must be in the ready state for cloning"; @@ -375,7 +382,15 @@ if ($snap) { $errors{"error"} = "$node_id is not at " . $aggregate->aggregate_urn(); UserError(); } + $parent_profile = $instance->Profile(); +} +elsif ($copy) { + $parent_profile = APT_Profile->Lookup($copyuuid); + if (!defined($parent_profile)) { + fatal("Could not look up copy profile $copyuuid"); + } } + if ($update) { $profile = APT_Profile->Lookup($uuid); if (!defined($profile)) { @@ -440,14 +455,12 @@ if ($update) { else { my $usererror; - $profile = APT_Profile->Lookup($new_args{"pid"}, $new_args{"name"}); - if (defined($profile)) { + if (defined(APT_Profile->Lookup($new_args{"pid"}, $new_args{"name"}))) { $errors{"profile_name"} = "Already in use"; UserError(); } - $profile = - APT_Profile->Create($profile, $project, - $this_user, \%new_args, \$usererror); + $profile = APT_Profile->Create($parent_profile, $project, + $this_user, \%new_args, \$usererror); if (!defined($profile)) { if (defined($usererror)) { $errors{"profile_name"} = $usererror; @@ -683,11 +696,8 @@ sub DeleteProfile($) fatal("Could not delete profile version"); } else { - # Purge it. At some point we want to save them. - $profile->Delete(1) == 0 or + $profile->Delete(0) == 0 or fatal("Could not delete profile"); - # Kill off object webtask, since we do not do that when purging. - WebTask->DeleteByObject($profile->uuid()); } # No need for this anonymous webtask anymore. $webtask->Delete() @@ -750,8 +760,6 @@ sub CanDelete($) my $project = Project->Lookup($profile->pid_idx()); return 0 if (!defined($project)); - return 0 - if (!$profile->IsHead()); return 1 if ($this_user->IsAdmin() || $this_user->stud()); return 1 diff --git a/sql/database-create.sql b/sql/database-create.sql index 8a143ad1dd7e50b671e09a7ffeefe97767db9886..49c85124045375586deca678c286c6f17d6d41f9 100644 --- a/sql/database-create.sql +++ b/sql/database-create.sql @@ -247,7 +247,7 @@ CREATE TABLE `apt_instances` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -- --- Table structure for table `apt_profile_versions` +-- Table structure for table `apt_profile_favorites` -- DROP TABLE IF EXISTS `apt_profile_favorites`; @@ -284,7 +284,6 @@ CREATE TABLE `apt_profile_versions` ( `script` mediumtext, `paramdefs` mediumtext, PRIMARY KEY (`profileid`,`version`), - UNIQUE KEY `pidname` (`pid_idx`,`name`,`version`), UNIQUE KEY `uuid` (`uuid`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; diff --git a/sql/updates/4/487 b/sql/updates/4/487 new file mode 100644 index 0000000000000000000000000000000000000000..9b644764a490673c2d6aa0922b27995407ae3d3f --- /dev/null +++ b/sql/updates/4/487 @@ -0,0 +1,16 @@ +use strict; +use libdb; + +sub DoUpdate($$$) +{ + my ($dbhandle, $dbname, $version) = @_; + + if (DBKeyExists("apt_profile_versions", "pidname")) { + DBQueryFatal("alter table apt_profile_versions drop key `pidname`"); + } + return 0; +} + +# Local Variables: +# mode:perl +# End: diff --git a/www/aptui/instantiate.php b/www/aptui/instantiate.php index ec5f8b38ec6e8e02d127732afc4595c225be2541..64802f290c5535ba3251d3346e20c299ff0ed281 100644 --- a/www/aptui/instantiate.php +++ b/www/aptui/instantiate.php @@ -132,7 +132,7 @@ if (isset($profile)) { SPITUSERERROR("Illegal profile for guest user: $profile"); exit(); } - if (! $obj) { + if (! $obj || $obj->deleted()) { SPITUSERERROR("No such profile: $profile"); exit(); } diff --git a/www/aptui/js/manage_profile.js b/www/aptui/js/manage_profile.js index 29b2ee841be27c1af9f096763bc209b428b43f9e..0ac80196fea3429a7130adb39c91b1d5fddb2325 100644 --- a/www/aptui/js/manage_profile.js +++ b/www/aptui/js/manage_profile.js @@ -108,6 +108,7 @@ function (_, sup, filesize, JacksEditor, ShowImagingModal, moment, ppstart, history: window.HISTORY, activity: window.ACTIVITY, manual: window.MANUAL, + copyuuid: (window.COPYUUID || null), snapuuid: (window.SNAPUUID || null), general_error: (errors.error || ''), iscloud: window.ISCLOUD, diff --git a/www/aptui/manage_profile.php b/www/aptui/manage_profile.php index 89d397f0e8a1a3f2a8fea046cc2ed3cc9dfc4355..596e95f31c8964bb7297f10225525781eea91c7c 100644 --- a/www/aptui/manage_profile.php +++ b/www/aptui/manage_profile.php @@ -47,6 +47,7 @@ $this_idx = $this_user->uid_idx(); $optargs = OptionalPageArguments("create", PAGEARG_STRING, "action", PAGEARG_STRING, "uuid", PAGEARG_STRING, + "copyuuid", PAGEARG_STRING, "snapuuid", PAGEARG_STRING, "finished", PAGEARG_BOOLEAN, "formfields", PAGEARG_ARRAY); @@ -57,7 +58,7 @@ $optargs = OptionalPageArguments("create", PAGEARG_STRING, function SPITFORM($formfields, $errors) { global $this_user, $projlist, $action, $profile, $DEFAULT_AGGREGATE; - global $notifyupdate, $notifyclone, $snapuuid, $am_array, $ISCLOUD; + global $notifyupdate, $notifyclone, $copyuuid, $snapuuid, $am_array, $ISCLOUD; global $version_array, $WITHPUBLISHING; $viewing = 0; $candelete = 0; @@ -194,11 +195,14 @@ function SPITFORM($formfields, $errors) echo " window.ISPPPROFILE = $ispp;\n"; echo " window.WITHPUBLISHING = $WITHPUBLISHING;\n"; if ($ISCLOUD) { - echo " window.ISCLOUD = true;"; + echo " window.ISCLOUD = true;\n"; } else { - echo " window.ISCLOUD = false;"; + echo " window.ISCLOUD = false;\n"; } - if (isset($snapuuid)) { + if (isset($copyuuid)) { + echo " window.COPYUUID = '$copyuuid';\n"; + } + elseif (isset($snapuuid)) { echo " window.SNAPUUID = '$snapuuid';\n"; } echo "\n"; @@ -231,6 +235,9 @@ if (isset($action) && ($action == "edit" || $action == "copy")) { else if ($profile->locked()) { SPITUSERERROR("Profile is currently locked!"); } + else if ($profile->deleted()) { + SPITUSERERROR("Profile is has been deleted!"); + } if ($action == "edit") { if ($this_idx != $profile->creator_idx() && !ISADMIN()) { SPITUSERERROR("Not enough permission!"); @@ -246,13 +253,20 @@ if (isset($action) && ($action == "edit" || $action == "copy")) { $profileid = $profile->profileid(); $query_result = - DBQueryFatal("select v.*,DATE(v.created) as created ". + DBQueryFatal("select v.*,DATE(v.created) as created, ". + " vp.uuid as parent_uuid ". " from apt_profile_versions as v ". - "where v.profileid='$profileid' ". + "left join apt_profile_versions as vp on ". + " v.parent_profileid is not null and ". + " vp.profileid=v.parent_profileid and ". + " vp.version=v.parent_version ". + "where v.profileid='$profileid' and ". + " v.deleted is null ". "order by v.created desc"); while ($row = mysql_fetch_array($query_result)) { $uuid = $row["uuid"]; + $puuid = $row["parent_uuid"]; $version = $row["version"]; $pversion= $row["parent_version"]; $created = $row["created"]; @@ -261,9 +275,6 @@ if (isset($action) && ($action == "edit" || $action == "copy")) { $desc = ''; $obj = array(); - if ($version == 0) { - $pversion = " "; - } if (!$published) { $published = " "; } @@ -281,6 +292,7 @@ if (isset($action) && ($action == "edit" || $action == "copy")) { $obj["description"] = $desc; $obj["created"] = $created; $obj["published"] = $published; + $obj["parent_uuid"] = $puuid; $obj["parent_version"] = $pversion; $version_array[] = $obj; @@ -331,6 +343,10 @@ if (! isset($create)) { SPITUSERERROR("Not allowed to access this profile!"); } } + elseif ($action == "copy") { + # Pass this along through the new create page. + $copyuuid = $profile->uuid(); + } $defaults["profile_rspec"] = $profile->rspec(); $defaults["profile_who"] = "private"; if ($profile->script() && $profile->script() != "") { @@ -471,7 +487,7 @@ else { } # -# Sanity check the snapuuid argument. +# Sanity check the snapuuid argument when doing a clone. # if (isset($action) && $action == "clone") { if (!isset($snapuuid) || $snapuuid == "" || !IsValidUUID($snapuuid)) { @@ -598,8 +614,11 @@ if ($action == "edit") { } else { $command .= " create -t $webtask_id "; - if (isset($snapuuid)) { - $command .= " -s " . escapeshellarg($snapuuid); + if (isset($copyuuid)) { + $command .= "-c " . escapeshellarg($copyuuid); + } + elseif (isset($snapuuid)) { + $command .= "-s " . escapeshellarg($snapuuid); } } $command .= " $xmlname"; @@ -626,6 +645,7 @@ if ($retval) { } } } + $webtask->Delete(); } unlink($xmlname); if (count($errors)) { diff --git a/www/aptui/profile-history.php b/www/aptui/profile-history.php index 280cbc170da7f18f07d7bcfc08b0bd882dcf00d9..b53110935cb4ff92769407afe8df5dbdb0c1ca3d 100644 --- a/www/aptui/profile-history.php +++ b/www/aptui/profile-history.php @@ -52,14 +52,20 @@ $profileid = $profile->profileid(); $profiles = array(); $query_result = - DBQueryFatal("select v.*,DATE(v.created) as created ". + DBQueryFatal("select v.*,DATE(v.created) as created,vp.uuid as parent_uuid ". " from apt_profile_versions as v ". - "where v.profileid='$profileid' ". + "left join apt_profile_versions as vp on ". + " v.parent_profileid is not null and ". + " vp.profileid=v.parent_profileid and ". + " vp.version=v.parent_version ". + "where v.profileid='$profileid' and v.deleted is null ". "order by v.created desc"); while ($row = mysql_fetch_array($query_result)) { $idx = $row["profileid"]; + $pidx = $row["parent_profileid"]; $uuid = $row["uuid"]; + $puuid = $row["parent_uuid"]; $version = $row["version"]; $pversion= $row["parent_version"]; $name = $row["name"]; @@ -70,9 +76,6 @@ while ($row = mysql_fetch_array($query_result)) { $rspec = $row["rspec"]; $desc = ''; - if ($version == 0) { - $pversion = " "; - } if (!$published) { $published = " "; } @@ -89,6 +92,7 @@ while ($row = mysql_fetch_array($query_result)) { $profile["description"] = $desc; $profile["created"] = $created; $profile["published"] = $published; + $profile["parent_uuid"] = $puuid; $profile["parent_version"] = $pversion; $profiles[] = $profile; diff --git a/www/aptui/profile_defs.php b/www/aptui/profile_defs.php index e33154abb87053e0751a0f71a421a3edf19b63a6..6bb27d6e010712e2fb79afe00f742f4d5bdb28c3 100644 --- a/www/aptui/profile_defs.php +++ b/www/aptui/profile_defs.php @@ -285,7 +285,7 @@ class Profile $query_result = DBQueryWarn("select max(version) from apt_profile_versions ". - "where profileid='$profileid'"); + "where profileid='$profileid' and deleted is null"); if (!$query_result || !mysql_num_rows($query_result)) { return -1; } diff --git a/www/aptui/template/manage-profile.html b/www/aptui/template/manage-profile.html index 085c449646c7cbc0e31cbbd587a1c44732d80b01..462adb61ec3cd98ab494338be7caeb387e37f45a 100644 --- a/www/aptui/template/manage-profile.html +++ b/www/aptui/template/manage-profile.html @@ -120,6 +120,9 @@ role="alert">
Update Successful!
+ <% if (copyuuid) { %> + + <% } %> <% if (snapuuid) { %> <% } %> @@ -627,8 +630,17 @@ <%- profile.published %> <% } %> - - <%- profile.parent_version %> + <% if (profile.parent_uuid) { %> + <% if (profile.version == 0) { %> + + <%- profile.parent_version %> + <% } else { %> + + <%- profile.parent_version %> + <% } %> + <% } else { %> +   + <% } %> <% }); %> diff --git a/www/aptui/template/profile-history.html b/www/aptui/template/profile-history.html index 750b5d0f71c47775e6624a8a0104ed0bffc5d9f7..1ea3a983a8d6dc416feb1f6a40b79f1a9ee311db 100644 --- a/www/aptui/template/profile-history.html +++ b/www/aptui/template/profile-history.html @@ -30,8 +30,17 @@ <%- profile.published %> <% } %> - - <%- profile.parent_version %> + <% if (profile.parent_uuid) { %> + <% if (profile.version == 0) { %> + + <%- profile.parent_version %> + <% } else { %> + + <%- profile.parent_version %> + <% } %> + <% } else { %> +   + <% } %> <% }); %>