Skip to content
This repository was archived by the owner on Nov 25, 2020. It is now read-only.

Commit 0510045

Browse files
committed
JS UI: handle Prompt exception and dialog.
1 parent 2a90fa2 commit 0510045

File tree

9 files changed

+247
-290
lines changed

9 files changed

+247
-290
lines changed
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<?php
2+
/*
3+
* Copyright 2007-2015 Abstrium <contact (at) pydio.com>
4+
* This file is part of Pydio.
5+
*
6+
* Pydio is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* Pydio is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU Affero General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Affero General Public License
17+
* along with Pydio. If not, see <http://www.gnu.org/licenses/>.
18+
*
19+
* The latest code can be found at <https://pydio.com>.
20+
*/
21+
namespace Pydio\Core\Http\Middleware;
22+
23+
use Psr\Http\Message\ResponseInterface;
24+
use Psr\Http\Message\ServerRequestInterface;
25+
use Pydio\Auth\Core\MemorySafe;
26+
use Pydio\Core\Exception\PydioException;
27+
28+
use Pydio\Core\Exception\PydioPromptException;
29+
use Pydio\Core\Exception\WorkspaceAuthRequired;
30+
use Pydio\Core\Http\Server;
31+
use Pydio\Core\Model\ContextInterface;
32+
use Pydio\Core\Services\SessionService;
33+
use Pydio\Core\Utils\Vars\StringHelper;
34+
35+
defined('AJXP_EXEC') or die('Access not allowed');
36+
37+
/**
38+
* Class WorkspaceAuthMiddleware
39+
* PSR7 Middleware that handle Workspace "prompted" authentication
40+
* @package Pydio\Core\Http\Middleware
41+
*/
42+
class WorkspaceAuthMiddleware
43+
{
44+
45+
const RESUBMIT_AUTH_VARS = "PYDIO_WORKSPACE_AUTH_VARS";
46+
const RESUBMIT_AUTH_KEY = "PYDIO_WORKSPACE_AUTH_RESUBMIT";
47+
const RESUBMIT_AUTH_COUNT = "PYDIO_WORKSPACE_AUTH_RESUBMIT_COUNT";
48+
49+
const FORM_RESUBMIT_KEY = "workspace-auth-submission-id";
50+
const FORM_RESUBMIT_PASS = "workspace-auth-password";
51+
52+
/**
53+
* @param ServerRequestInterface $requestInterface
54+
* @param ResponseInterface $responseInterface
55+
* @return ResponseInterface
56+
* @param callable|null $next
57+
* @throws PydioException
58+
*/
59+
public static function handleRequest(ServerRequestInterface $requestInterface, ResponseInterface $responseInterface, callable $next = null){
60+
61+
$vars = $requestInterface->getParsedBody();
62+
if(isSet($vars[self::FORM_RESUBMIT_KEY]) && SessionService::has(self::RESUBMIT_AUTH_VARS."-".$vars[self::FORM_RESUBMIT_KEY]) && !empty($vars[self::FORM_RESUBMIT_PASS])){
63+
$submittedId = $vars[self::FORM_RESUBMIT_KEY];
64+
// Count a max number of submission?
65+
66+
/** @var ContextInterface $ctx */
67+
$ctx = $requestInterface->getAttribute("ctx");
68+
if($ctx->hasUser()){
69+
$password = $vars[self::FORM_RESUBMIT_PASS];
70+
MemorySafe::storeCredentials($ctx->getUser()->getId(), $password);
71+
}
72+
73+
$newVars = SessionService::fetch(self::RESUBMIT_AUTH_VARS."-".$submittedId);
74+
SessionService::delete(self::RESUBMIT_AUTH_VARS."-".$submittedId);
75+
76+
$vars = $newVars;
77+
$requestInterface = $requestInterface->withParsedBody($newVars);
78+
if(isSet($vars["get_action"])){
79+
$requestInterface = $requestInterface->withAttribute("action", $vars["get_action"]);
80+
}
81+
}
82+
83+
try{
84+
85+
return Server::callNextMiddleWare($requestInterface, $responseInterface, $next);
86+
87+
} catch (WorkspaceAuthRequired $ex){
88+
89+
// Generate a random ID.
90+
$submissionId = StringHelper::generateRandomString(24);
91+
SessionService::save(self::RESUBMIT_AUTH_VARS."-".$submissionId, $vars);
92+
$parameters = [self::FORM_RESUBMIT_KEY => $submissionId];
93+
$postSubmitCallback = "";
94+
if($requestInterface->getAttribute("action") === "switch_repository"){
95+
$postSubmitCallback = "ajaxplorer.loadXmlRegistry();";
96+
}
97+
// Will throw a prompt exception with all current values
98+
return PydioPromptException::promptForWorkspaceCredentials($parameters, self::FORM_RESUBMIT_PASS, $postSubmitCallback);
99+
100+
}
101+
102+
103+
}
104+
105+
}

