parent
603754fdfb
commit
10658b0d77
3
src/jobs-jobs-jobs/.gitignore
vendored
3
src/jobs-jobs-jobs/.gitignore
vendored
|
@ -21,3 +21,6 @@ pnpm-debug.log*
|
||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
|
|
||||||
|
dev-client.txt
|
||||||
|
src/auth/config.ts
|
||||||
|
|
5
src/jobs-jobs-jobs/package-lock.json
generated
5
src/jobs-jobs-jobs/package-lock.json
generated
|
@ -11675,6 +11675,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"vue-router": {
|
||||||
|
"version": "4.0.0-beta.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.0-beta.9.tgz",
|
||||||
|
"integrity": "sha512-k8AGMm3LCTqnsEuF37AD4kcZVMwtnFEzdjACgmIII/xbLnTj3+o5XyH/zREBZutgv5q2hzlLltMVglqDQYMd/A=="
|
||||||
|
},
|
||||||
"vue-style-loader": {
|
"vue-style-loader": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
|
||||||
|
|
|
@ -3,20 +3,22 @@
|
||||||
"version": "0.8.0",
|
"version": "0.8.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve --port 3005",
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-cli-service build --modern",
|
||||||
"lint": "vue-cli-service lint"
|
"lint": "vue-cli-service lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"vue": "^3.0.0-0",
|
"vue": "^3.0.0-0",
|
||||||
"vue-class-component": "^8.0.0-0"
|
"vue-class-component": "^8.0.0-0",
|
||||||
|
"vue-router": "^4.0.0-0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "^2.33.0",
|
"@typescript-eslint/eslint-plugin": "^2.33.0",
|
||||||
"@typescript-eslint/parser": "^2.33.0",
|
"@typescript-eslint/parser": "^2.33.0",
|
||||||
"@vue/cli-plugin-babel": "~4.5.0",
|
"@vue/cli-plugin-babel": "~4.5.0",
|
||||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||||
|
"@vue/cli-plugin-router": "^4.5.4",
|
||||||
"@vue/cli-plugin-typescript": "^4.5.4",
|
"@vue/cli-plugin-typescript": "^4.5.4",
|
||||||
"@vue/cli-service": "~4.5.0",
|
"@vue/cli-service": "~4.5.0",
|
||||||
"@vue/compiler-sfc": "^3.0.0-0",
|
"@vue/compiler-sfc": "^3.0.0-0",
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<Home msg="this message is not displayed"/>
|
<div id="nav">
|
||||||
|
<router-link to="/">Home</router-link> |
|
||||||
|
<router-link to="/about">About</router-link> |
|
||||||
|
<a href="#" @click.stop="authorize">Log On</a>
|
||||||
|
</div>
|
||||||
|
<router-view/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Home from './components/Home.vue'
|
import { authorize } from '@/auth'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
setup() {
|
||||||
Home,
|
return {
|
||||||
},
|
authorize
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -21,6 +27,18 @@ export default {
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #2c3e50;
|
color: #2c3e50;
|
||||||
margin-top: 60px;
|
}
|
||||||
|
|
||||||
|
#nav {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav a {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #2c3e50;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav a.router-link-exact-active {
|
||||||
|
color: #42b983;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
63
src/jobs-jobs-jobs/src/auth/index.ts
Normal file
63
src/jobs-jobs-jobs/src/auth/index.ts
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/**
|
||||||
|
* Authentication and Authorization.
|
||||||
|
*
|
||||||
|
* This contains authentication and authorization functions needed to permit secure access to the application.
|
||||||
|
*
|
||||||
|
* @author Daniel J. Summers <daniel@bitbadger.solutions>
|
||||||
|
* @version 1
|
||||||
|
*/
|
||||||
|
import { CLIENT_SECRET } from './config'
|
||||||
|
|
||||||
|
/** Client ID for Jobs, Jobs, Jobs */
|
||||||
|
const CLIENT_ID = '6Ook3LBff00dOhyBgbf4eXSqIpAroK72aioIdGaDqxs'
|
||||||
|
|
||||||
|
/** No Agenda Social's base URL */
|
||||||
|
const NAS_URL = 'https://noagendasocial.com/'
|
||||||
|
|
||||||
|
/** No Agenda Social's base API URL */
|
||||||
|
const API_URL = `${NAS_URL}api/v1/`
|
||||||
|
|
||||||
|
/** The base URL for Jobs, Jobs, Jobs */
|
||||||
|
const JJJ_URL = `${location.protocol}//${location.host}/`
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authorize access to this application from No Agenda Social.
|
||||||
|
*
|
||||||
|
* This is the first step in a 2-step log on process; this step will prompt the user to authorize Jobs, Jobs, Jobs to
|
||||||
|
* get information from their No Agenda Social profile. Once that authorization has been granted, we receive an access
|
||||||
|
* code which we can use to request a full token.
|
||||||
|
*/
|
||||||
|
export function authorize() {
|
||||||
|
const params = new URLSearchParams([
|
||||||
|
[ 'client_id', CLIENT_ID ],
|
||||||
|
[ 'scope', 'read' ],
|
||||||
|
[ 'redirect_uri', `${JJJ_URL}user/authorized` ],
|
||||||
|
[ 'response_type', 'code' ]
|
||||||
|
]).toString()
|
||||||
|
location.assign(`${NAS_URL}oauth/authorize?${params}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function logOn(authCode: string) {
|
||||||
|
const options: RequestInit = {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify({
|
||||||
|
client_id: CLIENT_ID,
|
||||||
|
client_secret: CLIENT_SECRET,
|
||||||
|
redirect_uri: `${JJJ_URL}user/authorized`,
|
||||||
|
grant_type: 'authorization_code',
|
||||||
|
code: authCode,
|
||||||
|
scope: 'read'
|
||||||
|
}),
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
}
|
||||||
|
const resp = await fetch(`${NAS_URL}oauth/token`, options)
|
||||||
|
if (resp.ok) {
|
||||||
|
const token = await resp.json()
|
||||||
|
// TODO: submit token to server, let server obtain profile from NA Social
|
||||||
|
console.info(`Success - response ${JSON.stringify(token)}`)
|
||||||
|
} else {
|
||||||
|
// TODO: notify the user
|
||||||
|
const err = await resp.text()
|
||||||
|
console.error(`Failure - ${err}`)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
|
import router from './router'
|
||||||
|
|
||||||
createApp(App).mount('#app')
|
createApp(App).use(router).mount('#app')
|
||||||
|
|
33
src/jobs-jobs-jobs/src/router/index.ts
Normal file
33
src/jobs-jobs-jobs/src/router/index.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
|
||||||
|
|
||||||
|
import Home from '../views/Home.vue'
|
||||||
|
import Authorized from '../views/user/Authorized.vue'
|
||||||
|
|
||||||
|
const routes: Array<RouteRecordRaw> = [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
name: 'Home',
|
||||||
|
component: Home
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/about',
|
||||||
|
name: 'About',
|
||||||
|
// route level code-splitting
|
||||||
|
// this generates a separate chunk (about.[hash].js) for this route
|
||||||
|
// which is lazy-loaded when the route is visited.
|
||||||
|
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/user/authorized',
|
||||||
|
name: 'Authorized',
|
||||||
|
component: Authorized,
|
||||||
|
props: (route) => ({ code: route.query.code })
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const router = createRouter({
|
||||||
|
history: createWebHistory(process.env.BASE_URL),
|
||||||
|
routes
|
||||||
|
})
|
||||||
|
|
||||||
|
export default router
|
5
src/jobs-jobs-jobs/src/views/About.vue
Normal file
5
src/jobs-jobs-jobs/src/views/About.vue
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<template>
|
||||||
|
<div class="about">
|
||||||
|
<h1>This is an about page</h1>
|
||||||
|
</div>
|
||||||
|
</template>
|
75
src/jobs-jobs-jobs/src/views/Home.vue
Normal file
75
src/jobs-jobs-jobs/src/views/Home.vue
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
<template>
|
||||||
|
<div class="hello">
|
||||||
|
<h1>
|
||||||
|
Jobs, Jobs, Jobs<br>
|
||||||
|
<small><small><small><em>
|
||||||
|
(and Jobs - <a class="audio" @click="playJobs">Let's Vote for Jobs!</a>)
|
||||||
|
</em></small></small></small>
|
||||||
|
</h1>
|
||||||
|
<p>
|
||||||
|
Future home of No Agenda Jobs, where citizens of Gitmo Nation can assist one another in finding or enhancing
|
||||||
|
their employment. This will enable them to continue providing value for value to Adam and John, as they continue
|
||||||
|
their work deconstructing the misinformation that passes for news on a day-to-day basis.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Do you not understand the terms in the paragraph above? No worries; just head over to
|
||||||
|
<a href="https://noagendashow.net">The Best Podcast in the Universe</a> <em><a class="audio" @click="playTrue">(it's true!)</a></em> and find out what
|
||||||
|
you’re missing.
|
||||||
|
</p>
|
||||||
|
<audio ref="jobsAudio">
|
||||||
|
<source src="/pelosi-jobs.mp3">
|
||||||
|
</audio>
|
||||||
|
<audio ref="trueAudio">
|
||||||
|
<source src="/thats-true.mp3">
|
||||||
|
</audio>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
msg: String
|
||||||
|
},
|
||||||
|
setup() {
|
||||||
|
const jobsAudio = ref(null)
|
||||||
|
const trueAudio = ref(null)
|
||||||
|
|
||||||
|
const playJobs = () => jobsAudio.value.play()
|
||||||
|
const playTrue = () => trueAudio.value.play()
|
||||||
|
return {
|
||||||
|
jobsAudio,
|
||||||
|
trueAudio,
|
||||||
|
playJobs,
|
||||||
|
playTrue
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 40px 0 0;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 10px;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #42b983;
|
||||||
|
}
|
||||||
|
a.audio {
|
||||||
|
color: inherit;
|
||||||
|
border-bottom: dotted 1px lightgray;
|
||||||
|
}
|
||||||
|
a.audio:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
18
src/jobs-jobs-jobs/src/views/user/Authorized.vue
Normal file
18
src/jobs-jobs-jobs/src/views/user/Authorized.vue
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<template>
|
||||||
|
<p>Logging you on with No Agenda Social...</p>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { logOn } from '@/auth'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
code: {
|
||||||
|
type: String
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
logOn(props.code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
Loading…
Reference in New Issue
Block a user