Add mattermost authentication
This commit is contained in:
parent
dad5798472
commit
5cda55086a
14 changed files with 116 additions and 13 deletions
22
README.md
22
README.md
|
@ -8,8 +8,8 @@ HackMD
|
||||||
[![version][github-version-badge]][github-release-page]
|
[![version][github-version-badge]][github-release-page]
|
||||||
|
|
||||||
|
|
||||||
HackMD lets you create realtime collaborative markdown notes on all platforms.
|
HackMD lets you create realtime collaborative markdown notes on all platforms.
|
||||||
Inspired by Hackpad, with more focus on speed and flexibility.
|
Inspired by Hackpad, with more focus on speed and flexibility.
|
||||||
Still in the early stage, feel free to fork or contribute to HackMD.
|
Still in the early stage, feel free to fork or contribute to HackMD.
|
||||||
|
|
||||||
Thanks for using! :smile:
|
Thanks for using! :smile:
|
||||||
|
@ -97,13 +97,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)
|
* [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.
|
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)
|
* [migration-to-0.4.0](https://github.com/hackmdio/migration-to-0.4.0)
|
||||||
|
|
||||||
We've dropped MongoDB after version 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.
|
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.
|
This tool is also used for official service.
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
|
@ -141,6 +141,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_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_CLIENTID | no example | GitLab API client id |
|
||||||
| HMD_GITLAB_CLIENTSECRET | no example | GitLab API client secret |
|
| 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_CLIENTID | no example | Dropbox API client id |
|
||||||
| HMD_DROPBOX_CLIENTSECRET | no example | Dropbox API client secret |
|
| HMD_DROPBOX_CLIENTSECRET | no example | Dropbox API client secret |
|
||||||
| HMD_GOOGLE_CLIENTID | no example | Google API client id |
|
| HMD_GOOGLE_CLIENTID | no example | Google API client id |
|
||||||
|
@ -216,7 +219,7 @@ There are some configs you need to change in the files below
|
||||||
|
|
||||||
| service | settings location | description |
|
| 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 |
|
| imgur | environment variables or `config.json` | for image upload |
|
||||||
| google drive(`google/apiKey`, `google/clientID`), dropbox(`dropbox/appKey`) | `config.json` | for export and import |
|
| google drive(`google/apiKey`, `google/clientID`), dropbox(`dropbox/appKey`) | `config.json` | for export and import |
|
||||||
|
|
||||||
|
@ -228,6 +231,7 @@ There are some configs you need to change in the files below
|
||||||
| twitter | `/auth/twitter/callback` |
|
| twitter | `/auth/twitter/callback` |
|
||||||
| github | `/auth/github/callback` |
|
| github | `/auth/github/callback` |
|
||||||
| gitlab | `/auth/gitlab/callback` |
|
| gitlab | `/auth/gitlab/callback` |
|
||||||
|
| mattermost | `/auth/mattermost/callback` |
|
||||||
| dropbox | `/auth/dropbox/callback` |
|
| dropbox | `/auth/dropbox/callback` |
|
||||||
| google | `/auth/google/callback` |
|
| google | `/auth/google/callback` |
|
||||||
|
|
||||||
|
@ -249,9 +253,9 @@ hackmd/
|
||||||
|
|
||||||
## Operational Transformation
|
## Operational Transformation
|
||||||
|
|
||||||
From 0.3.2, we started supporting operational transformation.
|
From 0.3.2, we started supporting operational transformation.
|
||||||
It makes concurrent editing safe and will not break up other users' operations.
|
It makes concurrent editing safe and will not break up other users' operations.
|
||||||
Additionally, now can show other clients' selections.
|
Additionally, now can show other clients' selections.
|
||||||
See more at [http://operational-transformation.github.io/](http://operational-transformation.github.io/)
|
See more at [http://operational-transformation.github.io/](http://operational-transformation.github.io/)
|
||||||
|
|
||||||
|
|
||||||
|
|
12
app.json
12
app.json
|
@ -100,6 +100,18 @@
|
||||||
"description": "GitLab API client scope (optional)",
|
"description": "GitLab API client scope (optional)",
|
||||||
"required": false
|
"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": {
|
"HMD_DROPBOX_CLIENTID": {
|
||||||
"description": "Dropbox API client id",
|
"description": "Dropbox API client id",
|
||||||
"required": false
|
"required": false
|
||||||
|
|
|
@ -48,6 +48,11 @@
|
||||||
"clientSecret": "change this",
|
"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')"
|
"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": {
|
"dropbox": {
|
||||||
"clientID": "change this",
|
"clientID": "change this",
|
||||||
"clientSecret": "change this",
|
"clientSecret": "change this",
|
||||||
|
|
|
@ -74,6 +74,11 @@ module.exports = {
|
||||||
clientSecret: undefined,
|
clientSecret: undefined,
|
||||||
scope: undefined
|
scope: undefined
|
||||||
},
|
},
|
||||||
|
mattermost: {
|
||||||
|
baseURL: undefined,
|
||||||
|
clientID: undefined,
|
||||||
|
clientSecret: undefined
|
||||||
|
},
|
||||||
dropbox: {
|
dropbox: {
|
||||||
clientID: undefined,
|
clientID: undefined,
|
||||||
clientSecret: undefined
|
clientSecret: undefined
|
||||||
|
|
|
@ -38,6 +38,10 @@ if (fs.existsSync(basePath)) {
|
||||||
clientID: getSecret('gitlab_clientID'),
|
clientID: getSecret('gitlab_clientID'),
|
||||||
clientSecret: getSecret('gitlab_clientSecret')
|
clientSecret: getSecret('gitlab_clientSecret')
|
||||||
},
|
},
|
||||||
|
mattermost: {
|
||||||
|
clientID: getSecret('mattermost_clientID'),
|
||||||
|
clientSecret: getSecret('mattermost_clientSecret')
|
||||||
|
},
|
||||||
dropbox: {
|
dropbox: {
|
||||||
clientID: getSecret('dropbox_clientID'),
|
clientID: getSecret('dropbox_clientID'),
|
||||||
clientSecret: getSecret('dropbox_clientSecret')
|
clientSecret: getSecret('dropbox_clientSecret')
|
||||||
|
|
|
@ -49,6 +49,11 @@ module.exports = {
|
||||||
clientSecret: process.env.HMD_GITLAB_CLIENTSECRET,
|
clientSecret: process.env.HMD_GITLAB_CLIENTSECRET,
|
||||||
scope: process.env.HMD_GITLAB_SCOPE
|
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: {
|
dropbox: {
|
||||||
clientID: process.env.HMD_DROPBOX_CLIENTID,
|
clientID: process.env.HMD_DROPBOX_CLIENTID,
|
||||||
clientSecret: process.env.HMD_DROPBOX_CLIENTSECRET
|
clientSecret: process.env.HMD_DROPBOX_CLIENTSECRET
|
||||||
|
|
|
@ -90,6 +90,7 @@ config.isTwitterEnable = config.twitter.consumerKey && config.twitter.consumerSe
|
||||||
config.isEmailEnable = config.email
|
config.isEmailEnable = config.email
|
||||||
config.isGitHubEnable = config.github.clientID && config.github.clientSecret
|
config.isGitHubEnable = config.github.clientID && config.github.clientSecret
|
||||||
config.isGitLabEnable = config.gitlab.clientID && config.gitlab.clientSecret
|
config.isGitLabEnable = config.gitlab.clientID && config.gitlab.clientSecret
|
||||||
|
config.isMattermostEnable = config.mattermost.clientID && config.mattermost.clientSecret
|
||||||
config.isLDAPEnable = config.ldap.url
|
config.isLDAPEnable = config.ldap.url
|
||||||
config.isPDFExportEnable = config.allowpdfexport
|
config.isPDFExportEnable = config.allowpdfexport
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,15 @@ module.exports = function (sequelize, DataTypes) {
|
||||||
photo = letterAvatars(profile.username)
|
photo = letterAvatars(profile.username)
|
||||||
}
|
}
|
||||||
break
|
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':
|
case 'dropbox':
|
||||||
// no image api provided, use gravatar
|
// no image api provided, use gravatar
|
||||||
photo = 'https://www.gravatar.com/avatar/' + md5(profile.emails[0].value)
|
photo = 'https://www.gravatar.com/avatar/' + md5(profile.emails[0].value)
|
||||||
|
|
|
@ -64,6 +64,7 @@ function showIndex (req, res, next) {
|
||||||
twitter: config.isTwitterEnable,
|
twitter: config.isTwitterEnable,
|
||||||
github: config.isGitHubEnable,
|
github: config.isGitHubEnable,
|
||||||
gitlab: config.isGitLabEnable,
|
gitlab: config.isGitLabEnable,
|
||||||
|
mattermost: config.isMattermostEnable,
|
||||||
dropbox: config.isDropboxEnable,
|
dropbox: config.isDropboxEnable,
|
||||||
google: config.isGoogleEnable,
|
google: config.isGoogleEnable,
|
||||||
ldap: config.isLDAPEnable,
|
ldap: config.isLDAPEnable,
|
||||||
|
|
|
@ -33,6 +33,7 @@ if (config.isFacebookEnable) authRouter.use(require('./facebook'))
|
||||||
if (config.isTwitterEnable) authRouter.use(require('./twitter'))
|
if (config.isTwitterEnable) authRouter.use(require('./twitter'))
|
||||||
if (config.isGitHubEnable) authRouter.use(require('./github'))
|
if (config.isGitHubEnable) authRouter.use(require('./github'))
|
||||||
if (config.isGitLabEnable) authRouter.use(require('./gitlab'))
|
if (config.isGitLabEnable) authRouter.use(require('./gitlab'))
|
||||||
|
if (config.isMattermostEnable) authRouter.use(require('./mattermost'))
|
||||||
if (config.isDropboxEnable) authRouter.use(require('./dropbox'))
|
if (config.isDropboxEnable) authRouter.use(require('./dropbox'))
|
||||||
if (config.isGoogleEnable) authRouter.use(require('./google'))
|
if (config.isGoogleEnable) authRouter.use(require('./google'))
|
||||||
if (config.isLDAPEnable) authRouter.use(require('./ldap'))
|
if (config.isLDAPEnable) authRouter.use(require('./ldap'))
|
||||||
|
|
49
lib/web/auth/mattermost/index.js
Normal file
49
lib/web/auth/mattermost/index.js
Normal 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 + '/'
|
||||||
|
})
|
||||||
|
)
|
|
@ -76,6 +76,7 @@
|
||||||
"markdown-pdf": "^7.0.0",
|
"markdown-pdf": "^7.0.0",
|
||||||
"mathjax": "~2.7.0",
|
"mathjax": "~2.7.0",
|
||||||
"mermaid": "~7.1.0",
|
"mermaid": "~7.1.0",
|
||||||
|
"mattermost": "^3.4.0",
|
||||||
"meta-marked": "^0.4.2",
|
"meta-marked": "^0.4.2",
|
||||||
"method-override": "^2.3.7",
|
"method-override": "^2.3.7",
|
||||||
"moment": "^2.17.1",
|
"moment": "^2.17.1",
|
||||||
|
@ -91,6 +92,7 @@
|
||||||
"passport-google-oauth20": "^1.0.0",
|
"passport-google-oauth20": "^1.0.0",
|
||||||
"passport-ldapauth": "^0.6.0",
|
"passport-ldapauth": "^0.6.0",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
|
"passport-oauth2": "^1.4.0",
|
||||||
"passport-twitter": "^1.0.4",
|
"passport-twitter": "^1.0.4",
|
||||||
"passport.socketio": "^3.7.0",
|
"passport.socketio": "^3.7.0",
|
||||||
"pdfobject": "^2.0.201604172",
|
"pdfobject": "^2.0.201604172",
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
<% if(allowAnonymous) { %>
|
<% if(allowAnonymous) { %>
|
||||||
<a type="button" href="<%- url %>/new" class="btn btn-sm btn-primary"><i class="fa fa-plus"></i> <%= __('New guest note') %></a>
|
<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>
|
<button class="btn btn-sm btn-success ui-signin" data-toggle="modal" data-target=".signin-modal"><%= __('Sign In') %></button>
|
||||||
<% } %>
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
<% if (errorMessage && errorMessage.length > 0) { %>
|
<% if (errorMessage && errorMessage.length > 0) { %>
|
||||||
<div class="alert alert-danger" style="max-width: 400px; margin: 0 auto;"><%= errorMessage %></div>
|
<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">
|
<span class="ui-signin">
|
||||||
<br>
|
<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>
|
<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>
|
||||||
|
|
|
@ -28,6 +28,11 @@
|
||||||
<i class="fa fa-gitlab"></i> <%= __('Sign in via %s', 'GitLab') %>
|
<i class="fa fa-gitlab"></i> <%= __('Sign in via %s', 'GitLab') %>
|
||||||
</a>
|
</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) { %>
|
<% if(dropbox) { %>
|
||||||
<a href="<%- url %>/auth/dropbox" class="btn btn-lg btn-block btn-social btn-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') %>
|
<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') %>
|
<i class="fa fa-google"></i> <%= __('Sign in via %s', 'Google') %>
|
||||||
</a>
|
</a>
|
||||||
<% } %>
|
<% } %>
|
||||||
<% if((facebook || twitter || github || gitlab || dropbox || google) && ldap) { %>
|
<% if((facebook || twitter || github || gitlab || mattermost || dropbox || google) && ldap) { %>
|
||||||
<hr>
|
<hr>
|
||||||
<% }%>
|
<% }%>
|
||||||
<% if(ldap) { %>
|
<% if(ldap) { %>
|
||||||
|
@ -63,7 +68,7 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<% } %>
|
<% } %>
|
||||||
<% if((facebook || twitter || github || gitlab || dropbox || google || ldap) && email) { %>
|
<% if((facebook || twitter || github || gitlab || mattermost || dropbox || google || ldap) && email) { %>
|
||||||
<hr>
|
<hr>
|
||||||
<% }%>
|
<% }%>
|
||||||
<% if(email) { %>
|
<% if(email) { %>
|
||||||
|
|
Loading…
Reference in a new issue