mirror of
https://github.com/fazo96/markcloud.git
synced 2025-01-10 11:04:21 +01:00
huge update with accounts and notifications, not yet finished
This commit is contained in:
parent
a94be4c4de
commit
eb58554689
@ -10,5 +10,7 @@ coffeescript
|
|||||||
less
|
less
|
||||||
perak:markdown
|
perak:markdown
|
||||||
natestrauser:font-awesome
|
natestrauser:font-awesome
|
||||||
|
accounts-password
|
||||||
mrt:moment
|
mrt:moment
|
||||||
|
reactive-var
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
accounts-base@1.1.1
|
||||||
|
accounts-password@1.0.2
|
||||||
application-configuration@1.0.2
|
application-configuration@1.0.2
|
||||||
autoupdate@1.1.1
|
autoupdate@1.1.1
|
||||||
base64@1.0.0
|
base64@1.0.0
|
||||||
@ -13,6 +15,7 @@ ctl@1.0.1
|
|||||||
ddp@1.0.9
|
ddp@1.0.9
|
||||||
deps@1.0.4
|
deps@1.0.4
|
||||||
ejson@1.0.3
|
ejson@1.0.3
|
||||||
|
email@1.0.3
|
||||||
fastclick@1.0.0
|
fastclick@1.0.0
|
||||||
follower-livedata@1.0.1
|
follower-livedata@1.0.1
|
||||||
geojson-utils@1.0.0
|
geojson-utils@1.0.0
|
||||||
@ -28,6 +31,7 @@ jquery@1.0.0
|
|||||||
json@1.0.0
|
json@1.0.0
|
||||||
less@1.0.9
|
less@1.0.9
|
||||||
livedata@1.0.10
|
livedata@1.0.10
|
||||||
|
localstorage@1.0.0
|
||||||
logging@1.0.3
|
logging@1.0.3
|
||||||
meteor-platform@1.1.1
|
meteor-platform@1.1.1
|
||||||
meteor@1.1.1
|
meteor@1.1.1
|
||||||
@ -38,6 +42,7 @@ mobile-status-bar@1.0.0
|
|||||||
mongo@1.0.6
|
mongo@1.0.6
|
||||||
mrt:moment@2.8.1
|
mrt:moment@2.8.1
|
||||||
natestrauser:font-awesome@4.2.0
|
natestrauser:font-awesome@4.2.0
|
||||||
|
npm-bcrypt@0.7.7
|
||||||
observe-sequence@1.0.2
|
observe-sequence@1.0.2
|
||||||
ordered-dict@1.0.0
|
ordered-dict@1.0.0
|
||||||
perak:markdown@1.0.4
|
perak:markdown@1.0.4
|
||||||
@ -47,9 +52,12 @@ reactive-var@1.0.2
|
|||||||
reload@1.1.0
|
reload@1.1.0
|
||||||
retry@1.0.0
|
retry@1.0.0
|
||||||
routepolicy@1.0.1
|
routepolicy@1.0.1
|
||||||
|
service-configuration@1.0.1
|
||||||
session@1.0.2
|
session@1.0.2
|
||||||
|
sha@1.0.0
|
||||||
spacebars-compiler@1.0.2
|
spacebars-compiler@1.0.2
|
||||||
spacebars@1.0.2
|
spacebars@1.0.2
|
||||||
|
srp@1.0.0
|
||||||
templating@1.0.7
|
templating@1.0.7
|
||||||
tracker@1.0.2
|
tracker@1.0.2
|
||||||
ui@1.0.3
|
ui@1.0.3
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
docs = new Meteor.Collection 'docs'
|
docs = new Meteor.Collection 'docs'
|
||||||
|
Meteor.subscribe 'user'
|
||||||
|
UI.registerHelper 'mail', -> Meteor.user().emails[0].address
|
||||||
|
|
||||||
Router.configure
|
Router.configure
|
||||||
layoutTemplate: 'layout'
|
layoutTemplate: 'layout'
|
||||||
|
loadingTemplate: 'loading'
|
||||||
|
|
||||||
Router.map ->
|
Router.map ->
|
||||||
@route 'home',
|
@route 'home',
|
||||||
@ -17,10 +20,30 @@ Router.map ->
|
|||||||
waitOn: -> @docHandle = Meteor.subscribe 'doc', @params._id
|
waitOn: -> @docHandle = Meteor.subscribe 'doc', @params._id
|
||||||
data: -> docs.findOne @params._id
|
data: -> docs.findOne @params._id
|
||||||
action: ->
|
action: ->
|
||||||
if @ready()
|
if @ready() then @render()
|
||||||
@render()
|
|
||||||
else @render 'loading'
|
else @render 'loading'
|
||||||
|
@route 'verify',
|
||||||
|
path: '/verify/:token'
|
||||||
|
template: 'loading'
|
||||||
|
onBeforeAction: ->
|
||||||
|
Accounts.verifyEmail @params.token, (err) ->
|
||||||
|
if err then errCallback err else Router.go 'home'
|
||||||
@route 'new'
|
@route 'new'
|
||||||
|
@route 'signup'
|
||||||
|
@route 'signin', path: 'login'
|
||||||
|
@route '404', path: '*'
|
||||||
|
|
||||||
|
notification = new ReactiveVar()
|
||||||
|
share.notify = notify = (opt) ->
|
||||||
|
if !opt then notification.set undefined
|
||||||
|
else
|
||||||
|
opt.type ?= "danger"
|
||||||
|
notification.set opt
|
||||||
|
errCallback = (err) ->
|
||||||
|
if err.reason then notify msg: err.reason else notify msg: err
|
||||||
|
Template.notifications.notification = -> notification.get()
|
||||||
|
Template.notifications.events
|
||||||
|
'click .close': -> notify()
|
||||||
|
|
||||||
Template.layout.showSpinner = ->
|
Template.layout.showSpinner = ->
|
||||||
Meteor.status().connected is no or Router.current().ready() is no
|
Meteor.status().connected is no or Router.current().ready() is no
|
||||||
@ -28,6 +51,25 @@ Template.home.ndocs = -> docs.find().count()
|
|||||||
Template.new.events
|
Template.new.events
|
||||||
'click #new-btn': (e,t) ->
|
'click #new-btn': (e,t) ->
|
||||||
id = docs.insert
|
id = docs.insert
|
||||||
|
title: t.find('#title').value
|
||||||
text: t.find('#editor').value
|
text: t.find('#editor').value
|
||||||
if id?
|
dateCreated: moment().unix()
|
||||||
|
if id
|
||||||
Router.go 'doc', _id: id
|
Router.go 'doc', _id: id
|
||||||
|
else notify msg: 'document creation failed'
|
||||||
|
|
||||||
|
Template.signup.events
|
||||||
|
'click #signup': (e,t) ->
|
||||||
|
if not t.find('#mail').value
|
||||||
|
return notify msg: 'please enter an email'
|
||||||
|
else if not t.find('#pw').value
|
||||||
|
return notify msg: "Please enter a password"
|
||||||
|
else if t.find('#pw').value isnt t.find('#rpw').value
|
||||||
|
return notify msg: "The passwords don't match"
|
||||||
|
else # Sending actual registration request
|
||||||
|
console.log t.find('#mail').value
|
||||||
|
Accounts.createUser {
|
||||||
|
email: t.find('#mail').value
|
||||||
|
password: t.find('#pw').value
|
||||||
|
}, (err) -> if err then errCallback err
|
||||||
|
else notify type: 'success', msg: 'check your email'
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>MarkCloud</title>
|
<title>MarkCloud</title>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
</head>
|
</head>
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
|
// Body
|
||||||
.container {
|
.container {
|
||||||
max-width: 40em;
|
max-width: 40em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.close {
|
||||||
|
margin-top: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loading and spinner
|
||||||
#spinner {
|
#spinner {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 1em;
|
right: 1em;
|
||||||
@ -12,6 +18,19 @@
|
|||||||
margin-top: 2em;
|
margin-top: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Editor
|
||||||
#new-btn {
|
#new-btn {
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sign up
|
||||||
|
#signup-container, #signin-container {
|
||||||
|
#mail { margin-top: 2em; }
|
||||||
|
#pw {
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
.btn {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -3,19 +3,25 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<h1>MarkCloud</h1>
|
<h1>MarkCloud</h1>
|
||||||
<hr>
|
<hr>
|
||||||
|
{{> notifications}}
|
||||||
{{> yield}}
|
{{> yield}}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="home">
|
<template name="home">
|
||||||
|
{{#if currentUser}}<p>Logged in as <b>{{mail}}</b></p>{{/if}}
|
||||||
<p>This is a demo app. Click <a href="new">here</a> to create a new document.</p>
|
<p>This is a demo app. Click <a href="new">here</a> to create a new document.</p>
|
||||||
<p>After submitting the document you will be redirected to its permanent link</p>
|
<p>After submitting the document you will be redirected to its permanent link</p>
|
||||||
<p>There are <b>{{ndocs}}</b> documents in the database</p>
|
<p>There are <b>{{ndocs}}</b> documents in the database</p>
|
||||||
<p>This demo was built by <a href="http://github.com/fazo96">Enrico Fasoli (fazo96)</a> in 45 minutes. It's open source, you can find the code <a href="http://github.com/fazo96/markcloud">here</a></p>
|
<p>This demo was built by <a href="http://github.com/fazo96">Enrico
|
||||||
|
Fasoli (fazo96)</a> in 45 minutes, it's now evolving to a full app.</p>
|
||||||
|
<p>It's open source, you can find the code
|
||||||
|
<a href="http://github.com/fazo96/markcloud">here</a></p>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template name="new">
|
<template name="new">
|
||||||
<p>Write your document in <a href="https://help.github.com/articles/github-flavored-markdown/">GitHub Flavored Markdown</a> then submit it with the button. You will be redirected to its permanent link</p>
|
<p>Write your document in <a href="https://help.github.com/articles/github-flavored-markdown/">GitHub Flavored Markdown</a> then submit it with the button. You will be redirected to its permanent link</p>
|
||||||
|
<input type="text" id="title" class="form-control" placeholder="Title">
|
||||||
<textarea id="editor" class="form-control" rows="10" autofocus></textarea>
|
<textarea id="editor" class="form-control" rows="10" autofocus></textarea>
|
||||||
<button id="new-btn" class="btn btn-primary">
|
<button id="new-btn" class="btn btn-primary">
|
||||||
<i class="fa fa-upload"></i> Upload</button>
|
<i class="fa fa-upload"></i> Upload</button>
|
||||||
@ -50,3 +56,40 @@
|
|||||||
<i class="fa fa-2x fa-cog fa-spin"></i>
|
<i class="fa fa-2x fa-cog fa-spin"></i>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template name="404">
|
||||||
|
<div class="text-center">
|
||||||
|
<h1>404</h1>
|
||||||
|
<p>This page does not exist.</p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template name="notifications">
|
||||||
|
{{#if notification}}
|
||||||
|
<div class="center-block text-center">
|
||||||
|
<div class="alert alert-{{notification.type}} error">
|
||||||
|
<p align="center">{{notification.msg}}</p>
|
||||||
|
<button type="button" class="close close-error">×</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template name="signup">
|
||||||
|
<div id="signup-container">
|
||||||
|
<h2>Sign Up</h2>
|
||||||
|
<input type="text" class="form-control" id="mail" placeholder="E-Mail Address">
|
||||||
|
<input type="password" class="form-control" placeholder="Password" id="pw">
|
||||||
|
<input type="password" class="form-control" placeholder="Repeat Password" id="rpw">
|
||||||
|
<button class="btn btn-primary" id="signup">Sign Up</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template name="signin">
|
||||||
|
<div id="signin-container">
|
||||||
|
<h2>Sign In</h2>
|
||||||
|
<input type="text" class="form-control" id="mail" placeholder="E-Mail Address">
|
||||||
|
<input type="password" class="form-control" placeholder="Password" id="pw">
|
||||||
|
<button class="btn btn-primary" id="signin">Sign In</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
27
server/accounts.coffee
Normal file
27
server/accounts.coffee
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
# Homework - Server side accounts code
|
||||||
|
|
||||||
|
# Regular Expression to see if an email can be valid
|
||||||
|
validateEmail = (email) ->
|
||||||
|
x = /^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/
|
||||||
|
x.test email
|
||||||
|
|
||||||
|
Accounts.config {
|
||||||
|
sendVerificationEmail: true
|
||||||
|
loginExpirationInDays: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
# Code that checks if a new user request is valid
|
||||||
|
Accounts.validateNewUser (user) ->
|
||||||
|
user.dateCreated = moment().unix()
|
||||||
|
mail = user.emails[0].address
|
||||||
|
if Match.test(mail,String) is no or validateEmail(mail) is no
|
||||||
|
throw new Meteor.Error 403, "Invalid Email"
|
||||||
|
return yes
|
||||||
|
|
||||||
|
# Email configuration code
|
||||||
|
Accounts.emailTemplates.siteName = "MarkCloud"
|
||||||
|
Accounts.emailTemplates.verifyEmail.text = (user,url) ->
|
||||||
|
urlist = url.split('/'); token = urlist[urlist.length-1]
|
||||||
|
url = Meteor.absoluteUrl 'verify/'+token
|
||||||
|
'''Welcome to MarkCloud! To activate your account, click on the \
|
||||||
|
following link: '''+url
|
@ -1,9 +1,25 @@
|
|||||||
docs = new Meteor.Collection 'docs'
|
docs = new Meteor.Collection 'docs'
|
||||||
|
|
||||||
Meteor.publish 'doc', (id) -> docs.find _id: id
|
validatedUser = (uid) ->
|
||||||
Meteor.publish 'docs', -> docs.find()
|
return no unless Meteor.users.findOne uid
|
||||||
|
u = Meteor.users.findOne uid
|
||||||
|
return yes for mail in u.emails when mail.verified is yes; no
|
||||||
|
|
||||||
|
Meteor.publish 'doc', (id) -> docs.find {_id: id}, limit: 1
|
||||||
|
Meteor.publish 'docs', -> docs.find {}, fields: text: 0
|
||||||
|
Meteor.publish 'user', ->
|
||||||
|
if @userId
|
||||||
|
docs.find {_id:@userId}, fields: {dateCreated: 1}
|
||||||
|
else @ready()
|
||||||
|
|
||||||
docs.allow
|
docs.allow
|
||||||
insert: -> yes
|
insert: (uid,doc) ->
|
||||||
update: -> no
|
return no unless doc.text and doc.title
|
||||||
remove: -> no
|
if uid then doc.owner = uid; return yes
|
||||||
|
else if doc.owner then return no
|
||||||
|
# Owners can update and remove their documents
|
||||||
|
update: (uid,doc) -> doc.owner is uid
|
||||||
|
remove: (uid,doc) -> doc.owner is uid
|
||||||
|
fetch: ['owner'] # Only fetch the owner field from the database documents
|
||||||
|
|
||||||
|
# Save account creation date
|
||||||
|
Loading…
Reference in New Issue
Block a user