mirror of
https://github.com/quepasaevents/qpa-client.git
synced 2023-12-14 05:33:02 +01:00
Basic features without packing deps into bundle
This commit is contained in:
parent
6fb939b431
commit
050b125b8e
|
@ -4,10 +4,15 @@
|
|||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@google-cloud/datastore": "^1.4.0",
|
||||
"@types/es6-promise": "^3.3.0",
|
||||
"@types/node": "^9.6.1",
|
||||
"mailgun-js": "^0.16.0",
|
||||
"randomstring": "^1.1.5",
|
||||
"tslint": "^5.9.1",
|
||||
"typescript": "^2.8.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc "
|
||||
"build": "tsc"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
7
src/config.ts
Normal file
7
src/config.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
export const domain = 'quepasaalpujarra.com'
|
||||
export const mailgun = {
|
||||
apiKey: 'key-64fc7260cecfd4a8d5fb51e97791b330',
|
||||
domain
|
||||
}
|
||||
export const projectId = 'calendar-189316'
|
||||
|
18
src/index.ts
18
src/index.ts
|
@ -1,3 +1,17 @@
|
|||
export const hello = (req, res) => {
|
||||
res.send(`Hello World!`);
|
||||
import {parse} from 'url'
|
||||
import { getUser } from './user'
|
||||
|
||||
export const isUserAvailable = async (req, res) => {
|
||||
const params = parse(req.url, true).query
|
||||
|
||||
const user = await getUser({
|
||||
email: params.email as string,
|
||||
username: params.username as string
|
||||
})
|
||||
|
||||
res.send({
|
||||
exists: !!user
|
||||
});
|
||||
|
||||
return true
|
||||
}
|
24
src/post_office.ts
Normal file
24
src/post_office.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import mailgun from 'mailgun-js';
|
||||
import {mailgun as mailgunConfig} from './config';
|
||||
|
||||
const client = mailgun(mailgunConfig);
|
||||
|
||||
interface Email {
|
||||
from: string
|
||||
to: string
|
||||
subject: string
|
||||
text: string
|
||||
}
|
||||
|
||||
export const sendEmail = async (email: Email) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
mailgun.messages().send(email, function (error, body) {
|
||||
if (error) {
|
||||
reject(error)
|
||||
} else {
|
||||
resolve(body)
|
||||
}
|
||||
});
|
||||
|
||||
})
|
||||
}
|
43
src/repository.ts
Normal file
43
src/repository.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
const Datastore = require('@google-cloud/datastore')
|
||||
import {SessionInvite, User, UserKeys} from './types'
|
||||
import { projectId } from './config'
|
||||
|
||||
const datastore = Datastore({
|
||||
projectId: projectId,
|
||||
});
|
||||
|
||||
export default class Repository {
|
||||
|
||||
static createUser(user: User) {
|
||||
const entity = {
|
||||
key: datastore.key('User'),
|
||||
data: user
|
||||
}
|
||||
return datastore.save(entity)
|
||||
}
|
||||
|
||||
static async saveSessionInvite(invite: SessionInvite) {
|
||||
const entity = {
|
||||
key: datastore.key('SessionInvite'),
|
||||
data: invite
|
||||
}
|
||||
return await datastore.save(entity)
|
||||
}
|
||||
|
||||
static async getUser (user: UserKeys) {
|
||||
let query = datastore
|
||||
.createQuery('user')
|
||||
|
||||
if (user.email) {
|
||||
query = query.filter('email', '=', user.email)
|
||||
}
|
||||
if (user.username) {
|
||||
query = query.filter('username', '=', user.username)
|
||||
}
|
||||
|
||||
return await datastore.runQuery(query)
|
||||
.then(results => {
|
||||
return results[0]
|
||||
});
|
||||
};
|
||||
}
|
40
src/session.ts
Normal file
40
src/session.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
// Free API to get location from IP: http://freegeoip.net/json/149.11.144.50
|
||||
import randomstring from 'randomstring'
|
||||
|
||||
import { sendEmail } from './post_office'
|
||||
import { domain } from './config'
|
||||
import repository from './repository'
|
||||
import {SessionInvite, User} from "./types";
|
||||
|
||||
const newInvite = (user: User): SessionInvite => {
|
||||
return {
|
||||
oneTimeKey: randomstring.generate({
|
||||
length: 24,
|
||||
charset: 'alphabetic'
|
||||
}),
|
||||
userId: user.id
|
||||
}
|
||||
};
|
||||
|
||||
export const inviteUser = async (user: User) => {
|
||||
const invite = newInvite(user)
|
||||
try {
|
||||
await repository.saveSessionInvite(invite)
|
||||
} catch (e) {
|
||||
console.error('Failed to save invite', invite)
|
||||
throw e;
|
||||
}
|
||||
|
||||
try {
|
||||
await sendEmail({
|
||||
to: user.email,
|
||||
from: `signin@${domain}`,
|
||||
text: `invitation for session key: ${invite.oneTimeKey}`,
|
||||
subject: 'Invitation for session'
|
||||
})
|
||||
} catch (e) {
|
||||
console.error('Failed to send invitation email', invite)
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
28
src/types.d.ts
vendored
Normal file
28
src/types.d.ts
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
export interface Session {
|
||||
createdAt: Date
|
||||
ttlMs: number
|
||||
expired: boolean
|
||||
authMethod: string
|
||||
hash: string
|
||||
userAgent: string
|
||||
location: string
|
||||
}
|
||||
|
||||
export interface SessionInvite {
|
||||
oneTimeKey: string
|
||||
userId: string
|
||||
}
|
||||
|
||||
interface DBEntity {
|
||||
id: string
|
||||
}
|
||||
|
||||
interface UserKeys {
|
||||
username: string,
|
||||
email: string
|
||||
}
|
||||
|
||||
interface User extends UserKeys, DBEntity {
|
||||
firstName: string
|
||||
lastName?: string
|
||||
}
|
6
src/user.ts
Normal file
6
src/user.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import {UserKeys} from './types'
|
||||
import repository from './repository'
|
||||
|
||||
export const getUser = async (keys: UserKeys) => {
|
||||
return await repository.getUser(keys)
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"target": "es2015",
|
||||
"module": "commonjs",
|
||||
"outDir": "dist/"
|
||||
},
|
||||
"lib": [
|
||||
"es2016"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
|
|
Loading…
Reference in a new issue