Add frontend login

This commit is contained in:
2020-09-03 10:08:08 +10:00
parent a2c2f6136c
commit b902cf5183
16 changed files with 730 additions and 1188 deletions
+2
View File
@@ -1 +1,3 @@
www
badger
run.sh
+1
View File
@@ -2,3 +2,4 @@
.idea
badger
**/node_modules
run.sh
+6
View File
@@ -80,6 +80,7 @@ github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6Wezm
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -250,6 +251,8 @@ github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmv
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc=
github.com/zalando/gin-oauth2 v1.5.2 h1:qwwosUfM1NhN+TwhhujKzhBnDlnLDXHZa0hLHDrlUVU=
github.com/zalando/gin-oauth2 v1.5.2/go.mod h1:ji8FkTmYYc32KK9+ZxIi78YefLtcSCRp193jO57yOHc=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -275,7 +278,9 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -313,6 +318,7 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-2
View File
@@ -68,8 +68,6 @@ func main() {
handler := &handlers.BadgesHandler{DB: db, PrometheusAPIClient: client}
sentry.CaptureMessage("sentry enabled")
r := gin.Default()
r.Use(sentrygin.New(sentrygin.Options{
+23
View File
@@ -0,0 +1,23 @@
<!-- https://codepen.io/aurer/pen/jEGbA -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="24px" height="24px" viewBox="0 0 24 24" style="enable-background:new 0 0 50 50;" xml:space="preserve">
<rect x="0" y="0" width="4" height="7" fill="#41b883">
<animateTransform attributeType="xml"
attributeName="transform" type="scale"
values="1,1; 1,3; 1,1"
begin="0s" dur="0.6s" repeatCount="indefinite" />
</rect>
<rect x="10" y="0" width="4" height="7" fill="#41b883">
<animateTransform attributeType="xml"
attributeName="transform" type="scale"
values="1,1; 1,3; 1,1"
begin="0.2s" dur="0.6s" repeatCount="indefinite" />
</rect>
<rect x="20" y="0" width="4" height="7" fill="#41b883">
<animateTransform attributeType="xml"
attributeName="transform" type="scale"
values="1,1; 1,3; 1,1"
begin="0.4s" dur="0.6s" repeatCount="indefinite" />
</rect>
</svg>

After

Width:  |  Height:  |  Size: 1005 B

+35 -20
View File
@@ -1,24 +1,29 @@
<template>
<b-overlay :show="isLoading" rounded="sm" variant="dark" class="overlay">
<b-navbar toggleable="md" type="dark" variant="dark">
<b-navbar-brand href="#">Badges</b-navbar-brand>
<b-navbar-brand href="/">Badges</b-navbar-brand>
<b-navbar-toggle target="nav-collapse"> </b-navbar-toggle>
<b-collapse id="nav-collapse" is-nav hidden>
<!--
<b-navbar-nav>
<b-nav-item href="#">more</b-nav-item>
</b-navbar-nav> -->
<!-- Right aligned nav items -->
<b-navbar-nav class="ml-auto" hidden>
<b-nav-item-dropdown right>
<!-- Using 'button-content' slot -->
<template v-slot:button-content>
<em>User</em>
</template>
<b-dropdown-item href="#">Profile</b-dropdown-item>
<b-dropdown-item href="#">Sign Out</b-dropdown-item>
</b-nav-item-dropdown>
<b-collapse id="nav-collapse" is-nav>
<b-navbar-nav>
<b-nav-item to="/" exact>
Home
</b-nav-item>
</b-navbar-nav>
<b-navbar-nav class="ml-auto">
<template v-if="$auth.$state.loggedIn">
<b-nav-item-dropdown :text="$auth.user.name" right>
<b-dropdown-item @click="$auth.logout()">
Logout
</b-dropdown-item>
</b-nav-item-dropdown>
<b-img :src="picture" class="mt-1" rounded="circle" width="30px" height="30px" />
</template>
<template v-else>
<b-dropdown-item variant="light" to="/login">
Login
</b-dropdown-item>
</template>
</b-navbar-nav>
</b-collapse>
</b-navbar>
@@ -34,20 +39,26 @@
</b-overlay>
</template>
<script lang="ts">
<script>
import Vue from "vue";
import { mapMutations } from "vuex";
import get from "lodash.get";
export default Vue.extend({
computed: {
isLoading(): boolean {
isLoading() {
return this.$store.state.loading.loading;
},
isProduction(): boolean {
isProduction() {
return this.$config.env === "production";
},
myBadge(): string {
myBadge() {
return `${this.$config.myBadge}/green.svg`
},
picture () {
return get(this.$auth.user, 'picture') || // OpenID
get(this.$auth.user, 'picture.data.url') || // Facebook graph API
get(this.$auth.user, 'avatar_url') // GitHub
}
}
});
@@ -68,8 +79,12 @@ html {
.overlay {
overflow: hidden;
}
.container {
min-height: 80vh;
}
.footer {
margin-top: 5vh;
font-size: 13px;
background: #eee;
padding: 5vh 0;
+107 -64
View File
@@ -1,94 +1,137 @@
export default {
/*
** Nuxt rendering mode
** See https://nuxtjs.org/api/configuration-mode
*/
mode: 'universal',
** Nuxt rendering mode
** See https://nuxtjs.org/api/configuration-mode
*/
mode: "universal",
/*
** Nuxt target
** See https://nuxtjs.org/api/configuration-target
*/
target: 'static',
** Nuxt target
** See https://nuxtjs.org/api/configuration-target
*/
target: "static",
/*
** Headers of the page
** See https://nuxtjs.org/api/configuration-head
*/
** Headers of the page
** See https://nuxtjs.org/api/configuration-head
*/
head: {
title: process.env.npm_package_name || '',
title: process.env.npm_package_name || "",
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: process.env.npm_package_description || 'Count and display your Github repo page access in seconds' }
{ charset: "utf-8" },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
{
hid: "description",
name: "description",
content:
process.env.npm_package_description ||
"Count and display your Github repo page access in seconds"
}
],
link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }
]
link: [{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" }]
},
/*
** Global CSS
*/
css: [
],
** Global CSS
*/
css: [],
/*
** Plugins to load before mounting the App
** https://nuxtjs.org/guide/plugins
*/
plugins: [{ src: '~plugins/ga.js', mode: 'client' }],
** Plugins to load before mounting the App
** https://nuxtjs.org/guide/plugins
*/
plugins: [{ src: "~plugins/ga.js", mode: "client" }],
/*
** Auto import components
** See https://nuxtjs.org/api/configuration-components
*/
** Auto import components
** See https://nuxtjs.org/api/configuration-components
*/
components: true,
/*
** Nuxt.js dev-modules
*/
buildModules: [
'@nuxt/typescript-build',
],
** Nuxt.js dev-modules
*/
buildModules: ["@nuxt/typescript-build"],
/*
** Nuxt.js modules
*/
** Nuxt.js modules
*/
modules: [
// Doc: https://bootstrap-vue.js.org
'bootstrap-vue/nuxt',
'@nuxt/http',
"bootstrap-vue/nuxt",
// "@nuxt/http",
// Doc: https://axios.nuxtjs.org/usage
// '@nuxtjs/axios',
'@nuxtjs/pwa',
"@nuxtjs/auth-next",
"@nuxtjs/axios",
"@nuxtjs/pwa"
// 'nuxt-i18n',
// Doc: https://github.com/nuxt/content
// '@nuxt/content',
],
http: {
proxy: true // Can be also an object with default options
},
// http: {
// proxy: true // Can be also an object with default options
// },
proxy: {
'/api/': process.env.NODE_ENV === 'production' ? 'https://badges.toozhao.com' : 'http://localhost:8080',
"/api/":
process.env.NODE_ENV === "production"
? "https://badges.toozhao.com"
: "http://localhost:3000"
},
publicRuntimeConfig: {
env: process.env.NODE_ENV,
baseURL: process.env.BASE_URL || 'http://localhost:3000',
backendURL: process.env.NODE_ENV === 'production' ? 'https://badges.toozhao.com' : 'http://localhost:8080',
myBadge: process.env.NODE_ENV === 'production' ? 'https://badges.toozhao.com/badges/01EGTQ64XK7M48A67K9Y62J0QZ' : 'http://localhost:8080/badges/01EGTQ3JBFYS7VZG36SBPM0SA9'
baseURL: process.env.BASE_URL || "http://localhost:3000",
backendURL:
process.env.NODE_ENV === "production"
? "https://badges.toozhao.com"
: "http://localhost:8080",
myBadge:
process.env.NODE_ENV === "production"
? "https://badges.toozhao.com/badges/01EGTQ64XK7M48A67K9Y62J0QZ"
: "http://localhost:8080/badges/01EGTQ3JBFYS7VZG36SBPM0SA9"
},
/*
** Axios module configuration
** See https://axios.nuxtjs.org/options
*/
// axios: {},
** Axios module configuration
** See https://axios.nuxtjs.org/options
*/
axios: {
proxy: true
},
/*
** Content module configuration
** See https://content.nuxtjs.org/configuration
*/
// i18n: {
// locales: ['en', 'zh-CN'],
// },
** Content module configuration
** See https://content.nuxtjs.org/configuration
*/
// i18n: {
// locales: ['en', 'zh-CN'],
// },
content: {},
/*
** Build configuration
** See https://nuxtjs.org/api/configuration-build/
*/
build: {
}
}
** Build configuration
** See https://nuxtjs.org/api/configuration-build/
*/
build: {},
auth: {
redirect: {
callback: '/callback',
logout: '/signed-out',
},
strategies: {
github: {
clientId: 'e5f10ed97cf95f71c5b7',
clientSecret: '8543545533ca899c8d9b40b89c3685202c8eb683'
},
local: {
token: {
property: 'token.accessToken'
}
},
localRefresh: {
scheme: 'refresh',
token: {
property: 'token.accessToken',
maxAge: 15
},
refreshToken: {
property: 'token.refreshToken',
data: 'refreshToken',
maxAge: false
}
}
}
},
// router: {
// middleware: ['auth']
// }
};
+410 -1068
View File
File diff suppressed because it is too large Load Diff
+9 -5
View File
@@ -10,18 +10,22 @@
"test": "jest"
},
"dependencies": {
"@nuxt/content": "^1.5.0",
"@nuxt/http": "^0.5.11",
"@nuxt/typescript-runtime": "^1.0.0",
"@nuxtjs/axios": "^5.12.0",
"@nuxtjs/auth-next": "5.0.0-1595693547.db756d2",
"@nuxtjs/axios": "^5.12.2",
"@nuxtjs/pwa": "^3.0.0-beta.20",
"bootstrap": "^4.5.0",
"bootstrap-vue": "^2.15.0",
"nuxt": "^2.14.0",
"cookie-parser": "^1.4.5",
"express-jwt": "^6.0.0",
"lodash": "^4.17.20",
"lodash.get": "^4.4.2",
"nanoid": "^2.1.11",
"nuxt": "^2.14.4",
"nuxt-i18n": "^6.13.12"
},
"devDependencies": {
"@nuxt/types": "^2.14.0",
"@nuxt/types": "^2.14.4",
"@nuxt/typescript-build": "^2.0.2",
"@vue/test-utils": "^1.0.3",
"babel-core": "7.0.0-bridge.0",
+17
View File
@@ -0,0 +1,17 @@
<template>
<div class="my-badges-container">
<b-container fluid="lg">
<b-row>
<b-col lg="4" offset-lg="4">
Hello
</b-col>
</b-row>
</b-container>
</div>
</template>
<script lang="ts">
export default {
};
</script>
<style lang="scss"></style>
+14
View File
@@ -0,0 +1,14 @@
<template>
<div
class="container d-flex align-items-center justify-content-center flex-column"
>
<img src="~/assets/loading.svg" alt="Loading..." width="80px" />
Logging in...
</div>
</template>
<style scoped>
.container {
min-height: 70vh;
}
</style>
+19 -8
View File
@@ -70,7 +70,8 @@
>
<b-col lg>
<p>
Or simply insert the following embedded image in a <b>Notion</b> kind of page:
Or simply insert the following embedded image in a
<b>Notion</b> kind of page:
</p>
<code>{{ myEmbeddedImageScript(activeBadgeColor) }}</code>
</b-col>
@@ -172,11 +173,12 @@
</div>
</template>
<script lang="ts">
<script>
import Vue from "vue";
import { mapMutations, mapActions } from "vuex";
export default Vue.extend({
auth: 'guest',
data() {
return {
buttonText: "Generate your Badge",
@@ -189,29 +191,38 @@ export default Vue.extend({
badge() {
return this.$store.state.badges.currentBadge;
},
defaultBadge(): string {
defaultBadge() {
return `${this.$config.myBadge}/green.svg`;
},
state () {
return JSON.stringify(this.$auth.$state, undefined, 2)
}
},
mounted() {
console.log(this.$auth.$state)
console.log(this.$auth.user, this.$auth.loggedIn);
console.log(this.$auth.token, this.$auth.strategy.token.get());
console.log(this.$auth.strategy.refreshToken);
},
methods: {
isBadgeActive: function(color: String): boolean {
isBadgeActive: function(color) {
return this.activeBadgeColor === color;
},
generateBadge: function() {
this.createNewBadge();
},
shouldRenderBadgeTextarea: function(): boolean {
shouldRenderBadgeTextarea: function() {
return this.text !== "";
},
updateBadgeText: function(color: string) {
updateBadgeText: function(color) {
var url = `${this.$config.backendURL}/badges/${this.badge.id}/${color}.svg`;
this.text = `[![Page Views Count](${url})](${url} "Get your own page views count badge on badges.toozhao.com")`;
this.activeBadgeColor = color;
},
myBadge: function(color: String): string {
myBadge: function(color) {
return `${this.$config.backendURL}/badges/${this.badge.id}/${color}.svg`;
},
myEmbeddedImageScript(color: string): string {
myEmbeddedImageScript(color) {
return `<img src="${this.myBadge(color)}" />`;
},
createNewBadge() {
+54
View File
@@ -0,0 +1,54 @@
<template>
<div class="container">
<h2 class="text-center title">
Login
</h2>
<hr />
<b-row align-h="center" class="pt-4 login">
<b-col md="4" class="text-center">
<b-card title="" bg-variant="light">
<div v-for="s in strategies" :key="s.key" class="mb-2">
<b-btn
block
:style="{ background: s.color }"
class="login-button"
@click="$auth.loginWith(s.key)"
>
Login with {{ s.name }}
</b-btn>
</div>
</b-card>
</b-col>
</b-row>
</div>
</template>
<style scoped lang="scss">
.container {
min-height: 80vh;
.title {
margin-top: 5vh;
}
.login-button {
border: 0;
}
.login {
margin-top: 5vh
}
}
</style>
<script>
export default {
middleware: "auth",
data() {
return {
error: null
};
},
computed: {
strategies: () => [{ key: "github", name: "GitHub", color: "#202326" }]
},
methods: {}
};
</script>
+22
View File
@@ -0,0 +1,22 @@
<template>
<div class="container">
<b-alert show variant="info" class="logout-alert">
You have been signed out!
</b-alert>
</div>
</template>
<style lang="scss">
.container {
.logout-alert {
margin-top: 6vh;
}
}
</style>
<script>
export default {
middleware: 'auth',
options: {
auth: false
}
}
</script>
+3 -4
View File
@@ -10,9 +10,8 @@ export const mutations = {
export const actions = {
async createBadge(context, callback) {
const result = await this.$http.post("/api/badges");
const json = await result.json();
context.commit("updateBadge", json);
callback()
const result = await this.$axios.$post("/api/badges");
context.commit("updateBadge", result);
callback();
}
};
+8 -17
View File
@@ -3,11 +3,7 @@
"target": "ES2018",
"module": "ESNext",
"moduleResolution": "Node",
"lib": [
"ESNext",
"ESNext.AsyncIterable",
"DOM"
],
"lib": ["ESNext", "ESNext.AsyncIterable", "DOM"],
"esModuleInterop": true,
"allowJs": true,
"sourceMap": true,
@@ -16,22 +12,17 @@
"experimentalDecorators": true,
"baseUrl": ".",
"paths": {
"~/*": [
"./*"
],
"@/*": [
"./*"
]
"~/*": ["./*"],
"@/*": ["./*"]
},
"types": [
"@types/node",
"@nuxt/types",
"nuxt-i18n"
"nuxt-i18n",
"@nuxtjs/axios",
"@nuxtjs/auth-next",
"bootstrap-vue"
]
},
"exclude": [
"node_modules",
".nuxt",
"dist"
]
"exclude": ["node_modules", ".nuxt", "dist"]
}