Skip to content

Commit

Permalink
Merge pull request #426 from nih-sparc/add-login-functionality
Browse files Browse the repository at this point in the history
Add login functionality
  • Loading branch information
egauzens authored Mar 28, 2022
2 parents dfd0cd5 + ab32c6c commit 9a2f93e
Show file tree
Hide file tree
Showing 15 changed files with 881 additions and 14 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ Ensure that the following configuration variables are set in your environment pr
* CTF_CDA_ACCESS_TOKEN
* CTF_API_HOST
* DEPLOY_ENV
* SHOW_FACET_MENU
* PORTAL_API_HOST


Expand Down
14 changes: 14 additions & 0 deletions assets/components/_el-menu-popper.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@import '@nih-sparc/sparc-design-system-components/src/assets/_variables.scss';
.el-menu--popup {
min-width: fit-content !important;
width: fit-content !important;
padding: 0 !important;
}

.el-menu--popup::before, .el-menu--popup::after {
display: none !important;
}

.el-menu--popup-bottom-start {
margin-top: 8px !important;
}
1 change: 1 addition & 0 deletions assets/element-variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ $--font-path: '~element-ui/lib/theme-chalk/fonts';
@import './components/_el-dialog';
@import './components/_el-tag';
@import './components/_el-table';
@import './components/_el-menu-popper';
@import './base';
@import './spacing';
@import './layout';
Expand Down
1 change: 0 additions & 1 deletion components/FacetMenu/SparcInfoFacetMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ export default {
sparcInfoType: options[0].id,
sparcInvestigatorsCategory: sparcInvestigatorsCategory,
defaultCheckedIds: [],
showFacetMenu: (process.env.show_facet_menu == 'true') ? true : false,
selectedFacets: {},
selectedFacetsArray: []
}
Expand Down
106 changes: 101 additions & 5 deletions components/header/Header.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,27 @@
<div class="header">
<div class="header__nav">
<div class="header__nav--parent">
<svg-icon icon="icon-contact" width="18" height="18" />
<svg-icon class="pr-4" icon="icon-contact" width="18" height="18" />
<nuxt-link to="/contact-us" target="_blank">
Contact Us
</nuxt-link>
<svg-icon icon="icon-help" width="18" height="18" />
<svg-icon class="pr-4" icon="icon-help" width="18" height="18" />
<nuxt-link :to="{ name: 'help' }">
Help
</nuxt-link>
<template v-if="showLoginFeature">
<svg-icon icon="icon-sign-in" style="padding-top: .125rem" height="16" width="16" />
<a v-if="!loggedInUser" class="sign-in-link" @click="onLoginWithORCID">
Sign in
</a>
<el-menu class="mr-16 user-menu" v-else popper-class="user-popper" background-color="#24245b" mode="horizontal" @select="handleUserMenuSelect">
<el-submenu index="user">
<template slot="title">{{username}}</template>
<!--<el-menu-item class="user-submenu" index="account">My account</el-menu-item>-->
<el-menu-item class="user-submenu" index="logout">Logout</el-menu-item>
</el-submenu>
</el-menu>
</template>
</div>
<div class="header__nav--main">
<div class="nav-main-container">
Expand Down Expand Up @@ -84,6 +97,15 @@
Help
</nuxt-link>
</li>
<li v-if="showLoginFeature">
<svg-icon icon="icon-sign-in" style="padding-left: .125rem" height="18" width="18" />
<a v-if="!loggedInUser" class="sign-in-link" @click="onLoginWithORCID">
Sign in
</a>
<a v-else class="sign-in-link" @click="handleUserMenuSelect('logout', ['user','logout'])">
Logout
</a>
</li>
</ul>
<div class="mobile-navigation__links--social">
<a href="https://twitter.com/sparc_science" target="_blank">
Expand Down Expand Up @@ -147,6 +169,8 @@
<script>
import SparcLogo from '../logo/SparcLogo.vue'
import SearchForm from '@/components/SearchForm/SearchForm.vue'
import Request from '@/mixins/request'
import { mapState } from 'vuex'
const links = [
{
Expand Down Expand Up @@ -182,13 +206,21 @@ export default {
SparcLogo,
SearchForm
},
mixins: [Request],
mounted() {
if (this.showLoginFeature) {
this.$store.dispatch('user/fetchUser')
}
},
data: () => {
return {
links,
menuOpen: false,
mobileSearchOpen: false,
searchQuery: '',
searchSelect: 'data',
username: "",
showLoginFeature: process.env.SHOW_LOGIN_FEATURE,
searchSelectOptions: [
{
key: 'data',
Expand All @@ -215,6 +247,7 @@ export default {
},
computed: {
...mapState('user', ['loggedInUser']),
/**
* Compute if search should be visible
* @returns {Boolean}
Expand All @@ -238,6 +271,14 @@ export default {
immediate: true
},
loggedInUser: {
handler: function(newUser) {
if (newUser) {
this.fetchUsername(this.loggedInUser)
}
},
},
/**
* Watches menuOpen to check if it's false
* to enable scrolling
Expand All @@ -253,6 +294,30 @@ export default {
},
methods: {
handleUserMenuSelect(menuId, menuIdPath) {
if (menuId === 'logout') {
this.$store.dispatch('user/logout')
}
},
onLoginWithORCID: async function(x) {
x.preventDefault()
await this.$store.dispatch('user/login', 'ORCID')
},
fetchUsername: function() {
let token = this.$store.getters['user/userToken']
let url = `https://api.pennsieve.net/user?api_key=${token}`
this.sendXhr(url).then(this.setUsername, this.failureCallback)
},
setUsername: function(result) {
if (`${result.firstName[0]}` !== null && `${result.lastName}` !== null){
this.username = `${result.firstName[0]}. ${result.lastName}`}
else {
this.username = `${result.email}`
}
},
failureCallback: function(error) {
console.log(error)
},
/**
* Sets a link to active based on current page
* @param {String} query
Expand Down Expand Up @@ -398,9 +463,8 @@ export default {
margin-top: 8px;
margin-bottom: 8px;
.svg-icon {
color: $cochlear;
padding-right: 0.4rem;
padding-top: 0.2rem;
align-self: center;
color: white;
}
img {
margin-right: 5px;
Expand Down Expand Up @@ -686,4 +750,36 @@ export default {
margin-left: 5px;
user-select: none;
}
.sign-in-link:hover {
cursor: pointer;
}
::v-deep .el-submenu__title:hover {
background-color: inherit !important;
}
::v-deep .el-submenu__title {
line-height: inherit !important;
height: fit-content !important;
color: white !important;
border: none !important;
padding: 0;
i {
color: white;
}
}
.user-menu {
border: none !important;
}
.user-submenu {
color: #303133 !important;
background-color: white !important;
font-size: 14px !important;
line-height: 32px !important;
font-weight: medium !important;
height: fit-content !important;
}
.user-submenu:hover {
color: #8300bf !important;
}
</style>
16 changes: 13 additions & 3 deletions nuxt.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default {
]
},
env: {
portal_api: process.env.PORTAL_API_HOST || 'http://localhost:8000',
portal_api: process.env.PORTAL_API_HOST || 'https://sparc-api.herokuapp.com',
flatmap_api:
process.env.FLATMAP_API_HOST || 'https://mapcore-demo.org/current/flatmap/v2/',
crosscite_api_host:
Expand Down Expand Up @@ -88,6 +88,7 @@ export default {
CTF_SPACE_ID: process.env.CTF_SPACE_ID,
CTF_CDA_ACCESS_TOKEN: process.env.CTF_CDA_ACCESS_TOKEN,
CTF_API_HOST: process.env.CTF_API_HOST,
DEPLOY_ENV: process.env.DEPLOY_ENV || 'development',
ALGOLIA_API_KEY: process.env.ALGOLIA_API_KEY,
ALGOLIA_APP_ID: process.env.ALGOLIA_APP_ID,
ALGOLIA_INDEX: process.env.ALGOLIA_INDEX || 'k-core_dev_published_time_desc',
Expand All @@ -96,7 +97,16 @@ export default {
NL_LINK_PREFIX: 'https://sparc.biolucida.net:8081',
ROOT_URL: process.env.ROOT_URL || 'http://localhost:3000',
max_download_size: parseInt(process.env.MAX_DOWNLOAD_SIZE || '5000000000'),
show_facet_menu: process.env.SHOW_FACET_MENU || 'false',
AWS_REGION: process.env.AWS_REGION || 'us-east-1',
AWS_USER_POOL_ID: process.env.AWS_USER_POOL_ID || 'us-east-1_FVLhJ7CQA',
AWS_USER_POOL_WEB_CLIENT_ID: process.env.AWS_USER_POOL_WEB_CLIENT_ID || '',
AWS_USER_AUTHENTICATION_FLOW_TYPE: process.env.AWS_USER_AUTHENTICATION_FLOW_TYPE || 'USER_PASSWORD_AUTH',
AWS_OAUTH_DOMAIN: process.env.AWS_OAUTH_DOMAIN || 'pennsieve-dev-users2.auth.us-east-1.amazoncognito.com',
AWS_OAUTH_SCOPE: process.env.AWS_OAUTH_SCOPE || ["openid"],
AWS_OAUTH_REDIRECT_SIGN_IN_URL: process.env.AWS_OAUTH_REDIRECT_SIGN_IN_URL || 'http://localhost:3000',
AWS_OAUTH_REDIRECT_SIGN_OUT_URL: process.env.AWS_OAUTH_REDIRECT_SIGN_OUT_URL || 'http://localhost:3000',
AWS_OAUTH_RESPONSE_TYPE: process.env.AWS_OAUTH_RESPONSE_TYPE || "token",
SHOW_LOGIN_FEATURE: process.env.SHOW_LOGIN_FEATURE || false
},

serverMiddleware: [
Expand Down Expand Up @@ -134,7 +144,7 @@ export default {
/*
** Plugins to load before mounting the App
*/
plugins: ['@/plugins/bootstrap', '@/plugins/contentful', {
plugins: ['@/plugins/bootstrap', '@/plugins/contentful', '@/plugins/amplify', {
src: '@/plugins/system-design-components', mode: 'client'
}],
/*
Expand Down
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
"@abi-software/mapintegratedvuer": "0.2.6",
"@abi-software/plotvuer": "^0.3.0",
"@abi-software/scaffoldvuer": "0.1.51",
"@aws-amplify/auth": "^4.4.4",
"@aws-amplify/core": "^4.4.2",
"@miyaoka/nuxt-twitter-widgets-module": "^0.0.1",
"@nih-sparc/sparc-design-system-components": "^0.26.15",
"@nuxtjs/axios": "^5.8.0",
Expand Down
3 changes: 3 additions & 0 deletions plugins/amplify.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { Auth } from '@aws-amplify/auth'
import AWSConfig from '@/utils/awsExports.js'
Auth.configure(AWSConfig)
10 changes: 10 additions & 0 deletions static/icons-js/icon-sign-in.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* eslint-disable */
var icon = require('vue-svgicon')
icon.register({
'icon-sign-in': {
width: 16,
height: 16,
viewBox: '0 0 24 24',
data: '<path pid="0" d="M8 10c2.8 0 5-2.2 5-5s-2.2-5-5-5-5 2.2-5 5 2.2 5 5 5zm0-8c1.7 0 3 1.3 3 3S9.7 8 8 8 5 6.7 5 5s1.3-3 3-3zM15.9 18.9c-.5-3.5-3.3-6.3-6.8-6.8-2.1-.3-4.2.2-5.9 1.5S.4 16.7.1 18.9c-.1.5.3 1 .8 1.1H1c.5 0 .9-.4 1-.9.5-3.3 3.5-5.5 6.8-5.1 2.2.3 4.1 1.9 4.8 3.9H5c-.6 0-1 .4-1 1s.4 1 1 1h11.1l-.2-1z"/>'
}
})
1 change: 1 addition & 0 deletions static/icons-js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ require('./icon-permalink-nobg')
require('./icon-permalink')
require('./icon-preset')
require('./icon-remove')
require('./icon-sign-in')
require('./icon-share-facebook')
require('./icon-share-linked')
require('./icon-share-twitter')
Expand Down
14 changes: 14 additions & 0 deletions static/icons-svg/icon-sign-in.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const mutations = {

const actions = {
async nuxtServerInit({dispatch}) {
await dispatch('layouts/default/fetchFooterData');
await dispatch('layouts/default/fetchFooterData');
},
};

Expand Down
58 changes: 58 additions & 0 deletions store/user/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { Auth } from '@aws-amplify/auth'
import { pathOr } from 'ramda'

export const state = () => ({
loggedInUser: null,
loginError: '',
logoutError: '',
})

export const mutations = {
SET_LOGGED_IN_USER(state, data){
state.loggedInUser = data
},
UPDATE_USER_TOKEN(state, data) {
state.userToken = data.token
},
}

export const actions = {
async login({ dispatch }, providerName){
state.loginError = ''
try {
await Auth.federatedSignIn({customProvider: providerName})
await dispatch('fetchUser')
}
catch(err){
console.log(`Login Error [${err}]`)
state.loginError = err.message
}
},
async logout({ dispatch }){
state.logoutError = ''
try {
await Auth.signOut()
await dispatch('fetchUser')
}
catch(err){
console.log(`Logout Error [${err}]`)
state.logoutError = err.message
}
},
async fetchUser({ commit }){
const session = await Auth.currentSession()
if (session) {
const user = await Auth.currentAuthenticatedUser()
commit('SET_LOGGED_IN_USER', user)
}
},
}

export const getters = {
userToken (state, getters) {
return pathOr('', ['signInUserSession', 'accessToken', 'jwtToken'], getters.user)
},
user (state) {
return state.loggedInUser
}
}
17 changes: 17 additions & 0 deletions utils/awsExports.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const awsConfig = {
Auth: {
region: process.env.AWS_REGION,
userPoolId: process.env.AWS_USER_POOL_ID,
userPoolWebClientId: process.env.AWS_USER_POOL_WEB_CLIENT_ID,
authenticationFlowType: process.env.AWS_USER_AUTHENTICATION_FLOW_TYPE,
oauth: {
domain: process.env.AWS_OAUTH_DOMAIN,
scope: process.env.AWS_OAUTH_SCOPE,
redirectSignIn: process.env.AWS_OAUTH_REDIRECT_SIGN_IN_URL,
redirectSignOut: process.env.AWS_OAUTH_REDIRECT_SIGN_OUT_URL,
responseType: process.env.AWS_OAUTH_RESPONSE_TYPE
}
}
}

export default awsConfig
Loading

0 comments on commit 9a2f93e

Please sign in to comment.