pull/508/head
hunterlong 2020-04-19 20:02:34 -07:00
parent 6fc0be9d12
commit 0a29350d5f
9 changed files with 119 additions and 77 deletions

View File

@ -12,6 +12,11 @@ class Api {
} }
async oauth() {
const oauth = axios.get('api/oauth').then(response => (response.data))
return oauth
}
async core() { async core() {
const core = axios.get('api').then(response => (response.data)) const core = axios.get('api').then(response => (response.data))
if (core.allow_reports) { if (core.allow_reports) {

View File

@ -1,5 +1,5 @@
<template> <template>
<button v-html="loading ? loadLabel : label" @click.prevent="runAction" type="submit" :disabled="loading || disabled" class="btn btn-block" :class="{class: !loading, 'btn-outline-light': loading}"> <button v-html="loading ? loadLabel : label" @click.prevent="runAction" type="submit" :disabled="loading || disabled" class="btn btn-block" :class="{'btn-outline-light': loading}">
</button> </button>
</template> </template>
@ -15,10 +15,6 @@
type: String, type: String,
required: true required: true
}, },
class: {
type: String,
default: "btn-primary"
},
disabled: { disabled: {
type: Boolean, type: Boolean,
default: false default: false

View File

@ -1,4 +1,5 @@
<template> <template>
<div>
<form @submit.prevent="login" autocomplete="on"> <form @submit.prevent="login" autocomplete="on">
<div class="form-group row"> <div class="form-group row">
<label for="username" class="col-sm-2 col-form-label">Username</label> <label for="username" class="col-sm-2 col-form-label">Username</label>
@ -22,8 +23,21 @@
</button> </button>
</div> </div>
</div> </div>
</form> </form>
<a v-if="oauth.gh_client_id" :href="GHlogin()" class="btn btn-block">
Github Login
</a>
<a v-if="oauth.slack_client_id" :href="Slacklogin()" class="btn btn-block">
Slack Login
</a>
<a v-if="oauth.google_client_id" :href="Googlelogin()" class="btn btn-block">
Google Login
</a>
</div>
</template> </template>
<script> <script>
@ -32,12 +46,12 @@
export default { export default {
name: 'FormLogin', name: 'FormLogin',
computed: { computed: {
core() { core() {
return this.$store.getters.core return this.$store.getters.core
}, },
oauth() { oauth() {
return this.$store.getters.core.oauth return this.$store.getters.oauth
} }
}, },
data() { data() {
return { return {
@ -51,9 +65,6 @@
slack_scope: "identity.email,identity.basic" slack_scope: "identity.email,identity.basic"
} }
}, },
mounted() {
this.GHlogin()
},
methods: { methods: {
checkForm() { checkForm() {
if (!this.username || !this.password) { if (!this.username || !this.password) {
@ -76,10 +87,15 @@
} }
this.loading = false this.loading = false
}, },
async GHlogin() { GHlogin() {
const core = this.$store.getters.core; 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`
this.ghLoginURL = `https://github.com/login/oauth/authorize?client_id=${core.gh_client_id}&redirect_uri=${core.domain}/oauth/callback&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`
},
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`
}
} }
} }
</script> </script>

View File

@ -1,13 +1,14 @@
<template> <template>
<form @submit.prevent="saveOAuth"> <form @submit.prevent="saveOAuth">
{{core.oauth}}
<div class="card text-black-50 bg-white mb-3"> <div class="card text-black-50 bg-white mb-3">
<div class="card-header">Internal Login</div> <div class="card-header">Internal Login</div>
<div class="card-body"> <div class="card-body">
<div class="form-group row"> <div class="form-group row">
<label for="switch-gh-oauth" class="col-sm-4 col-form-label">OAuth Login Settings</label> <label for="switch-gh-oauth" class="col-sm-4 col-form-label">OAuth Login Settings</label>
<div class="col-md-8 col-xs-12 mt-1"> <div class="col-md-8 col-xs-12 mt-1">
<span @click="oauth.internal_enabled = !!core.oauth.internal_enabled" class="switch float-left"> <span @click="local_enabled = !!local_enabled" class="switch float-left">
<input v-model="oauth.internal_enabled" type="checkbox" class="switch" id="switch-local-oauth" :checked="oauth.internal_enabled"> <input v-model="local_enabled" type="checkbox" class="switch" id="switch-local-oauth" :checked="local_enabled">
<label for="switch-local-oauth">Use email/password Authentication</label> <label for="switch-local-oauth">Use email/password Authentication</label>
</span> </span>
</div> </div>
@ -15,7 +16,7 @@
<div class="form-group row"> <div class="form-group row">
<label for="whitelist_domains" class="col-sm-4 col-form-label">Whitelist Domains</label> <label for="whitelist_domains" class="col-sm-4 col-form-label">Whitelist Domains</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input v-model="oauth.oauth.oauth_domains" type="text" class="form-control" placeholder="domain.com" id="whitelist_domains"> <input v-model="oauth.oauth_domains" type="text" class="form-control" placeholder="domain.com" id="whitelist_domains">
</div> </div>
</div> </div>
</div> </div>
@ -28,20 +29,20 @@
<div class="form-group row mt-3"> <div class="form-group row mt-3">
<label for="github_client" class="col-sm-4 col-form-label">Github Client ID</label> <label for="github_client" class="col-sm-4 col-form-label">Github Client ID</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input v-model="oauth.oauth.gh_client_id" type="text" class="form-control" id="github_client" required> <input v-model="oauth.gh_client_id" type="text" class="form-control" id="github_client" required>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="github_secret" class="col-sm-4 col-form-label">Github Client Secret</label> <label for="github_secret" class="col-sm-4 col-form-label">Github Client Secret</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input v-model="oauth.oauth.gh_client_secret" type="text" class="form-control" id="github_secret" required> <input v-model="oauth.gh_client_secret" type="text" class="form-control" id="github_secret" required>
</div> </div>
</div> </div>
<div class="form-group row"> <div class="form-group row">
<label for="switch-gh-oauth" class="col-sm-4 col-form-label">Enable Github Login</label> <label for="switch-gh-oauth" class="col-sm-4 col-form-label">Enable Github Login</label>
<div class="col-md-8 col-xs-12 mt-1"> <div class="col-md-8 col-xs-12 mt-1">
<span @click="oauth.github_enabled = !!oauth.github_enabled" class="switch float-left"> <span @click="github_enabled = !!github_enabled" class="switch float-left">
<input v-model="oauth.github_enabled" type="checkbox" class="switch" id="switch-gh-oauth" :checked="oauth.github_enabled"> <input v-model="github_enabled" type="checkbox" class="switch" id="switch-gh-oauth" :checked="github_enabled">
<label for="switch-gh-oauth"> </label> <label for="switch-gh-oauth"> </label>
</span> </span>
</div> </div>
@ -50,7 +51,7 @@
<label for="gh_callback" class="col-sm-4 col-form-label">Callback URL</label> <label for="gh_callback" class="col-sm-4 col-form-label">Callback URL</label>
<div class="col-sm-8"> <div class="col-sm-8">
<div class="input-group"> <div class="input-group">
<input v-bind:value="`${core.domain}/oauth/github`" type="text" class="form-control" id="gh_callback" readonly> <input v-bind:value="`${core.domain}/api/oauth/github`" type="text" class="form-control" id="gh_callback" readonly>
<div class="input-group-append copy-btn"> <div class="input-group-append copy-btn">
<button @click.prevent="copy(`${core.domain}/oauth/github`)" class="btn btn-outline-secondary" type="button">Copy</button> <button @click.prevent="copy(`${core.domain}/oauth/github`)" class="btn btn-outline-secondary" type="button">Copy</button>
</div> </div>
@ -89,7 +90,7 @@
<label for="google_callback" class="col-sm-4 col-form-label">Callback URL</label> <label for="google_callback" class="col-sm-4 col-form-label">Callback URL</label>
<div class="col-sm-8"> <div class="col-sm-8">
<div class="input-group"> <div class="input-group">
<input v-bind:value="`${core.domain}/oauth/google`" type="text" class="form-control" id="google_callback" readonly> <input v-bind:value="`${core.domain}/api/oauth/google`" type="text" class="form-control" id="google_callback" readonly>
<div class="input-group-append copy-btn"> <div class="input-group-append copy-btn">
<button @click.prevent="copy(`${core.domain}/oauth/google`)" class="btn btn-outline-secondary" type="button">Copy</button> <button @click.prevent="copy(`${core.domain}/oauth/google`)" class="btn btn-outline-secondary" type="button">Copy</button>
</div> </div>
@ -126,7 +127,7 @@
<label for="switch-slack-oauth" class="col-sm-4 col-form-label">Enable Slack Login</label> <label for="switch-slack-oauth" class="col-sm-4 col-form-label">Enable Slack Login</label>
<div class="col-md-8 col-xs-12 mt-1"> <div class="col-md-8 col-xs-12 mt-1">
<span @click="slack_enabled = !!slack_enabled" class="switch float-left"> <span @click="slack_enabled = !!slack_enabled" class="switch float-left">
<input v-model="slack_enabled" type="checkbox" class="switch" id="switch-slack-oauth" :checked="google_enabled"> <input v-model="slack_enabled" type="checkbox" class="switch" id="switch-slack-oauth" :checked="slack_enabled">
<label for="switch-slack-oauth"> </label> <label for="switch-slack-oauth"> </label>
</span> </span>
</div> </div>
@ -135,7 +136,7 @@
<label for="slack_callback" class="col-sm-4 col-form-label">Callback URL</label> <label for="slack_callback" class="col-sm-4 col-form-label">Callback URL</label>
<div class="col-sm-8"> <div class="col-sm-8">
<div class="input-group"> <div class="input-group">
<input v-bind:value="`${core.domain}/oauth/slack`" type="text" class="form-control" id="slack_callback" readonly> <input v-bind:value="`${core.domain}/api/oauth/slack`" type="text" class="form-control" id="slack_callback" readonly>
<div class="input-group-append copy-btn"> <div class="input-group-append copy-btn">
<button @click.prevent="copy(`${core.domain}/oauth/slack`)" class="btn btn-outline-secondary" type="button">Copy</button> <button @click.prevent="copy(`${core.domain}/oauth/slack`)" class="btn btn-outline-secondary" type="button">Copy</button>
</div> </div>
@ -158,56 +159,61 @@
export default { export default {
name: 'OAuth', name: 'OAuth',
computed: { computed: {
oauth() { core() {
return this.$store.getters.core.oauth return this.$store.getters.core
} },
oauth() {
return this.$store.getters.oauth
}
}, },
data() { data() {
return { return {
internal_enabled: this.has('local'), google_enabled: false,
google_enabled: this.has('google'), slack_enabled: false,
github_enabled: this.has('github'), github_enabled: false,
slack_enabled: this.has('slack') local_enabled: false
} }
}, },
mounted() { mounted() {
window.console.log(this.core.oauth) this.local_enabled = this.has('local')
this.github_enabled = this.has('github')
this.google_enabled = this.has('google')
this.slack_enabled = this.has('slack')
}, },
beforeCreate() { beforeCreate() {
// this.github_enabled = this.$store.getters.core.oauth.oauth_providers.split(",").includes('github')
// const c = await Api.core()
// this.auth = c.auth
}, },
methods: { methods: {
providers() {
let providers = [];
if (this.github_enabled) {
providers.push("github")
}
if (this.local_enabled) {
providers.push("local")
}
if (this.google_enabled) {
providers.push("google")
}
if (this.slack_enabled) {
providers.push("slack")
}
return providers.join(",")
},
has(val) { has(val) {
if (!this.core.oauth.oauth_providers) { if (!this.oauth.oauth_providers) {
return false return false
} }
return this.core.oauth.oauth_providers.split(",").includes(val) return this.oauth.oauth_providers.split(",").includes(val)
},
providers() {
let providers = [];
if (this.github_enabled) {
providers.push("github")
}
if (this.internal_enabled) {
providers.push("local")
}
if (this.google_enabled) {
providers.push("google")
}
if (this.slack_enabled) {
providers.push("slack")
}
return providers.join(",")
}, },
async saveOAuth() { async saveOAuth() {
let c = this.$store.getters.core let c = this.core
c.oauth = this.oauth c.oauth = this.oauth
c.oauth.oauth_providers = this.providers() c.oauth.oauth_providers = this.providers()
await Api.core_save(c) await Api.core_save(c)
const core = await Api.core() const core = await Api.core()
this.$store.commit('setCore', core) this.$store.commit('setCore', core)
this.$store.commit('setOAuth', c.oauth)
} }
} }
} }

View File

@ -20,6 +20,7 @@ export default new Vuex.Store({
hasAllData: false, hasAllData: false,
hasPublicData: false, hasPublicData: false,
core: {}, core: {},
oauth: {},
token: null, token: null,
services: [], services: [],
service: null, service: null,
@ -35,6 +36,7 @@ export default new Vuex.Store({
hasAllData: state => state.hasAllData, hasAllData: state => state.hasAllData,
hasPublicData: state => state.hasPublicData, hasPublicData: state => state.hasPublicData,
core: state => state.core, core: state => state.core,
oauth: state => state.oauth,
token: state => state.token, token: state => state.token,
services: state => state.services, services: state => state.services,
service: state => state.service, service: state => state.service,
@ -130,9 +132,12 @@ export default new Vuex.Store({
setAdmin (state, admin) { setAdmin (state, admin) {
state.admin = admin state.admin = admin
}, },
setUser (state, user) { setUser (state, user) {
state.user = user state.user = user
}, },
setOAuth (state, oauth) {
state.oauth = oauth
},
}, },
actions: { actions: {
async getAllServices(context) { async getAllServices(context) {
@ -153,6 +158,8 @@ export default new Vuex.Store({
context.commit("setServices", services); context.commit("setServices", services);
const messages = await Api.messages() const messages = await Api.messages()
context.commit("setMessages", messages) context.commit("setMessages", messages)
const oauth = await Api.oauth()
context.commit("setOAuth", oauth);
context.commit("setHasPublicData", true) context.commit("setHasPublicData", true)
}, },
async loadAdmin(context) { async loadAdmin(context) {
@ -167,8 +174,10 @@ export default new Vuex.Store({
context.commit("setHasPublicData", true) context.commit("setHasPublicData", true)
const notifiers = await Api.notifiers() const notifiers = await Api.notifiers()
context.commit("setNotifiers", notifiers); context.commit("setNotifiers", notifiers);
const users = await Api.users() const users = await Api.users()
context.commit("setUsers", users); context.commit("setUsers", users);
const oauth = await Api.oauth()
context.commit("setOAuth", oauth);
} }
} }
}); });

View File

@ -51,6 +51,11 @@ func apiRenewHandler(w http.ResponseWriter, r *http.Request) {
returnJson(output, w, r) returnJson(output, w, r)
} }
func apiOAuthHandler(r *http.Request) interface{} {
app := core.App
return app.OAuth
}
func apiCoreHandler(w http.ResponseWriter, r *http.Request) { func apiCoreHandler(w http.ResponseWriter, r *http.Request) {
var c *core.Core var c *core.Core
err := DecodeJSON(r, &c) err := DecodeJSON(r, &c)

View File

@ -34,10 +34,13 @@ func oauthHandler(w http.ResponseWriter, r *http.Request) {
err, oauth = googleOAuth(r) err, oauth = googleOAuth(r)
case "github": case "github":
err, oauth = githubOAuth(r) err, oauth = githubOAuth(r)
case "slack":
err, oauth = slackOAuth(r)
} }
if err != nil { if err != nil {
log.Error(err) log.Error(err)
sendErrorJson(err, w, r)
return return
} }
@ -45,6 +48,7 @@ func oauthHandler(w http.ResponseWriter, r *http.Request) {
} }
func oauthLogin(oauth *oAuth, w http.ResponseWriter, r *http.Request) { func oauthLogin(oauth *oAuth, w http.ResponseWriter, r *http.Request) {
log.Infoln(oauth)
user := &users.User{ user := &users.User{
Id: 0, Id: 0,
Username: oauth.Email, Username: oauth.Email,
@ -80,7 +84,7 @@ func githubOAuth(r *http.Request) (error, *oAuth) {
} }
func googleOAuth(r *http.Request) (error, *oAuth) { func googleOAuth(r *http.Request) (error, *oAuth) {
c := *core.App c := core.App
code := r.URL.Query().Get("code") code := r.URL.Query().Get("code")
config := &oauth2.Config{ config := &oauth2.Config{

View File

@ -78,6 +78,7 @@ func Router() *mux.Router {
api.Handle("/api/cache", authenticated(apiCacheHandler, false)).Methods("GET") api.Handle("/api/cache", authenticated(apiCacheHandler, false)).Methods("GET")
api.Handle("/api/clear_cache", authenticated(apiClearCacheHandler, false)) api.Handle("/api/clear_cache", authenticated(apiClearCacheHandler, false))
api.Handle("/api/core", authenticated(apiCoreHandler, false)).Methods("POST") api.Handle("/api/core", authenticated(apiCoreHandler, false)).Methods("POST")
api.Handle("/api/oauth", scoped(apiOAuthHandler)).Methods("GET")
api.Handle("/api/logs", authenticated(logsHandler, false)).Methods("GET") api.Handle("/api/logs", authenticated(logsHandler, false)).Methods("GET")
api.Handle("/api/logs/last", authenticated(logsLineHandler, false)).Methods("GET") api.Handle("/api/logs/last", authenticated(logsLineHandler, false)).Methods("GET")
@ -158,7 +159,7 @@ func Router() *mux.Router {
// API Generic Routes // API Generic Routes
r.Handle("/metrics", readOnly(prometheusHandler, false)) r.Handle("/metrics", readOnly(prometheusHandler, false))
r.Handle("/health", http.HandlerFunc(healthCheckHandler)) r.Handle("/health", http.HandlerFunc(healthCheckHandler))
r.Handle("/oauth/{provider}", http.HandlerFunc(oauthHandler)) api.Handle("/api/oauth/{provider}", http.HandlerFunc(oauthHandler))
r.Handle("/.well-known/", http.StripPrefix("/.well-known/", http.FileServer(http.Dir(dir+"/.well-known")))) r.Handle("/.well-known/", http.StripPrefix("/.well-known/", http.FileServer(http.Dir(dir+"/.well-known"))))
r.NotFoundHandler = http.HandlerFunc(error404Handler) r.NotFoundHandler = http.HandlerFunc(error404Handler)
r.Handle("/", http.HandlerFunc(indexHandler)) r.Handle("/", http.HandlerFunc(indexHandler))

View File

@ -41,19 +41,19 @@ type Core struct {
Notifications []AllNotifiers `gorm:"-" json:"-"` Notifications []AllNotifiers `gorm:"-" json:"-"`
Integrations []Integrator `gorm:"-" json:"-"` Integrations []Integrator `gorm:"-" json:"-"`
OAuth `json:"oauth"` OAuth `json:"-"`
} }
type OAuth struct { type OAuth struct {
Domains string `gorm:"column:oauth_domains" json:"oauth_domains,omitempty" scope:"admin"` Domains string `gorm:"column:oauth_domains" json:"oauth_domains" scope:"admin"`
Providers string `gorm:"column:oauth_providers;" json:"oauth_providers,omitempty"` Providers string `gorm:"column:oauth_providers;" json:"oauth_providers"`
GithubClientID string `gorm:"column:gh_client_id" json:"gh_client_id,omitempty" scope:"admin"` GithubClientID string `gorm:"column:gh_client_id" json:"gh_client_id"`
GithubClientSecret string `gorm:"column:gh_client_secret" json:"gh_client_secret,omitempty" scope:"admin"` GithubClientSecret string `gorm:"column:gh_client_secret" json:"gh_client_secret" scope:"admin"`
GoogleClientID string `gorm:"column:google_client_id" json:"google_client_id,omitempty" scope:"admin"` GoogleClientID string `gorm:"column:google_client_id" json:"google_client_id"`
GoogleClientSecret string `gorm:"column:google_client_secret" json:"google_client_secret,omitempty" scope:"admin"` GoogleClientSecret string `gorm:"column:google_client_secret" json:"google_client_secret" scope:"admin"`
SlackClientID string `gorm:"column:slack_client_id" json:"slack_client_id,omitempty" scope:"admin"` SlackClientID string `gorm:"column:slack_client_id" json:"slack_client_id"`
SlackClientSecret string `gorm:"column:slack_client_secret" json:"slack_client_secret,omitempty" scope:"admin"` SlackClientSecret string `gorm:"column:slack_client_secret" json:"slack_client_secret" scope:"admin"`
SlackTeam string `gorm:"column:slack_team" json:"slack_team,omitempty" scope:"admin"` SlackTeam string `gorm:"column:slack_team" json:"slack_team"`
} }
// AllNotifiers contains all the Notifiers loaded // AllNotifiers contains all the Notifiers loaded