mirror of https://github.com/vx3r/wg-gen-web.git
Compare commits
6 Commits
7e2146a229
...
4a6cc6dea8
Author | SHA1 | Date |
---|---|---|
vx3r | 4a6cc6dea8 | |
vx3r | 6049ba8089 | |
vx3r | 172551dcab | |
vx3r | 34a06ad258 | |
TheLD | 9cd9f3e018 | |
TheLD | ce7e90e034 |
|
@ -5,6 +5,7 @@ import (
|
||||||
"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/api/v1"
|
"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/api/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ApplyRoutes apply routes to gin engine
|
||||||
func ApplyRoutes(r *gin.Engine, private bool) {
|
func ApplyRoutes(r *gin.Engine, private bool) {
|
||||||
api := r.Group("/api")
|
api := r.Group("/api")
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,8 +16,8 @@ import (
|
||||||
func ApplyRoutes(r *gin.RouterGroup) {
|
func ApplyRoutes(r *gin.RouterGroup) {
|
||||||
g := r.Group("/auth")
|
g := r.Group("/auth")
|
||||||
{
|
{
|
||||||
g.GET("/oauth2_url", oauth2_url)
|
g.GET("/oauth2_url", oauth2URL)
|
||||||
g.POST("/oauth2_exchange", oauth2_exchange)
|
g.POST("/oauth2_exchange", oauth2Exchange)
|
||||||
g.GET("/user", user)
|
g.GET("/user", user)
|
||||||
g.GET("/logout", logout)
|
g.GET("/logout", logout)
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ func ApplyRoutes(r *gin.RouterGroup) {
|
||||||
/*
|
/*
|
||||||
* generate redirect url to get OAuth2 code or let client know that OAuth2 is disabled
|
* generate redirect url to get OAuth2 code or let client know that OAuth2 is disabled
|
||||||
*/
|
*/
|
||||||
func oauth2_url(c *gin.Context) {
|
func oauth2URL(c *gin.Context) {
|
||||||
cacheDb := c.MustGet("cache").(*cache.Cache)
|
cacheDb := c.MustGet("cache").(*cache.Cache)
|
||||||
|
|
||||||
state, err := util.GenerateRandomString(32)
|
state, err := util.GenerateRandomString(32)
|
||||||
|
@ -62,7 +62,7 @@ func oauth2_url(c *gin.Context) {
|
||||||
/*
|
/*
|
||||||
* exchange code and get user infos, if OAuth2 is disable just send fake data
|
* exchange code and get user infos, if OAuth2 is disable just send fake data
|
||||||
*/
|
*/
|
||||||
func oauth2_exchange(c *gin.Context) {
|
func oauth2Exchange(c *gin.Context) {
|
||||||
var loginVals model.Auth
|
var loginVals model.Auth
|
||||||
if err := c.ShouldBind(&loginVals); err != nil {
|
if err := c.ShouldBind(&loginVals); err != nil {
|
||||||
log.WithFields(log.Fields{
|
log.WithFields(log.Fields{
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/api/v1/server"
|
"gitlab.127-0-0-1.fr/vx3r/wg-gen-web/api/v1/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ApplyRoutes apply routes to gin router
|
||||||
func ApplyRoutes(r *gin.RouterGroup, private bool) {
|
func ApplyRoutes(r *gin.RouterGroup, private bool) {
|
||||||
v1 := r.Group("/v1.0")
|
v1 := r.Group("/v1.0")
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Auth interface to implement as auth provider
|
||||||
type Auth interface {
|
type Auth interface {
|
||||||
Setup() error
|
Setup() error
|
||||||
CodeUrl(state string) string
|
CodeUrl(state string) string
|
||||||
|
@ -18,6 +19,7 @@ type Auth interface {
|
||||||
UserInfo(oauth2Token *oauth2.Token) (*model.User, error)
|
UserInfo(oauth2Token *oauth2.Token) (*model.User, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetAuthProvider get an instance of auth provider based on config
|
||||||
func GetAuthProvider() (Auth, error) {
|
func GetAuthProvider() (Auth, error) {
|
||||||
var oauth2Client Auth
|
var oauth2Client Auth
|
||||||
var err error
|
var err error
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Fake in order to implement interface, struct is required
|
||||||
type Fake struct{}
|
type Fake struct{}
|
||||||
|
|
||||||
// Setup validate provider
|
// Setup validate provider
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Github in order to implement interface, struct is required
|
||||||
type Github struct{}
|
type Github struct{}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Oauth2idc in order to implement interface, struct is required
|
||||||
type Oauth2idc struct{}
|
type Oauth2idc struct{}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package model
|
package model
|
||||||
|
|
||||||
|
// Auth structure
|
||||||
type Auth struct {
|
type Auth struct {
|
||||||
Oauth2 bool `json:"oauth2"`
|
Oauth2 bool `json:"oauth2"`
|
||||||
ClientId string `json:"clientId"`
|
ClientId string `json:"clientId"`
|
||||||
|
|
|
@ -16,6 +16,7 @@ type Client struct {
|
||||||
PresharedKey string `json:"presharedKey"`
|
PresharedKey string `json:"presharedKey"`
|
||||||
AllowedIPs []string `json:"allowedIPs"`
|
AllowedIPs []string `json:"allowedIPs"`
|
||||||
Address []string `json:"address"`
|
Address []string `json:"address"`
|
||||||
|
Tags []string `json:"tags"`
|
||||||
PrivateKey string `json:"privateKey"`
|
PrivateKey string `json:"privateKey"`
|
||||||
PublicKey string `json:"publicKey"`
|
PublicKey string `json:"publicKey"`
|
||||||
CreatedBy string `json:"createdBy"`
|
CreatedBy string `json:"createdBy"`
|
||||||
|
|
|
@ -2,6 +2,7 @@ package model
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
|
// User structure
|
||||||
type User struct {
|
type User struct {
|
||||||
Sub string `json:"sub"`
|
Sub string `json:"sub"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -8,22 +8,22 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.19.2",
|
||||||
"is-cidr": "^3.1.0",
|
"is-cidr": "^3.1.1",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.26.0",
|
||||||
"vue": "^2.6.10",
|
"vue": "^2.6.10",
|
||||||
"vue-axios": "^2.1.5",
|
"vue-axios": "^2.1.5",
|
||||||
"vue-moment": "^4.1.0",
|
"vue-moment": "^4.1.0",
|
||||||
"vue-router": "^3.1.6",
|
"vue-router": "^3.3.2",
|
||||||
"vuetify": "^2.2.22",
|
"vuetify": "^2.2.33",
|
||||||
"vuex": "^3.2.0"
|
"vuex": "^3.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-router": "^4.3.1",
|
"@vue/cli-plugin-router": "^4.4.1",
|
||||||
"@vue/cli-service": "^4.3.1",
|
"@vue/cli-service": "^4.4.1",
|
||||||
"sass": "^1.26.3",
|
"sass": "^1.26.8",
|
||||||
"sass-loader": "^8.0.0",
|
"sass-loader": "^8.0.0",
|
||||||
"vue-cli-plugin-vuetify": "^2.0.5",
|
"vue-cli-plugin-vuetify": "^2.0.5",
|
||||||
"vue-template-compiler": "^2.6.10",
|
"vue-template-compiler": "^2.6.10",
|
||||||
"vuetify-loader": "^1.3.0"
|
"vuetify-loader": "^1.4.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,17 @@
|
||||||
{{ ip }}
|
{{ ip }}
|
||||||
</v-chip>
|
</v-chip>
|
||||||
</template>
|
</template>
|
||||||
|
<template v-slot:item.tags="{ item }">
|
||||||
|
<v-chip
|
||||||
|
v-for="(tag, i) in item.tags"
|
||||||
|
:key="i"
|
||||||
|
color="blue-grey"
|
||||||
|
text-color="white"
|
||||||
|
>
|
||||||
|
<v-icon left>mdi-tag</v-icon>
|
||||||
|
{{ tag }}
|
||||||
|
</v-chip>
|
||||||
|
</template>
|
||||||
<template v-slot:item.created="{ item }">
|
<template v-slot:item.created="{ item }">
|
||||||
<v-row>
|
<v-row>
|
||||||
<p>At {{ item.created | formatDate }} by {{ item.createdBy }}</p>
|
<p>At {{ item.created | formatDate }} by {{ item.createdBy }}</p>
|
||||||
|
@ -55,30 +66,39 @@
|
||||||
</v-row>
|
</v-row>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:item.action="{ item }">
|
<template v-slot:item.action="{ item }">
|
||||||
<v-icon
|
<v-row>
|
||||||
class="pr-1 pl-1"
|
<v-icon
|
||||||
@click.stop="startUpdate(item)"
|
class="pr-1 pl-1"
|
||||||
>
|
@click.stop="startUpdate(item)"
|
||||||
mdi-square-edit-outline
|
>
|
||||||
</v-icon>
|
mdi-square-edit-outline
|
||||||
<v-icon
|
</v-icon>
|
||||||
class="pr-1 pl-1"
|
<v-icon
|
||||||
@click.stop="forceFileDownload(item)"
|
class="pr-1 pl-1"
|
||||||
>
|
@click.stop="forceFileDownload(item)"
|
||||||
mdi-cloud-download-outline
|
>
|
||||||
</v-icon>
|
mdi-cloud-download-outline
|
||||||
<v-icon
|
</v-icon>
|
||||||
class="pr-1 pl-1"
|
<v-icon
|
||||||
@click.stop="email(item)"
|
class="pr-1 pl-1"
|
||||||
>
|
@click.stop="email(item)"
|
||||||
mdi-email-send-outline
|
>
|
||||||
</v-icon>
|
mdi-email-send-outline
|
||||||
<v-icon
|
</v-icon>
|
||||||
class="pr-1 pl-1"
|
<v-icon
|
||||||
@click="remove(item)"
|
class="pr-1 pl-1"
|
||||||
>
|
@click="remove(item)"
|
||||||
mdi-trash-can-outline
|
>
|
||||||
</v-icon>
|
mdi-trash-can-outline
|
||||||
|
</v-icon>
|
||||||
|
<v-switch
|
||||||
|
dark
|
||||||
|
class="pr-1 pl-1"
|
||||||
|
color="success"
|
||||||
|
v-model="item.enable"
|
||||||
|
v-on:change="update(item)"
|
||||||
|
/>
|
||||||
|
</v-row>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</v-data-table>
|
</v-data-table>
|
||||||
|
@ -122,6 +142,17 @@
|
||||||
{{ ip }}
|
{{ ip }}
|
||||||
</v-chip>
|
</v-chip>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
|
<v-card-text class="text--primary">
|
||||||
|
<v-chip
|
||||||
|
v-for="(tag, i) in client.tags"
|
||||||
|
:key="i"
|
||||||
|
color="blue-grey"
|
||||||
|
text-color="white"
|
||||||
|
>
|
||||||
|
<v-icon left>mdi-tag</v-icon>
|
||||||
|
{{ tag }}
|
||||||
|
</v-chip>
|
||||||
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
<v-tooltip bottom>
|
<v-tooltip bottom>
|
||||||
<template v-slot:activator="{ on }">
|
<template v-slot:activator="{ on }">
|
||||||
|
@ -255,7 +286,26 @@
|
||||||
</v-chip>
|
</v-chip>
|
||||||
</template>
|
</template>
|
||||||
</v-combobox>
|
</v-combobox>
|
||||||
|
<v-combobox
|
||||||
|
v-model="client.tags"
|
||||||
|
chips
|
||||||
|
hint="Write tag name and hit enter"
|
||||||
|
label="Tags"
|
||||||
|
multiple
|
||||||
|
dark
|
||||||
|
>
|
||||||
|
<template v-slot:selection="{ attrs, item, select, selected }">
|
||||||
|
<v-chip
|
||||||
|
v-bind="attrs"
|
||||||
|
:input-value="selected"
|
||||||
|
close
|
||||||
|
@click="select"
|
||||||
|
@click:close="client.tags.splice(client.tags.indexOf(item), 1)"
|
||||||
|
>
|
||||||
|
<strong>{{ item }}</strong>
|
||||||
|
</v-chip>
|
||||||
|
</template>
|
||||||
|
</v-combobox>
|
||||||
<v-switch
|
<v-switch
|
||||||
v-model="client.enable"
|
v-model="client.enable"
|
||||||
color="red"
|
color="red"
|
||||||
|
@ -360,6 +410,26 @@
|
||||||
</v-chip>
|
</v-chip>
|
||||||
</template>
|
</template>
|
||||||
</v-combobox>
|
</v-combobox>
|
||||||
|
<v-combobox
|
||||||
|
v-model="client.tags"
|
||||||
|
chips
|
||||||
|
hint="Write tag name and hit enter"
|
||||||
|
label="Tags"
|
||||||
|
multiple
|
||||||
|
dark
|
||||||
|
>
|
||||||
|
<template v-slot:selection="{ attrs, item, select, selected }">
|
||||||
|
<v-chip
|
||||||
|
v-bind="attrs"
|
||||||
|
:input-value="selected"
|
||||||
|
close
|
||||||
|
@click="select"
|
||||||
|
@click:close="client.tags.splice(client.tags.indexOf(item), 1)"
|
||||||
|
>
|
||||||
|
<strong>{{ item }}</strong>
|
||||||
|
</v-chip>
|
||||||
|
</template>
|
||||||
|
</v-combobox>
|
||||||
<v-switch
|
<v-switch
|
||||||
v-model="client.ignorePersistentKeepalive"
|
v-model="client.ignorePersistentKeepalive"
|
||||||
color="red"
|
color="red"
|
||||||
|
@ -409,6 +479,7 @@
|
||||||
{ text: 'Name', value: 'name', },
|
{ text: 'Name', value: 'name', },
|
||||||
{ text: 'Email', value: 'email', },
|
{ text: 'Email', value: 'email', },
|
||||||
{ text: 'IP addresses', value: 'address', },
|
{ text: 'IP addresses', value: 'address', },
|
||||||
|
{ text: 'Tags', value: 'tags', },
|
||||||
{ text: 'Created', value: 'created', sortable: false, },
|
{ text: 'Created', value: 'created', sortable: false, },
|
||||||
{ text: 'Updated', value: 'updated', sortable: false, },
|
{ text: 'Updated', value: 'updated', sortable: false, },
|
||||||
{ text: 'Actions', value: 'action', sortable: false, },
|
{ text: 'Actions', value: 'action', sortable: false, },
|
||||||
|
@ -451,6 +522,7 @@
|
||||||
enable: true,
|
enable: true,
|
||||||
allowedIPs: this.server.allowedips,
|
allowedIPs: this.server.allowedips,
|
||||||
address: this.server.address,
|
address: this.server.address,
|
||||||
|
tags: [],
|
||||||
}
|
}
|
||||||
this.dialogCreate = true;
|
this.dialogCreate = true;
|
||||||
},
|
},
|
||||||
|
@ -529,7 +601,7 @@
|
||||||
const url = window.URL.createObjectURL(new Blob([config]))
|
const url = window.URL.createObjectURL(new Blob([config]))
|
||||||
const link = document.createElement('a')
|
const link = document.createElement('a')
|
||||||
link.href = url
|
link.href = url
|
||||||
link.setAttribute('download', 'wg0.conf') //or any other extension
|
link.setAttribute('download', client.name.split(' ').join('-') + '.conf') //or any other extension
|
||||||
document.body.appendChild(link)
|
document.body.appendChild(link)
|
||||||
link.click()
|
link.click()
|
||||||
},
|
},
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
// AuthTokenHeaderName http header for token transport
|
||||||
AuthTokenHeaderName = "x-wg-gen-web-auth"
|
AuthTokenHeaderName = "x-wg-gen-web-auth"
|
||||||
// RegexpEmail check valid email
|
// RegexpEmail check valid email
|
||||||
RegexpEmail = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
|
RegexpEmail = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$")
|
||||||
|
|
Loading…
Reference in New Issue