master 84801f7fa563 cached
33 files
34.2 KB
9.5k tokens
3 symbols
1 requests
Download .txt
Repository: wolfeidau/cognito-vue-bootstrap
Branch: master
Commit: 84801f7fa563
Files: 33
Total size: 34.2 KB

Directory structure:
gitextract_a2ppqcxr/

├── .browserslistrc
├── .eslintrc.js
├── .github/
│   └── workflows/
│       └── nodejs.yml
├── .gitignore
├── .nvmrc
├── LICENSE.md
├── Makefile
├── README.md
├── babel.config.js
├── jest.config.js
├── package.json
├── postcss.config.js
├── public/
│   └── index.html
├── src/
│   ├── App.vue
│   ├── aws-exports.js
│   ├── components/
│   │   ├── Footer.vue
│   │   ├── Menu.vue
│   │   └── auth/
│   │       └── Alert.vue
│   ├── main.js
│   ├── pages/
│   │   ├── Dashboard.vue
│   │   ├── Home.vue
│   │   └── auth/
│   │       ├── ChangePassword.vue
│   │       ├── ConfirmPasswordReset.vue
│   │       ├── ConfirmSignUp.vue
│   │       ├── PasswordReset.vue
│   │       ├── SignIn.vue
│   │       ├── SignOut.vue
│   │       └── SignUp.vue
│   ├── router/
│   │   └── index.js
│   └── store/
│       ├── index.js
│       └── modules/
│           └── auth.js
├── tests/
│   └── unit/
│       └── footer.spec.js
└── vue.config.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .browserslistrc
================================================
> 1%
last 2 versions


================================================
FILE: .eslintrc.js
================================================
module.exports = {
  root: true,
  env: {
    node: true
  },
  extends: ["plugin:vue/essential", "@vue/prettier"],
  rules: {
    "no-console": process.env.NODE_ENV === "production" ? "error" : "off",
    "no-debugger": process.env.NODE_ENV === "production" ? "error" : "off"
  },
  parserOptions: {
    parser: "babel-eslint"
  },
  overrides: [
    {
      files: [
        "**/__tests__/*.{j,t}s?(x)",
        "**/tests/unit/**/*.spec.{j,t}s?(x)"
      ],
      env: {
        jest: true
      }
    }
  ]
};


================================================
FILE: .github/workflows/nodejs.yml
================================================
name: Node CI

on: [push]

jobs:
  build:

    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [10.x, 12.x]

    steps:
    - uses: actions/checkout@v1
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v1
      with:
        node-version: ${{ matrix.node-version }}
    - name: npm install, build, and test
      run: |
        yarn
        yarn run build --if-present
        yarn jest
      env:
        CI: true


================================================
FILE: .gitignore
================================================
.DS_Store
node_modules
/dist

# local env files
.env.local
.env.*.local

# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*

# Don't commit your aws mobile configuration file
.envrc

================================================
FILE: .nvmrc
================================================
10


================================================
FILE: LICENSE.md
================================================
   Copyright 2018 Mark Wolfe

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: Makefile
================================================
ci: clean build deploy

clean:
	rm -rf dist

build:
	yarn build

deploy:
	aws s3 sync dist/ s3://$(S3_HOSTING_BUCKET)/ --delete --acl public-read
	aws cloudfront create-invalidation --distribution-id $(DISTRIBUTION_ID) --paths '/*'

================================================
FILE: README.md
================================================
# cognito-vue-bootstrap

