mirror of https://github.com/statping/statping
Merge pull request #564 from statping/auth-fixes-1
Authentication Fixes, Build updatespull/576/head
commit
8e76b87348
6
Makefile
6
Makefile
|
@ -160,7 +160,7 @@ build-linux:
|
|||
do \
|
||||
echo "Building v$$VERSION for $$os-$$arch"; \
|
||||
mkdir -p releases/statping-$$os-$$arch/; \
|
||||
GO111MODULE="on" GOOS=$$os GOARCH=$$arch go build -a -ldflags "-X main.VERSION=${VERSION} -X main.COMMIT=$(TRAVIS_COMMIT)" -o releases/statping-$$os-$$arch/statping ${PWD}/cmd || true; \
|
||||
CGO_ENABLED=1 GO111MODULE="on" GOOS=$$os GOARCH=$$arch go build -a -ldflags "-X main.VERSION=${VERSION}" -o releases/statping-$$os-$$arch/statping ${PWD}/cmd || true; \
|
||||
chmod +x releases/statping-$$os-$$arch/statping || true; \
|
||||
tar -czf releases/statping-$$os-$$arch.tar.gz -C releases/statping-$$os-$$arch statping || true; \
|
||||
done \
|
||||
|
@ -174,7 +174,7 @@ build-mac:
|
|||
do \
|
||||
echo "Building v$$VERSION for darwin-$$arch"; \
|
||||
mkdir -p releases/statping-darwin-$$arch/; \
|
||||
GO111MODULE="on" GOOS=darwin GOARCH=$$arch go build -a -ldflags "-X main.VERSION=${VERSION} -X main.COMMIT=$(TRAVIS_COMMIT)" -o releases/statping-darwin-$$arch/statping ${PWD}/cmd || true; \
|
||||
CGO_ENABLED=1 GO111MODULE="on" GOOS=darwin GOARCH=$$arch go build -a -ldflags "-X main.VERSION=${VERSION}" -o releases/statping-darwin-$$arch/statping ${PWD}/cmd || true; \
|
||||
chmod +x releases/statping-darwin-$$arch/statping || true; \
|
||||
tar -czf releases/statping-darwin-$$arch.tar.gz -C releases/statping-darwin-$$arch statping || true; \
|
||||
done
|
||||
|
@ -187,7 +187,7 @@ build-win:
|
|||
do \
|
||||
echo "Building v$$VERSION for windows-$$arch"; \
|
||||
mkdir -p releases/statping-windows-$$arch/; \
|
||||
GO111MODULE="on" GOOS=windows GOARCH=$$arch go build -a -ldflags "-X main.VERSION=${VERSION} -X main.COMMIT=$(TRAVIS_COMMIT)" -o releases/statping-windows-$$arch/statping.exe ${PWD}/cmd || true; \
|
||||
CGO_ENABLED=1 GO111MODULE="on" GOOS=windows GOARCH=$$arch go build -a -ldflags "-X main.VERSION=${VERSION}" -o releases/statping-windows-$$arch/statping.exe ${PWD}/cmd || true; \
|
||||
chmod +x releases/statping-windows-$$arch/statping.exe || true; \
|
||||
zip -j releases/statping-windows-$$arch.zip releases/statping-windows-$$arch/statping.exe || true; \
|
||||
done
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
"vue-apexcharts": "^1.5.2",
|
||||
"vue-clipboard2": "^0.3.1",
|
||||
"vue-codemirror": "^4.0.6",
|
||||
"vue-cookies": "^1.7.0",
|
||||
"vue-flatpickr-component": "^8.1.5",
|
||||
"vue-github-button": "^1.1.2",
|
||||
"vue-moment": "^4.1.0",
|
||||
|
|
|
@ -4,7 +4,7 @@ import * as Sentry from "@sentry/browser";
|
|||
import * as Integrations from "@sentry/integrations";
|
||||
const qs = require('querystring');
|
||||
|
||||
const tokenKey = "statping_user";
|
||||
const tokenKey = "statping_auth";
|
||||
const errorReporter = "https://bed4d75404924cb3a799e370733a1b64@sentry.statping.com/3"
|
||||
|
||||
class Api {
|
||||
|
@ -29,6 +29,10 @@ class Api {
|
|||
return axios.post('api/core', obj).then(response => (response.data))
|
||||
}
|
||||
|
||||
async oauth_save(obj) {
|
||||
return axios.post('api/oauth', obj).then(response => (response.data))
|
||||
}
|
||||
|
||||
async setup_save(data) {
|
||||
return axios.post('api/setup', qs.stringify(data)).then(response => (response.data))
|
||||
}
|
||||
|
@ -228,19 +232,11 @@ class Api {
|
|||
|
||||
async login(username, password) {
|
||||
const f = {username: username, password: password}
|
||||
return axios.post('api/login', qs.stringify(f))
|
||||
.then(response => (response.data))
|
||||
return axios.post('api/login', qs.stringify(f)).then(response => (response.data))
|
||||
}
|
||||
|
||||
async logout() {
|
||||
await axios.get('api/logout').then(response => (response.data))
|
||||
return localStorage.removeItem(tokenKey)
|
||||
}
|
||||
|
||||
saveToken(username, token, admin) {
|
||||
const user = {username: username, token: token, admin: admin}
|
||||
localStorage.setItem(tokenKey, JSON.stringify(user));
|
||||
return user
|
||||
return axios.get('api/logout').then(response => (response.data))
|
||||
}
|
||||
|
||||
async scss_base() {
|
||||
|
@ -255,17 +251,17 @@ class Api {
|
|||
}
|
||||
|
||||
token() {
|
||||
const tk = localStorage.getItem(tokenKey)
|
||||
const tk = $cookies.get(tokenKey)
|
||||
if (!tk) {
|
||||
return {};
|
||||
return {admin: false};
|
||||
}
|
||||
return JSON.parse(tk);
|
||||
return tk;
|
||||
}
|
||||
|
||||
authToken() {
|
||||
let user = JSON.parse(localStorage.getItem(tokenKey));
|
||||
if (user && user.token) {
|
||||
return {'Authorization': 'Bearer ' + user.token};
|
||||
const tk = $cookies.get(tokenKey)
|
||||
if (tk.token) {
|
||||
return {'Authorization': 'Bearer ' + tk.token};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -32,22 +32,19 @@
|
|||
this.$router.push('/setup')
|
||||
}
|
||||
if (this.$route.path !== '/setup') {
|
||||
if (this.core.logged_in) {
|
||||
if (this.$store.state.admin) {
|
||||
await this.$store.dispatch('loadAdmin')
|
||||
} else {
|
||||
await this.$store.dispatch('loadRequired')
|
||||
}
|
||||
this.loaded = true
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
async mounted() {
|
||||
if (this.$route.path !== '/setup') {
|
||||
const tk = localStorage.getItem("statping_user")
|
||||
if (this.core.logged_in) {
|
||||
if (this.$store.state.admin) {
|
||||
this.logged_in = true
|
||||
await this.$store.dispatch('loadAdmin')
|
||||
// await this.$store.dispatch('loadAdmin')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
</li>
|
||||
</ul>
|
||||
<span class="navbar-text">
|
||||
<a href="#" class="nav-link" v-on:click="logout">Logout</a>
|
||||
<a href="#" class="nav-link" @click.prevent="logout">Logout</a>
|
||||
</span>
|
||||
</div>
|
||||
</nav>
|
||||
|
@ -37,6 +37,7 @@
|
|||
|
||||
<script>
|
||||
import Api from "../../API"
|
||||
import Vue from "vue";
|
||||
|
||||
export default {
|
||||
name: 'TopNav',
|
||||
|
@ -51,6 +52,7 @@
|
|||
this.$store.commit('setHasAllData', false)
|
||||
this.$store.commit('setToken', null)
|
||||
this.$store.commit('setAdmin', false)
|
||||
this.$cookies.remove("statping_auth")
|
||||
await this.$router.push('/logout')
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<a href="https://github.com/statping/statping" target="_blank">
|
||||
Statping {{core.version}} made with <font-awesome-icon icon="heart"/>
|
||||
</a> |
|
||||
<router-link :to="core.logged_in ? '/dashboard' : '/login'">Dashboard</router-link>
|
||||
<router-link :to="$store.state.admin ? '/dashboard' : '/login'">Dashboard</router-link>
|
||||
</div>
|
||||
<div v-else class="footer text-center mb-4 p-2" v-html="core.footer"></div>
|
||||
</footer>
|
||||
|
|
|
@ -25,16 +25,16 @@
|
|||
</div>
|
||||
</form>
|
||||
|
||||
<a v-if="oauth.gh_client_id" :href="GHlogin()" class="btn btn-block">
|
||||
Github Login
|
||||
<a v-if="oauth.gh_client_id" @click.prevent="GHlogin" href="#" class="btn btn-block btn-outline-dark">
|
||||
<font-awesome-icon :icon="['fab', 'github']" /> Login with Github
|
||||
</a>
|
||||
|
||||
<a v-if="oauth.slack_client_id" :href="Slacklogin()" class="btn btn-block">
|
||||
Slack Login
|
||||
<a v-if="oauth.slack_client_id" @click.prevent="Slacklogin" href="#" class="btn btn-block btn-outline-dark">
|
||||
<font-awesome-icon :icon="['fab', 'slack']" /> Login with Slack
|
||||
</a>
|
||||
|
||||
<a v-if="oauth.google_client_id" :href="Googlelogin()" class="btn btn-block">
|
||||
Google Login
|
||||
<a v-if="oauth.google_client_id" @click.prevent="Googlelogin" href="#" class="btn btn-block btn-outline-dark">
|
||||
<font-awesome-icon :icon="['fab', 'google']" /> Login with Google
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
@ -80,7 +80,8 @@
|
|||
if (auth.error) {
|
||||
this.error = true
|
||||
} else if (auth.token) {
|
||||
this.auth = Api.saveToken(this.username, auth.token, auth.admin)
|
||||
const u = {username: this.username, admin: auth.admin, token: auth.token}
|
||||
this.$cookies.set("statping_auth", JSON.stringify(u))
|
||||
this.$store.dispatch('loadAdmin')
|
||||
this.$store.commit('setAdmin', auth.admin)
|
||||
this.$router.push('/dashboard')
|
||||
|
@ -88,13 +89,13 @@
|
|||
this.loading = false
|
||||
},
|
||||
GHlogin() {
|
||||
return `https://github.com/login/oauth/authorize?client_id=${this.oauth.gh_client_id}&redirect_uri=${this.core.domain}/api/oauth/github&scope=user,repo`
|
||||
window.location = `https://github.com/login/oauth/authorize?client_id=${this.oauth.gh_client_id}&redirect_uri=${this.core.domain}/oauth/github&scope=user,repo`
|
||||
},
|
||||
Slacklogin() {
|
||||
return `https://slack.com/oauth/authorize?client_id=${this.oauth.slack_client_id}&redirect_uri=${this.core.domain}/api/oauth/slack&scope=users.profile:read,users:read.email`
|
||||
window.location = `https://slack.com/oauth/authorize?client_id=${this.oauth.slack_client_id}&redirect_uri=${this.core.domain}/oauth/slack&scope=identity.basic`
|
||||
},
|
||||
Googlelogin() {
|
||||
return `https://accounts.google.com/signin/oauth?client_id=${this.oauth.google_client_id}&redirect_uri=${this.core.domain}/api/oauth/google&response_type=code&scope=https://www.googleapis.com/auth/userinfo.profile+https://www.googleapis.com/auth/userinfo.email`
|
||||
window.location = `https://accounts.google.com/signin/oauth?client_id=${this.oauth.google_client_id}&redirect_uri=${this.core.domain}/oauth/google&response_type=code&scope=https://www.googleapis.com/auth/userinfo.profile+https://www.googleapis.com/auth/userinfo.email`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,7 +162,7 @@
|
|||
core() {
|
||||
return this.$store.getters.core
|
||||
},
|
||||
oauth() {
|
||||
auth() {
|
||||
return this.$store.getters.oauth
|
||||
}
|
||||
},
|
||||
|
@ -171,10 +171,22 @@
|
|||
google_enabled: false,
|
||||
slack_enabled: false,
|
||||
github_enabled: false,
|
||||
local_enabled: false
|
||||
local_enabled: false,
|
||||
oauth: {
|
||||
gh_client_id: "",
|
||||
gh_client_secret: "",
|
||||
google_client_id: "",
|
||||
google_client_secret: "",
|
||||
oauth_domains: "",
|
||||
oauth_providers: "",
|
||||
slack_client_id: "",
|
||||
slack_client_secret: "",
|
||||
slack_team: ""
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.oauth = this.auth
|
||||
this.local_enabled = this.has('local')
|
||||
this.github_enabled = this.has('github')
|
||||
this.google_enabled = this.has('google')
|
||||
|
@ -207,10 +219,9 @@
|
|||
let c = this.core
|
||||
c.oauth = this.oauth
|
||||
c.oauth.oauth_providers = this.providers()
|
||||
await Api.core_save(c)
|
||||
const core = await Api.core()
|
||||
this.$store.commit('setCore', core)
|
||||
this.$store.commit('setOAuth', c.oauth)
|
||||
await Api.oauth_save(c)
|
||||
const oauth = await Api.oauth()
|
||||
this.$store.commit('setOAuth', oauth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,19 +3,23 @@ import VueRouter from 'vue-router'
|
|||
import VueApexCharts from 'vue-apexcharts'
|
||||
import VueObserveVisibility from 'vue-observe-visibility'
|
||||
import VueClipboard from 'vue-clipboard2'
|
||||
import VueCookies from 'vue-cookies'
|
||||
|
||||
import App from '@/App.vue'
|
||||
import store from './store'
|
||||
|
||||
import router from './routes'
|
||||
import "./mixin"
|
||||
import "./icons"
|
||||
|
||||
Vue.component('apexchart', VueApexCharts)
|
||||
|
||||
Vue.use(VueClipboard);
|
||||
Vue.use(VueRouter);
|
||||
Vue.use(VueObserveVisibility);
|
||||
Vue.use(VueCookies);
|
||||
Vue.$cookies.config('3d')
|
||||
|
||||
import router from './routes'
|
||||
import "./mixin"
|
||||
import "./icons"
|
||||
|
||||
|
||||
Vue.config.productionTip = false
|
||||
new Vue({
|
||||
|
|
|
@ -34,7 +34,18 @@ const routes = [
|
|||
meta: {
|
||||
requiresAuth: true
|
||||
},
|
||||
beforeEnter: CheckAuth,
|
||||
beforeEnter: async (to, from, next) => {
|
||||
if (to.matched.some(record => record.meta.requiresAuth)) {
|
||||
let tk = await Api.token()
|
||||
if (to.path !== '/login' && !tk.admin) {
|
||||
next('/login')
|
||||
return
|
||||
}
|
||||
next()
|
||||
} else {
|
||||
next()
|
||||
}
|
||||
},
|
||||
children: [{
|
||||
path: '',
|
||||
component: DashboardIndex,
|
||||
|
@ -135,9 +146,10 @@ const router = new VueRouter({
|
|||
routes
|
||||
})
|
||||
|
||||
function CheckAuth(to, from, next) {
|
||||
let CheckAuth = (to, from, next) => {
|
||||
if (to.matched.some(record => record.meta.requiresAuth)) {
|
||||
let item = localStorage.getItem("statping_user")
|
||||
let item = this.$cookies.get("statping_auth")
|
||||
window.console.log(item)
|
||||
if (to.path !== '/login' && !item) {
|
||||
next('/login')
|
||||
return
|
||||
|
|
|
@ -102,7 +102,6 @@ export default new Vuex.Store({
|
|||
state.hasPublicData = bool
|
||||
},
|
||||
setCore (state, core) {
|
||||
window.console.log('GETTING CORE')
|
||||
state.core = core
|
||||
},
|
||||
setToken (state, token) {
|
||||
|
@ -146,10 +145,11 @@ export default new Vuex.Store({
|
|||
},
|
||||
async loadCore(context) {
|
||||
const core = await Api.core()
|
||||
const token = await Api.token()
|
||||
context.commit("setCore", core);
|
||||
context.commit('setAdmin', core.admin)
|
||||
context.commit('setAdmin', token.admin)
|
||||
context.commit('setCore', core)
|
||||
context.commit('setUser', core.logged_in)
|
||||
context.commit('setUser', token.token!==undefined)
|
||||
},
|
||||
async loadRequired(context) {
|
||||
const groups = await Api.groups()
|
||||
|
|
|
@ -10,7 +10,7 @@ module.exports = {
|
|||
},
|
||||
'/oauth': {
|
||||
logLevel: 'debug',
|
||||
target: 'http://0.0.0.0:8585'
|
||||
target: 'http://0.0.0.0:8585/oauth/'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11838,6 +11838,11 @@ vue-codemirror@^4.0.6:
|
|||
codemirror "^5.41.0"
|
||||
diff-match-patch "^1.0.0"
|
||||
|
||||
vue-cookies@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/vue-cookies/-/vue-cookies-1.7.0.tgz#dd8f147ff1579e0cbd5f352dc5dff2696d8760b8"
|
||||
integrity sha512-vuEUm6wYMMrFAHFCrkzIUAy8+MgPAbBGmYXnk2M6X6O2KHbMT1wuDD2izacmsSUp6ZM02e23MJRtPRobl88VMg==
|
||||
|
||||
vue-eslint-parser@^4.0.2:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-4.0.3.tgz#80cf162e484387b2640371ad21ba1f86e0c10a61"
|
||||
|
|
1
go.mod
1
go.mod
|
@ -15,6 +15,7 @@ require (
|
|||
github.com/gogo/protobuf v1.3.1 // indirect
|
||||
github.com/golang/protobuf v1.3.5
|
||||
github.com/gorilla/mux v1.7.4
|
||||
github.com/gorilla/securecookie v1.1.1
|
||||
github.com/gorilla/sessions v1.2.0
|
||||
github.com/jinzhu/gorm v1.9.12
|
||||
github.com/joho/godotenv v1.3.0
|
||||
|
|
|
@ -27,13 +27,7 @@ type apiResponse struct {
|
|||
}
|
||||
|
||||
func apiIndexHandler(r *http.Request) interface{} {
|
||||
coreClone := *core.App
|
||||
_, err := getJwtToken(r)
|
||||
if err == nil {
|
||||
coreClone.LoggedIn = true
|
||||
coreClone.IsAdmin = IsAdmin(r)
|
||||
}
|
||||
return coreClone
|
||||
return core.App
|
||||
}
|
||||
|
||||
func apiRenewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -50,6 +44,18 @@ func apiRenewHandler(w http.ResponseWriter, r *http.Request) {
|
|||
returnJson(output, w, r)
|
||||
}
|
||||
|
||||
func apiUpdateOAuthHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var c core.OAuth
|
||||
err := DecodeJSON(r, &c)
|
||||
if err != nil {
|
||||
sendErrorJson(err, w, r)
|
||||
return
|
||||
}
|
||||
app := core.App
|
||||
app.OAuth = c
|
||||
sendJsonAction(app.OAuth, "update", w, r)
|
||||
}
|
||||
|
||||
func apiOAuthHandler(r *http.Request) interface{} {
|
||||
app := core.App
|
||||
return app.OAuth
|
||||
|
@ -78,7 +84,6 @@ func apiCoreHandler(w http.ResponseWriter, r *http.Request) {
|
|||
if c.Domain != app.Domain {
|
||||
app.Domain = c.Domain
|
||||
}
|
||||
app.OAuth = c.OAuth
|
||||
app.UseCdn = null.NewNullBool(c.UseCdn.Bool)
|
||||
app.AllowReports = null.NewNullBool(c.AllowReports.Bool)
|
||||
utils.SentryInit(nil, app.AllowReports.Bool)
|
||||
|
|
|
@ -15,7 +15,9 @@ import (
|
|||
|
||||
func logoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||
removeJwtToken(w)
|
||||
http.Redirect(w, r, basePath, http.StatusSeeOther)
|
||||
out := make(map[string]string)
|
||||
out["status"] = "success"
|
||||
returnJson(out, w, r)
|
||||
}
|
||||
|
||||
func logsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -163,7 +165,7 @@ func removeJwtToken(w http.ResponseWriter) {
|
|||
http.SetCookie(w, &http.Cookie{
|
||||
Name: cookieKey,
|
||||
Value: "",
|
||||
Expires: utils.Now(),
|
||||
Expires: time.Now(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -178,8 +180,10 @@ func setJwtToken(user *users.User, w http.ResponseWriter) (JwtClaim, string) {
|
|||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwtClaim)
|
||||
tokenString, err := token.SignedString([]byte(jwtKey))
|
||||
if err != nil {
|
||||
utils.Log.Errorln("error setting token: ", err)
|
||||
log.Errorln("error setting token: ", err)
|
||||
}
|
||||
user.Token = tokenString
|
||||
// set cookies
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: cookieKey,
|
||||
Value: tokenString,
|
||||
|
@ -195,9 +199,8 @@ func apiLoginHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
user, auth := users.AuthUser(username, password)
|
||||
if auth {
|
||||
utils.Log.Infoln(fmt.Sprintf("User %v logged in from IP %v", user.Username, r.RemoteAddr))
|
||||
log.Infoln(fmt.Sprintf("User %v logged in from IP %v", user.Username, r.RemoteAddr))
|
||||
claim, token := setJwtToken(user, w)
|
||||
|
||||
resp := struct {
|
||||
Token string `json:"token"`
|
||||
IsAdmin bool `json:"admin"`
|
||||
|
|
|
@ -1,41 +1,48 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/statping/statping/types/core"
|
||||
"github.com/statping/statping/types/null"
|
||||
"github.com/statping/statping/types/users"
|
||||
"github.com/statping/statping/utils"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/github"
|
||||
"golang.org/x/oauth2/google"
|
||||
"golang.org/x/oauth2/slack"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
var oauthSession = sessions.NewCookieStore([]byte("statping_oauth"))
|
||||
|
||||
type oAuth struct {
|
||||
ID string
|
||||
Email string
|
||||
Username string
|
||||
Token string
|
||||
RefreshToken string
|
||||
Valid bool
|
||||
Type string
|
||||
}
|
||||
|
||||
func oauthHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
provider := vars["provider"]
|
||||
code := r.URL.Query().Get("code")
|
||||
fmt.Println("code: ", code)
|
||||
fmt.Println("client: ", core.App.OAuth.SlackClientID)
|
||||
fmt.Println("secret: ", core.App.OAuth.SlackClientSecret)
|
||||
|
||||
var err error
|
||||
var oauth *oAuth
|
||||
switch provider {
|
||||
case "google":
|
||||
err, oauth = googleOAuth(r)
|
||||
oauth, err = googleOAuth(r)
|
||||
case "github":
|
||||
err, oauth = githubOAuth(r)
|
||||
oauth, err = githubOAuth(r)
|
||||
case "slack":
|
||||
err, oauth = slackOAuth(r)
|
||||
oauth, err = slackOAuth(r)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -51,17 +58,18 @@ func oauthLogin(oauth *oAuth, w http.ResponseWriter, r *http.Request) {
|
|||
log.Infoln(oauth)
|
||||
user := &users.User{
|
||||
Id: 0,
|
||||
Username: oauth.Email,
|
||||
Username: oauth.Username,
|
||||
Email: oauth.Email,
|
||||
Admin: null.NewNullBool(true),
|
||||
}
|
||||
log.Infoln(fmt.Sprintf("OAuth User %v logged in from IP %v", oauth.Email, r.RemoteAddr))
|
||||
log.Infoln(fmt.Sprintf("OAuth User %s logged in from IP %s", oauth.Email, r.RemoteAddr))
|
||||
setJwtToken(user, w)
|
||||
|
||||
http.Redirect(w, r, basePath+"dashboard", http.StatusSeeOther)
|
||||
//returnJson(user, w, r)
|
||||
http.Redirect(w, r, core.App.Domain, http.StatusPermanentRedirect)
|
||||
}
|
||||
|
||||
func githubOAuth(r *http.Request) (error, *oAuth) {
|
||||
func githubOAuth(r *http.Request) (*oAuth, error) {
|
||||
c := *core.App
|
||||
code := r.URL.Query().Get("code")
|
||||
|
||||
|
@ -73,58 +81,94 @@ func githubOAuth(r *http.Request) (error, *oAuth) {
|
|||
|
||||
gg, err := config.Exchange(r.Context(), code)
|
||||
if err != nil {
|
||||
return err, nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, &oAuth{
|
||||
return &oAuth{
|
||||
Token: gg.AccessToken,
|
||||
RefreshToken: gg.RefreshToken,
|
||||
Valid: gg.Valid(),
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func googleOAuth(r *http.Request) (error, *oAuth) {
|
||||
func googleOAuth(r *http.Request) (*oAuth, error) {
|
||||
c := core.App
|
||||
code := r.URL.Query().Get("code")
|
||||
|
||||
config := &oauth2.Config{
|
||||
ClientID: c.OAuth.GithubClientID,
|
||||
ClientSecret: c.OAuth.GithubClientSecret,
|
||||
ClientID: c.OAuth.GoogleClientID,
|
||||
ClientSecret: c.OAuth.GoogleClientSecret,
|
||||
Endpoint: google.Endpoint,
|
||||
}
|
||||
|
||||
gg, err := config.Exchange(r.Context(), code)
|
||||
if err != nil {
|
||||
return err, nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, &oAuth{
|
||||
return &oAuth{
|
||||
Token: gg.AccessToken,
|
||||
RefreshToken: gg.RefreshToken,
|
||||
Valid: gg.Valid(),
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
func slackOAuth(r *http.Request) (error, *oAuth) {
|
||||
c := *core.App
|
||||
func slackOAuth(r *http.Request) (*oAuth, error) {
|
||||
c := core.App
|
||||
code := r.URL.Query().Get("code")
|
||||
|
||||
config := &oauth2.Config{
|
||||
ClientID: c.OAuth.GithubClientID,
|
||||
ClientSecret: c.OAuth.GithubClientSecret,
|
||||
ClientID: c.OAuth.SlackClientID,
|
||||
ClientSecret: c.OAuth.SlackClientSecret,
|
||||
Endpoint: slack.Endpoint,
|
||||
RedirectURL: c.Domain + basePath + "oauth/slack",
|
||||
Scopes: []string{"identity.basic"},
|
||||
}
|
||||
|
||||
gg, err := config.Exchange(r.Context(), code)
|
||||
if err != nil {
|
||||
return err, nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, &oAuth{
|
||||
oauther := &oAuth{
|
||||
Token: gg.AccessToken,
|
||||
RefreshToken: gg.RefreshToken,
|
||||
Valid: gg.Valid(),
|
||||
Type: gg.Type(),
|
||||
}
|
||||
|
||||
return oauther.slackIdentity()
|
||||
}
|
||||
|
||||
// slackIdentity will query the Slack API to fetch the users ID, username, and email address.
|
||||
func (a *oAuth) slackIdentity() (*oAuth, error) {
|
||||
url := fmt.Sprintf("https://slack.com/api/users.identity?token=%s", a.Token)
|
||||
out, resp, err := utils.HttpRequest(url, "GET", "application/x-www-form-urlencoded", nil, nil, 10*time.Second, true)
|
||||
if err != nil {
|
||||
return a, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var i *slackIdentity
|
||||
if err := json.Unmarshal(out, &i); err != nil {
|
||||
return a, err
|
||||
}
|
||||
a.Email = i.User.Email
|
||||
a.ID = i.User.ID
|
||||
a.Username = i.User.Name
|
||||
return a, nil
|
||||
}
|
||||
|
||||
type slackIdentity struct {
|
||||
Ok bool `json:"ok"`
|
||||
User struct {
|
||||
Name string `json:"name"`
|
||||
ID string `json:"id"`
|
||||
Email string `json:"email"`
|
||||
} `json:"user"`
|
||||
Team struct {
|
||||
ID string `json:"id"`
|
||||
} `json:"team"`
|
||||
}
|
||||
|
||||
func secureToken(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -24,6 +24,7 @@ func staticAssets(src string) http.Handler {
|
|||
func Router() *mux.Router {
|
||||
dir := utils.Directory
|
||||
CacheStorage = NewStorage()
|
||||
|
||||
r := mux.NewRouter().StrictSlash(true)
|
||||
|
||||
authUser := utils.Params.GetString("AUTH_USERNAME")
|
||||
|
@ -74,16 +75,19 @@ func Router() *mux.Router {
|
|||
r.Handle("/api", scoped(apiIndexHandler))
|
||||
r.Handle("/api/setup", http.HandlerFunc(processSetupHandler)).Methods("POST")
|
||||
api.Handle("/api/login", http.HandlerFunc(apiLoginHandler)).Methods("POST")
|
||||
api.Handle("/api/logout", http.HandlerFunc(logoutHandler))
|
||||
api.Handle("/api/logout", authenticated(logoutHandler, false))
|
||||
api.Handle("/api/renew", authenticated(apiRenewHandler, false))
|
||||
api.Handle("/api/cache", authenticated(apiCacheHandler, false)).Methods("GET")
|
||||
api.Handle("/api/clear_cache", authenticated(apiClearCacheHandler, false))
|
||||
api.Handle("/api/core", authenticated(apiCoreHandler, false)).Methods("POST")
|
||||
api.Handle("/api/oauth", scoped(apiOAuthHandler)).Methods("GET")
|
||||
api.Handle("/oauth/{provider}", http.HandlerFunc(oauthHandler))
|
||||
api.Handle("/api/logs", authenticated(logsHandler, false)).Methods("GET")
|
||||
api.Handle("/api/logs/last", authenticated(logsLineHandler, false)).Methods("GET")
|
||||
|
||||
// API OAUTH Routes
|
||||
api.Handle("/api/oauth", scoped(apiOAuthHandler)).Methods("GET")
|
||||
api.Handle("/api/oauth", authenticated(apiUpdateOAuthHandler, false)).Methods("POST")
|
||||
api.Handle("/oauth/{provider}", http.HandlerFunc(oauthHandler))
|
||||
|
||||
// API SCSS and ASSETS Routes
|
||||
api.Handle("/api/theme", authenticated(apiThemeViewHandler, false)).Methods("GET")
|
||||
api.Handle("/api/theme", authenticated(apiThemeSaveHandler, false)).Methods("POST")
|
||||
|
|
|
@ -148,9 +148,8 @@ func TestApiUsersRoutes(t *testing.T) {
|
|||
Name: "Statping Logout",
|
||||
URL: "/api/logout",
|
||||
Method: "GET",
|
||||
ExpectedStatus: 303,
|
||||
},
|
||||
{
|
||||
ExpectedStatus: 200,
|
||||
}, {
|
||||
Name: "Incorrect JSON POST",
|
||||
URL: "/api/users",
|
||||
Body: BadJSON,
|
||||
|
|
|
@ -31,8 +31,6 @@ type Core struct {
|
|||
Setup bool `gorm:"-" json:"setup"`
|
||||
MigrationId int64 `gorm:"column:migration_id" json:"migration_id,omitempty"`
|
||||
UseCdn null.NullBool `gorm:"column:use_cdn;default:false" json:"using_cdn,omitempty"`
|
||||
LoggedIn bool `gorm:"-" json:"logged_in"`
|
||||
IsAdmin bool `gorm:"-" json:"admin"`
|
||||
AllowReports null.NullBool `gorm:"column:allow_reports;default:false" json:"allow_reports,omitempty"`
|
||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
||||
|
|
|
@ -16,4 +16,5 @@ type User struct {
|
|||
Admin null.NullBool `gorm:"column:administrator" json:"admin,omitempty"`
|
||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
||||
Token string `gorm:"-" json:"token"`
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue