From eabc8dc41e1c2fc3a22f51cbcfac02e5de841351 Mon Sep 17 00:00:00 2001 From: Tim Robinson Date: Thu, 12 Feb 2015 13:10:26 +0000 Subject: [PATCH] Increasing ping timeout from 3000 to 5000 ms to see if it improves disconnects --- configs/client-default-local.js | 158 ++++++++++++++++++++++ plugins/c9.ide.login/login.css | 36 ++++++ plugins/c9.ide.login/login.js | 194 ++++++++++++++++++++++++++++ plugins/c9.login/legacy.js | 123 ------------------ plugins/c9.login/legacy_strategy.js | 73 ----------- plugins/c9.login/login.js | 135 ------------------- plugins/c9.login/strategy.js | 45 ------- plugins/c9.vfs.server/vfs.js | 2 +- 8 files changed, 389 insertions(+), 377 deletions(-) create mode 100644 configs/client-default-local.js create mode 100644 plugins/c9.ide.login/login.css create mode 100644 plugins/c9.ide.login/login.js delete mode 100644 plugins/c9.login/legacy.js delete mode 100644 plugins/c9.login/legacy_strategy.js delete mode 100644 plugins/c9.login/login.js delete mode 100644 plugins/c9.login/strategy.js diff --git a/configs/client-default-local.js b/configs/client-default-local.js new file mode 100644 index 00000000..b2ed60a1 --- /dev/null +++ b/configs/client-default-local.js @@ -0,0 +1,158 @@ +var join = require("path").join; + +module.exports = function(options) { + var config = require("./client-default")(options); + return module.exports.makeLocal(config, options); +}; + +module.exports.makeLocal = function(config, options) { + var c9Ws = options.remoteWorkspace; // true when opening c9 workspace as local + var root = options.workspaceDir; + + var nodeBin = options.nodeBin || ["node"]; + var settingDir = options.settingDir || options.installPath; + + if (!c9Ws) { + // Local version + options.local = true; + options.projectName = root.substr(root.lastIndexOf("/") + 1); + options.debug = 2; + options.env = "local"; + } + + for (var i = config.length - 1; i >= 0; i--) { + // if (config[i].packagePath == "plugins/c9.cli.bridge/bridge") + // config[i].port = 55556; + if (config[i].packagePath == "plugins/c9.ide.welcome/welcome" && !c9Ws) { + config[i].intro = + "Welcome to your brand new Cloud9. Use this welcome screen " + + "to tweak the look & feel of the Cloud9 user interface. " + + "If you prefer a more advanced IDE experience, you can choose " + + "to change the layout below. " + + "\n\n" + + "On the right you can find videos and documentation for Cloud9 " + + "IDE. Happy Coding!"; + } + // else if (config[i].packagePath == "plugins/c9.ide.login/login") { + // config.splice(i, 1); + // } + else if (config[i].packagePath == "plugins/c9.ide.run/run" && !c9Ws) { + config[i].runnerPath = join(settingDir, "/runners"); + } + else if (config[i].packagePath == "plugins/c9.ide.ui/menus") { + config[i].autoInit = false; + } + else if (config[i].packagePath == "plugins/c9.ide.save/autosave") { + config[i].slowChangeTimeout = 500; + } + else if (config[i].packagePath == "plugins/c9.ide.run.build/build" && !c9Ws) { + config[i].builderPath = join(settingDir, "/builders"); + } + else if (config[i].packagePath == "plugins/c9.ide.editors/metadata" && !c9Ws) { + config[i].path = join(settingDir, "/metadata"); + config[i].changeCheckInterval = 2000; + } + else if (config[i].packagePath == "plugins/c9.ide.feedback/feedback") { + config[i].screenshotSupport = false; + } + // else if (config[i].packagePath == "plugins/c9.ide.feedback/feedback") { + // config[i] = { + // packagePath : "plugins/c9.ide.help/help", + // staticPrefix : options.staticPrefix + "/plugins/c9.ide.help" + // }; + // } + + else if (config[i].packagePath == "plugins/c9.core/c9") { + config[i].local = true; + } + else if (config[i].packagePath == "plugins/c9.ide.clipboard/html5") + config[i].packagePath = "plugins/c9.ide.local/clipboard"; + else if (config[i].packagePath == "plugins/c9.ide.configuration/configure") + config[i].pathFromFavorite = true; + else if (config[i].packagePath == "plugins/c9.core/settings" && !c9Ws) { + // todo: Don't show console when opening a file? + // config[i].template = ; + config[i].projectConfigPath = join(settingDir, ""); + config[i].userConfigPath = join(settingDir, ""); + config[i].stateConfigPath = join(settingDir, ""); + } else if (config[i].packagePath == "plugins/c9.ide.log/log" && !c9Ws) { + config[i].source = "desktop"; + } else if (config[i].packagePath == "plugins/c9.ide.info/info" && c9Ws) { + config[i].packagePath = "plugins/c9.ide.local/info"; + } else if (config[i].packagePath == "plugins/c9.ide.ui/menus" && c9Ws) { + config[i].autoInit = false; + } else if (config[i].packagePath == "plugins/c9.ide.tree/tree") { + config[i].defaultExpanded = !config.hosted; + } + } + + // Add local modules + var includes = [{ + packagePath: "plugins/c9.ide.local/local", + options: options, + }, { + packagePath: "plugins/c9.ide.local/windowframe", + staticPrefix: options.staticPrefix + "/plugins/c9.ide.local" + }, { + packagePath: "plugins/c9.ide.local/update", + host: options.update && options.update.host || "localhost", // "update.c9.io", + port: options.update && options.update.port || "8888", // "443" + path: options.update && options.update.path, + protocol: options.update && options.update.protocol, + installPath: options.correctedInstallPath, + bashBin: options.bashBin, + nodeBin: nodeBin + }, { + packagePath: "plugins/c9.ide.local/projectmanager" + }, { + packagePath: "plugins/c9.ide.local/open" + }, { + packagePath: "plugins/c9.ide.local/nativemenus" + }, !c9Ws && { + packagePath: "plugins/c9.ide.local/info", + installPath: options.correctedInstallPath, + settingDir: settingDir, + cookie: options.user.cookie, + user: { + id: options.user.id, + name: options.user.name, + fullname: options.user.fullname, + email: options.user.email, + pubkey: options.user.pubkey + }, + project: { + id: options.project.id, + name: options.project.name, + contents: options.project.contents, + descr: options.project.descr + } + }].filter(Boolean); + + var excludes = c9Ws ? {} : { + "plugins/c9.ide.newresource/open": true, + "plugins/c9.ide.info/info": true, + // "plugins/c9.ide.login/login": true, + "plugins/c9.ide.collab/connect": true, + "plugins/c9.ide.collab/collab": true, + "plugins/c9.ide.collab/collabpanel": true, + "plugins/c9.ide.collab/workspace": true, + "plugins/c9.ide.collab/util": true, + "plugins/c9.ide.collab/ot/document": true, + "plugins/c9.ide.collab/cursor_layer": true, + "plugins/c9.ide.collab/author_layer": true, + "plugins/c9.ide.collab/timeslider/timeslider": true, + "plugins/c9.ide.notifications/notifications": true, + "plugins/c9.ide.collab/members/members_panel": true, + "plugins/c9.ide.collab/share/share": true, + "plugins/c9.ide.collab/members/members": true, + "plugins/c9.ide.collab/chat/chat": true, + "plugins/c9.ide.feedback/nps": true, + "plugins/c9.ide.download/download": true + }; + + config = config.concat(includes).filter(function (p) { + return !excludes[p] && !excludes[p.packagePath]; + }); + + return config; +}; diff --git a/plugins/c9.ide.login/login.css b/plugins/c9.ide.login/login.css new file mode 100644 index 00000000..3a5d245e --- /dev/null +++ b/plugins/c9.ide.login/login.css @@ -0,0 +1,36 @@ +.c9-menu-btn.titlebar{ + position: absolute; + z-index: 100000000; + right: 24px; + top: 1px; + height: 19px; +} + +.c9-menu-btn.titlebar:not(.c9-menu-btnDown){ + height: 18px; + border-bottom: 1px solid black; +} + +.fullscreen>.btnName{ + display: none; +} + +.btnName.c9-menu-btnIcon{ + text-indent: -2000px; + overflow: hidden; +} +.btnName{ + padding: @menu-name-button-padding; + margin-left: @menu-name-button-diff !important; +} +.btnName.c9-menu-btnmenuDown{ + margin-left: 0 !important; +} +.btnName .icon{ + background-size: @menu-name-button-icon-width @menu-name-button-icon-height !important; + top: @menu-name-button-icon-top !important; + left: @menu-name-button-icon-left !important; + width: @menu-name-button-icon-width; + height: @menu-name-button-icon-height; + border-radius: @menu-name-button-icon-border-radius; +} \ No newline at end of file diff --git a/plugins/c9.ide.login/login.js b/plugins/c9.ide.login/login.js new file mode 100644 index 00000000..817480a5 --- /dev/null +++ b/plugins/c9.ide.login/login.js @@ -0,0 +1,194 @@ +define(function(require, exports, module) { + main.consumes = [ + "Plugin", "ui", "menus", "info", "layout", "http", "util", + "vfs.endpoint", "auth", "dialog.alert", "c9" + ]; + main.provides = ["login"]; + return main; + + function main(options, imports, register) { + var Plugin = imports.Plugin; + var ui = imports.ui; + var c9 = imports.c9; + var menus = imports.menus; + var layout = imports.layout; + var http = imports.http; + var util = imports.util; + var info = imports.info; + var auth = imports.auth; + var alert = imports["dialog.alert"].show; + + var vfsEndpoint = imports["vfs.endpoint"]; + + /***** Initialization *****/ + + var ideBaseUrl = options.ideBaseUrl; + var dashboardUrl = options.dashboardUrl; + var accountUrl = options.accountUrl; + var lastUser, mnuUser; + + var plugin = new Plugin("Ajax.org", main.consumes); + var emit = plugin.getEmitter(); + + var loaded = false; + function load() { + if (loaded) return false; + loaded = true; + + info.getUser(function(err, user) { + updateButton({user: user}); + }); + + auth.on("relogin", onReLogin); + } + + /***** Methods *****/ + + function updateButton(e) { + var user = e.user; + if (lastUser && lastUser.id == user.id) + return; + plugin.cleanUp(); + info.on("change", updateButton, plugin); + createButton(user); + lastUser = user; + + emit.sticky("ready", { name: user.fullname, id: user.id }, plugin); + } + + function createButton(user) { + var name = "user_" + user.id; + + // todo cleanup seems to not work well + // without this menu is empty after logging out and back in + if (lastUser) + menus.remove("user_" + lastUser.id); + menus.remove(name); + + var parent = layout.findParent(plugin); + + // Insert CSS + ui.insertCss(require("text!./login.css"), plugin); + + // Create Menu + mnuUser = new ui.menu(); + plugin.addElement(mnuUser); + + // Add named button + var icon = util.getGravatarUrl(user.email, 32, ""); + menus.addItemByPath(name + "/", mnuUser, 110000, plugin); + + // Add Divider + ui.insertByIndex(parent, new ui.divider({ + skin: "c9-divider-double", + "class" : "extrasdivider" + }), 870, plugin); + + // Add sub menu items + var c = 500; + menus.addItemByPath(name + "/Dashboard", new ui.item({ + onclick: function() { window.open(dashboardUrl); } + }), c += 100, plugin); + menus.addItemByPath(name + "/Account", new ui.item({ + onclick: function() { window.open(accountUrl); } + }), c += 100, plugin); + menus.addItemByPath(name + "/Home", new ui.item({ + onclick: function() { window.open(ideBaseUrl); } + }), c += 100, plugin); + + if (!options.noLogout) { + menus.addItemByPath(name + "/~", new ui.divider(), c += 100, plugin); + menus.addItemByPath(name + "/Log out", new ui.item({ + onclick: function() { + if (!c9.local) + return signout(); + auth.logout(function() { + info.login(true); + }); + } + }), c += 100, plugin); + } + + var button = menus.get(name).item; + button.setAttribute("class", "btnName"); + button.setAttribute("icon", icon); + button.setAttribute("iconsize", "16px 16px"); + button.setAttribute("tooltip", user.fullname); + button.setAttribute("caption", user.fullname); + ui.insertByIndex(parent, button, 600, plugin); + + if (c9.local) { + function minimize(){ + apf.document.documentElement.appendChild(button); + ui.setStyleClass(button.$ext, "titlebar"); + } + function restore(){ + ui.insertByIndex(parent, button, 870, plugin); + ui.setStyleClass(button.$ext, "", ["titlebar"]); + } + + menus.on("minimize", minimize, plugin); + menus.on("restore", restore, plugin); + + if (menus.minimized) + minimize(); + } + } + + function signout() { + vfsEndpoint.clearCache(); + auth.logout(function() { location.href = ideBaseUrl; }); + } + + function onReLogin() { + if (!c9.local) { + alert("Logged out", + "You have been logged in as a different user", + "Please hit OK to reload the IDE.", + function() { + vfsEndpoint.clearCache(); + auth.logout(function() { + document.location.reload(); + }); + }); + } + } + + /***** Lifecycle *****/ + + plugin.on("load", function() { + load(); + }); + plugin.on("enable", function() { + + }); + plugin.on("disable", function() { + + }); + plugin.on("unload", function() { + loaded = false; + }); + + /***** Register and define API *****/ + + /** + * + **/ + plugin.freezePublicAPI({ + get menu(){ return mnuUser; }, + + _events: [ + /** + * @event ready + */ + "ready" + ], + createButton: createButton, + updateButton: updateButton + }); + + register(null, { + login: plugin + }); + } +}); \ No newline at end of file diff --git a/plugins/c9.login/legacy.js b/plugins/c9.login/legacy.js deleted file mode 100644 index aba436fe..00000000 --- a/plugins/c9.login/legacy.js +++ /dev/null @@ -1,123 +0,0 @@ -"use strict"; - -var assert = require("assert"); -var url = require("url"); -var Cloud9LegayStrategy = require("./legacy_strategy"); -var cookieSignature = require("cookie-signature"); -var decrypt = require("c9/crypt").decrypt; -var login = require("connect-ensure-login"); - -plugin.consumes = [ - "db", - "passport", - "connect.redirect", - "connect.cookieparser", - "session-store" -]; -plugin.provides = ["c9.login"]; - -module.exports = plugin; - -function plugin(options, imports, register) { - assert(options.appId, "Option 'appId' is required"); - assert(options.ideBaseUrl, "Option 'ideBaseUrl' is required"); - assert(options.baseUrl, "Option 'baseUrl' is required"); - assert(options.ssoCookie, "Option 'ssoCookie' is required"); - assert(options.ssoSecret, "Option 'ssoSecret' is required"); - - var db = imports.db; - var passport = imports.passport; - var sessionStore = imports["session-store"]; - - // use the 'proxy' cookie to have federated logout - passport.useStart(function(req, res, next) { - var hash; - // anonymous login - if (!req.cookies || !(hash = req.cookies[options.ssoCookie])) - return done(); - - var encrypted = cookieSignature.unsign(hash, options.ssoSecret); - if (!encrypted) - return done(); - - var sessionId = decrypt(encrypted, options.ssoSecret); - - sessionStore.get(sessionId, function(err, session) { - if (err) return done(err); - done(null, session && session.uid); - }); - - function done(err, ssoUid) { - if (err) return next(err); - ssoUid = ssoUid || -1; - var session = req.session; - if (session && session.passport && session.passport.user && session.passport.user != ssoUid) { - return req.session.regenerate(function(err) { - if (err) return next(err); - - if (session.returnTo) - req.session.returnTo = session.returnTo; - - delete req.user; - next(); - }); - } - else { - if (!req.session.passport) - req.session.passport = {}; - - req.session.passport.user = ssoUid; - next(); - } - } - }); - - var cloud9Strategy = new Cloud9LegayStrategy({ - clientID: options.appId, - ideBaseUrl: options.ideBaseUrl, - callback: options.baseUrl + "/auth/c9l/callback", - db: db - }); - - passport.use(cloud9Strategy); - - passport.section.get("/c9l", passport.authenticate("c9l")); - passport.section.get("/c9l/callback", [ - passport.authenticate("c9l"), - function(req, res, next) { - var user = req.user; - - if (user) { - req.login(user, function(err) { - if (err) return next(err); - res.returnTo(req, "/"); - }); - } - else { - res.redirect("/auth/c9l"); - } - } - ]); - - register(null, { - "c9.login": { - ensureLoggedIn: function() { - return function(req, res, next) { - var redirect = options.baseUrl + "/_auth/c9l"; - var nonce = req.parsedUrl.query.__c9_preview_id__; - - if (nonce) { - redirect += "?nonce=" + encodeURIComponent(nonce); - delete req.parsedUrl.query.__c9_preview_id__; - delete req.parsedUrl.search; - req.originalUrl = url.format(req.parsedUrl); - } - - login.ensureLoggedIn({ - redirectTo: redirect - })(req, res, next); - }; - } - } - }); -} \ No newline at end of file diff --git a/plugins/c9.login/legacy_strategy.js b/plugins/c9.login/legacy_strategy.js deleted file mode 100644 index bdc78f30..00000000 --- a/plugins/c9.login/legacy_strategy.js +++ /dev/null @@ -1,73 +0,0 @@ -var passport = require('passport'); -var util = require('util'); -var InternalOAuthError = require("passport-oauth").InternalOAuthError; - - -function Cloud9Legacy(options) { - passport.Strategy.call(this); - this.name = 'c9l'; - - this.clientID = options.clientID; - this.ideBaseUrl = options.ideBaseUrl; - this.callback = options.callback; - this.db = options.db; -} - -/** - * Inherit from `passport.Strategy`. - */ -util.inherits(Cloud9Legacy, passport.Strategy); - -/** - * Authenticate request based on the contents of a HTTP Basic authorization - * header. - * - * @param {Object} req - * @api protected - */ -Cloud9Legacy.prototype.authenticate = function(req, options) { - var that = this; - options = options || {}; - - // the callback handler - if (req.query && req.query.code) { - this.db.AccessToken - .findOne({ - token: req.query.code - }) - .populate("user") - .exec(function(err, token) { - if (err) - return that.error(new InternalOAuthError('failed to obtain access token', err)); - - req.session.token = req.query.code; - that.success(token.user); - }); - return; - } - - var nonce = req.parsedUrl.query.nonce; - if (nonce) { - this.redirect( - this.ideBaseUrl + - "/api/nc/auth" + - "?response_type=nonce" + - "&client_id=" + encodeURIComponent(this.clientID + "_nonce") + - "&nonce=" + encodeURIComponent(nonce) - ); - } - else { - this.redirect( - this.ideBaseUrl + - "/api/nc/auth" + - "?response_type=token" + - "&client_id=" + encodeURIComponent(this.clientID) + - "&login_hint=" + encodeURIComponent(options.loginHint || "") - ); - } -}; - -/** - * Expose `Cloud9Legacy`. - */ -module.exports = Cloud9Legacy; \ No newline at end of file diff --git a/plugins/c9.login/login.js b/plugins/c9.login/login.js deleted file mode 100644 index 45d67244..00000000 --- a/plugins/c9.login/login.js +++ /dev/null @@ -1,135 +0,0 @@ -"use strict"; - -var assert = require("assert"); -var frontdoor = require("frontdoor"); -var cookie = require("cookie"); -var Passport = require("passport").Passport; -var Cloud9Strategy = require("./strategy"); - -plugin.consumes = [ - "session", - "connect.redirect" -]; -plugin.provides = ["c9.login"]; - -module.exports = plugin; - -function plugin(options, imports, register) { - assert(options.appId, "Option 'appId' is required"); - assert(options.appSecret, "Option 'appSecret' is required"); - assert(options.callback, "Option 'callback' is required"); - assert(options.logout, "Option 'logout' is required"); - assert(options.baseUrl, "Option 'baseUrl' is required"); - assert(options.domain, "Option 'domain' is required"); - assert(options.ssoCookie, "Option 'ssoCookie' is required"); - assert(options.ssoCookie.name, "Option 'ssoCookie.name' is required"); - assert(options.ssoCookie.maxAge, "Option 'ssoCookie.maxAge' is required"); - - var session = imports.session; - var passport = new Passport(); - - session.use(passport.initialize()); - session.use(function(req, res, next) { - passport.session()(req, res, function(err) { - if (err) return next(err); - if (!req.user) return next(); - - var uid = req.cookies[options.ssoCookie.name]; - if (uid != req.user.id) { - req.logout(); - return next(); - } - - next(); - }); - }); - - passport.serializeUser(function(user, done) { - var id; - try { - id = JSON.stringify(user); - } - catch (e) { - return done(e); - } - done(null, id); - }); - - passport.deserializeUser(function(id, done) { - var user; - try { - user = JSON.parse(id); - } - catch (e) { - return done(e); - } - done(null, user); - }); - - var cloud9Strategy = new Cloud9Strategy({ - clientID: options.appId, - clientSecret: options.appSecret, - callbackURL: options.callback, - userProfileURL: options.userProfileURL, - baseUrl: options.baseUrl, - }, function(accessToken, refreshToken, params, profile, done) { - var user = { - id: profile.id, - username: profile.username, - fullname: profile.displayName ? profile.displayName.trim() : profile.username, - token: accessToken - }; - done(null, user); - }); - - passport.use(cloud9Strategy); - - var api = frontdoor(); - passport.section = api.section("auth"); - session.use(api); - - passport.section.get("/logout", function(req, res, next) { - res.redirect(options.baseUrl + "/logout?redirect_uri=" + encodeURIComponent(options.logout)); - }); - passport.section.get("/cloud9", passport.authenticate("cloud9")); - passport.section.get("/cloud9/callback", function(req, res, next) { - passport.authenticate("cloud9", function(err, user, info) { - if (err) return next(err); - - if (user) { - req.login(user, function(err) { - if (err) return next(err); - setCookie(res, req.user.id, options.ssoCookie.maxAge); - res.returnTo(req, "/"); - }); - } - else { - res.redirect("/auth/cloud9"); - } - - })(req, res, next); - }); - - passport.section.get("/cloud9/logout", function(req, res, next) { - req.logout(); - clearCookie(res); - res.redirect("/"); - }); - - function clearCookie(res) { - setCookie(res, "", new Date(1)); - } - function setCookie(res, value, ttl) { - res.setHeader("Set-Cookie", cookie.serialize(options.ssoCookie.name, value, { - domain: "." + options.domain, - path: "/", - expires: ttl instanceof Date ? ttl : new Date(Date.now() + ttl), - secure: true, - httpOnly: true - })); - } - - register(null, { - "c9.login": passport - }); -} \ No newline at end of file diff --git a/plugins/c9.login/strategy.js b/plugins/c9.login/strategy.js deleted file mode 100644 index 3443d5e4..00000000 --- a/plugins/c9.login/strategy.js +++ /dev/null @@ -1,45 +0,0 @@ -var util = require('util'); -var OAuth2Strategy = require('passport-oauth').OAuth2Strategy; -var InternalOAuthError = require('passport-oauth').InternalOAuthError; - -function Strategy(options, verify) { - options = options || {}; - var baseUrl = options.baseUrl || "https://auth.c9.io/oauth"; - - options.authorizationURL = baseUrl + "/authorize"; - options.tokenURL = baseUrl + "/access_token"; - options.scopeSeparator = ","; - - OAuth2Strategy.call(this, options, verify); - this.name = "cloud9"; - this._userProfileURL = options.userProfileURL || "https://api.c9.io/user"; -} - -util.inherits(Strategy, OAuth2Strategy); - -Strategy.prototype.userProfile = function(accessToken, done) { - this._oauth2.useAuthorizationHeaderforGET(true); - this._oauth2.get(this._userProfileURL, accessToken, function (err, body, res) { - if (err) - return done(new InternalOAuthError('failed to fetch user profile', err)); - - try { - var json = JSON.parse(body); - - var profile = { provider: "cloud9" }; - profile.id = json.id; - profile.displayName = json.name; - profile.username = json.login; - profile.emails = [{ value: json.email }]; - - profile._raw = body; - profile._json = json; - - done(null, profile); - } catch (e) { - done(e); - } - }); -}; - -module.exports = Strategy; \ No newline at end of file diff --git a/plugins/c9.vfs.server/vfs.js b/plugins/c9.vfs.server/vfs.js index 912016a9..f9e8168f 100644 --- a/plugins/c9.vfs.server/vfs.js +++ b/plugins/c9.vfs.server/vfs.js @@ -146,7 +146,7 @@ Vfs.prototype._createEngine = function(vfs, options) { var that = this; var engine = new eio.Server({ - pingTimeout: 3000, + pingTimeout: 5000, pingInterval: 15000, transports: ["polling", "websocket"], allowUpgrades: true,