mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 12:12:26 +08:00
Revert "Revert "Merge branch 'master' of https://github.com/discourse/discourse""
This reverts commit20780a1eee
. * SECURITY: re-adds accidentally reverted commit: 03d26cd6: ensure embed_url contains valid http(s) uri * when the merge commite62a85cf
was reverted, git chose the2660c2e2
parent to land on instead of the03d26cd6
parent (which contains security fixes)
This commit is contained in:
parent
20780a1eee
commit
d9a02d1336
6
Gemfile
6
Gemfile
|
@ -127,10 +127,6 @@ gem 'mini_racer'
|
|||
# TODO: determine why highline is being held back and upgrade to latest
|
||||
gem 'highline', '~> 1.7.0', require: false
|
||||
|
||||
# TODO: Upgrading breaks Sidekiq Web
|
||||
# This is a bit of a hornets nest cause in an ideal world we much prefer
|
||||
# if Sidekiq reused session and CSRF mitigation with Discourse on the
|
||||
# _forum_session cookie instead of a rack.session cookie
|
||||
gem 'rack', '2.2.2'
|
||||
|
||||
gem 'rack-protection' # security
|
||||
|
@ -252,3 +248,5 @@ end
|
|||
gem 'webpush', require: false
|
||||
gem 'colored2', require: false
|
||||
gem 'maxminddb'
|
||||
|
||||
gem 'rails_failover', require: false
|
||||
|
|
14
Gemfile.lock
14
Gemfile.lock
|
@ -195,7 +195,7 @@ GEM
|
|||
mini_sql (0.2.5)
|
||||
mini_suffix (0.3.0)
|
||||
ffi (~> 1.9)
|
||||
minitest (5.14.0)
|
||||
minitest (5.14.1)
|
||||
mocha (1.11.2)
|
||||
mock_redis (0.23.0)
|
||||
msgpack (1.3.3)
|
||||
|
@ -262,7 +262,7 @@ GEM
|
|||
pry-rails (0.3.9)
|
||||
pry (>= 0.10.4)
|
||||
public_suffix (4.0.5)
|
||||
puma (4.3.3)
|
||||
puma (4.3.5)
|
||||
nio4r (~> 2.0)
|
||||
r2 (0.2.7)
|
||||
rack (2.2.2)
|
||||
|
@ -277,6 +277,8 @@ GEM
|
|||
nokogiri (>= 1.6)
|
||||
rails-html-sanitizer (1.3.0)
|
||||
loofah (~> 2.3)
|
||||
rails_failover (0.2.0)
|
||||
redis (~> 4)
|
||||
rails_multisite (2.1.2)
|
||||
activerecord (> 5.0, < 7)
|
||||
railties (> 5.0, < 7)
|
||||
|
@ -294,7 +296,7 @@ GEM
|
|||
rb-fsevent (0.10.4)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rbtrace (0.4.12)
|
||||
rbtrace (0.4.13)
|
||||
ffi (>= 1.0.6)
|
||||
msgpack (>= 0.4.3)
|
||||
optimist (>= 3.0.0)
|
||||
|
@ -341,13 +343,16 @@ GEM
|
|||
json-schema (~> 2.2)
|
||||
railties (>= 3.1, < 7.0)
|
||||
rtlit (0.0.5)
|
||||
rubocop (0.83.0)
|
||||
rubocop (0.84.0)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 2.7.0.1)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
rexml
|
||||
rubocop-ast (>= 0.0.3)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 2.0)
|
||||
rubocop-ast (0.0.3)
|
||||
parser (>= 2.7.0.1)
|
||||
rubocop-discourse (2.1.2)
|
||||
rubocop (>= 0.69.0)
|
||||
rubocop-rspec (>= 1.39.0)
|
||||
|
@ -509,6 +514,7 @@ DEPENDENCIES
|
|||
rack (= 2.2.2)
|
||||
rack-mini-profiler
|
||||
rack-protection
|
||||
rails_failover
|
||||
rails_multisite
|
||||
railties (= 6.0.3)
|
||||
rake
|
||||
|
|
|
@ -77,12 +77,6 @@ const AdminUser = User.extend({
|
|||
});
|
||||
},
|
||||
|
||||
revokeApiKey() {
|
||||
return ajax(`/admin/users/${this.id}/revoke_api_key`, {
|
||||
type: "DELETE"
|
||||
}).then(() => this.set("api_key", null));
|
||||
},
|
||||
|
||||
deleteAllPosts() {
|
||||
let deletedPosts = 0;
|
||||
const user = this;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { get } from "@ember/object";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import DiscourseRoute from "discourse/routes/discourse";
|
||||
|
||||
export default DiscourseRoute.extend({
|
||||
|
@ -15,7 +14,7 @@ export default DiscourseRoute.extend({
|
|||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
if (model.get("isNew") || isEmpty(model.get("web_hook_event_types"))) {
|
||||
if (model.get("isNew")) {
|
||||
model.set("web_hook_event_types", controller.get("defaultEventTypes"));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//= require_tree ./discourse-common/addon
|
||||
//= require ./polyfills
|
||||
//= require_tree ./select-kit/app
|
||||
//= require_tree ./select-kit/addon
|
||||
//= require ./discourse/app/app
|
||||
//= require ./app-boot
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@ var define, requirejs;
|
|||
default: Ember.Object,
|
||||
get: Ember.get,
|
||||
getProperties: Ember.getProperties,
|
||||
guidFor: Ember.guidFor,
|
||||
set: Ember.set,
|
||||
setProperties: Ember.setProperties,
|
||||
computed: Ember.computed,
|
||||
|
|
|
@ -2,13 +2,10 @@ import I18n from "I18n";
|
|||
import { inject } from "@ember/controller";
|
||||
import Controller from "@ember/controller";
|
||||
import { setDefaultHomepage } from "discourse/lib/utilities";
|
||||
import discourseComputed, { observes } from "discourse-common/utils/decorators";
|
||||
import {
|
||||
listThemes,
|
||||
previewTheme,
|
||||
setLocalTheme
|
||||
} from "discourse/lib/theme-selector";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { listThemes, setLocalTheme } from "discourse/lib/theme-selector";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import pageReloader from "discourse/helpers/page-reloader";
|
||||
import {
|
||||
safariHacksDisabled,
|
||||
isiPad,
|
||||
|
@ -28,6 +25,9 @@ const TEXT_SIZES = ["smaller", "normal", "larger", "largest"];
|
|||
const TITLE_COUNT_MODES = ["notifications", "contextual"];
|
||||
|
||||
export default Controller.extend({
|
||||
currentThemeId: -1,
|
||||
preferencesController: inject("preferences"),
|
||||
|
||||
@discourseComputed("makeThemeDefault")
|
||||
saveAttrNames(makeDefault) {
|
||||
let attrs = [
|
||||
|
@ -51,8 +51,6 @@ export default Controller.extend({
|
|||
return attrs;
|
||||
},
|
||||
|
||||
preferencesController: inject("preferences"),
|
||||
|
||||
@discourseComputed()
|
||||
isiPad() {
|
||||
// TODO: remove this preference checkbox when iOS adoption > 90%
|
||||
|
@ -105,10 +103,14 @@ export default Controller.extend({
|
|||
return themes && themes.length > 1;
|
||||
},
|
||||
|
||||
@observes("themeId")
|
||||
themeIdChanged() {
|
||||
const id = this.themeId;
|
||||
previewTheme([id]);
|
||||
@discourseComputed("themeId")
|
||||
themeIdChanged(themeId) {
|
||||
if (this.currentThemeId === -1) {
|
||||
this.set("currentThemeId", themeId);
|
||||
return false;
|
||||
} else {
|
||||
return this.currentThemeId !== themeId;
|
||||
}
|
||||
},
|
||||
|
||||
@discourseComputed("model.user_option.theme_ids", "themeId")
|
||||
|
@ -189,6 +191,10 @@ export default Controller.extend({
|
|||
this.disableSafariHacks.toString()
|
||||
);
|
||||
}
|
||||
|
||||
if (this.themeId !== this.currentThemeId) {
|
||||
pageReloader.reload();
|
||||
}
|
||||
})
|
||||
.catch(popupAjaxError);
|
||||
},
|
||||
|
|
|
@ -185,6 +185,13 @@ export default Controller.extend(bufferedProperty("model"), {
|
|||
);
|
||||
},
|
||||
|
||||
@discourseComputed("model.category")
|
||||
minimumRequiredTags(category) {
|
||||
return category && category.minimum_required_tags > 0
|
||||
? category.minimum_required_tags
|
||||
: null;
|
||||
},
|
||||
|
||||
_forceRefreshPostStream() {
|
||||
this.appEvents.trigger("post-stream:refresh", { force: true });
|
||||
},
|
||||
|
|
|
@ -51,13 +51,15 @@ export default Controller.extend(CanCheckEmails, {
|
|||
hasDeletedPosts: gt("model.number_of_deleted_posts", 0),
|
||||
hasBeenSuspended: gt("model.number_of_suspensions", 0),
|
||||
hasReceivedWarnings: gt("model.warnings_received_count", 0),
|
||||
hasRejectedPosts: gt("model.number_of_rejected_posts", 0),
|
||||
|
||||
showStaffCounters: or(
|
||||
"hasGivenFlags",
|
||||
"hasFlaggedPosts",
|
||||
"hasDeletedPosts",
|
||||
"hasBeenSuspended",
|
||||
"hasReceivedWarnings"
|
||||
"hasReceivedWarnings",
|
||||
"hasRejectedPosts"
|
||||
),
|
||||
|
||||
showFeaturedTopic: and(
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
import EmberObject from "@ember/object";
|
||||
import Ember from "ember";
|
||||
|
||||
export default EmberObject.create({
|
||||
reload: function() {
|
||||
if (!Ember.testing) {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
});
|
|
@ -3,6 +3,7 @@ import { cancel, later } from "@ember/runloop";
|
|||
import { Promise } from "rsvp";
|
||||
import { iconHTML } from "discourse-common/lib/icon-library";
|
||||
import I18n from "I18n";
|
||||
import { guidFor } from "@ember/object/internals";
|
||||
|
||||
// http://github.com/feross/clipboard-copy
|
||||
function clipboardCopy(text) {
|
||||
|
@ -90,7 +91,7 @@ export default {
|
|||
const state = button.innerHTML;
|
||||
button.innerHTML = I18n.t("copy_codeblock.copied");
|
||||
|
||||
const commandId = Ember.guidFor(button);
|
||||
const commandId = guidFor(button);
|
||||
|
||||
if (_fadeCopyCodeblocksRunners[commandId]) {
|
||||
cancel(_fadeCopyCodeblocksRunners[commandId]);
|
||||
|
|
|
@ -3,6 +3,13 @@ import showModal from "discourse/lib/show-modal";
|
|||
import { registerTopicFooterButton } from "discourse/lib/register-topic-footer-button";
|
||||
import { formattedReminderTime } from "discourse/lib/bookmark";
|
||||
|
||||
const SHARE_PRIORITY = 1000;
|
||||
const BOOKMARK_PRIORITY = 900;
|
||||
const ARCHIVE_PRIORITY = 800;
|
||||
const FLAG_PRIORITY = 700;
|
||||
const EDIT_MESSAGE_PRIORITY = 600;
|
||||
const DEFER_PRIORITY = 500;
|
||||
|
||||
export default {
|
||||
name: "topic-footer-buttons",
|
||||
|
||||
|
@ -11,8 +18,12 @@ export default {
|
|||
registerTopicFooterButton({
|
||||
id: "share-and-invite",
|
||||
icon: "link",
|
||||
priority: 999,
|
||||
label: "topic.share.title",
|
||||
priority: SHARE_PRIORITY,
|
||||
label() {
|
||||
if (!this.get("topic.isPrivateMessage") || this.site.mobileView) {
|
||||
return "topic.share.title";
|
||||
}
|
||||
},
|
||||
title: "topic.share.help",
|
||||
action() {
|
||||
const panels = [
|
||||
|
@ -67,7 +78,7 @@ export default {
|
|||
registerTopicFooterButton({
|
||||
id: "flag",
|
||||
icon: "flag",
|
||||
priority: 998,
|
||||
priority: FLAG_PRIORITY,
|
||||
label: "topic.flag_topic.title",
|
||||
title: "topic.flag_topic.help",
|
||||
action: "showFlagTopic",
|
||||
|
@ -93,14 +104,16 @@ export default {
|
|||
}
|
||||
return "bookmark";
|
||||
},
|
||||
priority: 1000,
|
||||
priority: BOOKMARK_PRIORITY,
|
||||
classNames() {
|
||||
const bookmarked = this.get("topic.bookmarked");
|
||||
return bookmarked ? ["bookmark", "bookmarked"] : ["bookmark"];
|
||||
},
|
||||
label() {
|
||||
if (!this.get("topic.isPrivateMessage") || this.site.mobileView) {
|
||||
const bookmarked = this.get("topic.bookmarked");
|
||||
return bookmarked ? "bookmarked.clear_bookmarks" : "bookmarked.title";
|
||||
}
|
||||
},
|
||||
translatedTitle() {
|
||||
const bookmarked = this.get("topic.bookmarked");
|
||||
|
@ -126,7 +139,7 @@ export default {
|
|||
|
||||
registerTopicFooterButton({
|
||||
id: "archive",
|
||||
priority: 996,
|
||||
priority: ARCHIVE_PRIORITY,
|
||||
icon() {
|
||||
return this.archiveIcon;
|
||||
},
|
||||
|
@ -155,13 +168,16 @@ export default {
|
|||
|
||||
registerTopicFooterButton({
|
||||
id: "edit-message",
|
||||
priority: 750,
|
||||
priority: EDIT_MESSAGE_PRIORITY,
|
||||
icon: "pencil-alt",
|
||||
label: "topic.edit_message.title",
|
||||
title: "topic.edit_message.help",
|
||||
action: "editFirstPost",
|
||||
classNames: ["edit-message"],
|
||||
dependentKeys: ["editFirstPost", "showEditOnFooter"],
|
||||
dropdown() {
|
||||
return this.site.mobileView && this.get("topic.isPrivateMessage");
|
||||
},
|
||||
displayed() {
|
||||
return this.showEditOnFooter;
|
||||
}
|
||||
|
@ -170,7 +186,7 @@ export default {
|
|||
registerTopicFooterButton({
|
||||
id: "defer",
|
||||
icon: "circle",
|
||||
priority: 300,
|
||||
priority: DEFER_PRIORITY,
|
||||
label: "topic.defer.title",
|
||||
title: "topic.defer.help",
|
||||
action: "deferTopic",
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import I18n from "I18n";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import deprecated from "discourse-common/lib/deprecated";
|
||||
|
||||
const keySelector = "meta[name=discourse_theme_ids]";
|
||||
|
@ -79,31 +78,6 @@ export function refreshCSS(node, hash, newHref) {
|
|||
$orig.data("copy", reloaded);
|
||||
}
|
||||
|
||||
export function previewTheme(ids = []) {
|
||||
ids = ids.reject(id => !id);
|
||||
if (!ids.includes(currentThemeId())) {
|
||||
Discourse.set("assetVersion", "forceRefresh");
|
||||
|
||||
ajax(`/themes/assets/${ids.length > 0 ? ids.join("-") : "default"}`).then(
|
||||
results => {
|
||||
const elem = _.first($(keySelector));
|
||||
if (elem) {
|
||||
elem.content = ids.join(",");
|
||||
}
|
||||
|
||||
results.themes.forEach(theme => {
|
||||
const node = $(
|
||||
`link[rel=stylesheet][data-target=${theme.target}]`
|
||||
)[0];
|
||||
if (node) {
|
||||
refreshCSS(node, null, theme.new_href);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function listThemes(site) {
|
||||
let themes = site.get("user_themes");
|
||||
|
||||
|
|
|
@ -273,12 +273,17 @@ export function addNavItem(item) {
|
|||
NavItem.extraNavItemDescriptors.push(item);
|
||||
}
|
||||
|
||||
if (typeof Discourse !== "undefined") {
|
||||
Object.defineProperty(Discourse, "NavItem", {
|
||||
get() {
|
||||
deprecated("Import the NavItem class instead of using Discourse.NavItem", {
|
||||
deprecated(
|
||||
"Import the NavItem class instead of using Discourse.NavItem",
|
||||
{
|
||||
since: "2.4.0",
|
||||
dropFrom: "2.5.0"
|
||||
});
|
||||
}
|
||||
);
|
||||
return NavItem;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -61,12 +61,15 @@ const TopicDetails = RestModel.extend({
|
|||
}
|
||||
},
|
||||
|
||||
updateNotifications(v) {
|
||||
this.set("notification_level", v);
|
||||
this.set("notifications_reason_id", null);
|
||||
return ajax("/t/" + this.get("topic.id") + "/notifications", {
|
||||
updateNotifications(level) {
|
||||
return ajax(`/t/${this.get("topic.id")}/notifications`, {
|
||||
type: "POST",
|
||||
data: { notification_level: v }
|
||||
data: { notification_level: level }
|
||||
}).then(() => {
|
||||
this.setProperties({
|
||||
notification_level: level,
|
||||
notifications_reason_id: null
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
</section>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
{{#if model.can_see_about_stats}}
|
||||
<section class="about stats">
|
||||
<h3>{{d-icon "far-chart-bar"}} {{i18n "about.stats"}}</h3>
|
||||
|
||||
|
@ -108,6 +109,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
{{/if}}
|
||||
|
||||
{{#if contactInfo}}
|
||||
<section class="about contact">
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
{{#if showCategoryAdmin}}
|
||||
{{categories-admin-dropdown
|
||||
onChange=(action "selectCategoryAdminDropdownAction")
|
||||
options=(hash
|
||||
triggerOnChangeOnTab=false
|
||||
)
|
||||
}}
|
||||
{{/if}}
|
||||
|
||||
|
|
|
@ -50,9 +50,9 @@
|
|||
args=(hash topic=topic)
|
||||
tagName=""
|
||||
connectorTagName="span"}}
|
||||
</div>
|
||||
|
||||
{{pinned-button pinned=topic.pinned topic=topic}}
|
||||
</div>
|
||||
|
||||
{{#if showNotificationsButton}}
|
||||
{{topic-notifications-button
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
{{combo-box
|
||||
content=userSelectableThemes
|
||||
value=themeId
|
||||
onChange=(action (mut themeId))
|
||||
}}
|
||||
</div>
|
||||
{{#if themeIdChanged}}
|
||||
<p class="alert alert-success save-theme-alert">{{i18n "user.save_to_change_theme" save_text=(i18n "save") }}</p>
|
||||
{{/if}}
|
||||
{{#if showThemeSetDefault}}
|
||||
<div class="controls">
|
||||
{{preference-checkbox labelKey="user.theme_default_on_all_devices" checked=makeThemeDefault}}
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
options=(hash
|
||||
filterable=true
|
||||
categoryId=buffered.category_id
|
||||
minimum=minimumRequiredTags
|
||||
)
|
||||
}}
|
||||
{{/if}}
|
||||
|
|
|
@ -125,6 +125,7 @@ createWidget(
|
|||
{
|
||||
attributes: {
|
||||
href: attrs.user.get("path"),
|
||||
title: attrs.user.get("name"),
|
||||
"data-auto-route": true
|
||||
}
|
||||
},
|
||||
|
|
0
app/assets/javascripts/select-kit/addon/.gitkeep
Normal file
0
app/assets/javascripts/select-kit/addon/.gitkeep
Normal file
|
@ -67,6 +67,7 @@ export default ComboBoxComponent.extend({
|
|||
|
||||
search(filter) {
|
||||
if (filter) {
|
||||
filter = filter.toLowerCase();
|
||||
return this.content.filter(item => {
|
||||
const category = Category.findById(this.getValue(item));
|
||||
const categoryName = this.getName(item);
|
|
@ -13,8 +13,7 @@ export default DropdownSelectBoxComponent.extend({
|
|||
autoFilterable: false,
|
||||
filterable: false,
|
||||
i18nPrefix: "",
|
||||
i18nPostfix: "",
|
||||
showCaret: true
|
||||
i18nPostfix: ""
|
||||
},
|
||||
|
||||
modifyComponentForRow() {
|
|
@ -1,5 +1,6 @@
|
|||
import I18n from "I18n";
|
||||
import EmberObject, { computed, get, guidFor } from "@ember/object";
|
||||
import EmberObject, { computed, get } from "@ember/object";
|
||||
import { guidFor } from "@ember/object/internals";
|
||||
import Component from "@ember/component";
|
||||
import deprecated from "discourse-common/lib/deprecated";
|
||||
import { makeArray } from "discourse-common/lib/helpers";
|
||||
|
@ -271,7 +272,8 @@ export default Component.extend(
|
|||
selectedNameComponent: "selected-name",
|
||||
castInteger: false,
|
||||
preventsClickPropagation: false,
|
||||
focusAfterOnChange: true
|
||||
focusAfterOnChange: true,
|
||||
triggerOnChangeOnTab: true
|
||||
},
|
||||
|
||||
autoFilterable: computed("content.[]", "selectKit.filter", function() {
|
|
@ -140,7 +140,11 @@ export default Component.extend(UtilsMixin, {
|
|||
this._focusFilterInput();
|
||||
} else if (event.keyCode === 9) {
|
||||
// Tab
|
||||
if (this.selectKit.highlighted && this.selectKit.isExpanded) {
|
||||
if (
|
||||
this.selectKit.highlighted &&
|
||||
this.selectKit.isExpanded &&
|
||||
this.selectKit.options.triggerOnChangeOnTab
|
||||
) {
|
||||
this.selectKit.select(
|
||||
this.getValue(this.selectKit.highlighted),
|
||||
this.selectKit.highlighted
|
|
@ -1,20 +1,28 @@
|
|||
import Component from "@ember/component";
|
||||
import { action } from "@ember/object";
|
||||
import { action, computed } from "@ember/object";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "select-kit/templates/components/topic-notifications-button",
|
||||
classNames: ["topic-notifications-button"],
|
||||
classNameBindings: ["isLoading"],
|
||||
appendReason: true,
|
||||
showFullTitle: true,
|
||||
placement: "bottom-start",
|
||||
notificationLevel: null,
|
||||
topic: null,
|
||||
showCaret: true,
|
||||
isLoading: false,
|
||||
icon: computed("isLoading", function() {
|
||||
return this.isLoading ? "spinner" : null;
|
||||
}),
|
||||
|
||||
@action
|
||||
changeTopicNotificationLevel(levelId) {
|
||||
if (levelId !== this.notificationLevel) {
|
||||
this.topic.details.updateNotifications(levelId);
|
||||
this.set("isLoading", true);
|
||||
this.topic.details
|
||||
.updateNotifications(levelId)
|
||||
.finally(() => this.set("isLoading", false));
|
||||
}
|
||||
}
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user