├── .gitignore ├── LICENSE ├── README.md ├── authentication └── email │ ├── .editorconfig │ ├── .env │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── .postcssrc.js │ ├── .stylintrc │ ├── README.md │ ├── babel.config.js │ ├── jsconfig.json │ ├── package.json │ ├── public │ ├── app-logo-128x128.png │ ├── fp-logo.png │ └── icons │ │ ├── apple-icon-120x120.png │ │ ├── apple-icon-152x152.png │ │ ├── apple-icon-167x167.png │ │ ├── apple-icon-180x180.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── favicon.ico │ │ ├── icon-128x128.png │ │ ├── icon-192x192.png │ │ ├── icon-256x256.png │ │ ├── icon-384x384.png │ │ ├── icon-512x512.png │ │ ├── ms-icon-144x144.png │ │ └── safari-pinned-tab.svg │ ├── quasar.conf.js │ └── src │ ├── App.vue │ ├── assets │ ├── firebase-icon.png │ ├── quasar-logo-full.svg │ ├── sad.svg │ └── sample-app-logo.png │ ├── boot │ └── firebaseConnection.js │ ├── components │ └── .gitkeep │ ├── css │ ├── app.styl │ └── quasar.variables.styl │ ├── index.template.html │ ├── layouts │ └── MainLayout.vue │ ├── pages │ ├── Auth.vue │ ├── Error404.vue │ ├── ForgotPassword.vue │ ├── Index.vue │ └── User.vue │ ├── router │ ├── index.js │ └── routes.js │ ├── services │ └── firebase │ │ ├── base.js │ │ ├── email.js │ │ └── index.js │ ├── store │ ├── auth │ │ ├── actions.js │ │ ├── getters.js │ │ ├── index.js │ │ ├── mutations.js │ │ └── state.js │ ├── index.js │ └── store-flag.d.ts │ └── utils │ └── environmentConfig.js ├── base ├── .editorconfig ├── .env ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .postcssrc.js ├── .stylintrc ├── README.md ├── babel.config.js ├── jsconfig.json ├── package.json ├── public │ ├── app-logo-128x128.png │ └── icons │ │ ├── apple-icon-120x120.png │ │ ├── apple-icon-152x152.png │ │ ├── apple-icon-167x167.png │ │ ├── apple-icon-180x180.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── favicon.ico │ │ ├── icon-128x128.png │ │ ├── icon-192x192.png │ │ ├── icon-256x256.png │ │ ├── icon-384x384.png │ │ ├── icon-512x512.png │ │ ├── ms-icon-144x144.png │ │ └── safari-pinned-tab.svg ├── quasar.conf.js └── src │ ├── App.vue │ ├── assets │ ├── firebase-icon.png │ ├── quasar-logo-full.svg │ ├── sad.svg │ └── sample-app-logo.png │ ├── boot │ └── firebaseConnection.js │ ├── components │ └── .gitkeep │ ├── css │ ├── app.styl │ └── quasar.variables.styl │ ├── index.template.html │ ├── layouts │ └── MainLayout.vue │ ├── pages │ ├── Error404.vue │ └── Index.vue │ ├── router │ ├── index.js │ └── routes.js │ ├── services │ └── firebase │ │ ├── base.js │ │ └── index.js │ └── utils │ └── environmentConfig.js ├── data └── profile │ ├── .editorconfig │ ├── .env │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── .postcssrc.js │ ├── .stylintrc │ ├── README.md │ ├── babel.config.js │ ├── jsconfig.json │ ├── package.json │ ├── public │ ├── app-logo-128x128.png │ ├── fp-logo.png │ └── icons │ │ ├── apple-icon-120x120.png │ │ ├── apple-icon-152x152.png │ │ ├── apple-icon-167x167.png │ │ ├── apple-icon-180x180.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── favicon.ico │ │ ├── icon-128x128.png │ │ ├── icon-192x192.png │ │ ├── icon-256x256.png │ │ ├── icon-384x384.png │ │ ├── icon-512x512.png │ │ ├── ms-icon-144x144.png │ │ └── safari-pinned-tab.svg │ ├── quasar.conf.js │ └── src │ ├── App.vue │ ├── assets │ ├── quasar-logo-full.svg │ ├── sad.svg │ └── sample-app-logo.png │ ├── boot │ └── firebaseConnection.js │ ├── components │ └── FBQUploader.vue │ ├── css │ ├── app.styl │ └── quasar.variables.styl │ ├── index.template.html │ ├── layouts │ ├── Basic.vue │ └── User.vue │ ├── models │ └── User.js │ ├── pages │ ├── Auth.vue │ ├── Error404.vue │ ├── ForgotPassword.vue │ ├── Index.vue │ └── user │ │ ├── Profile.vue │ │ └── profile │ │ └── UserSettings.vue │ ├── router │ ├── index.js │ └── routes.js │ ├── services │ └── firebase │ │ ├── base.js │ │ ├── db.js │ │ ├── email.js │ │ └── index.js │ ├── store │ ├── auth │ │ ├── actions.js │ │ ├── getters.js │ │ ├── index.js │ │ ├── mutations.js │ │ └── state.js │ ├── index.js │ ├── store-flag.d.ts │ └── user │ │ ├── actions.js │ │ ├── getters.js │ │ ├── index.js │ │ ├── mutations.js │ │ └── state.js │ └── utils │ └── environmentConfig.js └── jsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .Thumbs.db 3 | debug.log 4 | **/node_modules 5 | 6 | # Editor directories and files 7 | .idea 8 | .vscode 9 | *.suo 10 | *.ntvs* 11 | *.njsproj 12 | *.sln 13 | *.sublime* 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Quasar Framework 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # **Quasar-Firebase Sample Apps**: 2 | A working repository to highlight and show the integration of Google's Firebase services with in the Quasar framework. Each concept will be siloed with in its own application to focus on the scope of the implementation. If an example doesn't highlight a need or sepecific concern with in its scope please consider researching in our discord *#firebase* channel within the backend api grouping or post a question on our forum. 3 | 4 | Each application is meant to be considered in conjunction with the dev.to blog post series Quasar-Firebase. 5 | 6 | ## **Applications** 7 | ### **Base Implementation** 8 | - Firebase Initialization 9 | - Base Service & Structure 10 | ### **Email Authentication** 11 | - Create and log in users via Email & Password 12 | ### **Data Integration** 13 | - User Profile 14 | - Vuexfire 15 | - QUploader to Google Cloud Storage 16 | -------------------------------------------------------------------------------- /authentication/email/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /authentication/email/.env: -------------------------------------------------------------------------------- 1 | # DEVELOPMENT FIREBASE CONFIG 2 | DEV_API_KEY=AIzaSyA9-quFJzkM0qFuDQ30ecVVU6keefrzaFk 3 | DEV_AUTH_DOMAIN=quasar-firebase-38b4d.firebaseapp.com 4 | DEV_DATA_BASE_URLL=https://quasar-firebase-38b4d.firebaseio.com 5 | DEV_PROJECT_ID=quasar-firebase-38b4d 6 | DEV_STORAGE_BUCKET=quasar-firebase-38b4d.appspot.com 7 | DEV_MESSAGING_SENDER_ID=395306140214 8 | DEV_APP_ID=1:395306140214:web:6deafabd6e3147adb3ce97 9 | DEV_MEASUREMENT_ID=G-1FSVX8P8D 10 | 11 | # STAGING FIREBASE CONFIG 12 | # PROUDCTION FIREBASE CONFIG -------------------------------------------------------------------------------- /authentication/email/.eslintignore: -------------------------------------------------------------------------------- 1 | /dist 2 | -------------------------------------------------------------------------------- /authentication/email/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | 4 | parserOptions: { 5 | parser: 'babel-eslint', 6 | sourceType: 'module' 7 | }, 8 | 9 | env: { 10 | browser: true 11 | }, 12 | 13 | extends: [ 14 | // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention 15 | // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules. 16 | 'plugin:vue/essential', 17 | '@vue/standard' 18 | ], 19 | 20 | // required to lint *.vue files 21 | plugins: [ 22 | 'vue' 23 | ], 24 | 25 | globals: { 26 | 'ga': true, // Google Analytics 27 | 'cordova': true, 28 | '__statics': true, 29 | 'process': true, 30 | 'Capacitor': true 31 | }, 32 | 33 | // add your custom rules here 34 | rules: { 35 | // allow async-await 36 | 'generator-star-spacing': 'off', 37 | // allow paren-less arrow functions 38 | 'arrow-parens': 'off', 39 | 'one-var': 'off', 40 | 41 | 'import/first': 'off', 42 | 'import/named': 'error', 43 | 'import/namespace': 'error', 44 | 'import/default': 'error', 45 | 'import/export': 'error', 46 | 'import/extensions': 'off', 47 | 'import/no-unresolved': 'off', 48 | 'import/no-extraneous-dependencies': 'off', 49 | 'prefer-promise-reject-errors': 'off', 50 | 51 | // allow console.log during development only 52 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 53 | // allow debugger during development only 54 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /authentication/email/.gitignore: -------------------------------------------------------------------------------- 1 | .quasar 2 | .DS_Store 3 | .thumbs.db 4 | node_modules 5 | /dist 6 | /src-cordova/node_modules 7 | /src-cordova/platforms 8 | /src-cordova/plugins 9 | /src-cordova/www 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | -------------------------------------------------------------------------------- /authentication/email/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | plugins: [ 5 | // to edit target browsers: use "browserslist" field in package.json 6 | require('autoprefixer') 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /authentication/email/.stylintrc: -------------------------------------------------------------------------------- 1 | { 2 | "blocks": "never", 3 | "brackets": "never", 4 | "colons": "never", 5 | "colors": "always", 6 | "commaSpace": "always", 7 | "commentSpace": "always", 8 | "cssLiteral": "never", 9 | "depthLimit": false, 10 | "duplicates": true, 11 | "efficient": "always", 12 | "extendPref": false, 13 | "globalDupe": true, 14 | "indentPref": 2, 15 | "leadingZero": "never", 16 | "maxErrors": false, 17 | "maxWarnings": false, 18 | "mixed": false, 19 | "namingConvention": false, 20 | "namingConventionStrict": false, 21 | "none": "never", 22 | "noImportant": false, 23 | "parenSpace": "never", 24 | "placeholder": false, 25 | "prefixVarsWithDollar": "always", 26 | "quotePref": "single", 27 | "semicolons": "never", 28 | "sortOrder": false, 29 | "stackedProperties": "never", 30 | "trailingWhitespace": "never", 31 | "universal": "never", 32 | "valid": true, 33 | "zeroUnits": "never", 34 | "zIndexNormalize": false 35 | } 36 | -------------------------------------------------------------------------------- /authentication/email/README.md: -------------------------------------------------------------------------------- 1 | # Firebase Sample App: Email 2 | Email authentication implementation with Firebase 3 | 4 | ## Install the dependencies 5 | ```bash 6 | yarn 7 | ``` 8 | 9 | ### Start the app in development mode (hot-code reloading, error reporting, etc.) 10 | 11 | ```bash 12 | npm run dev 13 | or 14 | 15 | yarn run dev 16 | ``` 17 | 18 | Windwos users run: 19 | ```bash 20 | npm run dev:win 21 | 22 | or 23 | 24 | yarn run dev:win 25 | ``` 26 | 27 | ### Areas of focus 28 | 29 | - `firebaseConnetion.js` enhancement 30 | - Firebase service, `base.js` enhancements 31 | - Update User Creation Flow 32 | - User Profile with Vuexfire 33 | - Update User info 34 | -------------------------------------------------------------------------------- /authentication/email/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@quasar/babel-preset-app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /authentication/email/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "src/*": [ 6 | "src/*" 7 | ], 8 | "app/*": [ 9 | "*" 10 | ], 11 | "components/*": [ 12 | "src/components/*" 13 | ], 14 | "layouts/*": [ 15 | "src/layouts/*" 16 | ], 17 | "pages/*": [ 18 | "src/pages/*" 19 | ], 20 | "assets/*": [ 21 | "src/assets/*" 22 | ], 23 | "boot/*": [ 24 | "src/boot/*" 25 | ], 26 | "vue$": [ 27 | "node_modules/vue/dist/vue.esm.js" 28 | ] 29 | } 30 | }, 31 | "exclude": [ 32 | "dist", 33 | ".quasar", 34 | "node_modules" 35 | ] 36 | } -------------------------------------------------------------------------------- /authentication/email/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "email", 3 | "version": "0.0.1", 4 | "description": "Email authentication implementation with Firebase", 5 | "productName": "Firebase Sample App: Email Authentication", 6 | "author": "Adam K. Purdy ", 7 | "private": true, 8 | "scripts": { 9 | "dev": "QENV=DEV quasar dev", 10 | "dev:win": "cross-env QENV=DEV quasar dev", 11 | "lint": "eslint --ext .js,.vue src", 12 | "test": "echo \"No test specified\" && exit 0" 13 | }, 14 | "dependencies": { 15 | "@quasar/extras": "^1.10.7", 16 | "axios": "^0.21.1", 17 | "core-js": "^3.8.3", 18 | "firebase": "^8.2.4", 19 | "quasar": "^1.15.21" 20 | }, 21 | "devDependencies": { 22 | "@quasar/app": "^2.2.10", 23 | "@vue/eslint-config-standard": "^6.0.0", 24 | "babel-eslint": "^10.0.1", 25 | "cross-env": "^7.0.3", 26 | "dotenv": "^8.2.0", 27 | "eslint": "^7.18.0", 28 | "eslint-config-standard": "^16.0.2", 29 | "eslint-loader": "^4.0.2", 30 | "eslint-plugin-import": "^2.22.1", 31 | "eslint-plugin-node": "^11.1.0", 32 | "eslint-plugin-promise": "^4.2.1", 33 | "eslint-plugin-vue": "^7.5.0" 34 | }, 35 | "engines": { 36 | "node": ">= 8.9.0", 37 | "npm": ">= 5.6.0", 38 | "yarn": ">= 1.6.0" 39 | }, 40 | "browserslist": [ 41 | "last 10 Chrome versions", 42 | "last 10 Firefox versions", 43 | "last 4 Edge versions", 44 | "last 7 Safari versions", 45 | "last 8 Android versions", 46 | "last 8 ChromeAndroid versions", 47 | "last 8 FirefoxAndroid versions", 48 | "last 10 iOS versions", 49 | "last 5 Opera versions" 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /authentication/email/public/app-logo-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/app-logo-128x128.png -------------------------------------------------------------------------------- /authentication/email/public/fp-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/fp-logo.png -------------------------------------------------------------------------------- /authentication/email/public/icons/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/icons/apple-icon-120x120.png -------------------------------------------------------------------------------- /authentication/email/public/icons/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/icons/apple-icon-152x152.png -------------------------------------------------------------------------------- /authentication/email/public/icons/apple-icon-167x167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/icons/apple-icon-167x167.png -------------------------------------------------------------------------------- /authentication/email/public/icons/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/icons/apple-icon-180x180.png -------------------------------------------------------------------------------- /authentication/email/public/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/icons/favicon-16x16.png -------------------------------------------------------------------------------- /authentication/email/public/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/icons/favicon-32x32.png -------------------------------------------------------------------------------- /authentication/email/public/icons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/icons/favicon-96x96.png -------------------------------------------------------------------------------- /authentication/email/public/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/icons/favicon.ico -------------------------------------------------------------------------------- /authentication/email/public/icons/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/icons/icon-128x128.png -------------------------------------------------------------------------------- /authentication/email/public/icons/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/icons/icon-192x192.png -------------------------------------------------------------------------------- /authentication/email/public/icons/icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/icons/icon-256x256.png -------------------------------------------------------------------------------- /authentication/email/public/icons/icon-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/icons/icon-384x384.png -------------------------------------------------------------------------------- /authentication/email/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /authentication/email/public/icons/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/public/icons/ms-icon-144x144.png -------------------------------------------------------------------------------- /authentication/email/public/icons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /authentication/email/quasar.conf.js: -------------------------------------------------------------------------------- 1 | // Configuration for your app 2 | // https://quasar.dev/quasar-cli/quasar-conf-js 3 | const enviromentConfiguration = require('./src/utils/environmentConfig.js') 4 | module.exports = function (ctx) { 5 | return { 6 | // app boot file (/src/boot) 7 | // --> boot files are part of "main.js" 8 | // https://quasar.dev/quasar-cli/cli-documentation/boot-files 9 | boot: [ 10 | 'firebaseConnection' 11 | ], 12 | 13 | // https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-css 14 | css: [ 15 | 'app.styl' 16 | ], 17 | 18 | // https://github.com/quasarframework/quasar/tree/dev/extras 19 | extras: [ 20 | // 'ionicons-v4', 21 | // 'mdi-v4', 22 | // 'fontawesome-v5', 23 | // 'eva-icons', 24 | // 'themify', 25 | // 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both! 26 | 27 | 'roboto-font', // optional, you are not bound to it 28 | 'material-icons' // optional, you are not bound to it 29 | ], 30 | 31 | // https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-framework 32 | framework: { 33 | // iconSet: 'ionicons-v4', // Quasar icon set 34 | // lang: 'de', // Quasar language pack 35 | 36 | // Possible values for "all": 37 | // * 'auto' - Auto-import needed Quasar components & directives 38 | // (slightly higher compile time; next to minimum bundle size; most convenient) 39 | // * false - Manually specify what to import 40 | // (fastest compile time; minimum bundle size; most tedious) 41 | // * true - Import everything from Quasar 42 | // (not treeshaking Quasar; biggest bundle size; convenient) 43 | importStrategy: 'auto', 44 | 45 | components: [], 46 | directives: [], 47 | 48 | // Quasar plugins 49 | plugins: ['Loading', 'Notify'] 50 | }, 51 | 52 | // https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-build 53 | build: { 54 | scopeHoisting: true, 55 | // vueRouterMode: 'history', 56 | // showProgress: false, 57 | // gzip: true, 58 | // analyze: true, 59 | // preloadChunks: false, 60 | // extractCSS: false, 61 | 62 | // https://quasar.dev/quasar-cli/cli-documentation/handling-webpack 63 | extendWebpack (cfg) { 64 | cfg.module.rules.push({ 65 | enforce: 'pre', 66 | test: /\.(js|vue)$/, 67 | loader: 'eslint-loader', 68 | exclude: /node_modules/, 69 | options: { 70 | formatter: require('eslint').CLIEngine.getFormatter('stylish') 71 | } 72 | }) 73 | }, 74 | env: { 75 | QENV: enviromentConfiguration(process.env.QENV) 76 | } 77 | }, 78 | 79 | // https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-devServer 80 | devServer: { 81 | // https: true, 82 | // port: 8080, 83 | open: true // opens browser window automatically 84 | }, 85 | 86 | // animations: 'all', // --- includes all animations 87 | // https://quasar.dev/options/animations 88 | animations: [], 89 | 90 | // https://quasar.dev/quasar-cli/developing-ssr/configuring-ssr 91 | ssr: { 92 | pwa: false 93 | }, 94 | 95 | // https://quasar.dev/quasar-cli/developing-pwa/configuring-pwa 96 | pwa: { 97 | // workboxPluginMode: 'InjectManifest', 98 | // workboxOptions: {}, // only for NON InjectManifest 99 | manifest: { 100 | // name: 'Firebase Sample App: Email', 101 | // short_name: 'Firebase Sample App: Email', 102 | // description: 'Email authentication implementation with Firebase', 103 | display: 'standalone', 104 | orientation: 'portrait', 105 | background_color: '#ffffff', 106 | theme_color: '#027be3', 107 | icons: [ 108 | { 109 | src: 'icons/icon-128x128.png', 110 | sizes: '128x128', 111 | type: 'image/png' 112 | }, 113 | { 114 | src: 'icons/icon-192x192.png', 115 | sizes: '192x192', 116 | type: 'image/png' 117 | }, 118 | { 119 | src: 'icons/icon-256x256.png', 120 | sizes: '256x256', 121 | type: 'image/png' 122 | }, 123 | { 124 | src: 'icons/icon-384x384.png', 125 | sizes: '384x384', 126 | type: 'image/png' 127 | }, 128 | { 129 | src: 'icons/icon-512x512.png', 130 | sizes: '512x512', 131 | type: 'image/png' 132 | } 133 | ] 134 | } 135 | }, 136 | 137 | // https://quasar.dev/quasar-cli/developing-cordova-apps/configuring-cordova 138 | cordova: { 139 | // id: 'org.cordova.quasar.app', 140 | // noIosLegacyBuildFlag: true, // uncomment only if you know what you are doing 141 | }, 142 | 143 | // https://quasar.dev/quasar-cli/developing-electron-apps/configuring-electron 144 | electron: { 145 | // bundler: 'builder', // or 'packager' 146 | 147 | extendWebpack (cfg) { 148 | // do something with Electron main process Webpack cfg 149 | // chainWebpack also available besides this extendWebpack 150 | }, 151 | 152 | packager: { 153 | // https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options 154 | 155 | // OS X / Mac App Store 156 | // appBundleId: '', 157 | // appCategoryType: '', 158 | // osxSign: '', 159 | // protocol: 'myapp://path', 160 | 161 | // Windows only 162 | // win32metadata: { ... } 163 | }, 164 | 165 | builder: { 166 | // https://www.electron.build/configuration/configuration 167 | 168 | // appId: 'email' 169 | } 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /authentication/email/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /authentication/email/src/assets/firebase-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/src/assets/firebase-icon.png -------------------------------------------------------------------------------- /authentication/email/src/assets/sad.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /authentication/email/src/assets/sample-app-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/src/assets/sample-app-logo.png -------------------------------------------------------------------------------- /authentication/email/src/boot/firebaseConnection.js: -------------------------------------------------------------------------------- 1 | import firebaseServices from '../services/firebase' 2 | 3 | export default ({ router, store, Vue }) => { 4 | firebaseServices.fBInit(process.env.QENV.FIREBASE_CONFIG) 5 | 6 | // Tell the application what to do when the 7 | // authentication state has changed 8 | firebaseServices.auth().onAuthStateChanged((user) => { 9 | firebaseServices.handleOnAuthStateChanged(store, user) 10 | }, (error) => { 11 | console.error(error) 12 | }) 13 | 14 | Vue.prototype.$fb = firebaseServices 15 | store.$fb = firebaseServices 16 | } 17 | -------------------------------------------------------------------------------- /authentication/email/src/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/authentication/email/src/components/.gitkeep -------------------------------------------------------------------------------- /authentication/email/src/css/app.styl: -------------------------------------------------------------------------------- 1 | // app global css in Stylus form 2 | a 3 | color black 4 | text-decoration none 5 | 6 | .loader 7 | font-size 2em 8 | &:before 9 | opacity .9!important -------------------------------------------------------------------------------- /authentication/email/src/css/quasar.variables.styl: -------------------------------------------------------------------------------- 1 | // Quasar Stylus Variables 2 | // -------------------------------------------------- 3 | // To customize the look and feel of this app, you can override 4 | // the Stylus variables found in Quasar's source Stylus files. 5 | 6 | // Check documentation for full list of Quasar variables 7 | 8 | // Your own variables (that are declared here) and Quasar's own 9 | // ones will be available out of the box in your .vue/.styl files 10 | 11 | // It's highly recommended to change the default colors 12 | // to match your app's branding. 13 | // Tip: Use the "Theme Builder" on Quasar's documentation website. 14 | 15 | $primary = #027BE3 16 | $secondary = #26A69A 17 | $accent = #9C27B0 18 | 19 | $positive = #21BA45 20 | $negative = #C10015 21 | $info = #31CCEC 22 | $warning = #F2C037 23 | -------------------------------------------------------------------------------- /authentication/email/src/index.template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= productName %> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /authentication/email/src/layouts/MainLayout.vue: -------------------------------------------------------------------------------- 1 | 102 | 103 | 118 | -------------------------------------------------------------------------------- /authentication/email/src/pages/Auth.vue: -------------------------------------------------------------------------------- 1 | 74 | 75 | 136 | 137 | 143 | -------------------------------------------------------------------------------- /authentication/email/src/pages/Error404.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | -------------------------------------------------------------------------------- /authentication/email/src/pages/ForgotPassword.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 71 | 72 | 84 | -------------------------------------------------------------------------------- /authentication/email/src/pages/Index.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 19 | -------------------------------------------------------------------------------- /authentication/email/src/pages/User.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 19 | -------------------------------------------------------------------------------- /authentication/email/src/router/index.js: -------------------------------------------------------------------------------- 1 | import firebaseServices from '../services/firebase' 2 | import { Notify } from 'quasar' 3 | import { store } from '../store' 4 | import Vue from 'vue' 5 | import VueRouter from 'vue-router' 6 | 7 | import routes from './routes' 8 | 9 | Vue.use(VueRouter) 10 | 11 | /* 12 | * If not building with SSR mode, you can 13 | * directly export the Router instantiation 14 | */ 15 | 16 | export default function (/* { store, ssrContext } */) { 17 | const Router = new VueRouter({ 18 | scrollBehavior: () => ({ x: 0, y: 0 }), 19 | routes, 20 | 21 | // Leave these as is and change from quasar.conf.js instead! 22 | // quasar.conf.js -> build -> vueRouterMode 23 | // quasar.conf.js -> build -> publicPath 24 | mode: process.env.VUE_ROUTER_MODE, 25 | base: process.env.VUE_ROUTER_BASE 26 | }) 27 | 28 | // Setup the router to be intercepted on each route. 29 | // This allows the application to halt rendering until 30 | // Firebase is finished with its initialization process, 31 | // and handle the user accordingly 32 | Router.beforeEach(async (to, from, next) => { 33 | const { ensureAuthIsInitialized, isAuthenticated } = firebaseServices 34 | try { 35 | // Force the app to wait until Firebase has 36 | // finished its initialization, and handle the 37 | // authentication state of the user properly 38 | await ensureAuthIsInitialized(store) 39 | if (to.matched.some(record => record.meta.requiresAuth)) { 40 | if (isAuthenticated(store)) { 41 | next() 42 | } else { 43 | next('/auth/login') 44 | } 45 | } else if ((to.path === '/auth/register' && isAuthenticated(store)) || 46 | (to.path === '/auth/login' && isAuthenticated(store))) { 47 | next('/user') 48 | } else { 49 | next() 50 | } 51 | } catch (err) { 52 | Notify.create({ 53 | message: `${err}`, 54 | color: 'negative' 55 | }) 56 | } 57 | }) 58 | 59 | return Router 60 | } 61 | -------------------------------------------------------------------------------- /authentication/email/src/router/routes.js: -------------------------------------------------------------------------------- 1 | const routes = [ 2 | { 3 | path: '/', 4 | component: () => import('layouts/MainLayout.vue'), 5 | children: [ 6 | { 7 | path: '', 8 | component: () => import('pages/Index.vue') 9 | }, 10 | { 11 | path: 'user', 12 | name: 'User', 13 | component: () => import('pages/User.vue'), 14 | meta: { 15 | requiresAuth: true 16 | } 17 | } 18 | ] 19 | }, 20 | { 21 | path: '/auth', 22 | component: () => import('layouts/MainLayout.vue'), 23 | children: [ 24 | { 25 | path: 'forgotPassword', 26 | name: 'ForgotPassword', 27 | component: () => import('pages/ForgotPassword.vue') 28 | }, 29 | { 30 | path: 'login', 31 | name: 'Login', 32 | component: () => import('pages/Auth.vue') 33 | }, 34 | { 35 | path: 'register', 36 | name: 'Register', 37 | component: () => import('pages/Auth.vue') 38 | } 39 | ] 40 | } 41 | ] 42 | 43 | // Always leave this as last one 44 | routes.push({ 45 | path: '*', 46 | component: () => import('pages/Error404.vue') 47 | }) 48 | 49 | export default routes 50 | -------------------------------------------------------------------------------- /authentication/email/src/services/firebase/base.js: -------------------------------------------------------------------------------- 1 | 2 | import firebase from 'firebase/app' 3 | import 'firebase/auth' 4 | 5 | /** 6 | * Returns Firebase's auth service 7 | * https://firebase.google.com/docs/reference/js/firebase.auth.html#callable 8 | * @returns {Auth} - The Firebase Auth service interface 9 | */ 10 | export const auth = () => { 11 | return firebase.auth() 12 | } 13 | 14 | /** 15 | * Async function providing the application time to 16 | * wait for firebase to initialize and determine if a 17 | * user is authenticated or not with only a single observable. 18 | * https://firebase.google.com/docs/reference/js/firebase.auth.Auth#onauthstatechanged 19 | * @param {Object} store - Vuex store 20 | * @returns {Promise} - A promise that return firebase.Unsubscribe 21 | */ 22 | export const ensureAuthIsInitialized = async (store) => { 23 | if (store.state.auth.isReady) return true 24 | // Create the observer only once on init 25 | return new Promise((resolve, reject) => { 26 | // Use a promise to make sure that the router will eventually show the route after the auth is initialized. 27 | const unsubscribe = firebase.auth().onAuthStateChanged(user => { 28 | resolve() 29 | unsubscribe() 30 | }, () => { 31 | reject(new Error('Looks like there is a problem with the firebase service. Please try again later')) 32 | }) 33 | }) 34 | } 35 | 36 | /** 37 | * Convenience method to initialize firebase app 38 | * https://firebase.google.com/docs/reference/js/firebase?authuser=1#initializeapp 39 | * @param {Object} config - FIREBASE_CONFIG during the build process 40 | * @returns {App} - Creates and initializes a Firebase app instance. 41 | */ 42 | export const fBInit = (config) => { 43 | return firebase.initializeApp(config) 44 | } 45 | 46 | /** 47 | * Handle the auth state of the user and set it in the auth store module. 48 | * Also sets up redirection if the user loses authentication. The action 49 | * method will determine where the application routes to. 50 | * @param {Object} store - Vuex Store 51 | * @param {Object} currentUser - Firebase currentUser 52 | */ 53 | export const handleOnAuthStateChanged = async (store, currentUser) => { 54 | const initialAuthState = isAuthenticated(store) 55 | // Save to the store 56 | store.commit('auth/setAuthState', { 57 | isAuthenticated: currentUser !== null, 58 | isReady: true 59 | }) 60 | 61 | // If the user loses authentication route 62 | // them to the login page 63 | if (!currentUser && initialAuthState) { 64 | store.dispatch('auth/routeUserToAuth') 65 | } 66 | } 67 | 68 | /** 69 | * @param {Object} store - Vuex store 70 | * @return {Boolean} - isAuthenticated 71 | */ 72 | export const isAuthenticated = (store) => { 73 | return store.state.auth.isAuthenticated 74 | } 75 | 76 | /** 77 | * Removes firebase auth token 78 | * @returns {Promise} - Void 79 | */ 80 | export const logoutUser = () => { 81 | return auth().signOut() 82 | } 83 | -------------------------------------------------------------------------------- /authentication/email/src/services/firebase/email.js: -------------------------------------------------------------------------------- 1 | import firebase from 'firebase/app' 2 | import 'firebase/auth' 3 | 4 | /** 5 | * https://firebase.google.com/docs/reference/js/firebase.auth.Auth#createuserwithemailandpassword 6 | * @param {String} email - A Valid email 7 | * @param {String} password - Password 8 | * @returns {Promise} - UserCredentials https://firebase.google.com/docs/reference/js/firebase.auth#usercredential 9 | */ 10 | export const createUserWithEmail = async (email, password) => { 11 | return firebase.auth().createUserWithEmailAndPassword(email, password) 12 | } 13 | 14 | /** 15 | * https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signinwithemailandpassword 16 | * @param {String} email - A Valid email 17 | * @param {String} password - Password 18 | * @returns {Promise} - UserCredentials https://firebase.google.com/docs/reference/js/firebase.auth#usercredential 19 | */ 20 | export const loginWithEmail = (email, password) => { 21 | return firebase.auth().signInWithEmailAndPassword(email, password) 22 | } 23 | -------------------------------------------------------------------------------- /authentication/email/src/services/firebase/index.js: -------------------------------------------------------------------------------- 1 | import * as base from './base.js' 2 | import * as email from './email.js' 3 | 4 | /* 5 | Assign the base service to the firebaseServices namespace in the 6 | serviceConnection boot file. Over time other service modules separate by 7 | logic/concerns will be added here. Be aware of name conflicts between 8 | your modules. 9 | */ 10 | export default Object.assign({}, base, email) 11 | -------------------------------------------------------------------------------- /authentication/email/src/store/auth/actions.js: -------------------------------------------------------------------------------- 1 | /* 2 | Remember, we have access to our Vue instance not using 3 | an arrow function in our actions file. This allows us 4 | to create a scoped reference to our firebaseService - $fb 5 | That was assigned to the Vue instance earlier in our serviceConnection 6 | boot file. 7 | */ 8 | 9 | /** 10 | * @param {Object} $root - Place holder argument(Vuex store) to allow data to be passed 11 | * as second argument. 12 | * @param data.email - User's email 13 | * @param data.password - User's password 14 | * @returns {function} - Firebase services function: 15 | * src/services/firebase/email.js > createUserWithEmail 16 | */ 17 | export const createNewUser = async function ($root, data) { 18 | const $fb = this.$fb 19 | const { email, password } = data 20 | return $fb.createUserWithEmail(email, password) 21 | } 22 | 23 | /** 24 | * @param {Object} $root - Place holder argument(Vuex store) to allow data to be passed 25 | * as second argument. 26 | * @param data.email - User's email 27 | * @param data.password - User's password 28 | * @returns {function} - Firebase services function: 29 | * src/services/firebase/email.js > loginWithEmail 30 | */ 31 | export const loginUser = async function ($root, data) { 32 | const $fb = this.$fb 33 | const { email, password } = data 34 | return $fb.loginWithEmail(email, password) 35 | } 36 | 37 | /** 38 | * @returns {function} - Firebase services function: 39 | * src/services/firebase/email.js > logoutUser 40 | */ 41 | export const logoutUser = async function () { 42 | const $fb = this.$fb 43 | await $fb.logoutUser() 44 | } 45 | 46 | export function routeUserToAuth () { 47 | this.$router.push({ 48 | path: '/auth/login' 49 | }) 50 | } 51 | -------------------------------------------------------------------------------- /authentication/email/src/store/auth/getters.js: -------------------------------------------------------------------------------- 1 | export function someGetter (/* state */) { 2 | } 3 | -------------------------------------------------------------------------------- /authentication/email/src/store/auth/index.js: -------------------------------------------------------------------------------- 1 | import state from './state' 2 | import * as getters from './getters' 3 | import * as mutations from './mutations' 4 | import * as actions from './actions' 5 | 6 | export default { 7 | namespaced: true, 8 | getters, 9 | mutations, 10 | actions, 11 | state 12 | } 13 | -------------------------------------------------------------------------------- /authentication/email/src/store/auth/mutations.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {Object} state - Vuex 3 | * @param data.isAuthenticated - Boolean value from: 4 | * src/services/firebase/base > handleOnAuthStateChanged 5 | * @param data.isAuthenticated - Boolean value from: 6 | * src/services/firebase/base > handleOnAuthStateChanged 7 | */ 8 | export function setAuthState (state, data) { 9 | state.isAuthenticated = data.isAuthenticated 10 | state.isReady = data.isReady 11 | } 12 | -------------------------------------------------------------------------------- /authentication/email/src/store/auth/state.js: -------------------------------------------------------------------------------- 1 | export default { 2 | isAuthenticated: false, 3 | isReady: false 4 | } 5 | -------------------------------------------------------------------------------- /authentication/email/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | import auth from './auth' 5 | 6 | Vue.use(Vuex) 7 | 8 | /* 9 | * If not building with SSR mode, you can 10 | * directly export the Store instantiation 11 | */ 12 | let store = null 13 | export default function (/* { ssrContext } */) { 14 | const Store = new Vuex.Store({ 15 | modules: { 16 | auth 17 | }, 18 | 19 | // enable strict mode (adds overhead!) 20 | // for dev mode only 21 | strict: process.env.DEV 22 | }) 23 | store = Store 24 | return Store 25 | } 26 | 27 | export { store } 28 | -------------------------------------------------------------------------------- /authentication/email/src/store/store-flag.d.ts: -------------------------------------------------------------------------------- 1 | // THIS FEATURE-FLAG FILE IS AUTOGENERATED, 2 | // REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING 3 | import "quasar/dist/types/feature-flag"; 4 | 5 | declare module "quasar/dist/types/feature-flag" { 6 | interface QuasarFeatureFlags { 7 | store: true; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /authentication/email/src/utils/environmentConfig.js: -------------------------------------------------------------------------------- 1 | const ENV = require('dotenv').config().parsed 2 | /* 3 | Use an environment variable set in package.json scripts to determine 4 | the applications runtime environment. Add more switch cases as 5 | need for additional environments. Remember, Firebase recomends supporting 6 | separate Firebase project for different application environments: httpsq://firebase.google.com/docs/projects/multiprojects#support_different_environments 7 | */ 8 | 9 | module.exports = (QENV) => { 10 | if (!['DEV', 'STAGE', 'PROD'].includes(QENV)) { 11 | throw Error('Unknonw or not supplied environment variable') 12 | } 13 | return { 14 | FIREBASE_CONFIG: { 15 | apiKey: ENV[`${QENV}_API_KEY`], 16 | authDomain: ENV[`${QENV}_AUTH_DOMAIN`], 17 | databaseURL: ENV[`${QENV}_DATA_BASE_URL`], 18 | projectId: ENV[`${QENV}_PROJECT_ID`], 19 | storageBucket: ENV[`${QENV}_STORAGE_BUCKET`], 20 | messagingSenderId: ENV[`${QENV}_MESSAGING_SENDER_ID`], 21 | appId: ENV[`${QENV}_APP_ID`] 22 | }, 23 | API_ENDPOINT: ENV[`${QENV}_API_ENDPOINT`] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /base/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /base/.env: -------------------------------------------------------------------------------- 1 | # DEVELOPMENT FIREBASE CONFIG 2 | DEV_API_KEY=AIzaSyA9-quFJzkM0qFuDQ30ecVVU6keefrzaFk 3 | DEV_AUTH_DOMAIN=quasar-firebase-38b4d.firebaseapp.com 4 | DEV_DATA_BASE_URLL=https://quasar-firebase-38b4d.firebaseio.com 5 | DEV_PROJECT_ID=quasar-firebase-38b4d 6 | DEV_STORAGE_BUCKET=quasar-firebase-38b4d.appspot.com 7 | DEV_MESSAGING_SENDER_ID=395306140214 8 | DEV_APP_ID=1:395306140214:web:6deafabd6e3147adb3ce97 9 | DEV_MEASUREMENT_ID=G-1FSVX8P8D 10 | 11 | # STAGING FIREBASE CONFIG 12 | # PROUDCTION FIREBASE CONFIG -------------------------------------------------------------------------------- /base/.eslintignore: -------------------------------------------------------------------------------- 1 | /dist 2 | -------------------------------------------------------------------------------- /base/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | 4 | parserOptions: { 5 | parser: 'babel-eslint', 6 | sourceType: 'module' 7 | }, 8 | 9 | env: { 10 | browser: true 11 | }, 12 | 13 | extends: [ 14 | // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention 15 | // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules. 16 | 'plugin:vue/essential', 17 | '@vue/standard' 18 | ], 19 | 20 | // required to lint *.vue files 21 | plugins: [ 22 | 'vue' 23 | ], 24 | 25 | globals: { 26 | 'ga': true, // Google Analytics 27 | 'cordova': true, 28 | '__statics': true, 29 | 'process': true, 30 | 'Capacitor': true 31 | }, 32 | 33 | // add your custom rules here 34 | rules: { 35 | // allow async-await 36 | 'generator-star-spacing': 'off', 37 | // allow paren-less arrow functions 38 | 'arrow-parens': 'off', 39 | 'one-var': 'off', 40 | 41 | 'import/first': 'off', 42 | 'import/named': 'error', 43 | 'import/namespace': 'error', 44 | 'import/default': 'error', 45 | 'import/export': 'error', 46 | 'import/extensions': 'off', 47 | 'import/no-unresolved': 'off', 48 | 'import/no-extraneous-dependencies': 'off', 49 | 'prefer-promise-reject-errors': 'off', 50 | 51 | // allow console.log during development only 52 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 53 | // allow debugger during development only 54 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /base/.gitignore: -------------------------------------------------------------------------------- 1 | .quasar 2 | .DS_Store 3 | .thumbs.db 4 | node_modules 5 | /dist 6 | /src-cordova/node_modules 7 | /src-cordova/platforms 8 | /src-cordova/plugins 9 | /src-cordova/www 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | -------------------------------------------------------------------------------- /base/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | plugins: [ 5 | // to edit target browsers: use "browserslist" field in package.json 6 | require('autoprefixer') 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /base/.stylintrc: -------------------------------------------------------------------------------- 1 | { 2 | "blocks": "never", 3 | "brackets": "never", 4 | "colons": "never", 5 | "colors": "always", 6 | "commaSpace": "always", 7 | "commentSpace": "always", 8 | "cssLiteral": "never", 9 | "depthLimit": false, 10 | "duplicates": true, 11 | "efficient": "always", 12 | "extendPref": false, 13 | "globalDupe": true, 14 | "indentPref": 2, 15 | "leadingZero": "never", 16 | "maxErrors": false, 17 | "maxWarnings": false, 18 | "mixed": false, 19 | "namingConvention": false, 20 | "namingConventionStrict": false, 21 | "none": "never", 22 | "noImportant": false, 23 | "parenSpace": "never", 24 | "placeholder": false, 25 | "prefixVarsWithDollar": "always", 26 | "quotePref": "single", 27 | "semicolons": "never", 28 | "sortOrder": false, 29 | "stackedProperties": "never", 30 | "trailingWhitespace": "never", 31 | "universal": "never", 32 | "valid": true, 33 | "zeroUnits": "never", 34 | "zIndexNormalize": false 35 | } 36 | -------------------------------------------------------------------------------- /base/README.md: -------------------------------------------------------------------------------- 1 | # Firebase Sample App: Base 2 | Base implementation of Google's Firebase service. 3 | 4 | ## Install the dependencies 5 | ```bash 6 | yarn 7 | ``` 8 | 9 | ### Start the app in development mode (hot-code reloading, error reporting, etc.) 10 | ```bash 11 | npm run dev 12 | or 13 | 14 | yarn run dev 15 | ``` 16 | 17 | Windwos users run: 18 | ```bash 19 | npm run dev:win 20 | 21 | or 22 | 23 | yarn run dev:win 24 | ``` 25 | 26 | ### Areas of focus 27 | - `firebaseConnetion.js` implmentation 28 | - First Firebase service, `base.js`, created and used -------------------------------------------------------------------------------- /base/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@quasar/babel-preset-app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /base/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "src/*": [ 6 | "src/*" 7 | ], 8 | "app/*": [ 9 | "*" 10 | ], 11 | "components/*": [ 12 | "src/components/*" 13 | ], 14 | "layouts/*": [ 15 | "src/layouts/*" 16 | ], 17 | "pages/*": [ 18 | "src/pages/*" 19 | ], 20 | "assets/*": [ 21 | "src/assets/*" 22 | ], 23 | "boot/*": [ 24 | "src/boot/*" 25 | ], 26 | "vue$": [ 27 | "node_modules/vue/dist/vue.esm.js" 28 | ] 29 | } 30 | }, 31 | "exclude": [ 32 | "dist", 33 | ".quasar", 34 | "node_modules" 35 | ] 36 | } -------------------------------------------------------------------------------- /base/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "base", 3 | "version": "0.0.1", 4 | "description": "Basic implementation of firebase service", 5 | "productName": "Firebase Sample App: Base Service", 6 | "author": "Adam K. Purdy ", 7 | "private": true, 8 | "scripts": { 9 | "dev": "QENV=DEV quasar dev", 10 | "dev:win": "cross-env QENV=DEV quasar dev", 11 | "lint": "eslint --ext .js,.vue src", 12 | "test": "echo \"No test specified\" && exit 0" 13 | }, 14 | "dependencies": { 15 | "@quasar/extras": "^1.10.7", 16 | "core-js": "^3.8.3", 17 | "firebase": "^8.2.4", 18 | "quasar": "^1.15.21" 19 | }, 20 | "devDependencies": { 21 | "@quasar/app": "^2.2.10", 22 | "@vue/eslint-config-standard": "^6.0.0", 23 | "babel-eslint": "^10.0.1", 24 | "cross-env": "^7.0.3", 25 | "dotenv": "^8.2.0", 26 | "eslint": "^7.18.0", 27 | "eslint-config-standard": "^16.0.2", 28 | "eslint-loader": "^4.0.2", 29 | "eslint-plugin-import": "^2.22.1", 30 | "eslint-plugin-node": "^11.1.0", 31 | "eslint-plugin-promise": "^4.2.1", 32 | "eslint-plugin-vue": "^7.5.0" 33 | }, 34 | "engines": { 35 | "node": ">= 8.9.0", 36 | "npm": ">= 5.6.0", 37 | "yarn": ">= 1.6.0" 38 | }, 39 | "browserslist": [ 40 | "last 10 Chrome versions", 41 | "last 10 Firefox versions", 42 | "last 4 Edge versions", 43 | "last 7 Safari versions", 44 | "last 8 Android versions", 45 | "last 8 ChromeAndroid versions", 46 | "last 8 FirefoxAndroid versions", 47 | "last 10 iOS versions", 48 | "last 5 Opera versions" 49 | ] 50 | } 51 | -------------------------------------------------------------------------------- /base/public/app-logo-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/public/app-logo-128x128.png -------------------------------------------------------------------------------- /base/public/icons/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/public/icons/apple-icon-120x120.png -------------------------------------------------------------------------------- /base/public/icons/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/public/icons/apple-icon-152x152.png -------------------------------------------------------------------------------- /base/public/icons/apple-icon-167x167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/public/icons/apple-icon-167x167.png -------------------------------------------------------------------------------- /base/public/icons/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/public/icons/apple-icon-180x180.png -------------------------------------------------------------------------------- /base/public/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/public/icons/favicon-16x16.png -------------------------------------------------------------------------------- /base/public/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/public/icons/favicon-32x32.png -------------------------------------------------------------------------------- /base/public/icons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/public/icons/favicon-96x96.png -------------------------------------------------------------------------------- /base/public/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/public/icons/favicon.ico -------------------------------------------------------------------------------- /base/public/icons/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/public/icons/icon-128x128.png -------------------------------------------------------------------------------- /base/public/icons/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/public/icons/icon-192x192.png -------------------------------------------------------------------------------- /base/public/icons/icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/public/icons/icon-256x256.png -------------------------------------------------------------------------------- /base/public/icons/icon-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/public/icons/icon-384x384.png -------------------------------------------------------------------------------- /base/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /base/public/icons/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/public/icons/ms-icon-144x144.png -------------------------------------------------------------------------------- /base/public/icons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /base/quasar.conf.js: -------------------------------------------------------------------------------- 1 | // Configuration for your app 2 | // https://quasar.dev/quasar-cli/quasar-conf-js 3 | const enviromentConfiguration = require('./src/utils/environmentConfig.js') 4 | module.exports = function (ctx) { 5 | return { 6 | // app boot file (/src/boot) 7 | // --> boot files are part of "main.js" 8 | // https://quasar.dev/quasar-cli/cli-documentation/boot-files 9 | boot: [ 10 | 'firebaseConnection' 11 | ], 12 | 13 | // https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-css 14 | css: [ 15 | 'app.styl' 16 | ], 17 | 18 | // https://github.com/quasarframework/quasar/tree/dev/extras 19 | extras: [ 20 | // 'ionicons-v4', 21 | // 'mdi-v4', 22 | // 'fontawesome-v5', 23 | // 'eva-icons', 24 | // 'themify', 25 | // 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both! 26 | 27 | 'roboto-font', // optional, you are not bound to it 28 | 'material-icons' // optional, you are not bound to it 29 | ], 30 | 31 | // https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-framework 32 | framework: { 33 | // iconSet: 'ionicons-v4', // Quasar icon set 34 | // lang: 'de', // Quasar language pack 35 | 36 | // Possible values for "all": 37 | // * 'auto' - Auto-import needed Quasar components & directives 38 | // (slightly higher compile time; next to minimum bundle size; most convenient) 39 | // * false - Manually specify what to import 40 | // (fastest compile time; minimum bundle size; most tedious) 41 | // * true - Import everything from Quasar 42 | // (not treeshaking Quasar; biggest bundle size; convenient) 43 | importStrategy: 'auto', 44 | 45 | components: [], 46 | directives: [], 47 | 48 | // Quasar plugins 49 | plugins: [] 50 | }, 51 | 52 | // https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-build 53 | build: { 54 | scopeHoisting: true, 55 | // vueRouterMode: 'history', 56 | // showProgress: false, 57 | // gzip: true, 58 | // analyze: true, 59 | // preloadChunks: false, 60 | // extractCSS: false, 61 | 62 | // https://quasar.dev/quasar-cli/cli-documentation/handling-webpack 63 | extendWebpack (cfg) { 64 | cfg.module.rules.push({ 65 | enforce: 'pre', 66 | test: /\.(js|vue)$/, 67 | loader: 'eslint-loader', 68 | exclude: /node_modules/, 69 | options: { 70 | formatter: require('eslint').CLIEngine.getFormatter('stylish') 71 | } 72 | }) 73 | }, 74 | env: { 75 | QENV: enviromentConfiguration(process.env.QENV) 76 | } 77 | }, 78 | 79 | // https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-devServer 80 | devServer: { 81 | // https: true, 82 | // port: 8080, 83 | open: true // opens browser window automatically 84 | }, 85 | 86 | // animations: 'all', // --- includes all animations 87 | // https://quasar.dev/options/animations 88 | animations: [], 89 | 90 | // https://quasar.dev/quasar-cli/developing-ssr/configuring-ssr 91 | ssr: { 92 | pwa: false 93 | }, 94 | 95 | // https://quasar.dev/quasar-cli/developing-pwa/configuring-pwa 96 | pwa: { 97 | // workboxPluginMode: 'InjectManifest', 98 | // workboxOptions: {}, // only for NON InjectManifest 99 | manifest: { 100 | // name: 'Firebase Sample App: Base', 101 | // short_name: 'Firebase Sample App: Base', 102 | // description: 'Basis implementation of firebase service', 103 | display: 'standalone', 104 | orientation: 'portrait', 105 | background_color: '#ffffff', 106 | theme_color: '#027be3', 107 | icons: [ 108 | { 109 | src: 'icons/icon-128x128.png', 110 | sizes: '128x128', 111 | type: 'image/png' 112 | }, 113 | { 114 | src: 'icons/icon-192x192.png', 115 | sizes: '192x192', 116 | type: 'image/png' 117 | }, 118 | { 119 | src: 'icons/icon-256x256.png', 120 | sizes: '256x256', 121 | type: 'image/png' 122 | }, 123 | { 124 | src: 'icons/icon-384x384.png', 125 | sizes: '384x384', 126 | type: 'image/png' 127 | }, 128 | { 129 | src: 'icons/icon-512x512.png', 130 | sizes: '512x512', 131 | type: 'image/png' 132 | } 133 | ] 134 | } 135 | }, 136 | 137 | // https://quasar.dev/quasar-cli/developing-cordova-apps/configuring-cordova 138 | cordova: { 139 | // id: 'org.cordova.quasar.app', 140 | // noIosLegacyBuildFlag: true, // uncomment only if you know what you are doing 141 | }, 142 | 143 | // https://quasar.dev/quasar-cli/developing-electron-apps/configuring-electron 144 | electron: { 145 | // bundler: 'builder', // or 'packager' 146 | 147 | extendWebpack (cfg) { 148 | // do something with Electron main process Webpack cfg 149 | // chainWebpack also available besides this extendWebpack 150 | }, 151 | 152 | packager: { 153 | // https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options 154 | 155 | // OS X / Mac App Store 156 | // appBundleId: '', 157 | // appCategoryType: '', 158 | // osxSign: '', 159 | // protocol: 'myapp://path', 160 | 161 | // Windows only 162 | // win32metadata: { ... } 163 | }, 164 | 165 | builder: { 166 | // https://www.electron.build/configuration/configuration 167 | 168 | // appId: 'base' 169 | } 170 | } 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /base/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /base/src/assets/firebase-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/src/assets/firebase-icon.png -------------------------------------------------------------------------------- /base/src/assets/quasar-logo-full.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | 63 | 66 | 69 | 75 | 79 | 83 | 87 | 91 | 95 | 99 | 103 | 104 | 105 | 106 | 107 | 113 | 118 | 126 | 133 | 142 | 151 | 160 | 169 | 178 | 187 | 188 | 189 | 190 | 191 | 192 | -------------------------------------------------------------------------------- /base/src/assets/sad.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /base/src/assets/sample-app-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/src/assets/sample-app-logo.png -------------------------------------------------------------------------------- /base/src/boot/firebaseConnection.js: -------------------------------------------------------------------------------- 1 | import firebaseServices from '../services/firebase' 2 | 3 | export default async () => { 4 | const app = firebaseServices.fBInit(process.env.QENV.FIREBASE_CONFIG) 5 | 6 | // Validation that our service structure is working 7 | // with an initialize Firebase application and auth instance. 8 | console.log('Firebase App Instantiation:', app) 9 | console.log('Firebase Auth Module:', firebaseServices.auth()) 10 | } 11 | -------------------------------------------------------------------------------- /base/src/components/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/base/src/components/.gitkeep -------------------------------------------------------------------------------- /base/src/css/app.styl: -------------------------------------------------------------------------------- 1 | // app global css in Stylus form 2 | -------------------------------------------------------------------------------- /base/src/css/quasar.variables.styl: -------------------------------------------------------------------------------- 1 | // Quasar Stylus Variables 2 | // -------------------------------------------------- 3 | // To customize the look and feel of this app, you can override 4 | // the Stylus variables found in Quasar's source Stylus files. 5 | 6 | // Check documentation for full list of Quasar variables 7 | 8 | // Your own variables (that are declared here) and Quasar's own 9 | // ones will be available out of the box in your .vue/.styl files 10 | 11 | // It's highly recommended to change the default colors 12 | // to match your app's branding. 13 | // Tip: Use the "Theme Builder" on Quasar's documentation website. 14 | 15 | $primary = #027BE3 16 | $secondary = #26A69A 17 | $accent = #9C27B0 18 | 19 | $positive = #21BA45 20 | $negative = #C10015 21 | $info = #31CCEC 22 | $warning = #F2C037 23 | -------------------------------------------------------------------------------- /base/src/index.template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= productName %> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /base/src/layouts/MainLayout.vue: -------------------------------------------------------------------------------- 1 | 102 | 103 | 118 | -------------------------------------------------------------------------------- /base/src/pages/Error404.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | -------------------------------------------------------------------------------- /base/src/pages/Index.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /base/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | 4 | import routes from './routes' 5 | 6 | Vue.use(VueRouter) 7 | 8 | /* 9 | * If not building with SSR mode, you can 10 | * directly export the Router instantiation 11 | */ 12 | 13 | export default function (/* { store, ssrContext } */) { 14 | const Router = new VueRouter({ 15 | scrollBehavior: () => ({ x: 0, y: 0 }), 16 | routes, 17 | 18 | // Leave these as is and change from quasar.conf.js instead! 19 | // quasar.conf.js -> build -> vueRouterMode 20 | // quasar.conf.js -> build -> publicPath 21 | mode: process.env.VUE_ROUTER_MODE, 22 | base: process.env.VUE_ROUTER_BASE 23 | }) 24 | 25 | return Router 26 | } 27 | -------------------------------------------------------------------------------- /base/src/router/routes.js: -------------------------------------------------------------------------------- 1 | 2 | const routes = [ 3 | { 4 | path: '/', 5 | component: () => import('layouts/MainLayout.vue'), 6 | children: [ 7 | { path: '', component: () => import('pages/Index.vue') } 8 | ] 9 | } 10 | ] 11 | 12 | // Always leave this as last one 13 | routes.push({ 14 | path: '*', 15 | component: () => import('pages/Error404.vue') 16 | }) 17 | 18 | export default routes 19 | -------------------------------------------------------------------------------- /base/src/services/firebase/base.js: -------------------------------------------------------------------------------- 1 | import firebase from 'firebase/app' 2 | import 'firebase/auth' 3 | 4 | /** 5 | * Returns Firebase's auth service 6 | * https://firebase.google.com/docs/reference/js/firebase.auth.html#callable 7 | * @returns {Auth} - The Firebase Auth service interface 8 | */ 9 | export const auth = () => { 10 | return firebase.auth() 11 | } 12 | 13 | /** 14 | * Convenience method to initialize firebase app 15 | * https://firebase.google.com/docs/reference/js/firebase?authuser=1#initializeapp 16 | * @param {Object} config - FIREBASE_CONFIG during the build process 17 | * @returns {App} - Creates and initializes a Firebase app instance. 18 | */ 19 | export const fBInit = (config) => { 20 | return firebase.initializeApp(config) 21 | } 22 | -------------------------------------------------------------------------------- /base/src/services/firebase/index.js: -------------------------------------------------------------------------------- 1 | import * as base from './base.js' 2 | 3 | /* 4 | Assign the base service to the firebaseServices namespace in the 5 | serviceConnection boot file. Over time other service modules separate by 6 | logic/concerns will be added here. Be aware of name conflicts between 7 | your modules. 8 | */ 9 | export default Object.assign({}, base) 10 | -------------------------------------------------------------------------------- /base/src/utils/environmentConfig.js: -------------------------------------------------------------------------------- 1 | const ENV = require('dotenv').config().parsed 2 | /* 3 | Use an environment variable set in package.json scripts to determine 4 | the applications runtime environment. Add more switch cases as 5 | need for additional environments. Remember, Firebase recomends supporting 6 | separate Firebase project for different application environments: httpsq://firebase.google.com/docs/projects/multiprojects#support_different_environments 7 | */ 8 | 9 | module.exports = (QENV) => { 10 | if (!['DEV', 'STAGE', 'PROD'].includes(QENV)) { 11 | throw Error('Unknonw or not supplied environment variable') 12 | } 13 | return { 14 | FIREBASE_CONFIG: { 15 | apiKey: ENV[`${QENV}_API_KEY`], 16 | authDomain: ENV[`${QENV}_AUTH_DOMAIN`], 17 | databaseURL: ENV[`${QENV}_DATA_BASE_URL`], 18 | projectId: ENV[`${QENV}_PROJECT_ID`], 19 | storageBucket: ENV[`${QENV}_STORAGE_BUCKET`], 20 | messagingSenderId: ENV[`${QENV}_MESSAGING_SENDER_ID`], 21 | appId: ENV[`${QENV}_APP_ID`] 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /data/profile/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /data/profile/.env: -------------------------------------------------------------------------------- 1 | # DEVELOPMENT FIREBASE CONFIG 2 | DEV_API_KEY=AIzaSyA9-quFJzkM0qFuDQ30ecVVU6keefrzaFk 3 | DEV_AUTH_DOMAIN=quasar-firebase-38b4d.firebaseapp.com 4 | DEV_DATA_BASE_URLL=https://quasar-firebase-38b4d.firebaseio.com 5 | DEV_PROJECT_ID=quasar-firebase-38b4d 6 | DEV_STORAGE_BUCKET=quasar-firebase-38b4d.appspot.com 7 | DEV_MESSAGING_SENDER_ID=395306140214 8 | DEV_APP_ID=1:395306140214:web:6deafabd6e3147adb3ce97 9 | DEV_MEASUREMENT_ID=G-1FSVX8P8D 10 | 11 | # STAGING FIREBASE CONFIG 12 | # PROUDCTION FIREBASE CONFIG -------------------------------------------------------------------------------- /data/profile/.eslintignore: -------------------------------------------------------------------------------- 1 | /dist 2 | -------------------------------------------------------------------------------- /data/profile/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | 4 | parserOptions: { 5 | parser: 'babel-eslint', 6 | sourceType: 'module' 7 | }, 8 | 9 | env: { 10 | browser: true 11 | }, 12 | 13 | extends: [ 14 | // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention 15 | // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules. 16 | 'plugin:vue/essential', 17 | '@vue/standard' 18 | ], 19 | 20 | // required to lint *.vue files 21 | plugins: [ 22 | 'vue' 23 | ], 24 | 25 | globals: { 26 | ga: true, // Google Analytics 27 | cordova: true, 28 | __statics: true, 29 | process: true, 30 | Capacitor: true, 31 | chrome: true 32 | }, 33 | 34 | // add your custom rules here 35 | rules: { 36 | // allow async-await 37 | 'generator-star-spacing': 'off', 38 | // allow paren-less arrow functions 39 | 'arrow-parens': 'off', 40 | 'one-var': 'off', 41 | 42 | 'import/first': 'off', 43 | 'import/named': 'error', 44 | 'import/namespace': 'error', 45 | 'import/default': 'error', 46 | 'import/export': 'error', 47 | 'import/extensions': 'off', 48 | 'import/no-unresolved': 'off', 49 | 'import/no-extraneous-dependencies': 'off', 50 | 'prefer-promise-reject-errors': 'off', 51 | 52 | // allow console.log during development only 53 | 'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off', 54 | // allow debugger during development only 55 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off' 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /data/profile/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .thumbs.db 3 | node_modules 4 | 5 | # Quasar core related directories 6 | .quasar 7 | /dist 8 | 9 | # Cordova related directories and files 10 | /src-cordova/node_modules 11 | /src-cordova/platforms 12 | /src-cordova/plugins 13 | /src-cordova/www 14 | 15 | # Capacitor related directories and files 16 | /src-capacitor/www 17 | /src-capacitor/node_modules 18 | 19 | # BEX related directories and files 20 | /src-bex/www 21 | /src-bex/js/core 22 | 23 | # Log files 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # Editor directories and files 29 | .idea 30 | .vscode 31 | *.suo 32 | *.ntvs* 33 | *.njsproj 34 | *.sln 35 | -------------------------------------------------------------------------------- /data/profile/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | plugins: [ 5 | // to edit target browsers: use "browserslist" field in package.json 6 | require('autoprefixer') 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /data/profile/.stylintrc: -------------------------------------------------------------------------------- 1 | { 2 | "blocks": "never", 3 | "brackets": "never", 4 | "colons": "never", 5 | "colors": "always", 6 | "commaSpace": "always", 7 | "commentSpace": "always", 8 | "cssLiteral": "never", 9 | "depthLimit": false, 10 | "duplicates": true, 11 | "efficient": "always", 12 | "extendPref": false, 13 | "globalDupe": true, 14 | "indentPref": 2, 15 | "leadingZero": "never", 16 | "maxErrors": false, 17 | "maxWarnings": false, 18 | "mixed": false, 19 | "namingConvention": false, 20 | "namingConventionStrict": false, 21 | "none": "never", 22 | "noImportant": false, 23 | "parenSpace": "never", 24 | "placeholder": false, 25 | "prefixVarsWithDollar": "always", 26 | "quotePref": "single", 27 | "semicolons": "never", 28 | "sortOrder": false, 29 | "stackedProperties": "never", 30 | "trailingWhitespace": "never", 31 | "universal": "never", 32 | "valid": true, 33 | "zeroUnits": "never", 34 | "zIndexNormalize": false 35 | } 36 | -------------------------------------------------------------------------------- /data/profile/README.md: -------------------------------------------------------------------------------- 1 | # QUploader implementation with Google Cloud Storage (uploader) 2 | 3 | QUploader implementation with Google Cloud Storage 4 | 5 | ## Install the dependencies 6 | ```bash 7 | yarn 8 | ``` 9 | 10 | ### Start the app in development mode (hot-code reloading, error reporting, etc.) 11 | ```bash 12 | npm run dev 13 | or 14 | 15 | yarn run dev 16 | ``` 17 | 18 | Windwos users run: 19 | ```bash 20 | npm run dev:win 21 | 22 | or 23 | 24 | yarn run dev:win 25 | ``` 26 | 27 | ### Areas of focus 28 | 29 | - `firebaseConnetion.js` enhancement 30 | - Firebase service, `base.js` enhancements 31 | - Second Firebase service, `email.js`, created and used 32 | - Authentication form for creating new users and logging in users 33 | - Use of route guards for User page 34 | -------------------------------------------------------------------------------- /data/profile/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@quasar/babel-preset-app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /data/profile/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "src/*": [ 6 | "src/*" 7 | ], 8 | "app/*": [ 9 | "*" 10 | ], 11 | "components/*": [ 12 | "src/components/*" 13 | ], 14 | "layouts/*": [ 15 | "src/layouts/*" 16 | ], 17 | "pages/*": [ 18 | "src/pages/*" 19 | ], 20 | "assets/*": [ 21 | "src/assets/*" 22 | ], 23 | "boot/*": [ 24 | "src/boot/*" 25 | ], 26 | "vue$": [ 27 | "node_modules/vue/dist/vue.esm.js" 28 | ] 29 | } 30 | }, 31 | "exclude": [ 32 | "dist", 33 | ".quasar", 34 | "node_modules" 35 | ] 36 | } -------------------------------------------------------------------------------- /data/profile/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "uploader", 3 | "version": "0.0.1", 4 | "description": "User profile using Firebase, Vuexfire, and Google Cloud Storage", 5 | "productName": "Firebase Sample App: User Profile", 6 | "author": "Adam K. Purdy ", 7 | "private": true, 8 | "scripts": { 9 | "dev": "QENV=DEV quasar dev", 10 | "dev:win": "cross-env QENV=DEV quasar dev", 11 | "lint": "eslint --ext .js,.vue src", 12 | "test": "echo \"No test specified\" && exit 0" 13 | }, 14 | "dependencies": { 15 | "@quasar/extras": "^1.10.7", 16 | "core-js": "^3.8.3", 17 | "firebase": "^8.2.4", 18 | "quasar": "^1.15.21", 19 | "vuexfire": "^3.2.5" 20 | }, 21 | "devDependencies": { 22 | "@quasar/app": "^2.2.10", 23 | "@vue/eslint-config-standard": "^6.0.0", 24 | "babel-eslint": "^10.0.1", 25 | "cross-env": "^7.0.3", 26 | "dotenv": "^8.2.0", 27 | "eslint": "^7.18.0", 28 | "eslint-config-standard": "^16.0.2", 29 | "eslint-loader": "^4.0.2", 30 | "eslint-plugin-import": "^2.22.1", 31 | "eslint-plugin-node": "^11.1.0", 32 | "eslint-plugin-promise": "^4.2.1", 33 | "eslint-plugin-vue": "^7.5.0" 34 | }, 35 | "engines": { 36 | "node": ">= 8.9.0", 37 | "npm": ">= 5.6.0", 38 | "yarn": ">= 1.6.0" 39 | }, 40 | "browserslist": [ 41 | "last 10 Chrome versions", 42 | "last 10 Firefox versions", 43 | "last 4 Edge versions", 44 | "last 7 Safari versions", 45 | "last 8 Android versions", 46 | "last 8 ChromeAndroid versions", 47 | "last 8 FirefoxAndroid versions", 48 | "last 10 iOS versions", 49 | "last 5 Opera versions" 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /data/profile/public/app-logo-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/app-logo-128x128.png -------------------------------------------------------------------------------- /data/profile/public/fp-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/fp-logo.png -------------------------------------------------------------------------------- /data/profile/public/icons/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/icons/apple-icon-120x120.png -------------------------------------------------------------------------------- /data/profile/public/icons/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/icons/apple-icon-152x152.png -------------------------------------------------------------------------------- /data/profile/public/icons/apple-icon-167x167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/icons/apple-icon-167x167.png -------------------------------------------------------------------------------- /data/profile/public/icons/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/icons/apple-icon-180x180.png -------------------------------------------------------------------------------- /data/profile/public/icons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/icons/favicon-16x16.png -------------------------------------------------------------------------------- /data/profile/public/icons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/icons/favicon-32x32.png -------------------------------------------------------------------------------- /data/profile/public/icons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/icons/favicon-96x96.png -------------------------------------------------------------------------------- /data/profile/public/icons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/icons/favicon.ico -------------------------------------------------------------------------------- /data/profile/public/icons/icon-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/icons/icon-128x128.png -------------------------------------------------------------------------------- /data/profile/public/icons/icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/icons/icon-192x192.png -------------------------------------------------------------------------------- /data/profile/public/icons/icon-256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/icons/icon-256x256.png -------------------------------------------------------------------------------- /data/profile/public/icons/icon-384x384.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/icons/icon-384x384.png -------------------------------------------------------------------------------- /data/profile/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /data/profile/public/icons/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/public/icons/ms-icon-144x144.png -------------------------------------------------------------------------------- /data/profile/public/icons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /data/profile/quasar.conf.js: -------------------------------------------------------------------------------- 1 | // Configuration for your app 2 | // https://quasar.dev/quasar-cli/quasar-conf-js 3 | const enviromentConfiguration = require('./src/utils/environmentConfig.js') 4 | module.exports = function (ctx) { 5 | return { 6 | // app boot file (/src/boot) 7 | // --> boot files are part of "main.js" 8 | // https://quasar.dev/quasar-cli/cli-documentation/boot-files 9 | boot: [ 10 | 'firebaseConnection' 11 | ], 12 | 13 | // https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-css 14 | css: [ 15 | 'app.styl' 16 | ], 17 | 18 | // https://github.com/quasarframework/quasar/tree/dev/extras 19 | extras: [ 20 | // 'ionicons-v4', 21 | // 'mdi-v4', 22 | // 'fontawesome-v5', 23 | // 'eva-icons', 24 | // 'themify', 25 | // 'roboto-font-latin-ext', // this or either 'roboto-font', NEVER both! 26 | 27 | 'roboto-font', // optional, you are not bound to it 28 | 'material-icons' // optional, you are not bound to it 29 | ], 30 | 31 | // https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-framework 32 | framework: { 33 | // iconSet: 'ionicons-v4', // Quasar icon set 34 | // lang: 'de', // Quasar language pack 35 | 36 | // Possible values for "all": 37 | // * 'auto' - Auto-import needed Quasar components & directives 38 | // (slightly higher compile time; next to minimum bundle size; most convenient) 39 | // * false - Manually specify what to import 40 | // (fastest compile time; minimum bundle size; most tedious) 41 | // * true - Import everything from Quasar 42 | // (not treeshaking Quasar; biggest bundle size; convenient) 43 | importStrategy: 'auto', 44 | 45 | components: [], 46 | directives: [ 47 | 48 | ], 49 | 50 | // Quasar plugins 51 | plugins: ['Loading', 'Notify'] 52 | }, 53 | 54 | // https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-build 55 | build: { 56 | scopeHoisting: true, 57 | // vueRouterMode: 'history', 58 | // showProgress: false, 59 | // gzip: true, 60 | // analyze: true, 61 | // preloadChunks: false, 62 | // extractCSS: false, 63 | 64 | // https://quasar.dev/quasar-cli/cli-documentation/handling-webpack 65 | extendWebpack (cfg) { 66 | cfg.module.rules.push({ 67 | enforce: 'pre', 68 | test: /\.(js|vue)$/, 69 | loader: 'eslint-loader', 70 | exclude: /node_modules/, 71 | options: { 72 | formatter: require('eslint').CLIEngine.getFormatter('stylish') 73 | } 74 | }) 75 | }, 76 | env: { 77 | QENV: enviromentConfiguration(process.env.QENV) 78 | } 79 | }, 80 | 81 | // https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-devServer 82 | devServer: { 83 | // https: true, 84 | // port: 8080, 85 | open: true // opens browser window automatically 86 | }, 87 | 88 | // animations: 'all', // --- includes all animations 89 | // https://quasar.dev/options/animations 90 | animations: [], 91 | 92 | // https://quasar.dev/quasar-cli/developing-ssr/configuring-ssr 93 | ssr: { 94 | pwa: false 95 | }, 96 | 97 | // https://quasar.dev/quasar-cli/developing-pwa/configuring-pwa 98 | pwa: { 99 | // workboxPluginMode: 'InjectManifest', 100 | // workboxOptions: {}, // only for NON InjectManifest 101 | manifest: { 102 | // name: 'QUploader implementation with Google Cloud Storage', 103 | // short_name: 'QUploader implementation with Google Cloud Storage', 104 | // description: 'QUploader implementation with Google Cloud Storage', 105 | display: 'standalone', 106 | orientation: 'portrait', 107 | background_color: '#ffffff', 108 | theme_color: '#027be3', 109 | icons: [ 110 | { 111 | src: '/icon-128x128.png', 112 | sizes: '128x128', 113 | type: 'image/png' 114 | }, 115 | { 116 | src: '/icon-192x192.png', 117 | sizes: '192x192', 118 | type: 'image/png' 119 | }, 120 | { 121 | src: '/icon-256x256.png', 122 | sizes: '256x256', 123 | type: 'image/png' 124 | }, 125 | { 126 | src: '/icon-384x384.png', 127 | sizes: '384x384', 128 | type: 'image/png' 129 | }, 130 | { 131 | src: '/icon-512x512.png', 132 | sizes: '512x512', 133 | type: 'image/png' 134 | } 135 | ] 136 | } 137 | }, 138 | 139 | // https://quasar.dev/quasar-cli/developing-cordova-apps/configuring-cordova 140 | cordova: { 141 | // id: 'org.cordova.quasar.app', 142 | // noIosLegacyBuildFlag: true, // uncomment only if you know what you are doing 143 | }, 144 | 145 | // https://quasar.dev/quasar-cli/developing-capacitor-apps/configuring-capacitor 146 | capacitor: { 147 | // hideSplashscreen: false 148 | }, 149 | 150 | // https://quasar.dev/quasar-cli/developing-electron-apps/configuring-electron 151 | electron: { 152 | // bundler: 'builder', // or 'packager' 153 | 154 | packager: { 155 | // https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#options 156 | 157 | // OS X / Mac App Store 158 | // appBundleId: '', 159 | // appCategoryType: '', 160 | // osxSign: '', 161 | // protocol: 'myapp://path', 162 | 163 | // Windows only 164 | // win32metadata: { ... } 165 | }, 166 | 167 | builder: { 168 | // https://www.electron.build/configuration/configuration 169 | 170 | // appId: 'uploader' 171 | }, 172 | 173 | // keep in sync with /src-electron/main-process/electron-main 174 | // > BrowserWindow > webPreferences > nodeIntegration 175 | // More info: https://quasar.dev/quasar-cli/developing-electron-apps/node-integration 176 | nodeIntegration: true, 177 | 178 | extendWebpack (cfg) { 179 | // do something with Electron main process Webpack cfg 180 | // chainWebpack also available besides this extendWebpack 181 | } 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /data/profile/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /data/profile/src/assets/quasar-logo-full.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | 63 | 66 | 69 | 75 | 79 | 83 | 87 | 91 | 95 | 99 | 103 | 104 | 105 | 106 | 107 | 113 | 118 | 126 | 133 | 142 | 151 | 160 | 169 | 178 | 187 | 188 | 189 | 190 | 191 | 192 | -------------------------------------------------------------------------------- /data/profile/src/assets/sad.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /data/profile/src/assets/sample-app-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quasarframework/firebase-sample-apps/46e43d447fc8c6e2f6167abdb074362be48713fa/data/profile/src/assets/sample-app-logo.png -------------------------------------------------------------------------------- /data/profile/src/boot/firebaseConnection.js: -------------------------------------------------------------------------------- 1 | import firebaseServices from '../services/firebase' 2 | 3 | export default ({ store, Vue }) => { 4 | firebaseServices.fBInit(process.env.QENV.FIREBASE_CONFIG) 5 | 6 | // Tell the application what to do when the 7 | // authentication state has changed 8 | firebaseServices.auth().onAuthStateChanged((user) => { 9 | firebaseServices.handleOnAuthStateChanged(store, user) 10 | }, (error) => { 11 | console.error(error) 12 | }) 13 | 14 | Vue.prototype.$fb = firebaseServices 15 | store.$fb = firebaseServices 16 | } 17 | -------------------------------------------------------------------------------- /data/profile/src/components/FBQUploader.vue: -------------------------------------------------------------------------------- 1 | 119 | -------------------------------------------------------------------------------- /data/profile/src/css/app.styl: -------------------------------------------------------------------------------- 1 | // app global css in Stylus form 2 | a 3 | color black 4 | text-decoration none 5 | 6 | .loader 7 | font-size 2em 8 | &:before 9 | opacity .9!important -------------------------------------------------------------------------------- /data/profile/src/css/quasar.variables.styl: -------------------------------------------------------------------------------- 1 | // Quasar Stylus Variables 2 | // -------------------------------------------------- 3 | // To customize the look and feel of this app, you can override 4 | // the Stylus variables found in Quasar's source Stylus files. 5 | 6 | // Check documentation for full list of Quasar variables 7 | 8 | // Your own variables (that are declared here) and Quasar's own 9 | // ones will be available out of the box in your .vue/.styl files 10 | 11 | // It's highly recommended to change the default colors 12 | // to match your app's branding. 13 | // Tip: Use the "Theme Builder" on Quasar's documentation website. 14 | 15 | $primary = #027BE3 16 | $secondary = #26A69A 17 | $accent = #9C27B0 18 | 19 | $positive = #21BA45 20 | $negative = #C10015 21 | $info = #31CCEC 22 | $warning = #F2C037 23 | -------------------------------------------------------------------------------- /data/profile/src/index.template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= productName %> 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /data/profile/src/layouts/Basic.vue: -------------------------------------------------------------------------------- 1 | 92 | 93 | 108 | -------------------------------------------------------------------------------- /data/profile/src/layouts/User.vue: -------------------------------------------------------------------------------- 1 | 100 | 101 | 130 | 131 | 136 | -------------------------------------------------------------------------------- /data/profile/src/models/User.js: -------------------------------------------------------------------------------- 1 | /** Class representing a User. */ 2 | export default class User { 3 | /** 4 | * Create a user. 5 | * @param {String} id - Place holder for a unique Firebase id. 6 | * @param {String} backgroundPhoto - A generated URL from Google Storage. 7 | * @param {String} email - A valid email. 8 | * @param {String} fullName - The user's full name. 9 | * @param {String} mobile - the user's mobile number. 10 | * @param {String} profilePhoto - A generated URL from Google Storage. 11 | */ 12 | id = '' 13 | backgroundPhoto = '' 14 | email = '' 15 | fullName = '' 16 | mobile = '' 17 | profilePhoto = '' 18 | 19 | /** 20 | * @param {Object} args - User arguments supplied during 21 | * user creation 22 | */ 23 | constructor (args) { 24 | Object.keys(args).forEach((v, i) => { 25 | this[v] = args[v] 26 | }) 27 | 28 | return { 29 | ...this 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /data/profile/src/pages/Auth.vue: -------------------------------------------------------------------------------- 1 | 69 | 70 | 131 | 132 | 138 | -------------------------------------------------------------------------------- /data/profile/src/pages/Error404.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 24 | -------------------------------------------------------------------------------- /data/profile/src/pages/ForgotPassword.vue: -------------------------------------------------------------------------------- 1 | 30 | 31 | 71 | 72 | 84 | -------------------------------------------------------------------------------- /data/profile/src/pages/Index.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /data/profile/src/pages/user/Profile.vue: -------------------------------------------------------------------------------- 1 | 40 | 41 | 108 | 121 | -------------------------------------------------------------------------------- /data/profile/src/pages/user/profile/UserSettings.vue: -------------------------------------------------------------------------------- 1 | 50 | 51 | 142 | 180 | -------------------------------------------------------------------------------- /data/profile/src/router/index.js: -------------------------------------------------------------------------------- 1 | import firebaseServices from '../services/firebase' 2 | import { Notify } from 'quasar' 3 | import { store } from '../store' 4 | import Vue from 'vue' 5 | import VueRouter from 'vue-router' 6 | 7 | import routes from './routes' 8 | 9 | Vue.use(VueRouter) 10 | 11 | /* 12 | * If not building with SSR mode, you can 13 | * directly export the Router instantiation 14 | */ 15 | 16 | export default function (/* { store, ssrContext } */) { 17 | const Router = new VueRouter({ 18 | scrollBehavior: () => ({ x: 0, y: 0 }), 19 | routes, 20 | 21 | // Leave these as they are and change in quasar.conf.js instead! 22 | // quasar.conf.js -> build -> vueRouterMode 23 | // quasar.conf.js -> build -> publicPath 24 | mode: process.env.VUE_ROUTER_MODE, 25 | base: process.env.VUE_ROUTER_BASE 26 | }) 27 | 28 | // Navigational Guards 29 | Router.beforeEach(async (to, from, next) => { 30 | const { 31 | ensureAuthIsInitialized, 32 | isAuthenticated 33 | } = firebaseServices 34 | try { 35 | // Force the app to wait until Firebase has 36 | // finished its initialization, and handle the 37 | // authentication state of the user properly 38 | await ensureAuthIsInitialized(store) 39 | if (to.matched.some(record => record.meta.requiresAuth)) { 40 | if (isAuthenticated(store)) { 41 | next() 42 | } else { 43 | next('/auth/login') 44 | } 45 | } else if ((to.path === '/auth/register' && isAuthenticated(store)) || 46 | (to.path === '/auth/login' && isAuthenticated(store))) { 47 | next('/user/profile') 48 | } else { 49 | next() 50 | } 51 | } catch (err) { 52 | Notify.create({ 53 | message: `${err}`, 54 | color: 'negative' 55 | }) 56 | } 57 | }) 58 | 59 | return Router 60 | } 61 | -------------------------------------------------------------------------------- /data/profile/src/router/routes.js: -------------------------------------------------------------------------------- 1 | const routes = [ 2 | { 3 | path: '/', 4 | component: () => import('layouts/Basic.vue'), 5 | children: [ 6 | { 7 | path: '', 8 | component: () => import('pages/Index.vue') 9 | } 10 | ] 11 | }, 12 | { 13 | path: '/auth', 14 | component: () => import('layouts/Basic.vue'), 15 | children: [ 16 | { 17 | path: 'forgotPassword', 18 | name: 'ForgotPassword', 19 | component: () => import('pages/ForgotPassword.vue') 20 | }, 21 | { 22 | path: 'login', 23 | name: 'Login', 24 | component: () => import('pages/Auth.vue') 25 | }, 26 | { 27 | path: 'register', 28 | name: 'Register', 29 | component: () => import('pages/Auth.vue') 30 | } 31 | ] 32 | }, 33 | { 34 | path: '/user', 35 | component: () => import('layouts/User.vue'), 36 | children: [ 37 | { 38 | path: 'profile', 39 | name: 'UserProfile', 40 | component: () => import('pages/user/Profile.vue'), 41 | meta: { 42 | requiresAuth: true 43 | } 44 | } 45 | ] 46 | } 47 | ] 48 | 49 | // Always leave this as last one 50 | routes.push({ 51 | path: '*', 52 | component: () => import('pages/Error404.vue') 53 | }) 54 | 55 | export default routes 56 | -------------------------------------------------------------------------------- /data/profile/src/services/firebase/base.js: -------------------------------------------------------------------------------- 1 | 2 | import firebase from 'firebase/app' 3 | import 'firebase/auth' 4 | 5 | /** 6 | * Returns Firebase 's global namespace from which all Firebase services are accessed 7 | * https://firebase.google.com/docs/reference/js/firebase.auth.html#callable 8 | * @return {Object} Firebase Module 9 | */ 10 | export const self = () => { 11 | return firebase 12 | } 13 | 14 | /** 15 | * Returns Firebase's auth service 16 | * https://firebase.google.com/docs/reference/js/firebase.auth.html#callable 17 | * @returns {Auth} - The Firebase Auth service interface 18 | */ 19 | export const auth = () => { 20 | return firebase.auth() 21 | } 22 | 23 | /** 24 | * Async function providing the application time to 25 | * wait for firebase to initialize and determine if a 26 | * user is authenticated or not with only a single observable. 27 | * https://firebase.google.com/docs/reference/js/firebase.auth.Auth#onauthstatechanged 28 | * @param {Object} store - Vuex store 29 | * @returns {Promise} - A promise that return firebase.Unsubscribe 30 | */ 31 | export const ensureAuthIsInitialized = (store) => { 32 | if (store.state.auth.isReady) return true 33 | // Create the observer only once on init 34 | return new Promise((resolve, reject) => { 35 | // Use a promise to make sure that the router will eventually show the route after the auth is initialized. 36 | const unsubscribe = firebase.auth().onAuthStateChanged(() => { 37 | resolve() 38 | unsubscribe() 39 | }, () => { 40 | reject(new Error('Looks like there is a problem with the firebase service. Please try again later')) 41 | }) 42 | }) 43 | } 44 | 45 | /** 46 | * Convenience method to initialize firebase app 47 | * https://firebase.google.com/docs/reference/js/firebase?authuser=1#initializeapp 48 | * @param {Object} config - FIREBASE_CONFIG during the build process 49 | * @returns {App} - Creates and initializes a Firebase app instance. 50 | */ 51 | export const fBInit = (config) => { 52 | return firebase.initializeApp(config) 53 | } 54 | 55 | /** 56 | * Handle the auth state of the user and set it in the auth store module. 57 | * Also sets up redirection if the user loses authentication. The action 58 | * method will determine where the application routes to. 59 | * @param {Object} store - Vuex Store 60 | * @param {Object} currentUser - Firebase currentUser 61 | */ 62 | export const handleOnAuthStateChanged = async (store, currentUser) => { 63 | const initialAuthState = isAuthenticated(store) 64 | // Save to the store 65 | store.commit('auth/setAuthState', { 66 | isAuthenticated: currentUser !== null, 67 | isReady: true, 68 | uid: (currentUser ? currentUser.uid : '') 69 | }) 70 | 71 | // Get & bind the current user 72 | if (store.state.auth.isAuthenticated) { 73 | await store.dispatch('user/getCurrentUser', currentUser.uid) 74 | } 75 | 76 | // If the user looses authentication route 77 | // them to the login page 78 | if (!currentUser && initialAuthState) { 79 | store.dispatch('auth/routeUserToAuth') 80 | } 81 | } 82 | 83 | /** 84 | * @param {Object} store - Vuex store 85 | * @return {Boolean} - isAuthenticated 86 | */ 87 | export const isAuthenticated = (store) => { 88 | return store.state.auth.isAuthenticated 89 | } 90 | 91 | /** 92 | * Removes firebase auth token 93 | * @returns {Promise} - Void 94 | */ 95 | export const logoutUser = () => { 96 | return auth().signOut() 97 | } 98 | -------------------------------------------------------------------------------- /data/profile/src/services/firebase/db.js: -------------------------------------------------------------------------------- 1 | import firebase from 'firebase/app' 2 | import 'firebase/auth' 3 | import 'firebase/firestore' 4 | import 'firebase/storage' 5 | 6 | /** 7 | * @interface Firestore 8 | * https://firebase.google.com/docs/reference/js/firebase.firestore#callable 9 | * 10 | * @return {Object} - Firestore 11 | */ 12 | export const firestore = () => { 13 | return firebase.firestore() 14 | } 15 | /** 16 | * @param {String} collectionName - Firestore collection name 17 | * @param {String} id - Uid to assign to a doc in firestore collection 18 | * @returns {Object} - DcoumentReferecne https://firebase.google.com/docs/reference/js/firebase.firestore.DocumentReference 19 | */ 20 | export const docRef = (collectionName, id) => { 21 | return firestore().collection(collectionName).doc(id) 22 | } 23 | 24 | /** 25 | * @param {String} storageLocation - Location on Firebase Storage 26 | * @returns {Object} Reference to a Google Cloud Storage object. 27 | */ 28 | export const storageRef = (storageLocation) => { 29 | return firebase.storage().ref(storageLocation) 30 | } 31 | -------------------------------------------------------------------------------- /data/profile/src/services/firebase/email.js: -------------------------------------------------------------------------------- 1 | import firebase from 'firebase/app' 2 | import 'firebase/auth' 3 | 4 | /** 5 | * https://firebase.google.com/docs/reference/js/firebase.auth.Auth#createuserwithemailandpassword 6 | * @param {String} email - A Valid email 7 | * @param {String} password - Password 8 | * @returns {Promise} - UserCredentials https://firebase.google.com/docs/reference/js/firebase.auth#usercredential 9 | */ 10 | export const createUserWithEmail = async (email, password) => { 11 | return firebase.auth().createUserWithEmailAndPassword(email, password) 12 | } 13 | 14 | /** 15 | * https://firebase.google.com/docs/reference/js/firebase.auth.Auth#signinwithemailandpassword 16 | * @param {String} email - A Valid email 17 | * @param {String} password - Password 18 | * @returns {Promise} - UserCredentials https://firebase.google.com/docs/reference/js/firebase.auth#usercredential 19 | */ 20 | export const loginWithEmail = (email, password) => { 21 | return firebase.auth().signInWithEmailAndPassword(email, password) 22 | } 23 | -------------------------------------------------------------------------------- /data/profile/src/services/firebase/index.js: -------------------------------------------------------------------------------- 1 | import * as base from './base.js' 2 | import * as db from './db.js' 3 | import * as email from './email.js' 4 | 5 | /* 6 | Assign the base service to the firebaseServices namespace in the 7 | serviceConnection boot file. Over time other service modules separate by 8 | logic/concerns will be added here. Be aware of name conflicts between 9 | your modules. 10 | */ 11 | export default Object.assign({}, base, db, email) 12 | -------------------------------------------------------------------------------- /data/profile/src/store/auth/actions.js: -------------------------------------------------------------------------------- 1 | /* 2 | Remember, we have access to our Vue instance not using 3 | an arrow function in our actions file. This allows us 4 | to create a scoped reference to our firebaseService - $fb 5 | That was assigned to the Vue instance earlier in our serviceConnection 6 | boot file. 7 | */ 8 | 9 | import { firestoreAction } from 'vuexfire' 10 | import User from '../../models/User.js' 11 | import { docRef } from '../../services/firebase/db.js' 12 | import { Notify } from 'quasar' 13 | 14 | export const addUserToUsersCollection = function (state, userRef) { 15 | const 16 | { email } = state, 17 | user = new User({ email }) 18 | return userRef.set(user) 19 | } 20 | 21 | /** 22 | * @param {Object} $root - Place holder argument(Vuex store) to allow data to be passed 23 | * as second argument. 24 | * @param data.email - User's email 25 | * @param data.password - User's password 26 | * @returns {function} - Firebase services function: 27 | * src/services/firebase/email.js > createUserWithEmail 28 | */ 29 | export const createNewUser = async function ($root, data) { 30 | const $fb = this.$fb 31 | const { email, password } = data 32 | const fbAuthResponse = await $fb.createUserWithEmail(email, password) 33 | const id = fbAuthResponse.user.uid 34 | const userRef = docRef('users', id) 35 | return addUserToUsersCollection({ email }, userRef) 36 | } 37 | 38 | /** 39 | * @param {Object} $root - Place holder argument(Vuex store) to allow data to be passed 40 | * as second argument. 41 | * @param data.email - User's email 42 | * @param data.password - User's password 43 | * @returns {function} - Firebase services function: 44 | * src/services/firebase/email.js > loginWithEmail 45 | */ 46 | export const loginUser = async function ($root, data) { 47 | const $fb = this.$fb 48 | const { email, password } = data 49 | return $fb.loginWithEmail(email, password) 50 | } 51 | 52 | /** 53 | * @returns {function} - Firebase services function: 54 | * src/services/firebase/email.js > logoutUser 55 | */ 56 | export const logoutUser = async function ({ commit }) { 57 | try { 58 | await firestoreAction(({ unbindFirestoreRef }) => { unbindFirestoreRef('currentUser') }) 59 | await this.$fb.logoutUser() 60 | commit('common/setDrawerOpen', false, { root: true }) 61 | } catch (err) { 62 | Notify.create({ 63 | type: 'webapp_error', 64 | message: `An error as occured [logoutUser]: ${err}` 65 | }) 66 | } 67 | } 68 | 69 | export function routeUserToAuth () { 70 | this.$router.push({ 71 | path: '/auth/login' 72 | }) 73 | } 74 | -------------------------------------------------------------------------------- /data/profile/src/store/auth/getters.js: -------------------------------------------------------------------------------- 1 | export function someGetter (/* state */) { 2 | } 3 | -------------------------------------------------------------------------------- /data/profile/src/store/auth/index.js: -------------------------------------------------------------------------------- 1 | import state from './state' 2 | import * as getters from './getters' 3 | import * as mutations from './mutations' 4 | import * as actions from './actions' 5 | 6 | export default { 7 | namespaced: true, 8 | getters, 9 | mutations, 10 | actions, 11 | state 12 | } 13 | -------------------------------------------------------------------------------- /data/profile/src/store/auth/mutations.js: -------------------------------------------------------------------------------- 1 | export function setAuthState (state, data) { 2 | state.isAuthenticated = data.isAuthenticated 3 | state.isReady = data.isReady 4 | state.uid = data.uid 5 | } 6 | -------------------------------------------------------------------------------- /data/profile/src/store/auth/state.js: -------------------------------------------------------------------------------- 1 | export default { 2 | isAuthenticated: false, 3 | isReady: false, 4 | uid: '' 5 | } 6 | -------------------------------------------------------------------------------- /data/profile/src/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | import { vuexfireMutations } from 'vuexfire' 4 | 5 | import auth from './auth' 6 | import user from './user' 7 | 8 | Vue.use(Vuex) 9 | 10 | /* 11 | * If not building with SSR mode, you can 12 | * directly export the Store instantiation 13 | */ 14 | let store = null 15 | export default function (/* { ssrContext } */) { 16 | const Store = new Vuex.Store({ 17 | modules: { 18 | auth, 19 | user 20 | }, 21 | mutations: { 22 | ...vuexfireMutations 23 | }, 24 | 25 | // enable strict mode (adds overhead!) 26 | // for dev mode only 27 | strict: process.env.DEV 28 | }) 29 | store = Store 30 | return Store 31 | } 32 | 33 | export { store } 34 | -------------------------------------------------------------------------------- /data/profile/src/store/store-flag.d.ts: -------------------------------------------------------------------------------- 1 | // THIS FEATURE-FLAG FILE IS AUTOGENERATED, 2 | // REMOVAL OR CHANGES WILL CAUSE RELATED TYPES TO STOP WORKING 3 | import "quasar/dist/types/feature-flag"; 4 | 5 | declare module "quasar/dist/types/feature-flag" { 6 | interface QuasarFeatureFlags { 7 | store: true; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /data/profile/src/store/user/actions.js: -------------------------------------------------------------------------------- 1 | import { firestoreAction } from 'vuexfire' 2 | import { docRef } from '../../services/firebase/db.js' 3 | 4 | /** Get current user from the firestore collection user's 5 | * via firebase uid 6 | * @param {String} id - Firebase currentUser id 7 | * @returns {Function} bindFirestoreRef - https://vuefire.vuejs.org/api/vuexfire.html#bindfirestoreref 8 | */ 9 | export const getCurrentUser = firestoreAction(({ bindFirestoreRef }, id) => { 10 | return bindFirestoreRef('currentUser', docRef('users', id)) 11 | }) 12 | 13 | /** 14 | * @param {Object} $root - Place holder argument(Vuex store) to allow data to be passed 15 | * as second argument. 16 | * @param data.id - Firestore document id 17 | * @param {Object} data - User's data to be updated 18 | * @returns {Function} - Firebase services function: 19 | * src/services/firebase/db.js > docRef 20 | */ 21 | export const updateUserData = async function ($root, data) { 22 | return docRef('users', data.id).update(data) 23 | } 24 | -------------------------------------------------------------------------------- /data/profile/src/store/user/getters.js: -------------------------------------------------------------------------------- 1 | export const currentUser = ({ currentUser }) => currentUser 2 | export const editUserDialog = ({ editUserDialog }) => editUserDialog 3 | -------------------------------------------------------------------------------- /data/profile/src/store/user/index.js: -------------------------------------------------------------------------------- 1 | import state from './state' 2 | import * as getters from './getters' 3 | import * as mutations from './mutations' 4 | import * as actions from './actions' 5 | 6 | export default { 7 | namespaced: true, 8 | getters, 9 | mutations, 10 | actions, 11 | state 12 | } 13 | -------------------------------------------------------------------------------- /data/profile/src/store/user/mutations.js: -------------------------------------------------------------------------------- 1 | export const setEditUserDialog = (state, editUserDialog) => { 2 | state.editUserDialog = editUserDialog 3 | } 4 | -------------------------------------------------------------------------------- /data/profile/src/store/user/state.js: -------------------------------------------------------------------------------- 1 | export default { 2 | currentUser: null, 3 | editUserDialog: false 4 | } 5 | -------------------------------------------------------------------------------- /data/profile/src/utils/environmentConfig.js: -------------------------------------------------------------------------------- 1 | const ENV = require('dotenv').config().parsed 2 | /* 3 | Use an environment variable set in package.json scripts to determine 4 | the applications runtime environment. Add more switch cases as 5 | need for additional environments. Remember, Firebase recomends supporting 6 | separate Firebase project for different application environments: httpsq://firebase.google.com/docs/projects/multiprojects#support_different_environments 7 | */ 8 | 9 | module.exports = (QENV) => { 10 | if (!['DEV', 'STAGE', 'PROD'].includes(QENV)) { 11 | throw Error('Unknonw or not supplied environment variable') 12 | } 13 | return { 14 | FIREBASE_CONFIG: { 15 | apiKey: ENV[`${QENV}_API_KEY`], 16 | authDomain: ENV[`${QENV}_AUTH_DOMAIN`], 17 | databaseURL: ENV[`${QENV}_DATA_BASE_URL`], 18 | projectId: ENV[`${QENV}_PROJECT_ID`], 19 | storageBucket: ENV[`${QENV}_STORAGE_BUCKET`], 20 | messagingSenderId: ENV[`${QENV}_MESSAGING_SENDER_ID`], 21 | appId: ENV[`${QENV}_APP_ID`] 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "src/*": [ 6 | "src/*" 7 | ], 8 | "app/*": [ 9 | "*" 10 | ], 11 | "components/*": [ 12 | "src/components/*" 13 | ], 14 | "layouts/*": [ 15 | "src/layouts/*" 16 | ], 17 | "pages/*": [ 18 | "src/pages/*" 19 | ], 20 | "assets/*": [ 21 | "src/assets/*" 22 | ], 23 | "boot/*": [ 24 | "src/boot/*" 25 | ], 26 | "vue$": [ 27 | "node_modules/vue/dist/vue.esm.js" 28 | ] 29 | } 30 | }, 31 | "exclude": [ 32 | "dist", 33 | ".quasar", 34 | "node_modules" 35 | ] 36 | } --------------------------------------------------------------------------------