mycv's People
mycv's Issues
add
authenticate
//server
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const fs = require('fs');
const cors = require('cors');
const basicAuth = require('./routes/user/_helpers/basic-auth');
const errorHandler = require('./routes/user/_helpers/error-handler');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors())
// use basic HTTP auth to secure the api
// app.use(basicAuth);
const routes = require('./routes/routes.js')(app, fs);
// global error handler
app.use(errorHandler);
const server = app.listen(3001, () => {
console.log('listening on port %s...', server.address().port);
});
//routes
// import other routes
const userRoutes = require('./user/users');
const postRoutes = require('./post/posts');
const appRouter = (app, fs) => {
// default route
app.get('/', (req, res) => {
res.send('welcome to the development api-server');
});
// // other routes
userRoutes(app, fs);
postRoutes(app, fs);
};
module.exports = appRouter;
//usersjs
const userRoutes = (app, fs) => {
// variables
const dataPath = './data/users.json'
const userService = require('./users/user.service')
// helper methods
const readFile = (
callback,
returnJson = false,
filePath = dataPath,
encoding = 'utf8'
) => {
fs.readFile(filePath, encoding, (err, data) => {
if (err) {
throw err
}
callback(returnJson ? JSON.parse(data) : data)
})
}
const writeFile = (
fileData,
callback,
filePath = dataPath,
encoding = 'utf8'
) => {
fs.writeFile(filePath, fileData, encoding, err => {
if (err) {
throw err
}
callback()
})
}
// AUTHENTICATE USER
app.post('/users/authenticate', authenticate)
function authenticate(req, res, next) {
userService
.authenticate(req.body)
.then(user =>
user
? res.json(user)
: res
.status(400)
.json({ message: 'Username or password is incorrect' })
)
.catch(err => next(err))
}
// READ
app.get('/users', (req, res) => {
fs.readFile(dataPath, 'utf8', (err, data) => {
if (err) {
throw err
}
res.send(JSON.parse(data))
})
})
// CREATE
app.post('/users', (req, res) => {
readFile(data => {
const newUserId = Object.keys(data).length + 1
// add the new user
data[newUserId.toString()] = req.body
writeFile(JSON.stringify(data, null, 2), () => {
res.status(200).send('new user added')
})
}, true)
})
// UPDATE
app.put('/users/:id', (req, res) => {
readFile(data => {
// add the new user
const userId = req.params['id']
data[userId] = req.body
writeFile(JSON.stringify(data, null, 2), () => {
res.status(200).send(`users id:${userId} updated`)
})
}, true)
})
// DELETE
app.delete('/users/:id', (req, res) => {
readFile(data => {
// add the new user
const userId = req.params['id']
delete data[userId]
writeFile(JSON.stringify(data, null, 2), () => {
res.status(200).send(`users id:${userId} removed`)
})
}, true)
})
}
module.exports = userRoutes
//userservice
const dataPath = './data/users.json'
// helper methods
// const readFile = (
// callback,
// returnJson = false,
// filePath = dataPath,
// encoding = 'utf8'
// ) => {
// fs.readFile(filePath, encoding, (err, data) => {
// if (err) {
// throw err
// }
// callback(returnJson ? JSON.parse(data) : data)
// })
// }
// users hardcoded for simplicity, store in a db for production applications
const users = [{ id: 1, username: 'test', password: 'test', firstName: 'Test', lastName: 'User' }];
module.exports = {
authenticate,
getAll
}
async function authenticate({ username, password }) {
const user = users.find(
u => u.username === username && u.password === password
)
if (user) {
const { password, ...userWithoutPassword } = user
return userWithoutPassword
}
}
async function getAll() {
return users.map(u => {
const { password, ...userWithoutPassword } = u
return userWithoutPassword
})
}
//basic-auth
const userService = require('../users/user.service');
module.exports = basicAuth;
async function basicAuth(req, res, next) {
// make authenticate path public
if (req.path === '/users/authenticate') {
return next();
}
// check for basic auth header
if (!req.headers.authorization || req.headers.authorization.indexOf('Basic ') === -1) {
return res.status(401).json({ message: 'Missing Authorization Header' });
}
// verify auth credentials
const base64Credentials = req.headers.authorization.split(' ')[1];
const credentials = Buffer.from(base64Credentials, 'base64').toString('ascii');
const [username, password] = credentials.split(':');
const user = await userService.authenticate({ username, password });
if (!user) {
return res.status(401).json({ message: 'Invalid Authentication Credentials' });
}
// attach user to request object
req.user = user
next();
}
edit
table list
fix bug modal
<template>
<v-dialog :value="value" @input="$emit('input')" max-width="600" persistent>
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>
<v-tabs background-color="grey lighten-2" v-model="tabs">
<v-tab>Sign In</v-tab>
<v-tab>Sign Up</v-tab>
</v-tabs>
</v-card-title>
<v-tabs-items v-model="tabs">
<v-tab-item>
<v-form ref="form" v-model="signInValid">
<v-card-text>
<v-container>
<v-row>
<v-col cols="12">
<v-text-field
v-model="user.username"
:counter="18"
:rules="usernameRules"
label="Username*"
required
></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field
v-model="user.password"
:counter="18"
:rules="passwordRules"
label="Password*"
type="password"
required
></v-text-field>
</v-col>
</v-row>
</v-container>
<!-- <small>*indicates required field</small> -->
</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="green" text @click.native="$emit('input')">Close</v-btn>
<v-btn color="primary" :disabled="!signInValid" @click="signIn">Sign In</v-btn>
</v-card-actions>
</v-form>
</v-tab-item>
<v-tab-item>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12" sm="6" md="4">
<v-text-field label="Legal first name*" required></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
label="Legal middle name"
hint="example of helper text only on focus"
></v-text-field>
</v-col>
<v-col cols="12" sm="6" md="4">
<v-text-field
label="Legal last name*"
hint="example of persistent helper text"
persistent-hint
required
></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field label="Email*" required></v-text-field>
</v-col>
<v-col cols="12">
<v-text-field label="Password*" type="password" required></v-text-field>
</v-col>
<v-col cols="12" sm="6">
<v-select :items="['0-17', '18-29', '30-54', '54+']" label="Age*" required></v-select>
</v-col>
<v-col cols="12" sm="6">
<v-autocomplete
:items="['Skiing', 'Ice hockey', 'Soccer', 'Basketball', 'Hockey', 'Reading', 'Writing', 'Coding', 'Basejump']"
label="Interests"
multiple
></v-autocomplete>
</v-col>
</v-row>
</v-container>
<small>*indicates required field</small>
</v-card-text>
</v-tab-item>
</v-tabs-items>
</v-card>
</v-dialog>
</template>
<script>
import axios from "axios";
export default {
name: "UserDialog",
data() {
return {
user: {},
signInValid: true,
tabs: null,
usernameRules: [
v => !!v || "Username is required",
v => (v && v.length <= 18) || "Username must be less than 18 characters"
],
passwordRules: [
v => !!v || "Password is required",
v => (v && v.length <= 18) || "Password must be less than 18 characters"
]
};
},
props: {
value: {
type: Boolean
}
},
methods: {
signIn() {
axios
.post("http://localhost:3001/users/authenticate", {
username: this.user.username,
password: this.user.password
})
.then(response => {
if (response) {
// store user details and basic auth credentials in local storage
// to keep user logged in between page refreshes
response.authdata = window.btoa(
this.user.username + ":" + this.user.password
);
localStorage.setItem("user", JSON.stringify(response));
window.location.href("http://localhost:8080/");
}
// this.$router.re({ path: "/home" });
})
.catch(e => {
this.errors.push(e);
});
}
}
};
</script>
express-lowdb
// const start = async function() {
// const adapter = new FileAsync(link);
// const db = await low(adapter);
// // Get all
// router.get("/products", function(req, res, next) {
// const products = db
// .get("products")
// .orderBy(["id"], ["desc"])
// .value();
// res.send(products);
// });
// // Create
// router.post("/products", function(req, res, next) {
// const newProductId = Object.keys(db.get("products").value()).length + 1;
// let object = req.body;
// let data = {
// userId: object.userId,
// id: newProductId,
// img: "https://cdn.vuetifyjs.com/images/cards/sunshine.jpg",
// title: object.title,
// description: object.description,
// content: object.content
// };
// db.get("products")
// .push(data)
// .write();
// });
// };
App.vue
<v-img
alt="Vuetify Name"
class="shrink mt-1 hidden-sm-and-down"
contain
min-width="100"
src="https://cdn.vuetifyjs.com/images/logos/vuetify-name-dark.png"
width="100"
/>
</div>
<v-spacer></v-spacer>
<v-tabs background-color="primary" right hide-slider>
<v-tab :to="{name:'HomePage'}">Home</v-tab>
<v-tab :to="{name:'ProductTable'}" v-if="Object.keys(user).length !== 0">Product list</v-tab>
<v-tab :to="{name:'ProductAddNew'}" v-if="Object.keys(user).length !== 0">Add Product</v-tab>
</v-tabs>
<v-btn
color="success"
dark
@click="openDialog = true"
v-if="Object.keys(user).length === 0"
>Account</v-btn>
<v-menu bottom left v-if="Object.keys(user).length !== 0">
<template v-slot:activator="{ on }">
<v-btn dark icon v-on="on">
<v-icon>mdi-account-circle</v-icon>
</v-btn>
</template>
<v-list>
<v-list-item v-for="(item, i) in menu" :key="i" @click="selectItem(i)">
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-app-bar>
<user-dialog v-model="openDialog" />
<v-content>
<router-view></router-view>
</v-content>
route.js
import Vue from 'vue'
import Router from 'vue-router'
import HomePage from '@/components/HomePage'
import ProductDetail from '@/components/Product/ProductDetail'
import ProductTable from '@/components/Product/ProductTable'
import ProductAddNew from '@/components/Product/ProductAddNew'
import ProductEdit from '@/components/Product/ProductEdit'
Vue.use(Router)
const router = new Router({
routes: [
{
path: '/',
redirect: '/home'
},
{
path: '/home',
name: 'HomePage',
component: HomePage
},
{
path: '/product-detail/:id',
name: 'ProductDetail',
component: ProductDetail
},
{
path: '/product',
name: 'ProductTable',
component: ProductTable
},
{
path: '/add-product',
name: 'ProductAddNew',
component: ProductAddNew
},
{
path: '/edit-product/:id',
name: 'ProductEdit',
component: ProductEdit
}
]
})
router.beforeEach((to, from, next) => {
// redirect to login page if not logged in and trying to access a restricted page
const publicPages = ['/home', '/product-detail']
const path = to.path.split('/')[1]
const authRequired = !publicPages.includes('/' + path)
const loggedIn = localStorage.getItem('user')
if (authRequired && !loggedIn) {
return next({
path: '/home',
query: { returnUrl: to.path }
})
}
next()
})
export default router
use modal dialog
<template>
<v-row dense>
<v-col cols="3" v-for="product in products" :key="product.id">
<v-card class="mx-auto" outlined>
<v-list-item three-line>
<v-list-item-content>
<v-list-item-title class="headline mb-1">{{product.name}}</v-list-item-title>
<v-list-item-subtitle>{{product.title}}</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
<v-card-actions>
<v-btn dark color="cyan" @click="openDialog = true, productSelectedFromChild = product">
<v-icon dark>mdi-television</v-icon>
</v-btn>
<v-btn :to="{ name: 'ProductDetail', params: { id: product.id }}" color="primary">Detail</v-btn>
</v-card-actions>
</v-card>
</v-col>
<product-dialog v-model="openDialog" :productDetailInfo="productSelectedFromChild" />
</v-row>
</template>
<script>
import axios from "axios";
import ProductDialog from "./ProductDialog.vue";
export default {
name: "ProductList",
components: {
ProductDialog
},
data: function() {
return {
productSelectedFromChild: {},
openDialog: false,
products: [],
errors: []
};
},
created() {
axios
.get("http://localhost:3001/posts")
.then(response => {
this.products = response.data;
})
.catch(e => {
this.errors.push(e);
});
},
methods: {
// This line below
selectProduct(product) {
this.$emit("productSelected", product);
}
}
};
</script>
<template>
<v-dialog
:value="value"
@input="$emit('input')"
max-width="500"
v-if="Object.keys(productDetailInfo).length !== 0"
>
<v-card>
<v-card-title class="headline grey lighten-2" primary-title>{{ productDetailInfo.name }}</v-card-title>
<v-card-text>{{ productDetailInfo.title }}</v-card-text>
<v-divider></v-divider>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="green" text @click.native="$emit('input')">Close</v-btn>
<v-btn color="primary">Detail</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
name: "ProductDialog",
props: {
value: {
type: Boolean
},
productDetailInfo: {
type: Object
}
}
};
</script>
init editor
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
import { TiptapVuetifyPlugin } from 'tiptap-vuetify'
// don't forget to import styles
import 'tiptap-vuetify/dist/main.css'
const vuetify = new Vuetify()
Vue.use(TiptapVuetifyPlugin, {
// the next line is important! You need to provide the Vuetify Object to this place.
vuetify, // same as "vuetify: vuetify"
// optional, default to 'md' (default vuetify icons before v2.0.0)
iconsGroup: 'md'
})
export default new Vuetify({})
import Vue from 'vue'
import App from './App.vue'
import vuetify from './plugins/vuetify'
import router from './router'
import 'material-design-icons-iconfont/dist/material-design-icons.css'
import axios from 'axios'
import tiptapVuetifyPlugin from './plugins/tiptap'
Vue.config.productionTip = false
const baseURL = 'http://localhost:3001'
Vue.prototype.$axios = axios.create({ baseURL })
new Vue({
vuetify,
tiptapVuetifyPlugin,
router,
render: h => h(App)
}).$mount('#app')
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.