stash
This commit is contained in:
parent
d21f4a331b
commit
bbbf15cfb3
5 changed files with 130 additions and 44 deletions
|
@ -6,7 +6,6 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
<link rel="shortcut icon" href="/src/assets/icons/toolshed-48x48.png" type="image/png">
|
<link rel="shortcut icon" href="/src/assets/icons/toolshed-48x48.png" type="image/png">
|
||||||
<title>Toolshed</title>
|
<title>Toolshed</title>
|
||||||
<link href="/src/assets/base.css" rel="stylesheet">
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
|
@ -98,7 +98,7 @@
|
||||||
<ul class="list-inline">
|
<ul class="list-inline">
|
||||||
<li class="list-inline-item">
|
<li class="list-inline-item">
|
||||||
<a class="text-muted"
|
<a class="text-muted"
|
||||||
target="_blank" href="https://github.com/gr4yj3d1/toolshed">Dev Docs</a>
|
target="_blank" href="/docs/">API Docs</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-inline-item">
|
<li class="list-inline-item">
|
||||||
<a class="text-muted"
|
<a class="text-muted"
|
||||||
|
|
|
@ -72,28 +72,18 @@ export default createStore({
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
async login({commit, dispatch, state}, {username, password, remember}) {
|
async login({commit, dispatch, state}, {username, password, remember}) {
|
||||||
//this.setRemember(remember)
|
commit('setRemember', remember);
|
||||||
this.commit('setRemember', remember);
|
|
||||||
/*const response = await fetch('http://10.23.42.128:8000/auth/token/', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
username: username, password: password
|
|
||||||
})
|
|
||||||
})*/
|
|
||||||
const data = await dispatch('apiLocalPost', {
|
const data = await dispatch('apiLocalPost', {
|
||||||
target: '/token/', data: {
|
target: '/auth/token/', data: {
|
||||||
username: username, password: password
|
username: username, password: password
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if (data.token) {
|
if (data.token) {
|
||||||
commit('setToken', data.token);
|
commit('setToken', data.token);
|
||||||
commit('setUser', username + '@example.com');
|
commit('setUser', username);
|
||||||
const j = await dispatch('apiLocalGet', {target: '/keys/'})
|
const j = await dispatch('apiLocalGet', {target: '/auth/keys/'})
|
||||||
const k = j.key
|
const k = j.key
|
||||||
this.commit('setKey', k)
|
commit('setKey', k)
|
||||||
await router.push({path: '/'});
|
await router.push({path: '/'});
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -120,6 +110,9 @@ export default createStore({
|
||||||
if (state.unreachable_neighbors.queryUnreachable(host)) {
|
if (state.unreachable_neighbors.queryUnreachable(host)) {
|
||||||
throw new Error('unreachable neighbor')
|
throw new Error('unreachable neighbor')
|
||||||
}
|
}
|
||||||
|
if(!state.user || !state.keypair) {
|
||||||
|
throw new Error('no user or keypair')
|
||||||
|
}
|
||||||
const url = host + target
|
const url = host + target
|
||||||
const signature = nacl.crypto_sign_detached(nacl.encode_utf8(url), state.keypair.signSk)
|
const signature = nacl.crypto_sign_detached(nacl.encode_utf8(url), state.keypair.signSk)
|
||||||
const auth = 'Signature ' + state.user + ':' + nacl.to_hex(signature)
|
const auth = 'Signature ' + state.user + ':' + nacl.to_hex(signature)
|
||||||
|
@ -135,6 +128,9 @@ export default createStore({
|
||||||
if (state.unreachable_neighbors.queryUnreachable(host)) {
|
if (state.unreachable_neighbors.queryUnreachable(host)) {
|
||||||
throw new Error('unreachable neighbor')
|
throw new Error('unreachable neighbor')
|
||||||
}
|
}
|
||||||
|
if(!state.user || !state.keypair) {
|
||||||
|
throw new Error('no user or keypair')
|
||||||
|
}
|
||||||
const url = host + target
|
const url = host + target
|
||||||
const json = JSON.stringify(data)
|
const json = JSON.stringify(data)
|
||||||
const signature = nacl.crypto_sign_detached(nacl.encode_utf8(url + json), state.keypair.signSk)
|
const signature = nacl.crypto_sign_detached(nacl.encode_utf8(url + json), state.keypair.signSk)
|
||||||
|
@ -151,19 +147,21 @@ export default createStore({
|
||||||
},
|
},
|
||||||
async apiLocalGet({state}, {target}) {
|
async apiLocalGet({state}, {target}) {
|
||||||
const auth = state.token ? {'Authorization': 'Token ' + state.token} : {}
|
const auth = state.token ? {'Authorization': 'Token ' + state.token} : {}
|
||||||
return await fetch('http://10.23.42.128:8000/auth' + target, {
|
return await fetch(target, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: auth
|
headers: auth,
|
||||||
|
credentials: 'omit'
|
||||||
}).then(response => response.json())
|
}).then(response => response.json())
|
||||||
},
|
},
|
||||||
async apiLocalPost({state}, {target, data}) {
|
async apiLocalPost({state}, {target, data}) {
|
||||||
const auth = state.token ? {'Authorization': 'Token ' + state.token} : {}
|
const auth = state.token ? {'Authorization': 'Token ' + state.token} : {}
|
||||||
return await fetch('http://10.23.42.128:8000/auth' + target, {
|
return await fetch(target, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
...auth
|
...auth
|
||||||
},
|
},
|
||||||
|
credentials: 'omit',
|
||||||
body: JSON.stringify(data)
|
body: JSON.stringify(data)
|
||||||
}).then(response => response.json())
|
}).then(response => response.json())
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,34 +19,51 @@
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="m-sm-4">
|
<div class="m-sm-4">
|
||||||
<form role="form" method="post" action="">
|
<form role="form" method="post" @submit.prevent="do_register">
|
||||||
<!--{% csrf_token %}-->
|
<div :class="errors.username||errors.domain?['mb-3','is-invalid']:['mb-3']">
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label">Username</label>
|
<label class="form-label">Username</label>
|
||||||
<input class="form-control form-control-lg" type="text"
|
<div class="input-group">
|
||||||
name="username" placeholder="Enter your username"/>
|
<input class="form-control form-control-lg"
|
||||||
|
type="text" v-model="form.username" id="validationCustomUsername"
|
||||||
|
placeholder="Enter your username" required/>
|
||||||
|
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text form-control form-control-lg">@</span>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-error">{{ form.username.errors }}</span>
|
<select class="form-control form-control-lg"
|
||||||
<div class="mb-3">
|
id="exampleFormControlSelect1"
|
||||||
|
placeholder="Domain" v-model="form.domain" required>
|
||||||
|
<option v-for="domain in domains">{{ domain }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="invalid-feedback">
|
||||||
|
{{ errors.username }}{{ errors.domain }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div :class="errors.email?['mb-3','is-invalid']:['mb-3']">
|
||||||
<label class="form-label">Email</label>
|
<label class="form-label">Email</label>
|
||||||
<input class="form-control form-control-lg" type="email"
|
<input class="form-control form-control-lg" type="email"
|
||||||
name="email" placeholder="Enter your email"/>
|
v-model="form.email" placeholder="Enter your email"/>
|
||||||
|
<div class="invalid-feedback">{{ errors.email }}</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-error">{{ form.email.errors }}</span>
|
|
||||||
<div class="mb-3">
|
<div :class="errors.password?['mb-3','is-invalid']:['mb-3']">
|
||||||
<label class="form-label">Password</label>
|
<label class="form-label">Password</label>
|
||||||
<input class="form-control form-control-lg" type="password"
|
<input class="form-control form-control-lg" type="password"
|
||||||
name="password1" placeholder="Enter your password"/>
|
v-model="form.password" placeholder="Enter your password"/>
|
||||||
|
<div class="invalid-feedback">{{ errors.password }}</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-error">{{ form.password1.errors }}</span>
|
|
||||||
<div class="mb-3">
|
<div :class="errors.password2?['mb-3','is-invalid']:['mb-3']">
|
||||||
<label class="form-label">Password Check</label>
|
<label class="form-label">Password Check</label>
|
||||||
<input class="form-control form-control-lg" type="password"
|
<input class="form-control form-control-lg" type="password"
|
||||||
name="password2" placeholder="Enter your password again"/>
|
v-model="password2" placeholder="Enter your password again"/>
|
||||||
|
<div class="invalid-feedback">{{ errors.password2 }}</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-error">{{ form.password2.errors }}</span>
|
|
||||||
<div class="text-center mt-3">
|
<div class="text-center mt-3">
|
||||||
<button type="submit" name="register" class="btn btn-lg btn-primary">
|
<button type="submit" class="btn btn-lg btn-primary">
|
||||||
Register
|
Register
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -54,7 +71,8 @@
|
||||||
<br/>
|
<br/>
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<p class="mb-0 text-muted">
|
<p class="mb-0 text-muted">
|
||||||
Already have an account? <router-link to="/login">Login</router-link>
|
Already have an account?
|
||||||
|
<router-link to="/login">Login</router-link>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -73,16 +91,73 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
msg: 'Register',
|
msg: 'Register',
|
||||||
|
password2: '',
|
||||||
form: {
|
form: {
|
||||||
username: '',
|
username: '',
|
||||||
|
domain: '',
|
||||||
email: '',
|
email: '',
|
||||||
password1: '',
|
password: '',
|
||||||
password2: '',}
|
},
|
||||||
|
errors: {
|
||||||
|
username: null,
|
||||||
|
domain: null,
|
||||||
|
email: null,
|
||||||
|
password: null,
|
||||||
|
password2: null,
|
||||||
|
},
|
||||||
|
domains: []
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
do_register() {
|
||||||
|
console.log('do_register');
|
||||||
|
console.log(this.form);
|
||||||
|
if (this.form.password !== this.password2) {
|
||||||
|
this.errors.password2 = 'Passwords do not match';
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
this.errors.password2 = null;
|
||||||
|
}
|
||||||
|
fetch('/auth/register/', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(this.form)
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.errors) {
|
||||||
|
console.error('Error:', data.errors);
|
||||||
|
this.errors = data.errors;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('Success:', data);
|
||||||
|
this.msg = 'Success';
|
||||||
|
this.$router.push('/login');
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Error:', error);
|
||||||
|
this.msg = 'Error';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
fetch('/api/domains/')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
this.domains = data;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.is-invalid input, .is-invalid select {
|
||||||
|
border: 1px solid var(--bs-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-invalid .invalid-feedback {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -20,9 +20,23 @@ export default defineConfig({
|
||||||
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
||||||
'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Auth-Token, Authorization, Accept,charset,boundary,Content-Length',
|
'Access-Control-Allow-Headers': 'Origin, Content-Type, X-Auth-Token, Authorization, Accept,charset,boundary,Content-Length',
|
||||||
'Access-Control-Allow-Credentials': 'true'
|
'Access-Control-Allow-Credentials': 'true'
|
||||||
|
},
|
||||||
|
proxy: {
|
||||||
|
'^/api/': {
|
||||||
|
target: "http://127.0.0.1:8000/",
|
||||||
|
},
|
||||||
|
'^/auth/': {
|
||||||
|
target: "http://127.0.0.1:8000/",
|
||||||
|
},
|
||||||
|
'^/admin/': {
|
||||||
|
target: "http://127.0.0.1:8000/",
|
||||||
|
},
|
||||||
|
'^/docs/': {
|
||||||
|
target: "http://127.0.0.1:8000/",
|
||||||
|
},
|
||||||
|
'^/static/': {
|
||||||
|
target: "http://127.0.0.1:8000/",
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue