diff options
author | jakefeasel <jfeasel@gmail.com> | 2014-09-22 23:22:47 -0700 |
---|---|---|
committer | jakefeasel <jfeasel@gmail.com> | 2014-09-22 23:22:47 -0700 |
commit | e1ef10278c4dc4fbcf4e836d9975f5644a6f9677 (patch) | |
tree | f6e3446d59bc1841f0babe8cc06c1ad1e690f777 /src | |
parent | a205ec01e0b7785ed46995f4b6bfcea9ea3f2320 (diff) | |
download | sqlfiddle2-e1ef10278c4dc4fbcf4e836d9975f5644a6f9677.zip sqlfiddle2-e1ef10278c4dc4fbcf4e836d9975f5644a6f9677.tar.gz sqlfiddle2-e1ef10278c4dc4fbcf4e836d9975f5644a6f9677.tar.bz2 |
Initial attempted support for OpenID Connect authentication: upgrading to OpenIDM 3.1-SNAPSHOT, configuring auth module, adding UI support
Diffstat (limited to 'src')
20 files changed, 534 insertions, 345 deletions
diff --git a/src/main/resources/conf/authentication.json b/src/main/resources/conf/authentication.json index e99081c..4a08d62 100755 --- a/src/main/resources/conf/authentication.json +++ b/src/main/resources/conf/authentication.json @@ -1,14 +1,5 @@ { - "queryId" : "credential-query", - "queryOnResource" : "managed/user", - "propertyMapping" : { - "authenticationId" : "_id", - "userCredential" : "password", - "userRoles" : "roles" - }, - "defaultUserRoles" : [ ], "serverAuthContext" : { - "sessionModule" : { "name" : "JWT_SESSION", "properties" : { @@ -36,6 +27,27 @@ "defaultUserRoles" : [ ] }, "enabled" : true + }, + { + "name" : "OPENID_CONNECT", + "properties" : { + "openIdConnectHeader" : "oidc_id_token", + "resolvers" : [ + { + "name" : "Google", + "icon" : "https://developers.google.com/accounts/images/sign-in-with-google.png", + "client_id" : "1073755695213-hgckd5r1jr9l1vst1ikq48klcku7ihpg.apps.googleusercontent.com", + "client_secret" : "FKwuulv4TUcj3lZNHDIAGx_y", + "authorization_endpoint" : "https://accounts.google.com/o/oauth2/auth", + "token_endpoint" : "https://accounts.google.com/o/oauth2/token", + "well-known" : "https://accounts.google.com/.well-known/openid-configuration" + } + ], + "defaultUserRoles" : [ + "openidm-authorized" + ] + }, + "enabled" : true } ] } diff --git a/src/main/resources/conf/endpoint-oidc.json b/src/main/resources/conf/endpoint-oidc.json new file mode 100644 index 0000000..3764b05 --- /dev/null +++ b/src/main/resources/conf/endpoint-oidc.json @@ -0,0 +1,5 @@ +{ + "context" : "endpoint/oidc", + "type" : "text/javascript", + "source" : "require('oidc').process(request);" +}
\ No newline at end of file diff --git a/src/main/resources/script/access.js b/src/main/resources/script/access.js index a215ed4..2070498 100755 --- a/src/main/resources/script/access.js +++ b/src/main/resources/script/access.js @@ -70,6 +70,12 @@ var httpAccessConfig = "methods" : "action", "actions" : "query" }, + { + "pattern" : "endpoint/oidc", + "roles" : "*", + "methods" : "action,read", + "actions" : "getToken" + }, // openidm-admin can request nearly anything (some exceptions being a few system endpoints) { "pattern" : "*", diff --git a/src/main/resources/script/oidc.js b/src/main/resources/script/oidc.js new file mode 100644 index 0000000..61a5374 --- /dev/null +++ b/src/main/resources/script/oidc.js @@ -0,0 +1,109 @@ +/*global exports, openidm, require */ +(function () { + var _ = require("lib/lodash"), + authConfig = openidm.read("config/authentication"), + oidcModule = _.find(authConfig.serverAuthContext.authModules, function (a) { + return a.name === "OPENID_CONNECT"; + }), + obj = { + serializeParams: function (params) { + return _(params) + .pairs() + .map(function (p) { + return p[0] + "=" + encodeURIComponent(p[1]); + }) + .value() + .join("&"); + }, + getRequestHeader: function () { + return oidcModule.properties.openIdConnectHeader; + }, + getResolvers: function (isExternal) { + var resolvers = oidcModule.properties.resolvers; + + return _.map(resolvers, function (r) { + if (isExternal) { + return _.omit(r, "client_secret", "well-known"); + } else { + return r; + } + }); + }, + getToken: function (name, code, redirect_uri) { + var resolver = _.find(this.getResolvers(false), function (r) { + return r.name === name; + }), + response; + + if (!resolver) { + throw { "code": 400, "message": "Unable to find provider with name '" + name + "'"}; + } + + try { + response = openidm.action("external/rest", "call", { + "method": "POST", + "url": resolver.token_endpoint, + "contentType": "application/x-www-form-urlencoded", + "body": this.serializeParams({ + "grant_type": "authorization_code", + "redirect_uri": redirect_uri, + "code": code, + "client_id": resolver.client_id, + "client_secret": resolver.client_secret + }) + }); + } catch (e) { + throw { + "code" : e.javaException.getCode(), + "message" : e.javaException.getMessage(), + "detail" : e.javaException.getDetail() + }; + } + + if (!response || !response.id_token) { + throw { "code": 400, "message": "Incorrect response from server", "detail": response }; + } + + return { + "token": response.id_token, + "header": this.getRequestHeader() + } + } + }; + + exports.process = function (request) { + if (!oidcModule || !oidcModule.enabled) { + throw { "code": 500, "message": "OpenID Connect not configured"}; + } + + switch (request.method) { + case "read": + return obj.getResolvers(true); + break; + + case "action": + switch (request.action) { + case "getToken": + if (request.additionalParameters.code === undefined || + request.additionalParameters.name === undefined || + request.additionalParameters.redirect_uri === undefined + ) { + throw { "code": 400, "message": "getToken requires 'redirect_uri', 'code' and 'name' as URL parameters"}; + } + + return obj.getToken(request.additionalParameters.name, request.additionalParameters.code, request.additionalParameters.redirect_uri); + break; + + default: + throw { "code": 400, "message": "Unsupported action: '" + request.action + "'"}; + } + break; + + default: + throw { "code": 400, "message": "Unsupported method: '" + request.method + "'"}; + } + }; + + exports.impl = obj; + +}());
\ No newline at end of file diff --git a/src/main/resources/ui/sqlfiddle/www/css/fiddle.less b/src/main/resources/ui/sqlfiddle/www/css/fiddle.less index 30b7c80..adc62d0 100644 --- a/src/main/resources/ui/sqlfiddle/www/css/fiddle.less +++ b/src/main/resources/ui/sqlfiddle/www/css/fiddle.less @@ -321,15 +321,8 @@ pre.results, .resultSetPreview li pre { /* Customizations for third-party UI elements */ -#openid_identifier { - width: 250px; - margin: 0px; - padding: 2px; - padding-left: 20px; - vertical-align: middle; - background-image: url('http://www.idselector.com/images/openid.ico'); - background-repeat: no-repeat; - background-position: 3px 2px; +form.login input[type=image] { + width: 206px; } #gravatar { diff --git a/src/main/resources/ui/sqlfiddle/www/index.html b/src/main/resources/ui/sqlfiddle/www/index.html index 00b759f..9c3001f 100644 --- a/src/main/resources/ui/sqlfiddle/www/index.html +++ b/src/main/resources/ui/sqlfiddle/www/index.html @@ -290,36 +290,6 @@ </div> - <div id="loginModal" class="modal"> - <form action="index.cfm/Users/auth" method="post" class="form-horizontal"> - <input type="hidden" name="hash" value="" id="hash"> - <div class="modal-header"> - <a class="close" data-dismiss="modal">x</a> - <h3>Login to SQL Fiddle</h3> - </div> - <div class="modal-body"> - <div class="control-group"> - <label class="control-label" for="openid_identifier">OpenID Identity: </label> - <div class="controls"> - <input type="text" id="openid_identifier" name="openid_identity" value="" size="20" /> - </div> - </div> - - <div class="control-group"> - <label class="control-label" for="remember">Remember Me: </label> - <div class="controls"> - <input type="checkbox" value="true" name="remember" id="remember"> - </div> - </div> - </div> - - <div class="modal-footer"> - <input class="btn btn-primary" type="submit" value="Login" /> - </div> - - </form> - </div> - <div id="myFiddlesModal" class="modal"> <form action="index.cfm/Users/auth" method="post"> @@ -337,6 +307,8 @@ </form> </div> + <div id="loginModal" class="modal"></div> + <script type="text/javascript" src="javascript/main_min.js"></script> <script type="text/javascript"> diff --git a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/app.js b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/app.js index 8240c55..1453cc9 100644 --- a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/app.js +++ b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/app.js @@ -1,8 +1,7 @@ -// this is essentially the controller, as far as I can tell - define([ 'utils/browserEngines/engines', + './models/OpenIDConnectProviders', './models/UsedFiddle', './models/MyFiddleHistory', './models/DBTypesList', @@ -12,23 +11,28 @@ define([ './views/DBTypesList', './views/SchemaDef', './views/Query', + './views/Login', './router', - 'utils/renderTerminator' + 'utils/renderTerminator', + 'utils/openidconnect', + 'underscore', 'jquery' ], function ( browserEngines, - UsedFiddle, MyFiddleHistory, DBTypesList, SchemaDef, Query, - DBTypesListView, SchemaDefView, QueryView, - Router, - renderTerminator - ) { + OpenIDConnectProviers, UsedFiddle, MyFiddleHistory, DBTypesList, SchemaDef, Query, + DBTypesListView, SchemaDefView, QueryView, LoginView, + Router, renderTerminator, openidconnect, + _, $ + ) { - var obj = { +var obj = { initialize : function() { var router = {}; + var oidc = new OpenIDConnectProviers(); + var myFiddleHistory = new MyFiddleHistory(); var dbTypes = new DBTypesList(); @@ -41,7 +45,7 @@ define([ var dbTypesListView = new DBTypesListView({ el: $("#db_type_id")[0], - collection: dbTypes + collection: dbTypes }); var schemaDefView = new SchemaDefView({ @@ -57,6 +61,11 @@ define([ output_el: $("#output") }); + var loginView = new LoginView({ + el: $("#loginModal")[0], + collection: oidc + }); + /* UI Changes */ dbTypes.on("change", function () { // see also the router function defined below that also binds to this event @@ -218,6 +227,10 @@ define([ queryView.render(); }); + oidc.on("reset", function () { + loginView.render(); + }); + myFiddleHistory.on("change reset remove", function () { if (localStorage) { @@ -285,13 +298,21 @@ define([ }); dbTypes.fetch(); + openidconnect.getLoggedUserDetails().then(function (userInfo) { + debugger; + }, function () { + oidc.fetch(); + }); - return { + _.extend(this, { dbTypes: dbTypes, schemaDef: schemaDef, schemaDefView: schemaDefView, - queryView: queryView - }; + queryView: queryView, + loginView: loginView + }); + + return this; } diff --git a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/DBTypesList.js b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/DBTypesList.js index 8116f69..54ca313 100644 --- a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/DBTypesList.js +++ b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/DBTypesList.js @@ -1,23 +1,19 @@ -define(["jquery", "Backbone", "./DBType"], function ($, Backbone, DBType) { +define(["./OpenIDMResource", "Backbone", "./DBType"], function (idm, Backbone, DBType) { return Backbone.Collection.extend({ model: DBType, fetch: function () { var _this = this; - return $.ajax({ - url: '/openidm/system/fiddles/db_types?_queryFilter=full_name gt ""', - headers: { - "X-OpenIDM-Username" : "anonymous", - "X-OpenIDM-Password" : "anonymous", - "X-OpenIDM-NoSession" : "true" - } - }).then(function (qry) { - _this.reset(_.map(qry.result, function (r) { - r.id = r.db_type_id; - return new DBType(r); - })); - return _this; - }); + return idm.serviceCall({ + url: 'system/fiddles/db_types?_queryFilter=full_name gt ""' + }) + .then(function (qry) { + _this.reset(_.map(qry.result, function (r) { + r.id = r.db_type_id; + return new DBType(r); + })); + return _this; + }); }, getSelectedType: function () { return this.find(function (dbType) { @@ -28,7 +24,7 @@ define(["jquery", "Backbone", "./DBType"], function ($, Backbone, DBType) { this.each(function (dbType) { dbType.set({"selected": (dbType.id === db_type_id)}, {silent: true}); }); - if (! silentSelected) { + if (!silentSelected) { this.trigger("change"); } } diff --git a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/MyFiddleHistory.js b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/MyFiddleHistory.js index 080d3a2..844c462 100644 --- a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/MyFiddleHistory.js +++ b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/MyFiddleHistory.js @@ -3,7 +3,7 @@ define(["Backbone", "./UsedFiddle"], function (Backbone, UsedFiddle) { var MyFiddleHistory = Backbone.Collection.extend({ model: UsedFiddle, comparator: function (m1,m2) { - if (m1.get("last_used") == m2.get("last_used")) + if (m1.get("last_used") === m2.get("last_used")) return 0; else if (m1.get("last_used") > m2.get("last_used")) return -1; @@ -11,39 +11,30 @@ define(["Backbone", "./UsedFiddle"], function (Backbone, UsedFiddle) { return 1; }, insert: function (uf) { - if (! $("#user_choices", this).length) // simple way to detect if we are logged in - { - var existingFiddle = this.find(function (m){ + // simple way to detect if we are logged in + if (!$("#user_choices", this).length) { + var existingFiddle = this.find(function (m) { return m.get("fragment") == uf.get("fragment"); }); - if (existingFiddle) - { + if (existingFiddle) { existingFiddle.set("last_used", uf.get("last_used")); this.sort(); - } - else - { + } else { this.add(uf); } this.trigger("change"); } }, initialize: function () { - try - { - if (localStorage) - { + try { + if (localStorage) { var historyJSON = localStorage.getItem("fiddleHistory"); - if (historyJSON && historyJSON.length) - { + if (historyJSON && historyJSON.length) { this.add($.parseJSON(historyJSON)); } - } - } - catch (e) - { + } catch (e) { // I guess localStorage isn't available } } diff --git a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/OpenIDConnectProviders.js b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/OpenIDConnectProviders.js new file mode 100644 index 0000000..658fdcc --- /dev/null +++ b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/OpenIDConnectProviders.js @@ -0,0 +1,16 @@ +define(["./OpenIDMResource", "Backbone"], function (idm, Backbone) { + return Backbone.Collection.extend({ + fetch: function () { + var _this = this; + return idm.serviceCall({ + url: "endpoint/oidc" + }) + .then(function (data) { + _this.reset(_.map(data, function (r) { + return new Backbone.Model(r); + })); + return _this; + }) + } + }); +});
\ No newline at end of file diff --git a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/OpenIDMResource.js b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/OpenIDMResource.js new file mode 100644 index 0000000..7e71c03 --- /dev/null +++ b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/OpenIDMResource.js @@ -0,0 +1,25 @@ +define(["jquery"], function ($) { + return { + serviceCall : function (args) { + if (typeof args.data !== "undefined" && typeof args.data !== "string") { + args.data = JSON.stringify(args.data); + } + args.type = args.type || "GET"; + args.headers = args.headers || { + "X-OpenIDM-Username" : "anonymous", + "X-OpenIDM-Password" : "anonymous", + "X-OpenIDM-NoSession" : "true" + }; + + return $.ajax({ + type: args.type, + url: '/openidm/' + args.url, + headers: $.extend({}, args.headers, { + "Content-Type": "application/json" + }), + dataType: "json", + data: args.data + }); + } + }; +});
\ No newline at end of file diff --git a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/Query.js b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/Query.js index 53a288c..6f92ba5 100644 --- a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/Query.js +++ b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/Query.js @@ -1,4 +1,4 @@ -define(["jquery", "Backbone"], function ($, Backbone) { +define(["./OpenIDMResource", "Backbone"], function (idm, Backbone) { var Query = Backbone.Model.extend({ @@ -14,74 +14,59 @@ define(["jquery", "Backbone"], function ($, Backbone) { this.trigger("reloaded"); }, execute: function () { - var thisModel = this; - if (! this.has("schemaDef") || - ! this.get("schemaDef").has("dbType") || - ! this.get("schemaDef").get("ready") ) - { return false; } + if (!this.has("schemaDef") || !this.get("schemaDef").has("dbType") || !this.get("schemaDef").get("ready")) { + return false; + } - $.ajax({ + return idm.serviceCall({ type: "POST", - url: "/openidm/endpoint/executeQuery?_action=query", - data: JSON.stringify({ + url: "endpoint/executeQuery?_action=query", + data: { db_type_id: this.get("schemaDef").get("dbType").id, schema_short_code: this.get("schemaDef").get("short_code"), statement_separator: this.get("statement_separator"), sql: this.get("sql") - }), - headers: { - "X-OpenIDM-Username" : "anonymous", - "X-OpenIDM-Password" : "anonymous", - "X-OpenIDM-NoSession" : "true", - "Content-Type": "application/json" - }, - dataType: "json", - success: function (resp, textStatus, jqXHR) { - if (thisModel.get("schemaDef").get("dbType").get("context") == "browser") - { - thisModel.get("schemaDef").get("browserEngines")[thisModel.get("schemaDef").get("dbType").get("className")].executeQuery({ - sql: thisModel.get("sql"), - statement_separator: thisModel.get("statement_separator"), - success: function (sets) { - thisModel.set({ - "id": resp["ID"], - "sets": sets - }); - thisModel.trigger("executed"); - }, - error: function (e) { - thisModel.set({ - "sets": [{ - "SUCCEEDED": false, - "ERRORMESSAGE": e - }] - }); - thisModel.trigger("executed"); - } - }); - } - else - { - thisModel.set({ - "id": resp["ID"], - "sets": resp["sets"] - }); - } - }, - error: function (jqXHR, textStatus, errorThrown) - { + } + }) + .then(function (resp, textStatus, jqXHR) { + if (thisModel.get("schemaDef").get("dbType").get("context") === "browser") { + thisModel.get("schemaDef").get("browserEngines")[thisModel.get("schemaDef").get("dbType").get("className")].executeQuery({ + sql: thisModel.get("sql"), + statement_separator: thisModel.get("statement_separator"), + success: function (sets) { + thisModel.set({ + "id": resp["ID"], + "sets": sets + }); + thisModel.trigger("executed"); + }, + error: function (e) { + thisModel.set({ + "sets": [{ + "SUCCEEDED": false, + "ERRORMESSAGE": e + }] + }); + thisModel.trigger("executed"); + } + }); + } else { thisModel.set({ - "sets": [] + "id": resp["ID"], + "sets": resp["sets"] }); - }, - complete: function (jqXHR, textStatus) - { - thisModel.trigger("executed"); } + }, + function (jqXHR, textStatus, errorThrown) { + thisModel.set({ + "sets": [] + }); + }) + .always(function (jqXHR, textStatus) { + thisModel.trigger("executed"); }); - } }); diff --git a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/SchemaDef.js b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/SchemaDef.js index 0d0c461..79674a9 100644 --- a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/SchemaDef.js +++ b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/models/SchemaDef.js @@ -1,4 +1,4 @@ -define(["jquery", "Backbone"], function ($, Backbone) { +define(["./OpenIDMResource", "Backbone"], function (idm, Backbone) { var SchemaDef = Backbone.Model.extend({ @@ -23,100 +23,89 @@ define(["jquery", "Backbone"], function ($, Backbone) { var selectedDBType = this.get("dbType"); var thisModel = this; - $.ajax({ + return idm.serviceCall({ type: "POST", - url: "/openidm/endpoint/createSchema?_action=create", - data: JSON.stringify({ + url: "endpoint/createSchema?_action=create", + data: { statement_separator: this.get('statement_separator'), db_type_id: this.get('dbType').id, ddl: this.get('ddl') - }), - headers: { - "X-OpenIDM-Username" : "anonymous", - "X-OpenIDM-Password" : "anonymous", - "X-OpenIDM-NoSession" : "true", - "Content-Type": "application/json" - }, - dataType: "json", - success: function (data, textStatus, jqXHR) { - var short_code; - - if (data._id) { - short_code = data._id.split('_')[1]; + } + }) + .then(function (data) { + var short_code; - if (selectedDBType.get("context") === "browser") { - thisModel.get("browserEngines")[selectedDBType.get("className")].buildSchema({ + if (data._id) { + short_code = data._id.split('_')[1]; - short_code: short_code, - statement_separator: thisModel.get('statement_separator'), - ddl: thisModel.get('ddl'), - success: function () { - thisModel.set({ - "short_code": short_code, - "ready": true, - "valid": true, - "errorMessage": "" - }); + if (selectedDBType.get("context") === "browser") { + thisModel.get("browserEngines")[selectedDBType.get("className")].buildSchema({ - thisModel.get("browserEngines")[selectedDBType.get("className")].getSchemaStructure({ - callback: function (schemaStruct) { - thisModel.set({ - "schema_structure": schemaStruct - }); - thisModel.trigger("built"); - } - }); + short_code: short_code, + statement_separator: thisModel.get('statement_separator'), + ddl: thisModel.get('ddl'), + success: function () { + thisModel.set({ + "short_code": short_code, + "ready": true, + "valid": true, + "errorMessage": "" + }); - }, - error: function (message) { - thisModel.set({ - "short_code": short_code, - "ready": false, - "valid": false, - "errorMessage": message, - "schema_structure": [] + thisModel.get("browserEngines")[selectedDBType.get("className")].getSchemaStructure({ + callback: function (schemaStruct) { + thisModel.set({ + "schema_structure": schemaStruct + }); + thisModel.trigger("built"); + } }); - thisModel.trigger("failed"); - } - }); - } else { - thisModel.set({ - "short_code": short_code, - "ready": true, - "valid": true, - "errorMessage": ""/*, - "schema_structure": data["schema_structure"]*/ - }); + }, + error: function (message) { + thisModel.set({ + "short_code": short_code, + "ready": false, + "valid": false, + "errorMessage": message, + "schema_structure": [] + }); + thisModel.trigger("failed"); + } - thisModel.trigger("built"); - } - - } - else - { + }); + } else { thisModel.set({ - "short_code": "", - "ready": false, - "valid": false, - "errorMessage": data["error"], - "schema_structure": [] + "short_code": short_code, + "ready": true, + "valid": true, + "errorMessage": ""/*, + "schema_structure": data["schema_structure"]*/ }); - thisModel.trigger("failed"); + + thisModel.trigger("built"); } - }, - error: function (jqXHR, textStatus, errorThrown) - { + + } else { thisModel.set({ "short_code": "", "ready": false, "valid": false, - "errorMessage": errorThrown, + "errorMessage": data["error"], "schema_structure": [] }); thisModel.trigger("failed"); - } + }, + function (jqXHR, textStatus, errorThrown) { + thisModel.set({ + "short_code": "", + "ready": false, + "valid": false, + "errorMessage": errorThrown, + "schema_structure": [] + }); + thisModel.trigger("failed"); }); } diff --git a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/router.js b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/router.js index 51e15d8..32d399b 100644 --- a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/router.js +++ b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/router.js @@ -1,10 +1,11 @@ define([ + './models/OpenIDMResource', 'jquery', 'underscore', 'Backbone', "utils/renderTerminator", "./models/UsedFiddle" -], function($, _, Backbone, renderTerminator, UsedFiddle){ +], function(idm, $, _, Backbone, renderTerminator, UsedFiddle){ var initialize = function(dbTypes, schemaDef, query, myFiddleHistory, dbTypesListView) { @@ -33,25 +34,19 @@ define([ SetAnchor: function (db_type_id, short_code, query_id, set_id) { var selectSet = function () { - if ($("#set_" + set_id).length) - { + if ($("#set_" + set_id).length) { window.scrollTo(0,$("#set_" + set_id).offset()["top"]-50); $("#set_" + set_id).addClass("highlight"); } }; - if ( - !dbTypes.getSelectedType() || - dbTypes.getSelectedType().get("id") != db_type_id || - schemaDef.get("short_code") != short_code || - query.get("id") != query_id - ) - { + if (!dbTypes.getSelectedType() || dbTypes.getSelectedType().get("id") !== db_type_id || + schemaDef.get("short_code") !== short_code || query.get("id") !== query_id) { + query.bind("reloaded", _.once(selectSet)); this.loadContent(db_type_id, "!" + db_type_id + "/" + short_code + "/" + query_id); - } - else - { + + } else { $(".set").removeClass("highlight"); selectSet(); } @@ -61,63 +56,26 @@ define([ this.DBType(db_type_id); - if (query.get("pendingChanges") && !confirm("Warning! You have made changes to your query which will be lost. Continue?'")) + if (query.get("pendingChanges") && !confirm("Warning! You have made changes to your query which will be lost. Continue?'")) { return false; + } schemaDef.set("loading", true); $(".helpTip").css("display", "none"); $("body").block({ message: "Loading..."}); - $.ajax({ - url: "/openidm/endpoint/loadContent/" + frag.replace(/\//g, '_').replace(/^!/, ''), - headers: { - "X-OpenIDM-Username" : "anonymous", - "X-OpenIDM-Password" : "anonymous", - "X-OpenIDM-NoSession" : "true" - }, - success: function (resp) { + return idm.serviceCall({ + url: "endpoint/loadContent/" + frag.replace(/\//g, '_').replace(/^!/, '') + }) + .then(function (resp) { schemaDef.set("loading", false); - if (resp["short_code"]) - { + if (resp["short_code"]) { var selectedDBType = dbTypes.getSelectedType(); - if (selectedDBType.get("context") == "browser") - { - if ( - selectedDBType.get("className") == "sqljs" && - schemaDef.get("browserEngines")["websql"].nativeSQLite - ) - { - if (confirm("Fiddle originally built with SQL.js, but you have WebSQL available - would you like to use that instead (it'll be faster to load)?")) - { - dbTypes.setSelectedType(parseInt($("#db_type_id a:contains('WebSQL')").closest('li').attr('db_type_id'))); - selectedDBType = dbTypes.getSelectedType(); - schemaDef.set({ - "ddl": resp["ddl"], - "dbType": selectedDBType, - "statement_separator": resp["schema_statement_separator"] - }); - if (resp["sql"]) - { - query.set({ - "schemaDef": schemaDef, - "sql": resp["sql"], - "statement_separator": resp["query_statement_separator"] - }); - schemaDef.on("built", _.once(function () { - query.execute(); - })); - - } - schemaDef.build(); - - - } - } - + if (selectedDBType.get("context") === "browser") { schemaDef.get("browserEngines")[selectedDBType.get("className")].buildSchema({ short_code: $.trim(resp["short_code"]), @@ -136,8 +94,7 @@ define([ }); renderTerminator($(".panel.schema"), resp["schema_statement_separator"]); - if (resp["sql"]) - { + if (resp["sql"]) { myFiddleHistory.insert(new UsedFiddle({ "fragment": "!" + db_type_id + "/" + resp["short_code"] + "/" + resp["id"] })); @@ -147,56 +104,53 @@ define([ "sql": resp["sql"], "statement_separator": resp["query_statement_separator"] }); - } - else - { + } else { myFiddleHistory.insert(new UsedFiddle({ "fragment": "!" + db_type_id + "/" + resp["short_code"] })); } schemaDef.get("browserEngines")[selectedDBType.get("className")].getSchemaStructure({ - callback: function (schemaStruct) { - schemaDef.set({ - "schema_structure": schemaStruct - }); - - schemaDef.trigger("reloaded"); + callback: function (schemaStruct) { + schemaDef.set({ + "schema_structure": schemaStruct + }); - if (resp["sql"]) - { - schemaDef.get("browserEngines")[selectedDBType.get("className")].executeQuery({ - sql: resp["sql"], - statement_separator: resp["query_statement_separator"], - success: function (sets) { + schemaDef.trigger("reloaded"); - query.set({ - "sets": sets - }); + if (resp["sql"]) { + schemaDef.get("browserEngines")[selectedDBType.get("className")].executeQuery({ + sql: resp["sql"], + statement_separator: resp["query_statement_separator"], + success: function (sets) { - query.trigger("reloaded"); + query.set({ + "sets": sets + }); - $("body").unblock(); - }, - error: function (e) { + query.trigger("reloaded"); - query.set({ - "sets": [] - }); + $("body").unblock(); + }, + error: function (e) { - query.trigger("reloaded"); + query.set({ + "sets": [] + }); - $("body").unblock(); - } - }); - } - else - { - $("body").unblock(); - } // end if resp["sql"] + query.trigger("reloaded"); + $("body").unblock(); + } + }); } - }); + else + { + $("body").unblock(); + } // end if resp["sql"] + + } + }); }, @@ -215,8 +169,7 @@ define([ renderTerminator($(".panel.schema"), resp["schema_statement_separator"]); - if (resp["sql"]) - { + if (resp["sql"]) { query.set({ "id": resp["id"], "sql": resp["sql"], @@ -234,9 +187,8 @@ define([ } }); - } - else // context not "browser" - { + + } else { // context not "browser" schemaDef.set({ "short_code": resp["short_code"], @@ -250,8 +202,7 @@ define([ renderTerminator($(".panel.schema"), resp["schema_statement_separator"]); schemaDef.trigger("reloaded"); - if (resp["sql"]) - { + if (resp["sql"]) { myFiddleHistory.insert(new UsedFiddle({ "fragment": "!" + db_type_id + "/" + resp["short_code"] + "/" + resp["id"] })); @@ -263,9 +214,7 @@ define([ "statement_separator": resp["query_statement_separator"] }); query.trigger("reloaded"); - } - else - { + } else { myFiddleHistory.insert(new UsedFiddle({ "fragment": "!" + db_type_id + "/" + resp["short_code"] })); @@ -275,18 +224,12 @@ define([ } - } - else - { + } else { $("body").unblock(); } - } - }); - - + }); } - }); var router = new Router; diff --git a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/templates/login.html b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/templates/login.html new file mode 100644 index 0000000..5ecb575 --- /dev/null +++ b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/templates/login.html @@ -0,0 +1,22 @@ + <form class="form-horizontal login"> + <input type="hidden" name="hash" value="" id="hash"> + <div class="modal-header"> + <a class="close" data-dismiss="modal">x</a> + <h3>Login to SQL Fiddle</h3> + </div> + <div class="modal-body"> + <div class="control-group"> + <label class="control-label">Choose OpenID Connect Authentication Provider: </label> + <div class="controls"> + + {{#each resolvers}} + + <input type="image" src="{{icon}}" value="{{name}}" /> + + {{/each}} + + </div> + </div> + </div> + + </form>
\ No newline at end of file diff --git a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/utils/openidconnect.js b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/utils/openidconnect.js new file mode 100644 index 0000000..ed933fb --- /dev/null +++ b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/utils/openidconnect.js @@ -0,0 +1,50 @@ +/*global localStorage, JSON */ +define(["underscore", "jquery", "fiddle_backbone/models/OpenIDMResource"], function (_, $, idm) { + return { + getURLParams: function () { + return _.chain( window.location.search.replace(/^\?/, '').split("&") ) + .map(function (arg) { + return arg.split("="); + }) + .object() + .value(); + }, + getCode: function () { + return this.getURLParams().code; + }, + getRedirectUri: function () { + return window.location.protocol + "//" + window.location.host + + window.location.pathname.replace(/(\/index\.html)|(\/$)/, '/oauth.html'); + }, + getMainUri: function () { + return window.location.protocol + "//" + window.location.host + + window.location.pathname.replace(/(\/oauth\.html)|(\/$)/, '/index.html'); + }, + getToken: function () { + var params = this.getURLParams(); + return idm.serviceCall({ + "type": "POST", + "url": "endpoint/oidc?_action=getToken&code=" + params.code + "&name=" + params.state + "&redirect_uri=" + this.getRedirectUri() + }).then(function (result) { + localStorage.setItem("oidcToken", JSON.stringify(result)); + return result; + }); + }, + getLoggedUserDetails: function () { + var token = localStorage.getItem("oidcToken"), + jwt = {}; + + if (token) { + token = JSON.parse(token); + jwt[token.header] = token.token; + + return idm.serviceCall({ + "url": "info/login", + "headers": jwt + }); + } else { + return $.Deferred().reject(); + } + } + }; +});
\ No newline at end of file diff --git a/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/views/Login.js b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/views/Login.js new file mode 100644 index 0000000..487beb8 --- /dev/null +++ b/src/main/resources/ui/sqlfiddle/www/javascript/fiddle_backbone/views/Login.js @@ -0,0 +1,41 @@ +define ([ + "jquery", "underscore", "Backbone", "Handlebars", + "utils/openidconnect", "text!../templates/login.html" + ], + function ($,_,Backbone,Handlebars,openidconnect,loginTemplate) { + + var LoginView = Backbone.View.extend({ + initialize: function (options) { + this.options = options; + this.compiledTemplate = Handlebars.compile(loginTemplate); + }, + events: { + "click input[type=image]": "redirectToIDP" + }, + render: function () { + $(this.el).html( + this.compiledTemplate({ + resolvers: this.collection.toJSON() + }) + ); + return this; + }, + redirectToIDP: function (e) { + e.preventDefault(); + + var resolver = this.collection.find(function (r) { + return r.get('name') === $(e.target).val(); + }); + + window.location.href = resolver.get('authorization_endpoint') + + '?response_type=code&scope=openid' + + '&redirect_uri=' + openidconnect.getRedirectUri() + + '&state=' + resolver.get('name') + + '&client_id=' + resolver.get('client_id'); + + } + }); + + return LoginView; + +}); diff --git a/src/main/resources/ui/sqlfiddle/www/javascript/main.js b/src/main/resources/ui/sqlfiddle/www/javascript/main.js index dd0c9f5..d84baa9 100644 --- a/src/main/resources/ui/sqlfiddle/www/javascript/main.js +++ b/src/main/resources/ui/sqlfiddle/www/javascript/main.js @@ -11,10 +11,8 @@ requirejs.config({ DateFormat: 'libs/date.format', XPlans: 'libs/xplans', DDLBuilder: 'libs/ddl_builder', - utils: 'fiddle_backbone/utils' }, - shim: { DateFormat: { exports: 'dateFormat' @@ -26,12 +24,10 @@ requirejs.config({ 'XPlans/mssql': { exports: "QP" }, - jqBlockUI: ['jquery'], jqCookie: ['jquery'], Bootstrap: ['jquery'] } - }); require([ @@ -207,7 +203,7 @@ require([ }); - /* LOGIN/LOGOUT */ + /* LOGIN/LOGOUT // Upload localStorage fiddle history to server to use new mechanism if ($("#user_choices", this).length) // simple way to detect if we are logged in @@ -261,7 +257,6 @@ require([ .css("display", "none"); }); - $("#userInfo").on("click", "#logout", function (e) { e.preventDefault(); @@ -271,6 +266,7 @@ require([ .submit(); }); + */ /* TEXT TO DDL */ diff --git a/src/main/resources/ui/sqlfiddle/www/javascript/oauth.js b/src/main/resources/ui/sqlfiddle/www/javascript/oauth.js new file mode 100644 index 0000000..58ced9f --- /dev/null +++ b/src/main/resources/ui/sqlfiddle/www/javascript/oauth.js @@ -0,0 +1,13 @@ +requirejs.config({ + paths: { + jquery: 'libs/jquery/jquery-1.11.1.min', + underscore: 'libs/lodash.underscore.min', + utils: 'fiddle_backbone/utils' + } +}); + +require(["jquery", "utils/openidconnect"], function ($, oidc) { + oidc.getToken().always(function () { + window.location.href = oidc.getMainUri(); + }); +});
\ No newline at end of file diff --git a/src/main/resources/ui/sqlfiddle/www/oauth.html b/src/main/resources/ui/sqlfiddle/www/oauth.html new file mode 100644 index 0000000..e775d7a --- /dev/null +++ b/src/main/resources/ui/sqlfiddle/www/oauth.html @@ -0,0 +1,4 @@ +<!doctype html> +<body> + <script type="text/javascript" src="javascript/oauth_min.js"></script> +</body>
\ No newline at end of file |