summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md2
-rw-r--r--CONTRIBUTING.md4
-rw-r--r--ISSUE_TEMPLATE.md4
-rw-r--r--LICENSE.txt22
-rw-r--r--Makefile6
-rw-r--r--NOTICE.txt594
-rw-r--r--api/admin.go2
-rw-r--r--api/admin_test.go2
-rw-r--r--api/api.go2
-rw-r--r--api/apitestlib.go2
-rw-r--r--api/channel.go2
-rw-r--r--api/channel_test.go2
-rw-r--r--api/cli_test.go2
-rw-r--r--api/command.go2
-rw-r--r--api/command_echo_test.go2
-rw-r--r--api/command_expand_collapse_test.go2
-rw-r--r--api/command_invite_people_test.go2
-rw-r--r--api/command_join_test.go2
-rw-r--r--api/command_loadtest_test.go2
-rw-r--r--api/command_logout_test.go2
-rw-r--r--api/command_me_test.go2
-rw-r--r--api/command_msg_test.go2
-rw-r--r--api/command_shortcuts_test.go2
-rw-r--r--api/command_shrug_test.go2
-rw-r--r--api/command_statuses_test.go2
-rw-r--r--api/command_test.go2
-rw-r--r--api/context.go2
-rw-r--r--api/context_test.go2
-rw-r--r--api/deprecated.go2
-rw-r--r--api/deprecated_test.go2
-rw-r--r--api/emoji.go123
-rw-r--r--api/emoji_test.go103
-rw-r--r--api/file.go2
-rw-r--r--api/file_test.go2
-rw-r--r--api/general.go2
-rw-r--r--api/general_test.go2
-rw-r--r--api/license.go2
-rw-r--r--api/license_test.go2
-rw-r--r--api/oauth.go786
-rw-r--r--api/oauth_test.go4
-rw-r--r--api/post.go2
-rw-r--r--api/post_test.go2
-rw-r--r--api/preference.go2
-rw-r--r--api/preference_test.go2
-rw-r--r--api/reaction.go2
-rw-r--r--api/reaction_test.go2
-rw-r--r--api/server_test.go2
-rw-r--r--api/status.go2
-rw-r--r--api/status_test.go2
-rw-r--r--api/team.go2
-rw-r--r--api/team_test.go2
-rw-r--r--api/user.go220
-rw-r--r--api/user_test.go2
-rw-r--r--api/webhook.go2
-rw-r--r--api/webhook_test.go2
-rw-r--r--api/webrtc.go74
-rw-r--r--api/websocket.go2
-rw-r--r--api/websocket_test.go2
-rw-r--r--api4/api.go7
-rw-r--r--api4/apitestlib.go17
-rw-r--r--api4/brand.go2
-rw-r--r--api4/brand_test.go2
-rw-r--r--api4/channel.go2
-rw-r--r--api4/channel_test.go26
-rw-r--r--api4/cluster.go2
-rw-r--r--api4/cluster_test.go2
-rw-r--r--api4/command.go128
-rw-r--r--api4/command_test.go189
-rw-r--r--api4/compliance.go2
-rw-r--r--api4/context.go27
-rw-r--r--api4/emoji.go131
-rw-r--r--api4/emoji_test.go300
-rw-r--r--api4/file.go2
-rw-r--r--api4/file_test.go2
-rw-r--r--api4/ldap.go2
-rw-r--r--api4/ldap_test.go2
-rw-r--r--api4/params.go2
-rw-r--r--api4/post.go36
-rw-r--r--api4/post_test.go183
-rw-r--r--api4/preference.go2
-rw-r--r--api4/preference_test.go2
-rw-r--r--api4/reaction.go39
-rw-r--r--api4/reaction_test.go89
-rw-r--r--api4/saml.go2
-rw-r--r--api4/saml_test.go2
-rw-r--r--api4/status.go2
-rw-r--r--api4/system.go2
-rw-r--r--api4/team.go2
-rw-r--r--api4/team_test.go2
-rw-r--r--api4/user.go72
-rw-r--r--api4/user_test.go138
-rw-r--r--api4/webhook.go2
-rw-r--r--api4/webhook_test.go2
-rw-r--r--api4/webrtc.go29
-rw-r--r--api4/webrtc_test.go29
-rw-r--r--api4/websocket.go2
-rw-r--r--api4/websocket_test.go2
-rw-r--r--app/admin.go4
-rw-r--r--app/analytics.go2
-rw-r--r--app/app.go2
-rw-r--r--app/apptestlib.go10
-rw-r--r--app/audit.go2
-rw-r--r--app/authentication.go23
-rw-r--r--app/authorization.go2
-rw-r--r--app/authorization_test.go2
-rw-r--r--app/auto_channels.go2
-rw-r--r--app/auto_constants.go2
-rw-r--r--app/auto_environment.go2
-rw-r--r--app/auto_posts.go2
-rw-r--r--app/auto_teams.go2
-rw-r--r--app/auto_users.go2
-rw-r--r--app/brand.go2
-rw-r--r--app/channel.go4
-rw-r--r--app/command.go3
-rw-r--r--app/command_away.go2
-rw-r--r--app/command_echo.go2
-rw-r--r--app/command_expand_collapse.go2
-rw-r--r--app/command_invite_people.go2
-rw-r--r--app/command_join.go2
-rw-r--r--app/command_loadtest.go2
-rw-r--r--app/command_logout.go2
-rw-r--r--app/command_me.go2
-rw-r--r--app/command_msg.go2
-rw-r--r--app/command_offline.go2
-rw-r--r--app/command_online.go2
-rw-r--r--app/command_shortcuts.go2
-rw-r--r--app/command_shrug.go2
-rw-r--r--app/compliance.go2
-rw-r--r--app/diagnostics.go2
-rw-r--r--app/diagnostics_test.go2
-rw-r--r--app/email.go17
-rw-r--r--app/email_batching.go2
-rw-r--r--app/email_batching_test.go2
-rw-r--r--app/email_test.go2
-rw-r--r--app/emoji.go206
-rw-r--r--app/file.go2
-rw-r--r--app/file_test.go2
-rw-r--r--app/import.go2
-rw-r--r--app/import_test.go2
-rw-r--r--app/ldap.go80
-rw-r--r--app/license.go2
-rw-r--r--app/license_test.go2
-rw-r--r--app/login.go2
-rw-r--r--app/notification.go2
-rw-r--r--app/notification_test.go2
-rw-r--r--app/oauth.go649
-rw-r--r--app/oauth_test.go2
-rw-r--r--app/post.go14
-rw-r--r--app/preference.go2
-rw-r--r--app/reaction.go16
-rw-r--r--app/saml.go2
-rw-r--r--app/security_update_check.go2
-rw-r--r--app/server.go2
-rw-r--r--app/session.go2
-rw-r--r--app/session_test.go2
-rw-r--r--app/slackimport.go2
-rw-r--r--app/slackimport_test.go2
-rw-r--r--app/status.go2
-rw-r--r--app/team.go33
-rw-r--r--app/team_test.go2
-rw-r--r--app/user.go6
-rw-r--r--app/user_test.go2
-rw-r--r--app/web_conn.go2
-rw-r--r--app/web_hub.go2
-rw-r--r--app/webhook.go2
-rw-r--r--app/webrtc.go87
-rw-r--r--app/websocket_router.go2
-rw-r--r--app/webtrc.go2
-rw-r--r--build/MIT-COMPILED-LICENSE.md2
-rw-r--r--cmd/platform/channel.go2
-rw-r--r--cmd/platform/channelargs.go2
-rw-r--r--cmd/platform/channelargs_test.go.disabled106
-rw-r--r--cmd/platform/cmdtestlib.go45
-rw-r--r--cmd/platform/config.go66
-rw-r--r--cmd/platform/import.go2
-rw-r--r--cmd/platform/init.go1
-rw-r--r--cmd/platform/ldap.go2
-rw-r--r--cmd/platform/license.go2
-rw-r--r--cmd/platform/mattermost.go24
-rw-r--r--cmd/platform/output.go2
-rw-r--r--cmd/platform/roles.go2
-rw-r--r--cmd/platform/server.go4
-rw-r--r--cmd/platform/team.go2
-rw-r--r--cmd/platform/teamargs.go2
-rw-r--r--cmd/platform/teamargs_test.go.disabled58
-rw-r--r--cmd/platform/test.go2
-rw-r--r--cmd/platform/user.go83
-rw-r--r--cmd/platform/user_test.go.disabled212
-rw-r--r--cmd/platform/userargs.go2
-rw-r--r--cmd/platform/userargs_test.go.disabled58
-rw-r--r--cmd/platform/version.go2
-rw-r--r--config/config.json4
-rw-r--r--einterfaces/account_migration.go2
-rw-r--r--einterfaces/brand.go2
-rw-r--r--einterfaces/cluster.go2
-rw-r--r--einterfaces/compliance.go2
-rw-r--r--einterfaces/emoji.go2
-rw-r--r--einterfaces/ldap.go2
-rw-r--r--einterfaces/metrics.go2
-rw-r--r--einterfaces/mfa.go2
-rw-r--r--einterfaces/oauthproviders.go2
-rw-r--r--einterfaces/saml.go2
-rw-r--r--i18n/en.json18
-rw-r--r--manualtesting/manual_testing.go2
-rw-r--r--manualtesting/test_autolink.go2
-rw-r--r--mkdocs.yml2
-rw-r--r--model/access.go3
-rw-r--r--model/access_test.go2
-rw-r--r--model/analytics_row.go2
-rw-r--r--model/analytics_row_test.go2
-rw-r--r--model/audit.go2
-rw-r--r--model/audit_test.go2
-rw-r--r--model/audits.go2
-rw-r--r--model/audits_test.go2
-rw-r--r--model/authorization.go2
-rw-r--r--model/authorize.go2
-rw-r--r--model/authorize_test.go2
-rw-r--r--model/channel.go2
-rw-r--r--model/channel_count.go2
-rw-r--r--model/channel_data.go2
-rw-r--r--model/channel_list.go2
-rw-r--r--model/channel_member.go2
-rw-r--r--model/channel_member_test.go2
-rw-r--r--model/channel_search.go2
-rw-r--r--model/channel_search_test.go2
-rw-r--r--model/channel_stats.go2
-rw-r--r--model/channel_test.go2
-rw-r--r--model/channel_view.go2
-rw-r--r--model/client.go7
-rw-r--r--model/client4.go208
-rw-r--r--model/cluster_info.go2
-rw-r--r--model/cluster_info_test.go2
-rw-r--r--model/cluster_stats.go2
-rw-r--r--model/cluster_stats_test.go2
-rw-r--r--model/command.go2
-rw-r--r--model/command_args.go2
-rw-r--r--model/command_response.go2
-rw-r--r--model/command_response_test.go2
-rw-r--r--model/command_test.go2
-rw-r--r--model/compliance.go2
-rw-r--r--model/compliance_post.go2
-rw-r--r--model/compliance_post_test.go2
-rw-r--r--model/compliance_test.go2
-rw-r--r--model/config.go8
-rw-r--r--model/emoji.go2
-rw-r--r--model/emoji_test.go2
-rw-r--r--model/file.go2
-rw-r--r--model/file_info.go2
-rw-r--r--model/file_info_test.go2
-rw-r--r--model/gitlab.go2
-rw-r--r--model/gitlab/gitlab.go2
-rw-r--r--model/incoming_webhook.go2
-rw-r--r--model/incoming_webhook_test.go2
-rw-r--r--model/initial_load.go2
-rw-r--r--model/initial_load_test.go2
-rw-r--r--model/job.go2
-rw-r--r--model/job_test.go2
-rw-r--r--model/ldap.go2
-rw-r--r--model/license.go2
-rw-r--r--model/license_test.go2
-rw-r--r--model/mfa_secret.go2
-rw-r--r--model/mfa_secret_test.go2
-rw-r--r--model/oauth.go2
-rw-r--r--model/oauth_test.go2
-rw-r--r--model/outgoing_webhook.go2
-rw-r--r--model/outgoing_webhook_test.go2
-rw-r--r--model/password_recovery.go2
-rw-r--r--model/post.go2
-rw-r--r--model/post_list.go2
-rw-r--r--model/post_list_test.go2
-rw-r--r--model/post_test.go2
-rw-r--r--model/preference.go2
-rw-r--r--model/preference_test.go2
-rw-r--r--model/preferences.go2
-rw-r--r--model/push_notification.go2
-rw-r--r--model/push_notification_test.go2
-rw-r--r--model/push_response.go2
-rw-r--r--model/reaction.go2
-rw-r--r--model/reaction_test.go2
-rw-r--r--model/saml.go2
-rw-r--r--model/saml_test.go2
-rw-r--r--model/search_params.go12
-rw-r--r--model/search_params_test.go2
-rw-r--r--model/security_bulletin.go2
-rw-r--r--model/session.go2
-rw-r--r--model/session_test.go2
-rw-r--r--model/slack_attachment.go2
-rw-r--r--model/status.go2
-rw-r--r--model/status_test.go2
-rw-r--r--model/suggest_command.go2
-rw-r--r--model/suggest_command_test.go2
-rw-r--r--model/switch_request.go62
-rw-r--r--model/switch_request_test.go19
-rw-r--r--model/system.go2
-rw-r--r--model/system_test.go2
-rw-r--r--model/team.go2
-rw-r--r--model/team_member.go2
-rw-r--r--model/team_member_test.go2
-rw-r--r--model/team_search.go2
-rw-r--r--model/team_search_test.go2
-rw-r--r--model/team_stats.go2
-rw-r--r--model/team_test.go2
-rw-r--r--model/user.go42
-rw-r--r--model/user_autocomplete.go2
-rw-r--r--model/user_search.go2
-rw-r--r--model/user_search_test.go2
-rw-r--r--model/user_test.go57
-rw-r--r--model/utils.go2
-rw-r--r--model/utils_test.go2
-rw-r--r--model/version.go2
-rw-r--r--model/version_test.go2
-rw-r--r--model/webrtc.go32
-rw-r--r--model/webrtc_test.go19
-rw-r--r--model/websocket_client.go2
-rw-r--r--model/websocket_message.go2
-rw-r--r--model/websocket_message_test.go2
-rw-r--r--model/websocket_request.go2
-rw-r--r--model/websocket_request_test.go2
-rw-r--r--store/sql_audit_store.go2
-rw-r--r--store/sql_audit_store_test.go2
-rw-r--r--store/sql_channel_store.go2
-rw-r--r--store/sql_channel_store_test.go2
-rw-r--r--store/sql_command_store.go2
-rw-r--r--store/sql_command_store_test.go2
-rw-r--r--store/sql_compliance_store.go2
-rw-r--r--store/sql_compliance_store_test.go2
-rw-r--r--store/sql_emoji_store.go2
-rw-r--r--store/sql_emoji_store_test.go2
-rw-r--r--store/sql_file_info_store_test.go2
-rw-r--r--store/sql_license_store.go2
-rw-r--r--store/sql_license_store_test.go2
-rw-r--r--store/sql_oauth_store.go26
-rw-r--r--store/sql_oauth_store_test.go14
-rw-r--r--store/sql_post_store.go56
-rw-r--r--store/sql_post_store_test.go123
-rw-r--r--store/sql_preference_store.go2
-rw-r--r--store/sql_preference_store_test.go2
-rw-r--r--store/sql_reaction_store.go2
-rw-r--r--store/sql_reaction_store_test.go2
-rw-r--r--store/sql_recovery_store.go2
-rw-r--r--store/sql_recovery_store_test.go2
-rw-r--r--store/sql_session_store.go2
-rw-r--r--store/sql_session_store_test.go2
-rw-r--r--store/sql_status_store.go2
-rw-r--r--store/sql_status_store_test.go2
-rw-r--r--store/sql_store.go2
-rw-r--r--store/sql_store_test.go2
-rw-r--r--store/sql_system_store.go2
-rw-r--r--store/sql_system_store_test.go2
-rw-r--r--store/sql_team_store.go2
-rw-r--r--store/sql_team_store_test.go2
-rw-r--r--store/sql_upgrade.go13
-rw-r--r--store/sql_upgrade_test.go2
-rw-r--r--store/sql_user_store.go5
-rw-r--r--store/sql_user_store_test.go2
-rw-r--r--store/sql_webhook_store.go2
-rw-r--r--store/sql_webhook_store_test.go2
-rw-r--r--store/store.go9
-rw-r--r--utils/api.go2
-rw-r--r--utils/authorization.go2
-rw-r--r--utils/config.go20
-rw-r--r--utils/config_test.go2
-rw-r--r--utils/emoji.go62
-rw-r--r--utils/html.go2
-rw-r--r--utils/license.go2
-rw-r--r--utils/license_test.go2
-rw-r--r--utils/log.go2
-rw-r--r--utils/mail.go2
-rw-r--r--utils/mail_test.go2
-rw-r--r--utils/password.go2
-rw-r--r--utils/random.go2
-rw-r--r--utils/textgeneration.go2
-rw-r--r--utils/time_test.go2
-rw-r--r--utils/urlencode.go2
-rw-r--r--utils/urlencode_test.go2
-rw-r--r--utils/utils.go2
-rw-r--r--utils/utils_test.go2
-rw-r--r--web/web.go2
-rw-r--r--web/web_test.go2
-rw-r--r--webapp/actions/admin_actions.jsx2
-rw-r--r--webapp/actions/channel_actions.jsx6
-rw-r--r--webapp/actions/diagnostics_actions.jsx2
-rw-r--r--webapp/actions/emoji_actions.jsx2
-rw-r--r--webapp/actions/file_actions.jsx2
-rw-r--r--webapp/actions/global_actions.jsx4
-rw-r--r--webapp/actions/integration_actions.jsx2
-rw-r--r--webapp/actions/notification_actions.jsx2
-rw-r--r--webapp/actions/oauth_actions.jsx4
-rw-r--r--webapp/actions/post_actions.jsx2
-rw-r--r--webapp/actions/status_actions.jsx2
-rw-r--r--webapp/actions/team_actions.jsx2
-rw-r--r--webapp/actions/user_actions.jsx2
-rw-r--r--webapp/actions/webrtc_actions.jsx2
-rw-r--r--webapp/actions/websocket_actions.jsx2
-rw-r--r--webapp/client/browser_web_client.jsx2
-rw-r--r--webapp/client/client.jsx2
-rw-r--r--webapp/client/web_client.jsx2
-rw-r--r--webapp/client/web_websocket_client.jsx2
-rw-r--r--webapp/client/websocket_client.jsx2
-rw-r--r--webapp/components/about_build_modal.jsx7
-rw-r--r--webapp/components/access_history_modal.jsx2
-rw-r--r--webapp/components/activity_log_modal.jsx2
-rw-r--r--webapp/components/add_users_to_team.jsx2
-rw-r--r--webapp/components/admin_console/admin_console.jsx2
-rw-r--r--webapp/components/admin_console/admin_navbar_dropdown.jsx7
-rw-r--r--webapp/components/admin_console/admin_settings.jsx2
-rw-r--r--webapp/components/admin_console/admin_sidebar.jsx2
-rw-r--r--webapp/components/admin_console/admin_sidebar_category.jsx2
-rw-r--r--webapp/components/admin_console/admin_sidebar_header.jsx2
-rw-r--r--webapp/components/admin_console/admin_sidebar_section.jsx2
-rw-r--r--webapp/components/admin_console/audits.jsx2
-rw-r--r--webapp/components/admin_console/banner.jsx2
-rw-r--r--webapp/components/admin_console/boolean_setting.jsx2
-rw-r--r--webapp/components/admin_console/brand_image_setting.jsx2
-rw-r--r--webapp/components/admin_console/cluster_settings.jsx2
-rw-r--r--webapp/components/admin_console/cluster_table.jsx2
-rw-r--r--webapp/components/admin_console/cluster_table_container.jsx5
-rw-r--r--webapp/components/admin_console/compliance_reports.jsx2
-rw-r--r--webapp/components/admin_console/compliance_settings.jsx2
-rw-r--r--webapp/components/admin_console/configuration_settings.jsx2
-rw-r--r--webapp/components/admin_console/connection_security_dropdown_setting.jsx2
-rw-r--r--webapp/components/admin_console/connection_settings.jsx2
-rw-r--r--webapp/components/admin_console/custom_brand_settings.jsx2
-rw-r--r--webapp/components/admin_console/custom_emoji_settings.jsx2
-rw-r--r--webapp/components/admin_console/custom_integrations_settings.jsx2
-rw-r--r--webapp/components/admin_console/database_settings.jsx2
-rw-r--r--webapp/components/admin_console/developer_settings.jsx4
-rw-r--r--webapp/components/admin_console/dropdown_setting.jsx2
-rw-r--r--webapp/components/admin_console/email_authentication_settings.jsx2
-rw-r--r--webapp/components/admin_console/email_connection_test.jsx2
-rw-r--r--webapp/components/admin_console/email_settings.jsx2
-rw-r--r--webapp/components/admin_console/external_service_settings.jsx2
-rw-r--r--webapp/components/admin_console/file_upload_setting.jsx2
-rw-r--r--webapp/components/admin_console/generated_setting.jsx2
-rw-r--r--webapp/components/admin_console/gitlab_settings.jsx2
-rw-r--r--webapp/components/admin_console/image_settings.jsx2
-rw-r--r--webapp/components/admin_console/ldap_settings.jsx2
-rw-r--r--webapp/components/admin_console/ldap_test_button.jsx2
-rw-r--r--webapp/components/admin_console/legal_and_support_settings.jsx2
-rw-r--r--webapp/components/admin_console/license_settings.jsx2
-rw-r--r--webapp/components/admin_console/link_previews_settings.jsx2
-rw-r--r--webapp/components/admin_console/localization_settings.jsx2
-rw-r--r--webapp/components/admin_console/log_settings.jsx2
-rw-r--r--webapp/components/admin_console/logs.jsx2
-rw-r--r--webapp/components/admin_console/manage_teams_modal/manage_teams_dropdown.jsx2
-rw-r--r--webapp/components/admin_console/manage_teams_modal/manage_teams_modal.jsx2
-rw-r--r--webapp/components/admin_console/manage_teams_modal/remove_from_team_button.jsx2
-rw-r--r--webapp/components/admin_console/metrics_settings.jsx2
-rw-r--r--webapp/components/admin_console/mfa_settings.jsx2
-rw-r--r--webapp/components/admin_console/multiselect_settings.jsx2
-rw-r--r--webapp/components/admin_console/native_app_link_settings.jsx2
-rw-r--r--webapp/components/admin_console/oauth_settings.jsx2
-rw-r--r--webapp/components/admin_console/password_settings.jsx12
-rw-r--r--webapp/components/admin_console/policy_settings.jsx2
-rw-r--r--webapp/components/admin_console/post_edit_setting.jsx2
-rw-r--r--webapp/components/admin_console/privacy_settings.jsx2
-rw-r--r--webapp/components/admin_console/public_link_settings.jsx2
-rw-r--r--webapp/components/admin_console/purge_caches.jsx2
-rw-r--r--webapp/components/admin_console/push_settings.jsx2
-rw-r--r--webapp/components/admin_console/radio_setting.jsx2
-rw-r--r--webapp/components/admin_console/rate_settings.jsx2
-rw-r--r--webapp/components/admin_console/recycle_db.jsx4
-rw-r--r--webapp/components/admin_console/reload_config.jsx2
-rw-r--r--webapp/components/admin_console/remove_file_setting.jsx4
-rw-r--r--webapp/components/admin_console/reset_password_modal.jsx2
-rw-r--r--webapp/components/admin_console/saml_settings.jsx2
-rw-r--r--webapp/components/admin_console/save_button.jsx2
-rw-r--r--webapp/components/admin_console/session_settings.jsx2
-rw-r--r--webapp/components/admin_console/setting.jsx2
-rw-r--r--webapp/components/admin_console/settings_group.jsx2
-rw-r--r--webapp/components/admin_console/signup_settings.jsx2
-rw-r--r--webapp/components/admin_console/storage_settings.jsx2
-rw-r--r--webapp/components/admin_console/sync_now_button.jsx2
-rw-r--r--webapp/components/admin_console/system_users/system_users.jsx2
-rw-r--r--webapp/components/admin_console/system_users/system_users_dropdown.jsx2
-rw-r--r--webapp/components/admin_console/system_users/system_users_list.jsx2
-rw-r--r--webapp/components/admin_console/text_setting.jsx2
-rw-r--r--webapp/components/admin_console/users_and_teams_settings.jsx2
-rw-r--r--webapp/components/admin_console/webrtc_settings.jsx2
-rw-r--r--webapp/components/admin_console/webserver_mode_dropdown_setting.jsx2
-rw-r--r--webapp/components/analytics/doughnut_chart.jsx2
-rw-r--r--webapp/components/analytics/line_chart.jsx2
-rw-r--r--webapp/components/analytics/statistic_count.jsx2
-rw-r--r--webapp/components/analytics/system_analytics.jsx2
-rw-r--r--webapp/components/analytics/table_chart.jsx2
-rw-r--r--webapp/components/analytics/team_analytics.jsx2
-rw-r--r--webapp/components/audio_video_preview.jsx2
-rw-r--r--webapp/components/audit_table.jsx2
-rw-r--r--webapp/components/authorize.jsx2
-rw-r--r--webapp/components/autosize_textarea.jsx2
-rw-r--r--webapp/components/backstage/backstage_controller.jsx2
-rw-r--r--webapp/components/backstage/components/backstage_category.jsx2
-rw-r--r--webapp/components/backstage/components/backstage_header.jsx2
-rw-r--r--webapp/components/backstage/components/backstage_list.jsx2
-rw-r--r--webapp/components/backstage/components/backstage_navbar.jsx2
-rw-r--r--webapp/components/backstage/components/backstage_section.jsx2
-rw-r--r--webapp/components/backstage/components/backstage_sidebar.jsx2
-rw-r--r--webapp/components/change_url_modal.jsx2
-rw-r--r--webapp/components/channel_header.jsx2
-rw-r--r--webapp/components/channel_info_modal.jsx2
-rw-r--r--webapp/components/channel_invite_button.jsx2
-rw-r--r--webapp/components/channel_invite_modal.jsx2
-rw-r--r--webapp/components/channel_members_dropdown.jsx2
-rw-r--r--webapp/components/channel_members_modal.jsx2
-rw-r--r--webapp/components/channel_notifications_modal.jsx2
-rw-r--r--webapp/components/channel_select.jsx2
-rw-r--r--webapp/components/channel_switch_modal.jsx2
-rw-r--r--webapp/components/channel_view.jsx2
-rw-r--r--webapp/components/claim/claim_controller.jsx2
-rw-r--r--webapp/components/claim/components/email_to_ldap.jsx2
-rw-r--r--webapp/components/claim/components/email_to_oauth.jsx2
-rw-r--r--webapp/components/claim/components/ldap_to_email.jsx2
-rw-r--r--webapp/components/claim/components/oauth_to_email.jsx2
-rw-r--r--webapp/components/code_preview.jsx2
-rw-r--r--webapp/components/confirm_modal.jsx2
-rw-r--r--webapp/components/create_comment.jsx2
-rw-r--r--webapp/components/create_post.jsx2
-rw-r--r--webapp/components/create_team/components/display_name.jsx2
-rw-r--r--webapp/components/create_team/components/team_url.jsx2
-rw-r--r--webapp/components/create_team/create_team_controller.jsx2
-rw-r--r--webapp/components/delete_channel_modal.jsx2
-rw-r--r--webapp/components/delete_post_modal.jsx2
-rw-r--r--webapp/components/do_verify_email.jsx2
-rw-r--r--webapp/components/edit_channel_header_modal.jsx2
-rw-r--r--webapp/components/edit_channel_purpose_modal.jsx2
-rw-r--r--webapp/components/edit_post_modal.jsx2
-rw-r--r--webapp/components/emoji/components/add_emoji.jsx2
-rw-r--r--webapp/components/emoji/components/delete_emoji_modal.jsx2
-rw-r--r--webapp/components/emoji/components/emoji_list.jsx2
-rw-r--r--webapp/components/emoji/components/emoji_list_item.jsx2
-rw-r--r--webapp/components/emoji_picker/components/emoji_picker_category.jsx4
-rw-r--r--webapp/components/emoji_picker/components/emoji_picker_item.jsx2
-rw-r--r--webapp/components/emoji_picker/components/emoji_picker_preview.jsx4
-rw-r--r--webapp/components/emoji_picker/emoji_picker.jsx2
-rw-r--r--webapp/components/emoji_picker/emoji_picker_container.jsx2
-rw-r--r--webapp/components/error_bar.jsx2
-rw-r--r--webapp/components/error_page.jsx2
-rw-r--r--webapp/components/file_attachment.jsx4
-rw-r--r--webapp/components/file_attachment_list.jsx2
-rw-r--r--webapp/components/file_attachment_list_container.jsx2
-rw-r--r--webapp/components/file_info_preview.jsx2
-rw-r--r--webapp/components/file_preview.jsx4
-rw-r--r--webapp/components/file_upload.jsx2
-rw-r--r--webapp/components/file_upload_overlay.jsx2
-rw-r--r--webapp/components/filtered_user_list.jsx2
-rw-r--r--webapp/components/form_error.jsx2
-rw-r--r--webapp/components/get_android_app/get_android_app.jsx4
-rw-r--r--webapp/components/get_ios_app/get_ios_app.jsx4
-rw-r--r--webapp/components/get_link_modal.jsx2
-rw-r--r--webapp/components/get_post_link_modal.jsx2
-rw-r--r--webapp/components/get_public_link_modal.jsx2
-rw-r--r--webapp/components/get_team_invite_link_modal.jsx2
-rw-r--r--webapp/components/header_footer_template.jsx2
-rw-r--r--webapp/components/help/components/attaching.jsx2
-rw-r--r--webapp/components/help/components/commands.jsx2
-rw-r--r--webapp/components/help/components/composing.jsx2
-rw-r--r--webapp/components/help/components/formatting.jsx2
-rw-r--r--webapp/components/help/components/mentioning.jsx2
-rw-r--r--webapp/components/help/components/messaging.jsx2
-rw-r--r--webapp/components/help/help_controller.jsx4
-rw-r--r--webapp/components/integrations/components/abstract_incoming_webhook.jsx2
-rw-r--r--webapp/components/integrations/components/abstract_outgoing_webhook.jsx2
-rw-r--r--webapp/components/integrations/components/add_command.jsx2
-rw-r--r--webapp/components/integrations/components/add_incoming_webhook.jsx2
-rw-r--r--webapp/components/integrations/components/add_oauth_app.jsx2
-rw-r--r--webapp/components/integrations/components/add_outgoing_webhook.jsx2
-rw-r--r--webapp/components/integrations/components/commands_container.jsx2
-rw-r--r--webapp/components/integrations/components/confirm_integration.jsx2
-rw-r--r--webapp/components/integrations/components/edit_command.jsx2
-rw-r--r--webapp/components/integrations/components/edit_incoming_webhook.jsx2
-rw-r--r--webapp/components/integrations/components/edit_outgoing_webhook.jsx2
-rw-r--r--webapp/components/integrations/components/installed_command.jsx2
-rw-r--r--webapp/components/integrations/components/installed_commands.jsx2
-rw-r--r--webapp/components/integrations/components/installed_incoming_webhook.jsx2
-rw-r--r--webapp/components/integrations/components/installed_incoming_webhooks.jsx2
-rw-r--r--webapp/components/integrations/components/installed_oauth_app.jsx2
-rw-r--r--webapp/components/integrations/components/installed_oauth_apps.jsx2
-rw-r--r--webapp/components/integrations/components/installed_outgoing_webhook.jsx2
-rw-r--r--webapp/components/integrations/components/installed_outgoing_webhooks.jsx2
-rw-r--r--webapp/components/integrations/components/integration_option.jsx2
-rw-r--r--webapp/components/integrations/components/integrations.jsx2
-rw-r--r--webapp/components/invite_member_modal.jsx2
-rw-r--r--webapp/components/leave_team_modal.jsx2
-rw-r--r--webapp/components/loading_screen.jsx2
-rw-r--r--webapp/components/logged_in.jsx2
-rw-r--r--webapp/components/login/components/login_mfa.jsx2
-rw-r--r--webapp/components/login/login_controller.jsx2
-rw-r--r--webapp/components/member_list_channel.jsx2
-rw-r--r--webapp/components/member_list_team.jsx2
-rw-r--r--webapp/components/message_wrapper.jsx2
-rw-r--r--webapp/components/mfa/components/confirm.jsx2
-rw-r--r--webapp/components/mfa/components/setup.jsx2
-rw-r--r--webapp/components/mfa/mfa_controller.jsx2
-rw-r--r--webapp/components/more_channels.jsx2
-rw-r--r--webapp/components/more_direct_channels.jsx2
-rw-r--r--webapp/components/msg_typing.jsx2
-rw-r--r--webapp/components/multiselect/multiselect.jsx2
-rw-r--r--webapp/components/multiselect/multiselect_list.jsx2
-rw-r--r--webapp/components/navbar.jsx2
-rw-r--r--webapp/components/needs_team.jsx2
-rw-r--r--webapp/components/new_channel_flow.jsx2
-rw-r--r--webapp/components/new_channel_modal.jsx2
-rw-r--r--webapp/components/notify_counts.jsx2
-rw-r--r--webapp/components/password_reset_form.jsx2
-rw-r--r--webapp/components/password_reset_send_link.jsx2
-rw-r--r--webapp/components/pdf_preview.jsx2
-rw-r--r--webapp/components/permalink_view.jsx2
-rw-r--r--webapp/components/popover_list_members.jsx2
-rw-r--r--webapp/components/post_deleted_modal.jsx2
-rw-r--r--webapp/components/post_view/components/commented_on_files_message_container.jsx2
-rw-r--r--webapp/components/post_view/components/floating_timestamp.jsx2
-rw-r--r--webapp/components/post_view/components/new_message_indicator.jsx2
-rw-r--r--webapp/components/post_view/components/pending_post_options.jsx16
-rw-r--r--webapp/components/post_view/components/post.jsx2
-rw-r--r--webapp/components/post_view/components/post_attachment.jsx2
-rw-r--r--webapp/components/post_view/components/post_attachment_list.jsx2
-rw-r--r--webapp/components/post_view/components/post_attachment_opengraph.jsx2
-rw-r--r--webapp/components/post_view/components/post_body.jsx2
-rw-r--r--webapp/components/post_view/components/post_body_additional_content.jsx25
-rw-r--r--webapp/components/post_view/components/post_header.jsx2
-rw-r--r--webapp/components/post_view/components/post_image.jsx2
-rw-r--r--webapp/components/post_view/components/post_info.jsx2
-rw-r--r--webapp/components/post_view/components/post_list.jsx2
-rw-r--r--webapp/components/post_view/components/post_message_container.jsx2
-rw-r--r--webapp/components/post_view/components/post_message_view.jsx2
-rw-r--r--webapp/components/post_view/components/post_time.jsx2
-rw-r--r--webapp/components/post_view/components/reaction.jsx2
-rw-r--r--webapp/components/post_view/components/reaction_container.jsx2
-rw-r--r--webapp/components/post_view/components/reaction_list_container.jsx2
-rw-r--r--webapp/components/post_view/components/reaction_list_view.jsx2
-rw-r--r--webapp/components/post_view/components/scroll_to_bottom_arrows.jsx2
-rw-r--r--webapp/components/post_view/components/system_message_helpers.jsx2
-rw-r--r--webapp/components/post_view/post_focus_view_controller.jsx2
-rw-r--r--webapp/components/post_view/post_view_cache.jsx2
-rw-r--r--webapp/components/post_view/post_view_controller.jsx2
-rw-r--r--webapp/components/profile_picture.jsx2
-rw-r--r--webapp/components/profile_popover.jsx2
-rw-r--r--webapp/components/removed_from_channel_modal.jsx2
-rw-r--r--webapp/components/rename_channel_modal.jsx2
-rw-r--r--webapp/components/rhs_comment.jsx2
-rw-r--r--webapp/components/rhs_dropdown.jsx2
-rw-r--r--webapp/components/rhs_dropdown_menu.jsx2
-rw-r--r--webapp/components/rhs_header_post.jsx2
-rw-r--r--webapp/components/rhs_root_post.jsx2
-rw-r--r--webapp/components/rhs_thread.jsx2
-rw-r--r--webapp/components/root.jsx2
-rw-r--r--webapp/components/search_bar.jsx2
-rw-r--r--webapp/components/search_results.jsx2
-rw-r--r--webapp/components/search_results_header.jsx2
-rw-r--r--webapp/components/search_results_item.jsx2
-rw-r--r--webapp/components/searchable_channel_list.jsx4
-rw-r--r--webapp/components/searchable_user_list/searchable_user_list.jsx2
-rw-r--r--webapp/components/searchable_user_list/searchable_user_list_container.jsx2
-rw-r--r--webapp/components/select_team/components/select_team_item.jsx2
-rw-r--r--webapp/components/select_team/select_team.jsx2
-rw-r--r--webapp/components/setting_item_max.jsx2
-rw-r--r--webapp/components/setting_item_min.jsx2
-rw-r--r--webapp/components/setting_picture.jsx4
-rw-r--r--webapp/components/setting_upload.jsx4
-rw-r--r--webapp/components/settings_sidebar.jsx2
-rw-r--r--webapp/components/should_verify_email.jsx2
-rw-r--r--webapp/components/sidebar.jsx2
-rw-r--r--webapp/components/sidebar_header.jsx2
-rw-r--r--webapp/components/sidebar_header_dropdown.jsx2
-rw-r--r--webapp/components/sidebar_header_dropdown_button.jsx2
-rw-r--r--webapp/components/sidebar_right.jsx2
-rw-r--r--webapp/components/sidebar_right_menu.jsx2
-rw-r--r--webapp/components/signup/components/signup_email.jsx2
-rw-r--r--webapp/components/signup/components/signup_ldap.jsx2
-rw-r--r--webapp/components/signup/signup_controller.jsx2
-rw-r--r--webapp/components/spinner_button.jsx2
-rw-r--r--webapp/components/status_icon.jsx2
-rw-r--r--webapp/components/suggestion/at_mention_provider.jsx2
-rw-r--r--webapp/components/suggestion/channel_mention_provider.jsx2
-rw-r--r--webapp/components/suggestion/command_provider.jsx2
-rw-r--r--webapp/components/suggestion/emoticon_provider.jsx2
-rw-r--r--webapp/components/suggestion/provider.jsx2
-rw-r--r--webapp/components/suggestion/search_channel_provider.jsx2
-rw-r--r--webapp/components/suggestion/search_suggestion_list.jsx2
-rw-r--r--webapp/components/suggestion/search_user_provider.jsx2
-rw-r--r--webapp/components/suggestion/suggestion.jsx4
-rw-r--r--webapp/components/suggestion/suggestion_box.jsx2
-rw-r--r--webapp/components/suggestion/suggestion_list.jsx2
-rw-r--r--webapp/components/suggestion/switch_channel_provider.jsx2
-rw-r--r--webapp/components/team_general_tab.jsx2
-rw-r--r--webapp/components/team_import_tab.jsx2
-rw-r--r--webapp/components/team_members_dropdown.jsx2
-rw-r--r--webapp/components/team_members_modal.jsx2
-rw-r--r--webapp/components/team_settings.jsx2
-rw-r--r--webapp/components/team_settings_modal.jsx2
-rw-r--r--webapp/components/team_sidebar/components/team_button.jsx2
-rw-r--r--webapp/components/team_sidebar/team_sidebar_controller.jsx2
-rw-r--r--webapp/components/textbox.jsx2
-rw-r--r--webapp/components/toggle_modal_button.jsx2
-rw-r--r--webapp/components/tutorial/tutorial_intro_screens.jsx2
-rw-r--r--webapp/components/tutorial/tutorial_tip.jsx2
-rw-r--r--webapp/components/tutorial/tutorial_view.jsx2
-rw-r--r--webapp/components/unread_channel_indicator.jsx2
-rw-r--r--webapp/components/user_list.jsx2
-rw-r--r--webapp/components/user_list_row.jsx2
-rw-r--r--webapp/components/user_profile.jsx2
-rw-r--r--webapp/components/user_settings/custom_theme_chooser.jsx2
-rw-r--r--webapp/components/user_settings/desktop_notification_settings.jsx2
-rw-r--r--webapp/components/user_settings/email_notification_setting.jsx2
-rw-r--r--webapp/components/user_settings/import_theme_modal.jsx2
-rw-r--r--webapp/components/user_settings/premade_theme_chooser.jsx2
-rw-r--r--webapp/components/user_settings/user_settings.jsx2
-rw-r--r--webapp/components/user_settings/user_settings_advanced.jsx2
-rw-r--r--webapp/components/user_settings/user_settings_display.jsx2
-rw-r--r--webapp/components/user_settings/user_settings_general.jsx2
-rw-r--r--webapp/components/user_settings/user_settings_modal.jsx2
-rw-r--r--webapp/components/user_settings/user_settings_notifications.jsx2
-rw-r--r--webapp/components/user_settings/user_settings_security.jsx2
-rw-r--r--webapp/components/user_settings/user_settings_theme.jsx2
-rw-r--r--webapp/components/view_image.jsx4
-rw-r--r--webapp/components/view_image_popover_bar.jsx2
-rw-r--r--webapp/components/webrtc/components/webrtc_header.jsx2
-rw-r--r--webapp/components/webrtc/components/webrtc_notification.jsx2
-rw-r--r--webapp/components/webrtc/components/webrtc_sidebar.jsx2
-rw-r--r--webapp/components/webrtc/webrtc_controller.jsx2
-rw-r--r--webapp/components/youtube_video.jsx2
-rw-r--r--webapp/dispatcher/app_dispatcher.jsx2
-rwxr-xr-xwebapp/i18n/en.json51
-rw-r--r--webapp/i18n/i18n.jsx2
-rw-r--r--webapp/root.jsx2
-rw-r--r--webapp/routes/route_admin_console.jsx2
-rw-r--r--webapp/routes/route_emoji.jsx2
-rw-r--r--webapp/routes/route_help.jsx2
-rw-r--r--webapp/routes/route_integrations.jsx2
-rw-r--r--webapp/routes/route_root.jsx2
-rw-r--r--webapp/routes/route_team.jsx2
-rw-r--r--webapp/routes/route_utils.jsx2
-rw-r--r--webapp/sass/components/_emoticons.scss20
-rw-r--r--webapp/sass/layout/_markdown.scss10
-rw-r--r--webapp/sass/layout/_post.scss6
-rw-r--r--webapp/sass/layout/_sidebar-right.scss6
-rw-r--r--webapp/sass/responsive/_tablet.scss28
-rw-r--r--webapp/sass/routes/_admin-console.scss6
-rw-r--r--webapp/stores/admin_store.jsx2
-rw-r--r--webapp/stores/analytics_store.jsx2
-rw-r--r--webapp/stores/browser_store.jsx2
-rw-r--r--webapp/stores/channel_store.jsx2
-rw-r--r--webapp/stores/emoji_store.jsx2
-rw-r--r--webapp/stores/error_store.jsx2
-rw-r--r--webapp/stores/file_store.jsx4
-rw-r--r--webapp/stores/integration_store.jsx2
-rw-r--r--webapp/stores/localization_store.jsx2
-rw-r--r--webapp/stores/message_history_store.jsx4
-rw-r--r--webapp/stores/modal_store.jsx2
-rw-r--r--webapp/stores/notification_store.jsx2
-rw-r--r--webapp/stores/post_store.jsx2
-rw-r--r--webapp/stores/preference_store.jsx2
-rw-r--r--webapp/stores/reaction_store.jsx2
-rw-r--r--webapp/stores/search_store.jsx33
-rw-r--r--webapp/stores/suggestion_store.jsx2
-rw-r--r--webapp/stores/team_store.jsx2
-rw-r--r--webapp/stores/user_store.jsx2
-rw-r--r--webapp/stores/user_typing_store.jsx2
-rw-r--r--webapp/stores/webrtc_store.jsx4
-rw-r--r--webapp/tests/client/client_admin.test.jsx2
-rw-r--r--webapp/tests/client/client_channel.test.jsx2
-rw-r--r--webapp/tests/client/client_command.test.jsx2
-rw-r--r--webapp/tests/client/client_emoji.test.jsx2
-rw-r--r--webapp/tests/client/client_file.test.jsx2
-rw-r--r--webapp/tests/client/client_general.test.jsx2
-rw-r--r--webapp/tests/client/client_hooks.test.jsx2
-rw-r--r--webapp/tests/client/client_oauth.test.jsx6
-rw-r--r--webapp/tests/client/client_post.test.jsx2
-rw-r--r--webapp/tests/client/client_preferences.test.jsx2
-rw-r--r--webapp/tests/client/client_reaction.test.jsx2
-rw-r--r--webapp/tests/client/client_team.test.jsx2
-rw-r--r--webapp/tests/client/client_user.test.jsx2
-rw-r--r--webapp/tests/client/client_websocket.test.jsx2
-rw-r--r--webapp/tests/components/__snapshots__/about_build_modal.test.jsx.snap16
-rw-r--r--webapp/tests/components/about_build_modal.test.jsx2
-rw-r--r--webapp/tests/components/backstage/components/backstage_header.test.jsx2
-rw-r--r--webapp/tests/components/spinner_button.test.jsx2
-rw-r--r--webapp/tests/components/suggestion/suggestion_box.test.jsx2
-rw-r--r--webapp/tests/helpers/client-test-helper.jsx2
-rw-r--r--webapp/tests/helpers/intl-test-helper.jsx2
-rw-r--r--webapp/tests/utils/emoticons.test.jsx2
-rw-r--r--webapp/tests/utils/formatting_at_mentions.test.jsx2
-rw-r--r--webapp/tests/utils/formatting_hashtags.test.jsx2
-rw-r--r--webapp/tests/utils/formatting_imgs.test.jsx2
-rw-r--r--webapp/tests/utils/formatting_links.test.jsx2
-rw-r--r--webapp/utils/async_client.jsx8
-rw-r--r--webapp/utils/channel_intro_messages.jsx2
-rw-r--r--webapp/utils/constants.jsx3
-rw-r--r--webapp/utils/delayed_action.jsx2
-rw-r--r--webapp/utils/emoji.jsx2
-rw-r--r--webapp/utils/emoticons.jsx2
-rw-r--r--webapp/utils/license_utils.jsx2
-rw-r--r--webapp/utils/markdown.jsx2
-rw-r--r--webapp/utils/post_utils.jsx2
-rw-r--r--webapp/utils/syntax_highlighting.jsx2
-rw-r--r--webapp/utils/team_utils.jsx2
-rw-r--r--webapp/utils/text_formatting.jsx2
-rw-r--r--webapp/utils/url.jsx2
-rw-r--r--webapp/utils/user_agent.jsx2
-rw-r--r--webapp/utils/utils.jsx15
-rw-r--r--wsapi/api.go2
-rw-r--r--wsapi/status.go2
-rw-r--r--wsapi/system.go2
-rw-r--r--wsapi/user.go2
-rw-r--r--wsapi/webrtc.go2
-rw-r--r--wsapi/websocket_handler.go2
806 files changed, 5309 insertions, 2451 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f3d725ce8..3d19e4f63 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,3 @@
# Mattermost Changelog
-Please see [Mattermost Team Edition Changelog](http://docs.mattermost.com/administration/changelog.html) in product documentation.
+Please see [Mattermost Team Edition Changelog](http://docs.mattermost.com/administration/changelog.html) in product documentation.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3d87ef997..43be7ce79 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,12 +1,12 @@
# Code Contribution Guidelines
-Thank you for your interest in contributing! Please see the [Mattermost Contribution Guide](http://docs.mattermost.com/developer/contribution-guide.html) which describes the process for making code contributions across Mattermost projects.
+Thank you for your interest in contributing! Please see the [Mattermost Contribution Guide](http://docs.mattermost.com/developer/contribution-guide.html) which describes the process for making code contributions across Mattermost projects.
### Review Process for this Repo
When you submit a pull request, it goes through the review process outlined below. We aim to start reviewing pull requests in this repo the week they are submitted, but the length of time to complete the process will vary depending on the pull request.
-The one exception may be around release time, where the review process may take longer as the team focuses on our [release process](https://docs.mattermost.com/process/release-process.html).
+The one exception may be around release time, where the review process may take longer as the team focuses on our [release process](https://docs.mattermost.com/process/release-process.html).
#### PR submitted
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
index 851d17f6f..122880f1e 100644
--- a/ISSUE_TEMPLATE.md
+++ b/ISSUE_TEMPLATE.md
@@ -1,7 +1,7 @@
-For feature requests, please see: http://www.mattermost.org/feature-requests/.
+For feature requests, please see: http://www.mattermost.org/feature-requests/.
For troubleshooting questions, please post on the forums: http://forum.mattermost.org/.
-For issues with the product, please follow the steps at http://www.mattermost.org/filing-issues/ and post here in the following format:
+For issues with the product, please follow the steps at http://www.mattermost.org/filing-issues/ and post here in the following format:
#### Summary
Issue in one concise sentence
diff --git a/LICENSE.txt b/LICENSE.txt
index e58757114..ead98cf01 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,32 +1,32 @@
Mattermost Licensing
-SOFTWARE LICENSING
+SOFTWARE LICENSING
-You are licensed to use compiled versions of the Mattermost platform produced by Mattermost, Inc. under an MIT LICENSE
+You are licensed to use compiled versions of the Mattermost platform produced by Mattermost, Inc. under an MIT LICENSE
- See MIT-COMPILED-LICENSE.md included in compiled versions for details
You may be licensed to use source code to create compiled versions not produced by Mattermost, Inc. in one of two ways:
-1. Under the Free Software Foundation’s GNU AGPL v.3.0, subject to the exceptions outlined in this policy; or
-2. Under a commercial license available from Mattermost, Inc. by contacting commercial@mattermost.com
+1. Under the Free Software Foundation’s GNU AGPL v.3.0, subject to the exceptions outlined in this policy; or
+2. Under a commercial license available from Mattermost, Inc. by contacting commercial@mattermost.com
-You are licensed to use the source code in Admin Tools and Configuration Files (templates/, config/, model/,
+You are licensed to use the source code in Admin Tools and Configuration Files (templates/, config/, model/,
webapp/client, webapp/fonts, webapp/i18n, webapp/images and all subdirectories thereof) under the Apache License v2.0.
-We promise that we will not enforce the copyleft provisions in AGPL v3.0 against you if your application (a) does not
+We promise that we will not enforce the copyleft provisions in AGPL v3.0 against you if your application (a) does not
link to the Mattermost Platform directly, but exclusively uses the Mattermost Admin Tools and Configuration Files, and
-(b) you have not modified, added to or adapted the source code of Mattermost in a way that results in the creation of
+(b) you have not modified, added to or adapted the source code of Mattermost in a way that results in the creation of
a “modified version” or “work based on” Mattermost as these terms are defined in the AGPL v3.0 license.
MATTERMOST TRADEMARK GUIDELINES
-Your use of the mark Mattermost is subject to Mattermost, Inc's prior written approval and our organization’s Trademark
-Standards of Use at http://www.mattermost.org/trademark-standards-of-use/. For trademark approval or any questions
-you have about using these trademarks, please email trademark@mattermost.com
+Your use of the mark Mattermost is subject to Mattermost, Inc's prior written approval and our organization’s Trademark
+Standards of Use at http://www.mattermost.org/trademark-standards-of-use/. For trademark approval or any questions
+you have about using these trademarks, please email trademark@mattermost.com
------------------------------------------------------------------------------------------------------------------------------
-
+
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
diff --git a/Makefile b/Makefile
index 8b43d8513..b9c909ff1 100644
--- a/Makefile
+++ b/Makefile
@@ -197,7 +197,7 @@ test-te-race: start-docker prepare-enterprise
@for package in $(TE_PACKAGES); do \
echo "Testing "$$package; \
- $(GO) test $(GOFLAGS) -race -run=$(TESTS) -test.v -test.timeout=3000s $$package || exit 1; \
+ $(GO) test $(GOFLAGS) -race -run=$(TESTS) -test.timeout=4000s $$package || exit 1; \
done
test-ee-race: start-docker prepare-enterprise
@@ -211,7 +211,7 @@ ifeq ($(BUILD_ENTERPRISE_READY),true)
$(GO) test $(GOFLAGS) -race -run=$(TESTS) -c $$package; \
if [ -f $$(basename $$package).test ]; then \
echo "Testing "$$package; \
- ./$$(basename $$package).test -test.v -test.timeout=2000s || exit 1; \
+ ./$$(basename $$package).test -test.timeout=2000s || exit 1; \
rm -r $$(basename $$package).test; \
fi; \
done
@@ -417,7 +417,7 @@ run-server: prepare-enterprise start-docker
@echo Running mattermost for development
mkdir -p $(BUILD_WEBAPP_DIR)/dist/files
- $(GO) run $(GOFLAGS) $(GO_LINKER_FLAGS) ./cmd/platform/*.go &
+ $(GO) run $(GOFLAGS) $(GO_LINKER_FLAGS) ./cmd/platform/*.go --disableconfigwatch &
run-cli: prepare-enterprise start-docker
@echo Running mattermost for development
diff --git a/NOTICE.txt b/NOTICE.txt
index 89578adbe..b75f525cf 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,22 +1,22 @@
-Mattermost Platform
-© 2015-2017 Mattermost, Inc. All Rights Reserved. See LICENSE.txt for license information.
+Mattermost Platform
+© 2015-present Mattermost, Inc. All Rights Reserved. See LICENSE.txt for license information.
-NOTICES:
+NOTICES:
--------
-This document includes a list of open source components used in Mattermost, including those that have been modified.
+This document includes a list of open source components used in Mattermost, including those that have been modified.
--------
## react
-This product contains a modified portion of 'react', a declarative, efficient, and
-flexible JavaScript library for building user interfaces by Facebook, Inc.
+This product contains a modified portion of 'react', a declarative, efficient, and
+flexible JavaScript library for building user interfaces by Facebook, Inc.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/facebook/react
-
-* LICENSE:
+
+* LICENSE:
BSD License
@@ -52,41 +52,41 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---
-This product contains a modified portion of 'perfect-scrollbar', a scrollbar plugin
-by Hyunje Alex Jun and other contributors.
-* HOMEPAGE:
+This product contains a modified portion of 'perfect-scrollbar', a scrollbar plugin
+by Hyunje Alex Jun and other contributors.
+* HOMEPAGE:
* https://github.com/noraesae/perfect-scrollbar
-
-* LICENSE:
+
+* LICENSE:
The MIT License (MIT) Copyright (c) 2015 Hyunje Alex Jun and other contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy of this
-software and associated documentation files (the "Software"), to deal in the Software
-without restriction, including without limitation the rights to use, copy, modify,
-merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to the following
+software and associated documentation files (the "Software"), to deal in the Software
+without restriction, including without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to the following
conditions:
-The above copyright notice and this permission notice shall be included in all copies
+The above copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
---
-This product contains a modified portion of 'jquery-dragster', a drag and drop listener
-by Jan Martin.
+This product contains a modified portion of 'jquery-dragster', a drag and drop listener
+by Jan Martin.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/catmanjan/jquery-dragster
-
-* LICENSE:
+
+* LICENSE:
The MIT License (MIT)
@@ -112,12 +112,12 @@ SOFTWARE.
---
-This product contains a modified portion of 'twemoji', a set of emoticons by Twitter, Inc.
+This product contains a modified portion of 'twemoji', a set of emoticons by Twitter, Inc.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/twitter/twemoji
-
-* LICENSE:
+
+* LICENSE:
# Code licensed under the MIT License:
@@ -194,7 +194,7 @@ exhaustive, and do not form part of our licenses.
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More_considerations
- for the public:
+ for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
@@ -539,30 +539,30 @@ Creative Commons may be contacted at creativecommons.org.
---
-This product contains a modified portion of 'golang-lru', a golang LRU cache by hashicorp,
+This product contains a modified portion of 'golang-lru', a golang LRU cache by hashicorp,
based on Groupcache by Google Inc.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/hashicorp/golang-lru
-
-* LICENSE:
-This Source Code Form is subject to the terms of the Mozilla Public License, v.2.0. If a
-copy of the MPL was not distributed with this file, You can obtain one at
+* LICENSE:
+
+This Source Code Form is subject to the terms of the Mozilla Public License, v.2.0. If a
+copy of the MPL was not distributed with this file, You can obtain one at
http://mozilla.org/MPL/2.0/.
---
-This product contains a modified portion of 'golang-freetype', a port of the Freetype
-font rasterizer (www.freetype.org) to the Go programming.
+This product contains a modified portion of 'golang-freetype', a port of the Freetype
+font rasterizer (www.freetype.org) to the Go programming.
-Portions of this software are copyright © 2010 The FreeType Project (www.freetype.org).
+Portions of this software are copyright © 2010 The FreeType Project (www.freetype.org).
All rights reserved.
-* HOMEPAGE:
+* HOMEPAGE:
* http://www.freetype.org
-
-* LICENSE:
+
+* LICENSE:
The FreeType Project LICENSE
----------------------------
@@ -730,17 +730,17 @@ Legal Terms
Our home page can be found at
http://www.freetype.org
-
+
--- end of FTL.TXT ---
-
+
---
This product contains a modified portion of 'gemoji', a collection of emoji images and names by Apple Inc. and other contributors.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/github/gemoji/blob/master/LICENSE
-
-* LICENSE:
+
+* LICENSE:
octocat, squirrel, shipit
Copyright (c) 2013 GitHub Inc. All rights reserved.
@@ -758,32 +758,32 @@ All other images
Copyright (c) 2013 Apple Inc. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of this
-software and associated documentation files (the "Software"), to deal in the Software
-without restriction, including without limitation the rights to use, copy, modify,
-merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to the following
+software and associated documentation files (the "Software"), to deal in the Software
+without restriction, including without limitation the rights to use, copy, modify,
+merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to the following
conditions:
-The above copyright notice and this permission notice shall be included in all copies
+The above copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
-INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
-FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
---
This product contains a modified portion of 'marked', a full-featured markdown parser and compiler, written in JavaScript. Built for speed.
-by Christopher Jeffrey
+by Christopher Jeffrey
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/chjj/marked
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/)
@@ -813,10 +813,10 @@ This product contains a modified portion of 'react-bootstrap', a library of reus
by Stephen J. Collings, Matthew Honnibal, Pieter Vanderwerff
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/react-bootstrap/react-bootstrap
-
-* LICENSE:
+
+* LICENSE:
The MIT License (MIT)
@@ -846,10 +846,10 @@ This product contains a modified portion of 'goexif', which provides decoding of
by Robert Carlsen & Contributors
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/rwcarlsen/goexif
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2012, Robert Carlsen & Contributors
All rights reserved.
@@ -881,10 +881,10 @@ This product contains a modified portion of 'graphics-go', an implementation of
by The Graphics-Go Authors
-* HOMEPAGE:
+* HOMEPAGE:
* https://code.google.com/p/graphics-go/
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2011 The Graphics-Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -913,10 +913,10 @@ This product contains a modified portion of 'Bootstrap Colorpicker', a nice and
by Stefan Petre
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/mjolnic/bootstrap-colorpicker/
-
-* LICENSE:
+
+* LICENSE:
Copyright 2012 Stefan Petre
@@ -940,10 +940,10 @@ This product contains a modified portion of 'highlight.js', a syntax highlighter
by Ivan Sagalaev
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/isagalaev/highlight.js
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2006, Ivan Sagalaev
All rights reserved.
@@ -955,8 +955,8 @@ modification, are permitted provided that the following conditions are met:
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- * Neither the name of highlight.js nor the names of its contributors
- may be used to endorse or promote products derived from this software
+ * Neither the name of highlight.js nor the names of its contributors
+ may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
@@ -972,14 +972,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---
-This product contains a modified portion of 'Chart.min.js', used to make simple HTML5 charts using the canvas element.
+This product contains a modified portion of 'Chart.min.js', used to make simple HTML5 charts using the canvas element.
by Nick Downie
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/nnnick/Chart.js/
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2013-2015 Nick Downie
@@ -995,10 +995,10 @@ This product contains a modified portion of 'babel-es6-polyfill', a pure ES6 pol
by Jason Berry
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/JasonBerry/babel-es6-polyfill
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2015 Jason Berry
@@ -1026,10 +1026,10 @@ This product contains a modified portion of 'go-ldap', basic LDAP v3 functionali
by The Go Authors
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/go-ldap/ldap
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2012 The Go Authors. All rights reserved.
@@ -1065,10 +1065,10 @@ This product contains a modified portion of 'Google Fonts', various Open Source
by Google Inc.
-* HOMEPAGE:
+* HOMEPAGE:
* https://www.google.com/fonts
-
-* LICENSE:
+
+* LICENSE:
# Code licensed under the Apache 2.0 License:
@@ -1158,13 +1158,13 @@ Creative Commons may be contacted at https://creativecommons.org/.
---
-This product contains a modified portion of 'go-i18n', a Go package and a command that translates Go programs into multiple languages
-by Nick Snyder.
+This product contains a modified portion of 'go-i18n', a Go package and a command that translates Go programs into multiple languages
+by Nick Snyder.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/nicksnyder/go-i18n
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2014 Nick Snyder https://github.com/nicksnyder
@@ -1188,13 +1188,13 @@ THE SOFTWARE.
---
-This product contains a modified portion of 'react-intl', a library that provides React components and an API to format dates, numbers, and string messages including pluralization.
-by Yahoo Inc.
+This product contains a modified portion of 'react-intl', a library that provides React components and an API to format dates, numbers, and string messages including pluralization.
+by Yahoo Inc.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/yahoo/react-intl
-
-* LICENSE:
+
+* LICENSE:
Copyright 2014 Yahoo Inc.
All rights reserved.
@@ -1228,13 +1228,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## fastclick
-This product contains a modified portion of 'fastclick', a library for eliminating the delay between a physical tap and the firing of a click event on mobile browsers.
+This product contains a modified portion of 'fastclick', a library for eliminating the delay between a physical tap and the firing of a click event on mobile browsers.
by FT Labs.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/ftlabs/fastclick
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2014 The Financial Times Ltd.
@@ -1261,12 +1261,12 @@ OTHER DEALINGS IN THE SOFTWARE.
---
-This product contains a modified portion of 'dgoogauth', a go implementation of the Google Authenticator library by Damian Gryski.
+This product contains a modified portion of 'dgoogauth', a go implementation of the Google Authenticator library by Damian Gryski.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/dgryski/dgoogauth
-
-* LICENSE:
+
+* LICENSE:
Copyright 2012 Damian Gryski
@@ -1286,10 +1286,10 @@ limitations under the License.
This product contains a modified portion of 'compass-mixins', which pulls SASS style sheets on Bower, and enjoys the compass mixins by using libsass for faster compilation, by Christopher M. Eppstein.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/Igosuki/compass-mixins
-
-* LICENSE:
+
+* LICENSE:
The MIT License (MIT)(slightly modified)
@@ -1327,10 +1327,10 @@ control history of the product.
This product contains a modified portion of 'flux', an application architecture for React utilizing a unidirectional data flow by Facebook, Inc.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/facebook/flux
-
-* LICENSE:
+
+* LICENSE:
BSD License
@@ -1367,10 +1367,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of 'font-awesome', a full suite of 632 pictographic icons for easy scalable vector graphics on websites, created and maintained by Dave Gandy.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/FortAwesome/Font-Awesome
-
-* LICENSE:
+
+* LICENSE:
The MIT License (MIT)
@@ -1392,10 +1392,10 @@ No attribution is required by products that make use of this software.
This product contains a modified portion of 'jquery', a library for JavaScript for DOM operations by jQuery Foundation and other contributors.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/jquery/jquery
-
-* LICENSE:
+
+* LICENSE:
Copyright jQuery Foundation and other contributors, https://jquery.org/
@@ -1438,10 +1438,10 @@ the terms above.
This product contains a modified portion of 'fbjs', a collection of JavaScript utilities by Facebook, Inc.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/facebook/fbjs
-
-* LICENSE:
+
+* LICENSE:
BSD License
@@ -1477,16 +1477,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---
-This product contains a modified portion of 'marked', a full-featured markdown parser and compiler, written in JavaScript. Built for speed by Christopher Jeffrey.
+This product contains a modified portion of 'marked', a full-featured markdown parser and compiler, written in JavaScript. Built for speed by Christopher Jeffrey.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/chjj/marked
-
-* LICENSE:
+
+* LICENSE:
The MIT License (MIT)
-Copyright (c) 2011-2014, Christopher Jeffrey.
+Copyright (c) 2011-2014, Christopher Jeffrey.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
@@ -1502,12 +1502,12 @@ No attribution is required by products that make use of this software.
---
-This product contains a modified portion of 'match-at', to correspond to the original string, where it doesn't slice the string by Ben Alpert.
+This product contains a modified portion of 'match-at', to correspond to the original string, where it doesn't slice the string by Ben Alpert.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/spicyj/match-at
-
-* LICENSE:
+
+* LICENSE:
The MIT License (MIT)
@@ -1533,12 +1533,12 @@ SOFTWARE.
---
-This product contains a modified portion of 'object-assign', a polyfill that doesn't overwrite the native method by Sindre Sorhus.
+This product contains a modified portion of 'object-assign', a polyfill that doesn't overwrite the native method by Sindre Sorhus.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/sindresorhus/object-assign
-
-* LICENSE:
+
+* LICENSE:
The MIT License (MIT)
@@ -1566,10 +1566,10 @@ THE SOFTWARE.
This product contains a modified portion of 'react-custom-scrollbars', a React scrollbars component.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/malte-wessel/react-custom-scrollbars
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2015 react-custom-scrollbars
@@ -1595,10 +1595,10 @@ SOFTWARE.
This product contains a modified portion of 'react-dom', to be paired with the isomorphic React, which will be shipped as react to npm.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/facebook/react
-
-* LICENSE:
+
+* LICENSE:
BSD License
@@ -1636,10 +1636,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of 'react-router', a complete routing library for React by Ryan Florence and Michael Jackson.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/reactjs/react-router
-
-* LICENSE:
+
+* LICENSE:
The MIT License (MIT)
@@ -1667,10 +1667,10 @@ SOFTWARE.
This product contains a modified portion of 'react-router', a small progressive client-side HTTP request library, and Node.js module with the same API, sporting many high-level HTTP client features by TJ Holowaychuk.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/visionmedia/superagent
-
-* LICENSE:
+
+* LICENSE:
The MIT License (MIT)
@@ -1699,10 +1699,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This product contains a modified portion of 'velocity-animate', an animation engine with the same API as jQuery's $.animate() by Julian Shapiro.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/julianshapiro/velocity
-
-* LICENSE:
+
+* LICENSE:
The MIT License
@@ -1728,14 +1728,14 @@ SOFTWARE.
---
-## autolinker
+## autolinker
This product contains a modified portion of 'autolinker', to automatically link the URLs, email addresses, and Twitter handles in a given block of text/HTML by Gregory Jacobs.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/gregjacobs/Autolinker.js
-
-* LICENSE:
+
+* LICENSE:
The MIT License
@@ -1764,21 +1764,21 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This product contains a modified portion of 'gziphandler', a tiny Go package which wraps HTTP handlers to transparently gzip the response body, for clients which support it by The New York Times Company.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/NYTimes/gziphandler
-
-* LICENSE:
+
+* LICENSE:
Apache License 2.0
Copyright (c) 2015 The New York Times Company
-
+
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this library except in compliance with the License.
You may obtain a copy of the License at
-
+
http://www.apache.org/licenses/LICENSE-2.0
-
+
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -1789,10 +1789,10 @@ limitations under the License.
This product contains a modified portion of 'handlers', a collection of handlers (aka "HTTP middleware") for use with Go's net/http package (or any framework supporting http.Handler) by The Gorilla Handlers Authors.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/gorilla/handlers
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2013 The Gorilla Handlers Authors. All rights reserved.
@@ -1821,10 +1821,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of 'log4go', an unmaintained fork, left only so it doesn't break imports by Kyle Lemons.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/alecthomas/log4go
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2010, Kyle Lemons <kyle@kylelemons.net>. All rights reserved.
@@ -1844,10 +1844,10 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of 'manners', a package imaging providing basic image manipulation functions (resize, rotate, flip, crop, etc.) by Grigory Dryapak.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/disintegration/imaging
-
-* LICENSE:
+
+* LICENSE:
The MIT License (MIT)
@@ -1875,10 +1875,10 @@ SOFTWARE.
This product contains a modified portion of 'gorp', to save time, minimize the drudgery of getting data in and out of the database, and help code focus on algorithms, not infrastructure by James Cooper.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/go-gorp/gorp
-
-* LICENSE:
+
+* LICENSE:
The MIT License (MIT)
@@ -1907,10 +1907,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This product contains a modified portion of 'mysql', a lightweight and fast MySQL driver for Go's (golang) database/sql package by Mozilla Public.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/go-sql-driver/mysql
-
-* LICENSE:
+
+* LICENSE:
Mozilla Public License Version 2.0
==================================
@@ -1949,7 +1949,7 @@ Mozilla Public License Version 2.0
means any form of the work other than Source Code Form.
1.7. "Larger Work"
- means a work that combines Covered Software with other material, in
+ means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
@@ -2285,15 +2285,15 @@ Exhibit B - "Incompatible With Secondary Licenses" Notice
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.
-
+
---
This product contains a modified portion of 'context', a golang registry for global request variables by Rodrigo Moraes.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/gorilla/context
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2012 Rodrigo Moraes. All rights reserved.
@@ -2327,10 +2327,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of 'mux', a powerful URL router and dispatcher for golang by Rodrigo Moraes.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/gorilla/mux
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2012 Rodrigo Moraes. All rights reserved.
@@ -2364,10 +2364,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of 'websocket', a WebSocket implementation for Go by The Gorilla WebSocket Authors.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/gorilla/websocket
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2013 The Gorilla WebSocket Authors. All rights reserved.
@@ -2398,32 +2398,32 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of 'pq', a Pure Go Postgres driver for database/sql by Blake Mizerany and Contributors.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/lib/pq
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2011-2013, 'pq' Contributors
Portions Copyright (C) 2011 Blake Mizerany
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction,
-including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction,
+including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---
This product contains a modified portion of 'user_agent', a Go library that parses HTTP User Agents by Miquel Sabaté Solà.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/mssola/user_agent
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2012-2016 Miquel Sabaté Solà
@@ -2450,10 +2450,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This product contains a modified portion of 'uuid', a package generates and inspects UUIDs based on RFC 412 and DCE 1.1: Authentication and Security Services by Google Inc.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/pborman/uuid
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2009,2014 Google Inc. All rights reserved.
@@ -2487,10 +2487,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of 'yaml', a YAML support for the Go language by Canonical Inc.
-* HOMEPAGE:
+* HOMEPAGE:
* https://gopkg.in/yaml.v2
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2011-2014 - Canonical Inc.
@@ -2685,10 +2685,10 @@ Library.
This product contains a modified portion of 'throttled', a package store offering a memory-based and a Redis-based throttled by Martin Angers.
-* HOMEPAGE:
+* HOMEPAGE:
* http://gopkg.in/throttled/throttled.v1/store
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2014, Martin Angers
All rights reserved.
@@ -2701,20 +2701,20 @@ Redistribution and use in source and binary forms, with or without modification,
* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---
This product contains a modified portion of 'throttled', a package throttled implementing different throttling strategies for controlling access to HTTP handlers by Martin Angers and Contributors.
-* HOMEPAGE:
+* HOMEPAGE:
* http://gopkg.in/throttled/throttled.v1
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2014, Martin Angers and Contributors.
All rights reserved.
@@ -2727,20 +2727,20 @@ Redistribution and use in source and binary forms, with or without modification,
* Neither the name of the author nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---
This product contains a modified portion of 'fsnotify', to utilize golang.org/x/sys rather than syscall from the standard library by The Go Authors and fsnotify Authors.
-* HOMEPAGE:
+* HOMEPAGE:
* http://gopkg.in/fsnotify.v1
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2012 The Go Authors. All rights reserved.
Copyright (c) 2012 fsnotify Authors. All rights reserved.
@@ -2777,10 +2777,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of 'asn1-ber', an ASN1 BER Encoding / Decoding Library for the GO programming language by The Go Authors.
-* HOMEPAGE:
+* HOMEPAGE:
* http://gopkg.in/asn1-ber.v1
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2012 The Go Authors. All rights reserved.
@@ -2814,10 +2814,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of 'asn1-ber', an ASN1 BER Encoding / Decoding Library for the GO programming language by The Go Authors.
-* HOMEPAGE:
+* HOMEPAGE:
* http://gopkg.in/asn1-ber.v1
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2012 The Go Authors. All rights reserved.
@@ -2853,10 +2853,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of 'jasny-bootstrap', an extension of bootstrap with additional components
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/jasny/bootstrap
-
-* LICENSE:
+
+* LICENSE:
Apache License
Version 2.0, January 2004
@@ -3034,17 +3034,17 @@ This product contains a modified portion of 'jasny-bootstrap', an extension of b
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
-
+
---
## redigo
This product contains a modified portion of 'redigo', a Go client for the Redis database.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/garyburd/redigo
-
-* LICENSE:
+
+* LICENSE:
Apache License
Version 2.0, January 2004
@@ -3227,10 +3227,10 @@ This product contains a modified portion of 'redigo', a Go client for the Redis
This product contains a modified portion of 'crypto', a set of Go cryptographic libraries.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/golang/crypto
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2009 The Go Authors. All rights reserved.
@@ -3267,10 +3267,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of 'image', a set of Go image libraries.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/golang/image
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2009 The Go Authors. All rights reserved.
@@ -3307,10 +3307,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of 'rsc', a random source code library from Google
-* HOMEPAGE:
+* HOMEPAGE:
* https://code.google.com/archive/p/rsc/
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) <YEAR>, <OWNER>
All rights reserved.
@@ -3331,12 +3331,12 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
This product contains a modified portion of 'mattermost-driver-javascript', a Javascript library for interacting with the Mattermost API.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/mattermost/mattermost-driver-javascript
-
-* LICENSE:
-Copyright 2016 Mattermost
+* LICENSE:
+
+Copyright 2016-present Mattermost
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
@@ -3350,10 +3350,10 @@ Unless required by applicable law or agreed to in writing, software distributed
This product contains a modified portion of 'react-select', a select control built with and for ReactJS by jedwatson.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/JedWatson/react-select
-
-* LICENSE:
+
+* LICENSE:
The MIT License (MIT)
@@ -3380,12 +3380,12 @@ SOFTWARE.
---
-This product contains a modified portion of 'osext', providing a function that returns an absolute path to the current program executable, built by kardianos.
+This product contains a modified portion of 'osext', providing a function that returns an absolute path to the current program executable, built by kardianos.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/kardianos/osext
-
-* LICENSE:
+
+* LICENSE:
Copyright (c) 2012 The Go Authors. All rights reserved.
@@ -3419,10 +3419,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of 'go-saml', a SAML client library for Go written by RobotsAndPencils.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/RobotsAndPencils/go-saml
-* LICENSE:
+* LICENSE:
The MIT License (MIT)
@@ -3450,10 +3450,10 @@ SOFTWARE.
This product contains a modified portion of 'bootstrap', a sleek, intuitive, and powerful front-end framework for faster and easier web development.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/twbs/bootstrap
-* LICENSE:
+* LICENSE:
The MIT License (MIT)
@@ -3481,10 +3481,10 @@ THE SOFTWARE.
This product contains a modified portion of 'Intl.js', to bring long overdue localization methods to ECMAScript implementations, built by andyearnshaw.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/andyearnshaw/Intl.js
-* LICENSE:
+* LICENSE:
The MIT License (MIT)
@@ -3554,12 +3554,12 @@ the property of their respective owners.
---
-This product contains a modified portion of 'pdfjs-dist', is a Portable Document Format (PDF) library that is built with HTML5 built by mozilla.
+This product contains a modified portion of 'pdfjs-dist', is a Portable Document Format (PDF) library that is built with HTML5 built by mozilla.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/mozilla/pdfjs-dist
-* LICENSE:
+* LICENSE:
Apache License
Version 2.0, January 2004
@@ -3737,15 +3737,15 @@ This product contains a modified portion of 'pdfjs-dist', is a Portable Document
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
-
+
---
This product contains a modified portion of 'xregexp', used to provide augmented (and extensible) JavaScript regular expressions, built by slevithan.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/slevithan/xregexp
-* LICENSE:
+* LICENSE:
The MIT License
@@ -3773,10 +3773,10 @@ THE SOFTWARE.
This product contains a modified portion of 'iNoBounce', used to prevent overscrolling on iOS devices, built by lazd.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/lazd/iNoBounce
-* LICENSE:
+* LICENSE:
Copyright (c) 2013, Lawrence Davis
All rights reserved.
@@ -3792,7 +3792,7 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
This product contains a modified portion of 'minio-go', a Golang Client SDK providing simple APIs to access any Amazon S3 compatible object storage server, built by Minio.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/minio/minio-go
* LICENSE:
@@ -3979,10 +3979,10 @@ This product contains a modified portion of 'minio-go', a Golang Client SDK prov
This product contains a modified portion of 'graceful', a Go package enabling graceful shutdown of an http.Handler server, built by Tyler Bunnell.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/tylerb/graceful
-* LICENSE:
+* LICENSE:
The MIT License (MIT)
@@ -4010,10 +4010,10 @@ SOFTWARE.
This product contains a modified portion of 'letsencrypt' to manage TLS certificates automatically via LetsEncrypt.org, built by Russ Cox.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/rsc/letsencrypt
-* LICENSE:
+* LICENSE:
Copyright (c) 2009 The Go Authors. All rights reserved.
@@ -4047,10 +4047,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of ‘manners’ a polite webserver for Go, built by Braintree, a division of PayPal, Inc.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/braintree/manners
-* LICENSE:
+* LICENSE:
Copyright (c) 2014 Braintree, a division of PayPal, Inc.
@@ -4076,10 +4076,10 @@ THE SOFTWARE.
This product contains a modified portion of ‘perks’ which contains the Go package quantile that computes approximate quantiles over an unbounded data stream within low memory and CPU bounds, built by Blake Mizerany.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/beorn7/perks
-* LICENSE:
+* LICENSE:
Copyright (C) 2013 Blake Mizerany
@@ -4106,10 +4106,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This product contains a modified portion of ‘protobuf’ for Go support for Protocol Buffers, built by The Go Authors.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/golang/protobuf
-* LICENSE:
+* LICENSE:
Go support for Protocol Buffers - Google's data interchange format
@@ -4146,10 +4146,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains a modified portion of ‘golang_protobuf_extensions’ which provides various Protocol Buffer extensions, built by matttproud.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/matttproud/golang_protobuf_extensions
-* LICENSE:
+* LICENSE:
# Code licensed under the Apache 2.0 License:
@@ -4169,10 +4169,10 @@ limitations under the License.
This product contains a modified portion of ‘cobra’, a Commander for modern Go CLI interactions, built by spf13.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/spf13/cobra
-* LICENSE:
+* LICENSE:
# Code licensed under the Apache 2.0 License:
@@ -4192,10 +4192,10 @@ limitations under the License.
This product contains a modified portion of ‘pflag’, a Commander for modern Go CLI interactions, built by Alex Ogier.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/spf13/pflag
-* LICENSE:
+* LICENSE:
Copyright (c) 2012 Alex Ogier. All rights reserved.
Copyright (c) 2012 The Go Authors. All rights reserved.
@@ -4231,10 +4231,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
This product contains modified portions of Prometheus ‘client_golang’, which is the Go library for Prometheus. Prometheus is a systems and service monitoring system, started by Matt T. Proud and Julius Volz in 2012.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/prometheus/client_golang
-* LICENSE:
+* LICENSE:
# Code licensed under the Apache 2.0 License:
@@ -4254,10 +4254,10 @@ limitations under the License.
This product contains modified portions of Prometheus ‘client_model’, which provides data model artifacts for Prometheus. Prometheus is a systems and service monitoring system, started by Matt T. Proud and Julius Volz in 2012.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/prometheus/client_model
-* LICENSE:
+* LICENSE:
# Code licensed under the Apache 2.0 License:
@@ -4277,10 +4277,10 @@ limitations under the License.
This product contains modified portions of Prometheus ‘common’, which is the part of the Prometheus project that contains Go libraries that are shared across Prometheus components and libraries. Prometheus is a systems and service monitoring system, started by Matt T. Proud and Julius Volz in 2012.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/prometheus/common
-* LICENSE:
+* LICENSE:
# Code licensed under the Apache 2.0 License:
@@ -4300,10 +4300,10 @@ limitations under the License.
This product contains modified portions of Prometheus ‘procfs’, which is the part of the Prometheus project that provides functions to retrieve system, kernel and process metrics from the pseudo-filesystem proc. Prometheus is a systems and service monitoring system, started by Matt T. Proud and Julius Volz in 2012.
-* HOMEPAGE:
+* HOMEPAGE:
* https://github.com/prometheus/procfs
-* LICENSE:
+* LICENSE:
# Code licensed under the Apache 2.0 License:
diff --git a/api/admin.go b/api/admin.go
index cb1b7efde..a6ced71a9 100644
--- a/api/admin.go
+++ b/api/admin.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/admin_test.go b/api/admin_test.go
index dc569620e..ae7259863 100644
--- a/api/admin_test.go
+++ b/api/admin_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/api.go b/api/api.go
index 8ec078dd2..c9c876b02 100644
--- a/api/api.go
+++ b/api/api.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/apitestlib.go b/api/apitestlib.go
index bcc7de879..af14ac431 100644
--- a/api/apitestlib.go
+++ b/api/apitestlib.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/channel.go b/api/channel.go
index 0db3499e0..73daaf3d4 100644
--- a/api/channel.go
+++ b/api/channel.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/channel_test.go b/api/channel_test.go
index 23705f172..52212dac7 100644
--- a/api/channel_test.go
+++ b/api/channel_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/cli_test.go b/api/cli_test.go
index 1f60b02cd..afdada7b3 100644
--- a/api/cli_test.go
+++ b/api/cli_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/command.go b/api/command.go
index 75f37b9ff..aaaa790c0 100644
--- a/api/command.go
+++ b/api/command.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/command_echo_test.go b/api/command_echo_test.go
index 02583d2aa..56df94b0b 100644
--- a/api/command_echo_test.go
+++ b/api/command_echo_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/command_expand_collapse_test.go b/api/command_expand_collapse_test.go
index bad5ef6c4..54873377c 100644
--- a/api/command_expand_collapse_test.go
+++ b/api/command_expand_collapse_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/command_invite_people_test.go b/api/command_invite_people_test.go
index d4f579c4d..0e8c3fe38 100644
--- a/api/command_invite_people_test.go
+++ b/api/command_invite_people_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/command_join_test.go b/api/command_join_test.go
index cce837ceb..c179175fb 100644
--- a/api/command_join_test.go
+++ b/api/command_join_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/command_loadtest_test.go b/api/command_loadtest_test.go
index 091e05831..a02f4f9d3 100644
--- a/api/command_loadtest_test.go
+++ b/api/command_loadtest_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/command_logout_test.go b/api/command_logout_test.go
index d61b30633..ff20a3831 100644
--- a/api/command_logout_test.go
+++ b/api/command_logout_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/command_me_test.go b/api/command_me_test.go
index 0250cfb0f..1f49566fa 100644
--- a/api/command_me_test.go
+++ b/api/command_me_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/command_msg_test.go b/api/command_msg_test.go
index 4fe28fdba..2e2d927e3 100644
--- a/api/command_msg_test.go
+++ b/api/command_msg_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/command_shortcuts_test.go b/api/command_shortcuts_test.go
index 049175ec9..ce5019049 100644
--- a/api/command_shortcuts_test.go
+++ b/api/command_shortcuts_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/command_shrug_test.go b/api/command_shrug_test.go
index e64f4c4b1..b265fbb25 100644
--- a/api/command_shrug_test.go
+++ b/api/command_shrug_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/command_statuses_test.go b/api/command_statuses_test.go
index 063d76062..a562ed882 100644
--- a/api/command_statuses_test.go
+++ b/api/command_statuses_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/command_test.go b/api/command_test.go
index 8194a4c60..6207e6cf5 100644
--- a/api/command_test.go
+++ b/api/command_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/context.go b/api/context.go
index bc5855345..21bbb1e37 100644
--- a/api/context.go
+++ b/api/context.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/context_test.go b/api/context_test.go
index cd4d058cf..95a8459ff 100644
--- a/api/context_test.go
+++ b/api/context_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/deprecated.go b/api/deprecated.go
index eca6f78f8..1c1228793 100644
--- a/api/deprecated.go
+++ b/api/deprecated.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/deprecated_test.go b/api/deprecated_test.go
index b3249a58d..6943c6918 100644
--- a/api/deprecated_test.go
+++ b/api/deprecated_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/emoji.go b/api/emoji.go
index 2f94fb0e0..feb65877a 100644
--- a/api/emoji.go
+++ b/api/emoji.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
@@ -8,10 +8,6 @@ import (
"image"
"image/draw"
"image/gif"
- _ "image/jpeg"
- "image/png"
- "io"
- "mime/multipart"
"net/http"
"strings"
@@ -25,12 +21,6 @@ import (
"image/color/palette"
)
-const (
- MaxEmojiFileSize = 1000 * 1024 // 1 MB
- MaxEmojiWidth = 128
- MaxEmojiHeight = 128
-)
-
func InitEmoji() {
l4g.Debug(utils.T("api.emoji.init.debug"))
@@ -47,12 +37,12 @@ func getEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if result := <-app.Srv.Store.Emoji().GetAll(); result.Err != nil {
- c.Err = result.Err
+ listEmoji, err := app.GetEmojiList()
+ if err != nil {
+ c.Err = err
return
} else {
- emoji := result.Data.([]*model.Emoji)
- w.Write([]byte(model.EmojiListToJson(emoji)))
+ w.Write([]byte(model.EmojiListToJson(listEmoji)))
}
}
@@ -76,13 +66,13 @@ func createEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- if r.ContentLength > MaxEmojiFileSize {
+ if r.ContentLength > app.MaxEmojiFileSize {
c.Err = model.NewLocAppError("createEmoji", "api.emoji.create.too_large.app_error", nil, "")
c.Err.StatusCode = http.StatusRequestEntityTooLarge
return
}
- if err := r.ParseMultipartForm(MaxEmojiFileSize); err != nil {
+ if err := r.ParseMultipartForm(app.MaxEmojiFileSize); err != nil {
c.Err = model.NewLocAppError("createEmoji", "api.emoji.create.parse.app_error", nil, err.Error())
c.Err.StatusCode = http.StatusBadRequest
return
@@ -124,7 +114,7 @@ func createEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
if imageData := m.File["image"]; len(imageData) == 0 {
c.SetInvalidParam("createEmoji", "image")
return
- } else if err := uploadEmojiImage(emoji.Id, imageData[0]); err != nil {
+ } else if err := app.UploadEmojiImage(emoji.Id, imageData[0]); err != nil {
c.Err = err
return
}
@@ -137,58 +127,6 @@ func createEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
-func uploadEmojiImage(id string, imageData *multipart.FileHeader) *model.AppError {
- file, err := imageData.Open()
- if err != nil {
- return model.NewLocAppError("uploadEmojiImage", "api.emoji.upload.open.app_error", nil, "")
- }
- defer file.Close()
-
- buf := bytes.NewBuffer(nil)
- io.Copy(buf, file)
-
- // make sure the file is an image and is within the required dimensions
- if config, _, err := image.DecodeConfig(bytes.NewReader(buf.Bytes())); err != nil {
- return model.NewLocAppError("uploadEmojiImage", "api.emoji.upload.image.app_error", nil, err.Error())
- } else if config.Width > MaxEmojiWidth || config.Height > MaxEmojiHeight {
- data := buf.Bytes()
- newbuf := bytes.NewBuffer(nil)
- if info, err := model.GetInfoForBytes(imageData.Filename, data); err != nil {
- return err
- } else if info.MimeType == "image/gif" {
- if gif_data, err := gif.DecodeAll(bytes.NewReader(data)); err != nil {
- return model.NewLocAppError("uploadEmojiImage", "api.emoji.upload.large_image.gif_decode_error", nil, "")
- } else {
- resized_gif := resizeEmojiGif(gif_data)
- if err := gif.EncodeAll(newbuf, resized_gif); err != nil {
- return model.NewLocAppError("uploadEmojiImage", "api.emoji.upload.large_image.gif_encode_error", nil, "")
- }
- if err := app.WriteFile(newbuf.Bytes(), getEmojiImagePath(id)); err != nil {
- return err
- }
- }
- } else {
- if img, _, err := image.Decode(bytes.NewReader(data)); err != nil {
- return model.NewLocAppError("uploadEmojiImage", "api.emoji.upload.large_image.decode_error", nil, "")
- } else {
- resized_image := resizeEmoji(img, config.Width, config.Height)
- if err := png.Encode(newbuf, resized_image); err != nil {
- return model.NewLocAppError("uploadEmojiImage", "api.emoji.upload.large_image.encode_error", nil, "")
- }
- if err := app.WriteFile(newbuf.Bytes(), getEmojiImagePath(id)); err != nil {
- return err
- }
- }
- }
- } else {
- if err := app.WriteFile(buf.Bytes(), getEmojiImagePath(id)); err != nil {
- return err
- }
- }
-
- return nil
-}
-
func deleteEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
if !*utils.Cfg.ServiceSettings.EnableCustomEmoji {
c.Err = model.NewLocAppError("deleteEmoji", "api.emoji.disabled.app_error", nil, "")
@@ -210,41 +148,24 @@ func deleteEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- var emoji *model.Emoji
- if result := <-app.Srv.Store.Emoji().Get(id, false); result.Err != nil {
- c.Err = result.Err
- return
- } else {
- emoji = result.Data.(*model.Emoji)
-
- if c.Session.UserId != emoji.CreatorId && !app.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
- c.Err = model.NewLocAppError("deleteEmoji", "api.emoji.delete.permissions.app_error", nil, "user_id="+c.Session.UserId)
- c.Err.StatusCode = http.StatusUnauthorized
- return
- }
- }
-
- if err := (<-app.Srv.Store.Emoji().Delete(id, model.GetMillis())).Err; err != nil {
+ emoji, err := app.GetEmoji(id)
+ if err != nil {
c.Err = err
return
}
- go deleteEmojiImage(id)
- go deleteReactionsForEmoji(emoji.Name)
-
- ReturnStatusOK(w)
-}
-
-func deleteEmojiImage(id string) {
- if err := app.MoveFile(getEmojiImagePath(id), "emoji/"+id+"/image_deleted"); err != nil {
- l4g.Error("Failed to rename image when deleting emoji %v", id)
+ if c.Session.UserId != emoji.CreatorId && !app.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
+ c.Err = model.NewLocAppError("deleteEmoji", "api.emoji.delete.permissions.app_error", nil, "user_id="+c.Session.UserId)
+ c.Err.StatusCode = http.StatusUnauthorized
+ return
}
-}
-func deleteReactionsForEmoji(emojiName string) {
- if result := <-app.Srv.Store.Reaction().DeleteAllWithEmojiName(emojiName); result.Err != nil {
- l4g.Warn(utils.T("api.emoji.delete.delete_reactions.app_error"), emojiName)
- l4g.Warn(result.Err)
+ err = app.DeleteEmoji(emoji)
+ if err != nil {
+ c.Err = err
+ return
+ } else {
+ ReturnStatusOK(w)
}
}
@@ -302,10 +223,10 @@ func resizeEmoji(img image.Image, width int, height int) image.Image {
emojiHeight := float64(height)
var emoji image.Image
- if emojiHeight <= MaxEmojiHeight && emojiWidth <= MaxEmojiWidth {
+ if emojiHeight <= app.MaxEmojiHeight && emojiWidth <= app.MaxEmojiWidth {
emoji = img
} else {
- emoji = imaging.Fit(img, MaxEmojiWidth, MaxEmojiHeight, imaging.Lanczos)
+ emoji = imaging.Fit(img, app.MaxEmojiWidth, app.MaxEmojiHeight, imaging.Lanczos)
}
return emoji
}
diff --git a/api/emoji_test.go b/api/emoji_test.go
index fb90d8781..600f7975e 100644
--- a/api/emoji_test.go
+++ b/api/emoji_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
@@ -6,10 +6,7 @@ package api
import (
"bytes"
"image"
- "image/color"
"image/gif"
- "image/jpeg"
- "image/png"
"testing"
"time"
@@ -113,14 +110,14 @@ func TestCreateEmoji(t *testing.T) {
}
// try to create an emoji when they're disabled
- if _, err := Client.CreateEmoji(emoji, createTestGif(t, 10, 10), "image.gif"); err == nil {
+ if _, err := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif"); err == nil {
t.Fatal("shouldn't be able to create an emoji when they're disabled")
}
*utils.Cfg.ServiceSettings.EnableCustomEmoji = true
// try to create a valid gif emoji when they're enabled
- if emojiResult, err := Client.CreateEmoji(emoji, createTestGif(t, 10, 10), "image.gif"); err != nil {
+ if emojiResult, err := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif"); err != nil {
t.Fatal(err)
} else {
emoji = emojiResult
@@ -131,7 +128,7 @@ func TestCreateEmoji(t *testing.T) {
CreatorId: th.BasicUser.Id,
Name: emoji.Name,
}
- if _, err := Client.CreateEmoji(emoji2, createTestGif(t, 10, 10), "image.gif"); err == nil {
+ if _, err := Client.CreateEmoji(emoji2, utils.CreateTestGif(t, 10, 10), "image.gif"); err == nil {
t.Fatal("shouldn't be able to create an emoji with a duplicate name")
}
@@ -142,7 +139,7 @@ func TestCreateEmoji(t *testing.T) {
CreatorId: th.BasicUser.Id,
Name: model.NewId(),
}
- if emojiResult, err := Client.CreateEmoji(emoji, createTestAnimatedGif(t, 10, 10, 10), "image.gif"); err != nil {
+ if emojiResult, err := Client.CreateEmoji(emoji, utils.CreateTestAnimatedGif(t, 10, 10, 10), "image.gif"); err != nil {
t.Fatal(err)
} else {
emoji = emojiResult
@@ -154,7 +151,7 @@ func TestCreateEmoji(t *testing.T) {
CreatorId: th.BasicUser.Id,
Name: model.NewId(),
}
- if emojiResult, err := Client.CreateEmoji(emoji, createTestJpeg(t, 10, 10), "image.jpeg"); err != nil {
+ if emojiResult, err := Client.CreateEmoji(emoji, utils.CreateTestJpeg(t, 10, 10), "image.jpeg"); err != nil {
t.Fatal(err)
} else {
emoji = emojiResult
@@ -166,7 +163,7 @@ func TestCreateEmoji(t *testing.T) {
CreatorId: th.BasicUser.Id,
Name: model.NewId(),
}
- if emojiResult, err := Client.CreateEmoji(emoji, createTestPng(t, 10, 10), "image.png"); err != nil {
+ if emojiResult, err := Client.CreateEmoji(emoji, utils.CreateTestPng(t, 10, 10), "image.png"); err != nil {
t.Fatal(err)
} else {
emoji = emojiResult
@@ -178,7 +175,7 @@ func TestCreateEmoji(t *testing.T) {
CreatorId: th.BasicUser.Id,
Name: model.NewId(),
}
- if _, err := Client.CreateEmoji(emoji, createTestGif(t, 1000, 10), "image.gif"); err != nil {
+ if _, err := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 1000, 10), "image.gif"); err != nil {
t.Fatal("should be able to create an emoji that's too wide by resizing it")
}
@@ -187,7 +184,7 @@ func TestCreateEmoji(t *testing.T) {
CreatorId: th.BasicUser.Id,
Name: model.NewId(),
}
- if _, err := Client.CreateEmoji(emoji, createTestGif(t, 10, 1000), "image.gif"); err != nil {
+ if _, err := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 1000), "image.gif"); err != nil {
t.Fatal("should be able to create an emoji that's too tall by resizing it")
}
@@ -196,7 +193,7 @@ func TestCreateEmoji(t *testing.T) {
CreatorId: th.BasicUser.Id,
Name: model.NewId(),
}
- if _, err := Client.CreateEmoji(emoji, createTestAnimatedGif(t, 100, 100, 10000), "image.gif"); err == nil {
+ if _, err := Client.CreateEmoji(emoji, utils.CreateTestAnimatedGif(t, 100, 100, 10000), "image.gif"); err == nil {
t.Fatal("shouldn't be able to create an emoji that's too large")
}
@@ -214,7 +211,7 @@ func TestCreateEmoji(t *testing.T) {
CreatorId: th.BasicUser2.Id,
Name: model.NewId(),
}
- if _, err := Client.CreateEmoji(emoji, createTestGif(t, 10, 10), "image.gif"); err == nil {
+ if _, err := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif"); err == nil {
t.Fatal("shouldn't be able to create an emoji as another user")
}
}
@@ -232,7 +229,7 @@ func TestDeleteEmoji(t *testing.T) {
emoji1 := createTestEmoji(t, &model.Emoji{
CreatorId: th.BasicUser.Id,
Name: model.NewId(),
- }, createTestGif(t, 10, 10))
+ }, utils.CreateTestGif(t, 10, 10))
if _, err := Client.DeleteEmoji(emoji1.Id); err == nil {
t.Fatal("shouldn't have been able to delete an emoji when they're disabled")
@@ -253,7 +250,7 @@ func TestDeleteEmoji(t *testing.T) {
emoji2 := createTestEmoji(t, &model.Emoji{
CreatorId: th.BasicUser2.Id,
Name: model.NewId(),
- }, createTestGif(t, 10, 10))
+ }, utils.CreateTestGif(t, 10, 10))
if _, err := Client.DeleteEmoji(emoji2.Id); err == nil {
t.Fatal("shouldn't be able to delete another user's emoji")
@@ -266,54 +263,6 @@ func TestDeleteEmoji(t *testing.T) {
}
}
-func createTestGif(t *testing.T, width int, height int) []byte {
- var buffer bytes.Buffer
-
- if err := gif.Encode(&buffer, image.NewRGBA(image.Rect(0, 0, width, height)), nil); err != nil {
- t.Fatalf("failed to create gif: %v", err.Error())
- }
-
- return buffer.Bytes()
-}
-
-func createTestAnimatedGif(t *testing.T, width int, height int, frames int) []byte {
- var buffer bytes.Buffer
-
- img := gif.GIF{
- Image: make([]*image.Paletted, frames, frames),
- Delay: make([]int, frames, frames),
- }
- for i := 0; i < frames; i++ {
- img.Image[i] = image.NewPaletted(image.Rect(0, 0, width, height), color.Palette{color.Black})
- img.Delay[i] = 0
- }
- if err := gif.EncodeAll(&buffer, &img); err != nil {
- t.Fatalf("failed to create animated gif: %v", err.Error())
- }
-
- return buffer.Bytes()
-}
-
-func createTestJpeg(t *testing.T, width int, height int) []byte {
- var buffer bytes.Buffer
-
- if err := jpeg.Encode(&buffer, image.NewRGBA(image.Rect(0, 0, width, height)), nil); err != nil {
- t.Fatalf("failed to create jpeg: %v", err.Error())
- }
-
- return buffer.Bytes()
-}
-
-func createTestPng(t *testing.T, width int, height int) []byte {
- var buffer bytes.Buffer
-
- if err := png.Encode(&buffer, image.NewRGBA(image.Rect(0, 0, width, height))); err != nil {
- t.Fatalf("failed to create png: %v", err.Error())
- }
-
- return buffer.Bytes()
-}
-
func createTestEmoji(t *testing.T, emoji *model.Emoji, imageData []byte) *model.Emoji {
emoji = store.Must(app.Srv.Store.Emoji().Save(emoji)).(*model.Emoji)
@@ -342,7 +291,7 @@ func TestGetEmojiImage(t *testing.T) {
CreatorId: th.BasicUser.Id,
Name: model.NewId(),
}
- emoji1 = Client.MustGeneric(Client.CreateEmoji(emoji1, createTestGif(t, 10, 10), "image.gif")).(*model.Emoji)
+ emoji1 = Client.MustGeneric(Client.CreateEmoji(emoji1, utils.CreateTestGif(t, 10, 10), "image.gif")).(*model.Emoji)
defer func() { Client.MustGeneric(Client.DeleteEmoji(emoji1.Id)) }()
*utils.Cfg.ServiceSettings.EnableCustomEmoji = false
@@ -367,7 +316,7 @@ func TestGetEmojiImage(t *testing.T) {
CreatorId: th.BasicUser.Id,
Name: model.NewId(),
}
- emoji2 = Client.MustGeneric(Client.CreateEmoji(emoji2, createTestAnimatedGif(t, 10, 10, 10), "image.gif")).(*model.Emoji)
+ emoji2 = Client.MustGeneric(Client.CreateEmoji(emoji2, utils.CreateTestAnimatedGif(t, 10, 10, 10), "image.gif")).(*model.Emoji)
defer func() { Client.MustGeneric(Client.DeleteEmoji(emoji2.Id)) }()
if resp, err := Client.DoApiGet(Client.GetCustomEmojiImageUrl(emoji2.Id), "", ""); err != nil {
@@ -384,7 +333,7 @@ func TestGetEmojiImage(t *testing.T) {
CreatorId: th.BasicUser.Id,
Name: model.NewId(),
}
- emoji3 = Client.MustGeneric(Client.CreateEmoji(emoji3, createTestJpeg(t, 10, 10), "image.jpeg")).(*model.Emoji)
+ emoji3 = Client.MustGeneric(Client.CreateEmoji(emoji3, utils.CreateTestJpeg(t, 10, 10), "image.jpeg")).(*model.Emoji)
defer func() { Client.MustGeneric(Client.DeleteEmoji(emoji3.Id)) }()
if resp, err := Client.DoApiGet(Client.GetCustomEmojiImageUrl(emoji3.Id), "", ""); err != nil {
@@ -401,7 +350,7 @@ func TestGetEmojiImage(t *testing.T) {
CreatorId: th.BasicUser.Id,
Name: model.NewId(),
}
- emoji4 = Client.MustGeneric(Client.CreateEmoji(emoji4, createTestPng(t, 10, 10), "image.png")).(*model.Emoji)
+ emoji4 = Client.MustGeneric(Client.CreateEmoji(emoji4, utils.CreateTestPng(t, 10, 10), "image.png")).(*model.Emoji)
defer func() { Client.MustGeneric(Client.DeleteEmoji(emoji4.Id)) }()
if resp, err := Client.DoApiGet(Client.GetCustomEmojiImageUrl(emoji4.Id), "", ""); err != nil {
@@ -418,7 +367,7 @@ func TestGetEmojiImage(t *testing.T) {
CreatorId: th.BasicUser.Id,
Name: model.NewId(),
}
- emoji5 = Client.MustGeneric(Client.CreateEmoji(emoji5, createTestPng(t, 10, 10), "image.png")).(*model.Emoji)
+ emoji5 = Client.MustGeneric(Client.CreateEmoji(emoji5, utils.CreateTestPng(t, 10, 10), "image.png")).(*model.Emoji)
Client.MustGeneric(Client.DeleteEmoji(emoji5.Id))
if _, err := Client.DoApiGet(Client.GetCustomEmojiImageUrl(emoji5.Id), "", ""); err == nil {
@@ -428,12 +377,12 @@ func TestGetEmojiImage(t *testing.T) {
func TestResizeEmoji(t *testing.T) {
// try to resize a jpeg image within MaxEmojiWidth and MaxEmojiHeight
- small_img_data := createTestJpeg(t, MaxEmojiWidth, MaxEmojiHeight)
+ small_img_data := utils.CreateTestJpeg(t, app.MaxEmojiWidth, app.MaxEmojiHeight)
if small_img, _, err := image.Decode(bytes.NewReader(small_img_data)); err != nil {
t.Fatal("failed to decode jpeg bytes to image.Image")
} else {
resized_img := resizeEmoji(small_img, small_img.Bounds().Dx(), small_img.Bounds().Dy())
- if resized_img.Bounds().Dx() > MaxEmojiWidth || resized_img.Bounds().Dy() > MaxEmojiHeight {
+ if resized_img.Bounds().Dx() > app.MaxEmojiWidth || resized_img.Bounds().Dy() > app.MaxEmojiHeight {
t.Fatal("resized jpeg width and height should not be greater than MaxEmojiWidth or MaxEmojiHeight")
}
if resized_img != small_img {
@@ -441,32 +390,32 @@ func TestResizeEmoji(t *testing.T) {
}
}
// try to resize a jpeg image
- jpeg_data := createTestJpeg(t, 256, 256)
+ jpeg_data := utils.CreateTestJpeg(t, 256, 256)
if jpeg_img, _, err := image.Decode(bytes.NewReader(jpeg_data)); err != nil {
t.Fatal("failed to decode jpeg bytes to image.Image")
} else {
resized_jpeg := resizeEmoji(jpeg_img, jpeg_img.Bounds().Dx(), jpeg_img.Bounds().Dy())
- if resized_jpeg.Bounds().Dx() > MaxEmojiWidth || resized_jpeg.Bounds().Dy() > MaxEmojiHeight {
+ if resized_jpeg.Bounds().Dx() > app.MaxEmojiWidth || resized_jpeg.Bounds().Dy() > app.MaxEmojiHeight {
t.Fatal("resized jpeg width and height should not be greater than MaxEmojiWidth or MaxEmojiHeight")
}
}
// try to resize a png image
- png_data := createTestJpeg(t, 256, 256)
+ png_data := utils.CreateTestJpeg(t, 256, 256)
if png_img, _, err := image.Decode(bytes.NewReader(png_data)); err != nil {
t.Fatal("failed to decode png bytes to image.Image")
} else {
resized_png := resizeEmoji(png_img, png_img.Bounds().Dx(), png_img.Bounds().Dy())
- if resized_png.Bounds().Dx() > MaxEmojiWidth || resized_png.Bounds().Dy() > MaxEmojiHeight {
+ if resized_png.Bounds().Dx() > app.MaxEmojiWidth || resized_png.Bounds().Dy() > app.MaxEmojiHeight {
t.Fatal("resized png width and height should not be greater than MaxEmojiWidth or MaxEmojiHeight")
}
}
// try to resize an animated gif
- gif_data := createTestAnimatedGif(t, 256, 256, 10)
+ gif_data := utils.CreateTestAnimatedGif(t, 256, 256, 10)
if gif_img, err := gif.DecodeAll(bytes.NewReader(gif_data)); err != nil {
t.Fatal("failed to decode gif bytes to gif.GIF")
} else {
resized_gif := resizeEmojiGif(gif_img)
- if resized_gif.Config.Width > MaxEmojiWidth || resized_gif.Config.Height > MaxEmojiHeight {
+ if resized_gif.Config.Width > app.MaxEmojiWidth || resized_gif.Config.Height > app.MaxEmojiHeight {
t.Fatal("resized gif width and height should not be greater than MaxEmojiWidth or MaxEmojiHeight")
}
if len(resized_gif.Image) != len(gif_img.Image) {
diff --git a/api/file.go b/api/file.go
index 54df78dd7..0f2fd9319 100644
--- a/api/file.go
+++ b/api/file.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/file_test.go b/api/file_test.go
index c004bb562..1e65c33e8 100644
--- a/api/file_test.go
+++ b/api/file_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/general.go b/api/general.go
index e273268a4..16a739704 100644
--- a/api/general.go
+++ b/api/general.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/general_test.go b/api/general_test.go
index 0cc0f120f..51593ab9e 100644
--- a/api/general_test.go
+++ b/api/general_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/license.go b/api/license.go
index ea5de20d4..7a9e57677 100644
--- a/api/license.go
+++ b/api/license.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/license_test.go b/api/license_test.go
index c5fffd6e9..978e044cc 100644
--- a/api/license_test.go
+++ b/api/license_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/oauth.go b/api/oauth.go
index 1e3dd89b8..fa076c56e 100644
--- a/api/oauth.go
+++ b/api/oauth.go
@@ -1,25 +1,17 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
import (
- "crypto/tls"
- b64 "encoding/base64"
- "fmt"
- "io"
- "io/ioutil"
"net/http"
"net/url"
- "strconv"
"strings"
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
"github.com/mattermost/platform/app"
- "github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
- "github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
)
@@ -48,15 +40,8 @@ func InitOAuth() {
}
func registerOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
- if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
- c.Err = model.NewLocAppError("registerOAuthApp", "api.oauth.register_oauth_app.turn_off.app_error", nil, "")
- c.Err.StatusCode = http.StatusNotImplemented
- return
- }
-
if !app.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_OAUTH) {
- c.Err = model.NewLocAppError("registerOAuthApp", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
+ c.Err = model.NewAppError("registerOAuthApp", "api.command.admin_only.app_error", nil, "", http.StatusForbidden)
return
}
@@ -67,72 +52,50 @@ func registerOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- secret := model.NewId()
-
- oauthApp.ClientSecret = secret
oauthApp.CreatorId = c.Session.UserId
- if result := <-app.Srv.Store.OAuth().SaveApp(oauthApp); result.Err != nil {
- c.Err = result.Err
- return
- } else {
- oauthApp = result.Data.(*model.OAuthApp)
+ rapp, err := app.CreateOAuthApp(oauthApp)
- c.LogAudit("client_id=" + oauthApp.Id)
-
- w.Write([]byte(oauthApp.ToJson()))
+ if err != nil {
+ c.Err = err
return
}
+ c.LogAudit("client_id=" + rapp.Id)
+ w.Write([]byte(rapp.ToJson()))
}
func getOAuthApps(c *Context, w http.ResponseWriter, r *http.Request) {
- if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
- c.Err = model.NewLocAppError("getOAuthAppsByUser", "api.oauth.allow_oauth.turn_off.app_error", nil, "")
- c.Err.StatusCode = http.StatusNotImplemented
- return
- }
-
if !app.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_OAUTH) {
- c.Err = model.NewLocAppError("getOAuthApps", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
+ c.Err = model.NewAppError("getOAuthApps", "api.command.admin_only.app_error", nil, "", http.StatusForbidden)
return
}
- var ochan store.StoreChannel
+ var apps []*model.OAuthApp
+ var err *model.AppError
if app.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH) {
- ochan = app.Srv.Store.OAuth().GetApps()
+ apps, err = app.GetOAuthApps(0, 100000)
} else {
- c.Err = nil
- ochan = app.Srv.Store.OAuth().GetAppByUser(c.Session.UserId)
+ apps, err = app.GetOAuthAppsByCreator(c.Session.UserId, 0, 100000)
}
- if result := <-ochan; result.Err != nil {
- c.Err = result.Err
+ if err != nil {
+ c.Err = err
return
- } else {
- apps := result.Data.([]*model.OAuthApp)
- w.Write([]byte(model.OAuthAppListToJson(apps)))
}
+
+ w.Write([]byte(model.OAuthAppListToJson(apps)))
}
func getOAuthAppInfo(c *Context, w http.ResponseWriter, r *http.Request) {
- if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
- c.Err = model.NewLocAppError("getOAuthAppInfo", "api.oauth.allow_oauth.turn_off.app_error", nil, "")
- c.Err.StatusCode = http.StatusNotImplemented
- return
- }
-
params := mux.Vars(r)
-
clientId := params["client_id"]
- var oauthApp *model.OAuthApp
- if result := <-app.Srv.Store.OAuth().GetApp(clientId); result.Err != nil {
- c.Err = model.NewLocAppError("getOAuthAppInfo", "api.oauth.allow_oauth.database.app_error", nil, "")
+ oauthApp, err := app.GetOAuthApp(clientId)
+
+ if err != nil {
+ c.Err = err
return
- } else {
- oauthApp = result.Data.(*model.OAuthApp)
}
oauthApp.Sanitize()
@@ -140,123 +103,49 @@ func getOAuthAppInfo(c *Context, w http.ResponseWriter, r *http.Request) {
}
func allowOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
- if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
- c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.turn_off.app_error", nil, "")
- c.Err.StatusCode = http.StatusNotImplemented
- return
- }
-
- c.LogAudit("attempt")
-
- responseData := map[string]string{}
-
responseType := r.URL.Query().Get("response_type")
if len(responseType) == 0 {
- c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.bad_response.app_error", nil, "")
- c.Err.StatusCode = http.StatusBadRequest
+ c.Err = model.NewAppError("allowOAuth", "api.oauth.allow_oauth.bad_response.app_error", nil, "", http.StatusBadRequest)
return
}
clientId := r.URL.Query().Get("client_id")
if len(clientId) != 26 {
- c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.bad_client.app_error", nil, "")
- c.Err.StatusCode = http.StatusBadRequest
+ c.Err = model.NewAppError("allowOAuth", "api.oauth.allow_oauth.bad_client.app_error", nil, "", http.StatusBadRequest)
return
}
redirectUri := r.URL.Query().Get("redirect_uri")
if len(redirectUri) == 0 {
- c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.bad_redirect.app_error", nil, "")
- c.Err.StatusCode = http.StatusBadRequest
+ c.Err = model.NewAppError("allowOAuth", "api.oauth.allow_oauth.bad_redirect.app_error", nil, "", http.StatusBadRequest)
return
}
scope := r.URL.Query().Get("scope")
state := r.URL.Query().Get("state")
- if len(scope) == 0 {
- scope = model.DEFAULT_SCOPE
- }
-
- var oauthApp *model.OAuthApp
- if result := <-app.Srv.Store.OAuth().GetApp(clientId); result.Err != nil {
- c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.database.app_error", nil, "")
- return
- } else {
- oauthApp = result.Data.(*model.OAuthApp)
- }
-
- if !oauthApp.IsValidRedirectURL(redirectUri) {
- c.LogAudit("fail - redirect_uri did not match registered callback")
- c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.redirect_callback.app_error", nil, "")
- c.Err.StatusCode = http.StatusBadRequest
- return
- }
-
- if responseType != model.AUTHCODE_RESPONSE_TYPE {
- responseData["redirect"] = redirectUri + "?error=unsupported_response_type&state=" + state
- w.Write([]byte(model.MapToJson(responseData)))
- return
- }
-
- authData := &model.AuthData{UserId: c.Session.UserId, ClientId: clientId, CreateAt: model.GetMillis(), RedirectUri: redirectUri, State: state, Scope: scope}
- authData.Code = model.HashPassword(fmt.Sprintf("%v:%v:%v:%v", clientId, redirectUri, authData.CreateAt, c.Session.UserId))
-
- // this saves the OAuth2 app as authorized
- authorizedApp := model.Preference{
- UserId: c.Session.UserId,
- Category: model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP,
- Name: clientId,
- Value: scope,
- }
+ c.LogAudit("attempt")
- if result := <-app.Srv.Store.Preference().Save(&model.Preferences{authorizedApp}); result.Err != nil {
- responseData["redirect"] = redirectUri + "?error=server_error&state=" + state
- w.Write([]byte(model.MapToJson(responseData)))
- return
- }
+ redirectUrl, err := app.AllowOAuthAppAccessToUser(c.Session.UserId, responseType, clientId, redirectUri, scope, state)
- if result := <-app.Srv.Store.OAuth().SaveAuthData(authData); result.Err != nil {
- responseData["redirect"] = redirectUri + "?error=server_error&state=" + state
- w.Write([]byte(model.MapToJson(responseData)))
+ if err != nil {
+ c.Err = err
return
}
- c.LogAudit("success")
+ c.LogAudit("")
- responseData["redirect"] = redirectUri + "?code=" + url.QueryEscape(authData.Code) + "&state=" + url.QueryEscape(authData.State)
- w.Write([]byte(model.MapToJson(responseData)))
+ w.Write([]byte(model.MapToJson(map[string]string{"redirect": redirectUrl})))
}
func getAuthorizedApps(c *Context, w http.ResponseWriter, r *http.Request) {
- if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
- c.Err = model.NewLocAppError("getAuthorizedApps", "api.oauth.allow_oauth.turn_off.app_error", nil, "")
- c.Err.StatusCode = http.StatusNotImplemented
- return
- }
-
- ochan := app.Srv.Store.OAuth().GetAuthorizedApps(c.Session.UserId)
- if result := <-ochan; result.Err != nil {
- c.Err = result.Err
+ apps, err := app.GetAuthorizedAppsForUser(c.Session.UserId, 0, 10000)
+ if err != nil {
+ c.Err = err
return
- } else {
- apps := result.Data.([]*model.OAuthApp)
- for k, a := range apps {
- a.Sanitize()
- apps[k] = a
- }
-
- w.Write([]byte(model.OAuthAppListToJson(apps)))
}
-}
-func GetAuthData(code string) *model.AuthData {
- if result := <-app.Srv.Store.OAuth().GetAuthData(code); result.Err != nil {
- l4g.Error(utils.T("api.oauth.get_auth_data.find.error"), code)
- return nil
- } else {
- return result.Data.(*model.AuthData)
- }
+ w.Write([]byte(model.OAuthAppListToJson(apps)))
}
func completeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -273,60 +162,36 @@ func completeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
uri := c.GetSiteURLHeader() + "/signup/" + service + "/complete"
- if body, teamId, props, err := AuthorizeOAuthUser(service, code, state, uri); err != nil {
+ body, teamId, props, err := app.AuthorizeOAuthUser(service, code, state, uri)
+ if err != nil {
c.Err = err
return
+ }
+
+ user, err := app.CompleteOAuth(service, body, teamId, props)
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ action := props["action"]
+
+ var redirectUrl string
+ if action == model.OAUTH_ACTION_EMAIL_TO_SSO {
+ redirectUrl = c.GetSiteURLHeader() + "/login?extra=signin_change"
+ } else if action == model.OAUTH_ACTION_SSO_TO_EMAIL {
+
+ redirectUrl = app.GetProtocol(r) + "://" + r.Host + "/claim?email=" + url.QueryEscape(props["email"])
} else {
- defer func() {
- ioutil.ReadAll(body)
- body.Close()
- }()
-
- action := props["action"]
- switch action {
- case model.OAUTH_ACTION_SIGNUP:
- if user, err := app.CreateOAuthUser(service, body, teamId); err != nil {
- c.Err = err
- } else {
- doLogin(c, w, r, user, "")
- }
- if c.Err == nil {
- http.Redirect(w, r, app.GetProtocol(r)+"://"+r.Host, http.StatusTemporaryRedirect)
- }
- break
- case model.OAUTH_ACTION_LOGIN:
- user := LoginByOAuth(c, w, r, service, body)
- if len(teamId) > 0 {
- c.Err = app.AddUserToTeamByTeamId(teamId, user)
- }
- if c.Err == nil {
- if val, ok := props["redirect_to"]; ok {
- http.Redirect(w, r, c.GetSiteURLHeader()+val, http.StatusTemporaryRedirect)
- return
- }
- http.Redirect(w, r, app.GetProtocol(r)+"://"+r.Host, http.StatusTemporaryRedirect)
- }
- break
- case model.OAUTH_ACTION_EMAIL_TO_SSO:
- CompleteSwitchWithOAuth(c, w, r, service, body, props["email"])
- if c.Err == nil {
- http.Redirect(w, r, app.GetProtocol(r)+"://"+r.Host+"/login?extra=signin_change", http.StatusTemporaryRedirect)
- }
- break
- case model.OAUTH_ACTION_SSO_TO_EMAIL:
- LoginByOAuth(c, w, r, service, body)
- if c.Err == nil {
- http.Redirect(w, r, app.GetProtocol(r)+"://"+r.Host+"/claim?email="+url.QueryEscape(props["email"]), http.StatusTemporaryRedirect)
- }
- break
- default:
- LoginByOAuth(c, w, r, service, body)
- if c.Err == nil {
- http.Redirect(w, r, app.GetProtocol(r)+"://"+r.Host, http.StatusTemporaryRedirect)
- }
- break
+ doLogin(c, w, r, user, "")
+ if c.Err != nil {
+ return
}
+
+ redirectUrl = c.GetSiteURLHeader()
}
+
+ http.Redirect(w, r, redirectUrl, http.StatusTemporaryRedirect)
}
func authorizeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -373,42 +238,15 @@ func authorizeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
// Automatically allow if the app is trusted
if oauthApp.IsTrusted || isAuthorized {
- closeBody := func(r *http.Response) {
- if r.Body != nil {
- ioutil.ReadAll(r.Body)
- r.Body.Close()
- }
- }
+ redirectUrl, err := app.AllowOAuthAppAccessToUser(c.Session.UserId, model.AUTHCODE_RESPONSE_TYPE, clientId, redirect, scope, state)
- doAllow := func() (*http.Response, *model.AppError) {
- HttpClient := &http.Client{}
- url := c.GetSiteURLHeader() + "/api/v3/oauth/allow?response_type=" + model.AUTHCODE_RESPONSE_TYPE + "&client_id=" + clientId + "&redirect_uri=" + url.QueryEscape(redirect) + "&scope=" + scope + "&state=" + url.QueryEscape(state)
- rq, _ := http.NewRequest("GET", url, strings.NewReader(""))
-
- rq.Header.Set(model.HEADER_AUTH, model.HEADER_BEARER+" "+c.Session.Token)
-
- if rp, err := HttpClient.Do(rq); err != nil {
- return nil, model.NewLocAppError(url, "model.client.connecting.app_error", nil, err.Error())
- } else if rp.StatusCode == 304 {
- return rp, nil
- } else if rp.StatusCode >= 300 {
- defer closeBody(rp)
- return rp, model.AppErrorFromJson(rp.Body)
- } else {
- return rp, nil
- }
- }
-
- if result, err := doAllow(); err != nil {
+ if err != nil {
c.Err = err
return
- } else {
- //defer closeBody(result)
- data := model.MapFromJson(result.Body)
- redirectTo := data["redirect"]
- http.Redirect(w, r, redirectTo, http.StatusFound)
- return
}
+
+ http.Redirect(w, r, redirectUrl, http.StatusFound)
+ return
}
w.Header().Set("Content-Type", "text/html")
@@ -418,14 +256,6 @@ func authorizeOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
}
func getAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
- if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
- c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.disabled.app_error", nil, "")
- c.Err.StatusCode = http.StatusNotImplemented
- return
- }
-
- c.LogAudit("attempt")
-
r.ParseForm()
code := r.FormValue("code")
@@ -460,140 +290,21 @@ func getAccessToken(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- var oauthApp *model.OAuthApp
- achan := app.Srv.Store.OAuth().GetApp(clientId)
- if result := <-achan; result.Err != nil {
- c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.credentials.app_error", nil, "")
- return
- } else {
- oauthApp = result.Data.(*model.OAuthApp)
- }
-
- if oauthApp.ClientSecret != secret {
- c.LogAudit("fail - invalid client credentials")
- c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.credentials.app_error", nil, "")
- return
- }
-
- var user *model.User
- var accessData *model.AccessData
- var accessRsp *model.AccessResponse
- if grantType == model.ACCESS_TOKEN_GRANT_TYPE {
- redirectUri := r.FormValue("redirect_uri")
- authData := GetAuthData(code)
-
- if authData == nil {
- c.LogAudit("fail - invalid auth code")
- c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.expired_code.app_error", nil, "")
- return
- }
-
- if authData.IsExpired() {
- <-app.Srv.Store.OAuth().RemoveAuthData(authData.Code)
- c.LogAudit("fail - auth code expired")
- c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.expired_code.app_error", nil, "")
- return
- }
-
- if authData.RedirectUri != redirectUri {
- c.LogAudit("fail - redirect uri provided did not match previous redirect uri")
- c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.redirect_uri.app_error", nil, "")
- return
- }
-
- if !model.ComparePassword(code, fmt.Sprintf("%v:%v:%v:%v", clientId, redirectUri, authData.CreateAt, authData.UserId)) {
- c.LogAudit("fail - auth code is invalid")
- c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.expired_code.app_error", nil, "")
- return
- }
-
- uchan := app.Srv.Store.User().Get(authData.UserId)
- if result := <-uchan; result.Err != nil {
- c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.internal_user.app_error", nil, "")
- return
- } else {
- user = result.Data.(*model.User)
- }
-
- tchan := app.Srv.Store.OAuth().GetPreviousAccessData(user.Id, clientId)
- if result := <-tchan; result.Err != nil {
- c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.internal.app_error", nil, "")
- return
- } else if result.Data != nil {
- accessData := result.Data.(*model.AccessData)
- if accessData.IsExpired() {
- if access, err := newSessionUpdateToken(oauthApp.Name, accessData, user); err != nil {
- c.Err = err
- return
- } else {
- accessRsp = access
- }
- } else {
- //return the same token and no need to create a new session
- accessRsp = &model.AccessResponse{
- AccessToken: accessData.Token,
- TokenType: model.ACCESS_TOKEN_TYPE,
- ExpiresIn: int32((accessData.ExpiresAt - model.GetMillis()) / 1000),
- }
- }
- } else {
- // create a new session and return new access token
- var session *model.Session
- if result, err := newSession(oauthApp.Name, user); err != nil {
- c.Err = err
- return
- } else {
- session = result
- }
-
- accessData = &model.AccessData{ClientId: clientId, UserId: user.Id, Token: session.Token, RefreshToken: model.NewId(), RedirectUri: redirectUri, ExpiresAt: session.ExpiresAt}
-
- if result := <-app.Srv.Store.OAuth().SaveAccessData(accessData); result.Err != nil {
- l4g.Error(result.Err)
- c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.internal_saving.app_error", nil, "")
- return
- }
-
- accessRsp = &model.AccessResponse{
- AccessToken: session.Token,
- TokenType: model.ACCESS_TOKEN_TYPE,
- RefreshToken: accessData.RefreshToken,
- ExpiresIn: int32(*utils.Cfg.ServiceSettings.SessionLengthSSOInDays * 60 * 60 * 24),
- }
- }
-
- <-app.Srv.Store.OAuth().RemoveAuthData(authData.Code)
- } else {
- // when grantType is refresh_token
- if result := <-app.Srv.Store.OAuth().GetAccessDataByRefreshToken(refreshToken); result.Err != nil {
- c.LogAudit("fail - refresh token is invalid")
- c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.refresh_token.app_error", nil, "")
- return
- } else {
- accessData = result.Data.(*model.AccessData)
- }
+ redirectUri := r.FormValue("redirect_uri")
- uchan := app.Srv.Store.User().Get(accessData.UserId)
- if result := <-uchan; result.Err != nil {
- c.Err = model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.internal_user.app_error", nil, "")
- return
- } else {
- user = result.Data.(*model.User)
- }
+ c.LogAudit("attempt")
- if access, err := newSessionUpdateToken(oauthApp.Name, accessData, user); err != nil {
- c.Err = err
- return
- } else {
- accessRsp = access
- }
+ accessRsp, err := app.GetOAuthAccessToken(clientId, grantType, redirectUri, code, secret, refreshToken)
+ if err != nil {
+ c.Err = err
+ return
}
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Cache-Control", "no-store")
w.Header().Set("Pragma", "no-cache")
- c.LogAuditWithUserId(user.Id, "success")
+ c.LogAudit("success")
w.Write([]byte(accessRsp.ToJson()))
}
@@ -604,23 +315,13 @@ func loginWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
loginHint := r.URL.Query().Get("login_hint")
redirectTo := r.URL.Query().Get("redirect_to")
- teamId, err := getTeamIdFromQuery(r.URL.Query())
+ teamId, err := app.GetTeamIdFromQuery(r.URL.Query())
if err != nil {
c.Err = err
return
}
- stateProps := map[string]string{}
- stateProps["action"] = model.OAUTH_ACTION_LOGIN
- if len(teamId) != 0 {
- stateProps["team_id"] = teamId
- }
-
- if len(redirectTo) != 0 {
- stateProps["redirect_to"] = redirectTo
- }
-
- if authUrl, err := GetAuthorizationCode(c, service, stateProps, loginHint); err != nil {
+ if authUrl, err := app.GetOAuthLoginEndpoint(service, teamId, redirectTo, loginHint); err != nil {
c.Err = err
return
} else {
@@ -628,59 +329,22 @@ func loginWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
-func getTeamIdFromQuery(query url.Values) (string, *model.AppError) {
- hash := query.Get("h")
- inviteId := query.Get("id")
-
- if len(hash) > 0 {
- data := query.Get("d")
- props := model.MapFromJson(strings.NewReader(data))
-
- if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) {
- return "", model.NewLocAppError("getTeamIdFromQuery", "api.oauth.singup_with_oauth.invalid_link.app_error", nil, "")
- }
-
- t, err := strconv.ParseInt(props["time"], 10, 64)
- if err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours
- return "", model.NewLocAppError("getTeamIdFromQuery", "api.oauth.singup_with_oauth.expired_link.app_error", nil, "")
- }
-
- return props["id"], nil
- } else if len(inviteId) > 0 {
- if result := <-app.Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
- // soft fail, so we still create user but don't auto-join team
- l4g.Error("%v", result.Err)
- } else {
- return result.Data.(*model.Team).Id, nil
- }
- }
-
- return "", nil
-}
-
func signupWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
service := params["service"]
if !utils.Cfg.TeamSettings.EnableUserCreation {
- c.Err = model.NewLocAppError("signupWithOAuth", "api.oauth.singup_with_oauth.disabled.app_error", nil, "")
- c.Err.StatusCode = http.StatusNotImplemented
+ c.Err = model.NewAppError("signupWithOAuth", "api.oauth.singup_with_oauth.disabled.app_error", nil, "", http.StatusNotImplemented)
return
}
- teamId, err := getTeamIdFromQuery(r.URL.Query())
+ teamId, err := app.GetTeamIdFromQuery(r.URL.Query())
if err != nil {
c.Err = err
return
}
- stateProps := map[string]string{}
- stateProps["action"] = model.OAUTH_ACTION_SIGNUP
- if len(teamId) != 0 {
- stateProps["team_id"] = teamId
- }
-
- if authUrl, err := GetAuthorizationCode(c, service, stateProps, ""); err != nil {
+ if authUrl, err := app.GetOAuthSignupEndpoint(service, teamId); err != nil {
c.Err = err
return
} else {
@@ -688,201 +352,36 @@ func signupWithOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
-func GetAuthorizationCode(c *Context, service string, props map[string]string, loginHint string) (string, *model.AppError) {
-
- sso := utils.Cfg.GetSSOService(service)
- if sso != nil && !sso.Enable {
- return "", model.NewLocAppError("GetAuthorizationCode", "api.user.get_authorization_code.unsupported.app_error", nil, "service="+service)
- }
-
- clientId := sso.Id
- endpoint := sso.AuthEndpoint
- scope := sso.Scope
-
- props["hash"] = model.HashPassword(clientId)
- state := b64.StdEncoding.EncodeToString([]byte(model.MapToJson(props)))
-
- redirectUri := utils.GetSiteURL() + "/signup/" + service + "/complete"
-
- authUrl := endpoint + "?response_type=code&client_id=" + clientId + "&redirect_uri=" + url.QueryEscape(redirectUri) + "&state=" + url.QueryEscape(state)
-
- if len(scope) > 0 {
- authUrl += "&scope=" + utils.UrlEncode(scope)
- }
-
- if len(loginHint) > 0 {
- authUrl += "&login_hint=" + utils.UrlEncode(loginHint)
- }
-
- return authUrl, nil
-}
-
-func AuthorizeOAuthUser(service, code, state, redirectUri string) (io.ReadCloser, string, map[string]string, *model.AppError) {
- sso := utils.Cfg.GetSSOService(service)
- if sso == nil || !sso.Enable {
- return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.unsupported.app_error", nil, "service="+service)
- }
-
- stateStr := ""
- if b, err := b64.StdEncoding.DecodeString(state); err != nil {
- return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, err.Error())
- } else {
- stateStr = string(b)
- }
-
- stateProps := model.MapFromJson(strings.NewReader(stateStr))
-
- if !model.ComparePassword(stateProps["hash"], sso.Id) {
- return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, "")
- }
-
- teamId := stateProps["team_id"]
-
- p := url.Values{}
- p.Set("client_id", sso.Id)
- p.Set("client_secret", sso.Secret)
- p.Set("code", code)
- p.Set("grant_type", model.ACCESS_TOKEN_GRANT_TYPE)
- p.Set("redirect_uri", redirectUri)
-
- tr := &http.Transport{
- TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
- }
- client := &http.Client{Transport: tr}
- req, _ := http.NewRequest("POST", sso.TokenEndpoint, strings.NewReader(p.Encode()))
-
- req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
- req.Header.Set("Accept", "application/json")
-
- var ar *model.AccessResponse
- var respBody []byte
- if resp, err := client.Do(req); err != nil {
- return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.token_failed.app_error", nil, err.Error())
- } else {
- ar = model.AccessResponseFromJson(resp.Body)
- defer func() {
- ioutil.ReadAll(resp.Body)
- resp.Body.Close()
- }()
- if ar == nil {
- return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_response.app_error", nil, "")
- }
- }
-
- if strings.ToLower(ar.TokenType) != model.ACCESS_TOKEN_TYPE {
- return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_token.app_error", nil, "token_type="+ar.TokenType+", response_body="+string(respBody))
- }
-
- if len(ar.AccessToken) == 0 {
- return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.missing.app_error", nil, "")
- }
-
- p = url.Values{}
- p.Set("access_token", ar.AccessToken)
- req, _ = http.NewRequest("GET", sso.UserApiEndpoint, strings.NewReader(""))
-
- req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
- req.Header.Set("Accept", "application/json")
- req.Header.Set("Authorization", "Bearer "+ar.AccessToken)
-
- if resp, err := client.Do(req); err != nil {
- return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.service.app_error",
- map[string]interface{}{"Service": service}, err.Error())
- } else {
- return resp.Body, teamId, stateProps, nil
- }
-
-}
-
-func CompleteSwitchWithOAuth(c *Context, w http.ResponseWriter, r *http.Request, service string, userData io.ReadCloser, email string) {
- authData := ""
- ssoEmail := ""
- provider := einterfaces.GetOauthProvider(service)
- if provider == nil {
- c.Err = model.NewLocAppError("CompleteClaimWithOAuth", "api.user.complete_switch_with_oauth.unavailable.app_error",
- map[string]interface{}{"Service": strings.Title(service)}, "")
- return
- } else {
- ssoUser := provider.GetUserFromJson(userData)
- ssoEmail = ssoUser.Email
-
- if ssoUser.AuthData != nil {
- authData = *ssoUser.AuthData
- }
- }
-
- if len(authData) == 0 {
- c.Err = model.NewLocAppError("CompleteClaimWithOAuth", "api.user.complete_switch_with_oauth.parse.app_error",
- map[string]interface{}{"Service": service}, "")
- return
- }
-
- if len(email) == 0 {
- c.Err = model.NewLocAppError("CompleteClaimWithOAuth", "api.user.complete_switch_with_oauth.blank_email.app_error", nil, "")
- return
- }
-
- var user *model.User
- if result := <-app.Srv.Store.User().GetByEmail(email); result.Err != nil {
- c.Err = result.Err
- return
- } else {
- user = result.Data.(*model.User)
- }
-
- if err := app.RevokeAllSessions(user.Id); err != nil {
- c.Err = err
- return
- }
- c.LogAuditWithUserId(user.Id, "Revoked all sessions for user")
+func deleteOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
+ props := model.MapFromJson(r.Body)
- if result := <-app.Srv.Store.User().UpdateAuthData(user.Id, service, &authData, ssoEmail, true); result.Err != nil {
- c.Err = result.Err
+ id := props["id"]
+ if len(id) == 0 {
+ c.SetInvalidParam("deleteOAuthApp", "id")
return
}
- go func() {
- if err := app.SendSignInChangeEmail(user.Email, strings.Title(service)+" SSO", user.Locale, utils.GetSiteURL()); err != nil {
- l4g.Error(err.Error())
- }
- }()
-}
-
-func deleteOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
- if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
- c.Err = model.NewLocAppError("deleteOAuthApp", "api.oauth.allow_oauth.turn_off.app_error", nil, "")
- c.Err.StatusCode = http.StatusNotImplemented
- return
- }
+ c.LogAudit("attempt")
if !app.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_OAUTH) {
- c.Err = model.NewLocAppError("deleteOAuthApp", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
+ c.Err = model.NewAppError("deleteOAuthApp", "api.command.admin_only.app_error", nil, "", http.StatusForbidden)
return
}
- c.LogAudit("attempt")
-
- props := model.MapFromJson(r.Body)
-
- id := props["id"]
- if len(id) == 0 {
- c.SetInvalidParam("deleteOAuthApp", "id")
+ oauthApp, err := app.GetOAuthApp(id)
+ if err != nil {
+ c.Err = err
return
}
- if result := <-app.Srv.Store.OAuth().GetApp(id); result.Err != nil {
- c.Err = result.Err
+ if c.Session.UserId != oauthApp.CreatorId && !app.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH) {
+ c.LogAudit("fail - inappropriate permissions")
+ c.Err = model.NewAppError("deleteOAuthApp", "api.oauth.delete.permissions.app_error", nil, "user_id="+c.Session.UserId, http.StatusForbidden)
return
- } else {
- if c.Session.UserId != result.Data.(*model.OAuthApp).CreatorId && !app.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH) {
- c.LogAudit("fail - inappropriate permissions")
- c.Err = model.NewLocAppError("deleteOAuthApp", "api.oauth.delete.permissions.app_error", nil, "user_id="+c.Session.UserId)
- return
- }
}
- if err := (<-app.Srv.Store.OAuth().DeleteApp(id)).Err; err != nil {
+ err = app.DeleteOAuthApp(id)
+ if err != nil {
c.Err = err
return
}
@@ -892,37 +391,11 @@ func deleteOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
}
func deauthorizeOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
- if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
- c.Err = model.NewLocAppError("deleteOAuthApp", "api.oauth.allow_oauth.turn_off.app_error", nil, "")
- c.Err.StatusCode = http.StatusNotImplemented
- return
- }
-
params := mux.Vars(r)
id := params["id"]
- // revoke app sessions
- if result := <-app.Srv.Store.OAuth().GetAccessDataByUserForApp(c.Session.UserId, id); result.Err != nil {
- c.Err = result.Err
- return
- } else {
- accessData := result.Data.([]*model.AccessData)
-
- for _, a := range accessData {
- if err := app.RevokeAccessToken(a.Token); err != nil {
- c.Err = err
- return
- }
-
- if rad := <-app.Srv.Store.OAuth().RemoveAccessData(a.Token); rad.Err != nil {
- c.Err = rad.Err
- return
- }
- }
- }
-
- // Deauthorize the app
- if err := (<-app.Srv.Store.Preference().Delete(c.Session.UserId, model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP, id)).Err; err != nil {
+ err := app.DeauthorizeOAuthAppForUser(c.Session.UserId, id)
+ if err != nil {
c.Err = err
return
}
@@ -932,78 +405,25 @@ func deauthorizeOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
}
func regenerateOAuthSecret(c *Context, w http.ResponseWriter, r *http.Request) {
- if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
- c.Err = model.NewLocAppError("registerOAuthApp", "api.oauth.register_oauth_app.turn_off.app_error", nil, "")
- c.Err.StatusCode = http.StatusNotImplemented
- return
- }
-
params := mux.Vars(r)
id := params["id"]
- var oauthApp *model.OAuthApp
- if result := <-app.Srv.Store.OAuth().GetApp(id); result.Err != nil {
- c.Err = model.NewLocAppError("regenerateOAuthSecret", "api.oauth.allow_oauth.database.app_error", nil, "")
- return
- } else {
- oauthApp = result.Data.(*model.OAuthApp)
-
- if oauthApp.CreatorId != c.Session.UserId && !app.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH) {
- c.Err = model.NewLocAppError("registerOAuthApp", "api.command.admin_only.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
-
- oauthApp.ClientSecret = model.NewId()
- if update := <-app.Srv.Store.OAuth().UpdateApp(oauthApp); update.Err != nil {
- c.Err = update.Err
- return
- }
-
- w.Write([]byte(oauthApp.ToJson()))
+ oauthApp, err := app.GetOAuthApp(id)
+ if err != nil {
+ c.Err = err
return
}
-}
-
-func newSession(appName string, user *model.User) (*model.Session, *model.AppError) {
- // set new token an session
- session := &model.Session{UserId: user.Id, Roles: user.Roles, IsOAuth: true}
- session.SetExpireInDays(*utils.Cfg.ServiceSettings.SessionLengthSSOInDays)
- session.AddProp(model.SESSION_PROP_PLATFORM, appName)
- session.AddProp(model.SESSION_PROP_OS, "OAuth2")
- session.AddProp(model.SESSION_PROP_BROWSER, "OAuth2")
-
- if result := <-app.Srv.Store.Session().Save(session); result.Err != nil {
- return nil, model.NewLocAppError("getAccessToken", "api.oauth.get_access_token.internal_session.app_error", nil, "")
- } else {
- session = result.Data.(*model.Session)
- app.AddSessionToCache(session)
- }
-
- return session, nil
-}
-
-func newSessionUpdateToken(appName string, accessData *model.AccessData, user *model.User) (*model.AccessResponse, *model.AppError) {
- var session *model.Session
- <-app.Srv.Store.Session().Remove(accessData.Token) //remove the previous session
- if result, err := newSession(appName, user); err != nil {
- return nil, err
- } else {
- session = result
+ if oauthApp.CreatorId != c.Session.UserId && !app.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM_WIDE_OAUTH) {
+ c.Err = model.NewAppError("regenerateOAuthSecret", "api.command.admin_only.app_error", nil, "", http.StatusForbidden)
+ return
}
- accessData.Token = session.Token
- accessData.ExpiresAt = session.ExpiresAt
- if result := <-app.Srv.Store.OAuth().UpdateAccessData(accessData); result.Err != nil {
- l4g.Error(result.Err)
- return nil, model.NewLocAppError("getAccessToken", "web.get_access_token.internal_saving.app_error", nil, "")
- }
- accessRsp := &model.AccessResponse{
- AccessToken: session.Token,
- TokenType: model.ACCESS_TOKEN_TYPE,
- ExpiresIn: int32(*utils.Cfg.ServiceSettings.SessionLengthSSOInDays * 60 * 60 * 24),
+ oauthApp, err = app.RegenerateOAuthAppSecret(oauthApp)
+ if err != nil {
+ c.Err = err
+ return
}
- return accessRsp, nil
+ w.Write([]byte(oauthApp.ToJson()))
}
diff --git a/api/oauth_test.go b/api/oauth_test.go
index 5f55ae8f0..3dcaa0ddf 100644
--- a/api/oauth_test.go
+++ b/api/oauth_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
@@ -491,7 +491,7 @@ func TestOAuthAuthorize(t *testing.T) {
}
authToken := Client.AuthType + " " + Client.AuthToken
- if r, err := HttpGet(Client.Url+"/oauth/authorize?client_id="+oauthApp.Id+"&&redirect_uri=http://example.com&response_type="+model.AUTHCODE_RESPONSE_TYPE, Client.HttpClient, authToken, true); err != nil {
+ if r, err := HttpGet(Client.Url+"/oauth/authorize?client_id="+oauthApp.Id+"&redirect_uri=http://example.com&response_type="+model.AUTHCODE_RESPONSE_TYPE, Client.HttpClient, authToken, true); err != nil {
t.Fatal(err)
closeBody(r)
}
diff --git a/api/post.go b/api/post.go
index bfc68a0d0..192b01bd5 100644
--- a/api/post.go
+++ b/api/post.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/post_test.go b/api/post_test.go
index d2297fb69..8dc164c1b 100644
--- a/api/post_test.go
+++ b/api/post_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/preference.go b/api/preference.go
index 5384afbb5..9fdc0279c 100644
--- a/api/preference.go
+++ b/api/preference.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/preference_test.go b/api/preference_test.go
index 3e41c884f..8388138c1 100644
--- a/api/preference_test.go
+++ b/api/preference_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/reaction.go b/api/reaction.go
index 85b44b82d..a4992d61b 100644
--- a/api/reaction.go
+++ b/api/reaction.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/reaction_test.go b/api/reaction_test.go
index dad5a6a0c..27a296930 100644
--- a/api/reaction_test.go
+++ b/api/reaction_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/server_test.go b/api/server_test.go
index a9837203f..53ad652c9 100644
--- a/api/server_test.go
+++ b/api/server_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/status.go b/api/status.go
index df4be4603..b945d7e90 100644
--- a/api/status.go
+++ b/api/status.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/status_test.go b/api/status_test.go
index f886d1044..7aa6a2299 100644
--- a/api/status_test.go
+++ b/api/status_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/team.go b/api/team.go
index 899948a94..c7fa61df6 100644
--- a/api/team.go
+++ b/api/team.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/team_test.go b/api/team_test.go
index 9dd598834..a7cffbb34 100644
--- a/api/team_test.go
+++ b/api/team_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/user.go b/api/user.go
index 7f422b355..8b32dff36 100644
--- a/api/user.go
+++ b/api/user.go
@@ -1,13 +1,11 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
import (
- "bytes"
b64 "encoding/base64"
"fmt"
- "io"
"net/http"
"strconv"
"strings"
@@ -132,52 +130,6 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(user.ToJson()))
}
-func LoginByOAuth(c *Context, w http.ResponseWriter, r *http.Request, service string, userData io.Reader) *model.User {
- buf := bytes.Buffer{}
- buf.ReadFrom(userData)
-
- authData := ""
- provider := einterfaces.GetOauthProvider(service)
- if provider == nil {
- c.Err = model.NewLocAppError("LoginByOAuth", "api.user.login_by_oauth.not_available.app_error",
- map[string]interface{}{"Service": strings.Title(service)}, "")
- return nil
- } else {
- authData = provider.GetAuthDataFromJson(bytes.NewReader(buf.Bytes()))
- }
-
- if len(authData) == 0 {
- c.Err = model.NewLocAppError("LoginByOAuth", "api.user.login_by_oauth.parse.app_error",
- map[string]interface{}{"Service": service}, "")
- return nil
- }
-
- var user *model.User
- var err *model.AppError
- if user, err = app.GetUserByAuth(&authData, service); err != nil {
- if err.Id == store.MISSING_AUTH_ACCOUNT_ERROR {
- if user, err = app.CreateOAuthUser(service, bytes.NewReader(buf.Bytes()), ""); err != nil {
- c.Err = err
- return nil
- }
- }
- c.Err = err
- return nil
- }
-
- if err = app.UpdateOAuthUserAttrs(bytes.NewReader(buf.Bytes()), user, provider, service); err != nil {
- c.Err = err
- return nil
- }
-
- doLogin(c, w, r, user, "")
- if c.Err != nil {
- return nil
- }
-
- return user
-}
-
// User MUST be authenticated completely before calling Login
func doLogin(c *Context, w http.ResponseWriter, r *http.Request, user *model.User, deviceId string) {
session, err := app.DoLogin(w, r, user, deviceId)
@@ -914,41 +866,14 @@ func emailToOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- c.LogAudit("attempt")
-
- var user *model.User
- var err *model.AppError
- if user, err = app.GetUserByEmail(email); err != nil {
- c.LogAudit("fail - couldn't get user")
- c.Err = err
- return
- }
-
- if err := app.CheckPasswordAndAllCriteria(user, password, mfaToken); err != nil {
- c.LogAuditWithUserId(user.Id, "failed - bad authentication")
+ link, err := app.SwitchEmailToOAuth(email, password, mfaToken, service)
+ if err != nil {
c.Err = err
return
}
- stateProps := map[string]string{}
- stateProps["action"] = model.OAUTH_ACTION_EMAIL_TO_SSO
- stateProps["email"] = email
-
- m := map[string]string{}
- if service == model.USER_AUTH_SERVICE_SAML {
- m["follow_link"] = c.GetSiteURLHeader() + "/login/sso/saml?action=" + model.OAUTH_ACTION_EMAIL_TO_SSO + "&email=" + email
- } else {
- if authUrl, err := GetAuthorizationCode(c, service, stateProps, ""); err != nil {
- c.LogAuditWithUserId(user.Id, "fail - oauth issue")
- c.Err = err
- return
- } else {
- m["follow_link"] = authUrl
- }
- }
-
- c.LogAuditWithUserId(user.Id, "success")
- w.Write([]byte(model.MapToJson(m)))
+ c.LogAudit("success for email=" + email)
+ w.Write([]byte(model.MapToJson(map[string]string{"follow_link": link})))
}
func oauthToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -966,51 +891,19 @@ func oauthToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- c.LogAudit("attempt")
-
- var user *model.User
- var err *model.AppError
- if user, err = app.GetUserByEmail(email); err != nil {
- c.LogAudit("fail - couldn't get user")
- c.Err = err
- return
- }
-
- if user.Id != c.Session.UserId {
- c.LogAudit("fail - user ids didn't match")
- c.Err = model.NewLocAppError("oauthToEmail", "api.user.oauth_to_email.context.app_error", nil, "")
- c.Err.StatusCode = http.StatusForbidden
- return
- }
-
- if err := app.UpdatePassword(user, password); err != nil {
- c.LogAudit("fail - database issue")
- c.Err = err
- return
- }
-
- go func() {
- if err := app.SendSignInChangeEmail(user.Email, c.T("api.templates.signin_change_email.body.method_email"), user.Locale, utils.GetSiteURL()); err != nil {
- l4g.Error(err.Error())
- }
- }()
-
- if err := app.RevokeAllSessions(c.Session.UserId); err != nil {
+ link, err := app.SwitchOAuthToEmail(email, password, c.Session.UserId)
+ if err != nil {
c.Err = err
return
}
- c.LogAuditWithUserId(c.Session.UserId, "Revoked all sessions for user")
c.RemoveSessionCookie(w, r)
if c.Err != nil {
return
}
- m := map[string]string{}
- m["follow_link"] = "/login?extra=signin_change"
-
c.LogAudit("success")
- w.Write([]byte(model.MapToJson(m)))
+ w.Write([]byte(model.MapToJson(map[string]string{"follow_link": link})))
}
func emailToLdap(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -1044,55 +937,19 @@ func emailToLdap(c *Context, w http.ResponseWriter, r *http.Request) {
c.LogAudit("attempt")
- var user *model.User
- var err *model.AppError
- if user, err = app.GetUserByEmail(email); err != nil {
- c.LogAudit("fail - couldn't get user")
- c.Err = err
- return
- }
-
- if err := app.CheckPasswordAndAllCriteria(user, emailPassword, token); err != nil {
- c.LogAuditWithUserId(user.Id, "failed - bad authentication")
- c.Err = err
- return
- }
-
- if err := app.RevokeAllSessions(user.Id); err != nil {
+ link, err := app.SwitchEmailToLdap(email, emailPassword, token, ldapId, ldapPassword)
+ if err != nil {
c.Err = err
return
}
- c.LogAuditWithUserId(user.Id, "Revoked all sessions for user")
c.RemoveSessionCookie(w, r)
if c.Err != nil {
return
}
- ldapInterface := einterfaces.GetLdapInterface()
- if ldapInterface == nil {
- c.Err = model.NewLocAppError("emailToLdap", "api.user.email_to_ldap.not_available.app_error", nil, "")
- c.Err.StatusCode = http.StatusNotImplemented
- return
- }
-
- if err := ldapInterface.SwitchToLdap(user.Id, ldapId, ldapPassword); err != nil {
- c.LogAuditWithUserId(user.Id, "fail - ldap switch failed")
- c.Err = err
- return
- }
-
- go func() {
- if err := app.SendSignInChangeEmail(user.Email, "AD/LDAP", user.Locale, utils.GetSiteURL()); err != nil {
- l4g.Error(err.Error())
- }
- }()
-
- m := map[string]string{}
- m["follow_link"] = "/login?extra=signin_change"
-
c.LogAudit("success")
- w.Write([]byte(model.MapToJson(m)))
+ w.Write([]byte(model.MapToJson(map[string]string{"follow_link": link})))
}
func ldapToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -1120,66 +977,19 @@ func ldapToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
c.LogAudit("attempt")
- var user *model.User
- var err *model.AppError
- if user, err = app.GetUserByEmail(email); err != nil {
- c.LogAudit("fail - couldn't get user")
- c.Err = err
- return
- }
-
- if user.AuthService != model.USER_AUTH_SERVICE_LDAP {
- c.Err = model.NewLocAppError("ldapToEmail", "api.user.ldap_to_email.not_ldap_account.app_error", nil, "")
- return
- }
-
- ldapInterface := einterfaces.GetLdapInterface()
- if ldapInterface == nil || user.AuthData == nil {
- c.Err = model.NewLocAppError("ldapToEmail", "api.user.ldap_to_email.not_available.app_error", nil, "")
- c.Err.StatusCode = http.StatusNotImplemented
- return
- }
-
- if err := ldapInterface.CheckPassword(*user.AuthData, ldapPassword); err != nil {
- c.LogAuditWithUserId(user.Id, "fail - ldap authentication failed")
- c.Err = err
- return
- }
-
- if err := app.CheckUserMfa(user, token); err != nil {
- c.LogAuditWithUserId(user.Id, "fail - mfa token failed")
- c.Err = err
- return
- }
-
- if err := app.UpdatePassword(user, emailPassword); err != nil {
- c.LogAudit("fail - database issue")
- c.Err = err
- return
- }
-
- if err := app.RevokeAllSessions(user.Id); err != nil {
+ link, err := app.SwitchLdapToEmail(ldapPassword, token, email, emailPassword)
+ if err != nil {
c.Err = err
return
}
- c.LogAuditWithUserId(user.Id, "Revoked all sessions for user")
c.RemoveSessionCookie(w, r)
if c.Err != nil {
return
}
- go func() {
- if err := app.SendSignInChangeEmail(user.Email, c.T("api.templates.signin_change_email.body.method_email"), user.Locale, utils.GetSiteURL()); err != nil {
- l4g.Error(err.Error())
- }
- }()
-
- m := map[string]string{}
- m["follow_link"] = "/login?extra=signin_change"
-
c.LogAudit("success")
- w.Write([]byte(model.MapToJson(m)))
+ w.Write([]byte(model.MapToJson(map[string]string{"follow_link": link})))
}
func verifyEmail(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -1330,7 +1140,7 @@ func loginWithSaml(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- teamId, err := getTeamIdFromQuery(r.URL.Query())
+ teamId, err := app.GetTeamIdFromQuery(r.URL.Query())
if err != nil {
c.Err = err
return
diff --git a/api/user_test.go b/api/user_test.go
index cdbccc57e..ff2101c17 100644
--- a/api/user_test.go
+++ b/api/user_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/webhook.go b/api/webhook.go
index 12751943e..c17b5bc56 100644
--- a/api/webhook.go
+++ b/api/webhook.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/webhook_test.go b/api/webhook_test.go
index 8a170bd9a..5a0e44630 100644
--- a/api/webhook_test.go
+++ b/api/webhook_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/webrtc.go b/api/webrtc.go
index 7ba9d3762..58e35f2fa 100644
--- a/api/webrtc.go
+++ b/api/webrtc.go
@@ -1,21 +1,13 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
import (
- "crypto/hmac"
- "crypto/sha1"
- "crypto/tls"
- "encoding/base64"
"net/http"
- "strconv"
- "strings"
- "time"
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/app"
- "github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
@@ -26,68 +18,12 @@ func InitWebrtc() {
}
func webrtcToken(c *Context, w http.ResponseWriter, r *http.Request) {
- if token, err := getWebrtcToken(c.Session.Id); err != nil {
+ result, err := app.GetWebrtcInfoForSession(c.Session.Id)
+
+ if err != nil {
c.Err = err
return
- } else {
- result := make(map[string]string)
- result["token"] = token
- result["gateway_url"] = *utils.Cfg.WebrtcSettings.GatewayWebsocketUrl
-
- if len(*utils.Cfg.WebrtcSettings.StunURI) > 0 {
- result["stun_uri"] = *utils.Cfg.WebrtcSettings.StunURI
- }
-
- if len(*utils.Cfg.WebrtcSettings.TurnURI) > 0 {
- timestamp := strconv.FormatInt(utils.EndOfDay(time.Now().AddDate(0, 0, 1)).Unix(), 10)
- username := timestamp + ":" + *utils.Cfg.WebrtcSettings.TurnUsername
-
- result["turn_uri"] = *utils.Cfg.WebrtcSettings.TurnURI
- result["turn_password"] = generateTurnPassword(username, *utils.Cfg.WebrtcSettings.TurnSharedKey)
- result["turn_username"] = username
- }
- w.Write([]byte(model.MapToJson(result)))
}
-}
-
-func getWebrtcToken(sessionId string) (string, *model.AppError) {
- if !*utils.Cfg.WebrtcSettings.Enable {
- return "", model.NewLocAppError("WebRTC.getWebrtcToken", "api.webrtc.disabled.app_error", nil, "")
- }
-
- token := base64.StdEncoding.EncodeToString([]byte(sessionId))
-
- data := make(map[string]string)
- data["janus"] = "add_token"
- data["token"] = token
- data["transaction"] = model.NewId()
- data["admin_secret"] = *utils.Cfg.WebrtcSettings.GatewayAdminSecret
-
- rq, _ := http.NewRequest("POST", *utils.Cfg.WebrtcSettings.GatewayAdminUrl, strings.NewReader(model.MapToJson(data)))
- rq.Header.Set("Content-Type", "application/json")
-
- tr := &http.Transport{
- TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
- }
- httpClient := &http.Client{Transport: tr}
- if rp, err := httpClient.Do(rq); err != nil {
- return "", model.NewLocAppError("WebRTC.Token", "model.client.connecting.app_error", nil, err.Error())
- } else if rp.StatusCode >= 300 {
- defer app.CloseBody(rp)
- return "", model.AppErrorFromJson(rp.Body)
- } else {
- janusResponse := model.GatewayResponseFromJson(rp.Body)
- if janusResponse.Status != "success" {
- return "", model.NewLocAppError("getWebrtcToken", "api.webrtc.register_token.app_error", nil, "")
- }
- }
-
- return token, nil
-}
-func generateTurnPassword(username string, secret string) string {
- key := []byte(secret)
- h := hmac.New(sha1.New, key)
- h.Write([]byte(username))
- return base64.StdEncoding.EncodeToString(h.Sum(nil))
+ w.Write([]byte(result.ToJson()))
}
diff --git a/api/websocket.go b/api/websocket.go
index 192513bc0..6f53023db 100644
--- a/api/websocket.go
+++ b/api/websocket.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api/websocket_test.go b/api/websocket_test.go
index d3d8fc4b2..bda014f06 100644
--- a/api/websocket_test.go
+++ b/api/websocket_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api
diff --git a/api4/api.go b/api4/api.go
index dffed60e4..a91fb80b5 100644
--- a/api4/api.go
+++ b/api4/api.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
@@ -47,6 +47,7 @@ type Routes struct {
Posts *mux.Router // 'api/v4/posts'
Post *mux.Router // 'api/v4/posts/{post_id:[A-Za-z0-9]+}'
PostsForChannel *mux.Router // 'api/v4/channels/{channel_id:[A-Za-z0-9]+}/posts'
+ PostsForUser *mux.Router // 'api/v4/users/{user_id:[A-Za-z0-9]+}/posts'
Files *mux.Router // 'api/v4/files'
File *mux.Router // 'api/v4/files/{file_id:[A-Za-z0-9]+}'
@@ -126,6 +127,7 @@ func InitApi(full bool) {
BaseRoutes.Posts = BaseRoutes.ApiRoot.PathPrefix("/posts").Subrouter()
BaseRoutes.Post = BaseRoutes.Posts.PathPrefix("/{post_id:[A-Za-z0-9]+}").Subrouter()
BaseRoutes.PostsForChannel = BaseRoutes.Channel.PathPrefix("/posts").Subrouter()
+ BaseRoutes.PostsForUser = BaseRoutes.User.PathPrefix("/posts").Subrouter()
BaseRoutes.Files = BaseRoutes.ApiRoot.PathPrefix("/files").Subrouter()
BaseRoutes.File = BaseRoutes.Files.PathPrefix("/{file_id:[A-Za-z0-9]+}").Subrouter()
@@ -174,6 +176,9 @@ func InitApi(full bool) {
InitCommand()
InitStatus()
InitWebSocket()
+ InitEmoji()
+ InitReaction()
+ InitWebrtc()
app.Srv.Router.Handle("/api/v4/{anything:.*}", http.HandlerFunc(Handle404))
diff --git a/api4/apitestlib.go b/api4/apitestlib.go
index bd36f49cc..81a9ca311 100644
--- a/api4/apitestlib.go
+++ b/api4/apitestlib.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
@@ -564,6 +564,21 @@ func CheckInternalErrorStatus(t *testing.T, resp *model.Response) {
}
}
+func CheckPayLoadTooLargeStatus(t *testing.T, resp *model.Response) {
+ if resp.Error == nil {
+ debug.PrintStack()
+ t.Fatal("should have errored with status:" + strconv.Itoa(http.StatusRequestEntityTooLarge))
+ return
+ }
+
+ if resp.StatusCode != http.StatusRequestEntityTooLarge {
+ debug.PrintStack()
+ t.Log("actual: " + strconv.Itoa(resp.StatusCode))
+ t.Log("expected: " + strconv.Itoa(http.StatusRequestEntityTooLarge))
+ t.Fatal("wrong status code")
+ }
+}
+
func readTestFile(name string) ([]byte, error) {
path := utils.FindDir("tests")
file, err := os.Open(path + "/" + name)
diff --git a/api4/brand.go b/api4/brand.go
index f9a301acf..ac69f623b 100644
--- a/api4/brand.go
+++ b/api4/brand.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/brand_test.go b/api4/brand_test.go
index fd5e472a8..98a539574 100644
--- a/api4/brand_test.go
+++ b/api4/brand_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/channel.go b/api4/channel.go
index 78d4cc733..acef92415 100644
--- a/api4/channel.go
+++ b/api4/channel.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/channel_test.go b/api4/channel_test.go
index c5deda83e..50755fbe0 100644
--- a/api4/channel_test.go
+++ b/api4/channel_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
@@ -715,6 +715,30 @@ func TestDeleteChannel(t *testing.T) {
t.Fatal("should have failed")
}
+ // check system admin can delete a channel without any appropriate team or channel membership.
+ sdTeam := th.CreateTeamWithClient(Client)
+ sdPublicChannel := &model.Channel{
+ DisplayName: "dn_" + model.NewId(),
+ Name: GenerateTestChannelName(),
+ Type: model.CHANNEL_OPEN,
+ TeamId: sdTeam.Id,
+ }
+ sdPublicChannel, resp = Client.CreateChannel(sdPublicChannel)
+ CheckNoError(t, resp)
+ _, resp = th.SystemAdminClient.DeleteChannel(sdPublicChannel.Id)
+ CheckNoError(t, resp)
+
+ sdPrivateChannel := &model.Channel{
+ DisplayName: "dn_" + model.NewId(),
+ Name: GenerateTestChannelName(),
+ Type: model.CHANNEL_PRIVATE,
+ TeamId: sdTeam.Id,
+ }
+ sdPrivateChannel, resp = Client.CreateChannel(sdPrivateChannel)
+ CheckNoError(t, resp)
+ _, resp = th.SystemAdminClient.DeleteChannel(sdPrivateChannel.Id)
+ CheckNoError(t, resp)
+
th.LoginBasic()
publicChannel5 := th.CreatePublicChannel()
Client.Logout()
diff --git a/api4/cluster.go b/api4/cluster.go
index dbf198590..54ff15cf1 100644
--- a/api4/cluster.go
+++ b/api4/cluster.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/cluster_test.go b/api4/cluster_test.go
index 6d44ca209..573e309a4 100644
--- a/api4/cluster_test.go
+++ b/api4/cluster_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/command.go b/api4/command.go
index d6102bd70..f44363522 100644
--- a/api4/command.go
+++ b/api4/command.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
@@ -19,7 +19,11 @@ func InitCommand() {
BaseRoutes.Commands.Handle("", ApiSessionRequired(createCommand)).Methods("POST")
BaseRoutes.Commands.Handle("", ApiSessionRequired(listCommands)).Methods("GET")
+ BaseRoutes.Command.Handle("", ApiSessionRequired(updateCommand)).Methods("PUT")
+ BaseRoutes.Command.Handle("", ApiSessionRequired(deleteCommand)).Methods("DELETE")
+
BaseRoutes.Team.Handle("/commands/autocomplete", ApiSessionRequired(listAutocompleteCommands)).Methods("GET")
+ BaseRoutes.Command.Handle("/regen_token", ApiSessionRequired(regenCommandToken)).Methods("PUT")
}
func createCommand(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -49,6 +53,91 @@ func createCommand(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(rcmd.ToJson()))
}
+func updateCommand(c *Context, w http.ResponseWriter, r *http.Request) {
+ c.RequireCommandId()
+ if c.Err != nil {
+ return
+ }
+
+ cmd := model.CommandFromJson(r.Body)
+ if cmd == nil || cmd.Id != c.Params.CommandId {
+ c.SetInvalidParam("command")
+ return
+ }
+
+ c.LogAudit("attempt")
+
+ oldCmd, err := app.GetCommand(c.Params.CommandId)
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ if cmd.TeamId != oldCmd.TeamId {
+ c.Err = model.NewAppError("updateCommand", "api.command.team_mismatch.app_error", nil, "user_id="+c.Session.UserId, http.StatusBadRequest)
+ return
+ }
+
+ if !app.SessionHasPermissionToTeam(c.Session, oldCmd.TeamId, model.PERMISSION_MANAGE_SLASH_COMMANDS) {
+ c.LogAudit("fail - inappropriate permissions")
+ c.SetPermissionError(model.PERMISSION_MANAGE_SLASH_COMMANDS)
+ return
+ }
+
+ if c.Session.UserId != oldCmd.CreatorId && !app.SessionHasPermissionToTeam(c.Session, oldCmd.TeamId, model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS) {
+ c.LogAudit("fail - inappropriate permissions")
+ c.SetPermissionError(model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS)
+ return
+ }
+
+ rcmd, err := app.UpdateCommand(oldCmd, cmd)
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ c.LogAudit("success")
+
+ w.Write([]byte(rcmd.ToJson()))
+}
+
+func deleteCommand(c *Context, w http.ResponseWriter, r *http.Request) {
+ c.RequireCommandId()
+ if c.Err != nil {
+ return
+ }
+
+ c.LogAudit("attempt")
+
+ cmd, err := app.GetCommand(c.Params.CommandId)
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ if !app.SessionHasPermissionToTeam(c.Session, cmd.TeamId, model.PERMISSION_MANAGE_SLASH_COMMANDS) {
+ c.LogAudit("fail - inappropriate permissions")
+ c.SetPermissionError(model.PERMISSION_MANAGE_SLASH_COMMANDS)
+ return
+ }
+
+ if c.Session.UserId != cmd.CreatorId && !app.SessionHasPermissionToTeam(c.Session, cmd.TeamId, model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS) {
+ c.LogAudit("fail - inappropriate permissions")
+ c.SetPermissionError(model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS)
+ return
+ }
+
+ err = app.DeleteCommand(cmd.Id)
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ c.LogAudit("success")
+
+ ReturnStatusOK(w)
+}
+
func listCommands(c *Context, w http.ResponseWriter, r *http.Request) {
customOnly, failConv := strconv.ParseBool(r.URL.Query().Get("custom_only"))
if failConv != nil {
@@ -113,3 +202,40 @@ func listAutocompleteCommands(c *Context, w http.ResponseWriter, r *http.Request
w.Write([]byte(model.CommandListToJson(commands)))
}
+
+func regenCommandToken(c *Context, w http.ResponseWriter, r *http.Request) {
+ c.RequireCommandId()
+ if c.Err != nil {
+ return
+ }
+
+ c.LogAudit("attempt")
+ cmd, err := app.GetCommand(c.Params.CommandId)
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ if !app.SessionHasPermissionToTeam(c.Session, cmd.TeamId, model.PERMISSION_MANAGE_SLASH_COMMANDS) {
+ c.LogAudit("fail - inappropriate permissions")
+ c.SetPermissionError(model.PERMISSION_MANAGE_SLASH_COMMANDS)
+ return
+ }
+
+ if c.Session.UserId != cmd.CreatorId && !app.SessionHasPermissionToTeam(c.Session, cmd.TeamId, model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS) {
+ c.LogAudit("fail - inappropriate permissions")
+ c.SetPermissionError(model.PERMISSION_MANAGE_OTHERS_SLASH_COMMANDS)
+ return
+ }
+
+ rcmd, err := app.RegenCommandToken(cmd)
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ resp := make(map[string]string)
+ resp["token"] = rcmd.Token
+
+ w.Write([]byte(model.MapToJson(resp)))
+}
diff --git a/api4/command_test.go b/api4/command_test.go
index 75842886c..0aaca3c0f 100644
--- a/api4/command_test.go
+++ b/api4/command_test.go
@@ -1,12 +1,12 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
import (
"testing"
- // "time"
+ "github.com/mattermost/platform/app"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
@@ -60,6 +60,155 @@ func TestCreateCommand(t *testing.T) {
CheckErrorMessage(t, resp, "api.command.disabled.app_error")
}
+func TestUpdateCommand(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer TearDown()
+ Client := th.SystemAdminClient
+ user := th.SystemAdminUser
+ team := th.BasicTeam
+
+ enableCommands := *utils.Cfg.ServiceSettings.EnableCommands
+ defer func() {
+ utils.Cfg.ServiceSettings.EnableCommands = &enableCommands
+ }()
+ *utils.Cfg.ServiceSettings.EnableCommands = true
+
+ cmd1 := &model.Command{
+ CreatorId: user.Id,
+ TeamId: team.Id,
+ URL: "http://nowhere.com",
+ Method: model.COMMAND_METHOD_POST,
+ Trigger: "trigger1",
+ }
+
+ cmd1, _ = app.CreateCommand(cmd1)
+
+ cmd2 := &model.Command{
+ CreatorId: GenerateTestId(),
+ TeamId: team.Id,
+ URL: "http://nowhere.com/change",
+ Method: model.COMMAND_METHOD_GET,
+ Trigger: "trigger2",
+ Id: cmd1.Id,
+ Token: "tokenchange",
+ }
+
+ rcmd, resp := Client.UpdateCommand(cmd2)
+ CheckNoError(t, resp)
+
+ if rcmd.Trigger != cmd2.Trigger {
+ t.Fatal("Trigger should have updated")
+ }
+
+ if rcmd.Method != cmd2.Method {
+ t.Fatal("Method should have updated")
+ }
+
+ if rcmd.URL != cmd2.URL {
+ t.Fatal("URL should have updated")
+ }
+
+ if rcmd.CreatorId != cmd1.CreatorId {
+ t.Fatal("CreatorId should have not updated")
+ }
+
+ if rcmd.Token != cmd1.Token {
+ t.Fatal("Token should have not updated")
+ }
+
+ cmd2.Id = GenerateTestId()
+
+ rcmd, resp = Client.UpdateCommand(cmd2)
+ CheckNotFoundStatus(t, resp)
+
+ if rcmd != nil {
+ t.Fatal("should be empty")
+ }
+
+ cmd2.Id = "junk"
+
+ _, resp = Client.UpdateCommand(cmd2)
+ CheckBadRequestStatus(t, resp)
+
+ cmd2.Id = cmd1.Id
+ cmd2.TeamId = GenerateTestId()
+
+ _, resp = Client.UpdateCommand(cmd2)
+ CheckBadRequestStatus(t, resp)
+
+ cmd2.TeamId = team.Id
+
+ _, resp = th.Client.UpdateCommand(cmd2)
+ CheckForbiddenStatus(t, resp)
+
+ Client.Logout()
+ _, resp = Client.UpdateCommand(cmd2)
+ CheckUnauthorizedStatus(t, resp)
+}
+
+func TestDeleteCommand(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer TearDown()
+ Client := th.SystemAdminClient
+ user := th.SystemAdminUser
+ team := th.BasicTeam
+
+ enableCommands := *utils.Cfg.ServiceSettings.EnableCommands
+ defer func() {
+ utils.Cfg.ServiceSettings.EnableCommands = &enableCommands
+ }()
+ *utils.Cfg.ServiceSettings.EnableCommands = true
+
+ cmd1 := &model.Command{
+ CreatorId: user.Id,
+ TeamId: team.Id,
+ URL: "http://nowhere.com",
+ Method: model.COMMAND_METHOD_POST,
+ Trigger: "trigger1",
+ }
+
+ rcmd1, _ := app.CreateCommand(cmd1)
+
+ ok, resp := Client.DeleteCommand(rcmd1.Id)
+ CheckNoError(t, resp)
+
+ if !ok {
+ t.Fatal("should have returned true")
+ }
+
+ rcmd1, _ = app.GetCommand(rcmd1.Id)
+ if rcmd1 != nil {
+ t.Fatal("should be nil")
+ }
+
+ ok, resp = Client.DeleteCommand("junk")
+ CheckBadRequestStatus(t, resp)
+
+ if ok {
+ t.Fatal("should have returned false")
+ }
+
+ _, resp = Client.DeleteCommand(GenerateTestId())
+ CheckNotFoundStatus(t, resp)
+
+ cmd2 := &model.Command{
+ CreatorId: user.Id,
+ TeamId: team.Id,
+ URL: "http://nowhere.com",
+ Method: model.COMMAND_METHOD_POST,
+ Trigger: "trigger2",
+ }
+
+ rcmd2, _ := app.CreateCommand(cmd2)
+
+ _, resp = th.Client.DeleteCommand(rcmd2.Id)
+ CheckForbiddenStatus(t, resp)
+
+ Client.Logout()
+ _, resp = Client.DeleteCommand(rcmd2.Id)
+ CheckUnauthorizedStatus(t, resp)
+}
+
func TestListCommands(t *testing.T) {
th := Setup().InitBasic().InitSystemAdmin()
defer TearDown()
@@ -196,3 +345,39 @@ func TestListAutocompleteCommands(t *testing.T) {
}
})
}
+
+func TestRegenToken(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer TearDown()
+ Client := th.Client
+
+ enableCommands := *utils.Cfg.ServiceSettings.EnableCommands
+ defer func() {
+ utils.Cfg.ServiceSettings.EnableCommands = &enableCommands
+ }()
+ *utils.Cfg.ServiceSettings.EnableCommands = true
+
+ newCmd := &model.Command{
+ CreatorId: th.BasicUser.Id,
+ TeamId: th.BasicTeam.Id,
+ URL: "http://nowhere.com",
+ Method: model.COMMAND_METHOD_POST,
+ Trigger: "trigger"}
+
+ createdCmd, resp := th.SystemAdminClient.CreateCommand(newCmd)
+ CheckNoError(t, resp)
+ CheckCreatedStatus(t, resp)
+
+ token, resp := th.SystemAdminClient.RegenCommandToken(createdCmd.Id)
+ CheckNoError(t, resp)
+ if token == createdCmd.Token {
+ t.Fatal("should update the token")
+ }
+
+ token, resp = Client.RegenCommandToken(createdCmd.Id)
+ CheckForbiddenStatus(t, resp)
+ if token != "" {
+ t.Fatal("should not return the token")
+ }
+
+}
diff --git a/api4/compliance.go b/api4/compliance.go
index 37196c853..cabac6e21 100644
--- a/api4/compliance.go
+++ b/api4/compliance.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/context.go b/api4/context.go
index 484a6432f..847a8d55f 100644
--- a/api4/context.go
+++ b/api4/context.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
@@ -242,8 +242,7 @@ func (c *Context) IsSystemAdmin() bool {
func (c *Context) SessionRequired() {
if len(c.Session.UserId) == 0 {
- c.Err = model.NewLocAppError("", "api.context.session_expired.app_error", nil, "UserRequired")
- c.Err.StatusCode = http.StatusUnauthorized
+ c.Err = model.NewAppError("", "api.context.session_expired.app_error", nil, "UserRequired", http.StatusUnauthorized)
return
}
}
@@ -406,6 +405,17 @@ func (c *Context) RequireReportId() *Context {
return c
}
+func (c *Context) RequireEmojiId() *Context {
+ if c.Err != nil {
+ return c
+ }
+
+ if len(c.Params.EmojiId) != 26 {
+ c.SetInvalidUrlParam("emoji_id")
+ }
+ return c
+}
+
func (c *Context) RequireTeamName() *Context {
if c.Err != nil {
return c
@@ -477,3 +487,14 @@ func (c *Context) RequireHookId() *Context {
return c
}
+
+func (c *Context) RequireCommandId() *Context {
+ if c.Err != nil {
+ return c
+ }
+
+ if len(c.Params.CommandId) != 26 {
+ c.SetInvalidUrlParam("command_id")
+ }
+ return c
+}
diff --git a/api4/emoji.go b/api4/emoji.go
new file mode 100644
index 000000000..ff4919860
--- /dev/null
+++ b/api4/emoji.go
@@ -0,0 +1,131 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package api4
+
+import (
+ "net/http"
+ "strings"
+
+ l4g "github.com/alecthomas/log4go"
+
+ "github.com/mattermost/platform/app"
+ "github.com/mattermost/platform/einterfaces"
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
+)
+
+func InitEmoji() {
+ l4g.Debug(utils.T("api.emoji.init.debug"))
+
+ BaseRoutes.Emojis.Handle("", ApiSessionRequired(createEmoji)).Methods("POST")
+ BaseRoutes.Emojis.Handle("", ApiSessionRequired(getEmojiList)).Methods("GET")
+ BaseRoutes.Emoji.Handle("", ApiSessionRequired(deleteEmoji)).Methods("DELETE")
+ BaseRoutes.Emoji.Handle("", ApiSessionRequired(getEmoji)).Methods("GET")
+}
+
+func createEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
+ if !*utils.Cfg.ServiceSettings.EnableCustomEmoji {
+ c.Err = model.NewAppError("createEmoji", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented)
+ return
+ }
+
+ if emojiInterface := einterfaces.GetEmojiInterface(); emojiInterface != nil &&
+ !emojiInterface.CanUserCreateEmoji(c.Session.Roles, c.Session.TeamMembers) {
+ c.Err = model.NewAppError("getEmoji", "api.emoji.disabled.app_error", nil, "user_id="+c.Session.UserId, http.StatusUnauthorized)
+ return
+ }
+
+ if len(utils.Cfg.FileSettings.DriverName) == 0 {
+ c.Err = model.NewAppError("createEmoji", "api.emoji.storage.app_error", nil, "", http.StatusNotImplemented)
+ return
+ }
+
+ if r.ContentLength > app.MaxEmojiFileSize {
+ c.Err = model.NewAppError("createEmoji", "api.emoji.create.too_large.app_error", nil, "", http.StatusRequestEntityTooLarge)
+ return
+ }
+
+ if err := r.ParseMultipartForm(app.MaxEmojiFileSize); err != nil {
+ c.Err = model.NewAppError("createEmoji", "api.emoji.create.parse.app_error", nil, err.Error(), http.StatusBadRequest)
+ return
+ }
+
+ m := r.MultipartForm
+ props := m.Value
+
+ emoji := model.EmojiFromJson(strings.NewReader(props["emoji"][0]))
+ if emoji == nil {
+ c.SetInvalidParam("createEmoji")
+ return
+ }
+
+ newEmoji, err := app.CreateEmoji(c.Session.UserId, emoji, m)
+ if err != nil {
+ c.Err = err
+ return
+ } else {
+ w.Write([]byte(newEmoji.ToJson()))
+ }
+}
+
+func getEmojiList(c *Context, w http.ResponseWriter, r *http.Request) {
+ if !*utils.Cfg.ServiceSettings.EnableCustomEmoji {
+ c.Err = model.NewAppError("getEmoji", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented)
+ return
+ }
+
+ listEmoji, err := app.GetEmojiList()
+ if err != nil {
+ c.Err = err
+ return
+ } else {
+ w.Write([]byte(model.EmojiListToJson(listEmoji)))
+ }
+}
+
+func deleteEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
+ c.RequireEmojiId()
+ if c.Err != nil {
+ return
+ }
+
+ emoji, err := app.GetEmoji(c.Params.EmojiId)
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ if c.Session.UserId != emoji.CreatorId && !app.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
+ c.Err = model.NewAppError("deleteImage", "api.emoji.delete.permissions.app_error", nil, "user_id="+c.Session.UserId, http.StatusUnauthorized)
+ return
+ }
+
+ err = app.DeleteEmoji(emoji)
+ if err != nil {
+ c.Err = err
+ return
+ } else {
+ ReturnStatusOK(w)
+ }
+}
+
+func getEmoji(c *Context, w http.ResponseWriter, r *http.Request) {
+ c.RequireEmojiId()
+ if c.Err != nil {
+ return
+ }
+
+ if !*utils.Cfg.ServiceSettings.EnableCustomEmoji {
+ c.Err = model.NewAppError("getEmoji", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented)
+ return
+ }
+
+ emoji, err := app.GetEmoji(c.Params.EmojiId)
+ if err != nil {
+ c.Err = err
+ return
+ } else {
+ w.Write([]byte(emoji.ToJson()))
+ }
+}
diff --git a/api4/emoji_test.go b/api4/emoji_test.go
new file mode 100644
index 000000000..23188a3d2
--- /dev/null
+++ b/api4/emoji_test.go
@@ -0,0 +1,300 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package api4
+
+import (
+ "testing"
+
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
+)
+
+func TestCreateEmoji(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer TearDown()
+ Client := th.Client
+
+ EnableCustomEmoji := *utils.Cfg.ServiceSettings.EnableCustomEmoji
+ defer func() {
+ *utils.Cfg.ServiceSettings.EnableCustomEmoji = EnableCustomEmoji
+ }()
+ *utils.Cfg.ServiceSettings.EnableCustomEmoji = false
+
+ emoji := &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
+ // try to create an emoji when they're disabled
+ _, resp := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckNotImplementedStatus(t, resp)
+
+ *utils.Cfg.ServiceSettings.EnableCustomEmoji = true
+ // try to create a valid gif emoji when they're enabled
+ newEmoji, resp := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckNoError(t, resp)
+ if newEmoji.Name != emoji.Name {
+ t.Fatal("create with wrong name")
+ }
+
+ // try to create an emoji with a duplicate name
+ emoji2 := &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: newEmoji.Name,
+ }
+ _, resp = Client.CreateEmoji(emoji2, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckBadRequestStatus(t, resp)
+ CheckErrorMessage(t, resp, "api.emoji.create.duplicate.app_error")
+
+ // try to create a valid animated gif emoji
+ emoji = &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
+ newEmoji, resp = Client.CreateEmoji(emoji, utils.CreateTestAnimatedGif(t, 10, 10, 10), "image.gif")
+ CheckNoError(t, resp)
+ if newEmoji.Name != emoji.Name {
+ t.Fatal("create with wrong name")
+ }
+
+ // try to create a valid jpeg emoji
+ emoji = &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
+ newEmoji, resp = Client.CreateEmoji(emoji, utils.CreateTestJpeg(t, 10, 10), "image.gif")
+ CheckNoError(t, resp)
+ if newEmoji.Name != emoji.Name {
+ t.Fatal("create with wrong name")
+ }
+
+ // try to create a valid png emoji
+ emoji = &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
+ newEmoji, resp = Client.CreateEmoji(emoji, utils.CreateTestPng(t, 10, 10), "image.gif")
+ CheckNoError(t, resp)
+ if newEmoji.Name != emoji.Name {
+ t.Fatal("create with wrong name")
+ }
+
+ // try to create an emoji that's too wide
+ emoji = &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
+ newEmoji, resp = Client.CreateEmoji(emoji, utils.CreateTestGif(t, 1000, 10), "image.gif")
+ CheckNoError(t, resp)
+ if newEmoji.Name != emoji.Name {
+ t.Fatal("create with wrong name")
+ }
+
+ // try to create an emoji that's too tall
+ emoji = &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
+ newEmoji, resp = Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 1000), "image.gif")
+ CheckNoError(t, resp)
+ if newEmoji.Name != emoji.Name {
+ t.Fatal("create with wrong name")
+ }
+
+ // try to create an emoji that's too large
+ emoji = &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
+ _, resp = Client.CreateEmoji(emoji, utils.CreateTestAnimatedGif(t, 100, 100, 10000), "image.gif")
+ if resp.Error == nil {
+ t.Fatal("should fail - emoji is too big")
+ }
+
+ // try to create an emoji with data that isn't an image
+ emoji = &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
+ _, resp = Client.CreateEmoji(emoji, make([]byte, 100, 100), "image.gif")
+ CheckBadRequestStatus(t, resp)
+ CheckErrorMessage(t, resp, "api.emoji.upload.image.app_error")
+
+ // try to create an emoji as another user
+ emoji = &model.Emoji{
+ CreatorId: th.BasicUser2.Id,
+ Name: model.NewId(),
+ }
+
+ _, resp = Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckForbiddenStatus(t, resp)
+}
+
+func TestGetEmojiList(t *testing.T) {
+ th := Setup().InitBasic()
+ defer TearDown()
+ Client := th.Client
+
+ EnableCustomEmoji := *utils.Cfg.ServiceSettings.EnableCustomEmoji
+ defer func() {
+ *utils.Cfg.ServiceSettings.EnableCustomEmoji = EnableCustomEmoji
+ }()
+ *utils.Cfg.ServiceSettings.EnableCustomEmoji = true
+
+ emojis := []*model.Emoji{
+ {
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ },
+ {
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ },
+ {
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ },
+ }
+
+ for idx, emoji := range emojis {
+ emoji, resp := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckNoError(t, resp)
+ emojis[idx] = emoji
+ }
+
+ listEmoji, resp := Client.GetEmojiList()
+ CheckNoError(t, resp)
+ for _, emoji := range emojis {
+ found := false
+ for _, savedEmoji := range listEmoji {
+ if emoji.Id == savedEmoji.Id {
+ found = true
+ break
+ }
+ }
+ if !found {
+ t.Fatalf("failed to get emoji with id %v", emoji.Id)
+ }
+ }
+
+ _, resp = Client.DeleteEmoji(emojis[0].Id)
+ CheckNoError(t, resp)
+ listEmoji, resp = Client.GetEmojiList()
+ CheckNoError(t, resp)
+ found := false
+ for _, savedEmoji := range listEmoji {
+ if savedEmoji.Id == emojis[0].Id {
+ found = true
+ break
+ }
+ if found {
+ t.Fatalf("should not get a deleted emoji %v", emojis[0].Id)
+ }
+ }
+
+}
+
+func TestDeleteEmoji(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer TearDown()
+ Client := th.Client
+
+ EnableCustomEmoji := *utils.Cfg.ServiceSettings.EnableCustomEmoji
+ defer func() {
+ *utils.Cfg.ServiceSettings.EnableCustomEmoji = EnableCustomEmoji
+ }()
+ *utils.Cfg.ServiceSettings.EnableCustomEmoji = true
+
+ emoji := &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
+ newEmoji, resp := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckNoError(t, resp)
+
+ ok, resp := Client.DeleteEmoji(newEmoji.Id)
+ CheckNoError(t, resp)
+ if ok != true {
+ t.Fatal("should return true")
+ } else {
+ _, err := Client.GetEmoji(newEmoji.Id)
+ if err == nil {
+ t.Fatal("should not return the emoji it was deleted")
+ }
+ }
+
+ //Admin can delete other users emoji
+ newEmoji, resp = Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckNoError(t, resp)
+
+ ok, resp = th.SystemAdminClient.DeleteEmoji(newEmoji.Id)
+ CheckNoError(t, resp)
+ if ok != true {
+ t.Fatal("should return true")
+ } else {
+ _, err := th.SystemAdminClient.GetEmoji(newEmoji.Id)
+ if err == nil {
+ t.Fatal("should not return the emoji it was deleted")
+ }
+ }
+
+ // Try to delete just deleted emoji
+ _, resp = Client.DeleteEmoji(newEmoji.Id)
+ CheckInternalErrorStatus(t, resp)
+
+ //Try to delete non-existing emoji
+ _, resp = Client.DeleteEmoji(model.NewId())
+ CheckInternalErrorStatus(t, resp)
+
+ //Try to delete without Id
+ _, resp = Client.DeleteEmoji("")
+ CheckNotFoundStatus(t, resp)
+
+ //Try to delete other user's custom emoji
+ newEmoji, resp = Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckNoError(t, resp)
+
+ Client.Logout()
+ th.LoginBasic2()
+ ok, resp = Client.DeleteEmoji(newEmoji.Id)
+ CheckUnauthorizedStatus(t, resp)
+}
+
+func TestGetEmoji(t *testing.T) {
+ th := Setup().InitBasic()
+ defer TearDown()
+ Client := th.Client
+
+ EnableCustomEmoji := *utils.Cfg.ServiceSettings.EnableCustomEmoji
+ defer func() {
+ *utils.Cfg.ServiceSettings.EnableCustomEmoji = EnableCustomEmoji
+ }()
+ *utils.Cfg.ServiceSettings.EnableCustomEmoji = true
+
+ emoji := &model.Emoji{
+ CreatorId: th.BasicUser.Id,
+ Name: model.NewId(),
+ }
+
+ newEmoji, resp := Client.CreateEmoji(emoji, utils.CreateTestGif(t, 10, 10), "image.gif")
+ CheckNoError(t, resp)
+
+ emoji, resp = Client.GetEmoji(newEmoji.Id)
+ CheckNoError(t, resp)
+ if emoji.Id != newEmoji.Id {
+ t.Fatal("wrong emoji was returned")
+ }
+
+ _, resp = Client.GetEmoji(model.NewId())
+ CheckInternalErrorStatus(t, resp)
+
+}
diff --git a/api4/file.go b/api4/file.go
index e4bdbcc3c..de1ce454d 100644
--- a/api4/file.go
+++ b/api4/file.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/file_test.go b/api4/file_test.go
index 5e0824d45..9124e893b 100644
--- a/api4/file_test.go
+++ b/api4/file_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/ldap.go b/api4/ldap.go
index e138fdc97..eac5778b6 100644
--- a/api4/ldap.go
+++ b/api4/ldap.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/ldap_test.go b/api4/ldap_test.go
index d8eaedc50..6d79a92ad 100644
--- a/api4/ldap_test.go
+++ b/api4/ldap_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/params.go b/api4/params.go
index 8bb072742..fa5d96d88 100644
--- a/api4/params.go
+++ b/api4/params.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/post.go b/api4/post.go
index 5cbfeae92..f8e4cc54b 100644
--- a/api4/post.go
+++ b/api4/post.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
@@ -22,6 +22,7 @@ func InitPost() {
BaseRoutes.Post.Handle("/thread", ApiSessionRequired(getPostThread)).Methods("GET")
BaseRoutes.Post.Handle("/files/info", ApiSessionRequired(getFileInfosForPost)).Methods("GET")
BaseRoutes.PostsForChannel.Handle("", ApiSessionRequired(getPostsForChannel)).Methods("GET")
+ BaseRoutes.PostsForUser.Handle("/flagged", ApiSessionRequired(getFlaggedPostsForUser)).Methods("GET")
BaseRoutes.Team.Handle("/posts/search", ApiSessionRequired(searchPosts)).Methods("POST")
BaseRoutes.Post.Handle("", ApiSessionRequired(updatePost)).Methods("PUT")
@@ -127,6 +128,39 @@ func getPostsForChannel(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(list.ToJson()))
}
+func getFlaggedPostsForUser(c *Context, w http.ResponseWriter, r *http.Request) {
+ c.RequireUserId()
+ if c.Err != nil {
+ return
+ }
+
+ if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
+ c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
+ return
+ }
+
+ channelId := r.URL.Query().Get("in_channel")
+ teamId := r.URL.Query().Get("in_team")
+
+ var posts *model.PostList
+ var err *model.AppError
+
+ if len(channelId) > 0 {
+ posts, err = app.GetFlaggedPostsForChannel(c.Params.UserId, channelId, c.Params.Page, c.Params.PerPage)
+ } else if len(teamId) > 0 {
+ posts, err = app.GetFlaggedPostsForTeam(c.Params.UserId, teamId, c.Params.Page, c.Params.PerPage)
+ } else {
+ posts, err = app.GetFlaggedPosts(c.Params.UserId, c.Params.Page, c.Params.PerPage)
+ }
+
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ w.Write([]byte(posts.ToJson()))
+}
+
func getPost(c *Context, w http.ResponseWriter, r *http.Request) {
c.RequirePostId()
if c.Err != nil {
diff --git a/api4/post_test.go b/api4/post_test.go
index e5c72ae9e..c6e9dcb59 100644
--- a/api4/post_test.go
+++ b/api4/post_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
@@ -459,6 +459,187 @@ func TestGetPostsForChannel(t *testing.T) {
CheckNoError(t, resp)
}
+func TestGetFlaggedPostsForUser(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer TearDown()
+ Client := th.Client
+ user := th.BasicUser
+ team1 := th.BasicTeam
+ channel1 := th.BasicChannel
+ post1 := th.CreatePost()
+ channel2 := th.CreatePublicChannel()
+ post2 := th.CreatePostWithClient(Client, channel2)
+
+ preference := model.Preference{
+ UserId: user.Id,
+ Category: model.PREFERENCE_CATEGORY_FLAGGED_POST,
+ Name: post1.Id,
+ Value: "true",
+ }
+ Client.UpdatePreferences(user.Id, &model.Preferences{preference})
+ preference.Name = post2.Id
+ Client.UpdatePreferences(user.Id, &model.Preferences{preference})
+
+ opl := model.NewPostList()
+ opl.AddPost(post1)
+ opl.AddOrder(post1.Id)
+
+ rpl, resp := Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 10)
+ CheckNoError(t, resp)
+
+ if len(rpl.Posts) != 1 {
+ t.Fatal("should have returned 1 post")
+ }
+
+ if !reflect.DeepEqual(rpl.Posts, opl.Posts) {
+ t.Fatal("posts should have matched")
+ }
+
+ rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 1)
+ CheckNoError(t, resp)
+
+ if len(rpl.Posts) != 1 {
+ t.Fatal("should have returned 1 post")
+ }
+
+ rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 1, 1)
+ CheckNoError(t, resp)
+
+ if len(rpl.Posts) != 0 {
+ t.Fatal("should be empty")
+ }
+
+ rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, GenerateTestId(), 0, 10)
+ CheckNoError(t, resp)
+
+ if len(rpl.Posts) != 0 {
+ t.Fatal("should be empty")
+ }
+
+ rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, "junk", 0, 10)
+ CheckBadRequestStatus(t, resp)
+
+ if rpl != nil {
+ t.Fatal("should be nil")
+ }
+
+ opl.AddPost(post2)
+ opl.AddOrder(post2.Id)
+
+ rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 10)
+ CheckNoError(t, resp)
+
+ if len(rpl.Posts) != 2 {
+ t.Fatal("should have returned 2 posts")
+ }
+
+ if !reflect.DeepEqual(rpl.Posts, opl.Posts) {
+ t.Fatal("posts should have matched")
+ }
+
+ rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 1)
+ CheckNoError(t, resp)
+
+ if len(rpl.Posts) != 1 {
+ t.Fatal("should have returned 1 post")
+ }
+
+ rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 1, 1)
+ CheckNoError(t, resp)
+
+ if len(rpl.Posts) != 1 {
+ t.Fatal("should have returned 1 post")
+ }
+
+ rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 1000, 10)
+ CheckNoError(t, resp)
+
+ if len(rpl.Posts) != 0 {
+ t.Fatal("should be empty")
+ }
+
+ rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, GenerateTestId(), 0, 10)
+ CheckNoError(t, resp)
+
+ if len(rpl.Posts) != 0 {
+ t.Fatal("should be empty")
+ }
+
+ rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, "junk", 0, 10)
+ CheckBadRequestStatus(t, resp)
+
+ if rpl != nil {
+ t.Fatal("should be nil")
+ }
+
+ channel3 := th.CreatePrivateChannel()
+ post4 := th.CreatePostWithClient(Client, channel3)
+
+ preference.Name = post4.Id
+ Client.UpdatePreferences(user.Id, &model.Preferences{preference})
+
+ opl.AddPost(post4)
+ opl.AddOrder(post4.Id)
+
+ rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 10)
+ CheckNoError(t, resp)
+
+ if len(rpl.Posts) != 3 {
+ t.Fatal("should have returned 3 posts")
+ }
+
+ if !reflect.DeepEqual(rpl.Posts, opl.Posts) {
+ t.Fatal("posts should have matched")
+ }
+
+ rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 2)
+ CheckNoError(t, resp)
+
+ if len(rpl.Posts) != 2 {
+ t.Fatal("should have returned 2 posts")
+ }
+
+ rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 2, 2)
+ CheckNoError(t, resp)
+
+ if len(rpl.Posts) != 1 {
+ t.Fatal("should have returned 1 post")
+ }
+
+ rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 1000, 10)
+ CheckNoError(t, resp)
+
+ if len(rpl.Posts) != 0 {
+ t.Fatal("should be empty")
+ }
+
+ _, resp = Client.GetFlaggedPostsForUser("junk", 0, 10)
+ CheckBadRequestStatus(t, resp)
+
+ _, resp = Client.GetFlaggedPostsForUser(GenerateTestId(), 0, 10)
+ CheckForbiddenStatus(t, resp)
+
+ Client.Logout()
+
+ rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 10)
+ CheckUnauthorizedStatus(t, resp)
+
+ rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 10)
+ CheckUnauthorizedStatus(t, resp)
+
+ rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 10)
+ CheckUnauthorizedStatus(t, resp)
+
+ rpl, resp = th.SystemAdminClient.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 10)
+ CheckNoError(t, resp)
+
+ rpl, resp = th.SystemAdminClient.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 10)
+ CheckNoError(t, resp)
+
+ rpl, resp = th.SystemAdminClient.GetFlaggedPostsForUser(user.Id, 0, 10)
+ CheckNoError(t, resp)
+}
+
func TestGetPostsAfterAndBefore(t *testing.T) {
th := Setup().InitBasic()
defer TearDown()
diff --git a/api4/preference.go b/api4/preference.go
index 9ba6b85d2..f9a5bfba6 100644
--- a/api4/preference.go
+++ b/api4/preference.go
@@ -1,4 +1,4 @@
-// // Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// // See License.txt for license information.
package api4
diff --git a/api4/preference_test.go b/api4/preference_test.go
index 02df99b9b..6efc96ff3 100644
--- a/api4/preference_test.go
+++ b/api4/preference_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/reaction.go b/api4/reaction.go
new file mode 100644
index 000000000..4deae4370
--- /dev/null
+++ b/api4/reaction.go
@@ -0,0 +1,39 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package api4
+
+import (
+ "net/http"
+
+ l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/app"
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
+)
+
+func InitReaction() {
+ l4g.Debug(utils.T("api.reaction.init.debug"))
+
+ BaseRoutes.Post.Handle("/reactions", ApiSessionRequired(getReactions)).Methods("GET")
+}
+
+func getReactions(c *Context, w http.ResponseWriter, r *http.Request) {
+ c.RequirePostId()
+ if c.Err != nil {
+ return
+ }
+
+ if !app.SessionHasPermissionToChannelByPost(c.Session, c.Params.PostId, model.PERMISSION_READ_CHANNEL) {
+ c.SetPermissionError(model.PERMISSION_READ_CHANNEL)
+ return
+ }
+
+ if reactions, err := app.GetReactionsForPost(c.Params.PostId); err != nil {
+ c.Err = err
+ return
+ } else {
+ w.Write([]byte(model.ReactionsToJson(reactions)))
+ return
+ }
+}
diff --git a/api4/reaction_test.go b/api4/reaction_test.go
new file mode 100644
index 000000000..9e0847c2d
--- /dev/null
+++ b/api4/reaction_test.go
@@ -0,0 +1,89 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package api4
+
+import (
+ "testing"
+
+ "reflect"
+
+ "github.com/mattermost/platform/app"
+ "github.com/mattermost/platform/model"
+)
+
+func TestGetReactions(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer TearDown()
+ Client := th.Client
+ userId := th.BasicUser.Id
+ user2Id := th.BasicUser2.Id
+ postId := th.BasicPost.Id
+
+ userReactions := []*model.Reaction{
+ {
+ UserId: userId,
+ PostId: postId,
+ EmojiName: "smile",
+ },
+ {
+ UserId: userId,
+ PostId: postId,
+ EmojiName: "happy",
+ },
+ {
+ UserId: userId,
+ PostId: postId,
+ EmojiName: "sad",
+ },
+ {
+ UserId: user2Id,
+ PostId: postId,
+ EmojiName: "smile",
+ },
+ {
+ UserId: user2Id,
+ PostId: postId,
+ EmojiName: "sad",
+ },
+ }
+
+ var reactions []*model.Reaction
+
+ for _, userReaction := range userReactions {
+ if result := <-app.Srv.Store.Reaction().Save(userReaction); result.Err != nil {
+ t.Fatal(result.Err)
+ } else {
+ reactions = append(reactions, result.Data.(*model.Reaction))
+ }
+ }
+
+ rr, resp := Client.GetReactions(postId)
+ CheckNoError(t, resp)
+
+ if len(rr) != 5 {
+ t.Fatal("reactions should returned correct length")
+ }
+
+ if !reflect.DeepEqual(rr, reactions) {
+ t.Fatal("reactions should have matched")
+ }
+
+ rr, resp = Client.GetReactions("junk")
+ CheckBadRequestStatus(t, resp)
+
+ if len(rr) != 0 {
+ t.Fatal("reactions should return empty")
+ }
+
+ _, resp = Client.GetReactions(GenerateTestId())
+ CheckForbiddenStatus(t, resp)
+
+ Client.Logout()
+
+ _, resp = Client.GetReactions(postId)
+ CheckUnauthorizedStatus(t, resp)
+
+ _, resp = th.SystemAdminClient.GetReactions(postId)
+ CheckNoError(t, resp)
+}
diff --git a/api4/saml.go b/api4/saml.go
index e2c35f30d..b8167b505 100644
--- a/api4/saml.go
+++ b/api4/saml.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/saml_test.go b/api4/saml_test.go
index 7e4722a3b..0e16612d7 100644
--- a/api4/saml_test.go
+++ b/api4/saml_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/status.go b/api4/status.go
index 46d4f963b..3a2c5c762 100644
--- a/api4/status.go
+++ b/api4/status.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/system.go b/api4/system.go
index 098f7e4b7..dfc702c8c 100644
--- a/api4/system.go
+++ b/api4/system.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/team.go b/api4/team.go
index 22ab15bfd..b8ba47054 100644
--- a/api4/team.go
+++ b/api4/team.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/team_test.go b/api4/team_test.go
index b58a4dc72..7fd240480 100644
--- a/api4/team_test.go
+++ b/api4/team_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/user.go b/api4/user.go
index b30d066ab..70182c1ab 100644
--- a/api4/user.go
+++ b/api4/user.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
@@ -32,6 +32,7 @@ func InitUser() {
BaseRoutes.User.Handle("/patch", ApiSessionRequired(patchUser)).Methods("PUT")
BaseRoutes.User.Handle("", ApiSessionRequired(deleteUser)).Methods("DELETE")
BaseRoutes.User.Handle("/roles", ApiSessionRequired(updateUserRoles)).Methods("PUT")
+ BaseRoutes.User.Handle("/active", ApiSessionRequired(updateUserActive)).Methods("PUT")
BaseRoutes.User.Handle("/password", ApiSessionRequired(updatePassword)).Methods("PUT")
BaseRoutes.Users.Handle("/password/reset", ApiHandler(resetPassword)).Methods("POST")
BaseRoutes.Users.Handle("/password/reset/send", ApiHandler(sendPasswordReset)).Methods("POST")
@@ -43,6 +44,7 @@ func InitUser() {
BaseRoutes.User.Handle("/mfa/generate", ApiSessionRequired(generateMfaSecret)).Methods("POST")
BaseRoutes.Users.Handle("/login", ApiHandler(login)).Methods("POST")
+ BaseRoutes.Users.Handle("/login/switch", ApiHandler(switchAccountType)).Methods("POST")
BaseRoutes.Users.Handle("/logout", ApiHandler(logout)).Methods("POST")
BaseRoutes.UserByUsername.Handle("", ApiSessionRequired(getUserByUsername)).Methods("GET")
@@ -586,6 +588,37 @@ func updateUserRoles(c *Context, w http.ResponseWriter, r *http.Request) {
ReturnStatusOK(w)
}
+func updateUserActive(c *Context, w http.ResponseWriter, r *http.Request) {
+ c.RequireUserId()
+ if c.Err != nil {
+ return
+ }
+
+ props := model.StringInterfaceFromJson(r.Body)
+
+ active, ok := props["active"].(bool)
+ if !ok {
+ c.SetInvalidParam("active")
+ return
+ }
+
+ // true when you're trying to de-activate yourself
+ isSelfDeactive := !active && c.Params.UserId == c.Session.UserId
+
+ if !isSelfDeactive && !app.SessionHasPermissionTo(c.Session, model.PERMISSION_MANAGE_SYSTEM) {
+ c.Err = model.NewLocAppError("updateUserActive", "api.user.update_active.permissions.app_error", nil, "userId="+c.Params.UserId)
+ c.Err.StatusCode = http.StatusForbidden
+ return
+ }
+
+ if ruser, err := app.UpdateActiveNoLdap(c.Params.UserId, active); err != nil {
+ c.Err = err
+ } else {
+ c.LogAuditWithUserId(ruser.Id, fmt.Sprintf("active=%v", active))
+ ReturnStatusOK(w)
+ }
+}
+
func checkUserMfa(c *Context, w http.ResponseWriter, r *http.Request) {
props := model.MapFromJson(r.Body)
@@ -981,3 +1014,40 @@ func sendVerificationEmail(c *Context, w http.ResponseWriter, r *http.Request) {
ReturnStatusOK(w)
}
+
+func switchAccountType(c *Context, w http.ResponseWriter, r *http.Request) {
+ switchRequest := model.SwitchRequestFromJson(r.Body)
+ if switchRequest == nil {
+ c.SetInvalidParam("switch_request")
+ return
+ }
+
+ link := ""
+ var err *model.AppError
+
+ if switchRequest.EmailToOAuth() {
+ link, err = app.SwitchEmailToOAuth(switchRequest.Email, switchRequest.Password, switchRequest.MfaCode, switchRequest.NewService)
+ } else if switchRequest.OAuthToEmail() {
+ c.SessionRequired()
+ if c.Err != nil {
+ return
+ }
+
+ link, err = app.SwitchOAuthToEmail(switchRequest.Email, switchRequest.NewPassword, c.Session.UserId)
+ } else if switchRequest.EmailToLdap() {
+ link, err = app.SwitchEmailToLdap(switchRequest.Email, switchRequest.Password, switchRequest.MfaCode, switchRequest.LdapId, switchRequest.NewPassword)
+ } else if switchRequest.LdapToEmail() {
+ link, err = app.SwitchLdapToEmail(switchRequest.Password, switchRequest.MfaCode, switchRequest.Email, switchRequest.NewPassword)
+ } else {
+ c.SetInvalidParam("switch_request")
+ return
+ }
+
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ c.LogAudit("success")
+ w.Write([]byte(model.MapToJson(map[string]string{"follow_link": link})))
+}
diff --git a/api4/user_test.go b/api4/user_test.go
index b3e4edc3d..95271984c 100644
--- a/api4/user_test.go
+++ b/api4/user_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
@@ -850,6 +850,49 @@ func TestUpdateUserRoles(t *testing.T) {
CheckBadRequestStatus(t, resp)
}
+func TestUpdateUserActive(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ Client := th.Client
+ SystemAdminClient := th.SystemAdminClient
+ user := th.BasicUser
+
+ pass, resp := Client.UpdateUserActive(user.Id, false)
+ CheckNoError(t, resp)
+
+ if !pass {
+ t.Fatal("should have returned true")
+ }
+
+ pass, resp = Client.UpdateUserActive(user.Id, false)
+ CheckUnauthorizedStatus(t, resp)
+
+ if pass {
+ t.Fatal("should have returned false")
+ }
+
+ th.LoginBasic2()
+
+ _, resp = Client.UpdateUserActive(user.Id, true)
+ CheckForbiddenStatus(t, resp)
+
+ _, resp = Client.UpdateUserActive(GenerateTestId(), true)
+ CheckForbiddenStatus(t, resp)
+
+ _, resp = Client.UpdateUserActive("junk", true)
+ CheckBadRequestStatus(t, resp)
+
+ Client.Logout()
+
+ _, resp = Client.UpdateUserActive(user.Id, true)
+ CheckUnauthorizedStatus(t, resp)
+
+ _, resp = SystemAdminClient.UpdateUserActive(user.Id, true)
+ CheckNoError(t, resp)
+
+ _, resp = SystemAdminClient.UpdateUserActive(user.Id, false)
+ CheckNoError(t, resp)
+}
+
func TestGetUsers(t *testing.T) {
th := Setup().InitBasic()
defer TearDown()
@@ -1297,7 +1340,7 @@ func TestUpdateUserPassword(t *testing.T) {
// Should fail because account is locked out
_, resp = Client.UpdateUserPassword(th.BasicUser.Id, th.BasicUser.Password, "newpwd")
CheckErrorMessage(t, resp, "api.user.check_user_login_attempts.too_many.app_error")
- CheckForbiddenStatus(t, resp)
+ CheckUnauthorizedStatus(t, resp)
// System admin can update another user's password
adminSetPassword := "pwdsetbyadmin"
@@ -1651,3 +1694,94 @@ func TestSetProfileImage(t *testing.T) {
t.Fatal(err)
}
}
+
+func TestSwitchAccount(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer TearDown()
+ Client := th.Client
+
+ enableGitLab := utils.Cfg.GitLabSettings.Enable
+ defer func() {
+ utils.Cfg.GitLabSettings.Enable = enableGitLab
+ }()
+ utils.Cfg.GitLabSettings.Enable = true
+
+ Client.Logout()
+
+ sr := &model.SwitchRequest{
+ CurrentService: model.USER_AUTH_SERVICE_EMAIL,
+ NewService: model.USER_AUTH_SERVICE_GITLAB,
+ Email: th.BasicUser.Email,
+ Password: th.BasicUser.Password,
+ }
+
+ link, resp := Client.SwitchAccountType(sr)
+ CheckNoError(t, resp)
+
+ if link == "" {
+ t.Fatal("bad link")
+ }
+
+ th.LoginBasic()
+
+ fakeAuthData := "1"
+ if result := <-app.Srv.Store.User().UpdateAuthData(th.BasicUser.Id, model.USER_AUTH_SERVICE_GITLAB, &fakeAuthData, th.BasicUser.Email, true); result.Err != nil {
+ t.Fatal(result.Err)
+ }
+
+ sr = &model.SwitchRequest{
+ CurrentService: model.USER_AUTH_SERVICE_GITLAB,
+ NewService: model.USER_AUTH_SERVICE_EMAIL,
+ Email: th.BasicUser.Email,
+ NewPassword: th.BasicUser.Password,
+ }
+
+ link, resp = Client.SwitchAccountType(sr)
+ CheckNoError(t, resp)
+
+ if link != "/login?extra=signin_change" {
+ t.Log(link)
+ t.Fatal("bad link")
+ }
+
+ Client.Logout()
+ _, resp = Client.Login(th.BasicUser.Email, th.BasicUser.Password)
+ CheckNoError(t, resp)
+ Client.Logout()
+
+ sr = &model.SwitchRequest{
+ CurrentService: model.USER_AUTH_SERVICE_GITLAB,
+ NewService: model.SERVICE_GOOGLE,
+ }
+
+ _, resp = Client.SwitchAccountType(sr)
+ CheckBadRequestStatus(t, resp)
+
+ sr = &model.SwitchRequest{
+ CurrentService: model.USER_AUTH_SERVICE_EMAIL,
+ NewService: model.USER_AUTH_SERVICE_GITLAB,
+ Password: th.BasicUser.Password,
+ }
+
+ _, resp = Client.SwitchAccountType(sr)
+ CheckNotFoundStatus(t, resp)
+
+ sr = &model.SwitchRequest{
+ CurrentService: model.USER_AUTH_SERVICE_EMAIL,
+ NewService: model.USER_AUTH_SERVICE_GITLAB,
+ Email: th.BasicUser.Email,
+ }
+
+ _, resp = Client.SwitchAccountType(sr)
+ CheckUnauthorizedStatus(t, resp)
+
+ sr = &model.SwitchRequest{
+ CurrentService: model.USER_AUTH_SERVICE_GITLAB,
+ NewService: model.USER_AUTH_SERVICE_EMAIL,
+ Email: th.BasicUser.Email,
+ NewPassword: th.BasicUser.Password,
+ }
+
+ _, resp = Client.SwitchAccountType(sr)
+ CheckUnauthorizedStatus(t, resp)
+}
diff --git a/api4/webhook.go b/api4/webhook.go
index 86f8bcc2e..6602c7a26 100644
--- a/api4/webhook.go
+++ b/api4/webhook.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/webhook_test.go b/api4/webhook_test.go
index 1691b27e5..96451f8a7 100644
--- a/api4/webhook_test.go
+++ b/api4/webhook_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/webrtc.go b/api4/webrtc.go
new file mode 100644
index 000000000..81a1599b2
--- /dev/null
+++ b/api4/webrtc.go
@@ -0,0 +1,29 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package api4
+
+import (
+ "net/http"
+
+ l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/app"
+ "github.com/mattermost/platform/utils"
+)
+
+func InitWebrtc() {
+ l4g.Debug(utils.T("api.webrtc.init.debug"))
+
+ BaseRoutes.Webrtc.Handle("/token", ApiSessionRequired(webrtcToken)).Methods("GET")
+}
+
+func webrtcToken(c *Context, w http.ResponseWriter, r *http.Request) {
+ result, err := app.GetWebrtcInfoForSession(c.Session.Id)
+
+ if err != nil {
+ c.Err = err
+ return
+ }
+
+ w.Write([]byte(result.ToJson()))
+}
diff --git a/api4/webrtc_test.go b/api4/webrtc_test.go
new file mode 100644
index 000000000..806118f76
--- /dev/null
+++ b/api4/webrtc_test.go
@@ -0,0 +1,29 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package api4
+
+import (
+ "testing"
+
+ "github.com/mattermost/platform/utils"
+)
+
+func TestGetWebrtcToken(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer TearDown()
+ Client := th.Client
+
+ enableWebrtc := *utils.Cfg.WebrtcSettings.Enable
+ defer func() {
+ *utils.Cfg.WebrtcSettings.Enable = enableWebrtc
+ }()
+ *utils.Cfg.WebrtcSettings.Enable = false
+
+ _, resp := Client.GetWebrtcToken()
+ CheckNotImplementedStatus(t, resp)
+
+ Client.Logout()
+ _, resp = Client.GetWebrtcToken()
+ CheckUnauthorizedStatus(t, resp)
+}
diff --git a/api4/websocket.go b/api4/websocket.go
index c70327222..1caef6c4a 100644
--- a/api4/websocket.go
+++ b/api4/websocket.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/api4/websocket_test.go b/api4/websocket_test.go
index 6018bf7da..1098f4759 100644
--- a/api4/websocket_test.go
+++ b/api4/websocket_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package api4
diff --git a/app/admin.go b/app/admin.go
index b86eb5993..103c4617b 100644
--- a/app/admin.go
+++ b/app/admin.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
@@ -136,7 +136,6 @@ func SaveConfig(cfg *model.Config) *model.AppError {
return model.NewLocAppError("saveConfig", "ent.cluster.save_config.error", nil, "")
}
- //oldCfg := utils.Cfg
utils.DisableConfigWatch()
utils.SaveConfig(utils.CfgFileName, cfg)
utils.LoadConfig(utils.CfgFileName)
@@ -150,6 +149,7 @@ func SaveConfig(cfg *model.Config) *model.AppError {
}
}
+ // oldCfg := utils.Cfg
// Future feature is to sync the configuration files
// if einterfaces.GetClusterInterface() != nil {
// err := einterfaces.GetClusterInterface().ConfigChanged(cfg, oldCfg, true)
diff --git a/app/analytics.go b/app/analytics.go
index f1146327f..78e1fe7b4 100644
--- a/app/analytics.go
+++ b/app/analytics.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/app.go b/app/app.go
index 8568c7bba..2758add0e 100644
--- a/app/app.go
+++ b/app/app.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/apptestlib.go b/app/apptestlib.go
index 52530f92f..0c7086c64 100644
--- a/app/apptestlib.go
+++ b/app/apptestlib.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
@@ -75,6 +75,14 @@ func (me *TestHelper) InitBasic() *TestHelper {
return me
}
+func (me *TestHelper) MakeUsername() string {
+ return "un_" + model.NewId()
+}
+
+func (me *TestHelper) MakeEmail() string {
+ return "success_" + model.NewId() + "@simulator.amazonses.com"
+}
+
func (me *TestHelper) CreateTeam() *model.Team {
id := model.NewId()
team := &model.Team{
diff --git a/app/audit.go b/app/audit.go
index 6b7439d43..fdd152719 100644
--- a/app/audit.go
+++ b/app/audit.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/authentication.go b/app/authentication.go
index 369458527..5e1b4461f 100644
--- a/app/authentication.go
+++ b/app/authentication.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
@@ -43,7 +43,7 @@ func checkUserPassword(user *model.User, password string) *model.AppError {
return result.Err
}
- return model.NewLocAppError("checkUserPassword", "api.user.check_user_password.invalid.app_error", nil, "user_id="+user.Id)
+ return model.NewAppError("checkUserPassword", "api.user.check_user_password.invalid.app_error", nil, "user_id="+user.Id, http.StatusUnauthorized)
} else {
if result := <-Srv.Store.User().UpdateFailedPasswordAttempts(user.Id, 0); result.Err != nil {
return result.Err
@@ -57,8 +57,7 @@ func checkLdapUserPasswordAndAllCriteria(ldapId *string, password string, mfaTok
ldapInterface := einterfaces.GetLdapInterface()
if ldapInterface == nil || ldapId == nil {
- err := model.NewLocAppError("doLdapAuthentication", "api.user.login_ldap.not_available.app_error", nil, "")
- err.StatusCode = http.StatusNotImplemented
+ err := model.NewAppError("doLdapAuthentication", "api.user.login_ldap.not_available.app_error", nil, "", http.StatusNotImplemented)
return nil, err
}
@@ -109,13 +108,13 @@ func CheckUserMfa(user *model.User, token string) *model.AppError {
mfaInterface := einterfaces.GetMfaInterface()
if mfaInterface == nil {
- return model.NewLocAppError("checkUserMfa", "api.user.check_user_mfa.not_available.app_error", nil, "")
+ return model.NewAppError("checkUserMfa", "api.user.check_user_mfa.not_available.app_error", nil, "", http.StatusNotImplemented)
}
if ok, err := mfaInterface.ValidateToken(user.MfaSecret, token); err != nil {
return err
} else if !ok {
- return model.NewLocAppError("checkUserMfa", "api.user.check_user_mfa.bad_code.app_error", nil, "")
+ return model.NewAppError("checkUserMfa", "api.user.check_user_mfa.bad_code.app_error", nil, "", http.StatusUnauthorized)
}
return nil
@@ -123,7 +122,7 @@ func CheckUserMfa(user *model.User, token string) *model.AppError {
func checkUserLoginAttempts(user *model.User) *model.AppError {
if user.FailedAttempts >= utils.Cfg.ServiceSettings.MaximumLoginAttempts {
- return model.NewAppError("checkUserLoginAttempts", "api.user.check_user_login_attempts.too_many.app_error", nil, "user_id="+user.Id, http.StatusForbidden)
+ return model.NewAppError("checkUserLoginAttempts", "api.user.check_user_login_attempts.too_many.app_error", nil, "user_id="+user.Id, http.StatusUnauthorized)
}
return nil
@@ -131,14 +130,14 @@ func checkUserLoginAttempts(user *model.User) *model.AppError {
func checkEmailVerified(user *model.User) *model.AppError {
if !user.EmailVerified && utils.Cfg.EmailSettings.RequireEmailVerification {
- return model.NewLocAppError("Login", "api.user.login.not_verified.app_error", nil, "user_id="+user.Id)
+ return model.NewAppError("Login", "api.user.login.not_verified.app_error", nil, "user_id="+user.Id, http.StatusUnauthorized)
}
return nil
}
func checkUserNotDisabled(user *model.User) *model.AppError {
if user.DeleteAt > 0 {
- return model.NewLocAppError("Login", "api.user.login.inactive.app_error", nil, "user_id="+user.Id)
+ return model.NewAppError("Login", "api.user.login.inactive.app_error", nil, "user_id="+user.Id, http.StatusUnauthorized)
}
return nil
}
@@ -148,8 +147,7 @@ func authenticateUser(user *model.User, password, mfaToken string) (*model.User,
if user.AuthService == model.USER_AUTH_SERVICE_LDAP {
if !ldapAvailable {
- err := model.NewLocAppError("login", "api.user.login_ldap.not_available.app_error", nil, "")
- err.StatusCode = http.StatusNotImplemented
+ err := model.NewAppError("login", "api.user.login_ldap.not_available.app_error", nil, "", http.StatusNotImplemented)
return user, err
} else if ldapUser, err := checkLdapUserPasswordAndAllCriteria(user.AuthData, password, mfaToken); err != nil {
err.StatusCode = http.StatusUnauthorized
@@ -163,8 +161,7 @@ func authenticateUser(user *model.User, password, mfaToken string) (*model.User,
if authService == model.USER_AUTH_SERVICE_SAML {
authService = strings.ToUpper(authService)
}
- err := model.NewLocAppError("login", "api.user.login.use_auth_service.app_error", map[string]interface{}{"AuthService": authService}, "")
- err.StatusCode = http.StatusBadRequest
+ err := model.NewAppError("login", "api.user.login.use_auth_service.app_error", map[string]interface{}{"AuthService": authService}, "", http.StatusBadRequest)
return user, err
} else {
if err := CheckPasswordAndAllCriteria(user, password, mfaToken); err != nil {
diff --git a/app/authorization.go b/app/authorization.go
index 4d36c63e8..9fc2edfb9 100644
--- a/app/authorization.go
+++ b/app/authorization.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/authorization_test.go b/app/authorization_test.go
index 049567483..4d2fdd5a0 100644
--- a/app/authorization_test.go
+++ b/app/authorization_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/auto_channels.go b/app/auto_channels.go
index 3945a5a4f..2f91cf14b 100644
--- a/app/auto_channels.go
+++ b/app/auto_channels.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/auto_constants.go b/app/auto_constants.go
index c8c903e32..2a9438396 100644
--- a/app/auto_constants.go
+++ b/app/auto_constants.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/auto_environment.go b/app/auto_environment.go
index b0a4f54b8..8827ddf87 100644
--- a/app/auto_environment.go
+++ b/app/auto_environment.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/auto_posts.go b/app/auto_posts.go
index b32407539..07d260846 100644
--- a/app/auto_posts.go
+++ b/app/auto_posts.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/auto_teams.go b/app/auto_teams.go
index 6e66f4446..029d33aa1 100644
--- a/app/auto_teams.go
+++ b/app/auto_teams.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/auto_users.go b/app/auto_users.go
index 7a99cc90b..71e20817d 100644
--- a/app/auto_users.go
+++ b/app/auto_users.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/brand.go b/app/brand.go
index 9b3df3145..bb11bd581 100644
--- a/app/brand.go
+++ b/app/brand.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/channel.go b/app/channel.go
index 1c04905c2..17fa02ad3 100644
--- a/app/channel.go
+++ b/app/channel.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
@@ -81,7 +81,7 @@ func JoinDefaultChannels(teamId string, user *model.User, channelRole string, us
err = cmResult.Err
}
- if requestor == nil {
+ if requestor == nil {
if err := postJoinChannelMessage(user, offTopic); err != nil {
l4g.Error(utils.T("api.channel.post_user_add_remove_message_and_forget.error"), err)
}
diff --git a/app/command.go b/app/command.go
index 188729ad5..2af934710 100644
--- a/app/command.go
+++ b/app/command.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
@@ -312,6 +312,7 @@ func GetCommand(commandId string) (*model.Command, *model.AppError) {
}
if result := <-Srv.Store.Command().Get(commandId); result.Err != nil {
+ result.Err.StatusCode = http.StatusNotFound
return nil, result.Err
} else {
return result.Data.(*model.Command), nil
diff --git a/app/command_away.go b/app/command_away.go
index 55553fa3f..f4150dfeb 100644
--- a/app/command_away.go
+++ b/app/command_away.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/command_echo.go b/app/command_echo.go
index 40d70e54a..ef70cb609 100644
--- a/app/command_echo.go
+++ b/app/command_echo.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/command_expand_collapse.go b/app/command_expand_collapse.go
index a4a152c60..314a54b2a 100644
--- a/app/command_expand_collapse.go
+++ b/app/command_expand_collapse.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/command_invite_people.go b/app/command_invite_people.go
index 0496dadca..6b0ee96b4 100644
--- a/app/command_invite_people.go
+++ b/app/command_invite_people.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/command_join.go b/app/command_join.go
index 5b19dd7a0..9ad3682a1 100644
--- a/app/command_join.go
+++ b/app/command_join.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/command_loadtest.go b/app/command_loadtest.go
index d3c7474ae..ad64573fc 100644
--- a/app/command_loadtest.go
+++ b/app/command_loadtest.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/command_logout.go b/app/command_logout.go
index 1a353056e..cc59d2686 100644
--- a/app/command_logout.go
+++ b/app/command_logout.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/command_me.go b/app/command_me.go
index bb29ec1e0..be09ac5dd 100644
--- a/app/command_me.go
+++ b/app/command_me.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/command_msg.go b/app/command_msg.go
index fd4ace61a..977e403d5 100644
--- a/app/command_msg.go
+++ b/app/command_msg.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/command_offline.go b/app/command_offline.go
index 6e2c125f8..5316ccc5f 100644
--- a/app/command_offline.go
+++ b/app/command_offline.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/command_online.go b/app/command_online.go
index bd6fbab60..b0becaf14 100644
--- a/app/command_online.go
+++ b/app/command_online.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/command_shortcuts.go b/app/command_shortcuts.go
index 93e5f0f51..7df5dbaed 100644
--- a/app/command_shortcuts.go
+++ b/app/command_shortcuts.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/command_shrug.go b/app/command_shrug.go
index 12d1039ec..88dbcef8c 100644
--- a/app/command_shrug.go
+++ b/app/command_shrug.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/compliance.go b/app/compliance.go
index 966b9b523..cb1eece70 100644
--- a/app/compliance.go
+++ b/app/compliance.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/diagnostics.go b/app/diagnostics.go
index 2c8211f42..295164c97 100644
--- a/app/diagnostics.go
+++ b/app/diagnostics.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/diagnostics_test.go b/app/diagnostics_test.go
index 21b077bd8..80c12fd2d 100644
--- a/app/diagnostics_test.go
+++ b/app/diagnostics_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/email.go b/app/email.go
index cb2fa213a..235d949be 100644
--- a/app/email.go
+++ b/app/email.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
@@ -18,7 +18,7 @@ func SendChangeUsernameEmail(oldUsername, newUsername, email, locale, siteURL st
subject := T("api.templates.username_change_subject",
map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"],
- "TeamDisplayName": utils.Cfg.TeamSettings.SiteName})
+ "TeamDisplayName": utils.Cfg.TeamSettings.SiteName})
bodyPage := utils.NewHTMLTemplate("email_change_body", locale)
bodyPage.Props["SiteURL"] = siteURL
@@ -40,8 +40,7 @@ func SendEmailChangeVerifyEmail(userId, newUserEmail, locale, siteURL string) *m
subject := T("api.templates.email_change_verify_subject",
map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"],
- "TeamDisplayName": utils.Cfg.TeamSettings.SiteName})
-
+ "TeamDisplayName": utils.Cfg.TeamSettings.SiteName})
bodyPage := utils.NewHTMLTemplate("email_change_verify_body", locale)
bodyPage.Props["SiteURL"] = siteURL
@@ -63,7 +62,7 @@ func SendEmailChangeEmail(oldEmail, newEmail, locale, siteURL string) *model.App
subject := T("api.templates.email_change_subject",
map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"],
- "TeamDisplayName": utils.Cfg.TeamSettings.SiteName})
+ "TeamDisplayName": utils.Cfg.TeamSettings.SiteName})
bodyPage := utils.NewHTMLTemplate("email_change_body", locale)
bodyPage.Props["SiteURL"] = siteURL
@@ -128,7 +127,7 @@ func SendWelcomeEmail(userId string, email string, verified bool, locale, siteUR
subject := T("api.templates.welcome_subject",
map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"],
- "ServerURL": rawUrl.Host})
+ "ServerURL": rawUrl.Host})
bodyPage := utils.NewHTMLTemplate("welcome_body", locale)
bodyPage.Props["SiteURL"] = siteURL
@@ -161,7 +160,7 @@ func SendPasswordChangeEmail(email, method, locale, siteURL string) *model.AppEr
subject := T("api.templates.password_change_subject",
map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"],
- "TeamDisplayName": utils.Cfg.TeamSettings.SiteName})
+ "TeamDisplayName": utils.Cfg.TeamSettings.SiteName})
bodyPage := utils.NewHTMLTemplate("password_change_body", locale)
bodyPage.Props["SiteURL"] = siteURL
@@ -234,8 +233,8 @@ func SendInviteEmails(team *model.Team, senderName string, invites []string, sit
subject := utils.T("api.templates.invite_subject",
map[string]interface{}{"SenderName": senderName,
- "TeamDisplayName": team.DisplayName,
- "SiteName": utils.ClientCfg["SiteName"]})
+ "TeamDisplayName": team.DisplayName,
+ "SiteName": utils.ClientCfg["SiteName"]})
bodyPage := utils.NewHTMLTemplate("invite_body", model.DEFAULT_LOCALE)
bodyPage.Props["SiteURL"] = siteURL
diff --git a/app/email_batching.go b/app/email_batching.go
index ac91aae08..6d7a376ef 100644
--- a/app/email_batching.go
+++ b/app/email_batching.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/email_batching_test.go b/app/email_batching_test.go
index 23722facd..74fbea5c3 100644
--- a/app/email_batching_test.go
+++ b/app/email_batching_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/email_test.go b/app/email_test.go
index 6d1a6f14a..3f57c54f9 100644
--- a/app/email_test.go
+++ b/app/email_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/emoji.go b/app/emoji.go
new file mode 100644
index 000000000..b0c8418aa
--- /dev/null
+++ b/app/emoji.go
@@ -0,0 +1,206 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "bytes"
+ "image"
+ "image/color/palette"
+ "image/draw"
+ "image/gif"
+ _ "image/jpeg"
+ "image/png"
+ "io"
+ "mime/multipart"
+ "net/http"
+
+ l4g "github.com/alecthomas/log4go"
+
+ "github.com/disintegration/imaging"
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
+)
+
+const (
+ MaxEmojiFileSize = 1000 * 1024 // 1 MB
+ MaxEmojiWidth = 128
+ MaxEmojiHeight = 128
+)
+
+func CreateEmoji(sessionUserId string, emoji *model.Emoji, multiPartImageData *multipart.Form) (*model.Emoji, *model.AppError) {
+ // wipe the emoji id so that existing emojis can't get overwritten
+ emoji.Id = ""
+
+ // do our best to validate the emoji before committing anything to the DB so that we don't have to clean up
+ // orphaned files left over when validation fails later on
+ emoji.PreSave()
+ if err := emoji.IsValid(); err != nil {
+ return nil, err
+ }
+
+ if emoji.CreatorId != sessionUserId {
+ return nil, model.NewAppError("createEmoji", "api.emoji.create.other_user.app_error", nil, "", http.StatusForbidden)
+ }
+
+ if result := <-Srv.Store.Emoji().GetByName(emoji.Name); result.Err == nil && result.Data != nil {
+ return nil, model.NewAppError("createEmoji", "api.emoji.create.duplicate.app_error", nil, "", http.StatusBadRequest)
+ }
+
+ if imageData := multiPartImageData.File["image"]; len(imageData) == 0 {
+ err := model.NewLocAppError("Context", "api.context.invalid_body_param.app_error", map[string]interface{}{"Name": "createEmoji"}, "")
+ err.StatusCode = http.StatusBadRequest
+ return nil, err
+ } else if err := UploadEmojiImage(emoji.Id, imageData[0]); err != nil {
+ return nil, err
+ }
+
+ if result := <-Srv.Store.Emoji().Save(emoji); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.Emoji), nil
+ }
+}
+
+func GetEmojiList() ([]*model.Emoji, *model.AppError) {
+ if result := <-Srv.Store.Emoji().GetAll(); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.Emoji), nil
+ }
+}
+
+func UploadEmojiImage(id string, imageData *multipart.FileHeader) *model.AppError {
+ file, err := imageData.Open()
+ if err != nil {
+ return model.NewAppError("uploadEmojiImage", "api.emoji.upload.open.app_error", nil, "", http.StatusBadRequest)
+ }
+ defer file.Close()
+
+ buf := bytes.NewBuffer(nil)
+ io.Copy(buf, file)
+
+ // make sure the file is an image and is within the required dimensions
+ if config, _, err := image.DecodeConfig(bytes.NewReader(buf.Bytes())); err != nil {
+ return model.NewAppError("uploadEmojiImage", "api.emoji.upload.image.app_error", nil, "", http.StatusBadRequest)
+ } else if config.Width > MaxEmojiWidth || config.Height > MaxEmojiHeight {
+ data := buf.Bytes()
+ newbuf := bytes.NewBuffer(nil)
+ if info, err := model.GetInfoForBytes(imageData.Filename, data); err != nil {
+ return err
+ } else if info.MimeType == "image/gif" {
+ if gif_data, err := gif.DecodeAll(bytes.NewReader(data)); err != nil {
+ return model.NewAppError("uploadEmojiImage", "api.emoji.upload.large_image.gif_decode_error", nil, "", http.StatusBadRequest)
+ } else {
+ resized_gif := resizeEmojiGif(gif_data)
+ if err := gif.EncodeAll(newbuf, resized_gif); err != nil {
+ return model.NewAppError("uploadEmojiImage", "api.emoji.upload.large_image.gif_encode_error", nil, "", http.StatusBadRequest)
+ }
+ if err := WriteFile(newbuf.Bytes(), getEmojiImagePath(id)); err != nil {
+ return err
+ }
+ }
+ } else {
+ if img, _, err := image.Decode(bytes.NewReader(data)); err != nil {
+ return model.NewAppError("uploadEmojiImage", "api.emoji.upload.large_image.decode_error", nil, "", http.StatusBadRequest)
+ } else {
+ resized_image := resizeEmoji(img, config.Width, config.Height)
+ if err := png.Encode(newbuf, resized_image); err != nil {
+ return model.NewAppError("uploadEmojiImage", "api.emoji.upload.large_image.encode_error", nil, "", http.StatusBadRequest)
+ }
+ if err := WriteFile(newbuf.Bytes(), getEmojiImagePath(id)); err != nil {
+ return err
+ }
+ }
+ }
+ } else {
+ if err := WriteFile(buf.Bytes(), getEmojiImagePath(id)); err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func DeleteEmoji(emoji *model.Emoji) *model.AppError {
+ if err := (<-Srv.Store.Emoji().Delete(emoji.Id, model.GetMillis())).Err; err != nil {
+ return err
+ }
+
+ go deleteEmojiImage(emoji.Id)
+ go deleteReactionsForEmoji(emoji.Name)
+ return nil
+}
+
+func GetEmoji(emojiId string) (*model.Emoji, *model.AppError) {
+ if !*utils.Cfg.ServiceSettings.EnableCustomEmoji {
+ return nil, model.NewAppError("deleteEmoji", "api.emoji.disabled.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ if len(utils.Cfg.FileSettings.DriverName) == 0 {
+ return nil, model.NewAppError("deleteImage", "api.emoji.storage.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ if result := <-Srv.Store.Emoji().Get(emojiId, false); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.Emoji), nil
+ }
+}
+
+func resizeEmojiGif(gifImg *gif.GIF) *gif.GIF {
+ // Create a new RGBA image to hold the incremental frames.
+ firstFrame := gifImg.Image[0].Bounds()
+ b := image.Rect(0, 0, firstFrame.Dx(), firstFrame.Dy())
+ img := image.NewRGBA(b)
+
+ resizedImage := image.Image(nil)
+ // Resize each frame.
+ for index, frame := range gifImg.Image {
+ bounds := frame.Bounds()
+ draw.Draw(img, bounds, frame, bounds.Min, draw.Over)
+ resizedImage = resizeEmoji(img, firstFrame.Dx(), firstFrame.Dy())
+ gifImg.Image[index] = imageToPaletted(resizedImage)
+ }
+ // Set new gif width and height
+ gifImg.Config.Width = resizedImage.Bounds().Dx()
+ gifImg.Config.Height = resizedImage.Bounds().Dy()
+ return gifImg
+}
+
+func getEmojiImagePath(id string) string {
+ return "emoji/" + id + "/image"
+}
+
+func resizeEmoji(img image.Image, width int, height int) image.Image {
+ emojiWidth := float64(width)
+ emojiHeight := float64(height)
+
+ var emoji image.Image
+ if emojiHeight <= MaxEmojiHeight && emojiWidth <= MaxEmojiWidth {
+ emoji = img
+ } else {
+ emoji = imaging.Fit(img, MaxEmojiWidth, MaxEmojiHeight, imaging.Lanczos)
+ }
+ return emoji
+}
+
+func imageToPaletted(img image.Image) *image.Paletted {
+ b := img.Bounds()
+ pm := image.NewPaletted(b, palette.Plan9)
+ draw.FloydSteinberg.Draw(pm, b, img, image.ZP)
+ return pm
+}
+
+func deleteEmojiImage(id string) {
+ if err := MoveFile(getEmojiImagePath(id), "emoji/"+id+"/image_deleted"); err != nil {
+ l4g.Error("Failed to rename image when deleting emoji %v", id)
+ }
+}
+
+func deleteReactionsForEmoji(emojiName string) {
+ if result := <-Srv.Store.Reaction().DeleteAllWithEmojiName(emojiName); result.Err != nil {
+ l4g.Warn(utils.T("api.emoji.delete.delete_reactions.app_error"), emojiName)
+ l4g.Warn(result.Err)
+ }
+}
diff --git a/app/file.go b/app/file.go
index 8c0960fe8..c5e2982d4 100644
--- a/app/file.go
+++ b/app/file.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/file_test.go b/app/file_test.go
index 9df03315e..683b574b8 100644
--- a/app/file_test.go
+++ b/app/file_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/import.go b/app/import.go
index 6bf4e8a89..f92c9b1cc 100644
--- a/app/import.go
+++ b/app/import.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/import_test.go b/app/import_test.go
index e3ed80169..847864977 100644
--- a/app/import_test.go
+++ b/app/import_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/ldap.go b/app/ldap.go
index fe68dfa81..1b823dc47 100644
--- a/app/ldap.go
+++ b/app/ldap.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
@@ -18,7 +18,7 @@ func SyncLdap() {
if ldapI := einterfaces.GetLdapInterface(); ldapI != nil {
ldapI.SyncNow()
} else {
- l4g.Error("%v", model.NewLocAppError("ldapSyncNow", "ent.ldap.disabled.app_error", nil, "").Error())
+ l4g.Error("%v", model.NewLocAppError("SyncLdap", "ent.ldap.disabled.app_error", nil, "").Error())
}
}
}()
@@ -31,10 +31,84 @@ func TestLdap() *model.AppError {
return err
}
} else {
- err := model.NewLocAppError("ldapTest", "ent.ldap.disabled.app_error", nil, "")
+ err := model.NewLocAppError("TestLdap", "ent.ldap.disabled.app_error", nil, "")
err.StatusCode = http.StatusNotImplemented
return err
}
return nil
}
+
+func SwitchEmailToLdap(email, password, code, ldapId, ldapPassword string) (string, *model.AppError) {
+ user, err := GetUserByEmail(email)
+ if err != nil {
+ return "", err
+ }
+
+ if err := CheckPasswordAndAllCriteria(user, password, code); err != nil {
+ return "", err
+ }
+
+ if err := RevokeAllSessions(user.Id); err != nil {
+ return "", err
+ }
+
+ ldapInterface := einterfaces.GetLdapInterface()
+ if ldapInterface == nil {
+ return "", model.NewAppError("SwitchEmailToLdap", "api.user.email_to_ldap.not_available.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ if err := ldapInterface.SwitchToLdap(user.Id, ldapId, ldapPassword); err != nil {
+ return "", err
+ }
+
+ go func() {
+ if err := SendSignInChangeEmail(user.Email, "AD/LDAP", user.Locale, utils.GetSiteURL()); err != nil {
+ l4g.Error(err.Error())
+ }
+ }()
+
+ return "/login?extra=signin_change", nil
+}
+
+func SwitchLdapToEmail(ldapPassword, code, email, newPassword string) (string, *model.AppError) {
+ user, err := GetUserByEmail(email)
+ if err != nil {
+ return "", err
+ }
+
+ if user.AuthService != model.USER_AUTH_SERVICE_LDAP {
+ return "", model.NewAppError("SwitchLdapToEmail", "api.user.ldap_to_email.not_ldap_account.app_error", nil, "", http.StatusBadRequest)
+ }
+
+ ldapInterface := einterfaces.GetLdapInterface()
+ if ldapInterface == nil || user.AuthData == nil {
+ return "", model.NewAppError("SwitchLdapToEmail", "api.user.ldap_to_email.not_available.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ if err := ldapInterface.CheckPassword(*user.AuthData, ldapPassword); err != nil {
+ return "", err
+ }
+
+ if err := CheckUserMfa(user, code); err != nil {
+ return "", err
+ }
+
+ if err := UpdatePassword(user, newPassword); err != nil {
+ return "", err
+ }
+
+ if err := RevokeAllSessions(user.Id); err != nil {
+ return "", err
+ }
+
+ T := utils.GetUserTranslations(user.Locale)
+
+ go func() {
+ if err := SendSignInChangeEmail(user.Email, T("api.templates.signin_change_email.body.method_email"), user.Locale, utils.GetSiteURL()); err != nil {
+ l4g.Error(err.Error())
+ }
+ }()
+
+ return "/login?extra=signin_change", nil
+}
diff --git a/app/license.go b/app/license.go
index c41c17fd8..7a00d7fb4 100644
--- a/app/license.go
+++ b/app/license.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/license_test.go b/app/license_test.go
index d7d851589..a7761b204 100644
--- a/app/license_test.go
+++ b/app/license_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/login.go b/app/login.go
index e9bcf1f03..4c7ab8474 100644
--- a/app/login.go
+++ b/app/login.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/notification.go b/app/notification.go
index ef1b70aad..e983f5e8c 100644
--- a/app/notification.go
+++ b/app/notification.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/notification_test.go b/app/notification_test.go
index 3768a95c7..794bb4b37 100644
--- a/app/notification_test.go
+++ b/app/notification_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/oauth.go b/app/oauth.go
index 3e8b0b8d2..260e4ac00 100644
--- a/app/oauth.go
+++ b/app/oauth.go
@@ -1,14 +1,386 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
import (
+ "bytes"
+ "crypto/tls"
+ b64 "encoding/base64"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strings"
+
+ l4g "github.com/alecthomas/log4go"
+ "github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/store"
+ "github.com/mattermost/platform/utils"
)
-func RevokeAccessToken(token string) *model.AppError {
+func CreateOAuthApp(app *model.OAuthApp) (*model.OAuthApp, *model.AppError) {
+ if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
+ return nil, model.NewAppError("CreateOAuthApp", "api.oauth.register_oauth_app.turn_off.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ secret := model.NewId()
+ app.ClientSecret = secret
+
+ if result := <-Srv.Store.OAuth().SaveApp(app); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.OAuthApp), nil
+ }
+}
+
+func GetOAuthApp(appId string) (*model.OAuthApp, *model.AppError) {
+ if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
+ return nil, model.NewAppError("GetOAuthApp", "api.oauth.allow_oauth.turn_off.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ if result := <-Srv.Store.OAuth().GetApp(appId); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.OAuthApp), nil
+ }
+}
+
+func DeleteOAuthApp(appId string) *model.AppError {
+ if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
+ return model.NewAppError("DeleteOAuthApp", "api.oauth.allow_oauth.turn_off.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ if err := (<-Srv.Store.OAuth().DeleteApp(appId)).Err; err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func GetOAuthApps(page, perPage int) ([]*model.OAuthApp, *model.AppError) {
+ if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
+ return nil, model.NewAppError("GetOAuthApps", "api.oauth.allow_oauth.turn_off.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ if result := <-Srv.Store.OAuth().GetApps(page*perPage, perPage); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.OAuthApp), nil
+ }
+}
+
+func GetOAuthAppsByCreator(userId string, page, perPage int) ([]*model.OAuthApp, *model.AppError) {
+ if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
+ return nil, model.NewAppError("GetOAuthAppsByUser", "api.oauth.allow_oauth.turn_off.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ if result := <-Srv.Store.OAuth().GetAppByUser(userId, page*perPage, perPage); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.OAuthApp), nil
+ }
+}
+
+func AllowOAuthAppAccessToUser(userId, responseType, clientId, redirectUri, scope, state string) (string, *model.AppError) {
+ if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
+ return "", model.NewAppError("AllowOAuthAppAccessToUser", "api.oauth.allow_oauth.turn_off.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ if len(scope) == 0 {
+ scope = model.DEFAULT_SCOPE
+ }
+
+ var oauthApp *model.OAuthApp
+ if result := <-Srv.Store.OAuth().GetApp(clientId); result.Err != nil {
+ return "", result.Err
+ } else {
+ oauthApp = result.Data.(*model.OAuthApp)
+ }
+
+ if !oauthApp.IsValidRedirectURL(redirectUri) {
+ return "", model.NewAppError("AllowOAuthAppAccessToUser", "api.oauth.allow_oauth.redirect_callback.app_error", nil, "", http.StatusBadRequest)
+ }
+
+ if responseType != model.AUTHCODE_RESPONSE_TYPE {
+ return redirectUri + "?error=unsupported_response_type&state=" + state, nil
+ }
+
+ authData := &model.AuthData{UserId: userId, ClientId: clientId, CreateAt: model.GetMillis(), RedirectUri: redirectUri, State: state, Scope: scope}
+ authData.Code = model.HashPassword(fmt.Sprintf("%v:%v:%v:%v", clientId, redirectUri, authData.CreateAt, userId))
+
+ // this saves the OAuth2 app as authorized
+ authorizedApp := model.Preference{
+ UserId: userId,
+ Category: model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP,
+ Name: clientId,
+ Value: scope,
+ }
+
+ if result := <-Srv.Store.Preference().Save(&model.Preferences{authorizedApp}); result.Err != nil {
+ return redirectUri + "?error=server_error&state=" + state, nil
+ }
+
+ if result := <-Srv.Store.OAuth().SaveAuthData(authData); result.Err != nil {
+ return redirectUri + "?error=server_error&state=" + state, nil
+ }
+
+ return redirectUri + "?code=" + url.QueryEscape(authData.Code) + "&state=" + url.QueryEscape(authData.State), nil
+}
+
+func GetOAuthAccessToken(clientId, grantType, redirectUri, code, secret, refreshToken string) (*model.AccessResponse, *model.AppError) {
+ if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
+ return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.disabled.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ var oauthApp *model.OAuthApp
+ if result := <-Srv.Store.OAuth().GetApp(clientId); result.Err != nil {
+ return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.credentials.app_error", nil, "", http.StatusNotFound)
+ } else {
+ oauthApp = result.Data.(*model.OAuthApp)
+ }
+
+ if oauthApp.ClientSecret != secret {
+ return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.credentials.app_error", nil, "", http.StatusForbidden)
+ }
+
+ var user *model.User
+ var accessData *model.AccessData
+ var accessRsp *model.AccessResponse
+ if grantType == model.ACCESS_TOKEN_GRANT_TYPE {
+
+ var authData *model.AuthData
+ if result := <-Srv.Store.OAuth().GetAuthData(code); result.Err != nil {
+ return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.expired_code.app_error", nil, "", http.StatusInternalServerError)
+ } else {
+ authData = result.Data.(*model.AuthData)
+ }
+
+ if authData.IsExpired() {
+ <-Srv.Store.OAuth().RemoveAuthData(authData.Code)
+ return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.expired_code.app_error", nil, "", http.StatusForbidden)
+ }
+
+ if authData.RedirectUri != redirectUri {
+ return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.redirect_uri.app_error", nil, "", http.StatusBadRequest)
+ }
+
+ if !model.ComparePassword(code, fmt.Sprintf("%v:%v:%v:%v", clientId, redirectUri, authData.CreateAt, authData.UserId)) {
+ return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.expired_code.app_error", nil, "", http.StatusBadRequest)
+ }
+
+ if result := <-Srv.Store.User().Get(authData.UserId); result.Err != nil {
+ return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.internal_user.app_error", nil, "", http.StatusNotFound)
+ } else {
+ user = result.Data.(*model.User)
+ }
+ if result := <-Srv.Store.OAuth().GetPreviousAccessData(user.Id, clientId); result.Err != nil {
+ return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.internal.app_error", nil, "", http.StatusInternalServerError)
+ } else if result.Data != nil {
+ accessData := result.Data.(*model.AccessData)
+ if accessData.IsExpired() {
+ if access, err := newSessionUpdateToken(oauthApp.Name, accessData, user); err != nil {
+ return nil, err
+ } else {
+ accessRsp = access
+ }
+ } else {
+ //return the same token and no need to create a new session
+ accessRsp = &model.AccessResponse{
+ AccessToken: accessData.Token,
+ TokenType: model.ACCESS_TOKEN_TYPE,
+ ExpiresIn: int32((accessData.ExpiresAt - model.GetMillis()) / 1000),
+ }
+ }
+ } else {
+ // create a new session and return new access token
+ var session *model.Session
+ if result, err := newSession(oauthApp.Name, user); err != nil {
+ return nil, err
+ } else {
+ session = result
+ }
+
+ accessData = &model.AccessData{ClientId: clientId, UserId: user.Id, Token: session.Token, RefreshToken: model.NewId(), RedirectUri: redirectUri, ExpiresAt: session.ExpiresAt, Scope: authData.Scope}
+
+ if result := <-Srv.Store.OAuth().SaveAccessData(accessData); result.Err != nil {
+ l4g.Error(result.Err)
+ return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.internal_saving.app_error", nil, "", http.StatusInternalServerError)
+ }
+
+ accessRsp = &model.AccessResponse{
+ AccessToken: session.Token,
+ TokenType: model.ACCESS_TOKEN_TYPE,
+ RefreshToken: accessData.RefreshToken,
+ ExpiresIn: int32(*utils.Cfg.ServiceSettings.SessionLengthSSOInDays * 60 * 60 * 24),
+ }
+ }
+
+ <-Srv.Store.OAuth().RemoveAuthData(authData.Code)
+ } else {
+ // when grantType is refresh_token
+ if result := <-Srv.Store.OAuth().GetAccessDataByRefreshToken(refreshToken); result.Err != nil {
+ return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.refresh_token.app_error", nil, "", http.StatusNotFound)
+ } else {
+ accessData = result.Data.(*model.AccessData)
+ }
+
+ if result := <-Srv.Store.User().Get(accessData.UserId); result.Err != nil {
+ return nil, model.NewAppError("GetOAuthAccessToken", "api.oauth.get_access_token.internal_user.app_error", nil, "", http.StatusNotFound)
+ } else {
+ user = result.Data.(*model.User)
+ }
+
+ if access, err := newSessionUpdateToken(oauthApp.Name, accessData, user); err != nil {
+ return nil, err
+ } else {
+ accessRsp = access
+ }
+ }
+
+ return accessRsp, nil
+}
+
+func newSession(appName string, user *model.User) (*model.Session, *model.AppError) {
+ // set new token an session
+ session := &model.Session{UserId: user.Id, Roles: user.Roles, IsOAuth: true}
+ session.SetExpireInDays(*utils.Cfg.ServiceSettings.SessionLengthSSOInDays)
+ session.AddProp(model.SESSION_PROP_PLATFORM, appName)
+ session.AddProp(model.SESSION_PROP_OS, "OAuth2")
+ session.AddProp(model.SESSION_PROP_BROWSER, "OAuth2")
+
+ if result := <-Srv.Store.Session().Save(session); result.Err != nil {
+ return nil, model.NewAppError("newSession", "api.oauth.get_access_token.internal_session.app_error", nil, "", http.StatusInternalServerError)
+ } else {
+ session = result.Data.(*model.Session)
+ AddSessionToCache(session)
+ }
+
+ return session, nil
+}
+
+func newSessionUpdateToken(appName string, accessData *model.AccessData, user *model.User) (*model.AccessResponse, *model.AppError) {
+ var session *model.Session
+ <-Srv.Store.Session().Remove(accessData.Token) //remove the previous session
+
+ if result, err := newSession(appName, user); err != nil {
+ return nil, err
+ } else {
+ session = result
+ }
+
+ accessData.Token = session.Token
+ accessData.ExpiresAt = session.ExpiresAt
+ if result := <-Srv.Store.OAuth().UpdateAccessData(accessData); result.Err != nil {
+ l4g.Error(result.Err)
+ return nil, model.NewAppError("newSessionUpdateToken", "web.get_access_token.internal_saving.app_error", nil, "", http.StatusInternalServerError)
+ }
+ accessRsp := &model.AccessResponse{
+ AccessToken: session.Token,
+ TokenType: model.ACCESS_TOKEN_TYPE,
+ ExpiresIn: int32(*utils.Cfg.ServiceSettings.SessionLengthSSOInDays * 60 * 60 * 24),
+ }
+
+ return accessRsp, nil
+}
+
+func GetOAuthLoginEndpoint(service, teamId, redirectTo, loginHint string) (string, *model.AppError) {
+ stateProps := map[string]string{}
+ stateProps["action"] = model.OAUTH_ACTION_LOGIN
+ if len(teamId) != 0 {
+ stateProps["team_id"] = teamId
+ }
+
+ if len(redirectTo) != 0 {
+ stateProps["redirect_to"] = redirectTo
+ }
+
+ if authUrl, err := GetAuthorizationCode(service, stateProps, loginHint); err != nil {
+ return "", err
+ } else {
+ return authUrl, nil
+ }
+}
+
+func GetOAuthSignupEndpoint(service, teamId string) (string, *model.AppError) {
+ stateProps := map[string]string{}
+ stateProps["action"] = model.OAUTH_ACTION_SIGNUP
+ if len(teamId) != 0 {
+ stateProps["team_id"] = teamId
+ }
+
+ if authUrl, err := GetAuthorizationCode(service, stateProps, ""); err != nil {
+ return "", err
+ } else {
+ return authUrl, nil
+ }
+}
+
+func GetAuthorizedAppsForUser(userId string, page, perPage int) ([]*model.OAuthApp, *model.AppError) {
+ if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
+ return nil, model.NewAppError("GetAuthorizedAppsForUser", "api.oauth.allow_oauth.turn_off.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ if result := <-Srv.Store.OAuth().GetAuthorizedApps(userId, page*perPage, perPage); result.Err != nil {
+ return nil, result.Err
+ } else {
+ apps := result.Data.([]*model.OAuthApp)
+ for k, a := range apps {
+ a.Sanitize()
+ apps[k] = a
+ }
+
+ return apps, nil
+ }
+}
+
+func DeauthorizeOAuthAppForUser(userId, appId string) *model.AppError {
+ if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
+ return model.NewAppError("DeauthorizeOAuthAppForUser", "api.oauth.allow_oauth.turn_off.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ // revoke app sessions
+ if result := <-Srv.Store.OAuth().GetAccessDataByUserForApp(userId, appId); result.Err != nil {
+ return result.Err
+ } else {
+ accessData := result.Data.([]*model.AccessData)
+
+ for _, a := range accessData {
+ if err := RevokeAccessToken(a.Token); err != nil {
+ return err
+ }
+
+ if rad := <-Srv.Store.OAuth().RemoveAccessData(a.Token); rad.Err != nil {
+ return rad.Err
+ }
+ }
+ }
+
+ // Deauthorize the app
+ if err := (<-Srv.Store.Preference().Delete(userId, model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP, appId)).Err; err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func RegenerateOAuthAppSecret(app *model.OAuthApp) (*model.OAuthApp, *model.AppError) {
+ if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
+ return nil, model.NewAppError("RegenerateOAuthAppSecret", "api.oauth.allow_oauth.turn_off.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ app.ClientSecret = model.NewId()
+ if update := <-Srv.Store.OAuth().UpdateApp(app); update.Err != nil {
+ return nil, update.Err
+ }
+
+ return app, nil
+}
+
+func RevokeAccessToken(token string) *model.AppError {
session, _ := GetSession(token)
schan := Srv.Store.Session().Remove(token)
@@ -32,3 +404,276 @@ func RevokeAccessToken(token string) *model.AppError {
return nil
}
+
+func CompleteOAuth(service string, body io.ReadCloser, teamId string, props map[string]string) (*model.User, *model.AppError) {
+ defer func() {
+ ioutil.ReadAll(body)
+ body.Close()
+ }()
+
+ action := props["action"]
+
+ switch action {
+ case model.OAUTH_ACTION_SIGNUP:
+ return CreateOAuthUser(service, body, teamId)
+ case model.OAUTH_ACTION_LOGIN:
+ return LoginByOAuth(service, body, teamId)
+ case model.OAUTH_ACTION_EMAIL_TO_SSO:
+ return CompleteSwitchWithOAuth(service, body, props["email"])
+ case model.OAUTH_ACTION_SSO_TO_EMAIL:
+ return LoginByOAuth(service, body, teamId)
+ default:
+ return LoginByOAuth(service, body, teamId)
+ }
+}
+
+func LoginByOAuth(service string, userData io.Reader, teamId string) (*model.User, *model.AppError) {
+ buf := bytes.Buffer{}
+ buf.ReadFrom(userData)
+
+ authData := ""
+ provider := einterfaces.GetOauthProvider(service)
+ if provider == nil {
+ return nil, model.NewAppError("LoginByOAuth", "api.user.login_by_oauth.not_available.app_error",
+ map[string]interface{}{"Service": strings.Title(service)}, "", http.StatusNotImplemented)
+ } else {
+ authData = provider.GetAuthDataFromJson(bytes.NewReader(buf.Bytes()))
+ }
+
+ if len(authData) == 0 {
+ return nil, model.NewAppError("LoginByOAuth", "api.user.login_by_oauth.parse.app_error",
+ map[string]interface{}{"Service": service}, "", http.StatusBadRequest)
+ }
+
+ user, err := GetUserByAuth(&authData, service)
+ if err != nil {
+ if err.Id == store.MISSING_AUTH_ACCOUNT_ERROR {
+ return CreateOAuthUser(service, bytes.NewReader(buf.Bytes()), teamId)
+ }
+ return nil, err
+ }
+
+ if err = UpdateOAuthUserAttrs(bytes.NewReader(buf.Bytes()), user, provider, service); err != nil {
+ return nil, err
+ }
+
+ if len(teamId) > 0 {
+ err = AddUserToTeamByTeamId(teamId, user)
+ }
+
+ if err != nil {
+ return nil, err
+ }
+
+ return user, nil
+}
+
+func CompleteSwitchWithOAuth(service string, userData io.ReadCloser, email string) (*model.User, *model.AppError) {
+ authData := ""
+ ssoEmail := ""
+ provider := einterfaces.GetOauthProvider(service)
+ if provider == nil {
+ return nil, model.NewAppError("CompleteSwitchWithOAuth", "api.user.complete_switch_with_oauth.unavailable.app_error",
+ map[string]interface{}{"Service": strings.Title(service)}, "", http.StatusNotImplemented)
+ } else {
+ ssoUser := provider.GetUserFromJson(userData)
+ ssoEmail = ssoUser.Email
+
+ if ssoUser.AuthData != nil {
+ authData = *ssoUser.AuthData
+ }
+ }
+
+ if len(authData) == 0 {
+ return nil, model.NewAppError("CompleteSwitchWithOAuth", "api.user.complete_switch_with_oauth.parse.app_error",
+ map[string]interface{}{"Service": service}, "", http.StatusBadRequest)
+ }
+
+ if len(email) == 0 {
+ return nil, model.NewAppError("CompleteSwitchWithOAuth", "api.user.complete_switch_with_oauth.blank_email.app_error", nil, "", http.StatusBadRequest)
+ }
+
+ var user *model.User
+ if result := <-Srv.Store.User().GetByEmail(email); result.Err != nil {
+ return nil, result.Err
+ } else {
+ user = result.Data.(*model.User)
+ }
+
+ if err := RevokeAllSessions(user.Id); err != nil {
+ return nil, err
+ }
+
+ if result := <-Srv.Store.User().UpdateAuthData(user.Id, service, &authData, ssoEmail, true); result.Err != nil {
+ return nil, result.Err
+ }
+
+ go func() {
+ if err := SendSignInChangeEmail(user.Email, strings.Title(service)+" SSO", user.Locale, utils.GetSiteURL()); err != nil {
+ l4g.Error(err.Error())
+ }
+ }()
+
+ return user, nil
+}
+
+func GetAuthorizationCode(service string, props map[string]string, loginHint string) (string, *model.AppError) {
+ sso := utils.Cfg.GetSSOService(service)
+ if sso != nil && !sso.Enable {
+ return "", model.NewAppError("GetAuthorizationCode", "api.user.get_authorization_code.unsupported.app_error", nil, "service="+service, http.StatusNotImplemented)
+ }
+
+ clientId := sso.Id
+ endpoint := sso.AuthEndpoint
+ scope := sso.Scope
+
+ props["hash"] = model.HashPassword(clientId)
+ state := b64.StdEncoding.EncodeToString([]byte(model.MapToJson(props)))
+
+ redirectUri := utils.GetSiteURL() + "/signup/" + service + "/complete"
+
+ authUrl := endpoint + "?response_type=code&client_id=" + clientId + "&redirect_uri=" + url.QueryEscape(redirectUri) + "&state=" + url.QueryEscape(state)
+
+ if len(scope) > 0 {
+ authUrl += "&scope=" + utils.UrlEncode(scope)
+ }
+
+ if len(loginHint) > 0 {
+ authUrl += "&login_hint=" + utils.UrlEncode(loginHint)
+ }
+
+ return authUrl, nil
+}
+
+func AuthorizeOAuthUser(service, code, state, redirectUri string) (io.ReadCloser, string, map[string]string, *model.AppError) {
+ sso := utils.Cfg.GetSSOService(service)
+ if sso == nil || !sso.Enable {
+ return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.unsupported.app_error", nil, "service="+service)
+ }
+
+ stateStr := ""
+ if b, err := b64.StdEncoding.DecodeString(state); err != nil {
+ return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, err.Error())
+ } else {
+ stateStr = string(b)
+ }
+
+ stateProps := model.MapFromJson(strings.NewReader(stateStr))
+
+ if !model.ComparePassword(stateProps["hash"], sso.Id) {
+ return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, "")
+ }
+
+ teamId := stateProps["team_id"]
+
+ p := url.Values{}
+ p.Set("client_id", sso.Id)
+ p.Set("client_secret", sso.Secret)
+ p.Set("code", code)
+ p.Set("grant_type", model.ACCESS_TOKEN_GRANT_TYPE)
+ p.Set("redirect_uri", redirectUri)
+
+ tr := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
+ }
+ client := &http.Client{Transport: tr}
+ req, _ := http.NewRequest("POST", sso.TokenEndpoint, strings.NewReader(p.Encode()))
+
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ req.Header.Set("Accept", "application/json")
+
+ var ar *model.AccessResponse
+ var respBody []byte
+ if resp, err := client.Do(req); err != nil {
+ return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.token_failed.app_error", nil, err.Error())
+ } else {
+ ar = model.AccessResponseFromJson(resp.Body)
+ defer func() {
+ ioutil.ReadAll(resp.Body)
+ resp.Body.Close()
+ }()
+ if ar == nil {
+ return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_response.app_error", nil, "")
+ }
+ }
+
+ if strings.ToLower(ar.TokenType) != model.ACCESS_TOKEN_TYPE {
+ return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_token.app_error", nil, "token_type="+ar.TokenType+", response_body="+string(respBody))
+ }
+
+ if len(ar.AccessToken) == 0 {
+ return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.missing.app_error", nil, "")
+ }
+
+ p = url.Values{}
+ p.Set("access_token", ar.AccessToken)
+ req, _ = http.NewRequest("GET", sso.UserApiEndpoint, strings.NewReader(""))
+
+ req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
+ req.Header.Set("Accept", "application/json")
+ req.Header.Set("Authorization", "Bearer "+ar.AccessToken)
+
+ if resp, err := client.Do(req); err != nil {
+ return nil, "", nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.service.app_error",
+ map[string]interface{}{"Service": service}, err.Error())
+ } else {
+ return resp.Body, teamId, stateProps, nil
+ }
+
+}
+
+func SwitchEmailToOAuth(email, password, code, service string) (string, *model.AppError) {
+ var user *model.User
+ var err *model.AppError
+ if user, err = GetUserByEmail(email); err != nil {
+ return "", err
+ }
+
+ if err := CheckPasswordAndAllCriteria(user, password, code); err != nil {
+ return "", err
+ }
+
+ stateProps := map[string]string{}
+ stateProps["action"] = model.OAUTH_ACTION_EMAIL_TO_SSO
+ stateProps["email"] = email
+
+ if service == model.USER_AUTH_SERVICE_SAML {
+ return utils.GetSiteURL() + "/login/sso/saml?action=" + model.OAUTH_ACTION_EMAIL_TO_SSO + "&email=" + email, nil
+ } else {
+ if authUrl, err := GetAuthorizationCode(service, stateProps, ""); err != nil {
+ return "", err
+ } else {
+ return authUrl, nil
+ }
+ }
+}
+
+func SwitchOAuthToEmail(email, password, requesterId string) (string, *model.AppError) {
+ var user *model.User
+ var err *model.AppError
+ if user, err = GetUserByEmail(email); err != nil {
+ return "", err
+ }
+
+ if user.Id != requesterId {
+ return "", model.NewAppError("SwitchOAuthToEmail", "api.user.oauth_to_email.context.app_error", nil, "", http.StatusForbidden)
+ }
+
+ if err := UpdatePassword(user, password); err != nil {
+ return "", err
+ }
+
+ T := utils.GetUserTranslations(user.Locale)
+
+ go func() {
+ if err := SendSignInChangeEmail(user.Email, T("api.templates.signin_change_email.body.method_email"), user.Locale, utils.GetSiteURL()); err != nil {
+ l4g.Error(err.Error())
+ }
+ }()
+
+ if err := RevokeAllSessions(requesterId); err != nil {
+ return "", err
+ }
+
+ return "/login?extra=signin_change", nil
+}
diff --git a/app/oauth_test.go b/app/oauth_test.go
index 3ca3a2d4a..9e8fdfc7d 100644
--- a/app/oauth_test.go
+++ b/app/oauth_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/post.go b/app/post.go
index 7f38a9bd2..bf61bafb2 100644
--- a/app/post.go
+++ b/app/post.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
@@ -402,6 +402,14 @@ func GetFlaggedPostsForTeam(userId, teamId string, offset int, limit int) (*mode
}
}
+func GetFlaggedPostsForChannel(userId, channelId string, offset int, limit int) (*model.PostList, *model.AppError) {
+ if result := <-Srv.Store.Post().GetFlaggedPostsForChannel(userId, channelId, offset, limit); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(*model.PostList), nil
+ }
+}
+
func GetPermalinkPost(postId string, userId string) (*model.PostList, *model.AppError) {
if result := <-Srv.Store.Post().Get(postId); result.Err != nil {
return nil, result.Err
@@ -559,13 +567,13 @@ func GetOpenGraphMetadata(url string) *opengraph.OpenGraph {
res, err := httpClient.Get(url)
if err != nil {
- l4g.Error(err.Error())
+ l4g.Error("GetOpenGraphMetadata request failed for url=%v with err=%v", url, err.Error())
return og
}
defer CloseBody(res)
if err := og.ProcessHTML(res.Body); err != nil {
- l4g.Error(err.Error())
+ l4g.Error("GetOpenGraphMetadata processing failed for url=%v with err=%v", url, err.Error())
}
return og
diff --git a/app/preference.go b/app/preference.go
index ff251fb16..793f1802b 100644
--- a/app/preference.go
+++ b/app/preference.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/reaction.go b/app/reaction.go
new file mode 100644
index 000000000..cc31018ec
--- /dev/null
+++ b/app/reaction.go
@@ -0,0 +1,16 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "github.com/mattermost/platform/model"
+)
+
+func GetReactionsForPost(postId string) ([]*model.Reaction, *model.AppError) {
+ if result := <-Srv.Store.Reaction().GetForPost(postId, true); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.([]*model.Reaction), nil
+ }
+}
diff --git a/app/saml.go b/app/saml.go
index e2bf4ccb2..8a6e6f16c 100644
--- a/app/saml.go
+++ b/app/saml.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/security_update_check.go b/app/security_update_check.go
index 2b000f2b2..12014bdf3 100644
--- a/app/security_update_check.go
+++ b/app/security_update_check.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/server.go b/app/server.go
index 972c91ea3..a757e184e 100644
--- a/app/server.go
+++ b/app/server.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/session.go b/app/session.go
index 9e4fda4bd..0df643743 100644
--- a/app/session.go
+++ b/app/session.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/session_test.go b/app/session_test.go
index aea31cf86..b3cd9fd57 100644
--- a/app/session_test.go
+++ b/app/session_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/slackimport.go b/app/slackimport.go
index 3e226203b..71f16c874 100644
--- a/app/slackimport.go
+++ b/app/slackimport.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/slackimport_test.go b/app/slackimport_test.go
index 6db6adf2d..87de597ca 100644
--- a/app/slackimport_test.go
+++ b/app/slackimport_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/status.go b/app/status.go
index f6565b7d2..a3b921700 100644
--- a/app/status.go
+++ b/app/status.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/team.go b/app/team.go
index 12c970665..d4e6d6308 100644
--- a/app/team.go
+++ b/app/team.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
@@ -6,6 +6,7 @@ package app
import (
"fmt"
"net/http"
+ "net/url"
"strconv"
"strings"
@@ -747,3 +748,33 @@ func GetTeamStats(teamId string) (*model.TeamStats, *model.AppError) {
return stats, nil
}
+
+func GetTeamIdFromQuery(query url.Values) (string, *model.AppError) {
+ hash := query.Get("h")
+ inviteId := query.Get("id")
+
+ if len(hash) > 0 {
+ data := query.Get("d")
+ props := model.MapFromJson(strings.NewReader(data))
+
+ if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) {
+ return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.invalid_link.app_error", nil, "", http.StatusBadRequest)
+ }
+
+ t, err := strconv.ParseInt(props["time"], 10, 64)
+ if err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours
+ return "", model.NewAppError("GetTeamIdFromQuery", "api.oauth.singup_with_oauth.expired_link.app_error", nil, "", http.StatusBadRequest)
+ }
+
+ return props["id"], nil
+ } else if len(inviteId) > 0 {
+ if result := <-Srv.Store.Team().GetByInviteId(inviteId); result.Err != nil {
+ // soft fail, so we still create user but don't auto-join team
+ l4g.Error("%v", result.Err)
+ } else {
+ return result.Data.(*model.Team).Id, nil
+ }
+ }
+
+ return "", nil
+}
diff --git a/app/team_test.go b/app/team_test.go
index 86a383a39..f2356d562 100644
--- a/app/team_test.go
+++ b/app/team_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/user.go b/app/user.go
index 99e9d46a3..e339dfd5b 100644
--- a/app/user.go
+++ b/app/user.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
@@ -186,7 +186,9 @@ func CreateUser(user *model.User) (*model.User, *model.AppError) {
}
}
- user.Locale = *utils.Cfg.LocalizationSettings.DefaultClientLocale
+ if _, ok := utils.GetSupportedLocales()[user.Locale]; !ok {
+ user.Locale = *utils.Cfg.LocalizationSettings.DefaultClientLocale
+ }
if ruser, err := createUser(user); err != nil {
return nil, err
diff --git a/app/user_test.go b/app/user_test.go
index ff9e4d500..4cd26e729 100644
--- a/app/user_test.go
+++ b/app/user_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/web_conn.go b/app/web_conn.go
index 8d604ff3e..000704791 100644
--- a/app/web_conn.go
+++ b/app/web_conn.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/web_hub.go b/app/web_hub.go
index f65683f70..da2a41ec4 100644
--- a/app/web_hub.go
+++ b/app/web_hub.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/webhook.go b/app/webhook.go
index 0ec06365d..e095c1b80 100644
--- a/app/webhook.go
+++ b/app/webhook.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/webrtc.go b/app/webrtc.go
new file mode 100644
index 000000000..6692fff60
--- /dev/null
+++ b/app/webrtc.go
@@ -0,0 +1,87 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package app
+
+import (
+ "crypto/hmac"
+ "crypto/sha1"
+ "crypto/tls"
+ "encoding/base64"
+ "net/http"
+ "strconv"
+ "strings"
+ "time"
+
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
+)
+
+func GetWebrtcInfoForSession(sessionId string) (*model.WebrtcInfoResponse, *model.AppError) {
+ token, err := GetWebrtcToken(sessionId)
+ if err != nil {
+ return nil, err
+ }
+
+ result := &model.WebrtcInfoResponse{
+ Token: token,
+ GatewayUrl: *utils.Cfg.WebrtcSettings.GatewayWebsocketUrl,
+ }
+
+ if len(*utils.Cfg.WebrtcSettings.StunURI) > 0 {
+ result.StunUri = *utils.Cfg.WebrtcSettings.StunURI
+ }
+
+ if len(*utils.Cfg.WebrtcSettings.TurnURI) > 0 {
+ timestamp := strconv.FormatInt(utils.EndOfDay(time.Now().AddDate(0, 0, 1)).Unix(), 10)
+ username := timestamp + ":" + *utils.Cfg.WebrtcSettings.TurnUsername
+
+ result.TurnUri = *utils.Cfg.WebrtcSettings.TurnURI
+ result.TurnPassword = GenerateTurnPassword(username, *utils.Cfg.WebrtcSettings.TurnSharedKey)
+ result.TurnUsername = username
+ }
+
+ return result, nil
+}
+
+func GetWebrtcToken(sessionId string) (string, *model.AppError) {
+ if !*utils.Cfg.WebrtcSettings.Enable {
+ return "", model.NewAppError("WebRTC.getWebrtcToken", "api.webrtc.disabled.app_error", nil, "", http.StatusNotImplemented)
+ }
+
+ token := base64.StdEncoding.EncodeToString([]byte(sessionId))
+
+ data := make(map[string]string)
+ data["janus"] = "add_token"
+ data["token"] = token
+ data["transaction"] = model.NewId()
+ data["admin_secret"] = *utils.Cfg.WebrtcSettings.GatewayAdminSecret
+
+ rq, _ := http.NewRequest("POST", *utils.Cfg.WebrtcSettings.GatewayAdminUrl, strings.NewReader(model.MapToJson(data)))
+ rq.Header.Set("Content-Type", "application/json")
+
+ tr := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: *utils.Cfg.ServiceSettings.EnableInsecureOutgoingConnections},
+ }
+ httpClient := &http.Client{Transport: tr}
+ if rp, err := httpClient.Do(rq); err != nil {
+ return "", model.NewAppError("WebRTC.Token", "model.client.connecting.app_error", nil, err.Error(), http.StatusInternalServerError)
+ } else if rp.StatusCode >= 300 {
+ defer CloseBody(rp)
+ return "", model.AppErrorFromJson(rp.Body)
+ } else {
+ janusResponse := model.GatewayResponseFromJson(rp.Body)
+ if janusResponse.Status != "success" {
+ return "", model.NewAppError("getWebrtcToken", "api.webrtc.register_token.app_error", nil, "", http.StatusInternalServerError)
+ }
+ }
+
+ return token, nil
+}
+
+func GenerateTurnPassword(username string, secret string) string {
+ key := []byte(secret)
+ h := hmac.New(sha1.New, key)
+ h.Write([]byte(username))
+ return base64.StdEncoding.EncodeToString(h.Sum(nil))
+}
diff --git a/app/websocket_router.go b/app/websocket_router.go
index 4569134b0..84806b5cf 100644
--- a/app/websocket_router.go
+++ b/app/websocket_router.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/app/webtrc.go b/app/webtrc.go
index b526c96a6..a2ead21ab 100644
--- a/app/webtrc.go
+++ b/app/webtrc.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package app
diff --git a/build/MIT-COMPILED-LICENSE.md b/build/MIT-COMPILED-LICENSE.md
index 73a2ce215..a5525d50f 100644
--- a/build/MIT-COMPILED-LICENSE.md
+++ b/build/MIT-COMPILED-LICENSE.md
@@ -2,7 +2,7 @@ Mattermost MIT Compiled License
**Note: this license does not cover source code, for information on source code licensing see LICENSE.txt in the Mattermost source code.
-Copyright (c) 2016 Mattermost, Inc.
+Copyright (c) 2016-present Mattermost, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
diff --git a/cmd/platform/channel.go b/cmd/platform/channel.go
index cd8df0873..7419a0492 100644
--- a/cmd/platform/channel.go
+++ b/cmd/platform/channel.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package main
diff --git a/cmd/platform/channelargs.go b/cmd/platform/channelargs.go
index d64db10bd..02ee1b6ab 100644
--- a/cmd/platform/channelargs.go
+++ b/cmd/platform/channelargs.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package main
diff --git a/cmd/platform/channelargs_test.go.disabled b/cmd/platform/channelargs_test.go.disabled
new file mode 100644
index 000000000..5447a061d
--- /dev/null
+++ b/cmd/platform/channelargs_test.go.disabled
@@ -0,0 +1,106 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package main
+
+import (
+ "testing"
+
+ "github.com/mattermost/platform/app"
+ "github.com/mattermost/platform/model"
+)
+
+func TestParseChannelArg(t *testing.T) {
+ if team, channel := parseChannelArg("channel"); team != "" {
+ t.Fatal("got incorrect team", team)
+ } else if channel != "channel" {
+ t.Fatal("got incorrect channel", channel)
+ }
+
+ if team, channel := parseChannelArg("team:channel"); team != "team" {
+ t.Fatal("got incorrect team", team)
+ } else if channel != "channel" {
+ t.Fatal("got incorrect channel", channel)
+ }
+}
+
+func TestGetChannelFromChannelArg(t *testing.T) {
+ th := app.Setup().InitBasic()
+
+ team := th.BasicTeam
+ channel := th.BasicChannel
+
+ if found := getChannelFromChannelArg(""); found != nil {
+ t.Fatal("shoudn't have gotten a channel", found)
+ }
+
+ if found := getChannelFromChannelArg(channel.Id); found == nil || found.Id != channel.Id {
+ t.Fatal("got incorrect channel", found)
+ }
+
+ if found := getChannelFromChannelArg(model.NewId()); found != nil {
+ t.Fatal("shouldn't have gotten a channel that doesn't exist", found)
+ }
+
+ if found := getChannelFromChannelArg(channel.Name); found != nil {
+ t.Fatal("shouldn't have gotten a channel by name without team", found)
+ }
+
+ if found := getChannelFromChannelArg(team.Id + ":" + channel.Name); found == nil || found.Id != channel.Id {
+ t.Fatal("got incorrect channel", found)
+ }
+
+ if found := getChannelFromChannelArg(team.Name + ":" + channel.Name); found == nil || found.Id != channel.Id {
+ t.Fatal("got incorrect channel", found)
+ }
+
+ if found := getChannelFromChannelArg(team.Name + ":" + channel.Id); found == nil || found.Id != channel.Id {
+ t.Fatal("got incorrect channel", found)
+ }
+
+ if found := getChannelFromChannelArg("notateam" + ":" + channel.Name); found != nil {
+ t.Fatal("shouldn't have gotten a channel by name on incorrect team", found)
+ }
+
+ if found := getChannelFromChannelArg(team.Name + ":" + "notachannel"); found != nil {
+ t.Fatal("shouldn't have gotten a channel that doesn't exist", found)
+ }
+}
+
+func TestGetChannelsFromChannelArg(t *testing.T) {
+ th := app.Setup().InitBasic()
+
+ team := th.BasicTeam
+ channel := th.BasicChannel
+ channel2 := th.CreateChannel(team)
+
+ if found := getChannelsFromChannelArgs([]string{}); len(found) != 0 {
+ t.Fatal("shoudn't have gotten any channels", found)
+ }
+
+ if found := getChannelsFromChannelArgs([]string{channel.Id}); len(found) == 1 && found[0].Id != channel.Id {
+ t.Fatal("got incorrect channel", found)
+ }
+
+ if found := getChannelsFromChannelArgs([]string{team.Name + ":" + channel2.Name}); len(found) == 1 && found[0].Id != channel2.Id {
+ t.Fatal("got incorrect channel", found)
+ }
+
+ if found := getChannelsFromChannelArgs([]string{team.Name + ":" + channel.Name, team.Name + ":" + channel2.Name}); len(found) != 2 {
+ t.Fatal("got incorrect number of channels", found)
+ } else if !(found[0].Id == channel.Id && found[1].Id == channel2.Id) && !(found[1].Id == channel.Id && found[0].Id == channel2.Id) {
+ t.Fatal("got incorrect channels", found[0], found[1])
+ }
+
+ if found := getChannelsFromChannelArgs([]string{channel.Id, channel2.Id}); len(found) != 2 {
+ t.Fatal("got incorrect number of channels", found)
+ } else if !(found[0].Id == channel.Id && found[1].Id == channel2.Id) && !(found[1].Id == channel.Id && found[0].Id == channel2.Id) {
+ t.Fatal("got incorrect channels", found[0], found[1])
+ }
+
+ if found := getChannelsFromChannelArgs([]string{channel.Id, team.Name + ":" + channel2.Name}); len(found) != 2 {
+ t.Fatal("got incorrect number of channels", found)
+ } else if !(found[0].Id == channel.Id && found[1].Id == channel2.Id) && !(found[1].Id == channel.Id && found[0].Id == channel2.Id) {
+ t.Fatal("got incorrect channels", found[0], found[1])
+ }
+}
diff --git a/cmd/platform/cmdtestlib.go b/cmd/platform/cmdtestlib.go
new file mode 100644
index 000000000..16bfc2b21
--- /dev/null
+++ b/cmd/platform/cmdtestlib.go
@@ -0,0 +1,45 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package main
+
+import (
+ "bytes"
+ "strings"
+
+ "github.com/spf13/cobra"
+ "github.com/spf13/pflag"
+)
+
+func runCommand(argString string) error {
+ err, _ := runCommandWithOutput(argString)
+
+ return err
+}
+
+func runCommandWithOutput(argString string) (error, string) {
+ // Set arguments on the root command
+ rootCmd.SetArgs(strings.Split(argString, " "))
+ defer rootCmd.SetArgs([]string{})
+
+ output := new(bytes.Buffer)
+ rootCmd.SetOutput(output)
+ defer rootCmd.SetOutput(nil)
+
+ // Executing the root command will call the necessary subcommand
+ cmd, err := rootCmd.ExecuteC()
+
+ // And clear the arguments on the subcommand that was actually called since they'd otherwise
+ // be used on the next call to this command
+ clearArgs(cmd)
+
+ return err, output.String()
+}
+
+func clearArgs(command *cobra.Command) {
+ command.Flags().VisitAll(clearFlag)
+}
+
+func clearFlag(flag *pflag.Flag) {
+ flag.Value.Set(flag.DefValue)
+}
diff --git a/cmd/platform/config.go b/cmd/platform/config.go
new file mode 100644
index 000000000..d66129de4
--- /dev/null
+++ b/cmd/platform/config.go
@@ -0,0 +1,66 @@
+// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+package main
+
+import (
+ "encoding/json"
+ "errors"
+ "github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
+ "github.com/spf13/cobra"
+ "os"
+)
+
+var configCmd = &cobra.Command{
+ Use: "config",
+ Short: "Configuration",
+}
+
+var validateConfigCmd = &cobra.Command{
+ Use: "validate",
+ Short: "Validate config file",
+ Run: configValidateCmdF,
+}
+
+func init() {
+ configCmd.AddCommand(
+ validateConfigCmd,
+ )
+}
+
+func configValidateCmdF(cmd *cobra.Command, args []string) {
+ utils.TranslationsPreInit()
+ filePath, err := cmd.Flags().GetString("config")
+ if err != nil {
+ CommandPrintErrorln(err)
+ return
+ }
+
+ filePath = utils.FindConfigFile(filePath)
+
+ file, err := os.Open(filePath)
+ if err != nil {
+ CommandPrintErrorln(err)
+ return
+ }
+
+ decoder := json.NewDecoder(file)
+ config := model.Config{}
+ err = decoder.Decode(&config)
+ if err != nil {
+ CommandPrintErrorln(err)
+ return
+ }
+
+ if _, err := file.Stat(); err != nil {
+ CommandPrintErrorln(err)
+ return
+ }
+
+ if err := config.IsValid(); err != nil {
+ CommandPrintErrorln(errors.New(utils.T(err.Id)))
+ return
+ }
+
+ CommandPrettyPrintln("The document is valid")
+}
diff --git a/cmd/platform/import.go b/cmd/platform/import.go
index d0b2de162..9cee26a52 100644
--- a/cmd/platform/import.go
+++ b/cmd/platform/import.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package main
diff --git a/cmd/platform/init.go b/cmd/platform/init.go
index 0458e7a1c..7d01eb890 100644
--- a/cmd/platform/init.go
+++ b/cmd/platform/init.go
@@ -20,6 +20,7 @@ func doLoadConfig(filename string) (err string) {
utils.LoadConfig(filename)
utils.InitializeConfigWatch()
utils.EnableConfigWatch()
+
return ""
}
diff --git a/cmd/platform/ldap.go b/cmd/platform/ldap.go
index 8f3aa0c81..f578ec3e2 100644
--- a/cmd/platform/ldap.go
+++ b/cmd/platform/ldap.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package main
diff --git a/cmd/platform/license.go b/cmd/platform/license.go
index dedc4d306..91dc3bfba 100644
--- a/cmd/platform/license.go
+++ b/cmd/platform/license.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package main
diff --git a/cmd/platform/mattermost.go b/cmd/platform/mattermost.go
index fc2f1d4c2..a4e44e016 100644
--- a/cmd/platform/mattermost.go
+++ b/cmd/platform/mattermost.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package main
@@ -23,21 +23,25 @@ import (
//ENTERPRISE_IMPORTS
func main() {
- var rootCmd = &cobra.Command{
- Use: "platform",
- Short: "Open source, self-hosted Slack-alternative",
- Long: `Mattermost offers workplace messaging across web, PC and phones with archiving, search and integration with your existing systems. Documentation available at https://docs.mattermost.com`,
- RunE: runServerCmd,
+ if err := rootCmd.Execute(); err != nil {
+ os.Exit(1)
}
+}
+
+func init() {
rootCmd.PersistentFlags().StringP("config", "c", "config.json", "Configuration file to use.")
+ rootCmd.PersistentFlags().Bool("disableconfigwatch", false, "When set config.json will not be loaded from disk when the file is changed.")
resetCmd.Flags().Bool("confirm", false, "Confirm you really want to delete everything and a DB backup has been performed.")
- rootCmd.AddCommand(serverCmd, versionCmd, userCmd, teamCmd, licenseCmd, importCmd, resetCmd, channelCmd, rolesCmd, testCmd, ldapCmd)
+ rootCmd.AddCommand(serverCmd, versionCmd, userCmd, teamCmd, licenseCmd, importCmd, resetCmd, channelCmd, rolesCmd, testCmd, ldapCmd, configCmd)
+}
- if err := rootCmd.Execute(); err != nil {
- os.Exit(1)
- }
+var rootCmd = &cobra.Command{
+ Use: "platform",
+ Short: "Open source, self-hosted Slack-alternative",
+ Long: `Mattermost offers workplace messaging across web, PC and phones with archiving, search and integration with your existing systems. Documentation available at https://docs.mattermost.com`,
+ RunE: runServerCmd,
}
var resetCmd = &cobra.Command{
diff --git a/cmd/platform/output.go b/cmd/platform/output.go
index 5b7f91385..e4666910e 100644
--- a/cmd/platform/output.go
+++ b/cmd/platform/output.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package main
diff --git a/cmd/platform/roles.go b/cmd/platform/roles.go
index a65eb2bd6..df4b49436 100644
--- a/cmd/platform/roles.go
+++ b/cmd/platform/roles.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package main
diff --git a/cmd/platform/server.go b/cmd/platform/server.go
index 855cde19a..0d971afb6 100644
--- a/cmd/platform/server.go
+++ b/cmd/platform/server.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package main
@@ -36,6 +36,8 @@ func runServerCmd(cmd *cobra.Command, args []string) error {
return err
}
+ utils.CfgDisableConfigWatch, _ = cmd.Flags().GetBool("disableconfigwatch")
+
runServer(config)
return nil
}
diff --git a/cmd/platform/team.go b/cmd/platform/team.go
index eb2939617..71bcd543c 100644
--- a/cmd/platform/team.go
+++ b/cmd/platform/team.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package main
diff --git a/cmd/platform/teamargs.go b/cmd/platform/teamargs.go
index 506cc88ef..31f7b489e 100644
--- a/cmd/platform/teamargs.go
+++ b/cmd/platform/teamargs.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package main
diff --git a/cmd/platform/teamargs_test.go.disabled b/cmd/platform/teamargs_test.go.disabled
new file mode 100644
index 000000000..573ec8a99
--- /dev/null
+++ b/cmd/platform/teamargs_test.go.disabled
@@ -0,0 +1,58 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package main
+
+import (
+ "testing"
+
+ "github.com/mattermost/platform/app"
+ "github.com/mattermost/platform/model"
+)
+
+func TestGetTeamFromTeamArg(t *testing.T) {
+ th := app.Setup().InitBasic()
+
+ team := th.BasicTeam
+
+ if found := getTeamFromTeamArg(""); found != nil {
+ t.Fatal("shoudn't have gotten a team", found)
+ }
+
+ if found := getTeamFromTeamArg(model.NewId()); found != nil {
+ t.Fatal("shoudn't have gotten a team", found)
+ }
+
+ if found := getTeamFromTeamArg(team.Id); found == nil || found.Id != team.Id {
+ t.Fatal("got incorrect team", found)
+ }
+
+ if found := getTeamFromTeamArg(team.Name); found == nil || found.Id != team.Id {
+ t.Fatal("got incorrect team", found)
+ }
+}
+
+func TestGetTeamsFromTeamArg(t *testing.T) {
+ th := app.Setup().InitBasic()
+
+ team := th.BasicTeam
+ team2 := th.CreateTeam()
+
+ if found := getTeamsFromTeamArgs([]string{}); len(found) != 0 {
+ t.Fatal("shoudn't have gotten any teams", found)
+ }
+
+ if found := getTeamsFromTeamArgs([]string{team.Id}); len(found) == 1 && found[0].Id != team.Id {
+ t.Fatal("got incorrect team", found)
+ }
+
+ if found := getTeamsFromTeamArgs([]string{team2.Name}); len(found) == 1 && found[0].Id != team2.Id {
+ t.Fatal("got incorrect team", found)
+ }
+
+ if found := getTeamsFromTeamArgs([]string{team.Name, team2.Id}); len(found) != 2 {
+ t.Fatal("got incorrect number of teams", found)
+ } else if !(found[0].Id == team.Id && found[1].Id == team2.Id) && !(found[1].Id == team.Id && found[0].Id == team2.Id) {
+ t.Fatal("got incorrect teams", found[0], found[1])
+ }
+}
diff --git a/cmd/platform/test.go b/cmd/platform/test.go
index cd548568f..735261439 100644
--- a/cmd/platform/test.go
+++ b/cmd/platform/test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package main
diff --git a/cmd/platform/user.go b/cmd/platform/user.go
index 41f0b4f66..dc0aa0f71 100644
--- a/cmd/platform/user.go
+++ b/cmd/platform/user.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package main
@@ -40,7 +40,7 @@ var userCreateCmd = &cobra.Command{
Use: "create",
Short: "Create a user",
Long: "Create a user",
- Example: ` user create --email user@example.com --username userexample --password Password1
+ Example: ` user create --email user@example.com --username userexample --password Password1
user create --firstname Joe --system_admin --email joe@example.com --username joe --password Password1`,
RunE: userCreateCmdF,
}
@@ -67,7 +67,7 @@ var resetUserPasswordCmd = &cobra.Command{
var resetUserMfaCmd = &cobra.Command{
Use: "resetmfa [users]",
Short: "Turn off MFA",
- Long: `Turn off multi-factor authentication for a user.
+ Long: `Turn off multi-factor authentication for a user.
If MFA enforcement is enabled, the user will be forced to re-enable MFA as soon as they login.`,
Example: " user resetmfa user@example.com",
RunE: resetUserMfaCmdF,
@@ -94,13 +94,13 @@ var migrateAuthCmd = &cobra.Command{
Short: "Mass migrate user accounts authentication type",
Long: `Migrates accounts from one authentication provider to another. For example, you can upgrade your authentication provider from email to ldap.
-from_auth:
+from_auth:
The authentication service to migrate users accounts from.
- Supported options: email, gitlab, saml.
+ Supported options: email, gitlab, saml.
to_auth:
The authentication service to migrate users to.
- Supported options: ldap.
+ Supported options: ldap.
match_field:
The field that is guaranteed to be the same in both authentication services. For example, if the users emails are consistent set to email.
@@ -119,6 +119,14 @@ var verifyUserCmd = &cobra.Command{
RunE: verifyUserCmdF,
}
+var searchUserCmd = &cobra.Command{
+ Use: "search [users]",
+ Short: "Search for users",
+ Long: "Search for users based on username, email, or user ID.",
+ Example: " user search user1@mail.com user2@mail.com",
+ RunE: searchUserCmdF,
+}
+
func init() {
userCreateCmd.Flags().String("username", "", "Username")
userCreateCmd.Flags().String("email", "", "Email")
@@ -144,6 +152,7 @@ func init() {
deleteAllUsersCmd,
migrateAuthCmd,
verifyUserCmd,
+ searchUserCmd,
)
}
@@ -161,22 +170,26 @@ func userActivateCmdF(cmd *cobra.Command, args []string) error {
func changeUsersActiveStatus(userArgs []string, active bool) {
users := getUsersFromUserArgs(userArgs)
for i, user := range users {
- changeUserActiveStatus(user, userArgs[i], active)
+ err := changeUserActiveStatus(user, userArgs[i], active)
+
+ if err != nil {
+ CommandPrintErrorln(err.Error())
+ }
}
}
-func changeUserActiveStatus(user *model.User, userArg string, activate bool) {
+func changeUserActiveStatus(user *model.User, userArg string, activate bool) error {
if user == nil {
- CommandPrintErrorln("Can't find user '" + userArg + "'")
- return
+ return fmt.Errorf("Can't find user '%v'", userArg)
}
if user.IsLDAPUser() {
- CommandPrintErrorln(utils.T("api.user.update_active.no_deactivate_ldap.app_error"))
- return
+ return errors.New(utils.T("api.user.update_active.no_deactivate_ldap.app_error"))
}
if _, err := app.UpdateActive(user, activate); err != nil {
- CommandPrintErrorln("Unable to change activation status of user: " + userArg)
+ return fmt.Errorf("Unable to change activation status of user: %v", userArg)
}
+
+ return nil
}
func userDeactivateCmdF(cmd *cobra.Command, args []string) error {
@@ -249,20 +262,26 @@ func userInviteCmdF(cmd *cobra.Command, args []string) error {
teams := getTeamsFromTeamArgs(args[1:])
for i, team := range teams {
- inviteUser(email, team, args[i+1])
+ err := inviteUser(email, team, args[i+1])
+
+ if err != nil {
+ CommandPrintErrorln(err.Error())
+ }
}
return nil
}
-func inviteUser(email string, team *model.Team, teamArg string) {
+func inviteUser(email string, team *model.Team, teamArg string) error {
invites := []string{email}
if team == nil {
- CommandPrintErrorln("Can't find team '" + teamArg + "'")
- return
+ return fmt.Errorf("Can't find team '%v'", teamArg)
}
+
app.SendInviteEmails(team, "Administrator", invites, *utils.Cfg.ServiceSettings.SiteURL)
CommandPrettyPrintln("Invites may or may not have been sent.")
+
+ return nil
}
func resetUserPasswordCmdF(cmd *cobra.Command, args []string) error {
@@ -431,3 +450,33 @@ func verifyUserCmdF(cmd *cobra.Command, args []string) error {
return nil
}
+
+func searchUserCmdF(cmd *cobra.Command, args []string) error {
+ initDBCommandContextCobra(cmd)
+ if len(args) < 1 {
+ return errors.New("Enter at least one query.")
+ }
+
+ users := getUsersFromUserArgs(args)
+
+ for i, user := range users {
+ if i > 0 {
+ CommandPrettyPrintln("------------------------------")
+ }
+ if user == nil {
+ CommandPrintErrorln("Unable to find user '" + args[i] + "'")
+ continue
+ }
+
+ CommandPrettyPrintln("id: " + user.Id)
+ CommandPrettyPrintln("username: " + user.Username)
+ CommandPrettyPrintln("nickname: " + user.Nickname)
+ CommandPrettyPrintln("position: " + user.Position)
+ CommandPrettyPrintln("first_name: " + user.FirstName)
+ CommandPrettyPrintln("last_name: " + user.LastName)
+ CommandPrettyPrintln("email: " + user.Email)
+ CommandPrettyPrintln("auth_service: " + user.AuthService)
+ }
+
+ return nil
+}
diff --git a/cmd/platform/user_test.go.disabled b/cmd/platform/user_test.go.disabled
new file mode 100644
index 000000000..4119574f3
--- /dev/null
+++ b/cmd/platform/user_test.go.disabled
@@ -0,0 +1,212 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package main
+
+import (
+ "testing"
+
+ "github.com/mattermost/platform/app"
+ "github.com/mattermost/platform/model"
+)
+
+func TestChangeUserActiveStatus(t *testing.T) {
+ th := app.Setup().InitBasic()
+
+ user := th.BasicUser
+
+ if err := changeUserActiveStatus(nil, "user", false); err == nil {
+ t.Fatal("should've returned error when user doesn't exist")
+ }
+
+ if err := changeUserActiveStatus(user, user.Username, false); err != nil {
+ t.Fatal(err)
+ } else if user, _ = app.GetUser(user.Id); user.DeleteAt == 0 {
+ t.Fatal("should've deactivated user")
+ }
+
+ if err := changeUserActiveStatus(user, user.Username, true); err != nil {
+ t.Fatal(err)
+ } else if user, _ := app.GetUser(user.Id); user.DeleteAt != 0 {
+ t.Fatal("should've activated user")
+ }
+}
+
+func TestChangeUsersActiveStatus(t *testing.T) {
+ th := app.Setup().InitBasic()
+
+ user := th.BasicUser
+ user2 := th.CreateUser()
+
+ changeUsersActiveStatus([]string{user.Username, user2.Id}, false)
+
+ if user, _ = app.GetUser(user.Id); user.DeleteAt == 0 {
+ t.Fatal("should've deactivated user")
+ } else if user2, _ = app.GetUser(user2.Id); user2.DeleteAt == 0 {
+ t.Fatal("should've deactivated user")
+ }
+
+ changeUsersActiveStatus([]string{user.Username, user2.Id}, true)
+
+ if user, _ = app.GetUser(user.Id); user.DeleteAt != 0 {
+ t.Fatal("should've activated user")
+ } else if user2, _ = app.GetUser(user2.Id); user2.DeleteAt != 0 {
+ t.Fatal("should've activated user")
+ }
+}
+
+func TestUserActivateDeactivateCmdF(t *testing.T) {
+ th := app.Setup().InitBasic()
+
+ user := th.BasicUser
+ user2 := th.CreateUser()
+
+ userDeactivateCmdF(userDeactivateCmd, []string{user.Username, user2.Id})
+
+ if user, _ = app.GetUser(user.Id); user.DeleteAt == 0 {
+ t.Fatal("should've deactivated user")
+ } else if user2, _ = app.GetUser(user2.Id); user2.DeleteAt == 0 {
+ t.Fatal("should've deactivated user")
+ }
+
+ userActivateCmdF(userActivateCmd, []string{user.Username, user2.Id})
+
+ if user, _ = app.GetUser(user.Id); user.DeleteAt != 0 {
+ t.Fatal("should've activated user")
+ } else if user2, _ = app.GetUser(user2.Id); user2.DeleteAt != 0 {
+ t.Fatal("should've activated user")
+ }
+}
+
+func TestUserActivateDeactivateCmd(t *testing.T) {
+ th := app.Setup().InitBasic()
+
+ user := th.BasicUser
+ user2 := th.CreateUser()
+
+ if err := runCommand("user deactivate " + user.Username + " " + user2.Id); err != nil {
+ t.Fatal(err)
+ } else if user, _ = app.GetUser(user.Id); user.DeleteAt == 0 {
+ t.Fatal("should've deactivated user")
+ } else if user2, _ = app.GetUser(user2.Id); user2.DeleteAt == 0 {
+ t.Fatal("should've deactivated user")
+ }
+
+ if err := runCommand("user activate " + user.Id + " " + user2.Username); err != nil {
+ t.Fatal(err)
+ } else if user, _ = app.GetUser(user.Id); user.DeleteAt != 0 {
+ t.Fatal("should've activated user")
+ } else if user2, _ = app.GetUser(user2.Id); user2.DeleteAt != 0 {
+ t.Fatal("should've activated user")
+ }
+}
+
+func TestUserCreateCmd(t *testing.T) {
+ th := app.Setup().InitBasic()
+
+ if err := runCommand("user create"); err == nil {
+ t.Fatal("should've failed without any arguments")
+ }
+
+ username := th.MakeUsername()
+ email := th.MakeEmail()
+ if err := runCommand("user create --username " + username + " --email " + email + " --password " + model.NewId()); err != nil {
+ t.Fatal(err)
+ } else if user, err := app.GetUserByUsername(username); err != nil {
+ t.Fatal(err.Message)
+ } else if user.Username != username {
+ t.Fatal("should've set correct username")
+ } else if user.Email != email {
+ t.Fatal("should've set correct email")
+ }
+
+ username = th.MakeUsername()
+ nickname := model.NewId()
+ firstName := model.NewId()
+ lastName := model.NewId()
+ locale := "fr"
+ if err := runCommand("user create --username " + username + " --email " + th.MakeEmail() + " --password " + model.NewId() +
+ " --nickname " + nickname + " --firstname " + firstName + " --lastname " + lastName + " --locale " + locale); err != nil {
+ t.Fatal(err)
+ } else if user, err := app.GetUserByUsername(username); err != nil {
+ t.Fatal(err)
+ } else if user.Nickname != nickname {
+ t.Fatal("should've set correct nickname")
+ } else if user.FirstName != firstName {
+ t.Fatal("should've set correct first name")
+ } else if user.LastName != lastName {
+ t.Fatal("should've set correct last name")
+ } else if user.Locale != locale {
+ t.Fatal("should've set correct locale", user.Locale)
+ } else if user.Roles != "system_user" {
+ t.Fatal("should've set correct roles for user")
+ }
+
+ username = th.MakeUsername()
+ if err := runCommand("user create --username " + username + " --email " + th.MakeEmail() + " --password " + model.NewId() + " --system_admin"); err != nil {
+ t.Fatal(err)
+ } else if user, err := app.GetUserByUsername(username); err != nil {
+ t.Fatal(err)
+ } else if user.Roles != "system_user system_admin" {
+ t.Fatal("should've set correct roles for system admin")
+ }
+
+ if err := runCommand("user create --email " + th.MakeEmail() + " --password " + model.NewId()); err == nil {
+ t.Fatal("should've failed without username")
+ }
+
+ if err := runCommand("user create --username " + th.MakeUsername() + " --email " + th.MakeEmail()); err == nil {
+ t.Fatal("should've failed without password")
+ }
+
+ if err := runCommand("user create --username " + th.MakeUsername() + " --password " + model.NewId()); err == nil {
+ t.Fatal("should've failed without email")
+ }
+}
+
+func TestInviteUser(t *testing.T) {
+ th := app.Setup().InitBasic()
+
+ team := th.CreateTeam()
+
+ if err := inviteUser(th.MakeEmail(), nil, "faketeam"); err == nil {
+ t.Fatal("should've failed with nonexistent team")
+ }
+
+ if err := inviteUser(th.MakeEmail(), team, team.Name); err != nil {
+ t.Fatal(err)
+ }
+
+ // Nothing else to test here since this just fires off an email
+}
+
+func TestUserInviteCmd(t *testing.T) {
+ th := app.Setup().InitBasic()
+
+ team := th.BasicTeam
+ team2 := th.CreateTeam()
+
+ if err := runCommand("user invite"); err == nil {
+ t.Fatal("should've failed without any arguments")
+ }
+
+ if err := runCommand("user invite " + th.MakeEmail()); err == nil {
+ t.Fatal("should've failed with 1 argument")
+ }
+
+ if err := runCommand("user invite " + th.MakeEmail() + " " + team.Id); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := runCommand("user invite " + th.MakeEmail() + " " + team.Name); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := runCommand("user invite " + th.MakeEmail() + " " + team.Id + " " + team2.Name); err != nil {
+ t.Fatal(err)
+ }
+
+ if err := runCommand("user invite " + th.MakeEmail() + " " + team.Id + " " + team2.Name + " " + "faketeam"); err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/cmd/platform/userargs.go b/cmd/platform/userargs.go
index 31ae3c251..43b53edd7 100644
--- a/cmd/platform/userargs.go
+++ b/cmd/platform/userargs.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package main
diff --git a/cmd/platform/userargs_test.go.disabled b/cmd/platform/userargs_test.go.disabled
new file mode 100644
index 000000000..2b6a50bb8
--- /dev/null
+++ b/cmd/platform/userargs_test.go.disabled
@@ -0,0 +1,58 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package main
+
+import (
+ "testing"
+
+ "github.com/mattermost/platform/app"
+ "github.com/mattermost/platform/model"
+)
+
+func TestGetUserFromUserArg(t *testing.T) {
+ th := app.Setup().InitBasic()
+
+ user := th.BasicUser
+
+ if found := getUserFromUserArg(""); found != nil {
+ t.Fatal("shoudn't have gotten a user", found)
+ }
+
+ if found := getUserFromUserArg(model.NewId()); found != nil {
+ t.Fatal("shoudn't have gotten a user", found)
+ }
+
+ if found := getUserFromUserArg(user.Id); found == nil || found.Id != user.Id {
+ t.Fatal("got incorrect user", found)
+ }
+
+ if found := getUserFromUserArg(user.Username); found == nil || found.Id != user.Id {
+ t.Fatal("got incorrect user", found)
+ }
+}
+
+func TestGetUsersFromUserArg(t *testing.T) {
+ th := app.Setup().InitBasic()
+
+ user := th.BasicUser
+ user2 := th.CreateUser()
+
+ if found := getUsersFromUserArgs([]string{}); len(found) != 0 {
+ t.Fatal("shoudn't have gotten any users", found)
+ }
+
+ if found := getUsersFromUserArgs([]string{user.Id}); len(found) == 1 && found[0].Id != user.Id {
+ t.Fatal("got incorrect user", found)
+ }
+
+ if found := getUsersFromUserArgs([]string{user2.Username}); len(found) == 1 && found[0].Id != user2.Id {
+ t.Fatal("got incorrect user", found)
+ }
+
+ if found := getUsersFromUserArgs([]string{user.Username, user2.Id}); len(found) != 2 {
+ t.Fatal("got incorrect number of users", found)
+ } else if !(found[0].Id == user.Id && found[1].Id == user2.Id) && !(found[1].Id == user.Id && found[0].Id == user2.Id) {
+ t.Fatal("got incorrect users", found[0], found[1])
+ }
+}
diff --git a/cmd/platform/version.go b/cmd/platform/version.go
index 8978aa841..13ebdc1cd 100644
--- a/cmd/platform/version.go
+++ b/cmd/platform/version.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package main
diff --git a/config/config.json b/config/config.json
index b3dac758a..c8a52bd86 100644
--- a/config/config.json
+++ b/config/config.json
@@ -1,6 +1,7 @@
{
"ServiceSettings": {
"SiteURL": "http://localhost:8065",
+ "LicenseFileLocation": "",
"ListenAddress": ":8065",
"ConnectionSecurity": "",
"TLSCertFile": "",
@@ -40,6 +41,7 @@
"AllowEditPost": "always",
"PostEditTimeLimit": 300,
"TimeBetweenUserTypingUpdatesMilliseconds": 5000,
+ "EnablePostSearch": true,
"EnableUserTypingMessages": true,
"ClusterLogTimeoutMilliseconds": 2000
},
@@ -68,7 +70,7 @@
},
"SqlSettings": {
"DriverName": "mysql",
- "DataSource": "mmuser:mostest@tcp(dockerhost:3306)/mattermost_test?charset=utf8mb4,utf8",
+ "DataSource": "mmuser:mostest@tcp(dockerhost:3306)/mattermost_test?charset=utf8mb4,utf8&readTimeout=30s&writeTimeout=30s",
"DataSourceReplicas": [],
"MaxIdleConns": 20,
"MaxOpenConns": 300,
diff --git a/einterfaces/account_migration.go b/einterfaces/account_migration.go
index 4824de6d5..a52b5e348 100644
--- a/einterfaces/account_migration.go
+++ b/einterfaces/account_migration.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package einterfaces
diff --git a/einterfaces/brand.go b/einterfaces/brand.go
index 7c15659bb..f4e16eb04 100644
--- a/einterfaces/brand.go
+++ b/einterfaces/brand.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package einterfaces
diff --git a/einterfaces/cluster.go b/einterfaces/cluster.go
index 1c6b1e071..ba780f8b1 100644
--- a/einterfaces/cluster.go
+++ b/einterfaces/cluster.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package einterfaces
diff --git a/einterfaces/compliance.go b/einterfaces/compliance.go
index 2e72c67d3..b7c087e89 100644
--- a/einterfaces/compliance.go
+++ b/einterfaces/compliance.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package einterfaces
diff --git a/einterfaces/emoji.go b/einterfaces/emoji.go
index f276f6a32..45d1432dc 100644
--- a/einterfaces/emoji.go
+++ b/einterfaces/emoji.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package einterfaces
diff --git a/einterfaces/ldap.go b/einterfaces/ldap.go
index f50ea277e..721c8d30e 100644
--- a/einterfaces/ldap.go
+++ b/einterfaces/ldap.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package einterfaces
diff --git a/einterfaces/metrics.go b/einterfaces/metrics.go
index cc2eea97c..a9acb8c2b 100644
--- a/einterfaces/metrics.go
+++ b/einterfaces/metrics.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package einterfaces
diff --git a/einterfaces/mfa.go b/einterfaces/mfa.go
index 4830d261f..e1b6ecbc3 100644
--- a/einterfaces/mfa.go
+++ b/einterfaces/mfa.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package einterfaces
diff --git a/einterfaces/oauthproviders.go b/einterfaces/oauthproviders.go
index c2ea8c72d..b58e83078 100644
--- a/einterfaces/oauthproviders.go
+++ b/einterfaces/oauthproviders.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package einterfaces
diff --git a/einterfaces/saml.go b/einterfaces/saml.go
index af2e815a5..3e0208912 100644
--- a/einterfaces/saml.go
+++ b/einterfaces/saml.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package einterfaces
diff --git a/i18n/en.json b/i18n/en.json
index 051631f3c..75954a6c9 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -444,6 +444,10 @@
"translation": "Initializing command API routes"
},
{
+ "id": "api.emoji.init.debug",
+ "translation": "Initializing emoji API routes"
+ },
+ {
"id": "api.command.invite_people.desc",
"translation": "Send an email invite to your Mattermost team"
},
@@ -3704,6 +3708,14 @@
"translation": "Unable to write request"
},
{
+ "id": "model.client.get_flagged_posts_in_channel.missing_parameter.app_error",
+ "translation": "Missing channel parameter"
+ },
+ {
+ "id": "model.client.get_flagged_posts_in_team.missing_parameter.app_error",
+ "translation": "Missing team parameter"
+ },
+ {
"id": "model.client.login.app_error",
"translation": "Authentication tokens didn't match"
},
@@ -3949,7 +3961,7 @@
},
{
"id": "model.config.is_valid.max_file_size.app_error",
- "translation": "Invalid max file size for file settings. Must be a zero or positive number."
+ "translation": "Invalid max file size for file settings. Must be a whole number greater than zero."
},
{
"id": "model.config.is_valid.max_notify_per_channel.app_error",
@@ -5192,6 +5204,10 @@
"translation": "Query error searching posts: %v"
},
{
+ "id": "store.sql_post.search.disabled",
+ "translation": "Searching has been disabled on this server. Please contact your System Administrator."
+ },
+ {
"id": "store.sql_post.update.app_error",
"translation": "We couldn't update the Post"
},
diff --git a/manualtesting/manual_testing.go b/manualtesting/manual_testing.go
index 677b9999d..4e6baf8b0 100644
--- a/manualtesting/manual_testing.go
+++ b/manualtesting/manual_testing.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package manualtesting
diff --git a/manualtesting/test_autolink.go b/manualtesting/test_autolink.go
index f9f213da1..190185835 100644
--- a/manualtesting/test_autolink.go
+++ b/manualtesting/test_autolink.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package manualtesting
diff --git a/mkdocs.yml b/mkdocs.yml
index a8b37ecad..412914738 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -3,7 +3,7 @@ site_url: http://docs.mattermost.org
repo_url: https://github.com/mattermost/platform
repo_name: GitHub
site_favicon: favicon.ico
-copyright: "Copyright (c) 2015 Mattermost, Inc. All Rights Reserved."
+copyright: "Copyright (c) 2015-2017 Mattermost, Inc. All Rights Reserved."
strict: true
docs_dir: doc
site_dir: documentation-html
diff --git a/model/access.go b/model/access.go
index 520417f4e..9e16ed58b 100644
--- a/model/access.go
+++ b/model/access.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
@@ -21,6 +21,7 @@ type AccessData struct {
RefreshToken string `json:"refresh_token"`
RedirectUri string `json:"redirect_uri"`
ExpiresAt int64 `json:"expires_at"`
+ Scope string `json:"scope"`
}
type AccessResponse struct {
diff --git a/model/access_test.go b/model/access_test.go
index 77b4cf15b..f0ed2da77 100644
--- a/model/access_test.go
+++ b/model/access_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/analytics_row.go b/model/analytics_row.go
index ed1d69dd2..5493163dc 100644
--- a/model/analytics_row.go
+++ b/model/analytics_row.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/analytics_row_test.go b/model/analytics_row_test.go
index 1202d5b52..bd4e96c7d 100644
--- a/model/analytics_row_test.go
+++ b/model/analytics_row_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/audit.go b/model/audit.go
index 8fa1d5584..7699cf930 100644
--- a/model/audit.go
+++ b/model/audit.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/audit_test.go b/model/audit_test.go
index f4a2b6bcc..44e4cfb34 100644
--- a/model/audit_test.go
+++ b/model/audit_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/audits.go b/model/audits.go
index 36c80629f..e57e2a3ac 100644
--- a/model/audits.go
+++ b/model/audits.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/audits_test.go b/model/audits_test.go
index 6c7104475..3b22b2668 100644
--- a/model/audits_test.go
+++ b/model/audits_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/authorization.go b/model/authorization.go
index 384e4c865..458ed1bdb 100644
--- a/model/authorization.go
+++ b/model/authorization.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/authorize.go b/model/authorize.go
index 3f259718b..2f290fab2 100644
--- a/model/authorize.go
+++ b/model/authorize.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/authorize_test.go b/model/authorize_test.go
index 82a48332c..cbb57d54c 100644
--- a/model/authorize_test.go
+++ b/model/authorize_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/channel.go b/model/channel.go
index d80674444..50d487557 100644
--- a/model/channel.go
+++ b/model/channel.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/channel_count.go b/model/channel_count.go
index 6cc1b2f2d..aecb0c712 100644
--- a/model/channel_count.go
+++ b/model/channel_count.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/channel_data.go b/model/channel_data.go
index 731d50e70..41b7eaa65 100644
--- a/model/channel_data.go
+++ b/model/channel_data.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/channel_list.go b/model/channel_list.go
index 7a46de45d..18c726908 100644
--- a/model/channel_list.go
+++ b/model/channel_list.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/channel_member.go b/model/channel_member.go
index 32ffaf606..f6d58519a 100644
--- a/model/channel_member.go
+++ b/model/channel_member.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/channel_member_test.go b/model/channel_member_test.go
index 6fb666300..26c9c3ddf 100644
--- a/model/channel_member_test.go
+++ b/model/channel_member_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/channel_search.go b/model/channel_search.go
index 2c041503d..d915c164e 100644
--- a/model/channel_search.go
+++ b/model/channel_search.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/channel_search_test.go b/model/channel_search_test.go
index f7f6d66f7..97c1b3ecd 100644
--- a/model/channel_search_test.go
+++ b/model/channel_search_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/channel_stats.go b/model/channel_stats.go
index 079769eb0..758aa2b15 100644
--- a/model/channel_stats.go
+++ b/model/channel_stats.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/channel_test.go b/model/channel_test.go
index 207ce4639..ee6a70b0d 100644
--- a/model/channel_test.go
+++ b/model/channel_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/channel_view.go b/model/channel_view.go
index 8be7af175..8a7ead76f 100644
--- a/model/channel_view.go
+++ b/model/channel_view.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/client.go b/model/client.go
index 74793c5eb..564aa2e48 100644
--- a/model/client.go
+++ b/model/client.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
@@ -1841,15 +1841,14 @@ func (c *Client) GetTeamStats(teamId string) (*Result, *AppError) {
}
}
-// GetTeamStats will return a team stats object containing the number of users on the team
-// based on the team id provided. Must be authenticated.
+// GetTeamByName will return a team object based on the team name provided. Must be authenticated.
func (c *Client) GetTeamByName(teamName string) (*Result, *AppError) {
if r, err := c.DoApiGet(fmt.Sprintf("/teams/name/%v", teamName), "", ""); err != nil {
return nil, err
} else {
defer closeBody(r)
return &Result{r.Header.Get(HEADER_REQUEST_ID),
- r.Header.Get(HEADER_ETAG_SERVER), TeamStatsFromJson(r.Body)}, nil
+ r.Header.Get(HEADER_ETAG_SERVER), TeamFromJson(r.Body)}, nil
}
}
diff --git a/model/client4.go b/model/client4.go
index cd9a6de75..ad3ff51a4 100644
--- a/model/client4.go
+++ b/model/client4.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
@@ -226,6 +226,18 @@ func (c *Client4) GetCommandsRoute() string {
return fmt.Sprintf("/commands")
}
+func (c *Client4) GetCommandRoute(commandId string) string {
+ return fmt.Sprintf(c.GetCommandsRoute()+"/%v", commandId)
+}
+
+func (c *Client4) GetEmojisRoute() string {
+ return fmt.Sprintf("/emoji")
+}
+
+func (c *Client4) GetEmojiRoute(emojiId string) string {
+ return fmt.Sprintf(c.GetEmojisRoute()+"/%v", emojiId)
+}
+
func (c *Client4) DoApiGet(url string, etag string) (*http.Response, *AppError) {
return c.DoApiRequest(http.MethodGet, url, "", etag)
}
@@ -285,6 +297,25 @@ func (c *Client4) DoUploadFile(url string, data []byte, contentType string) (*Fi
}
}
+func (c *Client4) DoEmojiUploadFile(url string, data []byte, contentType string) (*Emoji, *Response) {
+ rq, _ := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data))
+ rq.Header.Set("Content-Type", contentType)
+ rq.Close = true
+
+ if len(c.AuthToken) > 0 {
+ rq.Header.Set(HEADER_AUTH, c.AuthType+" "+c.AuthToken)
+ }
+
+ if rp, err := c.HttpClient.Do(rq); err != nil {
+ return nil, &Response{Error: NewAppError(url, "model.client.connecting.app_error", nil, err.Error(), 0)}
+ } else if rp.StatusCode >= 300 {
+ return nil, &Response{StatusCode: rp.StatusCode, Error: AppErrorFromJson(rp.Body)}
+ } else {
+ defer closeBody(rp)
+ return EmojiFromJson(rp.Body), BuildResponse(rp)
+ }
+}
+
func (c *Client4) DoUploadImportTeam(url string, data []byte, contentType string) ([]byte, *Response) {
rq, _ := http.NewRequest("POST", c.ApiUrl+url, bytes.NewReader(data))
rq.Header.Set("Content-Type", contentType)
@@ -382,6 +413,16 @@ func (c *Client4) Logout() (bool, *Response) {
}
}
+// SwitchAccountType changes a user's login type from one type to another.
+func (c *Client4) SwitchAccountType(switchRequest *SwitchRequest) (string, *Response) {
+ if r, err := c.DoApiPost(c.GetUsersRoute()+"/login/switch", switchRequest.ToJson()); err != nil {
+ return "", &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return MapFromJson(r.Body)["follow_link"], BuildResponse(r)
+ }
+}
+
// User Section
// CreateUser creates a user in the system based on the provided user struct.
@@ -652,6 +693,19 @@ func (c *Client4) UpdateUserRoles(userId, roles string) (bool, *Response) {
}
}
+// UpdateUserActive updates status of a user whether active or not.
+func (c *Client4) UpdateUserActive(userId string, active bool) (bool, *Response) {
+ requestBody := make(map[string]interface{})
+ requestBody["active"] = active
+
+ if r, err := c.DoApiPut(c.GetUserRoute(userId)+"/active", StringInterfaceToJson(requestBody)); err != nil {
+ return false, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return CheckStatusOK(r), BuildResponse(r)
+ }
+}
+
// DeleteUser deactivates a user in the system based on the provided user id string.
func (c *Client4) DeleteUser(userId string) (bool, *Response) {
if r, err := c.DoApiDelete(c.GetUserRoute(userId)); err != nil {
@@ -1415,6 +1469,47 @@ func (c *Client4) GetPostsForChannel(channelId string, page, perPage int, etag s
}
}
+// GetFlaggedPostsForUser returns flagged posts of a user based on user id string.
+func (c *Client4) GetFlaggedPostsForUser(userId string, page int, perPage int) (*PostList, *Response) {
+ query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
+ if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/posts/flagged"+query, ""); err != nil {
+ return nil, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return PostListFromJson(r.Body), BuildResponse(r)
+ }
+}
+
+// GetFlaggedPostsForUserInTeam returns flagged posts in team of a user based on user id string.
+func (c *Client4) GetFlaggedPostsForUserInTeam(userId string, teamId string, page int, perPage int) (*PostList, *Response) {
+ if len(teamId) == 0 || len(teamId) != 26 {
+ return nil, &Response{StatusCode: http.StatusBadRequest, Error: NewAppError("GetFlaggedPostsForUserInTeam", "model.client.get_flagged_posts_in_team.missing_parameter.app_error", nil, "", http.StatusBadRequest)}
+ }
+
+ query := fmt.Sprintf("?in_team=%v&page=%v&per_page=%v", teamId, page, perPage)
+ if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/posts/flagged"+query, ""); err != nil {
+ return nil, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return PostListFromJson(r.Body), BuildResponse(r)
+ }
+}
+
+// GetFlaggedPostsForUserInChannel returns flagged posts in channel of a user based on user id string.
+func (c *Client4) GetFlaggedPostsForUserInChannel(userId string, channelId string, page int, perPage int) (*PostList, *Response) {
+ if len(channelId) == 0 || len(channelId) != 26 {
+ return nil, &Response{StatusCode: http.StatusBadRequest, Error: NewAppError("GetFlaggedPostsForUserInChannel", "model.client.get_flagged_posts_in_channel.missing_parameter.app_error", nil, "", http.StatusBadRequest)}
+ }
+
+ query := fmt.Sprintf("?in_channel=%v&page=%v&per_page=%v", channelId, page, perPage)
+ if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/posts/flagged"+query, ""); err != nil {
+ return nil, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return PostListFromJson(r.Body), BuildResponse(r)
+ }
+}
+
// GetPostsSince gets posts created after a specified time as Unix time in milliseconds.
func (c *Client4) GetPostsSince(channelId string, time int64) (*PostList, *Response) {
query := fmt.Sprintf("?since=%v", time)
@@ -2124,6 +2219,26 @@ func (c *Client4) CreateCommand(cmd *Command) (*Command, *Response) {
}
}
+// UpdateCommand updates a command based on the provided Command struct
+func (c *Client4) UpdateCommand(cmd *Command) (*Command, *Response) {
+ if r, err := c.DoApiPut(c.GetCommandRoute(cmd.Id), cmd.ToJson()); err != nil {
+ return nil, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return CommandFromJson(r.Body), BuildResponse(r)
+ }
+}
+
+// DeleteCommand deletes a command based on the provided command id string
+func (c *Client4) DeleteCommand(commandId string) (bool, *Response) {
+ if r, err := c.DoApiDelete(c.GetCommandRoute(commandId)); err != nil {
+ return false, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return CheckStatusOK(r), BuildResponse(r)
+ }
+}
+
// ListCommands will retrieve a list of commands available in the team.
func (c *Client4) ListCommands(teamId string, customOnly bool) ([]*Command, *Response) {
query := fmt.Sprintf("?team_id=%v&custom_only=%v", teamId, customOnly)
@@ -2145,6 +2260,16 @@ func (c *Client4) ListAutocompleteCommands(teamId string) ([]*Command, *Response
}
}
+// RegenCommandToken will create a new token if the user have the right permissions.
+func (c *Client4) RegenCommandToken(commandId string) (string, *Response) {
+ if r, err := c.DoApiPut(c.GetCommandRoute(commandId)+"/regen_token", ""); err != nil {
+ return "", &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return MapFromJson(r.Body)["token"], BuildResponse(r)
+ }
+}
+
// Status Section
// GetUserStatus returns a user based on the provided user id string.
@@ -2177,3 +2302,84 @@ func (c *Client4) UpdateUserStatus(userId string, userStatus *Status) (*Status,
}
}
+
+// Webrtc Section
+
+// GetWebrtcToken returns a valid token, stun server and turn server with credentials to
+// use with the Mattermost WebRTC service.
+func (c *Client4) GetWebrtcToken() (*WebrtcInfoResponse, *Response) {
+ if r, err := c.DoApiGet("/webrtc/token", ""); err != nil {
+ return nil, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return WebrtcInfoResponseFromJson(r.Body), BuildResponse(r)
+ }
+}
+
+// Emoji Section
+
+// CreateEmoji will save an emoji to the server if the current user has permission
+// to do so. If successful, the provided emoji will be returned with its Id field
+// filled in. Otherwise, an error will be returned.
+func (c *Client4) CreateEmoji(emoji *Emoji, image []byte, filename string) (*Emoji, *Response) {
+ body := &bytes.Buffer{}
+ writer := multipart.NewWriter(body)
+
+ if part, err := writer.CreateFormFile("image", filename); err != nil {
+ return nil, &Response{StatusCode: http.StatusForbidden, Error: NewLocAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error())}
+ } else if _, err = io.Copy(part, bytes.NewBuffer(image)); err != nil {
+ return nil, &Response{StatusCode: http.StatusForbidden, Error: NewLocAppError("CreateEmoji", "model.client.create_emoji.image.app_error", nil, err.Error())}
+ }
+
+ if err := writer.WriteField("emoji", emoji.ToJson()); err != nil {
+ return nil, &Response{StatusCode: http.StatusForbidden, Error: NewLocAppError("CreateEmoji", "model.client.create_emoji.emoji.app_error", nil, err.Error())}
+ }
+
+ if err := writer.Close(); err != nil {
+ return nil, &Response{StatusCode: http.StatusForbidden, Error: NewLocAppError("CreateEmoji", "model.client.create_emoji.writer.app_error", nil, err.Error())}
+ }
+
+ return c.DoEmojiUploadFile(c.GetEmojisRoute(), body.Bytes(), writer.FormDataContentType())
+}
+
+// GetEmojiList returns a list of custom emoji in the system.
+func (c *Client4) GetEmojiList() ([]*Emoji, *Response) {
+ if r, err := c.DoApiGet(c.GetEmojisRoute(), ""); err != nil {
+ return nil, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return EmojiListFromJson(r.Body), BuildResponse(r)
+ }
+}
+
+// DeleteEmoji delete an custom emoji on the provided emoji id string.
+func (c *Client4) DeleteEmoji(emojiId string) (bool, *Response) {
+ if r, err := c.DoApiDelete(c.GetEmojiRoute(emojiId)); err != nil {
+ return false, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return CheckStatusOK(r), BuildResponse(r)
+ }
+}
+
+// GetEmoji returns a custom emoji in the system on the provided emoji id string.
+func (c *Client4) GetEmoji(emojiId string) (*Emoji, *Response) {
+ if r, err := c.DoApiGet(c.GetEmojiRoute(emojiId), ""); err != nil {
+ return nil, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return EmojiFromJson(r.Body), BuildResponse(r)
+ }
+}
+
+// Reaction Section
+
+// GetReactions returns a list of reactions to a post.
+func (c *Client4) GetReactions(postId string) ([]*Reaction, *Response) {
+ if r, err := c.DoApiGet(c.GetPostRoute(postId)+"/reactions", ""); err != nil {
+ return nil, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return ReactionsFromJson(r.Body), BuildResponse(r)
+ }
+}
diff --git a/model/cluster_info.go b/model/cluster_info.go
index 0e4b1e365..f76a03c0b 100644
--- a/model/cluster_info.go
+++ b/model/cluster_info.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/cluster_info_test.go b/model/cluster_info_test.go
index e7aa9cd16..038927120 100644
--- a/model/cluster_info_test.go
+++ b/model/cluster_info_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/cluster_stats.go b/model/cluster_stats.go
index f2efa323e..879487c6e 100644
--- a/model/cluster_stats.go
+++ b/model/cluster_stats.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/cluster_stats_test.go b/model/cluster_stats_test.go
index 13920b5d1..82bacf526 100644
--- a/model/cluster_stats_test.go
+++ b/model/cluster_stats_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/command.go b/model/command.go
index decb647b7..47378bbec 100644
--- a/model/command.go
+++ b/model/command.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/command_args.go b/model/command_args.go
index f512410a3..76b03a2fa 100644
--- a/model/command_args.go
+++ b/model/command_args.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/command_response.go b/model/command_response.go
index f69772353..1b2e06cdf 100644
--- a/model/command_response.go
+++ b/model/command_response.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/command_response_test.go b/model/command_response_test.go
index 131d87789..b57a77608 100644
--- a/model/command_response_test.go
+++ b/model/command_response_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/command_test.go b/model/command_test.go
index 2376e2ef7..53c15f74a 100644
--- a/model/command_test.go
+++ b/model/command_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/compliance.go b/model/compliance.go
index 4a96a597a..14f8f4a5e 100644
--- a/model/compliance.go
+++ b/model/compliance.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/compliance_post.go b/model/compliance_post.go
index 027e534b7..f39fea2f5 100644
--- a/model/compliance_post.go
+++ b/model/compliance_post.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/compliance_post_test.go b/model/compliance_post_test.go
index 49f41a121..4866b2494 100644
--- a/model/compliance_post_test.go
+++ b/model/compliance_post_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/compliance_test.go b/model/compliance_test.go
index 6acc5a882..32ce48db5 100644
--- a/model/compliance_test.go
+++ b/model/compliance_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/config.go b/model/config.go
index 10d44a0ca..303d7bb75 100644
--- a/model/config.go
+++ b/model/config.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
@@ -151,6 +151,7 @@ type ServiceSettings struct {
AllowEditPost *string
PostEditTimeLimit *int
TimeBetweenUserTypingUpdatesMilliseconds *int64
+ EnablePostSearch *bool
EnableUserTypingMessages *bool
ClusterLogTimeoutMilliseconds *int
}
@@ -1148,6 +1149,11 @@ func (o *Config) SetDefaults() {
*o.ServiceSettings.TimeBetweenUserTypingUpdatesMilliseconds = 5000
}
+ if o.ServiceSettings.EnablePostSearch == nil {
+ o.ServiceSettings.EnablePostSearch = new(bool)
+ *o.ServiceSettings.EnablePostSearch = true
+ }
+
if o.ServiceSettings.EnableUserTypingMessages == nil {
o.ServiceSettings.EnableUserTypingMessages = new(bool)
*o.ServiceSettings.EnableUserTypingMessages = true
diff --git a/model/emoji.go b/model/emoji.go
index a66053aa0..7f2792777 100644
--- a/model/emoji.go
+++ b/model/emoji.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/emoji_test.go b/model/emoji_test.go
index cd6344ca5..81de50c6b 100644
--- a/model/emoji_test.go
+++ b/model/emoji_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/file.go b/model/file.go
index 20f6236de..f92581469 100644
--- a/model/file.go
+++ b/model/file.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/file_info.go b/model/file_info.go
index 687473d4f..8b5684127 100644
--- a/model/file_info.go
+++ b/model/file_info.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/file_info_test.go b/model/file_info_test.go
index d3671f252..f87dd4640 100644
--- a/model/file_info_test.go
+++ b/model/file_info_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/gitlab.go b/model/gitlab.go
index 3dfb1016a..8777614c1 100644
--- a/model/gitlab.go
+++ b/model/gitlab.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/gitlab/gitlab.go b/model/gitlab/gitlab.go
index 270d62d8b..7f1447edd 100644
--- a/model/gitlab/gitlab.go
+++ b/model/gitlab/gitlab.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package oauthgitlab
diff --git a/model/incoming_webhook.go b/model/incoming_webhook.go
index 2cc26cbca..2235cb2c6 100644
--- a/model/incoming_webhook.go
+++ b/model/incoming_webhook.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/incoming_webhook_test.go b/model/incoming_webhook_test.go
index 46e5b6743..f6baca988 100644
--- a/model/incoming_webhook_test.go
+++ b/model/incoming_webhook_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/initial_load.go b/model/initial_load.go
index afb0a2762..71ba17696 100644
--- a/model/initial_load.go
+++ b/model/initial_load.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/initial_load_test.go b/model/initial_load_test.go
index 24a07e412..ecae7ac88 100644
--- a/model/initial_load_test.go
+++ b/model/initial_load_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/job.go b/model/job.go
index a139b154c..453828bd2 100644
--- a/model/job.go
+++ b/model/job.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/job_test.go b/model/job_test.go
index 8908fed58..6ba8edaf9 100644
--- a/model/job_test.go
+++ b/model/job_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/ldap.go b/model/ldap.go
index 71b1d8a6b..1453a4add 100644
--- a/model/ldap.go
+++ b/model/ldap.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/license.go b/model/license.go
index 09da61eb7..57c49d3d8 100644
--- a/model/license.go
+++ b/model/license.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/license_test.go b/model/license_test.go
index 25c74a2e3..94a6ad130 100644
--- a/model/license_test.go
+++ b/model/license_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/mfa_secret.go b/model/mfa_secret.go
index 717681b3d..99580f5f3 100644
--- a/model/mfa_secret.go
+++ b/model/mfa_secret.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/mfa_secret_test.go b/model/mfa_secret_test.go
index c062e7311..e61359310 100644
--- a/model/mfa_secret_test.go
+++ b/model/mfa_secret_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/oauth.go b/model/oauth.go
index cfe643c9a..a8aca0ca0 100644
--- a/model/oauth.go
+++ b/model/oauth.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/oauth_test.go b/model/oauth_test.go
index e1f88a993..5c0547717 100644
--- a/model/oauth_test.go
+++ b/model/oauth_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/outgoing_webhook.go b/model/outgoing_webhook.go
index ec2ed75c7..3cfed9e74 100644
--- a/model/outgoing_webhook.go
+++ b/model/outgoing_webhook.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/outgoing_webhook_test.go b/model/outgoing_webhook_test.go
index 2458c62e4..725423cdf 100644
--- a/model/outgoing_webhook_test.go
+++ b/model/outgoing_webhook_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/password_recovery.go b/model/password_recovery.go
index 303d4a12e..8af046642 100644
--- a/model/password_recovery.go
+++ b/model/password_recovery.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/post.go b/model/post.go
index 0d9651924..f5a398656 100644
--- a/model/post.go
+++ b/model/post.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/post_list.go b/model/post_list.go
index 9b56f0233..63f6d6825 100644
--- a/model/post_list.go
+++ b/model/post_list.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/post_list_test.go b/model/post_list_test.go
index 9ce6447e1..56886d4fd 100644
--- a/model/post_list_test.go
+++ b/model/post_list_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/post_test.go b/model/post_test.go
index cbd323fab..1096ccbd8 100644
--- a/model/post_test.go
+++ b/model/post_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/preference.go b/model/preference.go
index 94807d2c9..4d534b17b 100644
--- a/model/preference.go
+++ b/model/preference.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/preference_test.go b/model/preference_test.go
index df7fe612d..c56d46e2c 100644
--- a/model/preference_test.go
+++ b/model/preference_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/preferences.go b/model/preferences.go
index f11b5fd80..b982e309d 100644
--- a/model/preferences.go
+++ b/model/preferences.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/push_notification.go b/model/push_notification.go
index 753495b2f..49d4043eb 100644
--- a/model/push_notification.go
+++ b/model/push_notification.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/push_notification_test.go b/model/push_notification_test.go
index e8b2fa2d4..a6e158105 100644
--- a/model/push_notification_test.go
+++ b/model/push_notification_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/push_response.go b/model/push_response.go
index 0271bc94b..095986f3e 100644
--- a/model/push_response.go
+++ b/model/push_response.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/reaction.go b/model/reaction.go
index afbdd1e88..4a02df8cb 100644
--- a/model/reaction.go
+++ b/model/reaction.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/reaction_test.go b/model/reaction_test.go
index da73f477a..e980b106d 100644
--- a/model/reaction_test.go
+++ b/model/reaction_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/saml.go b/model/saml.go
index 1371c433f..f5826a95d 100644
--- a/model/saml.go
+++ b/model/saml.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/saml_test.go b/model/saml_test.go
index 578e78da5..d7745bd6b 100644
--- a/model/saml_test.go
+++ b/model/saml_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/search_params.go b/model/search_params.go
index bc604317e..070ac6d24 100644
--- a/model/search_params.go
+++ b/model/search_params.go
@@ -1,9 +1,10 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
+ "encoding/json"
"regexp"
"strings"
)
@@ -19,6 +20,15 @@ type SearchParams struct {
OrTerms bool
}
+func (o *SearchParams) ToJson() string {
+ b, err := json.Marshal(o)
+ if err != nil {
+ return ""
+ } else {
+ return string(b)
+ }
+}
+
var searchFlags = [...]string{"from", "channel", "in"}
func splitWordsNoQuotes(text string) []string {
diff --git a/model/search_params_test.go b/model/search_params_test.go
index 7138d82c4..0e55c7ead 100644
--- a/model/search_params_test.go
+++ b/model/search_params_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/security_bulletin.go b/model/security_bulletin.go
index 8d9be6d3b..b8c1dc48d 100644
--- a/model/security_bulletin.go
+++ b/model/security_bulletin.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/session.go b/model/session.go
index 277e910f6..90cebe59d 100644
--- a/model/session.go
+++ b/model/session.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/session_test.go b/model/session_test.go
index 4cffcb9c0..295f00076 100644
--- a/model/session_test.go
+++ b/model/session_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/slack_attachment.go b/model/slack_attachment.go
index e1639f2af..6fd0071b4 100644
--- a/model/slack_attachment.go
+++ b/model/slack_attachment.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/status.go b/model/status.go
index 59115b42d..d838eea01 100644
--- a/model/status.go
+++ b/model/status.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/status_test.go b/model/status_test.go
index cb1720fd2..7730ff0ed 100644
--- a/model/status_test.go
+++ b/model/status_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/suggest_command.go b/model/suggest_command.go
index 7bc35369c..3d066499a 100644
--- a/model/suggest_command.go
+++ b/model/suggest_command.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/suggest_command_test.go b/model/suggest_command_test.go
index 6be700859..96f49e301 100644
--- a/model/suggest_command_test.go
+++ b/model/suggest_command_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/switch_request.go b/model/switch_request.go
new file mode 100644
index 000000000..964f47a90
--- /dev/null
+++ b/model/switch_request.go
@@ -0,0 +1,62 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package model
+
+import (
+ "encoding/json"
+ "io"
+)
+
+type SwitchRequest struct {
+ CurrentService string `json:"current_service"`
+ NewService string `json:"new_service"`
+ Email string `json:"email"`
+ Password string `json:"current_password"`
+ NewPassword string `json:"new_password"`
+ MfaCode string `json:"mfa_code"`
+ LdapId string `json:"ldap_id"`
+}
+
+func (o *SwitchRequest) ToJson() string {
+ b, err := json.Marshal(o)
+ if err != nil {
+ return ""
+ } else {
+ return string(b)
+ }
+}
+
+func SwitchRequestFromJson(data io.Reader) *SwitchRequest {
+ decoder := json.NewDecoder(data)
+ var o SwitchRequest
+ err := decoder.Decode(&o)
+ if err == nil {
+ return &o
+ } else {
+ return nil
+ }
+}
+
+func (o *SwitchRequest) EmailToOAuth() bool {
+ return o.CurrentService == USER_AUTH_SERVICE_EMAIL &&
+ (o.NewService == USER_AUTH_SERVICE_SAML ||
+ o.NewService == USER_AUTH_SERVICE_GITLAB ||
+ o.NewService == SERVICE_GOOGLE ||
+ o.NewService == SERVICE_OFFICE365)
+}
+
+func (o *SwitchRequest) OAuthToEmail() bool {
+ return (o.CurrentService == USER_AUTH_SERVICE_SAML ||
+ o.CurrentService == USER_AUTH_SERVICE_GITLAB ||
+ o.CurrentService == SERVICE_GOOGLE ||
+ o.CurrentService == SERVICE_OFFICE365) && o.NewService == USER_AUTH_SERVICE_EMAIL
+}
+
+func (o *SwitchRequest) EmailToLdap() bool {
+ return o.CurrentService == USER_AUTH_SERVICE_EMAIL && o.NewService == USER_AUTH_SERVICE_LDAP
+}
+
+func (o *SwitchRequest) LdapToEmail() bool {
+ return o.CurrentService == USER_AUTH_SERVICE_LDAP && o.NewService == USER_AUTH_SERVICE_EMAIL
+}
diff --git a/model/switch_request_test.go b/model/switch_request_test.go
new file mode 100644
index 000000000..49302fba6
--- /dev/null
+++ b/model/switch_request_test.go
@@ -0,0 +1,19 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package model
+
+import (
+ "strings"
+ "testing"
+)
+
+func TestSwitchRequestJson(t *testing.T) {
+ o := SwitchRequest{Email: NewId(), Password: NewId()}
+ json := o.ToJson()
+ ro := SwitchRequestFromJson(strings.NewReader(json))
+
+ if o.Email != ro.Email {
+ t.Fatal("Emails do not match")
+ }
+}
diff --git a/model/system.go b/model/system.go
index 68d542c15..e2f4283a4 100644
--- a/model/system.go
+++ b/model/system.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/system_test.go b/model/system_test.go
index 3f60eb5f9..bf167a6cc 100644
--- a/model/system_test.go
+++ b/model/system_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/team.go b/model/team.go
index 458f71e95..74d371ac2 100644
--- a/model/team.go
+++ b/model/team.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/team_member.go b/model/team_member.go
index efd77e7ec..3a0befa31 100644
--- a/model/team_member.go
+++ b/model/team_member.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/team_member_test.go b/model/team_member_test.go
index e957ffd4f..3661fff4b 100644
--- a/model/team_member_test.go
+++ b/model/team_member_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/team_search.go b/model/team_search.go
index 4ab30f96b..e0676022d 100644
--- a/model/team_search.go
+++ b/model/team_search.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/team_search_test.go b/model/team_search_test.go
index 996adad43..0f118c9ec 100644
--- a/model/team_search_test.go
+++ b/model/team_search_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/team_stats.go b/model/team_stats.go
index 9042e76d6..e94ed37bc 100644
--- a/model/team_stats.go
+++ b/model/team_stats.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/team_test.go b/model/team_test.go
index d471bbf49..60ba92f99 100644
--- a/model/team_test.go
+++ b/model/team_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/user.go b/model/user.go
index 5cefdf1b1..2c2ba734b 100644
--- a/model/user.go
+++ b/model/user.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
@@ -26,13 +26,12 @@ const (
PUSH_NOTIFY_PROP = "push"
EMAIL_NOTIFY_PROP = "email"
- DEFAULT_LOCALE = "en"
- USER_AUTH_SERVICE_EMAIL = "email"
- USER_AUTH_SERVICE_USERNAME = "username"
+ DEFAULT_LOCALE = "en"
+ USER_AUTH_SERVICE_EMAIL = "email"
USER_EMAIL_MAX_LENGTH = 128
USER_NICKNAME_MAX_RUNES = 64
- USER_POSITION_MAX_RUNES = 35
+ USER_POSITION_MAX_RUNES = 64
USER_FIRST_NAME_MAX_RUNES = 64
USER_LAST_NAME_MAX_RUNES = 64
USER_AUTH_DATA_MAX_LENGTH = 128
@@ -85,56 +84,65 @@ type UserPatch struct {
func (u *User) IsValid() *AppError {
if len(u.Id) != 26 {
- return NewAppError("User.IsValid", "model.user.is_valid.id.app_error", nil, "", http.StatusBadRequest)
+ return InvalidUserError("id", "")
}
if u.CreateAt == 0 {
- return NewAppError("User.IsValid", "model.user.is_valid.create_at.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
+ return InvalidUserError("create_at", u.Id)
}
if u.UpdateAt == 0 {
- return NewAppError("User.IsValid", "model.user.is_valid.update_at.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
+ return InvalidUserError("update_at", u.Id)
}
if !IsValidUsername(u.Username) {
- return NewAppError("User.IsValid", "model.user.is_valid.username.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
+ return InvalidUserError("username", u.Id)
}
if len(u.Email) > USER_EMAIL_MAX_LENGTH || len(u.Email) == 0 {
- return NewAppError("User.IsValid", "model.user.is_valid.email.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
+ return InvalidUserError("email", u.Id)
}
if utf8.RuneCountInString(u.Nickname) > USER_NICKNAME_MAX_RUNES {
- return NewAppError("User.IsValid", "model.user.is_valid.nickname.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
+ return InvalidUserError("nickname", u.Id)
}
if utf8.RuneCountInString(u.Position) > USER_POSITION_MAX_RUNES {
- return NewAppError("User.IsValid", "model.user.is_valid.position.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
+ return InvalidUserError("position", u.Id)
}
if utf8.RuneCountInString(u.FirstName) > USER_FIRST_NAME_MAX_RUNES {
- return NewAppError("User.IsValid", "model.user.is_valid.first_name.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
+ return InvalidUserError("first_name", u.Id)
}
if utf8.RuneCountInString(u.LastName) > USER_LAST_NAME_MAX_RUNES {
- return NewAppError("User.IsValid", "model.user.is_valid.last_name.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
+ return InvalidUserError("last_name", u.Id)
}
if u.AuthData != nil && len(*u.AuthData) > USER_AUTH_DATA_MAX_LENGTH {
- return NewAppError("User.IsValid", "model.user.is_valid.auth_data.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
+ return InvalidUserError("auth_data", u.Id)
}
if u.AuthData != nil && len(*u.AuthData) > 0 && len(u.AuthService) == 0 {
- return NewAppError("User.IsValid", "model.user.is_valid.auth_data_type.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
+ return InvalidUserError("auth_data_type", u.Id)
}
if len(u.Password) > 0 && u.AuthData != nil && len(*u.AuthData) > 0 {
- return NewAppError("User.IsValid", "model.user.is_valid.auth_data_pwd.app_error", nil, "user_id="+u.Id, http.StatusBadRequest)
+ return InvalidUserError("auth_data_pwd", u.Id)
}
return nil
}
+func InvalidUserError(fieldName string, userId string) *AppError {
+ id := fmt.Sprintf("model.user.is_valid.%s.app_error", fieldName)
+ details := ""
+ if userId != "" {
+ details = "user_id=" + userId
+ }
+ return NewAppError("User.IsValid", id, nil, details, http.StatusBadRequest)
+}
+
// PreSave will set the Id and Username if missing. It will also fill
// in the CreateAt, UpdateAt times. It will also hash the password. It should
// be run before saving the user to the db.
diff --git a/model/user_autocomplete.go b/model/user_autocomplete.go
index b80c6f992..43c030b8e 100644
--- a/model/user_autocomplete.go
+++ b/model/user_autocomplete.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/user_search.go b/model/user_search.go
index 8d6a5c567..6213b16e4 100644
--- a/model/user_search.go
+++ b/model/user_search.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/user_search_test.go b/model/user_search_test.go
index b2543ffdb..0fada7781 100644
--- a/model/user_search_test.go
+++ b/model/user_search_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/user_test.go b/model/user_test.go
index 47ec38dbf..3eb931f5d 100644
--- a/model/user_test.go
+++ b/model/user_test.go
@@ -1,9 +1,11 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
+ "fmt"
+ "net/http"
"strings"
"testing"
)
@@ -71,43 +73,43 @@ func TestUserUpdateMentionKeysFromUsername(t *testing.T) {
func TestUserIsValid(t *testing.T) {
user := User{}
- if err := user.IsValid(); err == nil {
- t.Fatal()
+ if err := user.IsValid(); !HasExpectedUserIsValidError(err, "id", "") {
+ t.Fatal(err)
}
user.Id = NewId()
- if err := user.IsValid(); err == nil {
+ if err := user.IsValid(); !HasExpectedUserIsValidError(err, "create_at", user.Id) {
t.Fatal()
}
user.CreateAt = GetMillis()
- if err := user.IsValid(); err == nil {
+ if err := user.IsValid(); !HasExpectedUserIsValidError(err, "update_at", user.Id) {
t.Fatal()
}
user.UpdateAt = GetMillis()
- if err := user.IsValid(); err == nil {
+ if err := user.IsValid(); !HasExpectedUserIsValidError(err, "username", user.Id) {
t.Fatal()
}
user.Username = NewId() + "^hello#"
- if err := user.IsValid(); err == nil {
+ if err := user.IsValid(); !HasExpectedUserIsValidError(err, "username", user.Id) {
t.Fatal()
}
user.Username = "n" + NewId()
- user.Email = strings.Repeat("01234567890", 20)
- if err := user.IsValid(); err == nil {
+ user.Email = strings.Repeat("a", 129)
+ if err := user.IsValid(); !HasExpectedUserIsValidError(err, "email", user.Id) {
t.Fatal()
}
- user.Email = "test@nowhere.com"
- user.Nickname = strings.Repeat("01234567890", 20)
- if err := user.IsValid(); err == nil {
+ user.Email = strings.Repeat("a", 128)
+ user.Nickname = strings.Repeat("a", 65)
+ if err := user.IsValid(); !HasExpectedUserIsValidError(err, "nickname", user.Id) {
t.Fatal()
}
- user.Nickname = ""
+ user.Nickname = strings.Repeat("a", 64)
if err := user.IsValid(); err != nil {
t.Fatal(err)
}
@@ -118,29 +120,40 @@ func TestUserIsValid(t *testing.T) {
t.Fatal(err)
}
- user.FirstName = strings.Repeat("01234567890", 20)
- if err := user.IsValid(); err == nil {
+ user.FirstName = strings.Repeat("a", 65)
+ if err := user.IsValid(); !HasExpectedUserIsValidError(err, "first_name", user.Id) {
t.Fatal(err)
}
- user.FirstName = ""
- user.LastName = strings.Repeat("01234567890", 20)
- if err := user.IsValid(); err == nil {
+ user.FirstName = strings.Repeat("a", 64)
+ user.LastName = strings.Repeat("a", 65)
+ if err := user.IsValid(); !HasExpectedUserIsValidError(err, "last_name", user.Id) {
t.Fatal(err)
}
- user.LastName = ""
- user.Position = ""
+ user.LastName = strings.Repeat("a", 64)
+ user.Position = strings.Repeat("a", 64)
if err := user.IsValid(); err != nil {
t.Fatal(err)
}
- user.Position = strings.Repeat("01234567890", 20)
- if err := user.IsValid(); err == nil {
+ user.Position = strings.Repeat("a", 65)
+ if err := user.IsValid(); !HasExpectedUserIsValidError(err, "position", user.Id) {
t.Fatal(err)
}
}
+func HasExpectedUserIsValidError(err *AppError, fieldName string, userId string) bool {
+ if err == nil {
+ return false
+ }
+
+ return err.Where == "User.IsValid" &&
+ err.Id == fmt.Sprintf("model.user.is_valid.%s.app_error", fieldName) &&
+ err.StatusCode == http.StatusBadRequest &&
+ (userId == "" || err.DetailedError == "user_id="+userId)
+}
+
func TestUserGetFullName(t *testing.T) {
user := User{}
diff --git a/model/utils.go b/model/utils.go
index 8ae45b140..6d8fafeea 100644
--- a/model/utils.go
+++ b/model/utils.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/utils_test.go b/model/utils_test.go
index 7c6100a04..e77ce80fb 100644
--- a/model/utils_test.go
+++ b/model/utils_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/version.go b/model/version.go
index 4eabf391f..01c243df7 100644
--- a/model/version.go
+++ b/model/version.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/version_test.go b/model/version_test.go
index e0346c43a..869ed8ad0 100644
--- a/model/version_test.go
+++ b/model/version_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/webrtc.go b/model/webrtc.go
index e746d62a8..fa15a4b71 100644
--- a/model/webrtc.go
+++ b/model/webrtc.go
@@ -1,3 +1,6 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
package model
import (
@@ -5,6 +8,15 @@ import (
"io"
)
+type WebrtcInfoResponse struct {
+ Token string `json:"token"`
+ GatewayUrl string `json:"gateway_url"`
+ StunUri string `json:"stun_uri,omitempty"`
+ TurnUri string `json:"turn_uri,omitempty"`
+ TurnPassword string `json:"turn_password,omitempty"`
+ TurnUsername string `json:"turn_username,omitempty"`
+}
+
type GatewayResponse struct {
Status string `json:"janus"`
}
@@ -19,3 +31,23 @@ func GatewayResponseFromJson(data io.Reader) *GatewayResponse {
return nil
}
}
+
+func (o *WebrtcInfoResponse) ToJson() string {
+ b, err := json.Marshal(o)
+ if err != nil {
+ return ""
+ } else {
+ return string(b)
+ }
+}
+
+func WebrtcInfoResponseFromJson(data io.Reader) *WebrtcInfoResponse {
+ decoder := json.NewDecoder(data)
+ var o WebrtcInfoResponse
+ err := decoder.Decode(&o)
+ if err == nil {
+ return &o
+ } else {
+ return nil
+ }
+}
diff --git a/model/webrtc_test.go b/model/webrtc_test.go
new file mode 100644
index 000000000..2418bd53a
--- /dev/null
+++ b/model/webrtc_test.go
@@ -0,0 +1,19 @@
+// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package model
+
+import (
+ "strings"
+ "testing"
+)
+
+func TestWebrtcJson(t *testing.T) {
+ o := WebrtcInfoResponse{Token: NewId(), GatewayUrl: NewId()}
+ json := o.ToJson()
+ ro := WebrtcInfoResponseFromJson(strings.NewReader(json))
+
+ if o.Token != ro.Token {
+ t.Fatal("Tokens do not match")
+ }
+}
diff --git a/model/websocket_client.go b/model/websocket_client.go
index 2da83be56..2fa405f31 100644
--- a/model/websocket_client.go
+++ b/model/websocket_client.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/websocket_message.go b/model/websocket_message.go
index c364f2613..0ed056cfe 100644
--- a/model/websocket_message.go
+++ b/model/websocket_message.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/websocket_message_test.go b/model/websocket_message_test.go
index dceb37eef..1b75d0f6e 100644
--- a/model/websocket_message_test.go
+++ b/model/websocket_message_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/websocket_request.go b/model/websocket_request.go
index d0f35f68b..7dc0b4335 100644
--- a/model/websocket_request.go
+++ b/model/websocket_request.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/model/websocket_request_test.go b/model/websocket_request_test.go
index 52de82069..0918fb714 100644
--- a/model/websocket_request_test.go
+++ b/model/websocket_request_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
diff --git a/store/sql_audit_store.go b/store/sql_audit_store.go
index 693b46bb9..c87b5fe6c 100644
--- a/store/sql_audit_store.go
+++ b/store/sql_audit_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_audit_store_test.go b/store/sql_audit_store_test.go
index 0b4d0b6ef..17d53e5e8 100644
--- a/store/sql_audit_store_test.go
+++ b/store/sql_audit_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_channel_store.go b/store/sql_channel_store.go
index 30f2cf7db..881f1cc61 100644
--- a/store/sql_channel_store.go
+++ b/store/sql_channel_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_channel_store_test.go b/store/sql_channel_store_test.go
index ed99575c2..ce3a9a12f 100644
--- a/store/sql_channel_store_test.go
+++ b/store/sql_channel_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_command_store.go b/store/sql_command_store.go
index 0db0ba98e..334c6daa7 100644
--- a/store/sql_command_store.go
+++ b/store/sql_command_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_command_store_test.go b/store/sql_command_store_test.go
index ae1c61df3..ff6e3b9eb 100644
--- a/store/sql_command_store_test.go
+++ b/store/sql_command_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_compliance_store.go b/store/sql_compliance_store.go
index 2307a98cf..ad502a795 100644
--- a/store/sql_compliance_store.go
+++ b/store/sql_compliance_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_compliance_store_test.go b/store/sql_compliance_store_test.go
index e9b0cf94a..7fb772c9c 100644
--- a/store/sql_compliance_store_test.go
+++ b/store/sql_compliance_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_emoji_store.go b/store/sql_emoji_store.go
index 513cf3c3c..2b7f0d0b3 100644
--- a/store/sql_emoji_store.go
+++ b/store/sql_emoji_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_emoji_store_test.go b/store/sql_emoji_store_test.go
index 8cd3eac8c..09cdbeead 100644
--- a/store/sql_emoji_store_test.go
+++ b/store/sql_emoji_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_file_info_store_test.go b/store/sql_file_info_store_test.go
index 5e4d0e66e..daec06269 100644
--- a/store/sql_file_info_store_test.go
+++ b/store/sql_file_info_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_license_store.go b/store/sql_license_store.go
index 6e4cb98c8..315659c1e 100644
--- a/store/sql_license_store.go
+++ b/store/sql_license_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_license_store_test.go b/store/sql_license_store_test.go
index d91cff481..737a79a60 100644
--- a/store/sql_license_store_test.go
+++ b/store/sql_license_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_oauth_store.go b/store/sql_oauth_store.go
index 72bc574d9..6311b56dd 100644
--- a/store/sql_oauth_store.go
+++ b/store/sql_oauth_store.go
@@ -1,9 +1,10 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
import (
+ "net/http"
"strings"
"github.com/go-gorp/gorp"
@@ -42,6 +43,7 @@ func NewSqlOAuthStore(sqlStore *SqlStore) OAuthStore {
tableAccess.ColMap("Token").SetMaxSize(26)
tableAccess.ColMap("RefreshToken").SetMaxSize(26)
tableAccess.ColMap("RedirectUri").SetMaxSize(256)
+ tableAccess.ColMap("Scope").SetMaxSize(128)
tableAccess.SetUniqueTogether("ClientId", "UserId")
}
@@ -138,9 +140,9 @@ func (as SqlOAuthStore) GetApp(id string) StoreChannel {
result := StoreResult{}
if obj, err := as.GetReplica().Get(model.OAuthApp{}, id); err != nil {
- result.Err = model.NewLocAppError("SqlOAuthStore.GetApp", "store.sql_oauth.get_app.finding.app_error", nil, "app_id="+id+", "+err.Error())
+ result.Err = model.NewAppError("SqlOAuthStore.GetApp", "store.sql_oauth.get_app.finding.app_error", nil, "app_id="+id+", "+err.Error(), http.StatusInternalServerError)
} else if obj == nil {
- result.Err = model.NewLocAppError("SqlOAuthStore.GetApp", "store.sql_oauth.get_app.find.app_error", nil, "app_id="+id)
+ result.Err = model.NewAppError("SqlOAuthStore.GetApp", "store.sql_oauth.get_app.find.app_error", nil, "app_id="+id, http.StatusNotFound)
} else {
result.Data = obj.(*model.OAuthApp)
}
@@ -153,7 +155,7 @@ func (as SqlOAuthStore) GetApp(id string) StoreChannel {
return storeChannel
}
-func (as SqlOAuthStore) GetAppByUser(userId string) StoreChannel {
+func (as SqlOAuthStore) GetAppByUser(userId string, offset, limit int) StoreChannel {
storeChannel := make(StoreChannel, 1)
@@ -162,8 +164,8 @@ func (as SqlOAuthStore) GetAppByUser(userId string) StoreChannel {
var apps []*model.OAuthApp
- if _, err := as.GetReplica().Select(&apps, "SELECT * FROM OAuthApps WHERE CreatorId = :UserId", map[string]interface{}{"UserId": userId}); err != nil {
- result.Err = model.NewLocAppError("SqlOAuthStore.GetAppByUser", "store.sql_oauth.get_app_by_user.find.app_error", nil, "user_id="+userId+", "+err.Error())
+ if _, err := as.GetReplica().Select(&apps, "SELECT * FROM OAuthApps WHERE CreatorId = :UserId LIMIT :Limit OFFSET :Offset", map[string]interface{}{"UserId": userId, "Offset": offset, "Limit": limit}); err != nil {
+ result.Err = model.NewAppError("SqlOAuthStore.GetAppByUser", "store.sql_oauth.get_app_by_user.find.app_error", nil, "user_id="+userId+", "+err.Error(), http.StatusInternalServerError)
}
result.Data = apps
@@ -175,7 +177,7 @@ func (as SqlOAuthStore) GetAppByUser(userId string) StoreChannel {
return storeChannel
}
-func (as SqlOAuthStore) GetApps() StoreChannel {
+func (as SqlOAuthStore) GetApps(offset, limit int) StoreChannel {
storeChannel := make(StoreChannel, 1)
@@ -184,8 +186,8 @@ func (as SqlOAuthStore) GetApps() StoreChannel {
var apps []*model.OAuthApp
- if _, err := as.GetReplica().Select(&apps, "SELECT * FROM OAuthApps"); err != nil {
- result.Err = model.NewLocAppError("SqlOAuthStore.GetAppByUser", "store.sql_oauth.get_apps.find.app_error", nil, "err="+err.Error())
+ if _, err := as.GetReplica().Select(&apps, "SELECT * FROM OAuthApps LIMIT :Limit OFFSET :Offset", map[string]interface{}{"Offset": offset, "Limit": limit}); err != nil {
+ result.Err = model.NewAppError("SqlOAuthStore.GetAppByUser", "store.sql_oauth.get_apps.find.app_error", nil, "err="+err.Error(), http.StatusInternalServerError)
}
result.Data = apps
@@ -197,7 +199,7 @@ func (as SqlOAuthStore) GetApps() StoreChannel {
return storeChannel
}
-func (as SqlOAuthStore) GetAuthorizedApps(userId string) StoreChannel {
+func (as SqlOAuthStore) GetAuthorizedApps(userId string, offset, limit int) StoreChannel {
storeChannel := make(StoreChannel, 1)
go func() {
@@ -207,8 +209,8 @@ func (as SqlOAuthStore) GetAuthorizedApps(userId string) StoreChannel {
if _, err := as.GetReplica().Select(&apps,
`SELECT o.* FROM OAuthApps AS o INNER JOIN
- Preferences AS p ON p.Name=o.Id AND p.UserId=:UserId`, map[string]interface{}{"UserId": userId}); err != nil {
- result.Err = model.NewLocAppError("SqlOAuthStore.GetAuthorizedApps", "store.sql_oauth.get_apps.find.app_error", nil, "err="+err.Error())
+ Preferences AS p ON p.Name=o.Id AND p.UserId=:UserId LIMIT :Limit OFFSET :Offset`, map[string]interface{}{"UserId": userId, "Offset": offset, "Limit": limit}); err != nil {
+ result.Err = model.NewAppError("SqlOAuthStore.GetAuthorizedApps", "store.sql_oauth.get_apps.find.app_error", nil, "err="+err.Error(), http.StatusInternalServerError)
}
result.Data = apps
diff --git a/store/sql_oauth_store_test.go b/store/sql_oauth_store_test.go
index dd6fe906e..8c707562f 100644
--- a/store/sql_oauth_store_test.go
+++ b/store/sql_oauth_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
@@ -56,7 +56,7 @@ func TestOAuthStoreGetApp(t *testing.T) {
}
// Lets try and get the app from a user that hasn't created any apps
- if result := (<-store.OAuth().GetAppByUser("fake0123456789abcderfgret1")); result.Err == nil {
+ if result := (<-store.OAuth().GetAppByUser("fake0123456789abcderfgret1", 0, 1000)); result.Err == nil {
if len(result.Data.([]*model.OAuthApp)) > 0 {
t.Fatal("Should have failed. Fake user hasn't created any apps")
}
@@ -64,11 +64,11 @@ func TestOAuthStoreGetApp(t *testing.T) {
t.Fatal(result.Err)
}
- if err := (<-store.OAuth().GetAppByUser(a1.CreatorId)).Err; err != nil {
+ if err := (<-store.OAuth().GetAppByUser(a1.CreatorId, 0, 1000)).Err; err != nil {
t.Fatal(err)
}
- if err := (<-store.OAuth().GetApps()).Err; err != nil {
+ if err := (<-store.OAuth().GetApps(0, 1000)).Err; err != nil {
t.Fatal(err)
}
}
@@ -324,7 +324,7 @@ func TestOAuthGetAuthorizedApps(t *testing.T) {
Must(store.OAuth().SaveApp(&a1))
// Lets try and get an Authorized app for a user who hasn't authorized it
- if result := <-store.OAuth().GetAuthorizedApps("fake0123456789abcderfgret1"); result.Err == nil {
+ if result := <-store.OAuth().GetAuthorizedApps("fake0123456789abcderfgret1", 0, 1000); result.Err == nil {
if len(result.Data.([]*model.OAuthApp)) > 0 {
t.Fatal("Should have failed. Fake user hasn't authorized the app")
}
@@ -340,7 +340,7 @@ func TestOAuthGetAuthorizedApps(t *testing.T) {
p.Value = "true"
Must(store.Preference().Save(&model.Preferences{p}))
- if result := <-store.OAuth().GetAuthorizedApps(a1.CreatorId); result.Err != nil {
+ if result := <-store.OAuth().GetAuthorizedApps(a1.CreatorId, 0, 1000); result.Err != nil {
t.Fatal(result.Err)
} else {
apps := result.Data.([]*model.OAuthApp)
@@ -368,7 +368,7 @@ func TestOAuthGetAccessDataByUserForApp(t *testing.T) {
p.Value = "true"
Must(store.Preference().Save(&model.Preferences{p}))
- if result := <-store.OAuth().GetAuthorizedApps(a1.CreatorId); result.Err != nil {
+ if result := <-store.OAuth().GetAuthorizedApps(a1.CreatorId, 0, 1000); result.Err != nil {
t.Fatal(result.Err)
} else {
apps := result.Data.([]*model.OAuthApp)
diff --git a/store/sql_post_store.go b/store/sql_post_store.go
index 14580dc5f..9d852abff 100644
--- a/store/sql_post_store.go
+++ b/store/sql_post_store.go
@@ -1,10 +1,11 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
import (
"fmt"
+ "net/http"
"regexp"
"strconv"
"strings"
@@ -13,7 +14,6 @@ import (
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
- "net/http"
)
type SqlPostStore struct {
@@ -237,7 +237,7 @@ func (s SqlPostStore) GetFlaggedPostsForTeam(userId, teamId string, offset int,
Preferences
WHERE
UserId = :UserId
- AND Category = 'flagged_post')
+ AND Category = :Category)
AND DeleteAt = 0
) as A
INNER JOIN Channels as B
@@ -247,7 +247,43 @@ func (s SqlPostStore) GetFlaggedPostsForTeam(userId, teamId string, offset int,
LIMIT :Limit OFFSET :Offset`
if _, err := s.GetReplica().Select(&posts, query, map[string]interface{}{"UserId": userId, "Category": model.PREFERENCE_CATEGORY_FLAGGED_POST, "Offset": offset, "Limit": limit, "TeamId": teamId}); err != nil {
- result.Err = model.NewLocAppError("SqlPostStore.GetFlaggedPosts", "store.sql_post.get_flagged_posts.app_error", nil, err.Error())
+ result.Err = model.NewLocAppError("SqlPostStore.GetFlaggedPostsForTeam", "store.sql_post.get_flagged_posts.app_error", nil, err.Error())
+ } else {
+ for _, post := range posts {
+ pl.AddPost(post)
+ pl.AddOrder(post.Id)
+ }
+ }
+
+ result.Data = pl
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
+
+func (s SqlPostStore) GetFlaggedPostsForChannel(userId, channelId string, offset int, limit int) StoreChannel {
+ storeChannel := make(StoreChannel, 1)
+ go func() {
+ result := StoreResult{}
+ pl := model.NewPostList()
+
+ var posts []*model.Post
+ query := `
+ SELECT
+ *
+ FROM Posts
+ WHERE
+ Id IN (SELECT Name FROM Preferences WHERE UserId = :UserId AND Category = :Category)
+ AND ChannelId = :ChannelId
+ AND DeleteAt = 0
+ ORDER BY CreateAt DESC
+ LIMIT :Limit OFFSET :Offset`
+
+ if _, err := s.GetReplica().Select(&posts, query, map[string]interface{}{"UserId": userId, "Category": model.PREFERENCE_CATEGORY_FLAGGED_POST, "ChannelId": channelId, "Offset": offset, "Limit": limit}); err != nil {
+ result.Err = model.NewLocAppError("SqlPostStore.GetFlaggedPostsForChannel", "store.sql_post.get_flagged_posts.app_error", nil, err.Error())
} else {
for _, post := range posts {
pl.AddPost(post)
@@ -872,6 +908,17 @@ func (s SqlPostStore) Search(teamId string, userId string, params *model.SearchP
go func() {
result := StoreResult{}
+ if !*utils.Cfg.ServiceSettings.EnablePostSearch {
+ list := &model.PostList{}
+ list.MakeNonNil()
+ result.Data = list
+
+ result.Err = model.NewLocAppError("SqlPostStore.Search", "store.sql_post.search.disabled", nil, fmt.Sprintf("teamId=%v userId=%v params=%v", teamId, userId, params.ToJson()))
+ storeChannel <- result
+ close(storeChannel)
+ return
+ }
+
queryParams := map[string]interface{}{
"TeamId": teamId,
"UserId": userId,
@@ -883,6 +930,7 @@ func (s SqlPostStore) Search(teamId string, userId string, params *model.SearchP
if terms == "" && len(params.InChannels) == 0 && len(params.FromUsers) == 0 {
result.Data = []*model.Post{}
storeChannel <- result
+ close(storeChannel)
return
}
diff --git a/store/sql_post_store_test.go b/store/sql_post_store_test.go
index f9dc5499f..b69f0f636 100644
--- a/store/sql_post_store_test.go
+++ b/store/sql_post_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
@@ -1144,6 +1144,18 @@ func TestPostStoreGetFlaggedPostsForTeam(t *testing.T) {
t.Fatal("should have 1 post")
}
+ r3 = (<-store.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 1, 1)).Data.(*model.PostList)
+
+ if len(r3.Order) != 1 {
+ t.Fatal("should have 1 post")
+ }
+
+ r3 = (<-store.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 1000, 10)).Data.(*model.PostList)
+
+ if len(r3.Order) != 0 {
+ t.Fatal("should be empty")
+ }
+
r4 := (<-store.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 2)).Data.(*model.PostList)
if len(r4.Order) != 2 {
@@ -1202,7 +1214,6 @@ func TestPostStoreGetFlaggedPostsForTeam(t *testing.T) {
r4 = (<-store.Post().GetFlaggedPostsForTeam(o1.UserId, c1.TeamId, 0, 10)).Data.(*model.PostList)
if len(r4.Order) != 3 {
- t.Log(len(r4.Order))
t.Fatal("should have 3 posts")
}
}
@@ -1232,7 +1243,7 @@ func TestPostStoreGetFlaggedPosts(t *testing.T) {
o3 = (<-store.Post().Save(o3)).Data.(*model.Post)
time.Sleep(2 * time.Millisecond)
- r1 := (<-store.Post().GetFlaggedPosts(o1.ChannelId, 0, 2)).Data.(*model.PostList)
+ r1 := (<-store.Post().GetFlaggedPosts(o1.UserId, 0, 2)).Data.(*model.PostList)
if len(r1.Order) != 0 {
t.Fatal("should be empty")
@@ -1272,6 +1283,18 @@ func TestPostStoreGetFlaggedPosts(t *testing.T) {
t.Fatal("should have 1 post")
}
+ r3 = (<-store.Post().GetFlaggedPosts(o1.UserId, 1, 1)).Data.(*model.PostList)
+
+ if len(r3.Order) != 1 {
+ t.Fatal("should have 1 post")
+ }
+
+ r3 = (<-store.Post().GetFlaggedPosts(o1.UserId, 1000, 10)).Data.(*model.PostList)
+
+ if len(r3.Order) != 0 {
+ t.Fatal("should be empty")
+ }
+
r4 := (<-store.Post().GetFlaggedPosts(o1.UserId, 0, 2)).Data.(*model.PostList)
if len(r4.Order) != 2 {
@@ -1296,6 +1319,100 @@ func TestPostStoreGetFlaggedPosts(t *testing.T) {
}
}
+func TestPostStoreGetFlaggedPostsForChannel(t *testing.T) {
+ Setup()
+
+ o1 := &model.Post{}
+ o1.ChannelId = model.NewId()
+ o1.UserId = model.NewId()
+ o1.Message = "a" + model.NewId() + "b"
+ o1 = (<-store.Post().Save(o1)).Data.(*model.Post)
+ time.Sleep(2 * time.Millisecond)
+
+ o2 := &model.Post{}
+ o2.ChannelId = o1.ChannelId
+ o2.UserId = model.NewId()
+ o2.Message = "a" + model.NewId() + "b"
+ o2 = (<-store.Post().Save(o2)).Data.(*model.Post)
+ time.Sleep(2 * time.Millisecond)
+
+ // deleted post
+ o3 := &model.Post{}
+ o3.ChannelId = model.NewId()
+ o3.UserId = o1.ChannelId
+ o3.Message = "a" + model.NewId() + "b"
+ o3.DeleteAt = 1
+ o3 = (<-store.Post().Save(o3)).Data.(*model.Post)
+ time.Sleep(2 * time.Millisecond)
+
+ o4 := &model.Post{}
+ o4.ChannelId = model.NewId()
+ o4.UserId = model.NewId()
+ o4.Message = "a" + model.NewId() + "b"
+ o4 = (<-store.Post().Save(o4)).Data.(*model.Post)
+ time.Sleep(2 * time.Millisecond)
+
+ r := (<-store.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 10)).Data.(*model.PostList)
+
+ if len(r.Order) != 0 {
+ t.Fatal("should be empty")
+ }
+
+ preference := model.Preference{
+ UserId: o1.UserId,
+ Category: model.PREFERENCE_CATEGORY_FLAGGED_POST,
+ Name: o1.Id,
+ Value: "true",
+ }
+
+ Must(store.Preference().Save(&model.Preferences{preference}))
+
+ r = (<-store.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 10)).Data.(*model.PostList)
+
+ if len(r.Order) != 1 {
+ t.Fatal("should have 1 post")
+ }
+
+ preference.Name = o2.Id
+ Must(store.Preference().Save(&model.Preferences{preference}))
+
+ preference.Name = o3.Id
+ Must(store.Preference().Save(&model.Preferences{preference}))
+
+ r = (<-store.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 1)).Data.(*model.PostList)
+
+ if len(r.Order) != 1 {
+ t.Fatal("should have 1 post")
+ }
+
+ r = (<-store.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 1, 1)).Data.(*model.PostList)
+
+ if len(r.Order) != 1 {
+ t.Fatal("should have 1 post")
+ }
+
+ r = (<-store.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 1000, 10)).Data.(*model.PostList)
+
+ if len(r.Order) != 0 {
+ t.Fatal("should be empty")
+ }
+
+ r = (<-store.Post().GetFlaggedPostsForChannel(o1.UserId, o1.ChannelId, 0, 10)).Data.(*model.PostList)
+
+ if len(r.Order) != 2 {
+ t.Fatal("should have 2 posts")
+ }
+
+ preference.Name = o4.Id
+ Must(store.Preference().Save(&model.Preferences{preference}))
+
+ r = (<-store.Post().GetFlaggedPostsForChannel(o1.UserId, o4.ChannelId, 0, 10)).Data.(*model.PostList)
+
+ if len(r.Order) != 1 {
+ t.Fatal("should have 1 post")
+ }
+}
+
func TestPostStoreGetPostsCreatedAt(t *testing.T) {
Setup()
diff --git a/store/sql_preference_store.go b/store/sql_preference_store.go
index 14a9ff48b..1ee7c4297 100644
--- a/store/sql_preference_store.go
+++ b/store/sql_preference_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_preference_store_test.go b/store/sql_preference_store_test.go
index adcaa8d89..c0df7a85b 100644
--- a/store/sql_preference_store_test.go
+++ b/store/sql_preference_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_reaction_store.go b/store/sql_reaction_store.go
index cfc7ac944..0d94a500f 100644
--- a/store/sql_reaction_store.go
+++ b/store/sql_reaction_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_reaction_store_test.go b/store/sql_reaction_store_test.go
index 01ce14e65..d71bc7a27 100644
--- a/store/sql_reaction_store_test.go
+++ b/store/sql_reaction_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_recovery_store.go b/store/sql_recovery_store.go
index d62993822..6c073a548 100644
--- a/store/sql_recovery_store.go
+++ b/store/sql_recovery_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_recovery_store_test.go b/store/sql_recovery_store_test.go
index cf1048482..39f5c068b 100644
--- a/store/sql_recovery_store_test.go
+++ b/store/sql_recovery_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_session_store.go b/store/sql_session_store.go
index 5892dab01..d7ea7073b 100644
--- a/store/sql_session_store.go
+++ b/store/sql_session_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_session_store_test.go b/store/sql_session_store_test.go
index aa088b377..2867adadf 100644
--- a/store/sql_session_store_test.go
+++ b/store/sql_session_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_status_store.go b/store/sql_status_store.go
index 49a38a5c9..d57a70f46 100644
--- a/store/sql_status_store.go
+++ b/store/sql_status_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_status_store_test.go b/store/sql_status_store_test.go
index 47561cda0..d7fbe9c24 100644
--- a/store/sql_status_store_test.go
+++ b/store/sql_status_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_store.go b/store/sql_store.go
index acf3f56c5..466042ca2 100644
--- a/store/sql_store.go
+++ b/store/sql_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_store_test.go b/store/sql_store_test.go
index 303cfc18e..3711d5fec 100644
--- a/store/sql_store_test.go
+++ b/store/sql_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_system_store.go b/store/sql_system_store.go
index 803383408..d9a64790e 100644
--- a/store/sql_system_store.go
+++ b/store/sql_system_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_system_store_test.go b/store/sql_system_store_test.go
index ab9c4c0f8..57827f00f 100644
--- a/store/sql_system_store_test.go
+++ b/store/sql_system_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_team_store.go b/store/sql_team_store.go
index 39a39fa0b..e6df0b656 100644
--- a/store/sql_team_store.go
+++ b/store/sql_team_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_team_store_test.go b/store/sql_team_store_test.go
index 3599a6d1a..85c758480 100644
--- a/store/sql_team_store_test.go
+++ b/store/sql_team_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_upgrade.go b/store/sql_upgrade.go
index 549f684bb..b25e7e73d 100644
--- a/store/sql_upgrade.go
+++ b/store/sql_upgrade.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
@@ -15,6 +15,7 @@ import (
)
const (
+ VERSION_3_9_0 = "3.9.0"
VERSION_3_8_0 = "3.8.0"
VERSION_3_7_0 = "3.7.0"
VERSION_3_6_0 = "3.6.0"
@@ -43,6 +44,7 @@ func UpgradeDatabase(sqlStore *SqlStore) {
UpgradeDatabaseToVersion36(sqlStore)
UpgradeDatabaseToVersion37(sqlStore)
UpgradeDatabaseToVersion38(sqlStore)
+ UpgradeDatabaseToVersion39(sqlStore)
// If the SchemaVersion is empty this this is the first time it has ran
// so lets set it to the current version.
@@ -251,3 +253,12 @@ func UpgradeDatabaseToVersion38(sqlStore *SqlStore) {
saveSchemaVersion(sqlStore, VERSION_3_8_0)
}
}
+
+func UpgradeDatabaseToVersion39(sqlStore *SqlStore) {
+ // TODO: Uncomment following condition when version 3.9.0 is released
+ //if shouldPerformUpgrade(sqlStore, VERSION_3_8_0, VERSION_3_9_0) {
+ sqlStore.CreateColumnIfNotExists("OAuthAccessData", "Scope", "varchar(128)", "varchar(128)", model.DEFAULT_SCOPE)
+
+ // saveSchemaVersion(sqlStore, VERSION_3_9_0)
+ //}
+}
diff --git a/store/sql_upgrade_test.go b/store/sql_upgrade_test.go
index 1ff68180d..7a65e5b81 100644
--- a/store/sql_upgrade_test.go
+++ b/store/sql_upgrade_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_user_store.go b/store/sql_user_store.go
index 2b1d34ea9..91c27cf3e 100644
--- a/store/sql_user_store.go
+++ b/store/sql_user_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
@@ -389,8 +389,7 @@ func (us SqlUserStore) Get(id string) StoreChannel {
if obj, err := us.GetReplica().Get(model.User{}, id); err != nil {
result.Err = model.NewLocAppError("SqlUserStore.Get", "store.sql_user.get.app_error", nil, "user_id="+id+", "+err.Error())
} else if obj == nil {
- result.Err = model.NewLocAppError("SqlUserStore.Get", MISSING_ACCOUNT_ERROR, nil, "user_id="+id)
- result.Err.StatusCode = http.StatusNotFound
+ result.Err = model.NewAppError("SqlUserStore.Get", MISSING_ACCOUNT_ERROR, nil, "user_id="+id, http.StatusNotFound)
} else {
result.Data = obj.(*model.User)
}
diff --git a/store/sql_user_store_test.go b/store/sql_user_store_test.go
index 84b7712aa..94fd30a6f 100644
--- a/store/sql_user_store_test.go
+++ b/store/sql_user_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_webhook_store.go b/store/sql_webhook_store.go
index 67290c983..1d750efac 100644
--- a/store/sql_webhook_store.go
+++ b/store/sql_webhook_store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/sql_webhook_store_test.go b/store/sql_webhook_store_test.go
index fbaf4bc82..f5e328b32 100644
--- a/store/sql_webhook_store_test.go
+++ b/store/sql_webhook_store_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
diff --git a/store/store.go b/store/store.go
index 3e508dfa5..18f7374dc 100644
--- a/store/store.go
+++ b/store/store.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package store
@@ -150,6 +150,7 @@ type PostStore interface {
GetPosts(channelId string, offset int, limit int, allowFromCache bool) StoreChannel
GetFlaggedPosts(userId string, offset int, limit int) StoreChannel
GetFlaggedPostsForTeam(userId, teamId string, offset int, limit int) StoreChannel
+ GetFlaggedPostsForChannel(userId, channelId string, offset int, limit int) StoreChannel
GetPostsBefore(channelId string, postId string, numPosts int, offset int) StoreChannel
GetPostsAfter(channelId string, postId string, numPosts int, offset int) StoreChannel
GetPostsSince(channelId string, time int64, allowFromCache bool) StoreChannel
@@ -245,9 +246,9 @@ type OAuthStore interface {
SaveApp(app *model.OAuthApp) StoreChannel
UpdateApp(app *model.OAuthApp) StoreChannel
GetApp(id string) StoreChannel
- GetAppByUser(userId string) StoreChannel
- GetApps() StoreChannel
- GetAuthorizedApps(userId string) StoreChannel
+ GetAppByUser(userId string, offset, limit int) StoreChannel
+ GetApps(offset, limit int) StoreChannel
+ GetAuthorizedApps(userId string, offset, limit int) StoreChannel
DeleteApp(id string) StoreChannel
SaveAuthData(authData *model.AuthData) StoreChannel
GetAuthData(code string) StoreChannel
diff --git a/utils/api.go b/utils/api.go
index 388271bd2..228808f3c 100644
--- a/utils/api.go
+++ b/utils/api.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/authorization.go b/utils/authorization.go
index 8078f4023..7dbb0c808 100644
--- a/utils/authorization.go
+++ b/utils/authorization.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/config.go b/utils/config.go
index 8c80d5349..802dfc2e9 100644
--- a/utils/config.go
+++ b/utils/config.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
@@ -37,6 +37,7 @@ var CfgDiagnosticId = ""
var CfgHash = ""
var ClientCfgHash = ""
var CfgFileName string = ""
+var CfgDisableConfigWatch = false
var ClientCfg map[string]string = map[string]string{}
var originalDisableDebugLvl l4g.Level = l4g.DEBUG
var siteURL = ""
@@ -67,6 +68,8 @@ func FindDir(dir string) string {
fileName, _ = filepath.Abs("./" + dir + "/")
} else if _, err := os.Stat("../" + dir + "/"); err == nil {
fileName, _ = filepath.Abs("../" + dir + "/")
+ } else if _, err := os.Stat("../../" + dir + "/"); err == nil {
+ fileName, _ = filepath.Abs("../../" + dir + "/")
}
return fileName + "/"
@@ -177,6 +180,10 @@ func InitializeConfigWatch() {
cfgMutex.Lock()
defer cfgMutex.Unlock()
+ if CfgDisableConfigWatch {
+ return
+ }
+
if watcher == nil {
var err error
watcher, err = fsnotify.NewWatcher()
@@ -214,11 +221,13 @@ func EnableConfigWatch() {
cfgMutex.Lock()
defer cfgMutex.Unlock()
- configFile := filepath.Clean(CfgFileName)
- configDir, _ := filepath.Split(configFile)
-
if watcher != nil {
- watcher.Add(configDir)
+ configFile := filepath.Clean(CfgFileName)
+ configDir, _ := filepath.Split(configFile)
+
+ if watcher != nil {
+ watcher.Add(configDir)
+ }
}
}
@@ -258,6 +267,7 @@ func LoadConfig(fileName string) {
viper.SetConfigType("json")
viper.AddConfigPath("./config")
viper.AddConfigPath("../config")
+ viper.AddConfigPath("../../config")
viper.AddConfigPath(".")
configReadErr := viper.ReadInConfig()
diff --git a/utils/config_test.go b/utils/config_test.go
index c15165fe5..755cd9acd 100644
--- a/utils/config_test.go
+++ b/utils/config_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/emoji.go b/utils/emoji.go
new file mode 100644
index 000000000..ced3c4ddd
--- /dev/null
+++ b/utils/emoji.go
@@ -0,0 +1,62 @@
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// See License.txt for license information.
+
+package utils
+
+import (
+ "bytes"
+ "image"
+ "image/color"
+ "image/gif"
+ "image/jpeg"
+ "image/png"
+ "testing"
+)
+
+func CreateTestGif(t *testing.T, width int, height int) []byte {
+ var buffer bytes.Buffer
+
+ if err := gif.Encode(&buffer, image.NewRGBA(image.Rect(0, 0, width, height)), nil); err != nil {
+ t.Fatalf("failed to create gif: %v", err.Error())
+ }
+
+ return buffer.Bytes()
+}
+
+func CreateTestAnimatedGif(t *testing.T, width int, height int, frames int) []byte {
+ var buffer bytes.Buffer
+
+ img := gif.GIF{
+ Image: make([]*image.Paletted, frames, frames),
+ Delay: make([]int, frames, frames),
+ }
+ for i := 0; i < frames; i++ {
+ img.Image[i] = image.NewPaletted(image.Rect(0, 0, width, height), color.Palette{color.Black})
+ img.Delay[i] = 0
+ }
+ if err := gif.EncodeAll(&buffer, &img); err != nil {
+ t.Fatalf("failed to create animated gif: %v", err.Error())
+ }
+
+ return buffer.Bytes()
+}
+
+func CreateTestJpeg(t *testing.T, width int, height int) []byte {
+ var buffer bytes.Buffer
+
+ if err := jpeg.Encode(&buffer, image.NewRGBA(image.Rect(0, 0, width, height)), nil); err != nil {
+ t.Fatalf("failed to create jpeg: %v", err.Error())
+ }
+
+ return buffer.Bytes()
+}
+
+func CreateTestPng(t *testing.T, width int, height int) []byte {
+ var buffer bytes.Buffer
+
+ if err := png.Encode(&buffer, image.NewRGBA(image.Rect(0, 0, width, height))); err != nil {
+ t.Fatalf("failed to create png: %v", err.Error())
+ }
+
+ return buffer.Bytes()
+}
diff --git a/utils/html.go b/utils/html.go
index 48033b43e..c902030d8 100644
--- a/utils/html.go
+++ b/utils/html.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/license.go b/utils/license.go
index f0763d741..d3e2c1362 100644
--- a/utils/license.go
+++ b/utils/license.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/license_test.go b/utils/license_test.go
index 7a30070b3..289262f4c 100644
--- a/utils/license_test.go
+++ b/utils/license_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/log.go b/utils/log.go
index 360c785d0..ab2750f36 100644
--- a/utils/log.go
+++ b/utils/log.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/mail.go b/utils/mail.go
index 959a60fb2..ea62fab12 100644
--- a/utils/mail.go
+++ b/utils/mail.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/mail_test.go b/utils/mail_test.go
index 523ca0ba5..774ecbf5b 100644
--- a/utils/mail_test.go
+++ b/utils/mail_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/password.go b/utils/password.go
index b129869d3..6aa785df8 100644
--- a/utils/password.go
+++ b/utils/password.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/random.go b/utils/random.go
index 99743e777..8f3008f9d 100644
--- a/utils/random.go
+++ b/utils/random.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/textgeneration.go b/utils/textgeneration.go
index 96c43f402..eeabe4705 100644
--- a/utils/textgeneration.go
+++ b/utils/textgeneration.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/time_test.go b/utils/time_test.go
index 7d65046bf..451ceb5aa 100644
--- a/utils/time_test.go
+++ b/utils/time_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/urlencode.go b/utils/urlencode.go
index dc8b9acfd..0110ab6e3 100644
--- a/utils/urlencode.go
+++ b/utils/urlencode.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/urlencode_test.go b/utils/urlencode_test.go
index 04d69fd98..2ba453c73 100644
--- a/utils/urlencode_test.go
+++ b/utils/urlencode_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/utils.go b/utils/utils.go
index 6d34387c4..f34c82f24 100644
--- a/utils/utils.go
+++ b/utils/utils.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/utils/utils_test.go b/utils/utils_test.go
index 88356dadb..b80247867 100644
--- a/utils/utils_test.go
+++ b/utils/utils_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package utils
diff --git a/web/web.go b/web/web.go
index 1ee216d55..8155f2016 100644
--- a/web/web.go
+++ b/web/web.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package web
diff --git a/web/web_test.go b/web/web_test.go
index 0e5353d19..9968bef08 100644
--- a/web/web_test.go
+++ b/web/web_test.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package web
diff --git a/webapp/actions/admin_actions.jsx b/webapp/actions/admin_actions.jsx
index 73b73c130..ee3d6fd8a 100644
--- a/webapp/actions/admin_actions.jsx
+++ b/webapp/actions/admin_actions.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Client from 'client/web_client.jsx';
diff --git a/webapp/actions/channel_actions.jsx b/webapp/actions/channel_actions.jsx
index ea2039047..d441a0e94 100644
--- a/webapp/actions/channel_actions.jsx
+++ b/webapp/actions/channel_actions.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
@@ -432,10 +432,10 @@ export function createChannel(channel, success, error) {
}
},
(err) => {
- AsyncClient.dispatchError(err, 'createChannel');
-
if (error) {
error(err);
+ } else {
+ AsyncClient.dispatchError(err, 'createChannel');
}
}
);
diff --git a/webapp/actions/diagnostics_actions.jsx b/webapp/actions/diagnostics_actions.jsx
index b093d8e8b..4ffdfa552 100644
--- a/webapp/actions/diagnostics_actions.jsx
+++ b/webapp/actions/diagnostics_actions.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Client from 'client/web_client.jsx';
diff --git a/webapp/actions/emoji_actions.jsx b/webapp/actions/emoji_actions.jsx
index 128a9325a..feb6bd76b 100644
--- a/webapp/actions/emoji_actions.jsx
+++ b/webapp/actions/emoji_actions.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
diff --git a/webapp/actions/file_actions.jsx b/webapp/actions/file_actions.jsx
index 0399a2c28..204f452d8 100644
--- a/webapp/actions/file_actions.jsx
+++ b/webapp/actions/file_actions.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as AsyncClient from 'utils/async_client.jsx';
diff --git a/webapp/actions/global_actions.jsx b/webapp/actions/global_actions.jsx
index f067a80be..c81bb02ac 100644
--- a/webapp/actions/global_actions.jsx
+++ b/webapp/actions/global_actions.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
@@ -525,7 +525,7 @@ export function clientLogout(redirectTo = '/') {
export function emitSearchMentionsEvent(user) {
let terms = '';
- if (user.notify_props && user.notify_props.mention_keys) {
+ if (user.notify_props) {
const termKeys = UserStore.getMentionKeys(user.id);
if (termKeys.indexOf('@channel') !== -1) {
diff --git a/webapp/actions/integration_actions.jsx b/webapp/actions/integration_actions.jsx
index 5fd2b024d..43a4c75f4 100644
--- a/webapp/actions/integration_actions.jsx
+++ b/webapp/actions/integration_actions.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
diff --git a/webapp/actions/notification_actions.jsx b/webapp/actions/notification_actions.jsx
index 50b300336..82a68c452 100644
--- a/webapp/actions/notification_actions.jsx
+++ b/webapp/actions/notification_actions.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Constants from 'utils/constants.jsx';
diff --git a/webapp/actions/oauth_actions.jsx b/webapp/actions/oauth_actions.jsx
index 07b4c2908..d7e033604 100644
--- a/webapp/actions/oauth_actions.jsx
+++ b/webapp/actions/oauth_actions.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Client from 'client/web_client.jsx';
@@ -57,4 +57,4 @@ export function registerOAuthApp(app, onSuccess, onError) {
},
onError
);
-} \ No newline at end of file
+}
diff --git a/webapp/actions/post_actions.jsx b/webapp/actions/post_actions.jsx
index 3af99f9fa..5319a00c6 100644
--- a/webapp/actions/post_actions.jsx
+++ b/webapp/actions/post_actions.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
diff --git a/webapp/actions/status_actions.jsx b/webapp/actions/status_actions.jsx
index 242e6aea0..649df835a 100644
--- a/webapp/actions/status_actions.jsx
+++ b/webapp/actions/status_actions.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
diff --git a/webapp/actions/team_actions.jsx b/webapp/actions/team_actions.jsx
index b091692f8..1dcfecbab 100644
--- a/webapp/actions/team_actions.jsx
+++ b/webapp/actions/team_actions.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import UserStore from 'stores/user_store.jsx';
diff --git a/webapp/actions/user_actions.jsx b/webapp/actions/user_actions.jsx
index ecbe83feb..9f9987cdd 100644
--- a/webapp/actions/user_actions.jsx
+++ b/webapp/actions/user_actions.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
diff --git a/webapp/actions/webrtc_actions.jsx b/webapp/actions/webrtc_actions.jsx
index b096e1c33..65820f35c 100644
--- a/webapp/actions/webrtc_actions.jsx
+++ b/webapp/actions/webrtc_actions.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
diff --git a/webapp/actions/websocket_actions.jsx b/webapp/actions/websocket_actions.jsx
index e9ebea472..916abb5af 100644
--- a/webapp/actions/websocket_actions.jsx
+++ b/webapp/actions/websocket_actions.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/client/browser_web_client.jsx b/webapp/client/browser_web_client.jsx
index 8f32f4e26..1d5e4cd84 100644
--- a/webapp/client/browser_web_client.jsx
+++ b/webapp/client/browser_web_client.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Client from './client.jsx';
diff --git a/webapp/client/client.jsx b/webapp/client/client.jsx
index 6e04b1f7a..697687a5f 100644
--- a/webapp/client/client.jsx
+++ b/webapp/client/client.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import request from 'superagent';
diff --git a/webapp/client/web_client.jsx b/webapp/client/web_client.jsx
index 925b53522..6ae2e2ebe 100644
--- a/webapp/client/web_client.jsx
+++ b/webapp/client/web_client.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
// This file is only for testing on non-browser environments.
diff --git a/webapp/client/web_websocket_client.jsx b/webapp/client/web_websocket_client.jsx
index d05207608..775c0ff59 100644
--- a/webapp/client/web_websocket_client.jsx
+++ b/webapp/client/web_websocket_client.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import WebSocketClient from './websocket_client.jsx';
diff --git a/webapp/client/websocket_client.jsx b/webapp/client/websocket_client.jsx
index 1cf97b788..eaa059197 100644
--- a/webapp/client/websocket_client.jsx
+++ b/webapp/client/websocket_client.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
const MAX_WEBSOCKET_FAILS = 7;
diff --git a/webapp/components/about_build_modal.jsx b/webapp/components/about_build_modal.jsx
index 71aee93c2..6fd2d8c03 100644
--- a/webapp/components/about_build_modal.jsx
+++ b/webapp/components/about_build_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {Modal} from 'react-bootstrap';
@@ -158,7 +158,10 @@ export default class AboutBuildModal extends React.Component {
<div className='form-group about-modal__copyright'>
<FormattedMessage
id='about.copyright'
- defaultMessage='Copyright 2016 Mattermost, Inc. All rights reserved'
+ defaultMessage='Copyright 2015 - {currentYear} Mattermost, Inc. All rights reserved'
+ values={{
+ currentYear: new Date().getFullYear()
+ }}
/>
</div>
</div>
diff --git a/webapp/components/access_history_modal.jsx b/webapp/components/access_history_modal.jsx
index 4e1e69e3e..25c7ef380 100644
--- a/webapp/components/access_history_modal.jsx
+++ b/webapp/components/access_history_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import LoadingScreen from './loading_screen.jsx';
diff --git a/webapp/components/activity_log_modal.jsx b/webapp/components/activity_log_modal.jsx
index 05c09ab88..8890a1d19 100644
--- a/webapp/components/activity_log_modal.jsx
+++ b/webapp/components/activity_log_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import LoadingScreen from './loading_screen.jsx';
diff --git a/webapp/components/add_users_to_team.jsx b/webapp/components/add_users_to_team.jsx
index fce651d9f..c03d9ccd9 100644
--- a/webapp/components/add_users_to_team.jsx
+++ b/webapp/components/add_users_to_team.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import MultiSelect from 'components/multiselect/multiselect.jsx';
diff --git a/webapp/components/admin_console/admin_console.jsx b/webapp/components/admin_console/admin_console.jsx
index 5b6909e34..d00293f04 100644
--- a/webapp/components/admin_console/admin_console.jsx
+++ b/webapp/components/admin_console/admin_console.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/admin_navbar_dropdown.jsx b/webapp/components/admin_console/admin_navbar_dropdown.jsx
index b4fd889bc..00cbbdb0c 100644
--- a/webapp/components/admin_console/admin_navbar_dropdown.jsx
+++ b/webapp/components/admin_console/admin_navbar_dropdown.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
@@ -15,6 +15,8 @@ import {Link} from 'react-router/es6';
import React from 'react';
+import * as Utils from 'utils/utils.jsx';
+
export default class AdminNavbarDropdown extends React.Component {
constructor(props) {
super(props);
@@ -71,6 +73,7 @@ export default class AdminNavbarDropdown extends React.Component {
teams.push(
<li key={'team_' + team.name}>
<Link
+ id={'swithTo' + Utils.createSafeId(team.name)}
to={'/' + team.name + '/channels/town-square'}
>
<FormattedMessage
@@ -113,6 +116,7 @@ export default class AdminNavbarDropdown extends React.Component {
>
<a
href='#'
+ id='adminNavbarDropdownButton'
className='dropdown-toggle admin-navbar-dropdown__toggle'
data-toggle='dropdown'
role='button'
@@ -136,6 +140,7 @@ export default class AdminNavbarDropdown extends React.Component {
<li>
<a
href='#'
+ id='logout'
onClick={() => GlobalActions.emitUserLoggedOutEvent()}
>
<FormattedMessage
diff --git a/webapp/components/admin_console/admin_settings.jsx b/webapp/components/admin_console/admin_settings.jsx
index ffb10d9ec..b21a84c05 100644
--- a/webapp/components/admin_console/admin_settings.jsx
+++ b/webapp/components/admin_console/admin_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/admin_sidebar.jsx b/webapp/components/admin_console/admin_sidebar.jsx
index aa7b970e0..a2f2b75c0 100644
--- a/webapp/components/admin_console/admin_sidebar.jsx
+++ b/webapp/components/admin_console/admin_sidebar.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/admin_console/admin_sidebar_category.jsx b/webapp/components/admin_console/admin_sidebar_category.jsx
index 1cf96f979..97e2f7d5d 100644
--- a/webapp/components/admin_console/admin_sidebar_category.jsx
+++ b/webapp/components/admin_console/admin_sidebar_category.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/admin_sidebar_header.jsx b/webapp/components/admin_console/admin_sidebar_header.jsx
index 5725551bf..87a1170dc 100644
--- a/webapp/components/admin_console/admin_sidebar_header.jsx
+++ b/webapp/components/admin_console/admin_sidebar_header.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/admin_console/admin_sidebar_section.jsx b/webapp/components/admin_console/admin_sidebar_section.jsx
index c15291de9..53720ef98 100644
--- a/webapp/components/admin_console/admin_sidebar_section.jsx
+++ b/webapp/components/admin_console/admin_sidebar_section.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/audits.jsx b/webapp/components/admin_console/audits.jsx
index 47a7e8d89..594e55e39 100644
--- a/webapp/components/admin_console/audits.jsx
+++ b/webapp/components/admin_console/audits.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import LoadingScreen from '../loading_screen.jsx';
diff --git a/webapp/components/admin_console/banner.jsx b/webapp/components/admin_console/banner.jsx
index 2071fff93..964d070bc 100644
--- a/webapp/components/admin_console/banner.jsx
+++ b/webapp/components/admin_console/banner.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/boolean_setting.jsx b/webapp/components/admin_console/boolean_setting.jsx
index bdc1d79bf..b7c1997c3 100644
--- a/webapp/components/admin_console/boolean_setting.jsx
+++ b/webapp/components/admin_console/boolean_setting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/brand_image_setting.jsx b/webapp/components/admin_console/brand_image_setting.jsx
index b58c0159c..4ceac1b91 100644
--- a/webapp/components/admin_console/brand_image_setting.jsx
+++ b/webapp/components/admin_console/brand_image_setting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/admin_console/cluster_settings.jsx b/webapp/components/admin_console/cluster_settings.jsx
index d3768ec25..895a87ce1 100644
--- a/webapp/components/admin_console/cluster_settings.jsx
+++ b/webapp/components/admin_console/cluster_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/cluster_table.jsx b/webapp/components/admin_console/cluster_table.jsx
index 34df04710..b291387ea 100644
--- a/webapp/components/admin_console/cluster_table.jsx
+++ b/webapp/components/admin_console/cluster_table.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/cluster_table_container.jsx b/webapp/components/admin_console/cluster_table_container.jsx
index 8dba80cce..7a67bb842 100644
--- a/webapp/components/admin_console/cluster_table_container.jsx
+++ b/webapp/components/admin_console/cluster_table_container.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
@@ -11,6 +11,9 @@ export default class ClusterTableContainer extends React.Component {
constructor(props) {
super(props);
+ this.load = this.load.bind(this);
+ this.reload = this.reload.bind(this);
+
this.interval = null;
this.state = {
diff --git a/webapp/components/admin_console/compliance_reports.jsx b/webapp/components/admin_console/compliance_reports.jsx
index 7274e6774..567a6ca04 100644
--- a/webapp/components/admin_console/compliance_reports.jsx
+++ b/webapp/components/admin_console/compliance_reports.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/admin_console/compliance_settings.jsx b/webapp/components/admin_console/compliance_settings.jsx
index e2df967d5..5521c6e39 100644
--- a/webapp/components/admin_console/compliance_settings.jsx
+++ b/webapp/components/admin_console/compliance_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/configuration_settings.jsx b/webapp/components/admin_console/configuration_settings.jsx
index 16ebf1952..47d3a665e 100644
--- a/webapp/components/admin_console/configuration_settings.jsx
+++ b/webapp/components/admin_console/configuration_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/connection_security_dropdown_setting.jsx b/webapp/components/admin_console/connection_security_dropdown_setting.jsx
index cc58bdd10..09cee0853 100644
--- a/webapp/components/admin_console/connection_security_dropdown_setting.jsx
+++ b/webapp/components/admin_console/connection_security_dropdown_setting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/connection_settings.jsx b/webapp/components/admin_console/connection_settings.jsx
index b35f3acf7..78a0b89ed 100644
--- a/webapp/components/admin_console/connection_settings.jsx
+++ b/webapp/components/admin_console/connection_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/custom_brand_settings.jsx b/webapp/components/admin_console/custom_brand_settings.jsx
index 48954ef78..4ca3dee0c 100644
--- a/webapp/components/admin_console/custom_brand_settings.jsx
+++ b/webapp/components/admin_console/custom_brand_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/custom_emoji_settings.jsx b/webapp/components/admin_console/custom_emoji_settings.jsx
index c1457d7e9..8ab8cde4e 100644
--- a/webapp/components/admin_console/custom_emoji_settings.jsx
+++ b/webapp/components/admin_console/custom_emoji_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/custom_integrations_settings.jsx b/webapp/components/admin_console/custom_integrations_settings.jsx
index 63015a061..18fdd22fd 100644
--- a/webapp/components/admin_console/custom_integrations_settings.jsx
+++ b/webapp/components/admin_console/custom_integrations_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/database_settings.jsx b/webapp/components/admin_console/database_settings.jsx
index 84adae29c..f4fbdbc72 100644
--- a/webapp/components/admin_console/database_settings.jsx
+++ b/webapp/components/admin_console/database_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/developer_settings.jsx b/webapp/components/admin_console/developer_settings.jsx
index 3bcc2a19b..34fb754d8 100644
--- a/webapp/components/admin_console/developer_settings.jsx
+++ b/webapp/components/admin_console/developer_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
@@ -71,7 +71,7 @@ export default class DeveloperSettings extends AdminSettings {
helpText={
<FormattedMessage
id='admin.service.developerDesc'
- defaultMessage='When true, JavaScript errors are shown in a red bar at the top of the user interface. Not recommended for use in production. '
+ defaultMessage='When true, JavaScript errors are shown in a purple bar at the top of the user interface. Not recommended for use in production. '
/>
}
value={this.state.enableDeveloper}
diff --git a/webapp/components/admin_console/dropdown_setting.jsx b/webapp/components/admin_console/dropdown_setting.jsx
index cf733ec90..a3741a629 100644
--- a/webapp/components/admin_console/dropdown_setting.jsx
+++ b/webapp/components/admin_console/dropdown_setting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/email_authentication_settings.jsx b/webapp/components/admin_console/email_authentication_settings.jsx
index 177f36d64..2361a3ab8 100644
--- a/webapp/components/admin_console/email_authentication_settings.jsx
+++ b/webapp/components/admin_console/email_authentication_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/email_connection_test.jsx b/webapp/components/admin_console/email_connection_test.jsx
index b99633eec..e8c3ed316 100644
--- a/webapp/components/admin_console/email_connection_test.jsx
+++ b/webapp/components/admin_console/email_connection_test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/email_settings.jsx b/webapp/components/admin_console/email_settings.jsx
index d54ab3906..959bbec7f 100644
--- a/webapp/components/admin_console/email_settings.jsx
+++ b/webapp/components/admin_console/email_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/external_service_settings.jsx b/webapp/components/admin_console/external_service_settings.jsx
index 21fc6c106..6359470a8 100644
--- a/webapp/components/admin_console/external_service_settings.jsx
+++ b/webapp/components/admin_console/external_service_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/file_upload_setting.jsx b/webapp/components/admin_console/file_upload_setting.jsx
index 85cb7f499..735853ff5 100644
--- a/webapp/components/admin_console/file_upload_setting.jsx
+++ b/webapp/components/admin_console/file_upload_setting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/admin_console/generated_setting.jsx b/webapp/components/admin_console/generated_setting.jsx
index d4feb9332..9103d1804 100644
--- a/webapp/components/admin_console/generated_setting.jsx
+++ b/webapp/components/admin_console/generated_setting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/gitlab_settings.jsx b/webapp/components/admin_console/gitlab_settings.jsx
index 6ba2245b8..d08597b7d 100644
--- a/webapp/components/admin_console/gitlab_settings.jsx
+++ b/webapp/components/admin_console/gitlab_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/image_settings.jsx b/webapp/components/admin_console/image_settings.jsx
index 0249e3979..94f893ee2 100644
--- a/webapp/components/admin_console/image_settings.jsx
+++ b/webapp/components/admin_console/image_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/ldap_settings.jsx b/webapp/components/admin_console/ldap_settings.jsx
index 50883ac22..f5d95634d 100644
--- a/webapp/components/admin_console/ldap_settings.jsx
+++ b/webapp/components/admin_console/ldap_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AdminSettings from './admin_settings.jsx';
diff --git a/webapp/components/admin_console/ldap_test_button.jsx b/webapp/components/admin_console/ldap_test_button.jsx
index a564fa42a..2a3559d25 100644
--- a/webapp/components/admin_console/ldap_test_button.jsx
+++ b/webapp/components/admin_console/ldap_test_button.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/legal_and_support_settings.jsx b/webapp/components/admin_console/legal_and_support_settings.jsx
index b0f85f43d..2d9cb2550 100644
--- a/webapp/components/admin_console/legal_and_support_settings.jsx
+++ b/webapp/components/admin_console/legal_and_support_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/license_settings.jsx b/webapp/components/admin_console/license_settings.jsx
index 7e77f44b6..84867ab2e 100644
--- a/webapp/components/admin_console/license_settings.jsx
+++ b/webapp/components/admin_console/license_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/admin_console/link_previews_settings.jsx b/webapp/components/admin_console/link_previews_settings.jsx
index f223ccc3e..b120d75d2 100644
--- a/webapp/components/admin_console/link_previews_settings.jsx
+++ b/webapp/components/admin_console/link_previews_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/localization_settings.jsx b/webapp/components/admin_console/localization_settings.jsx
index b3e8a7b65..78b63b163 100644
--- a/webapp/components/admin_console/localization_settings.jsx
+++ b/webapp/components/admin_console/localization_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/log_settings.jsx b/webapp/components/admin_console/log_settings.jsx
index e18cb8a23..8e1e4891e 100644
--- a/webapp/components/admin_console/log_settings.jsx
+++ b/webapp/components/admin_console/log_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/logs.jsx b/webapp/components/admin_console/logs.jsx
index d2464b37f..c8405a2f7 100644
--- a/webapp/components/admin_console/logs.jsx
+++ b/webapp/components/admin_console/logs.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AdminStore from 'stores/admin_store.jsx';
diff --git a/webapp/components/admin_console/manage_teams_modal/manage_teams_dropdown.jsx b/webapp/components/admin_console/manage_teams_modal/manage_teams_dropdown.jsx
index 81e6460af..798d61f46 100644
--- a/webapp/components/admin_console/manage_teams_modal/manage_teams_dropdown.jsx
+++ b/webapp/components/admin_console/manage_teams_modal/manage_teams_dropdown.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/manage_teams_modal/manage_teams_modal.jsx b/webapp/components/admin_console/manage_teams_modal/manage_teams_modal.jsx
index e3eae6310..0c30203b4 100644
--- a/webapp/components/admin_console/manage_teams_modal/manage_teams_modal.jsx
+++ b/webapp/components/admin_console/manage_teams_modal/manage_teams_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/manage_teams_modal/remove_from_team_button.jsx b/webapp/components/admin_console/manage_teams_modal/remove_from_team_button.jsx
index d733135f4..d95a816f2 100644
--- a/webapp/components/admin_console/manage_teams_modal/remove_from_team_button.jsx
+++ b/webapp/components/admin_console/manage_teams_modal/remove_from_team_button.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/metrics_settings.jsx b/webapp/components/admin_console/metrics_settings.jsx
index 607a21fb9..9eab4073b 100644
--- a/webapp/components/admin_console/metrics_settings.jsx
+++ b/webapp/components/admin_console/metrics_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/mfa_settings.jsx b/webapp/components/admin_console/mfa_settings.jsx
index 7ae1f2e18..9d7a64d05 100644
--- a/webapp/components/admin_console/mfa_settings.jsx
+++ b/webapp/components/admin_console/mfa_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AdminSettings from './admin_settings.jsx';
diff --git a/webapp/components/admin_console/multiselect_settings.jsx b/webapp/components/admin_console/multiselect_settings.jsx
index 2beebb337..c73eb6a79 100644
--- a/webapp/components/admin_console/multiselect_settings.jsx
+++ b/webapp/components/admin_console/multiselect_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
import ReactSelect from 'react-select';
diff --git a/webapp/components/admin_console/native_app_link_settings.jsx b/webapp/components/admin_console/native_app_link_settings.jsx
index d932af645..88c078476 100644
--- a/webapp/components/admin_console/native_app_link_settings.jsx
+++ b/webapp/components/admin_console/native_app_link_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/oauth_settings.jsx b/webapp/components/admin_console/oauth_settings.jsx
index f5eac13eb..abb4dc762 100644
--- a/webapp/components/admin_console/oauth_settings.jsx
+++ b/webapp/components/admin_console/oauth_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as Utils from 'utils/utils.jsx';
diff --git a/webapp/components/admin_console/password_settings.jsx b/webapp/components/admin_console/password_settings.jsx
index edb9669e1..68506fcfe 100644
--- a/webapp/components/admin_console/password_settings.jsx
+++ b/webapp/components/admin_console/password_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
@@ -53,9 +53,10 @@ export default class PasswordSettings extends AdminSettings {
this.sampleErrorMsg = (
<FormattedMessage
id={sampleErrorMsgId}
- default='Your password must be at least {min} characters.'
+ default='Your password must contain between {min} and {max} characters.'
values={{
- min: (this.state.passwordMinimumLength || Constants.MIN_PASSWORD_LENGTH)
+ min: (this.state.passwordMinimumLength || Constants.MIN_PASSWORD_LENGTH),
+ max: Constants.MAX_PASSWORD_LENGTH
}}
/>
);
@@ -115,9 +116,10 @@ export default class PasswordSettings extends AdminSettings {
return (
<FormattedMessage
id={sampleErrorMsgId}
- default='Your password must be at least {min} characters.'
+ default='Your password must contain between {min} and {max} characters.'
values={{
- min: (minLength || Constants.MIN_PASSWORD_LENGTH)
+ min: (minLength || Constants.MIN_PASSWORD_LENGTH),
+ max: Constants.MAX_PASSWORD_LENGTH
}}
/>
);
diff --git a/webapp/components/admin_console/policy_settings.jsx b/webapp/components/admin_console/policy_settings.jsx
index 3fb753edc..7d2985001 100644
--- a/webapp/components/admin_console/policy_settings.jsx
+++ b/webapp/components/admin_console/policy_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/post_edit_setting.jsx b/webapp/components/admin_console/post_edit_setting.jsx
index 282a1b6c5..9480409fd 100644
--- a/webapp/components/admin_console/post_edit_setting.jsx
+++ b/webapp/components/admin_console/post_edit_setting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/privacy_settings.jsx b/webapp/components/admin_console/privacy_settings.jsx
index 518ec807e..92fcb3e88 100644
--- a/webapp/components/admin_console/privacy_settings.jsx
+++ b/webapp/components/admin_console/privacy_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/public_link_settings.jsx b/webapp/components/admin_console/public_link_settings.jsx
index 592d607d1..a10574353 100644
--- a/webapp/components/admin_console/public_link_settings.jsx
+++ b/webapp/components/admin_console/public_link_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/purge_caches.jsx b/webapp/components/admin_console/purge_caches.jsx
index 9f52433d5..d2337d587 100644
--- a/webapp/components/admin_console/purge_caches.jsx
+++ b/webapp/components/admin_console/purge_caches.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/push_settings.jsx b/webapp/components/admin_console/push_settings.jsx
index 2fc63afe0..5a2f6d89b 100644
--- a/webapp/components/admin_console/push_settings.jsx
+++ b/webapp/components/admin_console/push_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/radio_setting.jsx b/webapp/components/admin_console/radio_setting.jsx
index dd45a5a26..100fab983 100644
--- a/webapp/components/admin_console/radio_setting.jsx
+++ b/webapp/components/admin_console/radio_setting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/rate_settings.jsx b/webapp/components/admin_console/rate_settings.jsx
index 9b0a8076f..a0cf14f75 100644
--- a/webapp/components/admin_console/rate_settings.jsx
+++ b/webapp/components/admin_console/rate_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/recycle_db.jsx b/webapp/components/admin_console/recycle_db.jsx
index 5683f97e2..5e536d908 100644
--- a/webapp/components/admin_console/recycle_db.jsx
+++ b/webapp/components/admin_console/recycle_db.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
@@ -108,4 +108,4 @@ export default class RecycleDbButton extends React.Component {
</div>
);
}
-} \ No newline at end of file
+}
diff --git a/webapp/components/admin_console/reload_config.jsx b/webapp/components/admin_console/reload_config.jsx
index 25e9463d3..ad3d9cca7 100644
--- a/webapp/components/admin_console/reload_config.jsx
+++ b/webapp/components/admin_console/reload_config.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/remove_file_setting.jsx b/webapp/components/admin_console/remove_file_setting.jsx
index 9a6266a62..4590b7ff6 100644
--- a/webapp/components/admin_console/remove_file_setting.jsx
+++ b/webapp/components/admin_console/remove_file_setting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
@@ -58,4 +58,4 @@ export default class RemoveFileSetting extends Setting {
</Setting>
);
}
-} \ No newline at end of file
+}
diff --git a/webapp/components/admin_console/reset_password_modal.jsx b/webapp/components/admin_console/reset_password_modal.jsx
index d01fc15f3..02bb00ab8 100644
--- a/webapp/components/admin_console/reset_password_modal.jsx
+++ b/webapp/components/admin_console/reset_password_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as Utils from 'utils/utils.jsx';
diff --git a/webapp/components/admin_console/saml_settings.jsx b/webapp/components/admin_console/saml_settings.jsx
index 6025abe28..0754747d9 100644
--- a/webapp/components/admin_console/saml_settings.jsx
+++ b/webapp/components/admin_console/saml_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/save_button.jsx b/webapp/components/admin_console/save_button.jsx
index fd7045605..b548c28ac 100644
--- a/webapp/components/admin_console/save_button.jsx
+++ b/webapp/components/admin_console/save_button.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/session_settings.jsx b/webapp/components/admin_console/session_settings.jsx
index b238da90f..a36126789 100644
--- a/webapp/components/admin_console/session_settings.jsx
+++ b/webapp/components/admin_console/session_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/setting.jsx b/webapp/components/admin_console/setting.jsx
index 024111fa5..1db5a76b7 100644
--- a/webapp/components/admin_console/setting.jsx
+++ b/webapp/components/admin_console/setting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/settings_group.jsx b/webapp/components/admin_console/settings_group.jsx
index 10b3444d8..0de8130de 100644
--- a/webapp/components/admin_console/settings_group.jsx
+++ b/webapp/components/admin_console/settings_group.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/signup_settings.jsx b/webapp/components/admin_console/signup_settings.jsx
index b75b7591a..b3ae6fe60 100644
--- a/webapp/components/admin_console/signup_settings.jsx
+++ b/webapp/components/admin_console/signup_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/storage_settings.jsx b/webapp/components/admin_console/storage_settings.jsx
index 41d38d1ca..3b634dc53 100644
--- a/webapp/components/admin_console/storage_settings.jsx
+++ b/webapp/components/admin_console/storage_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/sync_now_button.jsx b/webapp/components/admin_console/sync_now_button.jsx
index f1197b216..6c0c10f62 100644
--- a/webapp/components/admin_console/sync_now_button.jsx
+++ b/webapp/components/admin_console/sync_now_button.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/system_users/system_users.jsx b/webapp/components/admin_console/system_users/system_users.jsx
index a311aebb7..0b967dead 100644
--- a/webapp/components/admin_console/system_users/system_users.jsx
+++ b/webapp/components/admin_console/system_users/system_users.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/system_users/system_users_dropdown.jsx b/webapp/components/admin_console/system_users/system_users_dropdown.jsx
index 534017cf8..c6bf61b8f 100644
--- a/webapp/components/admin_console/system_users/system_users_dropdown.jsx
+++ b/webapp/components/admin_console/system_users/system_users_dropdown.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ConfirmModal from 'components/confirm_modal.jsx';
diff --git a/webapp/components/admin_console/system_users/system_users_list.jsx b/webapp/components/admin_console/system_users/system_users_list.jsx
index ccb1a39d4..89953b4c8 100644
--- a/webapp/components/admin_console/system_users/system_users_list.jsx
+++ b/webapp/components/admin_console/system_users/system_users_list.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/text_setting.jsx b/webapp/components/admin_console/text_setting.jsx
index 47a501dcc..dfdd8a303 100644
--- a/webapp/components/admin_console/text_setting.jsx
+++ b/webapp/components/admin_console/text_setting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/users_and_teams_settings.jsx b/webapp/components/admin_console/users_and_teams_settings.jsx
index 6e83c01e3..4535aec7b 100644
--- a/webapp/components/admin_console/users_and_teams_settings.jsx
+++ b/webapp/components/admin_console/users_and_teams_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/webrtc_settings.jsx b/webapp/components/admin_console/webrtc_settings.jsx
index e0238e7f3..d9453936c 100644
--- a/webapp/components/admin_console/webrtc_settings.jsx
+++ b/webapp/components/admin_console/webrtc_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/admin_console/webserver_mode_dropdown_setting.jsx b/webapp/components/admin_console/webserver_mode_dropdown_setting.jsx
index e86e01a01..9fdbccd2c 100644
--- a/webapp/components/admin_console/webserver_mode_dropdown_setting.jsx
+++ b/webapp/components/admin_console/webserver_mode_dropdown_setting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/analytics/doughnut_chart.jsx b/webapp/components/analytics/doughnut_chart.jsx
index ee5365c9b..b6539bd54 100644
--- a/webapp/components/analytics/doughnut_chart.jsx
+++ b/webapp/components/analytics/doughnut_chart.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {FormattedMessage} from 'react-intl';
diff --git a/webapp/components/analytics/line_chart.jsx b/webapp/components/analytics/line_chart.jsx
index 5ae80f9e9..7f4ca51d0 100644
--- a/webapp/components/analytics/line_chart.jsx
+++ b/webapp/components/analytics/line_chart.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {FormattedMessage} from 'react-intl';
diff --git a/webapp/components/analytics/statistic_count.jsx b/webapp/components/analytics/statistic_count.jsx
index a4ca66476..d7849f6dd 100644
--- a/webapp/components/analytics/statistic_count.jsx
+++ b/webapp/components/analytics/statistic_count.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {FormattedMessage} from 'react-intl';
diff --git a/webapp/components/analytics/system_analytics.jsx b/webapp/components/analytics/system_analytics.jsx
index b7a10f43b..3abd4f259 100644
--- a/webapp/components/analytics/system_analytics.jsx
+++ b/webapp/components/analytics/system_analytics.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import LineChart from './line_chart.jsx';
diff --git a/webapp/components/analytics/table_chart.jsx b/webapp/components/analytics/table_chart.jsx
index 18ed54f96..e6e210876 100644
--- a/webapp/components/analytics/table_chart.jsx
+++ b/webapp/components/analytics/table_chart.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Constants from 'utils/constants.jsx';
diff --git a/webapp/components/analytics/team_analytics.jsx b/webapp/components/analytics/team_analytics.jsx
index cc179a370..700dc5a10 100644
--- a/webapp/components/analytics/team_analytics.jsx
+++ b/webapp/components/analytics/team_analytics.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/audio_video_preview.jsx b/webapp/components/audio_video_preview.jsx
index 9a55e4835..bdad5c2eb 100644
--- a/webapp/components/audio_video_preview.jsx
+++ b/webapp/components/audio_video_preview.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/audit_table.jsx b/webapp/components/audit_table.jsx
index e7d366f04..e04ba4d1e 100644
--- a/webapp/components/audit_table.jsx
+++ b/webapp/components/audit_table.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import UserStore from 'stores/user_store.jsx';
diff --git a/webapp/components/authorize.jsx b/webapp/components/authorize.jsx
index f3f5770de..f4d80b1f0 100644
--- a/webapp/components/authorize.jsx
+++ b/webapp/components/authorize.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import FormError from 'components/form_error.jsx';
diff --git a/webapp/components/autosize_textarea.jsx b/webapp/components/autosize_textarea.jsx
index e14835737..656ce97d2 100644
--- a/webapp/components/autosize_textarea.jsx
+++ b/webapp/components/autosize_textarea.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/backstage/backstage_controller.jsx b/webapp/components/backstage/backstage_controller.jsx
index 0ec6a0091..f354f141d 100644
--- a/webapp/components/backstage/backstage_controller.jsx
+++ b/webapp/components/backstage/backstage_controller.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/backstage/components/backstage_category.jsx b/webapp/components/backstage/components/backstage_category.jsx
index 74dcf3476..50ade74dc 100644
--- a/webapp/components/backstage/components/backstage_category.jsx
+++ b/webapp/components/backstage/components/backstage_category.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/backstage/components/backstage_header.jsx b/webapp/components/backstage/components/backstage_header.jsx
index c2dc187b7..65ba5c77d 100644
--- a/webapp/components/backstage/components/backstage_header.jsx
+++ b/webapp/components/backstage/components/backstage_header.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/backstage/components/backstage_list.jsx b/webapp/components/backstage/components/backstage_list.jsx
index c13f86a00..2dcecb90a 100644
--- a/webapp/components/backstage/components/backstage_list.jsx
+++ b/webapp/components/backstage/components/backstage_list.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/backstage/components/backstage_navbar.jsx b/webapp/components/backstage/components/backstage_navbar.jsx
index d49c89b09..8e1b6bb27 100644
--- a/webapp/components/backstage/components/backstage_navbar.jsx
+++ b/webapp/components/backstage/components/backstage_navbar.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/backstage/components/backstage_section.jsx b/webapp/components/backstage/components/backstage_section.jsx
index e89ec9861..26c06ca29 100644
--- a/webapp/components/backstage/components/backstage_section.jsx
+++ b/webapp/components/backstage/components/backstage_section.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/backstage/components/backstage_sidebar.jsx b/webapp/components/backstage/components/backstage_sidebar.jsx
index 557c6d804..9c5ff3e6f 100644
--- a/webapp/components/backstage/components/backstage_sidebar.jsx
+++ b/webapp/components/backstage/components/backstage_sidebar.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/change_url_modal.jsx b/webapp/components/change_url_modal.jsx
index fd5cdfd74..1a0004bb0 100644
--- a/webapp/components/change_url_modal.jsx
+++ b/webapp/components/change_url_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ReactDOM from 'react-dom';
diff --git a/webapp/components/channel_header.jsx b/webapp/components/channel_header.jsx
index c0bd2ccfe..c51dce013 100644
--- a/webapp/components/channel_header.jsx
+++ b/webapp/components/channel_header.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/channel_info_modal.jsx b/webapp/components/channel_info_modal.jsx
index 4829d1dd9..702d9059c 100644
--- a/webapp/components/channel_info_modal.jsx
+++ b/webapp/components/channel_info_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as Utils from 'utils/utils.jsx';
diff --git a/webapp/components/channel_invite_button.jsx b/webapp/components/channel_invite_button.jsx
index 2ef8fb4af..c96b687a8 100644
--- a/webapp/components/channel_invite_button.jsx
+++ b/webapp/components/channel_invite_button.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import SpinnerButton from 'components/spinner_button.jsx';
diff --git a/webapp/components/channel_invite_modal.jsx b/webapp/components/channel_invite_modal.jsx
index dfc083f24..d41948a2b 100644
--- a/webapp/components/channel_invite_modal.jsx
+++ b/webapp/components/channel_invite_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ChannelInviteButton from './channel_invite_button.jsx';
diff --git a/webapp/components/channel_members_dropdown.jsx b/webapp/components/channel_members_dropdown.jsx
index 8c8c7dc3a..decf97044 100644
--- a/webapp/components/channel_members_dropdown.jsx
+++ b/webapp/components/channel_members_dropdown.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ChannelStore from 'stores/channel_store.jsx';
diff --git a/webapp/components/channel_members_modal.jsx b/webapp/components/channel_members_modal.jsx
index a82c620ca..de3a4a5e7 100644
--- a/webapp/components/channel_members_modal.jsx
+++ b/webapp/components/channel_members_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import MemberListChannel from './member_list_channel.jsx';
diff --git a/webapp/components/channel_notifications_modal.jsx b/webapp/components/channel_notifications_modal.jsx
index 2f76f19e1..7af563e7c 100644
--- a/webapp/components/channel_notifications_modal.jsx
+++ b/webapp/components/channel_notifications_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import SettingItemMin from 'components/setting_item_min.jsx';
diff --git a/webapp/components/channel_select.jsx b/webapp/components/channel_select.jsx
index 49c1edfef..59dc97d41 100644
--- a/webapp/components/channel_select.jsx
+++ b/webapp/components/channel_select.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/channel_switch_modal.jsx b/webapp/components/channel_switch_modal.jsx
index 2b08ee239..aad2251b2 100644
--- a/webapp/components/channel_switch_modal.jsx
+++ b/webapp/components/channel_switch_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import SuggestionList from './suggestion/suggestion_list.jsx';
diff --git a/webapp/components/channel_view.jsx b/webapp/components/channel_view.jsx
index ff101bca7..9359ff899 100644
--- a/webapp/components/channel_view.jsx
+++ b/webapp/components/channel_view.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/claim/claim_controller.jsx b/webapp/components/claim/claim_controller.jsx
index 581438ce9..cc92343fd 100644
--- a/webapp/components/claim/claim_controller.jsx
+++ b/webapp/components/claim/claim_controller.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/claim/components/email_to_ldap.jsx b/webapp/components/claim/components/email_to_ldap.jsx
index 7d062a957..deb7835c2 100644
--- a/webapp/components/claim/components/email_to_ldap.jsx
+++ b/webapp/components/claim/components/email_to_ldap.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import LoginMfa from 'components/login/components/login_mfa.jsx';
diff --git a/webapp/components/claim/components/email_to_oauth.jsx b/webapp/components/claim/components/email_to_oauth.jsx
index bc5a7bdaa..ea2fcb92e 100644
--- a/webapp/components/claim/components/email_to_oauth.jsx
+++ b/webapp/components/claim/components/email_to_oauth.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import LoginMfa from 'components/login/components/login_mfa.jsx';
diff --git a/webapp/components/claim/components/ldap_to_email.jsx b/webapp/components/claim/components/ldap_to_email.jsx
index 39056cd0d..5e2ca26a1 100644
--- a/webapp/components/claim/components/ldap_to_email.jsx
+++ b/webapp/components/claim/components/ldap_to_email.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import LoginMfa from 'components/login/components/login_mfa.jsx';
diff --git a/webapp/components/claim/components/oauth_to_email.jsx b/webapp/components/claim/components/oauth_to_email.jsx
index ffba1c331..6959f413c 100644
--- a/webapp/components/claim/components/oauth_to_email.jsx
+++ b/webapp/components/claim/components/oauth_to_email.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as Utils from 'utils/utils.jsx';
diff --git a/webapp/components/code_preview.jsx b/webapp/components/code_preview.jsx
index 6afe45c2e..67088972a 100644
--- a/webapp/components/code_preview.jsx
+++ b/webapp/components/code_preview.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/confirm_modal.jsx b/webapp/components/confirm_modal.jsx
index ef91b5ec0..8034caf9d 100644
--- a/webapp/components/confirm_modal.jsx
+++ b/webapp/components/confirm_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {FormattedMessage} from 'react-intl';
diff --git a/webapp/components/create_comment.jsx b/webapp/components/create_comment.jsx
index 3dd1ac924..a9fd69e41 100644
--- a/webapp/components/create_comment.jsx
+++ b/webapp/components/create_comment.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/create_post.jsx b/webapp/components/create_post.jsx
index 4ce6fc8ab..390940914 100644
--- a/webapp/components/create_post.jsx
+++ b/webapp/components/create_post.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ReactDOM from 'react-dom';
diff --git a/webapp/components/create_team/components/display_name.jsx b/webapp/components/create_team/components/display_name.jsx
index 865c0e6db..e1b5a678c 100644
--- a/webapp/components/create_team/components/display_name.jsx
+++ b/webapp/components/create_team/components/display_name.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {trackEvent} from 'actions/diagnostics_actions.jsx';
diff --git a/webapp/components/create_team/components/team_url.jsx b/webapp/components/create_team/components/team_url.jsx
index 07fd36f76..7722d9b31 100644
--- a/webapp/components/create_team/components/team_url.jsx
+++ b/webapp/components/create_team/components/team_url.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {checkIfTeamExists, createTeam} from 'actions/team_actions.jsx';
diff --git a/webapp/components/create_team/create_team_controller.jsx b/webapp/components/create_team/create_team_controller.jsx
index 84b890e26..71904a93c 100644
--- a/webapp/components/create_team/create_team_controller.jsx
+++ b/webapp/components/create_team/create_team_controller.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ErrorBar from 'components/error_bar.jsx';
diff --git a/webapp/components/delete_channel_modal.jsx b/webapp/components/delete_channel_modal.jsx
index 1893d28d1..4c5c428d5 100644
--- a/webapp/components/delete_channel_modal.jsx
+++ b/webapp/components/delete_channel_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {Modal} from 'react-bootstrap';
diff --git a/webapp/components/delete_post_modal.jsx b/webapp/components/delete_post_modal.jsx
index 39d4f41f9..a64c466cc 100644
--- a/webapp/components/delete_post_modal.jsx
+++ b/webapp/components/delete_post_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/do_verify_email.jsx b/webapp/components/do_verify_email.jsx
index 54b8382b0..9065e6bc4 100644
--- a/webapp/components/do_verify_email.jsx
+++ b/webapp/components/do_verify_email.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {FormattedMessage} from 'react-intl';
diff --git a/webapp/components/edit_channel_header_modal.jsx b/webapp/components/edit_channel_header_modal.jsx
index 0d8eb8acb..d1370506e 100644
--- a/webapp/components/edit_channel_header_modal.jsx
+++ b/webapp/components/edit_channel_header_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ReactDOM from 'react-dom';
diff --git a/webapp/components/edit_channel_purpose_modal.jsx b/webapp/components/edit_channel_purpose_modal.jsx
index ea34cf969..431182f43 100644
--- a/webapp/components/edit_channel_purpose_modal.jsx
+++ b/webapp/components/edit_channel_purpose_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import PreferenceStore from 'stores/preference_store.jsx';
diff --git a/webapp/components/edit_post_modal.jsx b/webapp/components/edit_post_modal.jsx
index 902b18d30..3ec7fedcc 100644
--- a/webapp/components/edit_post_modal.jsx
+++ b/webapp/components/edit_post_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Textbox from './textbox.jsx';
diff --git a/webapp/components/emoji/components/add_emoji.jsx b/webapp/components/emoji/components/add_emoji.jsx
index 53c7ecccf..fc02be3be 100644
--- a/webapp/components/emoji/components/add_emoji.jsx
+++ b/webapp/components/emoji/components/add_emoji.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/emoji/components/delete_emoji_modal.jsx b/webapp/components/emoji/components/delete_emoji_modal.jsx
index 604e3a27b..77afd4c01 100644
--- a/webapp/components/emoji/components/delete_emoji_modal.jsx
+++ b/webapp/components/emoji/components/delete_emoji_modal.jsx
@@ -25,7 +25,7 @@ export default class DeleteEmoji extends DeleteModalTrigger {
get modalMessage() {
return (
<div className='alert alert-warning'>
- <i className='fa fa-warning'/>
+ <i className='fa fa-warning fa-margin--right'/>
<FormattedMessage
id='emoji_list.delete.confirm.msg'
defaultMessage='This action permanently deletes the custom emoji. Are you sure you want to delete it?'
diff --git a/webapp/components/emoji/components/emoji_list.jsx b/webapp/components/emoji/components/emoji_list.jsx
index 949c74c45..14ce819b4 100644
--- a/webapp/components/emoji/components/emoji_list.jsx
+++ b/webapp/components/emoji/components/emoji_list.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import EmojiListItem from './emoji_list_item.jsx';
diff --git a/webapp/components/emoji/components/emoji_list_item.jsx b/webapp/components/emoji/components/emoji_list_item.jsx
index 019b0ca93..f169b2e9c 100644
--- a/webapp/components/emoji/components/emoji_list_item.jsx
+++ b/webapp/components/emoji/components/emoji_list_item.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/emoji_picker/components/emoji_picker_category.jsx b/webapp/components/emoji_picker/components/emoji_picker_category.jsx
index 1d5b12095..21c59baea 100644
--- a/webapp/components/emoji_picker/components/emoji_picker_category.jsx
+++ b/webapp/components/emoji_picker/components/emoji_picker_category.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
@@ -39,4 +39,4 @@ export default class EmojiPickerCategory extends React.Component {
</a>
);
}
-} \ No newline at end of file
+}
diff --git a/webapp/components/emoji_picker/components/emoji_picker_item.jsx b/webapp/components/emoji_picker/components/emoji_picker_item.jsx
index 3f38343fa..c7981c952 100644
--- a/webapp/components/emoji_picker/components/emoji_picker_item.jsx
+++ b/webapp/components/emoji_picker/components/emoji_picker_item.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/emoji_picker/components/emoji_picker_preview.jsx b/webapp/components/emoji_picker/components/emoji_picker_preview.jsx
index ac3f07025..24acf9668 100644
--- a/webapp/components/emoji_picker/components/emoji_picker_preview.jsx
+++ b/webapp/components/emoji_picker/components/emoji_picker_preview.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
@@ -44,7 +44,7 @@ export default class EmojiPickerPreview extends React.Component {
<div className='emoji-picker__preview-image-box'>
{previewImage}
</div>
- <div className='emoji-picker__preview-image-box'>
+ <div className='emoji-picker__preview-detail-box'>
<span className='emoji-picker__preview-name'>{name}</span>
<span
className='emoji-picker__preview-aliases'
diff --git a/webapp/components/emoji_picker/emoji_picker.jsx b/webapp/components/emoji_picker/emoji_picker.jsx
index 0f45b7297..13438e08e 100644
--- a/webapp/components/emoji_picker/emoji_picker.jsx
+++ b/webapp/components/emoji_picker/emoji_picker.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/emoji_picker/emoji_picker_container.jsx b/webapp/components/emoji_picker/emoji_picker_container.jsx
index 7cdc0e4b9..d352539ab 100644
--- a/webapp/components/emoji_picker/emoji_picker_container.jsx
+++ b/webapp/components/emoji_picker/emoji_picker_container.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/error_bar.jsx b/webapp/components/error_bar.jsx
index 341f0efb4..d0ecd604e 100644
--- a/webapp/components/error_bar.jsx
+++ b/webapp/components/error_bar.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AnalyticsStore from 'stores/analytics_store.jsx';
diff --git a/webapp/components/error_page.jsx b/webapp/components/error_page.jsx
index 9bd2c722d..aae538795 100644
--- a/webapp/components/error_page.jsx
+++ b/webapp/components/error_page.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/file_attachment.jsx b/webapp/components/file_attachment.jsx
index 23d8d2446..616231a6d 100644
--- a/webapp/components/file_attachment.jsx
+++ b/webapp/components/file_attachment.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Constants from 'utils/constants.jsx';
@@ -181,4 +181,4 @@ FileAttachment.propTypes = {
handleImageClick: React.PropTypes.func,
compactDisplay: React.PropTypes.bool
-}; \ No newline at end of file
+};
diff --git a/webapp/components/file_attachment_list.jsx b/webapp/components/file_attachment_list.jsx
index 472cd2686..0ea53c20a 100644
--- a/webapp/components/file_attachment_list.jsx
+++ b/webapp/components/file_attachment_list.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ViewImageModal from './view_image.jsx';
diff --git a/webapp/components/file_attachment_list_container.jsx b/webapp/components/file_attachment_list_container.jsx
index f9ad3814c..77d93f509 100644
--- a/webapp/components/file_attachment_list_container.jsx
+++ b/webapp/components/file_attachment_list_container.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/file_info_preview.jsx b/webapp/components/file_info_preview.jsx
index 51825ce5b..2491c986d 100644
--- a/webapp/components/file_info_preview.jsx
+++ b/webapp/components/file_info_preview.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/file_preview.jsx b/webapp/components/file_preview.jsx
index 624bfaf44..1e747b372 100644
--- a/webapp/components/file_preview.jsx
+++ b/webapp/components/file_preview.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import FileStore from 'stores/file_store.jsx';
@@ -33,7 +33,7 @@ export default class FilePreview extends React.Component {
let className = 'file-preview';
let previewImage;
- if (type === 'image') {
+ if (type === 'image' || type === 'svg') {
previewImage = (
<img
className='file-preview__image'
diff --git a/webapp/components/file_upload.jsx b/webapp/components/file_upload.jsx
index a0e7f5296..af5d76829 100644
--- a/webapp/components/file_upload.jsx
+++ b/webapp/components/file_upload.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/file_upload_overlay.jsx b/webapp/components/file_upload_overlay.jsx
index 86697cd62..8f0fbee16 100644
--- a/webapp/components/file_upload_overlay.jsx
+++ b/webapp/components/file_upload_overlay.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {FormattedMessage} from 'react-intl';
diff --git a/webapp/components/filtered_user_list.jsx b/webapp/components/filtered_user_list.jsx
index 0e06d5943..e9d22ef48 100644
--- a/webapp/components/filtered_user_list.jsx
+++ b/webapp/components/filtered_user_list.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/form_error.jsx b/webapp/components/form_error.jsx
index 9dce98ae9..6aa378361 100644
--- a/webapp/components/form_error.jsx
+++ b/webapp/components/form_error.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/get_android_app/get_android_app.jsx b/webapp/components/get_android_app/get_android_app.jsx
index ab73141b1..aa74d15ec 100644
--- a/webapp/components/get_android_app/get_android_app.jsx
+++ b/webapp/components/get_android_app/get_android_app.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
@@ -72,4 +72,4 @@ export default class GetAndroidApp extends React.Component {
</div>
);
}
-} \ No newline at end of file
+}
diff --git a/webapp/components/get_ios_app/get_ios_app.jsx b/webapp/components/get_ios_app/get_ios_app.jsx
index 0980b5882..de715b1fd 100644
--- a/webapp/components/get_ios_app/get_ios_app.jsx
+++ b/webapp/components/get_ios_app/get_ios_app.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
@@ -65,4 +65,4 @@ export default class GetIosApp extends React.Component {
</div>
);
}
-} \ No newline at end of file
+}
diff --git a/webapp/components/get_link_modal.jsx b/webapp/components/get_link_modal.jsx
index f33b7caae..a7ce31f53 100644
--- a/webapp/components/get_link_modal.jsx
+++ b/webapp/components/get_link_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/get_post_link_modal.jsx b/webapp/components/get_post_link_modal.jsx
index cc01d1124..4f89f1c9d 100644
--- a/webapp/components/get_post_link_modal.jsx
+++ b/webapp/components/get_post_link_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import GetLinkModal from './get_link_modal.jsx';
diff --git a/webapp/components/get_public_link_modal.jsx b/webapp/components/get_public_link_modal.jsx
index 851a78f80..b2903da87 100644
--- a/webapp/components/get_public_link_modal.jsx
+++ b/webapp/components/get_public_link_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/get_team_invite_link_modal.jsx b/webapp/components/get_team_invite_link_modal.jsx
index 109cb2120..78ccb368e 100644
--- a/webapp/components/get_team_invite_link_modal.jsx
+++ b/webapp/components/get_team_invite_link_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import GetLinkModal from './get_link_modal.jsx';
diff --git a/webapp/components/header_footer_template.jsx b/webapp/components/header_footer_template.jsx
index b508d9ba5..80274d985 100644
--- a/webapp/components/header_footer_template.jsx
+++ b/webapp/components/header_footer_template.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/help/components/attaching.jsx b/webapp/components/help/components/attaching.jsx
index 9796733ef..84c50004d 100644
--- a/webapp/components/help/components/attaching.jsx
+++ b/webapp/components/help/components/attaching.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {localizeMessage} from 'utils/utils.jsx';
diff --git a/webapp/components/help/components/commands.jsx b/webapp/components/help/components/commands.jsx
index b59847f0d..1c670ed77 100644
--- a/webapp/components/help/components/commands.jsx
+++ b/webapp/components/help/components/commands.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {localizeMessage} from 'utils/utils.jsx';
diff --git a/webapp/components/help/components/composing.jsx b/webapp/components/help/components/composing.jsx
index 20d6c3ee7..f3b16c76d 100644
--- a/webapp/components/help/components/composing.jsx
+++ b/webapp/components/help/components/composing.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {localizeMessage} from 'utils/utils.jsx';
diff --git a/webapp/components/help/components/formatting.jsx b/webapp/components/help/components/formatting.jsx
index 72d07c74c..52ad89772 100644
--- a/webapp/components/help/components/formatting.jsx
+++ b/webapp/components/help/components/formatting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {localizeMessage} from 'utils/utils.jsx';
diff --git a/webapp/components/help/components/mentioning.jsx b/webapp/components/help/components/mentioning.jsx
index 5ce42197a..83e19d14b 100644
--- a/webapp/components/help/components/mentioning.jsx
+++ b/webapp/components/help/components/mentioning.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {localizeMessage} from 'utils/utils.jsx';
diff --git a/webapp/components/help/components/messaging.jsx b/webapp/components/help/components/messaging.jsx
index dd1c90f8b..5f26f32ba 100644
--- a/webapp/components/help/components/messaging.jsx
+++ b/webapp/components/help/components/messaging.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {localizeMessage} from 'utils/utils.jsx';
diff --git a/webapp/components/help/help_controller.jsx b/webapp/components/help/help_controller.jsx
index 56a13b7e8..2e21861c1 100644
--- a/webapp/components/help/help_controller.jsx
+++ b/webapp/components/help/help_controller.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
@@ -24,4 +24,4 @@ export default class HelpController extends React.Component {
</div>
);
}
-} \ No newline at end of file
+}
diff --git a/webapp/components/integrations/components/abstract_incoming_webhook.jsx b/webapp/components/integrations/components/abstract_incoming_webhook.jsx
index 15e39e54b..a4d9e94f4 100644
--- a/webapp/components/integrations/components/abstract_incoming_webhook.jsx
+++ b/webapp/components/integrations/components/abstract_incoming_webhook.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/integrations/components/abstract_outgoing_webhook.jsx b/webapp/components/integrations/components/abstract_outgoing_webhook.jsx
index 6033647af..46178adde 100644
--- a/webapp/components/integrations/components/abstract_outgoing_webhook.jsx
+++ b/webapp/components/integrations/components/abstract_outgoing_webhook.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/integrations/components/add_command.jsx b/webapp/components/integrations/components/add_command.jsx
index ccff14c55..31f99976c 100644
--- a/webapp/components/integrations/components/add_command.jsx
+++ b/webapp/components/integrations/components/add_command.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/integrations/components/add_incoming_webhook.jsx b/webapp/components/integrations/components/add_incoming_webhook.jsx
index d7b7fb51b..c3ddf5798 100644
--- a/webapp/components/integrations/components/add_incoming_webhook.jsx
+++ b/webapp/components/integrations/components/add_incoming_webhook.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as AsyncClient from 'utils/async_client.jsx';
diff --git a/webapp/components/integrations/components/add_oauth_app.jsx b/webapp/components/integrations/components/add_oauth_app.jsx
index 701cbad76..4d91caf76 100644
--- a/webapp/components/integrations/components/add_oauth_app.jsx
+++ b/webapp/components/integrations/components/add_oauth_app.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/integrations/components/add_outgoing_webhook.jsx b/webapp/components/integrations/components/add_outgoing_webhook.jsx
index 24475e176..22fba7c7d 100644
--- a/webapp/components/integrations/components/add_outgoing_webhook.jsx
+++ b/webapp/components/integrations/components/add_outgoing_webhook.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as AsyncClient from 'utils/async_client.jsx';
diff --git a/webapp/components/integrations/components/commands_container.jsx b/webapp/components/integrations/components/commands_container.jsx
index 095dc4fea..29d1e9b33 100644
--- a/webapp/components/integrations/components/commands_container.jsx
+++ b/webapp/components/integrations/components/commands_container.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import IntegrationStore from 'stores/integration_store.jsx';
diff --git a/webapp/components/integrations/components/confirm_integration.jsx b/webapp/components/integrations/components/confirm_integration.jsx
index b4f299d1c..70dc787e1 100644
--- a/webapp/components/integrations/components/confirm_integration.jsx
+++ b/webapp/components/integrations/components/confirm_integration.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/integrations/components/edit_command.jsx b/webapp/components/integrations/components/edit_command.jsx
index ac2c12bff..7979f659d 100644
--- a/webapp/components/integrations/components/edit_command.jsx
+++ b/webapp/components/integrations/components/edit_command.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/integrations/components/edit_incoming_webhook.jsx b/webapp/components/integrations/components/edit_incoming_webhook.jsx
index 9e032409a..2c3a69c0d 100644
--- a/webapp/components/integrations/components/edit_incoming_webhook.jsx
+++ b/webapp/components/integrations/components/edit_incoming_webhook.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as AsyncClient from 'utils/async_client.jsx';
diff --git a/webapp/components/integrations/components/edit_outgoing_webhook.jsx b/webapp/components/integrations/components/edit_outgoing_webhook.jsx
index 2268af923..bd270e870 100644
--- a/webapp/components/integrations/components/edit_outgoing_webhook.jsx
+++ b/webapp/components/integrations/components/edit_outgoing_webhook.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/integrations/components/installed_command.jsx b/webapp/components/integrations/components/installed_command.jsx
index f07d261b8..60ea116cb 100644
--- a/webapp/components/integrations/components/installed_command.jsx
+++ b/webapp/components/integrations/components/installed_command.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/integrations/components/installed_commands.jsx b/webapp/components/integrations/components/installed_commands.jsx
index 4e1b4f565..27d91f204 100644
--- a/webapp/components/integrations/components/installed_commands.jsx
+++ b/webapp/components/integrations/components/installed_commands.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import BackstageList from 'components/backstage/components/backstage_list.jsx';
diff --git a/webapp/components/integrations/components/installed_incoming_webhook.jsx b/webapp/components/integrations/components/installed_incoming_webhook.jsx
index 7091f5eb8..68ac7b7ed 100644
--- a/webapp/components/integrations/components/installed_incoming_webhook.jsx
+++ b/webapp/components/integrations/components/installed_incoming_webhook.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/integrations/components/installed_incoming_webhooks.jsx b/webapp/components/integrations/components/installed_incoming_webhooks.jsx
index 002dbef7f..93ebf3066 100644
--- a/webapp/components/integrations/components/installed_incoming_webhooks.jsx
+++ b/webapp/components/integrations/components/installed_incoming_webhooks.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import BackstageList from 'components/backstage/components/backstage_list.jsx';
diff --git a/webapp/components/integrations/components/installed_oauth_app.jsx b/webapp/components/integrations/components/installed_oauth_app.jsx
index bb6e271d4..01cf345f4 100644
--- a/webapp/components/integrations/components/installed_oauth_app.jsx
+++ b/webapp/components/integrations/components/installed_oauth_app.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/integrations/components/installed_oauth_apps.jsx b/webapp/components/integrations/components/installed_oauth_apps.jsx
index 13246d05b..8a0b4678c 100644
--- a/webapp/components/integrations/components/installed_oauth_apps.jsx
+++ b/webapp/components/integrations/components/installed_oauth_apps.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/integrations/components/installed_outgoing_webhook.jsx b/webapp/components/integrations/components/installed_outgoing_webhook.jsx
index a452979ae..c840b1fa9 100644
--- a/webapp/components/integrations/components/installed_outgoing_webhook.jsx
+++ b/webapp/components/integrations/components/installed_outgoing_webhook.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/integrations/components/installed_outgoing_webhooks.jsx b/webapp/components/integrations/components/installed_outgoing_webhooks.jsx
index 7abacb241..bcf203b2a 100644
--- a/webapp/components/integrations/components/installed_outgoing_webhooks.jsx
+++ b/webapp/components/integrations/components/installed_outgoing_webhooks.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import BackstageList from 'components/backstage/components/backstage_list.jsx';
diff --git a/webapp/components/integrations/components/integration_option.jsx b/webapp/components/integrations/components/integration_option.jsx
index 483e6a888..49474d939 100644
--- a/webapp/components/integrations/components/integration_option.jsx
+++ b/webapp/components/integrations/components/integration_option.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/integrations/components/integrations.jsx b/webapp/components/integrations/components/integrations.jsx
index 580e70cf6..4d6c5e919 100644
--- a/webapp/components/integrations/components/integrations.jsx
+++ b/webapp/components/integrations/components/integrations.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/invite_member_modal.jsx b/webapp/components/invite_member_modal.jsx
index 849d5f274..6426a6a2b 100644
--- a/webapp/components/invite_member_modal.jsx
+++ b/webapp/components/invite_member_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ReactDOM from 'react-dom';
diff --git a/webapp/components/leave_team_modal.jsx b/webapp/components/leave_team_modal.jsx
index 69504ef4d..4728fb16d 100644
--- a/webapp/components/leave_team_modal.jsx
+++ b/webapp/components/leave_team_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {ActionTypes, WebrtcActionTypes} from 'utils/constants.jsx';
diff --git a/webapp/components/loading_screen.jsx b/webapp/components/loading_screen.jsx
index fe2cd6b11..2807cb0a7 100644
--- a/webapp/components/loading_screen.jsx
+++ b/webapp/components/loading_screen.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {FormattedMessage} from 'react-intl';
diff --git a/webapp/components/logged_in.jsx b/webapp/components/logged_in.jsx
index 8d7a00653..3dfab57b3 100644
--- a/webapp/components/logged_in.jsx
+++ b/webapp/components/logged_in.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import LoadingScreen from 'components/loading_screen.jsx';
diff --git a/webapp/components/login/components/login_mfa.jsx b/webapp/components/login/components/login_mfa.jsx
index 1a3393fa0..f945d3e07 100644
--- a/webapp/components/login/components/login_mfa.jsx
+++ b/webapp/components/login/components/login_mfa.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as Utils from 'utils/utils.jsx';
diff --git a/webapp/components/login/login_controller.jsx b/webapp/components/login/login_controller.jsx
index 1d812147a..482135a5e 100644
--- a/webapp/components/login/login_controller.jsx
+++ b/webapp/components/login/login_controller.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import LoginMfa from './components/login_mfa.jsx';
diff --git a/webapp/components/member_list_channel.jsx b/webapp/components/member_list_channel.jsx
index c23be2836..e9eef9fb8 100644
--- a/webapp/components/member_list_channel.jsx
+++ b/webapp/components/member_list_channel.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ChannelMembersDropdown from 'components/channel_members_dropdown.jsx';
diff --git a/webapp/components/member_list_team.jsx b/webapp/components/member_list_team.jsx
index fce6e1927..0aa1e6e57 100644
--- a/webapp/components/member_list_team.jsx
+++ b/webapp/components/member_list_team.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import SearchableUserList from 'components/searchable_user_list/searchable_user_list_container.jsx';
diff --git a/webapp/components/message_wrapper.jsx b/webapp/components/message_wrapper.jsx
index a79611e34..95205de82 100644
--- a/webapp/components/message_wrapper.jsx
+++ b/webapp/components/message_wrapper.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as TextFormatting from 'utils/text_formatting.jsx';
diff --git a/webapp/components/mfa/components/confirm.jsx b/webapp/components/mfa/components/confirm.jsx
index 026d12c6e..a6c2eda4e 100644
--- a/webapp/components/mfa/components/confirm.jsx
+++ b/webapp/components/mfa/components/confirm.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Constants from 'utils/constants.jsx';
diff --git a/webapp/components/mfa/components/setup.jsx b/webapp/components/mfa/components/setup.jsx
index a19e5d9fb..caec1571a 100644
--- a/webapp/components/mfa/components/setup.jsx
+++ b/webapp/components/mfa/components/setup.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {generateMfaSecret, activateMfa} from 'actions/user_actions.jsx';
diff --git a/webapp/components/mfa/mfa_controller.jsx b/webapp/components/mfa/mfa_controller.jsx
index cd9497985..5c41fdfbb 100644
--- a/webapp/components/mfa/mfa_controller.jsx
+++ b/webapp/components/mfa/mfa_controller.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {emitUserLoggedOutEvent} from 'actions/global_actions.jsx';
diff --git a/webapp/components/more_channels.jsx b/webapp/components/more_channels.jsx
index 4ab3cca8b..02a0628ba 100644
--- a/webapp/components/more_channels.jsx
+++ b/webapp/components/more_channels.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import SearchableChannelList from './searchable_channel_list.jsx';
diff --git a/webapp/components/more_direct_channels.jsx b/webapp/components/more_direct_channels.jsx
index 4d5016907..0fbd9053f 100644
--- a/webapp/components/more_direct_channels.jsx
+++ b/webapp/components/more_direct_channels.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import MultiSelect from 'components/multiselect/multiselect.jsx';
diff --git a/webapp/components/msg_typing.jsx b/webapp/components/msg_typing.jsx
index f6a6d12b2..503af1dc7 100644
--- a/webapp/components/msg_typing.jsx
+++ b/webapp/components/msg_typing.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import UserTypingStore from 'stores/user_typing_store.jsx';
diff --git a/webapp/components/multiselect/multiselect.jsx b/webapp/components/multiselect/multiselect.jsx
index f6d6b5d56..bba739ae5 100644
--- a/webapp/components/multiselect/multiselect.jsx
+++ b/webapp/components/multiselect/multiselect.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import MultiSelectList from './multiselect_list.jsx';
diff --git a/webapp/components/multiselect/multiselect_list.jsx b/webapp/components/multiselect/multiselect_list.jsx
index ff9f68bf8..e5faecb5a 100644
--- a/webapp/components/multiselect/multiselect_list.jsx
+++ b/webapp/components/multiselect/multiselect_list.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {cmdOrCtrlPressed} from 'utils/utils.jsx';
diff --git a/webapp/components/navbar.jsx b/webapp/components/navbar.jsx
index 62fb61d97..db7dc71df 100644
--- a/webapp/components/navbar.jsx
+++ b/webapp/components/navbar.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/needs_team.jsx b/webapp/components/needs_team.jsx
index 1f1f99aba..42f05c1a9 100644
--- a/webapp/components/needs_team.jsx
+++ b/webapp/components/needs_team.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/new_channel_flow.jsx b/webapp/components/new_channel_flow.jsx
index 55e47b149..0ca504534 100644
--- a/webapp/components/new_channel_flow.jsx
+++ b/webapp/components/new_channel_flow.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as Utils from 'utils/utils.jsx';
diff --git a/webapp/components/new_channel_modal.jsx b/webapp/components/new_channel_modal.jsx
index b515d5469..7f78c53c2 100644
--- a/webapp/components/new_channel_modal.jsx
+++ b/webapp/components/new_channel_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/notify_counts.jsx b/webapp/components/notify_counts.jsx
index fe40fd485..dda352349 100644
--- a/webapp/components/notify_counts.jsx
+++ b/webapp/components/notify_counts.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as utils from 'utils/utils.jsx';
diff --git a/webapp/components/password_reset_form.jsx b/webapp/components/password_reset_form.jsx
index c6fe2525f..0d67eb786 100644
--- a/webapp/components/password_reset_form.jsx
+++ b/webapp/components/password_reset_form.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ReactDOM from 'react-dom';
diff --git a/webapp/components/password_reset_send_link.jsx b/webapp/components/password_reset_send_link.jsx
index 1cd532855..260ef7250 100644
--- a/webapp/components/password_reset_send_link.jsx
+++ b/webapp/components/password_reset_send_link.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/pdf_preview.jsx b/webapp/components/pdf_preview.jsx
index 2cb0a324c..26444fe1f 100644
--- a/webapp/components/pdf_preview.jsx
+++ b/webapp/components/pdf_preview.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import FileInfoPreview from './file_info_preview.jsx';
diff --git a/webapp/components/permalink_view.jsx b/webapp/components/permalink_view.jsx
index 5cd2d0fff..d57564350 100644
--- a/webapp/components/permalink_view.jsx
+++ b/webapp/components/permalink_view.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/popover_list_members.jsx b/webapp/components/popover_list_members.jsx
index b28982b5d..268a87a6b 100644
--- a/webapp/components/popover_list_members.jsx
+++ b/webapp/components/popover_list_members.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ProfilePicture from 'components/profile_picture.jsx';
diff --git a/webapp/components/post_deleted_modal.jsx b/webapp/components/post_deleted_modal.jsx
index f70edf783..9f3125ffa 100644
--- a/webapp/components/post_deleted_modal.jsx
+++ b/webapp/components/post_deleted_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {FormattedMessage} from 'react-intl';
diff --git a/webapp/components/post_view/components/commented_on_files_message_container.jsx b/webapp/components/post_view/components/commented_on_files_message_container.jsx
index 5325a7644..d1fa455c7 100644
--- a/webapp/components/post_view/components/commented_on_files_message_container.jsx
+++ b/webapp/components/post_view/components/commented_on_files_message_container.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/post_view/components/floating_timestamp.jsx b/webapp/components/post_view/components/floating_timestamp.jsx
index 642b54c5d..d2d26c0bd 100644
--- a/webapp/components/post_view/components/floating_timestamp.jsx
+++ b/webapp/components/post_view/components/floating_timestamp.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {FormattedDate} from 'react-intl';
diff --git a/webapp/components/post_view/components/new_message_indicator.jsx b/webapp/components/post_view/components/new_message_indicator.jsx
index 5167a3d2d..488a38b1b 100644
--- a/webapp/components/post_view/components/new_message_indicator.jsx
+++ b/webapp/components/post_view/components/new_message_indicator.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
import {FormattedMessage} from 'react-intl';
diff --git a/webapp/components/post_view/components/pending_post_options.jsx b/webapp/components/post_view/components/pending_post_options.jsx
index 3c78b8b9b..0085a16f2 100644
--- a/webapp/components/post_view/components/pending_post_options.jsx
+++ b/webapp/components/post_view/components/pending_post_options.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import PostStore from 'stores/post_store.jsx';
@@ -14,13 +14,23 @@ import React from 'react';
export default class PendingPostOptions extends React.Component {
constructor(props) {
super(props);
+
this.retryPost = this.retryPost.bind(this);
this.cancelPost = this.cancelPost.bind(this);
+
+ this.submitting = false;
+
this.state = {};
}
retryPost(e) {
e.preventDefault();
+ if (this.submitting) {
+ return;
+ }
+
+ this.submitting = true;
+
var post = this.props.post;
queuePost(post, true, null,
(err) => {
@@ -30,9 +40,7 @@ export default class PendingPostOptions extends React.Component {
this.forceUpdate();
}
- this.setState({
- submitting: false
- });
+ this.submitting = false;
}
);
diff --git a/webapp/components/post_view/components/post.jsx b/webapp/components/post_view/components/post.jsx
index 645724467..f5c96d2bc 100644
--- a/webapp/components/post_view/components/post.jsx
+++ b/webapp/components/post_view/components/post.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import PostHeader from './post_header.jsx';
diff --git a/webapp/components/post_view/components/post_attachment.jsx b/webapp/components/post_view/components/post_attachment.jsx
index 57335b94a..930e75b41 100644
--- a/webapp/components/post_view/components/post_attachment.jsx
+++ b/webapp/components/post_view/components/post_attachment.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/post_view/components/post_attachment_list.jsx b/webapp/components/post_view/components/post_attachment_list.jsx
index 7e9d7980d..5223fb2b3 100644
--- a/webapp/components/post_view/components/post_attachment_list.jsx
+++ b/webapp/components/post_view/components/post_attachment_list.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import PostAttachment from './post_attachment.jsx';
diff --git a/webapp/components/post_view/components/post_attachment_opengraph.jsx b/webapp/components/post_view/components/post_attachment_opengraph.jsx
index da85905c0..f6e66a641 100644
--- a/webapp/components/post_view/components/post_attachment_opengraph.jsx
+++ b/webapp/components/post_view/components/post_attachment_opengraph.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/post_view/components/post_body.jsx b/webapp/components/post_view/components/post_body.jsx
index 741722ceb..108605eea 100644
--- a/webapp/components/post_view/components/post_body.jsx
+++ b/webapp/components/post_view/components/post_body.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import UserStore from 'stores/user_store.jsx';
diff --git a/webapp/components/post_view/components/post_body_additional_content.jsx b/webapp/components/post_view/components/post_body_additional_content.jsx
index cad618de0..549bb9faa 100644
--- a/webapp/components/post_view/components/post_body_additional_content.jsx
+++ b/webapp/components/post_view/components/post_body_additional_content.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import PostAttachmentList from './post_attachment_list.jsx';
@@ -153,30 +153,36 @@ export default class PostBodyAdditionalContent extends React.Component {
render() {
if (this.isLinkToggleable() && !this.state.linkLoadError) {
- const messageWithToggle = [];
-
// if message has only one line and starts with a link place toggle in this only line
// else - place it in new line between message and embed
const prependToggle = (/^\s*https?:\/\/.*$/).test(this.props.post.message);
- messageWithToggle.push(
+
+ const toggle = (
<a
+ key='toggle'
className={`post__embed-visibility ${prependToggle ? 'pull-left' : ''}`}
data-expanded={this.state.embedVisible}
aria-label='Toggle Embed Visibility'
onClick={this.toggleEmbedVisibility}
/>
);
+ const message = (
+ <div key='message'>
+ {this.props.message}
+ </div>
+ );
+ let contents;
if (prependToggle) {
- messageWithToggle.push(this.props.message);
+ contents = [toggle, message];
} else {
- messageWithToggle.unshift(this.props.message);
+ contents = [message, toggle];
}
- let toggleableEmbed;
if (this.state.embedVisible) {
- toggleableEmbed = (
+ contents.push(
<div
+ key='embed'
className='post__embed-container'
>
{this.generateToggleableEmbed()}
@@ -186,8 +192,7 @@ export default class PostBodyAdditionalContent extends React.Component {
return (
<div>
- {messageWithToggle}
- {toggleableEmbed}
+ {contents}
</div>
);
}
diff --git a/webapp/components/post_view/components/post_header.jsx b/webapp/components/post_view/components/post_header.jsx
index 3b5df47d5..9de0b7e79 100644
--- a/webapp/components/post_view/components/post_header.jsx
+++ b/webapp/components/post_view/components/post_header.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import UserProfile from 'components/user_profile.jsx';
diff --git a/webapp/components/post_view/components/post_image.jsx b/webapp/components/post_view/components/post_image.jsx
index 9a761bfca..39308ed2f 100644
--- a/webapp/components/post_view/components/post_image.jsx
+++ b/webapp/components/post_view/components/post_image.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/post_view/components/post_info.jsx b/webapp/components/post_view/components/post_info.jsx
index b76e3aed0..e7cb9ffb0 100644
--- a/webapp/components/post_view/components/post_info.jsx
+++ b/webapp/components/post_view/components/post_info.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/post_view/components/post_list.jsx b/webapp/components/post_view/components/post_list.jsx
index 496f39334..483ff78c8 100644
--- a/webapp/components/post_view/components/post_list.jsx
+++ b/webapp/components/post_view/components/post_list.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/post_view/components/post_message_container.jsx b/webapp/components/post_view/components/post_message_container.jsx
index 676aa010e..5d324ba46 100644
--- a/webapp/components/post_view/components/post_message_container.jsx
+++ b/webapp/components/post_view/components/post_message_container.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/post_view/components/post_message_view.jsx b/webapp/components/post_view/components/post_message_view.jsx
index 7f9789488..5b0790f36 100644
--- a/webapp/components/post_view/components/post_message_view.jsx
+++ b/webapp/components/post_view/components/post_message_view.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/post_view/components/post_time.jsx b/webapp/components/post_view/components/post_time.jsx
index 77f3f3266..e9c92b1f2 100644
--- a/webapp/components/post_view/components/post_time.jsx
+++ b/webapp/components/post_view/components/post_time.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/post_view/components/reaction.jsx b/webapp/components/post_view/components/reaction.jsx
index ae658da1f..0950b661b 100644
--- a/webapp/components/post_view/components/reaction.jsx
+++ b/webapp/components/post_view/components/reaction.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/post_view/components/reaction_container.jsx b/webapp/components/post_view/components/reaction_container.jsx
index 09e6ce5ea..e95325770 100644
--- a/webapp/components/post_view/components/reaction_container.jsx
+++ b/webapp/components/post_view/components/reaction_container.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/post_view/components/reaction_list_container.jsx b/webapp/components/post_view/components/reaction_list_container.jsx
index cdc58003b..b688afd94 100644
--- a/webapp/components/post_view/components/reaction_list_container.jsx
+++ b/webapp/components/post_view/components/reaction_list_container.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/post_view/components/reaction_list_view.jsx b/webapp/components/post_view/components/reaction_list_view.jsx
index b6c4b3a19..ee814883f 100644
--- a/webapp/components/post_view/components/reaction_list_view.jsx
+++ b/webapp/components/post_view/components/reaction_list_view.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/post_view/components/scroll_to_bottom_arrows.jsx b/webapp/components/post_view/components/scroll_to_bottom_arrows.jsx
index 461ca3358..d8d55f4be 100644
--- a/webapp/components/post_view/components/scroll_to_bottom_arrows.jsx
+++ b/webapp/components/post_view/components/scroll_to_bottom_arrows.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/post_view/components/system_message_helpers.jsx b/webapp/components/post_view/components/system_message_helpers.jsx
index 5db4ff871..c134e1a7a 100644
--- a/webapp/components/post_view/components/system_message_helpers.jsx
+++ b/webapp/components/post_view/components/system_message_helpers.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/post_view/post_focus_view_controller.jsx b/webapp/components/post_view/post_focus_view_controller.jsx
index 8edec6970..dadc6b80e 100644
--- a/webapp/components/post_view/post_focus_view_controller.jsx
+++ b/webapp/components/post_view/post_focus_view_controller.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import PostList from './components/post_list.jsx';
diff --git a/webapp/components/post_view/post_view_cache.jsx b/webapp/components/post_view/post_view_cache.jsx
index 5cf5b3094..d7cb360d1 100644
--- a/webapp/components/post_view/post_view_cache.jsx
+++ b/webapp/components/post_view/post_view_cache.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information
import PostViewController from './post_view_controller.jsx';
diff --git a/webapp/components/post_view/post_view_controller.jsx b/webapp/components/post_view/post_view_controller.jsx
index 220fe6b67..18ce61de3 100644
--- a/webapp/components/post_view/post_view_controller.jsx
+++ b/webapp/components/post_view/post_view_controller.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import PostList from './components/post_list.jsx';
diff --git a/webapp/components/profile_picture.jsx b/webapp/components/profile_picture.jsx
index 7a5f892db..b7ee08785 100644
--- a/webapp/components/profile_picture.jsx
+++ b/webapp/components/profile_picture.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ProfilePopover from './profile_popover.jsx';
import * as Utils from 'utils/utils.jsx';
diff --git a/webapp/components/profile_popover.jsx b/webapp/components/profile_popover.jsx
index c7d45474f..c86de514e 100644
--- a/webapp/components/profile_popover.jsx
+++ b/webapp/components/profile_popover.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as Utils from 'utils/utils.jsx';
diff --git a/webapp/components/removed_from_channel_modal.jsx b/webapp/components/removed_from_channel_modal.jsx
index 228132803..c82faf7e0 100644
--- a/webapp/components/removed_from_channel_modal.jsx
+++ b/webapp/components/removed_from_channel_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/rename_channel_modal.jsx b/webapp/components/rename_channel_modal.jsx
index 9fd505535..f7d8fad28 100644
--- a/webapp/components/rename_channel_modal.jsx
+++ b/webapp/components/rename_channel_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ReactDOM from 'react-dom';
diff --git a/webapp/components/rhs_comment.jsx b/webapp/components/rhs_comment.jsx
index 23c1b3819..10cd5fb55 100644
--- a/webapp/components/rhs_comment.jsx
+++ b/webapp/components/rhs_comment.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import UserProfile from './user_profile.jsx';
diff --git a/webapp/components/rhs_dropdown.jsx b/webapp/components/rhs_dropdown.jsx
index 882fdcf68..9c0f4d7b1 100644
--- a/webapp/components/rhs_dropdown.jsx
+++ b/webapp/components/rhs_dropdown.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as Agent from 'utils/user_agent.jsx';
diff --git a/webapp/components/rhs_dropdown_menu.jsx b/webapp/components/rhs_dropdown_menu.jsx
index 6efaa9dea..5f5107691 100644
--- a/webapp/components/rhs_dropdown_menu.jsx
+++ b/webapp/components/rhs_dropdown_menu.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {Dropdown} from 'react-bootstrap';
diff --git a/webapp/components/rhs_header_post.jsx b/webapp/components/rhs_header_post.jsx
index 72f00facf..951201024 100644
--- a/webapp/components/rhs_header_post.jsx
+++ b/webapp/components/rhs_header_post.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
diff --git a/webapp/components/rhs_root_post.jsx b/webapp/components/rhs_root_post.jsx
index 9a9f83f0c..41dd92e91 100644
--- a/webapp/components/rhs_root_post.jsx
+++ b/webapp/components/rhs_root_post.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import UserProfile from './user_profile.jsx';
diff --git a/webapp/components/rhs_thread.jsx b/webapp/components/rhs_thread.jsx
index 4ac36717a..a7bc65243 100644
--- a/webapp/components/rhs_thread.jsx
+++ b/webapp/components/rhs_thread.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import CreateComment from './create_comment.jsx';
diff --git a/webapp/components/root.jsx b/webapp/components/root.jsx
index 07c4415f5..b49b4d509 100644
--- a/webapp/components/root.jsx
+++ b/webapp/components/root.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as GlobalActions from 'actions/global_actions.jsx';
diff --git a/webapp/components/search_bar.jsx b/webapp/components/search_bar.jsx
index 910e3f5d9..0766ee3b7 100644
--- a/webapp/components/search_bar.jsx
+++ b/webapp/components/search_bar.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as GlobalActions from 'actions/global_actions.jsx';
diff --git a/webapp/components/search_results.jsx b/webapp/components/search_results.jsx
index 70f686f42..682b04e2a 100644
--- a/webapp/components/search_results.jsx
+++ b/webapp/components/search_results.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import SearchResultsHeader from './search_results_header.jsx';
diff --git a/webapp/components/search_results_header.jsx b/webapp/components/search_results_header.jsx
index 288d883ee..ca0a49012 100644
--- a/webapp/components/search_results_header.jsx
+++ b/webapp/components/search_results_header.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Constants from 'utils/constants.jsx';
diff --git a/webapp/components/search_results_item.jsx b/webapp/components/search_results_item.jsx
index 2773a8ee8..09ea8c427 100644
--- a/webapp/components/search_results_item.jsx
+++ b/webapp/components/search_results_item.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/searchable_channel_list.jsx b/webapp/components/searchable_channel_list.jsx
index 77a229d41..9c89f8dd4 100644
--- a/webapp/components/searchable_channel_list.jsx
+++ b/webapp/components/searchable_channel_list.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import LoadingScreen from './loading_screen.jsx';
@@ -210,4 +210,4 @@ SearchableChannelList.propTypes = {
search: React.PropTypes.func.isRequired,
handleJoin: React.PropTypes.func.isRequired,
noResultsText: React.PropTypes.object
-}; \ No newline at end of file
+};
diff --git a/webapp/components/searchable_user_list/searchable_user_list.jsx b/webapp/components/searchable_user_list/searchable_user_list.jsx
index 91e0205b0..5b262bcdf 100644
--- a/webapp/components/searchable_user_list/searchable_user_list.jsx
+++ b/webapp/components/searchable_user_list/searchable_user_list.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/searchable_user_list/searchable_user_list_container.jsx b/webapp/components/searchable_user_list/searchable_user_list_container.jsx
index 816dec062..9713572de 100644
--- a/webapp/components/searchable_user_list/searchable_user_list_container.jsx
+++ b/webapp/components/searchable_user_list/searchable_user_list_container.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/select_team/components/select_team_item.jsx b/webapp/components/select_team/components/select_team_item.jsx
index bff9e28d8..95325c4f3 100644
--- a/webapp/components/select_team/components/select_team_item.jsx
+++ b/webapp/components/select_team/components/select_team_item.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/select_team/select_team.jsx b/webapp/components/select_team/select_team.jsx
index 292c90510..43472bdad 100644
--- a/webapp/components/select_team/select_team.jsx
+++ b/webapp/components/select_team/select_team.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import UserStore from 'stores/user_store.jsx';
diff --git a/webapp/components/setting_item_max.jsx b/webapp/components/setting_item_max.jsx
index 2e7be779a..e45ffd10c 100644
--- a/webapp/components/setting_item_max.jsx
+++ b/webapp/components/setting_item_max.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {FormattedMessage} from 'react-intl';
diff --git a/webapp/components/setting_item_min.jsx b/webapp/components/setting_item_min.jsx
index 03c4da537..3b3ae13c5 100644
--- a/webapp/components/setting_item_min.jsx
+++ b/webapp/components/setting_item_min.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {FormattedMessage} from 'react-intl';
diff --git a/webapp/components/setting_picture.jsx b/webapp/components/setting_picture.jsx
index 45ac4096d..9c5913f3c 100644
--- a/webapp/components/setting_picture.jsx
+++ b/webapp/components/setting_picture.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {FormattedMessage} from 'react-intl';
@@ -112,7 +112,7 @@ export default class SettingPicture extends React.Component {
var helpText = (
<FormattedMessage
id='setting_picture.help'
- defaultMessage='Upload a profile picture in either JPG or PNG format, at least {width}px in width and {height}px height.'
+ defaultMessage='Upload a profile picture in BMP, JPG, JPEG or PNG format, at least {width}px in width and {height}px height.'
values={{
width: global.window.mm_config.ProfileWidth,
height: global.window.mm_config.ProfileHeight
diff --git a/webapp/components/setting_upload.jsx b/webapp/components/setting_upload.jsx
index 04e2de301..d6055ef08 100644
--- a/webapp/components/setting_upload.jsx
+++ b/webapp/components/setting_upload.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
@@ -124,4 +124,4 @@ SettingsUpload.propTypes = {
clientError: React.PropTypes.string,
serverError: React.PropTypes.string,
helpText: React.PropTypes.object
-}; \ No newline at end of file
+};
diff --git a/webapp/components/settings_sidebar.jsx b/webapp/components/settings_sidebar.jsx
index d537b6d10..dc98cdda3 100644
--- a/webapp/components/settings_sidebar.jsx
+++ b/webapp/components/settings_sidebar.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/should_verify_email.jsx b/webapp/components/should_verify_email.jsx
index 61edf9422..799f09c56 100644
--- a/webapp/components/should_verify_email.jsx
+++ b/webapp/components/should_verify_email.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {FormattedMessage} from 'react-intl';
diff --git a/webapp/components/sidebar.jsx b/webapp/components/sidebar.jsx
index 76ac81c6e..72dcac992 100644
--- a/webapp/components/sidebar.jsx
+++ b/webapp/components/sidebar.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/sidebar_header.jsx b/webapp/components/sidebar_header.jsx
index 9bc4a5639..83ed6a5de 100644
--- a/webapp/components/sidebar_header.jsx
+++ b/webapp/components/sidebar_header.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/sidebar_header_dropdown.jsx b/webapp/components/sidebar_header_dropdown.jsx
index baa8aae7b..728017b27 100644
--- a/webapp/components/sidebar_header_dropdown.jsx
+++ b/webapp/components/sidebar_header_dropdown.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/sidebar_header_dropdown_button.jsx b/webapp/components/sidebar_header_dropdown_button.jsx
index f8c258d33..f922af448 100644
--- a/webapp/components/sidebar_header_dropdown_button.jsx
+++ b/webapp/components/sidebar_header_dropdown_button.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/sidebar_right.jsx b/webapp/components/sidebar_right.jsx
index 3f3bacb05..483d30fc7 100644
--- a/webapp/components/sidebar_right.jsx
+++ b/webapp/components/sidebar_right.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/sidebar_right_menu.jsx b/webapp/components/sidebar_right_menu.jsx
index 7e689d95e..784f06eac 100644
--- a/webapp/components/sidebar_right_menu.jsx
+++ b/webapp/components/sidebar_right_menu.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
diff --git a/webapp/components/signup/components/signup_email.jsx b/webapp/components/signup/components/signup_email.jsx
index cf4ff0a95..c33fb45e0 100644
--- a/webapp/components/signup/components/signup_email.jsx
+++ b/webapp/components/signup/components/signup_email.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import LoadingScreen from 'components/loading_screen.jsx';
diff --git a/webapp/components/signup/components/signup_ldap.jsx b/webapp/components/signup/components/signup_ldap.jsx
index d93470db6..80fac3ecc 100644
--- a/webapp/components/signup/components/signup_ldap.jsx
+++ b/webapp/components/signup/components/signup_ldap.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import FormError from 'components/form_error.jsx';
diff --git a/webapp/components/signup/signup_controller.jsx b/webapp/components/signup/signup_controller.jsx
index 4facbc60d..251f05bb8 100644
--- a/webapp/components/signup/signup_controller.jsx
+++ b/webapp/components/signup/signup_controller.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/spinner_button.jsx b/webapp/components/spinner_button.jsx
index becf395c5..8e946592f 100644
--- a/webapp/components/spinner_button.jsx
+++ b/webapp/components/spinner_button.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/status_icon.jsx b/webapp/components/status_icon.jsx
index cf5ef6947..07416e6fc 100644
--- a/webapp/components/status_icon.jsx
+++ b/webapp/components/status_icon.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Constants from 'utils/constants.jsx';
diff --git a/webapp/components/suggestion/at_mention_provider.jsx b/webapp/components/suggestion/at_mention_provider.jsx
index 68a5c64bc..ddf9d46e7 100644
--- a/webapp/components/suggestion/at_mention_provider.jsx
+++ b/webapp/components/suggestion/at_mention_provider.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Suggestion from './suggestion.jsx';
diff --git a/webapp/components/suggestion/channel_mention_provider.jsx b/webapp/components/suggestion/channel_mention_provider.jsx
index 7ea5f7374..a464fcec9 100644
--- a/webapp/components/suggestion/channel_mention_provider.jsx
+++ b/webapp/components/suggestion/channel_mention_provider.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Suggestion from './suggestion.jsx';
diff --git a/webapp/components/suggestion/command_provider.jsx b/webapp/components/suggestion/command_provider.jsx
index ea89df98d..30b989d70 100644
--- a/webapp/components/suggestion/command_provider.jsx
+++ b/webapp/components/suggestion/command_provider.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/suggestion/emoticon_provider.jsx b/webapp/components/suggestion/emoticon_provider.jsx
index 6cead0abb..0a7f1ff8a 100644
--- a/webapp/components/suggestion/emoticon_provider.jsx
+++ b/webapp/components/suggestion/emoticon_provider.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/suggestion/provider.jsx b/webapp/components/suggestion/provider.jsx
index db34dcebf..b65068d47 100644
--- a/webapp/components/suggestion/provider.jsx
+++ b/webapp/components/suggestion/provider.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
export default class Provider {
diff --git a/webapp/components/suggestion/search_channel_provider.jsx b/webapp/components/suggestion/search_channel_provider.jsx
index 06b332127..3e0015778 100644
--- a/webapp/components/suggestion/search_channel_provider.jsx
+++ b/webapp/components/suggestion/search_channel_provider.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Suggestion from './suggestion.jsx';
diff --git a/webapp/components/suggestion/search_suggestion_list.jsx b/webapp/components/suggestion/search_suggestion_list.jsx
index ee7a77366..4eb26a1cf 100644
--- a/webapp/components/suggestion/search_suggestion_list.jsx
+++ b/webapp/components/suggestion/search_suggestion_list.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/suggestion/search_user_provider.jsx b/webapp/components/suggestion/search_user_provider.jsx
index f1b45c0d6..6fcc7f7e9 100644
--- a/webapp/components/suggestion/search_user_provider.jsx
+++ b/webapp/components/suggestion/search_user_provider.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Suggestion from './suggestion.jsx';
diff --git a/webapp/components/suggestion/suggestion.jsx b/webapp/components/suggestion/suggestion.jsx
index 8547d50d0..1ad816638 100644
--- a/webapp/components/suggestion/suggestion.jsx
+++ b/webapp/components/suggestion/suggestion.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
@@ -25,4 +25,4 @@ export default class Suggestion extends React.Component {
this.props.onClick(this.props.term, this.props.matchedPretext);
}
-} \ No newline at end of file
+}
diff --git a/webapp/components/suggestion/suggestion_box.jsx b/webapp/components/suggestion/suggestion_box.jsx
index e6179d5e5..6126a16a0 100644
--- a/webapp/components/suggestion/suggestion_box.jsx
+++ b/webapp/components/suggestion/suggestion_box.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Constants from 'utils/constants.jsx';
diff --git a/webapp/components/suggestion/suggestion_list.jsx b/webapp/components/suggestion/suggestion_list.jsx
index 18d45242a..959ed595a 100644
--- a/webapp/components/suggestion/suggestion_list.jsx
+++ b/webapp/components/suggestion/suggestion_list.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/suggestion/switch_channel_provider.jsx b/webapp/components/suggestion/switch_channel_provider.jsx
index 6d4340780..3d295951c 100644
--- a/webapp/components/suggestion/switch_channel_provider.jsx
+++ b/webapp/components/suggestion/switch_channel_provider.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Suggestion from './suggestion.jsx';
diff --git a/webapp/components/team_general_tab.jsx b/webapp/components/team_general_tab.jsx
index 288faae6c..21ad6a8a2 100644
--- a/webapp/components/team_general_tab.jsx
+++ b/webapp/components/team_general_tab.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/team_import_tab.jsx b/webapp/components/team_import_tab.jsx
index 364190a52..a17442dc9 100644
--- a/webapp/components/team_import_tab.jsx
+++ b/webapp/components/team_import_tab.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as utils from 'utils/utils.jsx';
diff --git a/webapp/components/team_members_dropdown.jsx b/webapp/components/team_members_dropdown.jsx
index 7d0b645cd..3f4180425 100644
--- a/webapp/components/team_members_dropdown.jsx
+++ b/webapp/components/team_members_dropdown.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ConfirmModal from './confirm_modal.jsx';
diff --git a/webapp/components/team_members_modal.jsx b/webapp/components/team_members_modal.jsx
index 37bfe9ea5..87b0ff294 100644
--- a/webapp/components/team_members_modal.jsx
+++ b/webapp/components/team_members_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import MemberListTeam from './member_list_team.jsx';
diff --git a/webapp/components/team_settings.jsx b/webapp/components/team_settings.jsx
index 0725f9fe5..8edd5e0a6 100644
--- a/webapp/components/team_settings.jsx
+++ b/webapp/components/team_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TeamStore from 'stores/team_store.jsx';
diff --git a/webapp/components/team_settings_modal.jsx b/webapp/components/team_settings_modal.jsx
index bbe426d2e..a1756da76 100644
--- a/webapp/components/team_settings_modal.jsx
+++ b/webapp/components/team_settings_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/team_sidebar/components/team_button.jsx b/webapp/components/team_sidebar/components/team_button.jsx
index 894567538..2a35e1172 100644
--- a/webapp/components/team_sidebar/components/team_button.jsx
+++ b/webapp/components/team_sidebar/components/team_button.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Constants from 'utils/constants.jsx';
diff --git a/webapp/components/team_sidebar/team_sidebar_controller.jsx b/webapp/components/team_sidebar/team_sidebar_controller.jsx
index 9863b5e32..2f41d485c 100644
--- a/webapp/components/team_sidebar/team_sidebar_controller.jsx
+++ b/webapp/components/team_sidebar/team_sidebar_controller.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TeamButton from './components/team_button.jsx';
diff --git a/webapp/components/textbox.jsx b/webapp/components/textbox.jsx
index f15848688..edc4b0502 100644
--- a/webapp/components/textbox.jsx
+++ b/webapp/components/textbox.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/toggle_modal_button.jsx b/webapp/components/toggle_modal_button.jsx
index 304ba386c..7d4d0a364 100644
--- a/webapp/components/toggle_modal_button.jsx
+++ b/webapp/components/toggle_modal_button.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/tutorial/tutorial_intro_screens.jsx b/webapp/components/tutorial/tutorial_intro_screens.jsx
index 5197696c4..78203fec0 100644
--- a/webapp/components/tutorial/tutorial_intro_screens.jsx
+++ b/webapp/components/tutorial/tutorial_intro_screens.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import UserStore from 'stores/user_store.jsx';
diff --git a/webapp/components/tutorial/tutorial_tip.jsx b/webapp/components/tutorial/tutorial_tip.jsx
index e78668b10..f0e0d7673 100644
--- a/webapp/components/tutorial/tutorial_tip.jsx
+++ b/webapp/components/tutorial/tutorial_tip.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import UserStore from 'stores/user_store.jsx';
diff --git a/webapp/components/tutorial/tutorial_view.jsx b/webapp/components/tutorial/tutorial_view.jsx
index 39e7b6816..491e3146e 100644
--- a/webapp/components/tutorial/tutorial_view.jsx
+++ b/webapp/components/tutorial/tutorial_view.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TutorialIntroScreens from './tutorial_intro_screens.jsx';
diff --git a/webapp/components/unread_channel_indicator.jsx b/webapp/components/unread_channel_indicator.jsx
index ee62a3e43..9d6b57d44 100644
--- a/webapp/components/unread_channel_indicator.jsx
+++ b/webapp/components/unread_channel_indicator.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
// Indicator for the left sidebar which indicate if there's unread posts in a channel that is not shown
diff --git a/webapp/components/user_list.jsx b/webapp/components/user_list.jsx
index c521b95cc..62301b852 100644
--- a/webapp/components/user_list.jsx
+++ b/webapp/components/user_list.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import UserListRow from './user_list_row.jsx';
diff --git a/webapp/components/user_list_row.jsx b/webapp/components/user_list_row.jsx
index 3a13ccb66..3a7fc5d1c 100644
--- a/webapp/components/user_list_row.jsx
+++ b/webapp/components/user_list_row.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ProfilePicture from 'components/profile_picture.jsx';
diff --git a/webapp/components/user_profile.jsx b/webapp/components/user_profile.jsx
index 8c365b6da..37993094b 100644
--- a/webapp/components/user_profile.jsx
+++ b/webapp/components/user_profile.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ProfilePopover from './profile_popover.jsx';
diff --git a/webapp/components/user_settings/custom_theme_chooser.jsx b/webapp/components/user_settings/custom_theme_chooser.jsx
index 8c5cf939e..79edd230e 100644
--- a/webapp/components/user_settings/custom_theme_chooser.jsx
+++ b/webapp/components/user_settings/custom_theme_chooser.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/user_settings/desktop_notification_settings.jsx b/webapp/components/user_settings/desktop_notification_settings.jsx
index be403ebb6..d94c02007 100644
--- a/webapp/components/user_settings/desktop_notification_settings.jsx
+++ b/webapp/components/user_settings/desktop_notification_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import SettingItemMin from 'components/setting_item_min.jsx';
diff --git a/webapp/components/user_settings/email_notification_setting.jsx b/webapp/components/user_settings/email_notification_setting.jsx
index 6980be0b7..4620adcc4 100644
--- a/webapp/components/user_settings/email_notification_setting.jsx
+++ b/webapp/components/user_settings/email_notification_setting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/components/user_settings/import_theme_modal.jsx b/webapp/components/user_settings/import_theme_modal.jsx
index 9d3cff53d..298391f87 100644
--- a/webapp/components/user_settings/import_theme_modal.jsx
+++ b/webapp/components/user_settings/import_theme_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ModalStore from 'stores/modal_store.jsx';
diff --git a/webapp/components/user_settings/premade_theme_chooser.jsx b/webapp/components/user_settings/premade_theme_chooser.jsx
index 03ea56449..4a0254d40 100644
--- a/webapp/components/user_settings/premade_theme_chooser.jsx
+++ b/webapp/components/user_settings/premade_theme_chooser.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/user_settings/user_settings.jsx b/webapp/components/user_settings/user_settings.jsx
index 99a7ec93b..d9d5423fe 100644
--- a/webapp/components/user_settings/user_settings.jsx
+++ b/webapp/components/user_settings/user_settings.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import UserStore from 'stores/user_store.jsx';
diff --git a/webapp/components/user_settings/user_settings_advanced.jsx b/webapp/components/user_settings/user_settings_advanced.jsx
index bd5597bbb..329bdd50d 100644
--- a/webapp/components/user_settings/user_settings_advanced.jsx
+++ b/webapp/components/user_settings/user_settings_advanced.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/user_settings/user_settings_display.jsx b/webapp/components/user_settings/user_settings_display.jsx
index 60f322467..bf4d24b49 100644
--- a/webapp/components/user_settings/user_settings_display.jsx
+++ b/webapp/components/user_settings/user_settings_display.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/user_settings/user_settings_general.jsx b/webapp/components/user_settings/user_settings_general.jsx
index d558958f0..ce4349519 100644
--- a/webapp/components/user_settings/user_settings_general.jsx
+++ b/webapp/components/user_settings/user_settings_general.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/user_settings/user_settings_modal.jsx b/webapp/components/user_settings/user_settings_modal.jsx
index e05f61ea7..1d43126bd 100644
--- a/webapp/components/user_settings/user_settings_modal.jsx
+++ b/webapp/components/user_settings/user_settings_modal.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/user_settings/user_settings_notifications.jsx b/webapp/components/user_settings/user_settings_notifications.jsx
index ebd43e5af..0caffb512 100644
--- a/webapp/components/user_settings/user_settings_notifications.jsx
+++ b/webapp/components/user_settings/user_settings_notifications.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/user_settings/user_settings_security.jsx b/webapp/components/user_settings/user_settings_security.jsx
index 9ca7f4b62..ead579c19 100644
--- a/webapp/components/user_settings/user_settings_security.jsx
+++ b/webapp/components/user_settings/user_settings_security.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import SettingItemMin from '../setting_item_min.jsx';
diff --git a/webapp/components/user_settings/user_settings_theme.jsx b/webapp/components/user_settings/user_settings_theme.jsx
index 35df0bd13..88b03a0ff 100644
--- a/webapp/components/user_settings/user_settings_theme.jsx
+++ b/webapp/components/user_settings/user_settings_theme.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/view_image.jsx b/webapp/components/view_image.jsx
index e5c3caa0a..580c9e7a4 100644
--- a/webapp/components/view_image.jsx
+++ b/webapp/components/view_image.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AudioVideoPreview from './audio_video_preview.jsx';
@@ -180,7 +180,7 @@ export default class ViewImageModal extends React.Component {
if (this.state.loaded[this.state.imgId]) {
const fileType = Utils.getFileType(fileInfo.extension);
- if (fileType === 'image') {
+ if (fileType === 'image' || fileType === 'svg') {
content = (
<ImagePreview
fileInfo={fileInfo}
diff --git a/webapp/components/view_image_popover_bar.jsx b/webapp/components/view_image_popover_bar.jsx
index 3554ae3f8..0a07522fc 100644
--- a/webapp/components/view_image_popover_bar.jsx
+++ b/webapp/components/view_image_popover_bar.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {FormattedMessage} from 'react-intl';
diff --git a/webapp/components/webrtc/components/webrtc_header.jsx b/webapp/components/webrtc/components/webrtc_header.jsx
index 7e62f99ed..56bd65ed7 100644
--- a/webapp/components/webrtc/components/webrtc_header.jsx
+++ b/webapp/components/webrtc/components/webrtc_header.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Constants from 'utils/constants.jsx';
diff --git a/webapp/components/webrtc/components/webrtc_notification.jsx b/webapp/components/webrtc/components/webrtc_notification.jsx
index f69e731f8..2a86b932e 100644
--- a/webapp/components/webrtc/components/webrtc_notification.jsx
+++ b/webapp/components/webrtc/components/webrtc_notification.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Client from 'client/web_client.jsx';
diff --git a/webapp/components/webrtc/components/webrtc_sidebar.jsx b/webapp/components/webrtc/components/webrtc_sidebar.jsx
index 2979e6025..c207ab489 100644
--- a/webapp/components/webrtc/components/webrtc_sidebar.jsx
+++ b/webapp/components/webrtc/components/webrtc_sidebar.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/components/webrtc/webrtc_controller.jsx b/webapp/components/webrtc/webrtc_controller.jsx
index 9d625dcf4..02c064026 100644
--- a/webapp/components/webrtc/webrtc_controller.jsx
+++ b/webapp/components/webrtc/webrtc_controller.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import UserStore from 'stores/user_store.jsx';
diff --git a/webapp/components/youtube_video.jsx b/webapp/components/youtube_video.jsx
index 7b7133af3..48c426b73 100644
--- a/webapp/components/youtube_video.jsx
+++ b/webapp/components/youtube_video.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import ChannelStore from 'stores/channel_store.jsx';
diff --git a/webapp/dispatcher/app_dispatcher.jsx b/webapp/dispatcher/app_dispatcher.jsx
index d4a709c23..c74a16220 100644
--- a/webapp/dispatcher/app_dispatcher.jsx
+++ b/webapp/dispatcher/app_dispatcher.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as Flux from 'flux';
diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json
index 1a6bfa897..adcc2187f 100755
--- a/webapp/i18n/en.json
+++ b/webapp/i18n/en.json
@@ -1,6 +1,6 @@
{
"about.close": "Close",
- "about.copyright": "Copyright 2016 Mattermost, Inc. All rights reserved",
+ "about.copyright": "Copyright 2015 - {currentYear} Mattermost, Inc. All rights reserved",
"about.database": "Database:",
"about.date": "Build Date:",
"about.enterpriseEditionLearn": "Learn more about Enterprise Edition at ",
@@ -166,6 +166,7 @@
"admin.cluster.status_table.status": "Status",
"admin.cluster.status_table.url": "Inter-Node URL",
"admin.cluster.status_table.version": "Version",
+ "admin.cluster.unknown": "unknown",
"admin.compliance.directoryDescription": "Directory to which compliance reports are written. If blank, will be set to ./data/.",
"admin.compliance.directoryExample": "E.g.: \"./data/\"",
"admin.compliance.directoryTitle": "Compliance Report Directory:",
@@ -393,6 +394,7 @@
"admin.image.amazonS3RegionExample": "E.g.: \"us-east-1\"",
"admin.image.amazonS3RegionTitle": "Amazon S3 Region:",
"admin.image.amazonS3SSLDescription": "When false, allow insecure connections to Amazon S3. Defaults to secure connections only.",
+ "admin.image.amazonS3SSLExample": "E.g.: \"true\"",
"admin.image.amazonS3SSLTitle": "Enable Secure Amazon S3 Connections:",
"admin.image.amazonS3SecretDescription": "Obtain this credential from your Amazon EC2 administrator.",
"admin.image.amazonS3SecretExample": "E.g.: \"jcuS8PuvcpGhpgHhlcpT1Mx42pnqMxQY\"",
@@ -694,9 +696,9 @@
"admin.service.corsDescription": "Enable HTTP Cross origin request from a specific domain. Use \"*\" if you want to allow CORS from any domain or leave it blank to disable it.",
"admin.service.corsEx": "http://example.com",
"admin.service.corsTitle": "Enable cross-origin requests from:",
- "admin.service.developerDesc": "When true, JavaScript errors are shown in a red bar at the top of the user interface. Not recommended for use in production. ",
+ "admin.service.developerDesc": "When true, JavaScript errors are shown in a purple bar at the top of the user interface. Not recommended for use in production. ",
"admin.service.developerTitle": "Enable Developer Mode: ",
- "admin.service.enforcMfaTitle": "Enforce Multi-factor Authentication:",
+ "admin.service.enforceMfaTitle": "Enforce Multi-factor Authentication:",
"admin.service.enforceMfaDesc": "When true, <a href='https://docs.mattermost.com/deployment/auth.html' target='_blank'>multi-factor authentication</a> is required for login. New users will be required to configure MFA on signup. Logged in users without MFA configured are redirected to the MFA setup page until configuration is complete.<br/><br/>If your system has users with login methods other than AD/LDAP and email, MFA must be enforced with the authentication provider outside of Mattermost.",
"admin.service.forward80To443": "Forward port 80 to 443:",
"admin.service.forward80To443Description": "Forwards all insecure traffic from port 80 to secure port 443",
@@ -778,6 +780,7 @@
"admin.sidebar.login": "Login",
"admin.sidebar.logs": "Logs",
"admin.sidebar.metrics": "Performance Monitoring",
+ "admin.sidebar.mfa": "MFA",
"admin.sidebar.nativeAppLinks": "Mattermost App Links",
"admin.sidebar.notifications": "Notifications",
"admin.sidebar.oauth": "OAuth 2.0",
@@ -1135,7 +1138,7 @@
"channel_modal.publicChannel2": "Create a new public channel anyone can join. ",
"channel_modal.purpose": "Purpose",
"channel_modal.purposeEx": "E.g.: \"A channel to file bugs and improvements\"",
- "channel_notification.push": "Send mobile push notifications",
+ "channel_notifications.push": "Send mobile push notifications",
"channel_notifications.allActivity": "For all activity",
"channel_notifications.allUnread": "For all unread messages",
"channel_notifications.globalDefault": "Global default ({notifyLevel})",
@@ -1296,6 +1299,10 @@
"emoji_picker.search": "Search",
"emoji_picker.symbols": "Symbols",
"emoji_picker.travel": "Travel",
+ "error.local_storage.help1": "Enable cookies",
+ "error.local_storage.help2": "Turn off private browsing",
+ "error.local_storage.help3": "Use a supported browser (IE 11, Chrome 43+, Firefox 38+, Safari 9, Edge)",
+ "error.local_storage.message": "Mattermost was unable to load because a setting in your browser prevents the use of its local storage features. To allow Mattermost to load, try the following actions:",
"error.not_found.link_message": "Back to Mattermost",
"error.not_found.message": "The page you were trying to reach does not exist",
"error.not_found.title": "Page not found",
@@ -1886,7 +1893,7 @@
"setting_item_max.save": "Save",
"setting_item_min.edit": "Edit",
"setting_picture.cancel": "Cancel",
- "setting_picture.help": "Upload a profile picture in either JPG or PNG format, at least {width}px in width and {height}px height.",
+ "setting_picture.help": "Upload a profile picture in BMP, JPG, JPEG or PNG format, at least {width}px in width and {height}px height.",
"setting_picture.save": "Save",
"setting_picture.select": "Select",
"setting_upload.import": "Import",
@@ -1957,7 +1964,7 @@
"signup_user_completed.office365": "with Office 365",
"signup_user_completed.onSite": "on {siteName}",
"signup_user_completed.or": "or",
- "signup_user_completed.passwordLength": "Please enter at least {min} characters",
+ "signup_user_completed.passwordLength": "Please enter between {min} and {max} characters",
"signup_user_completed.required": "This field is required",
"signup_user_completed.reserved": "This username is reserved, please choose a new one.",
"signup_user_completed.signIn": "Click here to sign in.",
@@ -2306,22 +2313,22 @@
"user.settings.security.office365": "Office 365",
"user.settings.security.oneSignin": "You may only have one sign-in method at a time. Switching sign-in method will send an email notifying you if the change was successful.",
"user.settings.security.password": "Password",
- "user.settings.security.passwordError": "Your password must contain at least {min} characters.",
- "user.settings.security.passwordErrorLowercase": "Your password must contain at least {min} characters made up of at least one lowercase letter.",
- "user.settings.security.passwordErrorLowercaseNumber": "Your password must contain at least {min} characters made up of at least one lowercase letter and at least one number.",
- "user.settings.security.passwordErrorLowercaseNumberSymbol": "Your password must contain at least {min} characters made up of at least one lowercase letter, at least one number, and at least one symbol (e.g. \"~!@#$%^&*()\").",
- "user.settings.security.passwordErrorLowercaseSymbol": "Your password must contain at least {min} characters made up of at least one lowercase letter and at least one symbol (e.g. \"~!@#$%^&*()\").",
- "user.settings.security.passwordErrorLowercaseUppercase": "Your password must contain at least {min} characters made up of at least one lowercase letter and at least one uppercase letter.",
- "user.settings.security.passwordErrorLowercaseUppercaseNumber": "Your password must contain at least {min} characters made up of at least one lowercase letter, at least one uppercase letter, and at least one number.",
- "user.settings.security.passwordErrorLowercaseUppercaseNumberSymbol": "Your password must contain at least {min} characters made up of at least one lowercase letter, at least one uppercase letter, at least one number, and at least one symbol (e.g. \"~!@#$%^&*()\").",
- "user.settings.security.passwordErrorLowercaseUppercaseSymbol": "Your password must contain at least {min} characters made up of at least one lowercase letter, at least one uppercase letter, and at least one symbol (e.g. \"~!@#$%^&*()\").",
- "user.settings.security.passwordErrorNumber": "Your password must contain at least {min} characters made up of at least one number.",
- "user.settings.security.passwordErrorNumberSymbol": "Your password must contain at least {min} characters made up of at least one number and at least one symbol (e.g. \"~!@#$%^&*()\").",
- "user.settings.security.passwordErrorSymbol": "Your password must contain at least {min} characters made up of at least one symbol (e.g. \"~!@#$%^&*()\").",
- "user.settings.security.passwordErrorUppercase": "Your password must contain at least {min} characters made up of at least one uppercase letter.",
- "user.settings.security.passwordErrorUppercaseNumber": "Your password must contain at least {min} characters made up of at least one uppercase letter and at least one number.",
- "user.settings.security.passwordErrorUppercaseNumberSymbol": "Your password must contain at least {min} characters made up of at least one uppercase letter, at least one number, and at least one symbol (e.g. \"~!@#$%^&*()\").",
- "user.settings.security.passwordErrorUppercaseSymbol": "Your password must contain at least {min} characters made up of at least one uppercase letter and at least one symbol (e.g. \"~!@#$%^&*()\").",
+ "user.settings.security.passwordError": "Your password must contain between {min} and {max} characters.",
+ "user.settings.security.passwordErrorLowercase": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter.",
+ "user.settings.security.passwordErrorLowercaseNumber": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter and at least one number.",
+ "user.settings.security.passwordErrorLowercaseNumberSymbol": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter, at least one number, and at least one symbol (e.g. \"~!@#$%^&*()\").",
+ "user.settings.security.passwordErrorLowercaseSymbol": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter and at least one symbol (e.g. \"~!@#$%^&*()\").",
+ "user.settings.security.passwordErrorLowercaseUppercase": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter and at least one uppercase letter.",
+ "user.settings.security.passwordErrorLowercaseUppercaseNumber": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter, at least one uppercase letter, and at least one number.",
+ "user.settings.security.passwordErrorLowercaseUppercaseNumberSymbol": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter, at least one uppercase letter, at least one number, and at least one symbol (e.g. \"~!@#$%^&*()\").",
+ "user.settings.security.passwordErrorLowercaseUppercaseSymbol": "Your password must contain between {min} and {max} characters made up of at least one lowercase letter, at least one uppercase letter, and at least one symbol (e.g. \"~!@#$%^&*()\").",
+ "user.settings.security.passwordErrorNumber": "Your password must contain between {min} and {max} characters made up of at least one number.",
+ "user.settings.security.passwordErrorNumberSymbol": "Your password must contain between {min} and {max} characters made up of at least one number and at least one symbol (e.g. \"~!@#$%^&*()\").",
+ "user.settings.security.passwordErrorSymbol": "Your password must contain between {min} and {max} characters made up of at least one symbol (e.g. \"~!@#$%^&*()\").",
+ "user.settings.security.passwordErrorUppercase": "Your password must contain between {min} and {max} characters made up of at least one uppercase letter.",
+ "user.settings.security.passwordErrorUppercaseNumber": "Your password must contain between {min} and {max} characters made up of at least one uppercase letter and at least one number.",
+ "user.settings.security.passwordErrorUppercaseNumberSymbol": "Your password must contain between {min} and {max} characters made up of at least one uppercase letter, at least one number, and at least one symbol (e.g. \"~!@#$%^&*()\").",
+ "user.settings.security.passwordErrorUppercaseSymbol": "Your password must contain between {min} and {max} characters made up of at least one uppercase letter and at least one symbol (e.g. \"~!@#$%^&*()\").",
"user.settings.security.passwordGitlabCantUpdate": "Login occurs through GitLab. Password cannot be updated.",
"user.settings.security.passwordGoogleCantUpdate": "Login occurs through Google Apps. Password cannot be updated.",
"user.settings.security.passwordLdapCantUpdate": "Login occurs through AD/LDAP. Password cannot be updated.",
diff --git a/webapp/i18n/i18n.jsx b/webapp/i18n/i18n.jsx
index fd4e42a32..8768b5715 100644
--- a/webapp/i18n/i18n.jsx
+++ b/webapp/i18n/i18n.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
const de = require('!!file-loader?name=i18n/[name].[hash].[ext]!./de.json');
diff --git a/webapp/root.jsx b/webapp/root.jsx
index e28cbfd75..177eb1ec4 100644
--- a/webapp/root.jsx
+++ b/webapp/root.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/routes/route_admin_console.jsx b/webapp/routes/route_admin_console.jsx
index 1f23f9139..7dde044cb 100644
--- a/webapp/routes/route_admin_console.jsx
+++ b/webapp/routes/route_admin_console.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as RouteUtils from 'routes/route_utils.jsx';
diff --git a/webapp/routes/route_emoji.jsx b/webapp/routes/route_emoji.jsx
index 207c81172..2718a428e 100644
--- a/webapp/routes/route_emoji.jsx
+++ b/webapp/routes/route_emoji.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as RouteUtils from 'routes/route_utils.jsx';
diff --git a/webapp/routes/route_help.jsx b/webapp/routes/route_help.jsx
index 37c3c4884..7c0ad2dd1 100644
--- a/webapp/routes/route_help.jsx
+++ b/webapp/routes/route_help.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as RouteUtils from 'routes/route_utils.jsx';
diff --git a/webapp/routes/route_integrations.jsx b/webapp/routes/route_integrations.jsx
index 2933ba189..cf59882dd 100644
--- a/webapp/routes/route_integrations.jsx
+++ b/webapp/routes/route_integrations.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as RouteUtils from 'routes/route_utils.jsx';
diff --git a/webapp/routes/route_root.jsx b/webapp/routes/route_root.jsx
index cd0cb9a5d..4f22edb80 100644
--- a/webapp/routes/route_root.jsx
+++ b/webapp/routes/route_root.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as RouteUtils from 'routes/route_utils.jsx';
diff --git a/webapp/routes/route_team.jsx b/webapp/routes/route_team.jsx
index d8350a3c7..e8ef3f410 100644
--- a/webapp/routes/route_team.jsx
+++ b/webapp/routes/route_team.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
diff --git a/webapp/routes/route_utils.jsx b/webapp/routes/route_utils.jsx
index f36d7bcd8..c5d889017 100644
--- a/webapp/routes/route_utils.jsx
+++ b/webapp/routes/route_utils.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as Utils from 'utils/utils.jsx';
diff --git a/webapp/sass/components/_emoticons.scss b/webapp/sass/components/_emoticons.scss
index cf8815a24..df4bbc158 100644
--- a/webapp/sass/components/_emoticons.scss
+++ b/webapp/sass/components/_emoticons.scss
@@ -240,6 +240,7 @@
margin: 3px;
}
}
+
.emojisprite-wrapper {
cursor: pointer;
}
@@ -247,30 +248,33 @@
.emoji-picker__preview {
border-top: 1px solid;
display: table-cell;
- vertical-align: middle;
flex-grow: 0;
flex-shrink: 0;
- height:45px;
- width: 278px;
+ height: 45px;
padding: 3px 10px;
+ vertical-align: middle;
+ width: 278px;
&.emoji-picker__preview-placeholder {
padding: 12px;
}
- .emoji-picker__preview-image-box {
+ > div {
display: table-cell;
vertical-align: middle;
+ }
+
+ .emoji-picker__preview-image-box {
height: 36px;
width: 42px;
.sprite-preview {
+ border: none;
+ display: inline-block;
height: 36px;
- width: 36px;
+ padding: 0;
vertical-align: middle;
- padding: 0px;
- border: 0px;
- display: inline-block;
+ width: 36px;
}
}
diff --git a/webapp/sass/layout/_markdown.scss b/webapp/sass/layout/_markdown.scss
index a98b67f94..7df279f5e 100644
--- a/webapp/sass/layout/_markdown.scss
+++ b/webapp/sass/layout/_markdown.scss
@@ -67,19 +67,19 @@
padding: 4px 10px 5px;
position: absolute;
right: 0;
- top: 0;
+ top: 5;
z-index: 5;
}
.post-code__lineno {
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -o-user-select: none;
+ -webkit-user-select: none;
border-right: 1px solid #aaa;
color: #aaa;
margin-right: .5em;
text-align: right;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- -o-user-select: none;
user-select: none;
}
diff --git a/webapp/sass/layout/_post.scss b/webapp/sass/layout/_post.scss
index 00276ec7e..6ffb47c2d 100644
--- a/webapp/sass/layout/_post.scss
+++ b/webapp/sass/layout/_post.scss
@@ -837,7 +837,7 @@
}
.post__img {
- padding-top: 3px;
+ padding-top: 1px;
width: 16px;
img {
@@ -913,7 +913,7 @@
left: 36px;
margin-left: 7px;
position: absolute;
- top: 8px;
+ top: 6px;
}
.post__img {
@@ -1036,6 +1036,7 @@
right: 0;
top: -4px;
white-space: nowrap;
+ z-index: 6;
}
.col__remove {
@@ -1159,7 +1160,6 @@
word-wrap: break-word;
div {
- margin-bottom: .4em;
}
p + p {
diff --git a/webapp/sass/layout/_sidebar-right.scss b/webapp/sass/layout/_sidebar-right.scss
index 8d801a0c2..bb979357d 100644
--- a/webapp/sass/layout/_sidebar-right.scss
+++ b/webapp/sass/layout/_sidebar-right.scss
@@ -42,6 +42,12 @@
}
.post {
+ &.post--compact {
+ .post__pinned-badge {
+ margin: 0 0 0 5px;
+ }
+ }
+
.post__content {
padding: 0 10px 0 0;
}
diff --git a/webapp/sass/responsive/_tablet.scss b/webapp/sass/responsive/_tablet.scss
index e97eb3b59..1a0a27267 100644
--- a/webapp/sass/responsive/_tablet.scss
+++ b/webapp/sass/responsive/_tablet.scss
@@ -19,16 +19,18 @@
width: 300px;
}
}
- .post-right__scroll{
- .post-create__container{
+
+ .post-right__scroll {
+ .post-create__container {
.post-create-body {
.icon__emoji_picker {
- display:none;
+ display: none;
top: -7px;
}
}
}
}
+
.post-create__container {
form {
padding: .5em 0 0;
@@ -262,8 +264,12 @@
&:not(.post--thread) {
padding: 0 .5em 0 77px;
+ &.other--root {
+
+ }
+
.post__link {
- margin: 4px 0 7px;
+ margin: 3px 0 7px;
vertical-align: bottom;
}
@@ -278,7 +284,7 @@
.post__header {
float: left;
height: 21px;
- padding-top: 3px;
+ padding-top: 2px;
.col__name {
font-weight: bold;
@@ -298,14 +304,6 @@
}
&.other--root {
- .post__body {
- > div {
- &:first-child {
- min-height: 21px;
- }
- }
- }
-
.post__link + .post__body {
clear: both;
}
@@ -422,11 +420,11 @@
display: inline-block;
font-size: 11px;
left: -14px;
- line-height: 34px;
+ line-height: 20px;
position: absolute;
text-align: right;
text-rendering: auto;
- top: -2px;
+ top: 4px;
width: 51px;
&:hover {
diff --git a/webapp/sass/routes/_admin-console.scss b/webapp/sass/routes/_admin-console.scss
index a39e1c20a..854c84e20 100644
--- a/webapp/sass/routes/_admin-console.scss
+++ b/webapp/sass/routes/_admin-console.scss
@@ -498,7 +498,11 @@
.system-users__team-filter {
display: inline-block;
- width: 200px
+ width: 200px;
+ }
+
+ label {
+ font-weight: normal;
}
}
diff --git a/webapp/stores/admin_store.jsx b/webapp/stores/admin_store.jsx
index 59c763575..8d83dc360 100644
--- a/webapp/stores/admin_store.jsx
+++ b/webapp/stores/admin_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
diff --git a/webapp/stores/analytics_store.jsx b/webapp/stores/analytics_store.jsx
index 565622c76..01c60b2f9 100644
--- a/webapp/stores/analytics_store.jsx
+++ b/webapp/stores/analytics_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
diff --git a/webapp/stores/browser_store.jsx b/webapp/stores/browser_store.jsx
index 123a7d8b9..b0c923594 100644
--- a/webapp/stores/browser_store.jsx
+++ b/webapp/stores/browser_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {browserHistory} from 'react-router/es6';
diff --git a/webapp/stores/channel_store.jsx b/webapp/stores/channel_store.jsx
index 41fa76b39..8530d0620 100644
--- a/webapp/stores/channel_store.jsx
+++ b/webapp/stores/channel_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
diff --git a/webapp/stores/emoji_store.jsx b/webapp/stores/emoji_store.jsx
index 432c176d2..ff9ec64f8 100644
--- a/webapp/stores/emoji_store.jsx
+++ b/webapp/stores/emoji_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Client from '../client/web_client.jsx';
diff --git a/webapp/stores/error_store.jsx b/webapp/stores/error_store.jsx
index 3b0bb023f..b72c45ed4 100644
--- a/webapp/stores/error_store.jsx
+++ b/webapp/stores/error_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
diff --git a/webapp/stores/file_store.jsx b/webapp/stores/file_store.jsx
index 18a35e1fd..34378c062 100644
--- a/webapp/stores/file_store.jsx
+++ b/webapp/stores/file_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
@@ -70,4 +70,4 @@ class FileStore extends EventEmitter {
}
}
-export default new FileStore(); \ No newline at end of file
+export default new FileStore();
diff --git a/webapp/stores/integration_store.jsx b/webapp/stores/integration_store.jsx
index 34da3751a..89d2438bb 100644
--- a/webapp/stores/integration_store.jsx
+++ b/webapp/stores/integration_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
diff --git a/webapp/stores/localization_store.jsx b/webapp/stores/localization_store.jsx
index 64380d650..2eb482699 100644
--- a/webapp/stores/localization_store.jsx
+++ b/webapp/stores/localization_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
diff --git a/webapp/stores/message_history_store.jsx b/webapp/stores/message_history_store.jsx
index 51f673d9e..6c758fb05 100644
--- a/webapp/stores/message_history_store.jsx
+++ b/webapp/stores/message_history_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Constants from 'utils/constants.jsx';
@@ -76,4 +76,4 @@ class MessageHistoryStoreClass {
var MessageHistoryStore = new MessageHistoryStoreClass();
-export default MessageHistoryStore; \ No newline at end of file
+export default MessageHistoryStore;
diff --git a/webapp/stores/modal_store.jsx b/webapp/stores/modal_store.jsx
index b1c2887df..3478d6d5e 100644
--- a/webapp/stores/modal_store.jsx
+++ b/webapp/stores/modal_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
diff --git a/webapp/stores/notification_store.jsx b/webapp/stores/notification_store.jsx
index 2797dacdd..27259bbdd 100644
--- a/webapp/stores/notification_store.jsx
+++ b/webapp/stores/notification_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
diff --git a/webapp/stores/post_store.jsx b/webapp/stores/post_store.jsx
index 6f81619c2..4a5763c0e 100644
--- a/webapp/stores/post_store.jsx
+++ b/webapp/stores/post_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
diff --git a/webapp/stores/preference_store.jsx b/webapp/stores/preference_store.jsx
index 3197ac7e9..7a286f7a2 100644
--- a/webapp/stores/preference_store.jsx
+++ b/webapp/stores/preference_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Constants from 'utils/constants.jsx';
diff --git a/webapp/stores/reaction_store.jsx b/webapp/stores/reaction_store.jsx
index 51ad5140e..ebebd4374 100644
--- a/webapp/stores/reaction_store.jsx
+++ b/webapp/stores/reaction_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
diff --git a/webapp/stores/search_store.jsx b/webapp/stores/search_store.jsx
index 49f8b3c2f..62cc5635b 100644
--- a/webapp/stores/search_store.jsx
+++ b/webapp/stores/search_store.jsx
@@ -1,10 +1,12 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
import EventEmitter from 'events';
import Constants from 'utils/constants.jsx';
+import ChannelStore from 'stores/channel_store.jsx';
+
var ActionTypes = Constants.ActionTypes;
var CHANGE_EVENT = 'change';
@@ -117,6 +119,20 @@ class SearchStoreClass extends EventEmitter {
});
}
}
+
+ togglePinPost(postId, isPinned) {
+ const results = this.getSearchResults();
+ if (results == null) {
+ return;
+ }
+
+ if (postId in results.posts) {
+ const post = results.posts[postId];
+ results.posts[postId] = Object.assign({}, post, {
+ is_pinned: isPinned
+ });
+ }
+ }
}
var SearchStore = new SearchStoreClass();
@@ -126,6 +142,13 @@ SearchStore.dispatchToken = AppDispatcher.register((payload) => {
switch (action.type) {
case ActionTypes.RECEIVED_SEARCH:
+ if (SearchStore.getIsPinnedPosts() === action.is_pinned_posts &&
+ action.is_pinned_posts === true &&
+ SearchStore.getSearchResults().posts &&
+ ChannelStore.getCurrentId() !== Object.values(SearchStore.getSearchResults().posts)[0].channel_id) {
+ // ignore pin posts update after switch to a new channel
+ return;
+ }
SearchStore.storeSearchResults(action.results, action.is_mention_search, action.is_flagged_posts, action.is_pinned_posts);
SearchStore.emitSearchChange();
break;
@@ -140,6 +163,14 @@ SearchStore.dispatchToken = AppDispatcher.register((payload) => {
SearchStore.deletePost(action.post);
SearchStore.emitSearchChange();
break;
+ case ActionTypes.RECEIVED_POST_PINNED:
+ SearchStore.togglePinPost(action.reaction, true);
+ SearchStore.emitSearchChange();
+ break;
+ case ActionTypes.RECEIVED_POST_UNPINNED:
+ SearchStore.togglePinPost(action.reaction, false);
+ SearchStore.emitSearchChange();
+ break;
default:
}
});
diff --git a/webapp/stores/suggestion_store.jsx b/webapp/stores/suggestion_store.jsx
index 5a8ea3006..a41268ccb 100644
--- a/webapp/stores/suggestion_store.jsx
+++ b/webapp/stores/suggestion_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
diff --git a/webapp/stores/team_store.jsx b/webapp/stores/team_store.jsx
index a77527d37..85480bdac 100644
--- a/webapp/stores/team_store.jsx
+++ b/webapp/stores/team_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
diff --git a/webapp/stores/user_store.jsx b/webapp/stores/user_store.jsx
index 02adeb789..fa077f16b 100644
--- a/webapp/stores/user_store.jsx
+++ b/webapp/stores/user_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
diff --git a/webapp/stores/user_typing_store.jsx b/webapp/stores/user_typing_store.jsx
index 8bbce117f..39805fdb4 100644
--- a/webapp/stores/user_typing_store.jsx
+++ b/webapp/stores/user_typing_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from '../dispatcher/app_dispatcher.jsx';
diff --git a/webapp/stores/webrtc_store.jsx b/webapp/stores/webrtc_store.jsx
index 8213b15aa..d5828eebc 100644
--- a/webapp/stores/webrtc_store.jsx
+++ b/webapp/stores/webrtc_store.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import AppDispatcher from 'dispatcher/app_dispatcher.jsx';
@@ -107,4 +107,4 @@ WebrtcStore.dispatchToken = AppDispatcher.register((payload) => {
}
});
-export default WebrtcStore; \ No newline at end of file
+export default WebrtcStore;
diff --git a/webapp/tests/client/client_admin.test.jsx b/webapp/tests/client/client_admin.test.jsx
index 36feac8cc..cfd539d22 100644
--- a/webapp/tests/client/client_admin.test.jsx
+++ b/webapp/tests/client/client_admin.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TestHelper from 'tests/helpers/client-test-helper.jsx';
diff --git a/webapp/tests/client/client_channel.test.jsx b/webapp/tests/client/client_channel.test.jsx
index 106cfe38c..8f69b8619 100644
--- a/webapp/tests/client/client_channel.test.jsx
+++ b/webapp/tests/client/client_channel.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TestHelper from 'tests/helpers/client-test-helper.jsx';
diff --git a/webapp/tests/client/client_command.test.jsx b/webapp/tests/client/client_command.test.jsx
index 0b5f4bbb2..160f61ba8 100644
--- a/webapp/tests/client/client_command.test.jsx
+++ b/webapp/tests/client/client_command.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TestHelper from 'tests/helpers/client-test-helper.jsx';
diff --git a/webapp/tests/client/client_emoji.test.jsx b/webapp/tests/client/client_emoji.test.jsx
index da7fab711..8946a5ccc 100644
--- a/webapp/tests/client/client_emoji.test.jsx
+++ b/webapp/tests/client/client_emoji.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TestHelper from 'tests/helpers/client-test-helper.jsx';
diff --git a/webapp/tests/client/client_file.test.jsx b/webapp/tests/client/client_file.test.jsx
index aa0704b5a..a1f12a899 100644
--- a/webapp/tests/client/client_file.test.jsx
+++ b/webapp/tests/client/client_file.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TestHelper from 'tests/helpers/client-test-helper.jsx';
diff --git a/webapp/tests/client/client_general.test.jsx b/webapp/tests/client/client_general.test.jsx
index ddfb9d4ca..c18b89ffb 100644
--- a/webapp/tests/client/client_general.test.jsx
+++ b/webapp/tests/client/client_general.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TestHelper from 'tests/helpers/client-test-helper.jsx';
diff --git a/webapp/tests/client/client_hooks.test.jsx b/webapp/tests/client/client_hooks.test.jsx
index 79aa0b53d..81f1aa7a0 100644
--- a/webapp/tests/client/client_hooks.test.jsx
+++ b/webapp/tests/client/client_hooks.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TestHelper from 'tests/helpers/client-test-helper.jsx';
diff --git a/webapp/tests/client/client_oauth.test.jsx b/webapp/tests/client/client_oauth.test.jsx
index 555b38438..44ce95a19 100644
--- a/webapp/tests/client/client_oauth.test.jsx
+++ b/webapp/tests/client/client_oauth.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TestHelper from 'tests/helpers/client-test-helper.jsx';
@@ -12,7 +12,7 @@ describe('Client.OAuth', function() {
app.name = 'test';
app.homepage = 'homepage';
app.description = 'desc';
- app.callback_urls = '';
+ app.callback_urls = [''];
TestHelper.basicClient().registerOAuthApp(
app,
@@ -33,7 +33,7 @@ describe('Client.OAuth', function() {
TestHelper.basicClient().allowOAuth2(
'GET',
- '123456',
+ '12345678901234567890123456',
'http://nowhere.com',
'state',
'scope',
diff --git a/webapp/tests/client/client_post.test.jsx b/webapp/tests/client/client_post.test.jsx
index bad72c8b0..ee63c9aaa 100644
--- a/webapp/tests/client/client_post.test.jsx
+++ b/webapp/tests/client/client_post.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TestHelper from 'tests/helpers/client-test-helper.jsx';
diff --git a/webapp/tests/client/client_preferences.test.jsx b/webapp/tests/client/client_preferences.test.jsx
index 9a8f75b95..49241c72c 100644
--- a/webapp/tests/client/client_preferences.test.jsx
+++ b/webapp/tests/client/client_preferences.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TestHelper from 'tests/helpers/client-test-helper.jsx';
diff --git a/webapp/tests/client/client_reaction.test.jsx b/webapp/tests/client/client_reaction.test.jsx
index a7b1f3389..d1571d3ae 100644
--- a/webapp/tests/client/client_reaction.test.jsx
+++ b/webapp/tests/client/client_reaction.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TestHelper from 'tests/helpers/client-test-helper.jsx';
diff --git a/webapp/tests/client/client_team.test.jsx b/webapp/tests/client/client_team.test.jsx
index 76bdd2776..66927d44d 100644
--- a/webapp/tests/client/client_team.test.jsx
+++ b/webapp/tests/client/client_team.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TestHelper from 'tests/helpers/client-test-helper.jsx';
diff --git a/webapp/tests/client/client_user.test.jsx b/webapp/tests/client/client_user.test.jsx
index 22bdd0e0f..d10ad6ef0 100644
--- a/webapp/tests/client/client_user.test.jsx
+++ b/webapp/tests/client/client_user.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TestHelper from 'tests/helpers/client-test-helper.jsx';
diff --git a/webapp/tests/client/client_websocket.test.jsx b/webapp/tests/client/client_websocket.test.jsx
index 9a754c345..c5b60011e 100644
--- a/webapp/tests/client/client_websocket.test.jsx
+++ b/webapp/tests/client/client_websocket.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import TestHelper from 'tests/helpers/client-test-helper.jsx';
diff --git a/webapp/tests/components/__snapshots__/about_build_modal.test.jsx.snap b/webapp/tests/components/__snapshots__/about_build_modal.test.jsx.snap
index 27eefa273..f5c6647c9 100644
--- a/webapp/tests/components/__snapshots__/about_build_modal.test.jsx.snap
+++ b/webapp/tests/components/__snapshots__/about_build_modal.test.jsx.snap
@@ -127,9 +127,13 @@ exports[`components/AboutBuildModal should match snapshot for enterprise edition
className="form-group about-modal__copyright"
>
<FormattedMessage
- defaultMessage="Copyright 2016 Mattermost, Inc. All rights reserved"
+ defaultMessage="Copyright 2015 - {currentYear} Mattermost, Inc. All rights reserved"
id="about.copyright"
- values={Object {}}
+ values={
+ Object {
+ "currentYear": 2017,
+ }
+ }
/>
</div>
</div>
@@ -294,9 +298,13 @@ exports[`components/AboutBuildModal should match snapshot for team edition 1`] =
className="form-group about-modal__copyright"
>
<FormattedMessage
- defaultMessage="Copyright 2016 Mattermost, Inc. All rights reserved"
+ defaultMessage="Copyright 2015 - {currentYear} Mattermost, Inc. All rights reserved"
id="about.copyright"
- values={Object {}}
+ values={
+ Object {
+ "currentYear": 2017,
+ }
+ }
/>
</div>
</div>
diff --git a/webapp/tests/components/about_build_modal.test.jsx b/webapp/tests/components/about_build_modal.test.jsx
index 981bbac67..c780c1ff9 100644
--- a/webapp/tests/components/about_build_modal.test.jsx
+++ b/webapp/tests/components/about_build_modal.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/tests/components/backstage/components/backstage_header.test.jsx b/webapp/tests/components/backstage/components/backstage_header.test.jsx
index ef70ad242..f6da444d9 100644
--- a/webapp/tests/components/backstage/components/backstage_header.test.jsx
+++ b/webapp/tests/components/backstage/components/backstage_header.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/tests/components/spinner_button.test.jsx b/webapp/tests/components/spinner_button.test.jsx
index 39e93071d..40a323f44 100644
--- a/webapp/tests/components/spinner_button.test.jsx
+++ b/webapp/tests/components/spinner_button.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
diff --git a/webapp/tests/components/suggestion/suggestion_box.test.jsx b/webapp/tests/components/suggestion/suggestion_box.test.jsx
index fe7f0e132..85ca634ad 100644
--- a/webapp/tests/components/suggestion/suggestion_box.test.jsx
+++ b/webapp/tests/components/suggestion/suggestion_box.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import SuggestionBox from 'components/suggestion/suggestion_box.jsx';
diff --git a/webapp/tests/helpers/client-test-helper.jsx b/webapp/tests/helpers/client-test-helper.jsx
index 24aa5e281..26e8d6ba5 100644
--- a/webapp/tests/helpers/client-test-helper.jsx
+++ b/webapp/tests/helpers/client-test-helper.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Client from 'client/client.jsx';
diff --git a/webapp/tests/helpers/intl-test-helper.jsx b/webapp/tests/helpers/intl-test-helper.jsx
index 49094f8d4..db164c45c 100644
--- a/webapp/tests/helpers/intl-test-helper.jsx
+++ b/webapp/tests/helpers/intl-test-helper.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {mount, shallow} from 'enzyme';
diff --git a/webapp/tests/utils/emoticons.test.jsx b/webapp/tests/utils/emoticons.test.jsx
index 65848d2cc..28829428b 100644
--- a/webapp/tests/utils/emoticons.test.jsx
+++ b/webapp/tests/utils/emoticons.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import EmojiStore from 'stores/emoji_store.jsx';
diff --git a/webapp/tests/utils/formatting_at_mentions.test.jsx b/webapp/tests/utils/formatting_at_mentions.test.jsx
index 1216134f2..d64b42c3f 100644
--- a/webapp/tests/utils/formatting_at_mentions.test.jsx
+++ b/webapp/tests/utils/formatting_at_mentions.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import assert from 'assert';
diff --git a/webapp/tests/utils/formatting_hashtags.test.jsx b/webapp/tests/utils/formatting_hashtags.test.jsx
index e1b382601..1740a8ce7 100644
--- a/webapp/tests/utils/formatting_hashtags.test.jsx
+++ b/webapp/tests/utils/formatting_hashtags.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import assert from 'assert';
diff --git a/webapp/tests/utils/formatting_imgs.test.jsx b/webapp/tests/utils/formatting_imgs.test.jsx
index 023359533..645a648d1 100644
--- a/webapp/tests/utils/formatting_imgs.test.jsx
+++ b/webapp/tests/utils/formatting_imgs.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import assert from 'assert';
diff --git a/webapp/tests/utils/formatting_links.test.jsx b/webapp/tests/utils/formatting_links.test.jsx
index 1a95cc3de..efa66ae6b 100644
--- a/webapp/tests/utils/formatting_links.test.jsx
+++ b/webapp/tests/utils/formatting_links.test.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import assert from 'assert';
diff --git a/webapp/utils/async_client.jsx b/webapp/utils/async_client.jsx
index 1879fed4a..abc1017fa 100644
--- a/webapp/utils/async_client.jsx
+++ b/webapp/utils/async_client.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import BrowserStore from 'stores/browser_store.jsx';
@@ -1606,7 +1606,8 @@ export function pinPost(channelId, reaction) {
// the "post_edited" websocket event take cares of updating the posts
// the action below is mostly dispatched for the RHS to update
AppDispatcher.handleServerAction({
- type: ActionTypes.RECEIVED_POST_PINNED
+ type: ActionTypes.RECEIVED_POST_PINNED,
+ reaction
});
},
(err) => {
@@ -1623,7 +1624,8 @@ export function unpinPost(channelId, reaction) {
// the "post_edited" websocket event take cares of updating the posts
// the action below is mostly dispatched for the RHS to update
AppDispatcher.handleServerAction({
- type: ActionTypes.RECEIVED_POST_UNPINNED
+ type: ActionTypes.RECEIVED_POST_UNPINNED,
+ reaction
});
},
(err) => {
diff --git a/webapp/utils/channel_intro_messages.jsx b/webapp/utils/channel_intro_messages.jsx
index 4871a8d69..b75474eb0 100644
--- a/webapp/utils/channel_intro_messages.jsx
+++ b/webapp/utils/channel_intro_messages.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as Utils from './utils.jsx';
diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx
index 3678b0b07..d1bc73228 100644
--- a/webapp/utils/constants.jsx
+++ b/webapp/utils/constants.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import keyMirror from 'key-mirror/keyMirror.js';
@@ -335,6 +335,7 @@ export const Constants = {
CODE_TYPES: ['as', 'applescript', 'osascript', 'scpt', 'bash', 'sh', 'zsh', 'clj', 'boot', 'cl2', 'cljc', 'cljs', 'cljs.hl', 'cljscm', 'cljx', 'hic', 'coffee', '_coffee', 'cake', 'cjsx', 'cson', 'iced', 'cpp', 'c', 'cc', 'h', 'c++', 'h++', 'hpp', 'cs', 'csharp', 'css', 'd', 'di', 'dart', 'delphi', 'dpr', 'dfm', 'pas', 'pascal', 'freepascal', 'lazarus', 'lpr', 'lfm', 'diff', 'django', 'jinja', 'dockerfile', 'docker', 'erl', 'f90', 'f95', 'fsharp', 'fs', 'gcode', 'nc', 'go', 'groovy', 'handlebars', 'hbs', 'html.hbs', 'html.handlebars', 'hs', 'hx', 'java', 'jsp', 'js', 'jsx', 'json', 'jl', 'kt', 'ktm', 'kts', 'less', 'lisp', 'lua', 'mk', 'mak', 'md', 'mkdown', 'mkd', 'matlab', 'm', 'mm', 'objc', 'obj-c', 'ml', 'perl', 'pl', 'php', 'php3', 'php4', 'php5', 'php6', 'ps', 'ps1', 'pp', 'py', 'gyp', 'r', 'ruby', 'rb', 'gemspec', 'podspec', 'thor', 'irb', 'rs', 'scala', 'scm', 'sld', 'scss', 'st', 'sql', 'swift', 'tex', 'txt', 'vbnet', 'vb', 'bas', 'vbs', 'v', 'veo', 'xml', 'html', 'xhtml', 'rss', 'atom', 'xsl', 'plist', 'yaml'],
PDF_TYPES: ['pdf'],
PATCH_TYPES: ['patch'],
+ SVG_TYPES: ['svg'],
ICON_FROM_TYPE: {
audio: audioIcon,
video: videoIcon,
diff --git a/webapp/utils/delayed_action.jsx b/webapp/utils/delayed_action.jsx
index c3b164733..3d64df51d 100644
--- a/webapp/utils/delayed_action.jsx
+++ b/webapp/utils/delayed_action.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
export default class DelayedAction {
diff --git a/webapp/utils/emoji.jsx b/webapp/utils/emoji.jsx
index d9e9ee897..97d97ce56 100644
--- a/webapp/utils/emoji.jsx
+++ b/webapp/utils/emoji.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
// This file is automatically generated. Make changes to it at your own risk.
diff --git a/webapp/utils/emoticons.jsx b/webapp/utils/emoticons.jsx
index 502b3dbba..b13b50a77 100644
--- a/webapp/utils/emoticons.jsx
+++ b/webapp/utils/emoticons.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import EmojiStore from 'stores/emoji_store.jsx';
diff --git a/webapp/utils/license_utils.jsx b/webapp/utils/license_utils.jsx
index 038e3ca29..a44cfb9d4 100644
--- a/webapp/utils/license_utils.jsx
+++ b/webapp/utils/license_utils.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import LocalizationStore from 'stores/localization_store.jsx';
diff --git a/webapp/utils/markdown.jsx b/webapp/utils/markdown.jsx
index 29547b7e1..beba474fc 100644
--- a/webapp/utils/markdown.jsx
+++ b/webapp/utils/markdown.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as TextFormatting from './text_formatting.jsx';
diff --git a/webapp/utils/post_utils.jsx b/webapp/utils/post_utils.jsx
index 1f2021e4a..b07c024a5 100644
--- a/webapp/utils/post_utils.jsx
+++ b/webapp/utils/post_utils.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Client from 'client/web_client.jsx';
diff --git a/webapp/utils/syntax_highlighting.jsx b/webapp/utils/syntax_highlighting.jsx
index 73e1087cb..0fb10638f 100644
--- a/webapp/utils/syntax_highlighting.jsx
+++ b/webapp/utils/syntax_highlighting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import * as TextFormatting from './text_formatting.jsx';
diff --git a/webapp/utils/team_utils.jsx b/webapp/utils/team_utils.jsx
index 207245111..7cd788388 100644
--- a/webapp/utils/team_utils.jsx
+++ b/webapp/utils/team_utils.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import LocalizationStore from 'stores/localization_store.jsx';
diff --git a/webapp/utils/text_formatting.jsx b/webapp/utils/text_formatting.jsx
index 7f6101e36..c2c71a4e1 100644
--- a/webapp/utils/text_formatting.jsx
+++ b/webapp/utils/text_formatting.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import Autolinker from 'autolinker';
diff --git a/webapp/utils/url.jsx b/webapp/utils/url.jsx
index 6307814f2..14ea055d1 100644
--- a/webapp/utils/url.jsx
+++ b/webapp/utils/url.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
export function cleanUpUrlable(input) {
diff --git a/webapp/utils/user_agent.jsx b/webapp/utils/user_agent.jsx
index 18b20dc76..1074b02e2 100644
--- a/webapp/utils/user_agent.jsx
+++ b/webapp/utils/user_agent.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
/*
diff --git a/webapp/utils/utils.jsx b/webapp/utils/utils.jsx
index 55ea72e8d..9a4f5c21f 100644
--- a/webapp/utils/utils.jsx
+++ b/webapp/utils/utils.jsx
@@ -1,4 +1,4 @@
-// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import $ from 'jquery';
@@ -426,6 +426,10 @@ export function getFileType(extin) {
return 'patch';
}
+ if (Constants.SVG_TYPES.indexOf(ext) > -1) {
+ return 'svg';
+ }
+
return 'other';
}
@@ -449,7 +453,7 @@ export function getIconClassName(fileTypeIn) {
return Constants.ICON_NAME_FROM_TYPE[fileType];
}
- return 'glyphicon-file';
+ return 'generic';
}
export function splitFileLocation(fileLocation) {
@@ -1277,7 +1281,7 @@ export function isValidPassword(password) {
}
minimumLength = global.window.mm_config.PasswordMinimumLength;
- } else if (password.length < Constants.MIN_PASSWORD_LENGTH) {
+ } else if (password.length < Constants.MIN_PASSWORD_LENGTH || password.length > Constants.MAX_PASSWORD_LENGTH) {
error = true;
}
@@ -1285,9 +1289,10 @@ export function isValidPassword(password) {
errorMsg = (
<FormattedMessage
id={errorId}
- default='Your password must be at least {min} characters.'
+ default='Your password must contain between {min} and {max} characters.'
values={{
- min: minimumLength
+ min: minimumLength,
+ max: Constants.MAX_PASSWORD_LENGTH
}}
/>
);
diff --git a/wsapi/api.go b/wsapi/api.go
index 2d4c99674..b7a06e42e 100644
--- a/wsapi/api.go
+++ b/wsapi/api.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package wsapi
diff --git a/wsapi/status.go b/wsapi/status.go
index a9ff8831d..a69603399 100644
--- a/wsapi/status.go
+++ b/wsapi/status.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package wsapi
diff --git a/wsapi/system.go b/wsapi/system.go
index 644d0196f..878bf50a7 100644
--- a/wsapi/system.go
+++ b/wsapi/system.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package wsapi
diff --git a/wsapi/user.go b/wsapi/user.go
index a89bf1118..7c4bdfa59 100644
--- a/wsapi/user.go
+++ b/wsapi/user.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package wsapi
diff --git a/wsapi/webrtc.go b/wsapi/webrtc.go
index fd8eede30..feb45b126 100644
--- a/wsapi/webrtc.go
+++ b/wsapi/webrtc.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package wsapi
diff --git a/wsapi/websocket_handler.go b/wsapi/websocket_handler.go
index 8d78ece04..bbad142b3 100644
--- a/wsapi/websocket_handler.go
+++ b/wsapi/websocket_handler.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package wsapi