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..7195e25ac 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() { } 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..3dcfe6022 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: { type: String, default: 'master' }, // 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/userEditPreferencesPage.html b/views/pages/userEditPreferencesPage.html index db59ec969..c554b0b88 100644 --- a/views/pages/userEditPreferencesPage.html +++ b/views/pages/userEditPreferencesPage.html @@ -66,6 +66,34 @@