diff --git a/controllers/scriptStorage.js b/controllers/scriptStorage.js index 99a38ceb8..04635914c 100644 --- a/controllers/scriptStorage.js +++ b/controllers/scriptStorage.js @@ -2308,6 +2308,7 @@ exports.webhook = function (aReq, aRes) { var repos = {}; var repo = null; var update = null; + var defaultBranch = null; // Return if script storage is in read-only mode if (process.env.READ_ONLY_SCRIPT_STORAGE === 'true') { @@ -2375,12 +2376,6 @@ exports.webhook = function (aReq, aRes) { // - // Only accept commits from the `master` branch - if (payload.ref !== 'refs/heads/master') { - aRes.status(403).send('Default branch is not `master`.'); // Forbidden - return; - } - // Gather all the info for the RepoManager username = payload.repository.owner.name; reponame = payload.repository.name; @@ -2411,6 +2406,13 @@ exports.webhook = function (aReq, aRes) { return; } + // Only accept commits from the default branch (defaults to `master`, allows user migration to `main`) + defaultBranch = aUser.ghBranch || 'master'; + if (payload.ref !== 'refs/heads/' + defaultBranch) { + aRes.status(403).send('Default branch is not `' + defaultBranch + '`.'); // Forbidden + return; + } + aRes.status(202).send('Your request is queued.'); // Close connection with Accepted but processing // Gather the modified user scripts diff --git a/controllers/user.js b/controllers/user.js index eeb9fe004..defe88f08 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -1272,6 +1272,44 @@ exports.userEditPreferencesPage = function (aReq, aRes, aNext) { }); }; +exports.userUpdatePreferences = function (aReq, aRes, aNext) { + var authedUser = aReq.session.user; + var branch = aReq.body.branch; + + if (!authedUser) { + aRes.redirect('/login'); + return; + } + + User.findOne({ + _id: authedUser._id + }, function (aErr, aUser) { + if (aErr || !aUser) { + aNext(); + return; + } + + // One-way migration to `main` for GitHub authed accounts only + if (branch === 'main' && aUser.strategies && aUser.strategies.indexOf('github') > -1) { + if (aUser.ghBranch !== 'main') { + aUser.ghBranch = 'main'; + aUser.save(function (aErr) { + if (aErr) { + console.error(aErr); + } + if (aReq.session && aReq.session.user) { + aReq.session.user.ghBranch = 'main'; + } + aRes.redirect('/user/preferences'); + }); + return; + } + } + + aRes.redirect('/user/preferences'); + }); +}; + exports.newScriptPage = function (aReq, aRes, aNext) { function preRender() { } @@ -1703,7 +1741,8 @@ exports.userGitHubImportScriptPage = function (aReq, aRes, aNext) { } options.githubRepoName = githubRepoName = aReq.body.repo || aReq.query.repo; - options.githubDefaultBranch = githubDefaultBranch = aReq.body.default_branch || aReq.query.default_branch; + options.githubDefaultBranch = githubDefaultBranch = + aReq.body.default_branch || aReq.query.default_branch; options.githubPathName = githubPathName = aReq.body.pathname || aReq.query.pathname; options.githubPathExt = githubPathExt = aReq.body.pathext || aReq.query.pathext; options.githubBlobPath = githubBlobPath = aReq.body.path || aReq.query.path; diff --git a/libs/modelParser.js b/libs/modelParser.js index b8757f96e..d456f26c0 100644 --- a/libs/modelParser.js +++ b/libs/modelParser.js @@ -738,6 +738,8 @@ var parseUser = function (aUser) { user.userStrategies = user.strategies; user.hasGithub = user.strategies && user.strategies.indexOf('github') > -1; // NOTE: Watchpoint user.canSync = user.hasGithub; + user.ghBranch = user.ghBranch || 'master'; + user.isGhBranchMain = user.ghBranch === 'main'; // Dates parseDateProperty(user, 'created'); diff --git a/libs/repoManager.js b/libs/repoManager.js index ff0fc4c5c..94b262978 100644 --- a/libs/repoManager.js +++ b/libs/repoManager.js @@ -163,9 +163,10 @@ RepoManager.prototype.loadSyncs = function (aUpdate, aCallback) { // TODO: Alter usage of makeRepoArray since it causes redundant looping arrayOfRepos.forEach(function (aRepo) { async.each(aRepo.scripts, function (aScript, aInnerCallback) { + var branch = (that.user && that.user.ghBranch) || 'master'; var hostname = 'raw.githubusercontent.com'; var uri = '/' + aRepo.user + '/' + aRepo.repo - + '/master' + aScript.path; + + '/' + branch + aScript.path; Sync.findOne( { _authorId: that.user.id, id: aUpdate, target: 'https://' + hostname + uri }, @@ -216,11 +217,12 @@ RepoManager.prototype.loadScripts = function (aUpdate, aCallback) { // TODO: Alter usage of makeRepoArray since it causes redundant looping arrayOfRepos.forEach(function (aRepo) { async.each(aRepo.scripts, function (aScript, aInnerCallback) { + var branch = (that.user && that.user.ghBranch) || 'master'; var hostname = 'raw.githubusercontent.com'; var uri = '/' + aRepo.user + '/' + aRepo.repo - + '/master' + aScript.path; + + '/' + branch + aScript.path; var url = '/' + encodeURI(aRepo.user) + '/' + encodeURI(aRepo.repo) - + '/master' + aScript.path; + + '/' + branch + aScript.path; fetchRaw(hostname, url, function (aBufs) { var msg = null; diff --git a/models/user.js b/models/user.js index 9cb4c0aa3..58c78f784 100644 --- a/models/user.js +++ b/models/user.js @@ -28,6 +28,7 @@ var userSchema = new Schema({ // Store their GitHub username when they import scripts ghUsername: String, + ghBranch: String, // Moderation role: Number, diff --git a/routes.js b/routes.js index 5b349cd44..b3f5864ae 100644 --- a/routes.js +++ b/routes.js @@ -561,7 +561,9 @@ module.exports = function (aApp) { aApp.route('/users/:username/profile/captcha').head(statusTMR).get(captchaCapLimiter, authentication.validateUser, user.userEditProfilePageCaptcha); aApp.route('/users/:username/update').head(statusTMR).post(authentication.validateUser, admin.adminUserUpdate); // NOTE: Some below inconsistent with priors - aApp.route('/user/preferences').head(statusTMR).get(authentication.validateUser, user.userEditPreferencesPage); + aApp.route('/user/preferences').head(statusTMR) + .get(authentication.validateUser, user.userEditPreferencesPage) + .post(authentication.validateUser, user.userUpdatePreferences); aApp.route('/user').head(statusTMR).get(function (aReq, aRes) { aRes.redirect(302, '/users'); }); diff --git a/views/pages/newScriptPage.html b/views/pages/newScriptPage.html index 056171eab..5f3b8b757 100644 --- a/views/pages/newScriptPage.html +++ b/views/pages/newScriptPage.html @@ -367,7 +367,12 @@

You may use Write Script Online or Upload Script to the site first to determine if there are any validation issues. When the service is available you may use the link at Import Script from GitHub to speed things up as a shortcut.

    + {{#authedUser.isGhBranchMain}} +
  1. Ensure that you have and use a default main branch.
  2. + {{/authedUser.isGhBranchMain}} + {{^authedUser.isGhBranchMain}}
  3. Ensure that you have and use a default master branch.
  4. + {{/authedUser.isGhBranchMain}}
  5. On your target GitHub repo, click Settings > Webhooks > Add Webhook.
  6. In the Payload URL input, paste
    https://openuserjs.org/github/hook
  7. Change the Content Type dropdown to
    application/x-www-form-urlencoded
  8. diff --git a/views/pages/userEditPreferencesPage.html b/views/pages/userEditPreferencesPage.html index db59ec969..7cebf9806 100644 --- a/views/pages/userEditPreferencesPage.html +++ b/views/pages/userEditPreferencesPage.html @@ -66,6 +66,31 @@

    Authentication

    {{/unusedStrategies}}
+ {{#user.hasGithub}} + {{^user.isGhBranchMain}} +
+

GitHub Integration

+
+ + + + + Default branch: master + +
+
+
+ + +
+
+
+
+
+ {{/user.isGhBranchMain}} + {{/user.hasGithub}}

Session