core/src/plugins/gui.ajax/res/js/es6/http/PydioApi.es6

Lines changed: 8 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ class PydioApi{
382382

383383
for(var i=0; i<childs.length;i++)
384384
{
385-
if(childs[i].tagName == "message")
385+
if(childs[i].tagName === "message")
386386
{
387387
var messageTxt = "No message";
388388
if(childs[i].firstChild) messageTxt = childs[i].firstChild.nodeValue;
@@ -393,43 +393,13 @@ class PydioApi{
393393
Logger.log(messageTxt);
394394
}
395395

396-
}else if(childs[i].tagName == "prompt"){
397-
398-
var message = XMLUtils.XPathSelectSingleNode(childs[i], "message").firstChild.nodeValue;
399-
var jsonData = XMLUtils.XPathSelectSingleNode(childs[i], "data").firstChild.nodeValue;
400-
var json = JSON.parse(jsonData);
401-
// TODO: DELEGATE TO UI
402-
/*
403-
var dialogContent = new Element('div').update(json["DIALOG"]);
404-
modal.showSimpleModal(modal.messageBox?modal.messageBox:document.body, dialogContent, function(){
405-
// ok callback;
406-
if(json["OK"]["GET_FIELDS"]){
407-
var params = $H();
408-
$A(json["OK"]["GET_FIELDS"]).each(function(fName){
409-
params.set(fName, dialogContent.down('input[name="'+fName+'"]').getValue());
410-
});
411-
var conn = new Connexion();
412-
conn.setParameters(params);
413-
if(json["OK"]["EVAL"]){
414-
conn.onComplete = function(){
415-
eval(json["OK"]["EVAL"]);
416-
};
417-
}
418-
conn.sendAsync();
419-
}else{
420-
if(json["OK"]["EVAL"]){
421-
eval(json["OK"]["EVAL"]);
422-
}
423-
}
424-
return true;
425-
}, function(){
426-
// cancel callback
427-
if(json["CANCEL"]["EVAL"]){
428-
eval(json["CANCEL"]["EVAL"]);
429-
}
430-
return true;
431-
});
432-
*/
396+
}else if(childs[i].tagName === "prompt"){
397+
398+
if(pydio && pydio.UI && pydio.UI.openPromptDialog){
399+
let jsonData = XMLUtils.XPathSelectSingleNode(childs[i], "data").firstChild.nodeValue;
400+
pydio.UI.openPromptDialog(JSON.parse(jsonData));
401+
}
402+
// Interrupt further process
433403
throw new Error();
434404

435405
}

core/src/plugins/gui.ajax/res/js/es6/model/RemoteNodeProvider.es6

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,14 @@ class RemoteNodeProvider{
217217
}
218218
}
219219

220+
// CHECK FOR AUTH PROMPT REQUIRED
221+
var authNode = XMLUtils.XPathSelectSingleNode(rootNode, "prompt");
222+
if(authNode && pydio && pydio.UI && pydio.UI.openPromptDialog){
223+
let jsonData = XMLUtils.XPathSelectSingleNode(authNode, "data").firstChild.nodeValue;
224+
pydio.UI.openPromptDialog(JSON.parse(jsonData));
225+
throw new Error();
226+
}
227+
220228
// CHECK FOR PAGINATION DATA
221229
var paginationNode = XMLUtils.XPathSelectSingleNode(rootNode, "pagination");
222230
if(paginationNode){

core/src/plugins/gui.ajax/res/js/ui/prototype/class.Modal.js

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -340,11 +340,21 @@ Class.create("Modal", {
340340
this.showDialogForm('', editorData.formId, loadFunc, null, null, true, true);
341341
},
342342

343-
showSimpleModal : function(element, content, okCallback, cancelCallback, position){
344-
var box = new Element("div", {className:"dialogBox css_boxshadow", style:'display:block;'});
343+
showSimpleModal : function(element, content, okCallback, cancelCallback, position, additionalClass, skipEffect){
344+
if(!additionalClass) additionalClass = '';
345+
var box = new Element("div", {className:"dialogBox css_boxshadow" + ' ' + additionalClass, style:'display:block;'});
345346
box.insert(content);
346347
content.addClassName("dialogContent");
347-
addLightboxMarkupToElement(element);
348+
var overlay;
349+
if(element === document.body){
350+
overlay = $(document.body).down('#overlay');
351+
overlay.setStyle({display:'block'});
352+
pydio.UI.disableShortcuts();
353+
}else{
354+
addLightboxMarkupToElement(element);
355+
overlay = element.down("#element_overlay");
356+
overlay.setStyle({opacity:0.9});
357+
}
348358
if(Prototype.Browser.IE && !Prototype.Browser.IE10plus){
349359
$("all_forms").insert(box);
350360
var outBox = element.up(".dialogBox");
@@ -364,60 +374,62 @@ Class.create("Modal", {
364374
});
365375
}
366376
}else{
367-
$(element).down("#element_overlay").insert({after:box});
368-
$(element).down("#element_overlay").setStyle({opacity:0.9});
369-
if(element.up('div.dialogBox')){
370-
//Effect.BlindDown(box, {
371-
// duration:0.6,
372-
// transition:Effect.Transitions.sinoidal
373-
//});
374-
}
377+
overlay.insert({after:box});
375378
}
376379
this.currentLightBoxElement = $(element);
377380
this.currentLightBoxModal = box;
378381
this.addSubmitCancel(content, cancelCallback, (cancelCallback==null), position);
382+
383+
var finish = function(){
384+
content.down('div.dialogButtons').remove();
385+
box.remove();
386+
if(element !== document.body){
387+
overlay.setStyle({opacity:0});
388+
removeLightboxFromElement(element);
389+
}else{
390+
overlay.setStyle({display:null});
391+
pydio.UI.enableShortcuts();
392+
}
393+
this.currentLightBoxElement = null;
394+
this.currentLightBoxModal = null;
395+
}.bind(this);
396+
var finishWrapped = function(){
397+
if(skipEffect){
398+
finish();
399+
}else{
400+
Effect.BlindUp(box, {
401+
duration:0.4,
402+
afterFinish:finish
403+
});
404+
}
405+
};
406+
379407
content.down(".dialogButtons").select("input").each(function(button){
380408
if(((cancelCallback==null) && button.getAttribute("name") == "close") || button.getAttribute("name") == "ok"){
381409
button.observe("click", function(event){
382410
Event.stop(event);
383-
var res = okCallback();
384-
if(res){
385-
Effect.BlindUp(box, {
386-
duration:0.4,
387-
afterFinish:function(){
388-
content.down('div.dialogButtons').remove();
389-
$(element).down("#element_overlay").setStyle({opacity:0});
390-
box.remove();
391-
removeLightboxFromElement(element);
392-
this.currentLightBoxElement = null;
393-
this.currentLightBoxModal = null;
394-
}.bind(this)
395-
});
411+
if(okCallback()){
412+
finishWrapped();
396413
}
397414
}.bind(this));
398415
}else{
399416
button.stopObserving("click");
400417
button.observe("click", function(event){
401418
Event.stop(event);
402-
var res = cancelCallback();
403-
if(res){
404-
Effect.BlindUp(box, {
405-
duration:0.4,
406-
afterFinish:function(){
407-
content.down('div.dialogButtons').remove();
408-
if($(element).down("#element_overlay")) {
409-
$(element).down("#element_overlay").setStyle({opacity:0});
410-
}
411-
box.remove();
412-
removeLightboxFromElement(element);
413-
this.currentLightBoxElement = null;
414-
this.currentLightBoxModal = null;
415-
}.bind(this)
416-
});
419+
if(cancelCallback()){
420+
finishWrapped();
417421
}
418422
}.bind(this));
419423
}
420424
});
425+
content.select('input[type="password"],input[type="text"]').invoke("observe", "keydown", function(event){
426+
if(event.keyCode === Event.KEY_RETURN){
427+
Event.stop(event);
428+
if(okCallback()){
429+
finishWrapped();
430+
}
431+
}
432+
});
421433
},
422434

423435

core/src/plugins/gui.ajax/res/js/ui/prototype/class.PydioUI.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,38 @@ Class.create("PydioUI", {
771771

772772
enableAllKeyBindings : function(){
773773
this.blockNavigation = this.blockShortcuts = this.blockEditorShortcuts = false;
774+
},
775+
776+
openPromptDialog: function(json){
777+
var dialogContent = new Element('div').update(json["DIALOG"]);
778+
modal.showSimpleModal(document.body, dialogContent, function(){
779+
// ok callback;
780+
if(json["OK"]["GET_FIELDS"]){
781+
var params = $H();
782+
$A(json["OK"]["GET_FIELDS"]).each(function(fName){
783+
params.set(fName, dialogContent.down('input[name="'+fName+'"]').getValue());
784+
});
785+
var conn = new Connexion();
786+
conn.setParameters(params);
787+
if(json["OK"]["EVAL"]){
788+
conn.onComplete = function(){
789+
eval(json["OK"]["EVAL"]);
790+
};
791+
}
792+
conn.sendAsync();
793+
}else{
794+
if(json["OK"]["EVAL"]){
795+
eval(json["OK"]["EVAL"]);
796+
}
797+
}
798+
return true;
799+
}, function(){
800+
// cancel callback
801+
if(json["CANCEL"]["EVAL"]){
802+
eval(json["CANCEL"]["EVAL"]);
803+
}
804+
return true;
805+
}, 'bottom', 'simple-modal-auth-prompt', true);
774806
}
775807

776808
});

0 commit comments

Comments
 (0)