This application illustrates how to use the [Amazon Amplify](https://github.com/aws/aws-amplify) with [vue.js](https://vuejs.org/), it includes signup, signin, signout, recover password and account verification using email or sms codes. It uses [bootstrap-vue](https://bootstrap-vue.js.org/) for layout.

# overview

This example application currently illustrates the following:

* Sign Up for an account
* Verify your account by entering verification code which has been sent to you via emailed or SMS
* Dashboard which requires authentication to access
* Change Password
* Recover Password using verification code which has been sent to you via emailed or SMS
* Sign In to the application
* Sign Out of the application

Demo version is located at https://cognito-vue-bootstrapv2.wolfe.id.au/

# Build Setup

Before you start have a read over [What is Amazon Cognito?](http://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html)

To setup this project you first need to configure an aws mobile project using the following snapshot [CognitoVue](https://console.aws.amazon.com/mobilehub/home#/snapshot/ef9bu3t7nsa8uz).

For more information on this process see [Exporting and Importing AWS Mobile Hub Projects](https://docs.aws.amazon.com/aws-mobile/latest/developerguide/project-import-export.html)

Once you have imported the project you will have created:

* An S3 bucket with Cloudfront for your web application.
* A Cognito pool to store your users
* An analytics project to capture metrics on your users login / failure ect.

Click on the integrate button in your aws mobile project, the download and extract the cloud config zip file, find `aws-exports.js` inside, and replace this file in `src/` directory.

I use [yarn](https://yarnpkg.com/) to build and run this project.

``` bash
# install dependencies
yarn install

# serve with hot reload at localhost:8080
yarn serve

# build for production with minification
yarn build
```

Sync all the files from your `dist` directory up to the S3 hosting bucket within your AWS Mobile project using the following command.

```
aws --region ap-southeast-2 s3 sync dist/ s3://cognitovuebootstrap-hosting-mobilehub-XXXXXXXXXX/ --delete --acl public-read
```

# hosting configuration notes

To host a website on a custom URL using AWS mobile I have found some changes to the current setup. Navigating to the buckets and CDN configuration is done via the `Hosting And Streaming` panel in the mobile project UI.

* disable website hosting on the hosting S3 bucket
* add an Error Page which sends any 404 (not found) errors to `/index.html` in cloudfront
* enable redirect http -> https on the origin
* configure a route53 domain for your website
* configure a AWS Certificate Manager (ACM) certificate for your domain
* add an A record in route53 of type `alias` pointing to your Cloudfront distribution, then update the origin domain name to match the FQDN.

For a more detailed explanation on how things work, checkout:

* [AWS Amplify Documentation](https://aws.github.io/aws-amplify/)
* [AWS Amplify Modularization](https://github.com/aws-amplify/amplify-js/wiki/Amplify-modularization)
* [docs for vue-cli](https://cli.vuejs.org/)
* [docs for vue-router](http://router.vuejs.org/en/)
* [docs for vuex](https://vuex.vuejs.org/)

# License

This project is released under the Apache License, Version 2.0.


================================================
FILE: babel.config.js
================================================
module.exports = {
  presets: ["@vue/cli-plugin-babel/preset"]
};


================================================
FILE: jest.config.js
================================================
module.exports = {
  preset: "@vue/cli-plugin-unit-jest"
};


================================================
FILE: package.json
================================================
{
  "name": "cognito-vue-bootstrap",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "test:unit": "vue-cli-service test:unit",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "@aws-amplify/auth": "^1.5.0",
    "bootstrap-vue": "^2.0.4",
    "core-js": "^3.3.2",
    "vue": "^2.6.10",
    "vue-awesome": "^3.5.4",
    "vue-resource": "^1.5.1",
    "vue-router": "^3.1.3",
    "vuex": "^3.0.1",
    "vuex-localstorage": "^1.0.0"
  },
  "devDependencies": {
    "@testing-library/vue": "^4.1.0",
    "@vue/cli-plugin-babel": "^4.0.0",
    "@vue/cli-plugin-eslint": "^4.0.0",
    "@vue/cli-plugin-router": "^4.0.0",
    "@vue/cli-plugin-unit-jest": "^4.0.0",
    "@vue/cli-plugin-vuex": "^4.0.0",
    "@vue/cli-service": "^4.0.0",
    "@vue/eslint-config-prettier": "^5.0.0",
    "@vue/test-utils": "1.0.0-beta.29",
    "babel-eslint": "^10.0.3",
    "eslint": "^5.16.0",
    "eslint-plugin-prettier": "^3.1.1",
    "eslint-plugin-vue": "^5.0.0",
    "prettier": "^1.18.2",
    "vue-template-compiler": "^2.6.10"
  }
}


================================================
FILE: postcss.config.js
================================================
module.exports = {
  plugins: {
    autoprefixer: {}
  }
};


================================================
FILE: public/index.html
================================================
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title>cognito-vue-bootstrapv3</title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but cognito-vue-bootstrapv3 doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>


================================================
FILE: src/App.vue
================================================
<template>
  <div id="app">
    <b-container class="main" fluid>
      <v-menu />
      <router-view />
      <v-footer />
    </b-container>
  </div>
</template>

<script>
import Vue from "vue";
import Menu from "@/components/Menu.vue";
import Footer from "@/components/Footer.vue";
import Icon from "vue-awesome/components/Icon";

Vue.component("v-menu", Menu);
Vue.component("v-footer", Footer);
Vue.component("v-icon", Icon);

export default {
  name: "App"
};
</script>

<style>
@import "~bootstrap/dist/css/bootstrap.css";
@import "~bootstrap-vue/dist/bootstrap-vue.css";

#app {
  font-family: "Avenir", Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  margin: 0;
  padding: 0;
}

.main {
  margin: 0;
  padding: 0;
}

.b-main-content {
  padding-top: 1.5rem;
  padding-bottom: 1.5rem;
  margin-right: 0;
  margin-left: 0;
}

.b-form-1 {
  padding-top: 1.5rem;
  padding-bottom: 1.5rem;
  margin-right: 0;
  margin-left: 0;
  border-width: 0.2rem;
}
</style>


================================================
FILE: src/aws-exports.js
================================================
const config = {
  // To get the AWS Credentials, you need to configure
  // the Auth module with your Cognito Federated Identity Pool
  Auth: {
    identityPoolId: process.env.IDENTITY_POOL_ID,
    region: process.env.AWS_REGION,
    userPoolId: process.env.USER_POOL_ID,
    userPoolWebClientId: process.env.USER_POOL_WEB_CLIENT_ID,
    mandatorySignIn: false,
    clientMetadata: { app: "cognito-vue-bootstrap" }
  },
  Analytics: {
    disabled: false,
    autoSessionRecord: true,
    AWSPinpoint: {
      appId: process.env.PINPOINT_APP_ID,
      region: process.env.AWS_REGION
    }
  }
};

export default config;


================================================
FILE: src/components/Footer.vue
================================================
<template>
  <footer class="bd-footer">
    <b-container>
      <b-row class="justify-content-md-center">
        <div class="bd-footer-copyright">© 2018 Company, Inc.</div>
      </b-row>
    </b-container>
  </footer>
</template>

<script>
export default {};
</script>

<style>
.bd-footer {
  margin-top: 2em;
  border-top: 0.2rem #f7f7f7 solid !important;
}

.bd-footer-copyright {
  padding-top: 1rem;
  padding-bottom: 1rem;
}
</style>


================================================
FILE: src/components/Menu.vue
================================================
<template>
  <b-navbar toggleable="md" type="dark">
    <b-navbar-toggle target="nav_collapse" />
    <b-navbar-brand to="/">Cognito Bootstrap</b-navbar-brand>
    <b-navbar-nav>
      <b-nav-item to="/dashboard">Dashboard</b-nav-item>
    </b-navbar-nav>
    <b-navbar-nav class="ml-auto">
      <b-nav-item v-if="!isAuthenticated" class="nav-btn" to="/signIn"
        ><span class="nav-username">Sign In</span></b-nav-item
      >
      <b-nav-item-dropdown v-if="isAuthenticated" right>
        <template slot="button-content">
          <v-icon name="regular/user-circle" /><strong class="nav-username">{{
            user.username
          }}</strong>
        </template>
        <b-row class="justify-content-md-center" style="margin:5px">
          <b-dropdown-item to="/changePassword"
            ><span class="nav-username">Change Password</span></b-dropdown-item
          >
          <b-dropdown-item to="/signOut"
            ><v-icon name="sign-out-alt" /><span class="nav-username"
              >Sign Out</span
            ></b-dropdown-item
          >
        </b-row>
      </b-nav-item-dropdown>
      <b-nav-item class="nav-btn" href="https://twitter.com/wolfeidau"
        ><v-icon name="brands/twitter"
      /></b-nav-item>
      <b-nav-item
        class="nav-btn"
        href="https://github.com/wolfeidau/cognito-vue-bootstrap"
        ><v-icon name="brands/github"
      /></b-nav-item>
    </b-navbar-nav>
  </b-navbar>
</template>

<script>
import { mapState } from "vuex";

import "vue-awesome/icons/regular/user-circle";
import "vue-awesome/icons/sign-out-alt";
import "vue-awesome/icons/brands/twitter";
import "vue-awesome/icons/brands/github";

export default {
  name: "Navbar",
  computed: {
    ...mapState({
      user: state => state.auth.user,
      isAuthenticated: state => state.auth.isAuthenticated
    })
  },
  methods: {
    signIn() {
      this.$store.dispatch("signIn");
    }
  }
};
</script>

<style scoped>
.navbar {
  background-color: #563d7c;
}
.navbar-nav .nav-link {
  color: #cbbde2;
}
.nav-username {
  padding-left: 0.5em;
  padding-right: 0.5em;
}
</style>


================================================
FILE: src/components/auth/Alert.vue
================================================
<template>
  <b-alert
    :show="hasAuthenticationStatus"
    :variant="authenticationStatus.variant"
    >{{ authenticationStatus.message }}.</b-alert
  >
</template>

<script>
import { mapGetters } from "vuex";

export default {
  mounted() {
    // clear existing status message
    this.$store.dispatch("auth/clearAuthenticationStatus");
  },
  computed: {
    ...mapGetters("auth", ["authenticationStatus", "hasAuthenticationStatus"])
  }
};
</script>


================================================
FILE: src/main.js
================================================
import Vue from "vue";
import BootstrapVue from "bootstrap-vue";
import App from "@/App.vue";
import router from "@/router";
import store from "@/store";
import Auth from "@aws-amplify/auth";
import AuthConfig from "@/aws-exports";

Auth.configure(AuthConfig);

Vue.use(BootstrapVue);

Vue.config.productionTip = false;

new Vue({
  router,
  store,
  el: "#app",
  render: h => h(App)
});


================================================
FILE: src/pages/Dashboard.vue
================================================
<template>
  <b-container>
    <div class="b-main-content">
      <h2>Cognito Bootstrap Vue</h2>
      <p>You are logged in as {{ user.username }}.</p>
    </div>
  </b-container>
</template>

<script>
import { mapState } from "vuex";

export default {
  computed: {
    ...mapState({
      user: state => state.auth.user
    })
  }
};
</script>


================================================
FILE: src/pages/Home.vue
================================================
<template>
  <b-container>
    <div class="b-main-content">
      <h2>Cognito Bootstrap Vue</h2>
      <p>
        This site provides an example of how to use
        <b-link href="https://aws.amazon.com/cognito">Amazon Cognito</b-link>
        with <b-link href="https://vuejs.org">Vue.js</b-link>
      </p>
      <p>To give it a try:</p>
      <ol>
        <li>
          Sign up using your email address, this will send through an activation
          code.
        </li>
        <li>
          Once you get the activation code enter it with your email address.
        </li>
        <li>Sign in with your credentials.</li>
        <li>Request a password reset to recover an account.</li>
        <li>Change your password.</li>
      </ol>
      <p>
        <b-button variant="outline-dark" to="signUp">Sign Up</b-button>
      </p>
      <p>
        The full source code for this example application is available here:
      </p>
      <ul>
        <li>
          <b-link href="https://github.com/wolfeidau/cognito-vue-bootstrap"
            >https://github.com/wolfeidau/cognito-vue-bootstrap</b-link
          >
        </li>
      </ul>
    </div>
  </b-container>
</template>

<script>
export default {};
</script>


================================================
FILE: src/pages/auth/ChangePassword.vue
================================================
<template>
  <b-container>
    <b-row class="justify-content-md-center">
      <b-col cols="4">
        <div class="b-form-1">
          <h2>Change Password</h2>
          <p>Request a password change.</p>
          <b-form @submit.prevent="passwordChange">
            <b-form-group
              label="Current Password:"
              label-for="currentPasswordInput"
            >
              <b-form-input
                id="currentPasswordInput"
                type="password"
                v-model="currentPassword"
                required
                placeholder="Enter Current Password"
              />
            </b-form-group>
            <b-form-group label="New Password:" label-for="newPasswordInput">
              <b-form-input
                id="newPasswordInput"
                type="password"
                v-model="newPassword"
                required
                placeholder="Enter New Password"
              />
            </b-form-group>
            <b-button type="submit" variant="primary">Submit</b-button>
          </b-form>
        </div>
      </b-col>
    </b-row>
    <b-row class="justify-content-md-center">
      <b-col cols="4">
        <v-alert />
      </b-col>
    </b-row>
  </b-container>
</template>

<script>
import Vue from "vue";

import { mapGetters } from "vuex";
import router from "@/router";
import store from "@/store";

import Alert from "@/components/auth/Alert.vue";

Vue.component("v-alert", Alert);

export default {
  data() {
    return {
      currentPassword: "",
      newPassword: ""
    };
  },
  computed: {
    ...mapGetters("auth", ["hasAuthenticationStatus"])
  },
  methods: {
    async passwordChange() {
      await store.dispatch("auth/passwordChange", {
        currentPassword: this.currentPassword,
        newPassword: this.newPassword
      });
      if (!this.hasAuthenticationStatus) {
        router.push("dashboard");
      }
    }
  }
};
</script>


================================================
FILE: src/pages/auth/ConfirmPasswordReset.vue
================================================
<template>
  <b-container>
    <b-row class="justify-content-md-center">
      <b-col cols="4">
        <div class="b-form-1">
          <h2>Confirm Reset Password</h2>
          <p>
            Confirm a password reset using the code you recieved via emailed.
          </p>
          <b-form-group label="Username:" label-for="usernameInput">
            <b-form-input
              id="usernameInput"
              type="text"
              v-model="username"
              required
              autofocus
              placeholder="Enter username"
            />
          </b-form-group>
          <b-form-group label="Code:" label-for="codeInput">
            <b-form-input
              id="codeInput"
              type="password"
              v-model="code"
              required
              placeholder="Enter Code"
            />
          </b-form-group>
          <b-form-group label="Password:" label-for="passwordInput">
            <b-form-input
              id="passwordInput"
              type="password"
              v-model="password"
              required
              placeholder="Enter Code"
            />
          </b-form-group>
          <b-button
            type="submit"
            variant="primary"
            @click="confirmPasswordReset"
            >Submit</b-button
          >
          <b-button variant="primary" @click="passwordResetResend"
            >Resend Code</b-button
          >
        </div>
      </b-col>
    </b-row>
    <b-row class="justify-content-md-center">
      <b-col cols="4">
        <v-alert />
      </b-col>
    </b-row>
  </b-container>
</template>

<script>
import Vue from "vue";

import { mapGetters } from "vuex";
import router from "@/router";
import store from "@/store";

import Alert from "@/components/auth/Alert.vue";

Vue.component("v-alert", Alert);

export default {
  data() {
    return {
      username: "",
      code: "",
      password: ""
    };
  },
  computed: {
    ...mapGetters("auth", ["hasAuthenticationStatus"])
  },
  methods: {
    async confirmPasswordReset() {
      await store.dispatch("auth/confirmPasswordReset", {
        username: this.username,
        code: this.code,
        password: this.password
      });
      if (!this.hasAuthenticationStatus) {
        router.push("signIn");
      }
    },
    async passwordResetResend() {
      await store.dispatch("auth/passwordReset", {
        username: this.username
      });
    }
  }
};
</script>


================================================
FILE: src/pages/auth/ConfirmSignUp.vue
================================================
<template>
  <b-container>
    <b-row class="justify-content-md-center">
      <b-col cols="4">
        <div class="b-form-1">
          <h2>Confirm Sign Up</h2>
          <b-form-group label="Username:" label-for="usernameInput">
            <b-form-input
              id="usernameInput"
              type="text"
              v-model="username"
              required
              autofocus
              placeholder="Enter username"
            />
          </b-form-group>
          <b-form-group label="Code:" label-for="codeInput">
            <b-form-input
              id="codeInput"
              type="password"
              v-model="code"
              required
              placeholder="Enter Code"
            />
          </b-form-group>
          <b-button type="submit" variant="primary" @click="confirmSignUp"
            >Submit</b-button
          >
          <b-button variant="primary" @click="confirmResend"
            >Resend Code</b-button
          >
        </div>
      </b-col>
    </b-row>
    <b-row class="justify-content-md-center">
      <b-col cols="4">
        <v-alert />
      </b-col>
    </b-row>
  </b-container>
</template>

<script>
import Vue from "vue";

import { mapGetters } from "vuex";
import router from "@/router";
import store from "@/store";

import Alert from "@/components/auth/Alert.vue";

Vue.component("v-alert", Alert);

export default {
  data() {
    return {
      username: "",
      code: ""
    };
  },
  computed: {
    ...mapGetters("auth", ["hasAuthenticationStatus"])
  },
  methods: {
    async confirmSignUp() {
      await store.dispatch("auth/confirmSignUp", {
        username: this.username,
        code: this.code
      });
      if (!this.hasAuthenticationStatus) {
        router.push("signIn");
      }
    },
    async confirmResend() {
      await store.dispatch("auth/confirmResend", {
        username: this.username
      });
    }
  }
};
</script>


================================================
FILE: src/pages/auth/PasswordReset.vue
================================================
<template>
  <b-container>
    <b-row class="justify-content-md-center">
      <b-col cols="4">
        <div class="b-form-1">
          <h2>Reset Password</h2>
          <p>Request a password reset code via email.</p>
          <b-form @submit.prevent="passwordReset">
            <b-form-group label="Username:" label-for="usernameInput">
              <b-form-input
                id="usernameInput"
                type="text"
                v-model="username"
                required
                autofocus
                placeholder="Enter username"
              />
            </b-form-group>
            <b-button type="submit" variant="primary">Submit</b-button>
          </b-form>
        </div>
      </b-col>
    </b-row>
    <b-row class="justify-content-md-center">
      <b-col cols="4">
        <v-alert />
      </b-col>
    </b-row>
  </b-container>
</template>

<script>
import Vue from "vue";

import { mapGetters } from "vuex";
import router from "@/router";
import store from "@/store";

import Alert from "@/components/auth/Alert.vue";

Vue.component("v-alert", Alert);

export default {
  data() {
    return {
      username: ""
    };
  },
  computed: {
    ...mapGetters("auth", ["hasAuthenticationStatus"])
  },
  methods: {
    async passwordReset() {
      await store.dispatch("auth/passwordReset", {
        username: this.username
      });
      if (!this.hasAuthenticationStatus) {
        router.push("confirmPasswordReset");
      }
    }
  }
};
</script>


================================================
FILE: src/pages/auth/SignIn.vue
================================================
<template>
  <b-container>
    <b-row class="justify-content-md-center">
      <b-col cols="4">
        <div class="b-form-1">
          <h2>Sign In</h2>
          <p>Sign into this site.</p>
          <b-form @submit.prevent="signIn">
            <b-form-group label="Email:" label-for="emailInput">
              <b-form-input
                id="emailInput"
                type="email"
                v-model="email"
                required
                placeholder="Enter email"
              />
            </b-form-group>
            <b-form-group label="Password:" label-for="passwordInput">
              <b-form-input
                id="passwordInput"
                type="password"
                v-model="pass"
                required
                placeholder="Enter Password"
              />
            </b-form-group>
            <b-button type="submit" variant="primary">Submit</b-button>
          </b-form>
        </div>
      </b-col>
    </b-row>
    <b-row class="justify-content-md-center">
      <b-col cols="4">
        <p>
          <b-link to="signUp">Create an account</b-link> or
          <b-link to="passwordReset">reset password</b-link>
        </p>
      </b-col>
    </b-row>
    <b-row class="justify-content-md-center">
      <b-col cols="4">
        <v-alert />
      </b-col>
    </b-row>
  </b-container>
</template>

<script>
import Vue from "vue";
import { mapGetters } from "vuex";
import router from "@/router";
import store from "@/store";

import Alert from "@/components/auth/Alert.vue";

Vue.component("v-alert", Alert);

export default {
  data() {
    return {
      email: "",
      pass: ""
    };
  },
  computed: {
    ...mapGetters("auth", ["hasAuthenticationStatus"])
  },
  methods: {
    async signIn() {
      await store.dispatch("auth/signIn", {
        username: this.email,
        password: this.pass
      });

      if (!this.hasAuthenticationStatus) {
        router.push("dashboard");
      }
    }
  }
};
</script>

<style></style>


================================================
FILE: src/pages/auth/SignOut.vue
================================================
<template>
  <b-row class="justify-content-md-center">
    <b-col cols="8">
      <h2>Sign Out...</h2>
    </b-col>
  </b-row>
</template>

<script>
import router from "@/router";

export default {
  async created() {
    await this.$store.dispatch("auth/signOut");
    router.push("/");
  }
};
</script>


================================================
FILE: src/pages/auth/SignUp.vue
================================================
<template>
  <b-container>
    <b-row class="justify-content-md-center">
      <b-col cols="4">
        <div class="b-form-1">
          <h2>Sign Up</h2>
          <p>Sign up for an account.</p>
          <b-form @submit.prevent="signUp">
            <b-form-group label="Username:" label-for="usernameInput">
              <b-form-input
                id="usernameInput"
                type="text"
                v-model="username"
                required
                placeholder="Enter username"
              />
            </b-form-group>
            <b-form-group label="Name:" label-for="nameInput">
              <b-form-input
                id="nameInput"
                type="text"
                v-model="name"
                required
                placeholder="Enter your full name"
              />
            </b-form-group>
            <b-form-group label="Email:" label-for="emailInput">
              <b-form-input
                id="emailInput"
                type="email"
                v-model="email"
                required
                placeholder="Enter email"
              />
            </b-form-group>
            <b-form-group label="Password:" label-for="passwordInput">
              <b-form-input
                id="passwordInput"
                type="password"
                v-model="pass"
                required
                placeholder="Enter Password"
              />
            </b-form-group>
            <b-button type="submit" variant="primary">Submit</b-button>
          </b-form>
        </div>
      </b-col>
    </b-row>
    <b-row class="justify-content-md-center">
      <b-col cols="4">
        <v-alert />
      </b-col>
    </b-row>
  </b-container>
</template>

<script>
import Vue from "vue";
import router from "@/router";
import { mapGetters } from "vuex";
import Alert from "@/components/auth/Alert.vue";
import Amplify from "@aws-amplify/core";

const Logger = Amplify.Logger;

Vue.component("v-alert", Alert);

const logger = new Logger("SignUpPage");

export default {
  data() {
    return {
      username: "",
      email: "",
      name: "",
      pass: ""
    };
  },
  mounted() {
    // clear existing status message
    this.$store.dispatch("auth/clearAuthenticationStatus");
  },
  computed: {
    ...mapGetters("auth", ["hasAuthenticationStatus"])
  },
  methods: {
    async signUp() {
      logger.debug("sign-up");
      await this.$store.dispatch("auth/signUp", {
        username: this.username,
        password: this.pass,
        attributes: {
          name: this.name,
          email: this.email
        }
      });

      if (!this.hasAuthenticationStatus) {
        router.push("confirmSignUp");
      }
    }
  }
};
</script>


================================================
FILE: src/router/index.js
================================================
import Vue from "vue";
import Router from "vue-router";
import Home from "@/pages/Home.vue";
import Dashboard from "@/pages/Dashboard.vue";
import SignIn from "@/pages/auth/SignIn.vue";
import SignUp from "@/pages/auth/SignUp.vue";
import SignOut from "@/pages/auth/SignOut.vue";
import ConfirmSignUp from "@/pages/auth/ConfirmSignUp.vue";
import PasswordReset from "@/pages/auth/PasswordReset.vue";
import ChangePassword from "@/pages/auth/ChangePassword.vue";
import ConfirmPasswordReset from "@/pages/auth/ConfirmPasswordReset.vue";

import store from "@/store";

Vue.use(Router);

const routes = [
  {
    path: "/",
    name: "home",
    component: Home,
    meta: { title: "Home", auth: false }
  },
  {
    path: "/dashboard",
    name: "dashboard",
    component: Dashboard,
    meta: { title: "Dashboard", auth: true }
  },
  {
    path: "/signIn",
    name: "signIn",
    component: SignIn,
    meta: { title: "Sign In", auth: false }
  },
  {
    path: "/signOut",
    name: "signOut",
    component: SignOut,
    meta: { title: "Sign Out", auth: true }
  },
  {
    path: "/signUp",
    name: "signUp",
    component: SignUp,
    meta: { title: "Sign Up", auth: false }
  },
  {
    path: "/confirmSignUp",
    name: "confirmSignUp",
    component: ConfirmSignUp,
    meta: { title: "Confirm SignUp", auth: false }
  },
  {
    path: "/changePassword",
    name: "changePassword",
    component: ChangePassword,
    meta: { title: "Change Password", auth: true }
  },
  {
    path: "/passwordReset",
    name: "passwordReset",
    component: PasswordReset,
    meta: { title: "Password Reset", auth: false }
  },
  {
    path: "/confirmPasswordReset",
    name: "confirmPasswordReset",
    component: ConfirmPasswordReset,
    meta: { title: "Confirm Password Reset", auth: false }
  }
];

const router = new Router({ mode: "history", routes });

// this routine will ensure that any pages marked as `auth` in the `meta` section are
// protected from access by unauthenticated users.
router.beforeEach((to, from, next) => {
  // Use the page's router title to name the page
  if (to.meta && to.meta.title) {
    document.title = to.meta.title;
  }

  // is there a meta and auth attribute?
  if (to.meta && to.meta.auth !== undefined) {
    // if the page requires auth
    if (to.meta.auth) {
      // and we are authenticated?
      if (store.getters["auth/isAuthenticated"]) {
        next(); // route normally
        return;
      }
      // otherwise off to the sign in page
      router.push({ name: "signIn" });
      return;
    }
    // otherwise are we already authenticated?
    if (store.getters["auth/isAuthenticated"]) {
      // yes we are, so off to dashboard
      router.push({ name: "dashboard" });
      return;
    }
    next(); // route normally
    return;
  }
  next(); // route normally
  return;
});

export default router;


================================================
FILE: src/store/index.js
================================================
import Vue from "vue";
import Vuex from "vuex";
import createPersist from "vuex-localstorage";

Vue.use(Vuex);

// Modules
import auth from "./modules/auth";

const debug = process.env.NODE_ENV !== "production";

const store = new Vuex.Store({
  modules: {
    auth
  },
  strict: debug,
  plugins: [
    createPersist({
      namespace: "cognito-vue-bootstrap",
      initialState: {},
      // ONE_WEEK
      expires: 7 * 24 * 60 * 60 * 1e3
    })
  ]
});

export default store;


================================================
FILE: src/store/modules/auth.js
================================================
import Auth from "@aws-amplify/auth";
import Amplify from "@aws-amplify/core";

const Logger = Amplify.Logger;
Logger.LOG_LEVEL = "DEBUG"; // to show detailed logs from Amplify library
const logger = new Logger("store:auth");

// initial state
const state = {
  user: null,
  isAuthenticated: false,
  authenticationStatus: null
};

const getters = {
  authenticatedUser: state => state.user,
  isAuthenticated: state => state.isAuthenticated,
  authenticationStatus: state => {
    return state.authenticationStatus
      ? state.authenticationStatus
      : { variant: "secondary" };
  },
  hasAuthenticationStatus: state => {
    return !!state.authenticationStatus;
  }
};

const mutations = {
  setAuthenticationError(state, err) {
    logger.debug("auth error: {}", err);
    state.authenticationStatus = {
      state: "failed",
      message: err.message,
      variant: "danger"
    };
  },
  clearAuthenticationStatus: state => {
    state.authenticationStatus = null;
  },
  setUserAuthenticated(state, user) {
    state.user = user;
    state.isAuthenticated = true;
  },
  clearAuthentication(state) {
    state.user = null;
    state.userId = null;
    state.isAuthenticated = false;
  }
};

const actions = {
  clearAuthenticationStatus: context => {
    context.commit("clearAuthenticationStatus", null);
  },
  signIn: async (context, params) => {
    logger.debug("signIn for {}", params.username);
    context.commit("auth/clearAuthenticationStatus", null, { root: true });
    try {
      const user = await Auth.signIn(params.username, params.password);
      context.commit("setUserAuthenticated", user);
    } catch (err) {
      context.commit("auth/setAuthenticationError", err, { root: true });
    }
  },
  signOut: async context => {
    try {
      await Auth.signOut();
    } catch (err) {
      logger.error("error during sign out: {}", err);
    }
    context.commit("auth/clearAuthentication", null, { root: true });
  },
  signUp: async (context, params) => {
    context.commit("auth/clearAuthenticationStatus", null, { root: true });
    try {
      await Auth.signUp(params);
      context.commit("auth/clearAuthentication", null, { root: true });
    } catch (err) {
      context.commit("auth/setAuthenticationError", err, { root: true });
    }
  },
  confirmSignUp: async (context, params) => {
    logger.debug("confirm signup for {}", params.username);
    context.commit("auth/clearAuthenticationStatus", null, { root: true });
    try {
      await Auth.confirmSignUp(params.username, params.code);
    } catch (err) {
      context.commit("auth/setAuthenticationError", err, { root: true });
    }
  },
  confirmResend: async (context, params) => {
    context.commit("auth/clearAuthenticationStatus", null, { root: true });
    try {
      await Auth.resendSignUp(params.username);
    } catch (err) {
      context.commit("auth/setAuthenticationError", err, { root: true });
    }
  },
  passwordReset: async (context, params) => {
    context.commit("auth/clearAuthenticationStatus", null, { root: true });
    try {
      await Auth.forgotPassword(params.username);
    } catch (err) {
      context.commit("auth/setAuthenticationError", err, { root: true });
    }
  },
  confirmPasswordReset: async (context, params) => {
    context.commit("auth/clearAuthenticationStatus", null, { root: true });
    try {
      await Auth.forgotPasswordSubmit(
        params.username,
        params.code,
        params.password
      );
    } catch (err) {
      context.commit("auth/setAuthenticationError", err, { root: true });
    }
  },
  passwordResetResend: async (context, params) => {
    context.commit("auth/clearAuthenticationStatus", null, { root: true });
    try {
      await Auth.passwordResetResend(params.username);
    } catch (err) {
      context.commit("auth/setAuthenticationError", err, { root: true });
    }
  },
  passwordChange: async (context, params) => {
    logger.debug("password change for {}", context.state.user.username);
    context.commit("auth/clearAuthenticationStatus", null, { root: true });
    try {
      const user = await Auth.currentAuthenticatedUser();
      await Auth.changePassword(
        user,
        params.currentPassword,
        params.newPassword
      );
    } catch (err) {
      context.commit("auth/setAuthenticationError", err, { root: true });
    }
  }
};

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations
};


================================================
FILE: tests/unit/footer.spec.js
================================================
import { render } from '@testing-library/vue'
import Footer from "@/components/Footer.vue";

describe("Footer.vue", () => {
  it("renders props.msg when passed", () => {
    const { getByText } = render(Footer)
    getByText('© 2018 Company, Inc.')
  });
});


================================================
FILE: vue.config.js
================================================
// vue.config.js
module.exports = {
  transpileDependencies: [/\bvue-awesome\b/]
};
Download .txt
gitextract_a2ppqcxr/

├── .browserslistrc
├── .eslintrc.js
├── .github/
│   └── workflows/
│       └── nodejs.yml
├── .gitignore
├── .nvmrc
├── LICENSE.md
├── Makefile
├── README.md
├── babel.config.js
├── jest.config.js
├── package.json
├── postcss.config.js
├── public/
│   └── index.html
├── src/
│   ├── App.vue
│   ├── aws-exports.js
│   ├── components/
│   │   ├── Footer.vue
│   │   ├── Menu.vue
│   │   └── auth/
│   │       └── Alert.vue
│   ├── main.js
│   ├── pages/
│   │   ├── Dashboard.vue
│   │   ├── Home.vue
│   │   └── auth/
│   │       ├── ChangePassword.vue
│   │       ├── ConfirmPasswordReset.vue
│   │       ├── ConfirmSignUp.vue
│   │       ├── PasswordReset.vue
│   │       ├── SignIn.vue
│   │       ├── SignOut.vue
│   │       └── SignUp.vue
│   ├── router/
│   │   └── index.js
│   └── store/
│       ├── index.js
│       └── modules/
│           └── auth.js
├── tests/
│   └── unit/
│       └── footer.spec.js
└── vue.config.js
Download .txt
SYMBOL INDEX (3 symbols across 1 files)

FILE: src/store/modules/auth.js
  method setAuthenticationError (line 29) | setAuthenticationError(state, err) {
  method setUserAuthenticated (line 40) | setUserAuthenticated(state, user) {
  method clearAuthentication (line 44) | clearAuthentication(state) {
Condensed preview — 33 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (39K chars).
[
  {
    "path": ".browserslistrc",
    "chars": 21,
    "preview": "> 1%\nlast 2 versions\n"
  },
  {
    "path": ".eslintrc.js",
    "chars": 513,
    "preview": "module.exports = {\n  root: true,\n  env: {\n    node: true\n  },\n  extends: [\"plugin:vue/essential\", \"@vue/prettier\"],\n  ru"
  },
  {
    "path": ".github/workflows/nodejs.yml",
    "chars": 473,
    "preview": "name: Node CI\n\non: [push]\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    strategy:\n      matrix:\n        node-version:"
  },
  {
    "path": ".gitignore",
    "chars": 271,
    "preview": ".DS_Store\nnode_modules\n/dist\n\n# local env files\n.env.local\n.env.*.local\n\n# Log files\nnpm-debug.log*\nyarn-debug.log*\nyarn"
  },
  {
    "path": ".nvmrc",
    "chars": 3,
    "preview": "10\n"
  },
  {
    "path": "LICENSE.md",
    "chars": 581,
    "preview": "   Copyright 2018 Mark Wolfe\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this"
  },
  {
    "path": "Makefile",
    "chars": 231,
    "preview": "ci: clean build deploy\n\nclean:\n\trm -rf dist\n\nbuild:\n\tyarn build\n\ndeploy:\n\taws s3 sync dist/ s3://$(S3_HOSTING_BUCKET)/ -"
  },
  {
    "path": "README.md",
    "chars": 3404,
    "preview": "# cognito-vue-bootstrap\n\nThis application illustrates how to use the [Amazon Amplify](https://github.com/aws/aws-amplify"
  },
  {
    "path": "babel.config.js",
    "chars": 66,
    "preview": "module.exports = {\n  presets: [\"@vue/cli-plugin-babel/preset\"]\n};\n"
  },
  {
    "path": "jest.config.js",
    "chars": 60,
    "preview": "module.exports = {\n  preset: \"@vue/cli-plugin-unit-jest\"\n};\n"
  },
  {
    "path": "package.json",
    "chars": 1119,
    "preview": "{\n  \"name\": \"cognito-vue-bootstrap\",\n  \"version\": \"0.1.0\",\n  \"private\": true,\n  \"scripts\": {\n    \"serve\": \"vue-cli-servi"
  },
  {
    "path": "postcss.config.js",
    "chars": 60,
    "preview": "module.exports = {\n  plugins: {\n    autoprefixer: {}\n  }\n};\n"
  },
  {
    "path": "public/index.html",
    "chars": 573,
    "preview": "<!DOCTYPE html>\n<html>\n  <head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n   "
  },
  {
    "path": "src/App.vue",
    "chars": 1026,
    "preview": "<template>\n  <div id=\"app\">\n    <b-container class=\"main\" fluid>\n      <v-menu />\n      <router-view />\n      <v-footer "
  },
  {
    "path": "src/aws-exports.js",
    "chars": 621,
    "preview": "const config = {\n  // To get the AWS Credentials, you need to configure\n  // the Auth module with your Cognito Federated"
  },
  {
    "path": "src/components/Footer.vue",
    "chars": 441,
    "preview": "<template>\n  <footer class=\"bd-footer\">\n    <b-container>\n      <b-row class=\"justify-content-md-center\">\n        <div c"
  },
  {
    "path": "src/components/Menu.vue",
    "chars": 2122,
    "preview": "<template>\n  <b-navbar toggleable=\"md\" type=\"dark\">\n    <b-navbar-toggle target=\"nav_collapse\" />\n    <b-navbar-brand to"
  },
  {
    "path": "src/components/auth/Alert.vue",
    "chars": 457,
    "preview": "<template>\n  <b-alert\n    :show=\"hasAuthenticationStatus\"\n    :variant=\"authenticationStatus.variant\"\n    >{{ authentica"
  },
  {
    "path": "src/main.js",
    "chars": 390,
    "preview": "import Vue from \"vue\";\nimport BootstrapVue from \"bootstrap-vue\";\nimport App from \"@/App.vue\";\nimport router from \"@/rout"
  },
  {
    "path": "src/pages/Dashboard.vue",
    "chars": 346,
    "preview": "<template>\n  <b-container>\n    <div class=\"b-main-content\">\n      <h2>Cognito Bootstrap Vue</h2>\n      <p>You are logged"
  },
  {
    "path": "src/pages/Home.vue",
    "chars": 1224,
    "preview": "<template>\n  <b-container>\n    <div class=\"b-main-content\">\n      <h2>Cognito Bootstrap Vue</h2>\n      <p>\n        This "
  },
  {
    "path": "src/pages/auth/ChangePassword.vue",
    "chars": 1953,
    "preview": "<template>\n  <b-container>\n    <b-row class=\"justify-content-md-center\">\n      <b-col cols=\"4\">\n        <div class=\"b-fo"
  },
  {
    "path": "src/pages/auth/ConfirmPasswordReset.vue",
    "chars": 2470,
    "preview": "<template>\n  <b-container>\n    <b-row class=\"justify-content-md-center\">\n      <b-col cols=\"4\">\n        <div class=\"b-fo"
  },
  {
    "path": "src/pages/auth/ConfirmSignUp.vue",
    "chars": 1940,
    "preview": "<template>\n  <b-container>\n    <b-row class=\"justify-content-md-center\">\n      <b-col cols=\"4\">\n        <div class=\"b-fo"
  },
  {
    "path": "src/pages/auth/PasswordReset.vue",
    "chars": 1502,
    "preview": "<template>\n  <b-container>\n    <b-row class=\"justify-content-md-center\">\n      <b-col cols=\"4\">\n        <div class=\"b-fo"
  },
  {
    "path": "src/pages/auth/SignIn.vue",
    "chars": 2014,
    "preview": "<template>\n  <b-container>\n    <b-row class=\"justify-content-md-center\">\n      <b-col cols=\"4\">\n        <div class=\"b-fo"
  },
  {
    "path": "src/pages/auth/SignOut.vue",
    "chars": 305,
    "preview": "<template>\n  <b-row class=\"justify-content-md-center\">\n    <b-col cols=\"8\">\n      <h2>Sign Out...</h2>\n    </b-col>\n  </"
  },
  {
    "path": "src/pages/auth/SignUp.vue",
    "chars": 2740,
    "preview": "<template>\n  <b-container>\n    <b-row class=\"justify-content-md-center\">\n      <b-col cols=\"4\">\n        <div class=\"b-fo"
  },
  {
    "path": "src/router/index.js",
    "chars": 2863,
    "preview": "import Vue from \"vue\";\nimport Router from \"vue-router\";\nimport Home from \"@/pages/Home.vue\";\nimport Dashboard from \"@/pa"
  },
  {
    "path": "src/store/index.js",
    "chars": 481,
    "preview": "import Vue from \"vue\";\nimport Vuex from \"vuex\";\nimport createPersist from \"vuex-localstorage\";\n\nVue.use(Vuex);\n\n// Modul"
  },
  {
    "path": "src/store/modules/auth.js",
    "chars": 4451,
    "preview": "import Auth from \"@aws-amplify/auth\";\nimport Amplify from \"@aws-amplify/core\";\n\nconst Logger = Amplify.Logger;\nLogger.LO"
  },
  {
    "path": "tests/unit/footer.spec.js",
    "chars": 259,
    "preview": "import { render } from '@testing-library/vue'\nimport Footer from \"@/components/Footer.vue\";\n\ndescribe(\"Footer.vue\", () ="
  },
  {
    "path": "vue.config.js",
    "chars": 84,
    "preview": "// vue.config.js\nmodule.exports = {\n  transpileDependencies: [/\\bvue-awesome\\b/]\n};\n"
  }
]

About this extraction

This page contains the full source code of the wolfeidau/cognito-vue-bootstrap GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 33 files (34.2 KB), approximately 9.5k tokens, and a symbol index with 3 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!