@ -0,0 +1,86 @@ | |||||
<app-users> | |||||
<div class="buckets"> | |||||
<table class="table"> | |||||
<div class="table__row" each={ user in state.users }> | |||||
<div class="table__column"> | |||||
{ user.username } | |||||
</div> | |||||
<div class="table__column"> | |||||
{ user.email } | |||||
</div> | |||||
<div class="table__column"> | |||||
</div> | |||||
</div> | |||||
</table> | |||||
<div class="grid" if={ state.maxLength > state.users.length }> | |||||
<div class="col-12"> | |||||
<div class="buckets__more"> | |||||
<button type="button" class="button" onclick={ handleClick }> | |||||
More | |||||
<svg class="icon" aria-hidden="true"> | |||||
<use xlink:href="/symbol-defs.svg#icon-arrow-down"></use> | |||||
</svg> | |||||
</button> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<script> | |||||
import axios from 'axios' | |||||
import remove from 'lodash.remove' | |||||
/** | |||||
* | |||||
* | |||||
* | |||||
* @author Björn Hase | |||||
* | |||||
*/ | |||||
export default { | |||||
state: { | |||||
users: [], | |||||
maxLength: 0 | |||||
}, | |||||
onBeforeMount() { | |||||
this.fetch() | |||||
}, | |||||
handleClick() { | |||||
}, | |||||
handleDelete(event, bucket) { | |||||
event.preventDefault() | |||||
axios.delete('/api/bucket/' + bucket._id) | |||||
.then((response) => { | |||||
// removing from buckets | |||||
remove(this.state.buckets, function(b) { | |||||
return b._id === bucket._id | |||||
}) | |||||
this.update() | |||||
}) | |||||
}, | |||||
/** | |||||
* getting all buckets | |||||
* | |||||
* | |||||
*/ | |||||
fetch() { | |||||
axios.get('/api/users').then((response) => { | |||||
this.state.users = response.data.data | |||||
this.update() | |||||
}) | |||||
} | |||||
} | |||||
</script> | |||||
</app-users> |
@ -0,0 +1,128 @@ | |||||
<app-users-form> | |||||
<div class="sidebar sidebar--open"> | |||||
<div class="sidebar__inner"> | |||||
<div class="bar"> | |||||
<div class="bar__main"> | |||||
Create User | |||||
</div> | |||||
<div class="bar__end"> | |||||
<button class="button button--transparent" type="button" onclick={ (event) => { handleClose(event) } }> | |||||
<svg class="icon fill-text-contrast" aria-hidden="true"> | |||||
<use xlink:href="/symbol-defs.svg#icon-close"></use> | |||||
</svg> | |||||
</button> | |||||
</div> | |||||
</div> | |||||
<div class="sidebar__body"> | |||||
<form id="app-users-form"> | |||||
<div class="field-group"> | |||||
<label class="field-label"> | |||||
<input name="email" type="text" class="field-text" /> | |||||
</label> | |||||
<field-error name="email"></field-error> | |||||
</div> | |||||
<div class="field-group"> | |||||
<label class="field-label"> | |||||
Password | |||||
<input name="password" type="password" class="field-text" /> | |||||
</label> | |||||
<field-error name="password"></field-error> | |||||
</div> | |||||
</form> | |||||
</div> | |||||
<div class="sidebar__footer"> | |||||
<button class="button m-bottom-0" type="submit" form="app-users-form"> | |||||
Save | |||||
<svg class="icon fill-success p-left-3" aria-hidden="true"> | |||||
<use xlink:href="/symbol-defs.svg#icon-check"></use> | |||||
</svg> | |||||
</button> | |||||
<button class="button m-bottom-0" type="submit" form="app-users-form"> | |||||
Save and Close | |||||
<svg class="icon fill-success p-left-3" aria-hidden="true"> | |||||
<use xlink:href="/symbol-defs.svg#icon-arrow-right"></use> | |||||
</svg> | |||||
</button> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<script> | |||||
import axios from 'axios' | |||||
import * as riot from 'riot' | |||||
import FormValidator from './../../FormValidator' | |||||
import FieldError from './../field-error.riot' | |||||
riot.register('field-error', FieldError) | |||||
riot.mount('field-error') | |||||
export default { | |||||
state: { | |||||
user: { } | |||||
}, | |||||
/** | |||||
* | |||||
* | |||||
*/ | |||||
onMounted(props, state) { | |||||
// create form validation | |||||
const formValidation = new FormValidator('app-users-form', { | |||||
'email': { | |||||
'length': { | |||||
'maximum': 255 | |||||
}, | |||||
'email': true, | |||||
'presence': true | |||||
}, | |||||
'password': { | |||||
'length': { | |||||
'maximum': 64 | |||||
}, | |||||
'presence': true | |||||
} | |||||
}, (event, data) => { | |||||
this.handleSubmit(event, data) | |||||
}) | |||||
}, | |||||
handleClose(event) | |||||
{ | |||||
event.preventDefault() | |||||
this.$('.sidebar').classList.remove('sidebar--open') | |||||
}, | |||||
/** | |||||
* | |||||
* | |||||
*/ | |||||
handleSubmit(event, data) { | |||||
let method = 'post' | |||||
if (this.state.user && this.state.user._id) { | |||||
method = 'put' | |||||
} | |||||
axios({ | |||||
method: method, | |||||
url: '/api/users', | |||||
data: data | |||||
}).then((response) => { | |||||
this.state.user = response.data.data | |||||
this.update() | |||||
}) | |||||
} | |||||
} | |||||
</script> | |||||
</app-users-form> |
@ -0,0 +1,11 @@ | |||||
import * as riot from 'riot' | |||||
import AppUsers from './components/users.riot' | |||||
import AppUsersForm from './components/users/form.riot' | |||||
// register components for buckets | |||||
riot.register('app-users', AppUsers) | |||||
riot.mount('app-users') | |||||
riot.register('app-users-form', AppUsersForm) | |||||
riot.mount('app-users-form') |
@ -0,0 +1,68 @@ | |||||
.sidebar { | |||||
position: fixed; | |||||
top: 0; | |||||
left: 0; | |||||
width: 100%; | |||||
height: 100%; | |||||
max-width: 33%; | |||||
z-index: 1; | |||||
visibility: hidden; | |||||
transition: visibility 0s linear 0.5s; | |||||
&__body { | |||||
@extend .panel__body; | |||||
} | |||||
&__inner { | |||||
@extend .panel; | |||||
position: relative; | |||||
height: 100%; | |||||
transition: transform 0.2s; | |||||
transform: translateX(-100%); | |||||
} | |||||
&__footer { | |||||
position: fixed; | |||||
left: 0; | |||||
bottom: 0; | |||||
display: flex; | |||||
justify-content: space-between; | |||||
background: var(--background); | |||||
width: 100%; | |||||
padding: 1rem; | |||||
} | |||||
&:before { | |||||
position: fixed; | |||||
top: 0; | |||||
left: 0; | |||||
width: 100%; | |||||
height: 100%; | |||||
background-color: transparent; | |||||
transition: background-color 0.5s; | |||||
z-index: 0; | |||||
content: ""; | |||||
} | |||||
&--open { | |||||
visibility: visible; | |||||
transition: visibility 0s linear 0s; | |||||
.sidebar__inner { | |||||
transform: translateX(0); | |||||
} | |||||
&:before { | |||||
background: rgba(0,0,0,.7); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,15 @@ | |||||
<% layout('./layout.html') %> | |||||
<div class="container container--app"> | |||||
<div class="grid"> | |||||
<div class="col-12"> | |||||
<h1 class="highlight"> | |||||
Users | |||||
</h1> | |||||
<app-users></app-users> | |||||
<app-users-form></app-users-form> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<script type="text/javascript" src="/js/users.js" defer></script> |
@ -0,0 +1,57 @@ | |||||
import 'https://deno.land/x/dotenv@v2.0.0/load.ts' | |||||
import { | |||||
opine, | |||||
serveStatic, | |||||
json, | |||||
urlencoded | |||||
} from 'https://deno.land/x/opine@1.5.3/mod.ts' | |||||
import { dirname, join, createError } from "https://deno.land/x/opine@1.5.3/deps.ts"; | |||||
import { renderFile } from 'https://deno.land/x/eta@v1.12.2/mod.ts' | |||||
// middleware | |||||
import session from './src/middleware/session.ts' | |||||
// getting routes | |||||
import index from './src/http/index.ts' | |||||
//import bucket from './src/http/bucket.ts' | |||||
//import settings from './src/http/settings.ts' | |||||
import users from './src/http/users.ts' | |||||
//import bucketApi from './src/http/api/bucket.ts' | |||||
//import noteApi from './src/http/api/note.ts' | |||||
const app = opine() | |||||
const __dirname = dirname(import.meta.url) | |||||
// for parsing application/json | |||||
app.use(json()) | |||||
// for parsing application/x-www-form-urlencoded | |||||
app.use(urlencoded()) | |||||
// adding static files | |||||
app.use(serveStatic(join(__dirname, 'public'))) | |||||
// adding eta as view engine | |||||
app.engine('.html', renderFile) | |||||
app.set('views', join(__dirname, 'resources/views')) | |||||
app.set('view engine', 'html') | |||||
// adding http classes for routes | |||||
app.use('*', session) | |||||
app.use('/', index) | |||||
//app.use('/bucket', bucket) | |||||
//app.use('/settings', settings) | |||||
app.use('/users', users) | |||||
//app.use('/api/bucket', bucketApi) | |||||
//app.use('/api/note', noteApi) | |||||
app.use((request, response, next) => { | |||||
response.setStatus(404) | |||||
response.render('errors/404') | |||||
}) | |||||
// let it rain | |||||
app.listen(Number(Deno.env.get('SERVER_PORT'))) | |||||
console.log('running on ' + Deno.env.get('SERVER_PORT')) |
@ -0,0 +1,93 @@ | |||||
import { v4 } from "https://deno.land/std@0.99.0/uuid/mod.ts"; | |||||
import { validate, required, isIn, maxLength } from 'https://deno.land/x/validasaur@v0.15.0/mod.ts' | |||||
import { Database } from 'https://deno.land/x/aloedb@0.9.0/mod.ts' | |||||
import { BucketSchema } from './../../stores/bucket.ts' | |||||
import { NoteSchema } from './../../stores/note.ts' | |||||
import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts' | |||||
const router = Router() | |||||
/** | |||||
* | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.post('/:bucket_id', async function(request, response) | |||||
{ | |||||
const body = request.body | |||||
const [ valid, errors ] = await validate(body, { | |||||
title: [ maxLength(255) ], | |||||
content: [ maxLength(10922) ] | |||||
}) | |||||
if (valid) { | |||||
const noteRepository = new NoteRepository(request.bucket._id) | |||||
note = await db.insertOne(body) | |||||
} | |||||
response.json({ | |||||
data: note | |||||
}) | |||||
}) | |||||
/** | |||||
* | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.put('/:bucket_id', async function(request, response, next) | |||||
{ | |||||
const body = request.body | |||||
let note | |||||
// check if uuid is valid | |||||
if (!v4.validate(request.params.bucket_id)) { | |||||
response.setStatus(404) | |||||
} | |||||
// check if bucket exists | |||||
const bucketDb = new Database<BucketSchema>('./storage/database/buckets.json') | |||||
const bucket = await bucketDb.findOne({ _id: request.params.bucket_id }) | |||||
if (!bucket) { | |||||
response.setStatus(404) | |||||
} | |||||
const [ valid, errors ] = await validate(body, { | |||||
title: [ maxLength(255) ], | |||||
content: [ maxLength(10922) ] | |||||
}) | |||||
if (valid && bucket) { | |||||
// getting database and search by uuid | |||||
const db = new Database<NoteSchema>('./storage/database/' + bucket._id + '.json') | |||||
note = await db.updateOne({ _id: body._id }, body) | |||||
} | |||||
response.json({ | |||||
data: note | |||||
}) | |||||
}) | |||||
/** | |||||
* | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.delete('/:bucket_id/:id', function(request, response, next) | |||||
{ | |||||
}) | |||||
export default router |
@ -0,0 +1,149 @@ | |||||
import { v4 } from "https://deno.land/std@0.99.0/uuid/mod.ts"; | |||||
import { validate, required, isIn, maxLength } from 'https://deno.land/x/validasaur@v0.15.0/mod.ts' | |||||
import { Database } from 'https://deno.land/x/aloedb@0.9.0/mod.ts' | |||||
import { UserSchema } from './../../stores/user.ts' | |||||
import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts' | |||||
const router = Router() | |||||
/** | |||||
* get all users | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
* | |||||
*/ | |||||
router.get('/', async function(request, response) | |||||
{ | |||||
const userRepository = new UserRepository() | |||||
const users = await userRepository.db.findAll() | |||||
response.json({ | |||||
data: user | |||||
}) | |||||
}) | |||||
/** | |||||
* create user | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
* | |||||
*/ | |||||
router.get('/:id', async function(request, response) | |||||
{ | |||||
const userRepository = new UserRepository() | |||||
const [ valid, errors ] = await validate(request.params, { | |||||
id: [ required, uuid ] | |||||
}) | |||||
if (valid) { | |||||
const user = await userRepository.db.findOne({ | |||||
'_id': request.params.id | |||||
}) | |||||
if (!user) { | |||||
response.setStatus(404) | |||||
} | |||||
} else { | |||||
response.setStatus(405) | |||||
} | |||||
response.json({ | |||||
data: user | |||||
}) | |||||
}) | |||||
/** | |||||
* create user | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
* | |||||
*/ | |||||
router.post('/', async function(request, response) | |||||
{ | |||||
const body = request.body | |||||
const userRepository = new UserRepository() | |||||
const [ valid, errors ] = await validate(body, { | |||||
email: [ email, required ] | |||||
}) | |||||
if (valid) { | |||||
user = await userRepository.create(body) | |||||
} | |||||
response.json({ | |||||
data: user | |||||
}) | |||||
}) | |||||
/** | |||||
* | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.put('/:id', async function(request, response, next) | |||||
{ | |||||
const body = request.body | |||||
const userRepository = new UserRepository() | |||||
let user = false | |||||
const [ valid, errors ] = await validate(body, { | |||||
_id: [ required, uuid, exists ], | |||||
email: [ email, required, unique ], | |||||
password: [ maxLength(64) ], | |||||
displayname: [ maxLength(128) ], | |||||
role: [ array() ] | |||||
}) | |||||
if (valid) { | |||||
user = userRepository.update(body) | |||||
} | |||||
response.json({ | |||||
data: user | |||||
}) | |||||
}) | |||||
/** | |||||
* | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
* | |||||
*/ | |||||
router.delete('/:id', function(request, response) | |||||
{ | |||||
const userRepository = new UserRepository() | |||||
let user = false | |||||
const [ valid, errors ] = await validate(request.params, { | |||||
'_id': [ required, uuid, exists ] | |||||
}) | |||||
if (valid) { | |||||
user = userRepository.db.deleteOne({ | |||||
'_id': request.params._id | |||||
}) | |||||
} | |||||
response.json({ | |||||
data: user | |||||
}) | |||||
}) | |||||
export default router |
@ -0,0 +1,60 @@ | |||||
import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts' | |||||
import UserRepository from '../../repositories/user.ts' | |||||
import { validate, required, maxLength, isEmail } from 'https://deno.land/x/validasaur@v0.15.0/mod.ts' | |||||
const router = Router() | |||||
/** | |||||
* get all users | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
* | |||||
*/ | |||||
router.get('/', async function(request, response) | |||||
{ | |||||
const userRepository = new UserRepository() | |||||
const users = await userRepository.db.findMany() | |||||
response.json({ | |||||
data: users | |||||
}) | |||||
}) | |||||
/** | |||||
* create user | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
* | |||||
*/ | |||||
router.post('/', async function(request, response) | |||||
{ | |||||
const body = request.body | |||||
const userRepository = new UserRepository() | |||||
let user = [] | |||||
const [ valid, errors ] = await validate(body, { | |||||
email: [ isEmail, maxLength(255), required ], | |||||
password: [ required, maxLength(64) ] | |||||
}) | |||||
if (valid) { | |||||
user = await userRepository.create(body) | |||||
// remove password | |||||
// @TODO make sure repository can hide variables | |||||
delete user.password | |||||
} | |||||
response.json({ | |||||
data: user | |||||
}) | |||||
}) | |||||
export default router |
@ -0,0 +1,43 @@ | |||||
import { validate, required, email } from 'https://deno.land/x/validasaur@v0.15.0/mod.ts' | |||||
import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts' | |||||
const router = Router() | |||||
/** | |||||
* auth user, check for password in db | |||||
* and create jwt | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.post('/', async function(request, response) | |||||
{ | |||||
if (body.password) { | |||||
body.password = escapeHtml(body.password) | |||||
} | |||||
const [ valid, errors ] = await validate(body, { | |||||
email: [ required, email ], | |||||
password: [ required, maxLength(64) ] | |||||
}); | |||||
if (valid) { | |||||
// check if user exists | |||||
user = await userRepository.db.findOne({ | |||||
'email': body.email | |||||
}) | |||||
if (user) { | |||||
result = userRepository.verifyPassword(user, body.password) | |||||
if (result) { | |||||
response.cookie('auth-token', jwt) | |||||
} | |||||
} | |||||
} | |||||
response.redirect('/') | |||||
} |
@ -0,0 +1,23 @@ | |||||
import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts' | |||||
import bucketMiddleware from '../middleware/bucket.ts' | |||||
const router = Router() | |||||
// check for id and try load bucket | |||||
router.param('bucket_id', bucketMiddleware) | |||||
/** | |||||
* render single bucket | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.get('/:bucket_id', async function(request, response) | |||||
{ | |||||
response.render('bucket/single', { | |||||
bucket: response.locals.bucket | |||||
}) | |||||
}) | |||||
export default router |
@ -0,0 +1,17 @@ | |||||
import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts' | |||||
const router = Router() | |||||
/** | |||||
* render template for settings | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @return | |||||
*/ | |||||
router.get('/', function(request, response, next) | |||||
{ | |||||
response.render('users') | |||||
}) | |||||
export default router |
@ -0,0 +1,51 @@ | |||||
import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts' | |||||
import { validate, required } from 'https://deno.land/x/validasaur@v0.15.0/mod.ts' | |||||
import { uuid } from '../rules/uuid.ts' | |||||
import BucketRepository from '../repositories/bucket.ts' | |||||
const router = Router() | |||||
/** | |||||
* check every route for single bucket | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @param next | |||||
* @return | |||||
*/ | |||||
async function bucketMiddleware(request: any, response: any, next: any) | |||||
{ | |||||
// max for id | |||||
request.params.bucket_id = request.params.bucket_id.slice(0, 128) | |||||
// only dash, numbers & letters are allowed | |||||
request.params.bucket_id = request.params.bucket_id.replace(/[^a-z0-9-]/gi, '') | |||||
const [ valid, errors ] = await validate(request.params, { | |||||
bucket_id: [ uuid ] | |||||
}) | |||||
// if invalid send 404 | |||||
if (!valid) { | |||||
response | |||||
.setStatus(404) | |||||
.send() | |||||
} | |||||
// getting | |||||
const bucketRepository = new BucketRepository() | |||||
const bucket = await bucketRepository.db.findOne({ '_id': request.params.bucket_id }) | |||||
// if not exists send 404 | |||||
if (!bucket) { | |||||
response | |||||
.setStatus(404) | |||||
.send() | |||||
} | |||||
response.locals.bucket = bucket | |||||
next() | |||||
} | |||||
export default bucketMiddleware |
@ -0,0 +1,32 @@ | |||||
import { Router } from 'https://deno.land/x/opine@1.5.3/mod.ts' | |||||
import { v4 } from 'https://deno.land/std@0.99.0/uuid/mod.ts' | |||||
import UserRepository from './../repositories/user.ts' | |||||
export default async function(request: any, response: any, next: any) | |||||
{ | |||||
request.user = false | |||||
try { | |||||
const token = request.headers.authorization.split(' ')[1]; | |||||
// if v4 is not validate next | |||||
if (!v4.validate(token)) { | |||||
next() | |||||
} | |||||
// search for user with session id | |||||
const userRepository = new UserRepository() | |||||
const user = await userRepository.db.findOne({ | |||||
'session_id': token | |||||
}) | |||||
if (user) { | |||||
response.locals.user = user | |||||
} | |||||
} catch(error) { | |||||
} | |||||
next() | |||||
} |
@ -0,0 +1,36 @@ | |||||
import { v4 } from 'https://deno.land/std@0.99.0/uuid/mod.ts' | |||||
import { Database } from 'https://deno.land/x/aloedb@0.9.0/mod.ts' | |||||
import { BucketSchema } from '../stores/bucket.ts' | |||||
/** | |||||
* | |||||
* | |||||
*/ | |||||
class BucketRepository | |||||
{ | |||||
db: any | |||||
constructor() | |||||
{ | |||||
this.db = new Database<BucketSchema>('./storage/database/buckets.json') | |||||
} | |||||
/** | |||||
* | |||||
*/ | |||||
async create(data: any) | |||||
{ | |||||
data._id = v4.generate() | |||||
return await this.db.insertOne(data) | |||||
} | |||||
/** | |||||
* | |||||
*/ | |||||
async update(data: any) | |||||
{ | |||||
return await this.db.updateOne({ '_id': data._id }, data) | |||||
} | |||||
} | |||||
export default BucketRepository |
@ -0,0 +1,47 @@ | |||||
import * as bcrypt from 'https://deno.land/x/bcrypt@v0.2.4/mod.ts' | |||||
import { v4 } from 'https://deno.land/std@0.99.0/uuid/mod.ts' | |||||
import { Database } from 'https://deno.land/x/aloedb@0.9.0/mod.ts' | |||||
import { UserSchema } from './../stores/user.ts' | |||||
/** | |||||
* | |||||
* | |||||
*/ | |||||
class UserRepository | |||||
{ | |||||
db: any; | |||||
constructor() | |||||
{ | |||||
this.db = new Database<UserSchema>('./../../storage/database/users.json') | |||||
} | |||||
/** | |||||
* | |||||
*/ | |||||
async create(data: any) | |||||
{ | |||||
data._id = v4.generate() | |||||
data.password = await bcrypt.hash(data.password) | |||||
return await this.db.insertOne(data) | |||||
} | |||||
/** | |||||
* | |||||
*/ | |||||
async update(data: any) | |||||
{ | |||||
const user = await this.db.findOne({ '_id': data._id }) | |||||
// if password has changed hash password new | |||||
if (user && user.password !== data.password) { | |||||
data.password = await bcrypt.hash(data.password) | |||||
} | |||||
return await this.db.updateOne({ '_id': data._id }, data) | |||||
} | |||||
} | |||||
export default UserRepository |
@ -0,0 +1,23 @@ | |||||
import { invalid, Validity, Rule } from "https://deno.land/x/validasaur/mod.ts"; | |||||
/** | |||||
* | |||||
* @param id | |||||
* @return | |||||
*/ | |||||
export function exists(id: string): Rule { | |||||
return async function existsRule(value: any): Promise<Validity> { | |||||
if (typeof value !== 'string' && typeof value !== 'number') { | |||||
return invalid('exists', { value, table, column }); | |||||
} | |||||
const data = await db.findOne({ | |||||
key: value | |||||
}) | |||||
if (data !== null) { | |||||
return invalid('unique', { value, table, column }); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,25 @@ | |||||
import { invalid, Validity, Rule } from "https://deno.land/x/validasaur/mod.ts"; | |||||
/** | |||||
* search for key | |||||
* | |||||
* @param key | |||||
* @param value | |||||
* @return | |||||
*/ | |||||
export function unique(key: string, value: string): Rule { | |||||
return async function uniqueRule(value: any): Promise<Validity> { | |||||
if (typeof value !== 'string' && typeof value !== 'number') { | |||||
return invalid('unique', { value, table, column }); | |||||
} | |||||
const data = await db.findOne({ | |||||
key: value | |||||
}) | |||||
if (data !== null) { | |||||
return invalid('unique', { value, table, column }); | |||||
} | |||||
} | |||||
} |
@ -0,0 +1,19 @@ | |||||
import { invalid, Validity } from 'https://deno.land/x/validasaur@v0.15.0/mod.ts' | |||||
import { v4 } from 'https://deno.land/std@0.99.0/uuid/mod.ts' | |||||
/** | |||||
* validate uuid v4 | |||||
* | |||||
* @param value | |||||
* @return <Promise> | |||||
* | |||||
*/ | |||||
export async function uuid(value: any): Promise<Validity> { | |||||
if (typeof value !== 'string') { | |||||
return invalid('uuid', { value: value }) | |||||
} | |||||
if (!v4.validate(value)) { | |||||
return invalid('uuid', { value: value }) | |||||
} | |||||
} |
@ -1,13 +0,0 @@ | |||||
import { validate, required, isNumber } from 'https://deno.land/x/validasaur@0.15.0/mod.ts' | |||||
// create shema for validation | |||||
const BucketSchema = Schema({ | |||||
title: string.trim().normalize(), | |||||
description: string.trim().normalize().optional(), | |||||
type: Schema.either('a', 'b', 'c'), | |||||
visiblity: Schema.either('a', 'b', 'c') | |||||
}) | |||||
// create type and get validator from schema | |||||
export type bucketType = Type<typeof BucketSchema> | |||||
export const bucketValidator = BucketSchema.destruct() |
@ -1,15 +0,0 @@ | |||||
import Schema, { Type, string, number, array } from 'https://denoporter.sirjosh.workers.dev/v1/deno.land/x/computed_types/src/index.ts' | |||||
// create shema for validation | |||||
const NoteSchema = Schema({ | |||||
title: string.trim().normalize(), | |||||
description: string.trim().normalize().optional(), | |||||
type: Schema.either('a', 'b', 'c'), | |||||
visiblity: Schema.either('a', 'b', 'c') | |||||
}) | |||||
// create type and get validator from schema | |||||
type Note = Type<typeof NoteSchema> | |||||
const validator = NoteSchema.destruct() | |||||
export default validator |
@ -1,14 +0,0 @@ | |||||
import Schema, { Type, string, number, array } from 'https://denoporter.sirjosh.workers.dev/v1/deno.land/x/computed_types/src/index.ts' | |||||
// create shema for validation | |||||
const UserSchema = Schema({ | |||||
username: string.trim().normalize(), | |||||
password: string.normalize(), | |||||
email: Schema.email() | |||||
}) | |||||
// create type and get validator from schema | |||||
type User = Type<typeof UserSchema> | |||||
const validator = UserSchema.destruct() | |||||
export default validator |