Add config options for overriding username and icon, and add BOT indicator next to webhook posts.

Этот коммит содержится в:
JoramWilander
2015-10-05 08:46:23 -04:00
родитель 11903a3834
Коммит 2a23d90ca6
11 изменённых файлов: 119 добавлений и 17 удалений

Просмотреть файл

@@ -6,6 +6,8 @@
"GoogleDeveloperKey": "", "GoogleDeveloperKey": "",
"EnableOAuthServiceProvider": false, "EnableOAuthServiceProvider": false,
"EnableIncomingWebhooks": true, "EnableIncomingWebhooks": true,
"EnablePostUsernameOverride": false,
"EnablePostIconOverride": false,
"EnableTesting": false "EnableTesting": false
}, },
"TeamSettings": { "TeamSettings": {
@@ -86,4 +88,4 @@
"TokenEndpoint": "", "TokenEndpoint": "",
"UserApiEndpoint": "" "UserApiEndpoint": ""
} }
} }

Просмотреть файл

@@ -6,6 +6,8 @@
"GoogleDeveloperKey": "", "GoogleDeveloperKey": "",
"EnableOAuthServiceProvider": false, "EnableOAuthServiceProvider": false,
"EnableIncomingWebhooks": true, "EnableIncomingWebhooks": true,
"EnablePostUsernameOverride": false,
"EnablePostIconOverride": false,
"EnableTesting": false "EnableTesting": false
}, },
"TeamSettings": { "TeamSettings": {

Просмотреть файл

@@ -6,6 +6,8 @@
"GoogleDeveloperKey": "", "GoogleDeveloperKey": "",
"EnableOAuthServiceProvider": false, "EnableOAuthServiceProvider": false,
"EnableIncomingWebhooks": true, "EnableIncomingWebhooks": true,
"EnablePostUsernameOverride": false,
"EnablePostIconOverride": false,
"EnableTesting": false "EnableTesting": false
}, },
"TeamSettings": { "TeamSettings": {

Просмотреть файл

@@ -29,6 +29,8 @@ type ServiceSettings struct {
GoogleDeveloperKey string GoogleDeveloperKey string
EnableOAuthServiceProvider bool EnableOAuthServiceProvider bool
EnableIncomingWebhooks bool EnableIncomingWebhooks bool
EnablePostUsernameOverride bool
EnablePostIconOverride bool
EnableTesting bool EnableTesting bool
} }

Просмотреть файл

@@ -184,6 +184,8 @@ func getClientProperties(c *model.Config) map[string]string {
props["SegmentDeveloperKey"] = c.ServiceSettings.SegmentDeveloperKey props["SegmentDeveloperKey"] = c.ServiceSettings.SegmentDeveloperKey
props["GoogleDeveloperKey"] = c.ServiceSettings.GoogleDeveloperKey props["GoogleDeveloperKey"] = c.ServiceSettings.GoogleDeveloperKey
props["EnableIncomingWebhooks"] = strconv.FormatBool(c.ServiceSettings.EnableIncomingWebhooks) props["EnableIncomingWebhooks"] = strconv.FormatBool(c.ServiceSettings.EnableIncomingWebhooks)
props["EnablePostUsernameOverride"] = strconv.FormatBool(c.ServiceSettings.EnablePostUsernameOverride)
props["EnablePostIconOverride"] = strconv.FormatBool(c.ServiceSettings.EnablePostIconOverride)
props["SendEmailNotifications"] = strconv.FormatBool(c.EmailSettings.SendEmailNotifications) props["SendEmailNotifications"] = strconv.FormatBool(c.EmailSettings.SendEmailNotifications)
props["EnableSignUpWithEmail"] = strconv.FormatBool(c.EmailSettings.EnableSignUpWithEmail) props["EnableSignUpWithEmail"] = strconv.FormatBool(c.EmailSettings.EnableSignUpWithEmail)

Просмотреть файл

@@ -37,6 +37,8 @@ export default class ServiceSettings extends React.Component {
config.ServiceSettings.GoogleDeveloperKey = React.findDOMNode(this.refs.GoogleDeveloperKey).value.trim(); config.ServiceSettings.GoogleDeveloperKey = React.findDOMNode(this.refs.GoogleDeveloperKey).value.trim();
//config.ServiceSettings.EnableOAuthServiceProvider = React.findDOMNode(this.refs.EnableOAuthServiceProvider).checked; //config.ServiceSettings.EnableOAuthServiceProvider = React.findDOMNode(this.refs.EnableOAuthServiceProvider).checked;
config.ServiceSettings.EnableIncomingWebhooks = React.findDOMNode(this.refs.EnableIncomingWebhooks).checked; config.ServiceSettings.EnableIncomingWebhooks = React.findDOMNode(this.refs.EnableIncomingWebhooks).checked;
config.ServiceSettings.EnablePostUsernameOverride = React.findDOMNode(this.refs.EnablePostUsernameOverride).checked;
config.ServiceSettings.EnablePostIconOverride = React.findDOMNode(this.refs.EnablePostIconOverride).checked;
config.ServiceSettings.EnableTesting = React.findDOMNode(this.refs.EnableTesting).checked; config.ServiceSettings.EnableTesting = React.findDOMNode(this.refs.EnableTesting).checked;
var MaximumLoginAttempts = 10; var MaximumLoginAttempts = 10;
@@ -203,6 +205,72 @@ export default class ServiceSettings extends React.Component {
</div> </div>
</div> </div>
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='EnablePostUsernameOverride'
>
{'Enable Overriding Usernames from Webhooks: '}
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
<input
type='radio'
name='EnablePostUsernameOverride'
value='true'
ref='EnablePostUsernameOverride'
defaultChecked={this.props.config.ServiceSettings.EnablePostUsernameOverride}
onChange={this.handleChange}
/>
{'true'}
</label>
<label className='radio-inline'>
<input
type='radio'
name='EnablePostUsernameOverride'
value='false'
defaultChecked={!this.props.config.ServiceSettings.EnablePostUsernameOverride}
onChange={this.handleChange}
/>
{'false'}
</label>
<p className='help-text'>{'When true, webhooks will be allowed to change the username they are posting as. Note, combined with allowing icon overriding, this could open users up to phishing attacks.'}</p>
</div>
</div>
<div className='form-group'>
<label
className='control-label col-sm-4'
htmlFor='EnablePostIconOverride'
>
{'Enable Overriding Icon from Webhooks: '}
</label>
<div className='col-sm-8'>
<label className='radio-inline'>
<input
type='radio'
name='EnablePostIconOverride'
value='true'
ref='EnablePostIconOverride'
defaultChecked={this.props.config.ServiceSettings.EnablePostIconOverride}
onChange={this.handleChange}
/>
{'true'}
</label>
<label className='radio-inline'>
<input
type='radio'
name='EnablePostIconOverride'
value='false'
defaultChecked={!this.props.config.ServiceSettings.EnablePostIconOverride}
onChange={this.handleChange}
/>
{'false'}
</label>
<p className='help-text'>{'When true, webhooks will be allowed to change the icon they post with. Note, combined with allowing username overriding, this could open users up to phishing attacks.'}</p>
</div>
</div>
<div className='form-group'> <div className='form-group'>
<label <label
className='control-label col-sm-4' className='control-label col-sm-4'

Просмотреть файл

@@ -159,8 +159,10 @@ export default class Post extends React.Component {
var profilePic = null; var profilePic = null;
if (!this.props.hideProfilePic) { if (!this.props.hideProfilePic) {
let src = '/api/v1/users/' + post.user_id + '/image?time=' + timestamp; let src = '/api/v1/users/' + post.user_id + '/image?time=' + timestamp;
if (post.props && post.props.override_icon_url) { if (post.props && post.props.from_webhook && global.window.config.EnablePostIconOverride === 'true') {
src = post.props.override_icon_url; if (post.props.override_icon_url) {
src = post.props.override_icon_url;
}
} }
profilePic = ( profilePic = (

Просмотреть файл

@@ -13,19 +13,26 @@ export default class PostHeader extends React.Component {
var post = this.props.post; var post = this.props.post;
let userProfile = <UserProfile userId={post.user_id} />; let userProfile = <UserProfile userId={post.user_id} />;
if (post.props && post.props.override_username) { let botIndicator;
userProfile = (
<UserProfile if (post.props && post.props.from_webhook) {
userId={post.user_id} if (post.props.override_username && global.window.config.EnablePostUsernameOverride === 'true') {
overwriteName={post.props.override_username} userProfile = (
disablePopover={true} <UserProfile
/> userId={post.user_id}
); overwriteName={post.props.override_username}
disablePopover={true}
/>
);
}
botIndicator = <li className='post-header-col post-header__name bot-indicator'>{'BOT'}</li>;
} }
return ( return (
<ul className='post-header post-header-post'> <ul className='post-header post-header-post'>
<li className='post-header-col post-header__name'><strong>{userProfile}</strong></li> <li className='post-header-col post-header__name'><strong>{userProfile}</strong></li>
{botIndicator}
<li className='post-info--hidden'> <li className='post-info--hidden'>
<PostInfo <PostInfo
post={post} post={post}

Просмотреть файл

@@ -520,13 +520,13 @@ export default class PostList extends React.Component {
// the previous post was made by the same user as the current post, // the previous post was made by the same user as the current post,
// the previous post is not a comment, // the previous post is not a comment,
// the current post is not a comment, // the current post is not a comment,
// the current profile pic is not overridden // the current post is not from a webhook
// and the previous profile pic is not overridden // and the previous post is not from a webhook
if ((prevPost.user_id === post.user_id) && if ((prevPost.user_id === post.user_id) &&
!utils.isComment(prevPost) && !utils.isComment(prevPost) &&
!utils.isComment(post) && !utils.isComment(post) &&
(!post.props || !post.props.override_icon_url) && (!post.props || !post.props.from_webhook) &&
(!prevPost.props || !prevPost.props.override_icon_url)) { (!prevPost.props || !prevPost.props.from_webhook)) {
hideProfilePic = true; hideProfilePic = true;
} }
} }

Просмотреть файл

@@ -509,3 +509,11 @@ body.ios {
} }
} }
} }
.bot-indicator {
background-color: lightgrey;
border-radius:2px;
padding-left:2px;
padding-right:2px;
font-family:"Courier New"
}

Просмотреть файл

@@ -843,6 +843,12 @@ func getAccessToken(c *api.Context, w http.ResponseWriter, r *http.Request) {
} }
func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) { func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks {
c.Err = model.NewAppError("incomingWebhook", "Incoming webhooks have been disabled by the system admin.", "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
params := mux.Vars(r) params := mux.Vars(r)
id := params["id"] id := params["id"]
@@ -913,12 +919,13 @@ func incomingWebhook(c *api.Context, w http.ResponseWriter, r *http.Request) {
pchan := api.Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId) pchan := api.Srv.Store.Channel().CheckPermissionsTo(hook.TeamId, channel.Id, hook.UserId)
post := &model.Post{UserId: hook.UserId, ChannelId: channel.Id, Message: text} post := &model.Post{UserId: hook.UserId, ChannelId: channel.Id, Message: text}
post.AddProp("from_webhook", "true")
if len(overrideUsername) != 0 { if len(overrideUsername) != 0 && utils.Cfg.ServiceSettings.EnablePostUsernameOverride {
post.AddProp("override_username", overrideUsername) post.AddProp("override_username", overrideUsername)
} }
if len(overrideIconUrl) != 0 { if len(overrideIconUrl) != 0 && utils.Cfg.ServiceSettings.EnablePostIconOverride {
post.AddProp("override_icon_url", overrideIconUrl) post.AddProp("override_icon_url", overrideIconUrl)
} }