-
-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue 14 add from cms #62
Issue 14 add from cms #62
Conversation
To be clear, I'm going to step through manually testing before I would prefer that @rfay review at the code/test level to the degree that he can/feels comfortable with. |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added my full, manual review. Once @rfay reviews the test coverage and adds his feedback we can merge if you're ready @andrew-c-tran.
Going to note this as a blocker because this issue allows us to close the v0.1 review and move onto other PRs, branches, issues, etc. |
Tests added, ready for code review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a quick manual test.
- I love the new finder option, looks so much better.
- I started ddev-ui with no sites running, and it's just one big blank screen, with no prompts to do anything.
- I'm pretty sure that when I manually started a site, the big blank screen remained big and blank the first time I went through this, but trying it out a second time I ended up with a very attractive screen. (Note that the router display is no longer there on the bottom, is that intentional?)
- I removed the ~/.ddev/CMS to see what would happen. (Wasn't sure when the files were downloaded). That definitely didn't work out well. It results in a perpetual "Unzipping files" display. (Note that the "Create site" button remains active at this time.) Not sure if the whole thing is worth fixing, but ddev-ui certainly should be able to detect and handle an error of this type.
- I created a drupal8 site successfully. However, the approot is not what I'd expect. I told it to put a site by the name of junker99.1 in ~/workspace, so I'd expect it to have an approot of ~/workspace/junker99.1, but it's actually ~/workspace/junker99.1/drupal-8.4.3. I think to solution to this is just to untar without keeping the top directory.
- I note that there's no longer any option to remove a site.
The no-sites-running blank screen and the approot are certainly critical problems, along with the lack of error handling on unzipping, so some more work is needed on this. I haven't taken a look at the code yet.
…ot folder instead of target/wordpress(etc)
addressed untar error handling, as well as approot path, pushed and build succeeded. looking into how to communicate no running sites now. |
@rfay the grey screen of no sites running is easily detectable from the output of |
So @andrew-c-tran there's no reason not to have the "Add/Create Site" button when there are no sites running. That would make people feel more comfortable. And it should say somewhere "No sites are running". Otherwise, it just looks totally broken. Maybe "There are no sites running, create one!" |
Sure, we can definitely have just the add button, will have to figure out
some very clear messaging for no running sites as I can see someone who has
only used the UI wondering where their sites went. Even then, if they
didn't want to create a new site, how would one with no CLI experience (or
the knowledge that a CLI even exists for that matter) start a site?
On Dec 18, 2017 5:23 PM, "Randy Fay" <[email protected]> wrote:
So @andrew-c-tran <https://github.com/andrew-c-tran> there's no reason not
to have the "Add/Create Site" button when there are no sites running. That
would make people feel more comfortable. And it should say somewhere "No
sites are running". Otherwise, it just looks totally broken.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#62 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AIi5a3jVJ5bhssGRwBGBHvITDWIqHMj3ks5tBwIRgaJpZM4Q6g6r>
.
|
I think the (current) inability to create a site from within the ddev-ui is a serious problem, because people who want to try ddev-ui will be baffled at the start. |
|
I see the router monitoring has been reintroduced (and no sites running notification), and it often works. However, it doesn't work if you start ddev-ui with no sites running and then start some sites. It continues to insist forever that the router's not running and there are no sites.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't get a chance to look at the tests yet but wanted to finish this here. Lots of comments, some that you can do things about now, others that you probably can't.
The cold-start with no sites now looks better, thanks! At least you can tell there's something to do.
- Router status and "no sites" doesn't work right if you start with no sites and then start a site. It continues to say there aren't any sites.
- The security implications of your use of sudo are off the chart, that needs to be rethought carefully.
- Windows doesn't seem to be handled or tested at this point, and I'm pretty sure we're aiming for windows to work all the time still right?
- Please add function headers to all code, not just the new stuff in this PR. (ddev-shell.sh and ui.js don't have anything).
- Markup embedded in js with explicit style= doesn't seem right. Why isn't CSS being used for that stuff?
index.html
Outdated
@@ -50,6 +52,29 @@ <h2 class="modal-title" id="modalLabel">Modal title</h2> | |||
</div> | |||
</div> | |||
|
|||
<div class="modal fade" id="addOptionsDialog" tabindex="-1" role="dialog" aria-labelledby="addOptionsDialog" aria-hidden="true"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I would expect this to be in the js application and not in the index.html?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed modals and created a createModal template that programmatically generates and injects modals into the DOM.
function validateCMSType(cmsType){ | ||
var promise = new Promise(function(resolve, reject){ | ||
var cmsString = cmsType.toLowerCase(); | ||
if(cmsString === 'wordpress' || cmsString === 'drupal7' || cmsString === 'drupal8'){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type of code is of course what we're ripping out of ddev, because we're going to support a number of CMSs. This would be a lot nicer as a check against an array of possible types though (instead of inline if statement), probably configured globally. I don't think there's any need to do that yet, but I hate to see us have to do all the work we're doing now in ddev to generalize this. So I'm just giving warning, but probably nothing needs to be done here yet. Opened #67 for this.
targetCMS = 'wordpress'; | ||
break; | ||
case 'drupal7': | ||
targetCMS = 'drupal-7'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Life would be a lot better if cmsType and targetCMS used the same semantics. Or use an associative array to map instead of a switch. No action needed here, but it would really be a lot nicer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So what I was saying here is, if possible, use the same words for targetCMS as you do for cmsType. Drop the drupal-7 stuff and just use drupal7.
js/cms-installer.js
Outdated
*/ | ||
function unpackCMSTarball(tarballPath, outputPath) { | ||
var promise = new Promise(function(resolve,reject){ | ||
exec('mkdir '+outputPath, function(err, stdout, stderr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't there a better way to create a directory than execing mkdir? Unless I'm misunderstanding, this should be done another way. Does Windows mkdir even work the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can subsitute mkdir with node's fs.mkdir that will use a platform specific call. Good catch. node-tar does require an existing, writable path though, so I do believe creating the directory via fs.mkdir is the only option here.
js/cms-installer.js
Outdated
* @param siteName {string} name of site to create hosts file entry | ||
* @return {promise} resolves with a successful terminal output from ddev hostname, rejects with ddev error output | ||
*/ | ||
function updateHostsFile(siteName) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sure doesn't seem to be a very useful function. Why not just call ddevShell.hostname()? It also doesn't return a promise does it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, ddevShell.hostname() does indeed return a promise, and there is no reason for this wrapper. removed.
js/ui.js
Outdated
</div> | ||
<div class="card-body"> | ||
<a href="#"> | ||
<div style="height: 155px; line-height: 155px; font-size: 75px;" > |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be in the css instead of use style here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all inline CSS removed and pulled into stylesheet
js/ui.js
Outdated
</div> | ||
</a> | ||
</div> | ||
<div style="height:73px;" class="card-footer"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In css instead of in style=?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all inline CSS removed and pulled into stylesheet
js/ui.js
Outdated
var options = { | ||
name: 'DDEV UI', | ||
}; | ||
var command = 'ls'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can't possibly work on Windows, right? Since there's no ls command?
You're also execing 'ls' with sudo, without controlling the path. So all I have to do is write a script called ls that does rm -rf / and it will destroy the machine? This needs to be seriously rethought.
I'm pretty sure that ddev needs to be accessed always with a full configured path. If we have a reason to trust ddev, then ddev version
or just ddev
would be a reasonable command here (with full path of trusted ddev). But just assuming a random command like ls isn't going to be very good.
js/ui.js
Outdated
$('#distroModal').modal(); | ||
}); | ||
$(document).on('click', '.start-from-directory', function () { | ||
alert('WIP...'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs to have something real right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a fragment, should not have been here and was removed
main.js
Outdated
@@ -25,7 +25,7 @@ app.on('ready', function () { | |||
mainWindow.loadURL('file://' + __dirname + '/index.html'); | |||
|
|||
// Open the DevTools. | |||
mainWindow.openDevTools(); // requires a height 410px | |||
// mainWindow.openDevTools(); // requires a height 410px |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's get this controlled with a different technique (global config?) instead of commenting and uncommenting code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added detection if running in development mode (via electron .
in cli) vs production (compiled/built binary) and will launch devtools if in dev mode.
I had a chance to review this with @andrew-c-tran this morning where we discussed this and other ddev-ui priorities and the overall roadmap. The rough draft notes can be found here https://docs.google.com/document/d/1Xy0ag25AA9NqmH6MhLIph5abcp9i_YD5mG7F5RS14jQ/edit#. I think these are the most pertinent items to get this issue to the finish line while moving other issues to an appropriate area.
I concur there are some open issues on design/colors/styles, but I want to make sure we're scoping properly and we will prioritize this in v0.3 given that much of the functionality for v0.1-v0.2 is in flight and I'd like to reduce WIP as much as possible with the hope that we have a more structured cadence post v0.3. BTW, if my summary is wrong or missing any key items, I'm happy to have a conversation. However, if there are no objections, I'd like to keep this as the path forward. |
…x to dynamically generated, guarded sudo
…etection for devtools
…e easier for testing
@rfay 's comments addressed, cleanup of code, and tested (including priv escalation) in windows 10 pro and ubuntu Ubuntu 16.04.3 LTS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some things for you to work on while I get to the code review. The first is highly critical IMO.
- If you try to create a site in a directory that already exists, It will spin in the "unzipping files" forever, the error is never notified. Please improve error handling on this process. This is a critical error, and I would imagine there are other ways to demonstrate it. We need to catch errors like this. (This situation isn't even an error, there's nothing really wrong with creating a site in an empty existing directory.) You get the same result if the chosen directory has permissions that don't allow creation of a subdirectory. For example, mkdir /tmp/j; chmod 444 /tmp/j" then use /tmp/j as the directory and junker99 as the sitename.
- I see the code still has
Start Process Initiated. It may take a few seconds for the new site card to appear
- Please improve that as our users don't know what a "site card" is. Maybe just "site" would do the job, drop "card". - The errors "hostname cannot be blank" and "hostname is invalid" should read "Project name cannot be blank", etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made several smaller comments; can't finish the code today. I got down to about #62 (comment), can start there Tuesday.
* @returns {string} - markup for a boostrap modal | ||
*/ | ||
function createModal(id, title, body, footer) { | ||
var markup = `<div class="modal fade" id="`+id+`" tabindex="-1" role="dialog" aria-labelledby="`+id+`Label" aria-hidden="true"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wish this was already jsx.
js/cms-installer.js
Outdated
$('.loading-overlay').css('display', displayType); | ||
} | ||
|
||
function showErrorScreen(display, error='Something Went Wrong'){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you were intending (I think) to do function headers everywhere. These can use them IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, i missed those two. Minor refactor to make them more consistent with one another, and added JSDOC headers
js/cms-installer.js
Outdated
if(hostnameRegex.test(hostname.toLowerCase())){ | ||
resolve(true); | ||
} else { | ||
var error = hostname ? 'Hostname is Invalid.' : 'Hostname Cannot Be Blank.'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we don't expose this to them as a hostname, but rather as "project", this should be adjusted to match what we're presenting to them in the gui.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated to "project name" vs "hostname"
js/cms-installer.js
Outdated
if(cmsString === 'wordpress' || cmsString === 'drupal7' || cmsString === 'drupal8'){ | ||
resolve(true); | ||
} else { | ||
var error = cmsType ? 'CMS Type is Invalid.' : 'CMS Type Cannot Be Blank.'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is kind of an ugly message "CMS type cannot be blank" as they didn't type anything. Better "Please select a CMS type".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated to "please select a cms type"
targetCMS = 'wordpress'; | ||
break; | ||
case 'drupal7': | ||
targetCMS = 'drupal-7'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So what I was saying here is, if possible, use the same words for targetCMS as you do for cmsType. Drop the drupal-7 stuff and just use drupal7.
js/cms-installer.js
Outdated
resolve(cmsPath + '/' + fileName); | ||
} | ||
}); | ||
reject('CMS tarball not found'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"CMS archive not found" is friendlier.". I'd say also give a mention of where it was looking for the tarball, because if we have a user with this problem we'll be able to help them better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see below
js/cms-installer.js
Outdated
}); | ||
reject('CMS tarball not found'); | ||
}).catch(function(){ | ||
reject('CMS tarball not found in `~/.ddev/CMS`. Restarting the UI will attempt to redownload these files.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This reject verbiage doesn't happen any more does it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah good catch (pun intended). the catch never fires in this case, i've removed it and changed the reject message above to "CMS archive not found in ~/.ddev/CMS
. Restarting the UI will attempt to redownload these files."
js/cms-installer.js
Outdated
* @param targetFolder {string} target folder to extract to | ||
* @return {promise} resolves with path to new site docroot, rejects with error returned from any failed called function | ||
*/ | ||
function createFiles(siteName, cmsType, cmsPath, targetFolder){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like a pretty wimpy function name given the job it performs. Improving it will improve readability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
definitely understated it's functionality. i've made a shot at updating it to be more accurate
function addCMS(name, type, targetPath) { | ||
var cmsPath = "~/.ddev/CMS"; | ||
var workingPath = cmsPath; | ||
cmsPath = cmsPath.replace('~', os.homedir()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you have to do this more than one place? It should probably be a global utility function. We sure have to do it a lot more than once in ddev.
.then((stdout) => { | ||
if(stdout.toString().indexOf('Starting environment') != -1){ | ||
resetAddModal(); | ||
alert('Start Process Initiated. It may take a few seconds for the new site to appear on your dashboard.'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like the new verbiage.
showLoadingScreen(true,'Updating Hosts File'); | ||
return ddevShell.hostname(name); | ||
}) | ||
.then(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole section works pretty well. Not sure about the modal dialog at the end, but that will be talked about down the line.
resetAddModal(); | ||
alert('In order to add a new site, DDEV requires elevated permissions to modify your Hosts file. You may be prompted for your username and password to continue.'); | ||
var command = 'version'; | ||
ddevShell.sudo(command) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sudo-ing ddev version
is pretty safe, but still a bit odd. I assume you're trying to get the sudo out of the way and hoping it won't be needed for ddev hostname
. I'm not sure this needs to be done here as opposed to later when we know the sitename.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ddev version
is the only command allowed to initiate a permissions request dialog, and yes it is to get sudo out of the way as well as ensuring that the add flow can actually finish before having the user go through and select a CMS, directory, unpack it all, only to find it fails during hostname setup for some sudo reason. It's super benign and there's no risk in running it multiple times in succession if a user should open and cancel out of the add site flow multiple times in succession. ddev hostname
then inherits sudo from this as you guessed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thinking about this further, perhaps we should also allow ddev hostname
to prompt in the event a user doesn't have tty_tickets enabled
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're assuming that sudo is set up to have a timeout like a period of time where pass won't be required. This is not necessarily the case. Sudo is often set up to always require password.
But my question was really, why would you have a whitelist that didn't include the most important command (hostname)? And if it doesn't include that, is it working at all?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was under the assumption that tty_ticket timestamping would allow the end user a grace period in which they didn't have to re-enter their password? In documentation and some of my tests it appeared that on osx that grace is 5 minutes and on ubuntu it's 15 by default. I know this is something that can be changed, though, and perhaps it's unwise to assume it's enabled by default on everyone's machine.
The intention for the whitelist was to catch non-intended escalation requests, and to fail out if a sudo dialog flow was started from any other entry point. We can filter all commands through this if that's the end goal. In hindsight, that's probably the better route, to corral every command through this screen, and not just the entry points
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, i see, the whitelist can and should be abstracted to a higher level and cut off the sudo library in it's entirety, will open a pull and do that now
alert(err); | ||
}); | ||
}); | ||
$(document).on('click', '.start-from-template', function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking forward to React handling for this stuff.
*/ | ||
const sudo = (command, promptOptions = {name: 'DDEV UI'}) => { | ||
var bannedCharacters = [';','|','&']; | ||
var whitelistedCommands = ['version']; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't hostname have to be whitelisted for this to work? What's up with that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, dangit, i got so ahead of myself looking forward that i completely missed what you were actually saying. I see now, and You're right, will address sudo in a much more thoroughly tested and protected way and address a flow issue relevant to both .1 and .2
js/ddev-shell.js
Outdated
@@ -58,7 +59,12 @@ const list = () => { | |||
var promise = new Promise((resolve, reject) => { | |||
function getRaw(output) { | |||
var outputObject = JSON.parse(output); | |||
if(Array.isArray(outputObject.raw)){ | |||
if(outputObject.msg === 'There are no running ddev applications.') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking for info instead of array is probably ok. Would rather ddev do something saner. Not exactly sure how to pull that off. Opened ddev/ddev#588
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all the work on this! It looks better and is more robust than ever before.
I'm ok with this now, although I haven't tested on Linux or Windows.
Please take a look at these few comments, I think the whitelisting of sudo commands isn't working as expected?
The Problem/Issue/Bug:
As a user, I need to be able to create a new site from a base CMS image
How this PR Solves The Problem:
Allows user to select a base CMS (drupal 7, 8, or wordpress), define the name and path, and start it.
Manual Testing Instructions:
make build darwin
Related Issue Link(s):
#14