Merge pull request #606 from DoubleMalt/feature/MattermostAuth

Add Mattermost authentication strategy
This commit is contained in:
Sheogorath 2017-10-31 12:11:41 +01:00 committed by GitHub
commit 16b3e015ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 116 additions and 13 deletions

View File

@ -8,8 +8,8 @@ HackMD
[![version][github-version-badge]][github-release-page]
HackMD lets you create realtime collaborative markdown notes on all platforms.
Inspired by Hackpad, with more focus on speed and flexibility.
HackMD lets you create realtime collaborative markdown notes on all platforms.
Inspired by Hackpad, with more focus on speed and flexibility.
Still in the early stage, feel free to fork or contribute to HackMD.
Thanks for using! :smile:
@ -112,13 +112,13 @@ If you are upgrading HackMD from an older version, follow these steps:
* [migration-to-0.5.0](https://github.com/hackmdio/migration-to-0.5.0)
We don't use LZString to compress socket.io data and DB data after version 0.5.0.
We don't use LZString to compress socket.io data and DB data after version 0.5.0.
Please run the migration tool if you're upgrading from the old version.
* [migration-to-0.4.0](https://github.com/hackmdio/migration-to-0.4.0)
We've dropped MongoDB after version 0.4.0.
So here is the migration tool for you to transfer the old DB data to the new DB.
We've dropped MongoDB after version 0.4.0.
So here is the migration tool for you to transfer the old DB data to the new DB.
This tool is also used for official service.
# Configuration
@ -156,6 +156,9 @@ There are some configs you need to change in the files below
| HMD_GITLAB_BASEURL | no example | GitLab authentication endpoint, set to use other endpoint than GitLab.com (optional) |
| HMD_GITLAB_CLIENTID | no example | GitLab API client id |
| HMD_GITLAB_CLIENTSECRET | no example | GitLab API client secret |
| HMD_MATTERMOST_BASEURL | no example | Mattermost authentication endpoint |
| HMD_MATTERMOST_CLIENTID | no example | Mattermost API client id |
| HMD_MATTERMOST_CLIENTSECRET | no example | Mattermost API client secret |
| HMD_DROPBOX_CLIENTID | no example | Dropbox API client id |
| HMD_DROPBOX_CLIENTSECRET | no example | Dropbox API client secret |
| HMD_GOOGLE_CLIENTID | no example | Google API client id |
@ -231,7 +234,7 @@ There are some configs you need to change in the files below
| service | settings location | description |
| ------- | --------- | ----------- |
| facebook, twitter, github, gitlab, dropbox, google, ldap | environment variables or `config.json` | for signin |
| facebook, twitter, github, gitlab, mattermost, dropbox, google, ldap | environment variables or `config.json` | for signin |
| imgur | environment variables or `config.json` | for image upload |
| google drive(`google/apiKey`, `google/clientID`), dropbox(`dropbox/appKey`) | `config.json` | for export and import |
@ -243,6 +246,7 @@ There are some configs you need to change in the files below
| twitter | `/auth/twitter/callback` |
| github | `/auth/github/callback` |
| gitlab | `/auth/gitlab/callback` |
| mattermost | `/auth/mattermost/callback` |
| dropbox | `/auth/dropbox/callback` |
| google | `/auth/google/callback` |
@ -264,9 +268,9 @@ hackmd/
## Operational Transformation
From 0.3.2, we started supporting operational transformation.
It makes concurrent editing safe and will not break up other users' operations.
Additionally, now can show other clients' selections.
From 0.3.2, we started supporting operational transformation.
It makes concurrent editing safe and will not break up other users' operations.
Additionally, now can show other clients' selections.
See more at [http://operational-transformation.github.io/](http://operational-transformation.github.io/)

View File

@ -100,6 +100,18 @@
"description": "GitLab API client scope (optional)",
"required": false
},
"HMD_MATTERMOST_BASEURL": {
"description": "Mattermost authentication endpoint",
"required": false
},
"HMD_MATTERMOST_CLIENTID": {
"description": "Mattermost API client id",
"required": false
},
"HMD_MATTERMOST_CLIENTSECRET": {
"description": "Mattermost API client secret",
"required": false
},
"HMD_DROPBOX_CLIENTID": {
"description": "Dropbox API client id",
"required": false

View File

@ -48,6 +48,11 @@
"clientSecret": "change this",
"scope": "use 'read_user' scope for auth user only or remove this property if you need gitlab snippet import/export support (will result to be default scope 'api')"
},
"mattermost": {
"baseURL": "change this",
"clientID": "change this",
"clientSecret": "change this"
},
"dropbox": {
"clientID": "change this",
"clientSecret": "change this",

View File

@ -74,6 +74,11 @@ module.exports = {
clientSecret: undefined,
scope: undefined
},
mattermost: {
baseURL: undefined,
clientID: undefined,
clientSecret: undefined
},
dropbox: {
clientID: undefined,
clientSecret: undefined

View File

@ -38,6 +38,10 @@ if (fs.existsSync(basePath)) {
clientID: getSecret('gitlab_clientID'),
clientSecret: getSecret('gitlab_clientSecret')
},
mattermost: {
clientID: getSecret('mattermost_clientID'),
clientSecret: getSecret('mattermost_clientSecret')
},
dropbox: {
clientID: getSecret('dropbox_clientID'),
clientSecret: getSecret('dropbox_clientSecret')

View File

@ -49,6 +49,11 @@ module.exports = {
clientSecret: process.env.HMD_GITLAB_CLIENTSECRET,
scope: process.env.HMD_GITLAB_SCOPE
},
mattermost: {
baseURL: process.env.HMD_MATTERMOST_BASEURL,
clientID: process.env.HMD_MATTERMOST_CLIENTID,
clientSecret: process.env.HMD_MATTERMOST_CLIENTSECRET
},
dropbox: {
clientID: process.env.HMD_DROPBOX_CLIENTID,
clientSecret: process.env.HMD_DROPBOX_CLIENTSECRET

View File

@ -90,6 +90,7 @@ config.isTwitterEnable = config.twitter.consumerKey && config.twitter.consumerSe
config.isEmailEnable = config.email
config.isGitHubEnable = config.github.clientID && config.github.clientSecret
config.isGitLabEnable = config.gitlab.clientID && config.gitlab.clientSecret
config.isMattermostEnable = config.mattermost.clientID && config.mattermost.clientSecret
config.isLDAPEnable = config.ldap.url
config.isPDFExportEnable = config.allowpdfexport

View File

@ -111,6 +111,15 @@ module.exports = function (sequelize, DataTypes) {
photo = letterAvatars(profile.username)
}
break
case 'mattermost':
photo = profile.avatarUrl
if (photo) {
if (bigger) photo = photo.replace(/(\?s=)\d*$/i, '$1400')
else photo = photo.replace(/(\?s=)\d*$/i, '$196')
} else {
photo = letterAvatars(profile.username)
}
break
case 'dropbox':
// no image api provided, use gravatar
photo = 'https://www.gravatar.com/avatar/' + md5(profile.emails[0].value)

View File

@ -64,6 +64,7 @@ function showIndex (req, res, next) {
twitter: config.isTwitterEnable,
github: config.isGitHubEnable,
gitlab: config.isGitLabEnable,
mattermost: config.isMattermostEnable,
dropbox: config.isDropboxEnable,
google: config.isGoogleEnable,
ldap: config.isLDAPEnable,

View File

@ -33,6 +33,7 @@ if (config.isFacebookEnable) authRouter.use(require('./facebook'))
if (config.isTwitterEnable) authRouter.use(require('./twitter'))
if (config.isGitHubEnable) authRouter.use(require('./github'))
if (config.isGitLabEnable) authRouter.use(require('./gitlab'))
if (config.isMattermostEnable) authRouter.use(require('./mattermost'))
if (config.isDropboxEnable) authRouter.use(require('./dropbox'))
if (config.isGoogleEnable) authRouter.use(require('./google'))
if (config.isLDAPEnable) authRouter.use(require('./ldap'))

View File

@ -0,0 +1,49 @@
'use strict'
const Router = require('express').Router
const passport = require('passport')
const Mattermost = require('mattermost')
const OAuthStrategy = require('passport-oauth2').Strategy
const config = require('../../../config')
const {setReturnToFromReferer, passportGeneralCallback} = require('../utils')
const mattermost = new Mattermost.Client()
let mattermostAuth = module.exports = Router()
let mattermostStrategy = new OAuthStrategy({
authorizationURL: config.mattermost.baseURL + '/oauth/authorize',
tokenURL: config.mattermost.baseURL + '/oauth/access_token',
clientID: config.mattermost.clientID,
clientSecret: config.mattermost.clientSecret,
callbackURL: config.serverurl + '/auth/mattermost/callback'
}, passportGeneralCallback)
mattermostStrategy.userProfile = (accessToken, done) => {
mattermost.setUrl(config.mattermost.baseURL)
mattermost.token = accessToken
mattermost.useHeaderToken()
mattermost.getMe(
(data) => {
done(null, data)
},
(err) => {
done(err)
}
)
}
passport.use(mattermostStrategy)
mattermostAuth.get('/auth/mattermost', function (req, res, next) {
setReturnToFromReferer(req)
passport.authenticate('oauth2')(req, res, next)
})
// mattermost auth callback
mattermostAuth.get('/auth/mattermost/callback',
passport.authenticate('oauth2', {
successReturnToOrRedirect: config.serverurl + '/',
failureRedirect: config.serverurl + '/'
})
)

View File

@ -76,6 +76,7 @@
"markdown-pdf": "^7.0.0",
"mathjax": "~2.7.0",
"mermaid": "~7.1.0",
"mattermost": "^3.4.0",
"meta-marked": "^0.4.2",
"method-override": "^2.3.7",
"moment": "^2.17.1",
@ -91,6 +92,7 @@
"passport-google-oauth20": "^1.0.0",
"passport-ldapauth": "^0.6.0",
"passport-local": "^1.0.0",
"passport-oauth2": "^1.4.0",
"passport-twitter": "^1.0.4",
"passport.socketio": "^3.7.0",
"pdfobject": "^2.0.201604172",

View File

@ -15,7 +15,7 @@
<% if(allowAnonymous) { %>
<a type="button" href="<%- url %>/new" class="btn btn-sm btn-primary"><i class="fa fa-plus"></i> <%= __('New guest note') %></a>
<% } %>
<% if(facebook || twitter || github || gitlab || dropbox || google || ldap || email) { %>
<% if(facebook || twitter || github || gitlab || mattermost || dropbox || google || ldap || email) { %>
<button class="btn btn-sm btn-success ui-signin" data-toggle="modal" data-target=".signin-modal"><%= __('Sign In') %></button>
<% } %>
</div>
@ -48,7 +48,7 @@
<% if (errorMessage && errorMessage.length > 0) { %>
<div class="alert alert-danger" style="max-width: 400px; margin: 0 auto;"><%= errorMessage %></div>
<% } %>
<% if(facebook || twitter || github || gitlab || dropbox || google || ldap || email) { %>
<% if(facebook || twitter || github || gitlab || mattermost || dropbox || google || ldap || email) { %>
<span class="ui-signin">
<br>
<a type="button" class="btn btn-lg btn-success ui-signin" data-toggle="modal" data-target=".signin-modal" style="min-width: 200px;"><%= __('Sign In') %></a>

View File

@ -28,6 +28,11 @@
<i class="fa fa-gitlab"></i> <%= __('Sign in via %s', 'GitLab') %>
</a>
<% } %>
<% if(mattermost) { %>
<a href="<%- url %>/auth/mattermost" class="btn btn-lg btn-block btn-social btn-soundcloud">
<i class="fa fa-mattermost"></i> <%= __('Sign in via %s', 'Mattermost') %>
</a>
<% } %>
<% if(dropbox) { %>
<a href="<%- url %>/auth/dropbox" class="btn btn-lg btn-block btn-social btn-dropbox">
<i class="fa fa-dropbox"></i> <%= __('Sign in via %s', 'Dropbox') %>
@ -38,7 +43,7 @@
<i class="fa fa-google"></i> <%= __('Sign in via %s', 'Google') %>
</a>
<% } %>
<% if((facebook || twitter || github || gitlab || dropbox || google) && ldap) { %>
<% if((facebook || twitter || github || gitlab || mattermost || dropbox || google) && ldap) { %>
<hr>
<% }%>
<% if(ldap) { %>
@ -63,7 +68,7 @@
</div>
</form>
<% } %>
<% if((facebook || twitter || github || gitlab || dropbox || google || ldap) && email) { %>
<% if((facebook || twitter || github || gitlab || mattermost || dropbox || google || ldap) && email) { %>
<hr>
<% }%>
<% if(email) { %>