Add accounts
This commit is contained in:
parent
8c153440cf
commit
073edf820b
2
Makefile
2
Makefile
|
@ -22,6 +22,8 @@ install:
|
||||||
go get github.com/gorilla/mux
|
go get github.com/gorilla/mux
|
||||||
go get github.com/go-sql-driver/mysql
|
go get github.com/go-sql-driver/mysql
|
||||||
go get github.com/lib/pq
|
go get github.com/lib/pq
|
||||||
|
go get golang.org/x/crypto/bcrypt
|
||||||
|
go get github.com/gorilla/securecookie
|
||||||
|
|
||||||
test: install
|
test: install
|
||||||
go install $(GOFLAGS) ./...
|
go install $(GOFLAGS) ./...
|
||||||
|
|
|
@ -119,20 +119,30 @@
|
||||||
<span class='swal-bold'> Create Paste</span> \
|
<span class='swal-bold'> Create Paste</span> \
|
||||||
<span class='swal-code'>echo '{"paste": "Hello FooBar"}' | curl -H 'Content-Type: application/json' -d @- {{ .UrlAddress }}/api </span> \
|
<span class='swal-code'>echo '{"paste": "Hello FooBar"}' | curl -H 'Content-Type: application/json' -d @- {{ .UrlAddress }}/api </span> \
|
||||||
\
|
\
|
||||||
|
<span class='swal-bold'> Create Paste</span> \
|
||||||
|
<span class='swal-code'>echo '{"paste": "Hello FooBar","key": "{{.UserKey}}"}' | curl -H 'Content-Type: application/json' -d @- {{ .UrlAddress }}/api </span> \
|
||||||
|
\
|
||||||
<span class='swal-bold'> Delete Paste </span> \
|
<span class='swal-bold'> Delete Paste </span> \
|
||||||
<span class='swal-code'> curl -X DELETE -F 'delkey=insert-your-delete-key-here' {{ .UrlAddress }}/api/{pasteid} </span> \
|
<span class='swal-code'> curl -X DELETE -F 'delkey=insert-your-delete-key-here' {{ .UrlAddress }}/api/{pasteid} </span> \
|
||||||
\
|
\
|
||||||
<span class='swal-bold'> Show Paste </span> \
|
<span class='swal-bold'> Show Paste </span> \
|
||||||
<span class='swal-code'> {{ .UrlAddress }}/p/{passte-id} </span> \
|
<span class='swal-code'> {{ .UrlAddress }}/p/{paste-id} </span> \
|
||||||
\
|
\
|
||||||
<span class='swal-bold'> Show Paste with a specific language </span> \
|
<span class='swal-bold'> Show Paste with a specific language </span> \
|
||||||
<span class='swal-code'> {{ .UrlAddress }}/p/{passte-id}/{language} </span> \
|
<span class='swal-code'> {{ .UrlAddress }}/p/{paste-id}/{language} </span> \
|
||||||
\
|
\
|
||||||
<span class='swal-bold'> Show Paste with a specific language and style </span> \
|
<span class='swal-bold'> Show Paste with a specific language and style </span> \
|
||||||
<span class='swal-code'> {{ .UrlAddress }}/p/{passte-id}/{language}/{style} </span> \
|
<span class='swal-code'> {{ .UrlAddress }}/p/{paste-id}/{language}/{style} </span> \
|
||||||
<span class='swal-bold'> Notes, </span> \
|
<span class='swal-bold'> Notes, </span> \
|
||||||
<span class='swal-code'> * Languages and Styles are standard components of the Python Syntax Highlighter (pygments)</span><br>\
|
<span class='swal-code'> * Languages and Styles are standard components of the Python Syntax Highlighter (pygments)</span><br>\
|
||||||
\
|
\
|
||||||
|
<span class='swal-bold'>User accounts </span> \
|
||||||
|
<span class='swal-code'>If you would like to save your pastes please register for an account at <a href="/register">register</a></span><br>\
|
||||||
|
<span class='swal-code'>To view and delete your pastes:<a href="/pastes">register</a></span><br>\
|
||||||
|
\
|
||||||
|
<span class='swal-bold'> API key, Keep secret </span> \
|
||||||
|
<span class='swal-code' id='key'>{{.UserKey}}</span><br>\
|
||||||
|
\
|
||||||
<span class='swal-code'>Source: <a href='https://github.com/ewhal/Pastebin'>Github</a></span>\
|
<span class='swal-code'>Source: <a href='https://github.com/ewhal/Pastebin'>Github</a></span>\
|
||||||
<span class='swal-code'>Tools: <a href='https://github.com/ewhal/scripts/blob/master/paste.sh'>Paste.sh</a></span>",
|
<span class='swal-code'>Tools: <a href='https://github.com/ewhal/scripts/blob/master/paste.sh'>Paste.sh</a></span>",
|
||||||
html: true
|
html: true
|
||||||
|
@ -157,11 +167,13 @@
|
||||||
var data_expiry = $("#button-expiry").attr("value");
|
var data_expiry = $("#button-expiry").attr("value");
|
||||||
var data_title = $("#title").val();
|
var data_title = $("#title").val();
|
||||||
var data_paste = $("#paste").val();
|
var data_paste = $("#paste").val();
|
||||||
|
var user_key = {{.UserKey}};
|
||||||
|
|
||||||
var json_data = { expiry : data_expiry,
|
var json_data = { expiry : data_expiry,
|
||||||
title : data_title,
|
title : data_title,
|
||||||
paste : data_paste,
|
paste : data_paste,
|
||||||
lang : data_lang,
|
lang : data_lang,
|
||||||
|
userkey: user_key,
|
||||||
webreq : true };
|
webreq : true };
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
|
||||||
|
<title>Login</title>
|
||||||
|
|
||||||
|
<!-- Material Design fonts -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700">
|
||||||
|
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/icon?family=Material+Icons">
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/bootstrap.material-design/0.5.10/css/bootstrap-material-design.min.css" integrity="sha256-j3CLSRG31GkOu6kaeLh7XsRgL2YNvRl9aOtXoAYt320=" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/bootstrap.material-design/0.5.10/css/ripples.min.css" integrity="sha256-+Og2qJI9qzvKYwhGo/LYXg0FzE1BhEQfDsUSjKXQ3Bg=" crossorigin="anonymous">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||||
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||||
|
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="bs-component">
|
||||||
|
<div class="navbar navbar-default">
|
||||||
|
<div class="container">
|
||||||
|
<div class="navbar-header">
|
||||||
|
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-responsive-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</button>
|
||||||
|
<a class="navbar-brand" href="/">Home</a>
|
||||||
|
</div>
|
||||||
|
<div class="navbar-collapse collapse navbar-responsive-collapse">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li><a href="/pastes">pastes</a></li>
|
||||||
|
<li><a href="/register">Register</a></li>
|
||||||
|
<li><a href="/login">Login</a></li>
|
||||||
|
<li><a href="/logout">Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="well bs-component">
|
||||||
|
<form class="form-horizontal" action="/login" method="POST">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Login</legend>
|
||||||
|
<div class="form-group is-empty">
|
||||||
|
<label for="inputEmail" class="col-md-2 control-label">Email</label>
|
||||||
|
|
||||||
|
<div class="col-md-10">
|
||||||
|
<input type="email" class="form-control" id="inputEmail" placeholder="Email" required name="email">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group is-empty">
|
||||||
|
<label for="inputPassword" class="col-md-2 control-label">Password</label>
|
||||||
|
|
||||||
|
<div class="col-md-10">
|
||||||
|
<input type="password" class="form-control" id="inputPassword" placeholder="Password" required name="password">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-10 pull-right">
|
||||||
|
<button type="submit" class="btn btn-raised btn-primary">Submit<div class="ripple-container"></div></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||||
|
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/bootstrap.material-design/0.5.10/js/material.min.js" integrity="sha256-uZbIqasulk7Y9yEwknbeQ0FpF3aUhtPwuggbpvQaI8Y=" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/bootstrap.material-design/0.5.10/js/ripples.min.js" integrity="sha256-TY/EO/++Ug/P+fSBjaqlmtuphCBKwlP7TOnS+SGnN8g=" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$.material.init();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,121 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
|
||||||
|
<title>Your Pastes</title>
|
||||||
|
|
||||||
|
<!-- Material Design fonts -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700">
|
||||||
|
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/icon?family=Material+Icons">
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/bootstrap.material-design/0.5.10/css/bootstrap-material-design.min.css" integrity="sha256-j3CLSRG31GkOu6kaeLh7XsRgL2YNvRl9aOtXoAYt320=" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/bootstrap.material-design/0.5.10/css/ripples.min.css" integrity="sha256-+Og2qJI9qzvKYwhGo/LYXg0FzE1BhEQfDsUSjKXQ3Bg=" crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/fontawesome/4.6.3/css/font-awesome.min.css" integrity="sha256-AIodEDkC8V/bHBkfyxzolUMw57jeQ9CauwhVW6YJ9CA=" crossorigin="anonymous">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||||
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||||
|
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="bs-component">
|
||||||
|
<div class="navbar navbar-default">
|
||||||
|
<div class="container">
|
||||||
|
<div class="navbar-header">
|
||||||
|
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-responsive-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</button>
|
||||||
|
<a class="navbar-brand" href="/">Home</a>
|
||||||
|
</div>
|
||||||
|
<div class="navbar-collapse collapse navbar-responsive-collapse">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li><a href="/pastes">User</a></li>
|
||||||
|
<li><a href="/register">Register</a></li>
|
||||||
|
<li><a href="/login">Login</a></li>
|
||||||
|
<li><a href="/logout">Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<table class="table table-hover" id="local">
|
||||||
|
<thead>
|
||||||
|
<th>URL</th>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Size</th>
|
||||||
|
<th>Delete</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{ range .Response}}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{{.Url}}">{{.Id}}</a></td>
|
||||||
|
<td>{{.Title}}</td>
|
||||||
|
<td>{{.Size}}</td>
|
||||||
|
<td><button class="del" id="{{.Id}}" value="{{.DelKey}}">{{.Id}}</button></td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||||
|
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/bootstrap.material-design/0.5.10/js/material.min.js" integrity="sha256-uZbIqasulk7Y9yEwknbeQ0FpF3aUhtPwuggbpvQaI8Y=" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/bootstrap.material-design/0.5.10/js/ripples.min.js" integrity="sha256-TY/EO/++Ug/P+fSBjaqlmtuphCBKwlP7TOnS+SGnN8g=" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Dynatable/0.3.1/jquery.dynatable.min.css">
|
||||||
|
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Dynatable/0.3.1/jquery.dynatable.min.js"></script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$.material.init();
|
||||||
|
$(document).ready(function() {
|
||||||
|
|
||||||
|
$('#local').dynatable();
|
||||||
|
$( '.del' ).click(function() {
|
||||||
|
|
||||||
|
|
||||||
|
var Id = $(this).text();
|
||||||
|
var del_key = $(this).val();
|
||||||
|
$(this).closest('tr').remove();
|
||||||
|
|
||||||
|
var json_data = {delkey: del_key,
|
||||||
|
webreq : true };
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: "http://localhost:9999/api/" + Id,
|
||||||
|
type: 'DELETE',
|
||||||
|
contentType: "application/json; charset=utf-8",
|
||||||
|
data: JSON.stringify(json_data),
|
||||||
|
dataType: "json",
|
||||||
|
success: function(json){
|
||||||
|
// window.location = json.url+"/"+data_lang;
|
||||||
|
},
|
||||||
|
error: function(json){
|
||||||
|
// sweetAlert("", json.responseText, "error");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
} );
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,93 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
|
||||||
|
<title>Register</title>
|
||||||
|
|
||||||
|
<!-- Material Design fonts -->
|
||||||
|
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700">
|
||||||
|
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/icon?family=Material+Icons">
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/bootstrap.material-design/0.5.10/css/bootstrap-material-design.min.css" integrity="sha256-j3CLSRG31GkOu6kaeLh7XsRgL2YNvRl9aOtXoAYt320=" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/bootstrap.material-design/0.5.10/css/ripples.min.css" integrity="sha256-+Og2qJI9qzvKYwhGo/LYXg0FzE1BhEQfDsUSjKXQ3Bg=" crossorigin="anonymous">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||||
|
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
|
||||||
|
<!--[if lt IE 9]>
|
||||||
|
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||||
|
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||||
|
<![endif]-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="bs-component">
|
||||||
|
<div class="navbar navbar-default">
|
||||||
|
<div class="container">
|
||||||
|
<div class="navbar-header">
|
||||||
|
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-responsive-collapse">
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</button>
|
||||||
|
<a class="navbar-brand" href="/">Home</a>
|
||||||
|
</div>
|
||||||
|
<div class="navbar-collapse collapse navbar-responsive-collapse">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
<li><a href="/pastes">User</a></li>
|
||||||
|
<li><a href="/register">Register</a></li>
|
||||||
|
<li><a href="/login">Login</a></li>
|
||||||
|
<li><a href="/logout">Logout</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="well bs-component">
|
||||||
|
<form class="form-horizontal" action="/register" method="POST">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Register</legend>
|
||||||
|
<div class="form-group is-empty">
|
||||||
|
<label for="inputEmail" class="col-md-2 control-label">Email</label>
|
||||||
|
|
||||||
|
<div class="col-md-10">
|
||||||
|
<input type="email" class="form-control" id="inputEmail" placeholder="Email" required name="email">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group is-empty">
|
||||||
|
<label for="inputPassword" class="col-md-2 control-label">Password</label>
|
||||||
|
|
||||||
|
<div class="col-md-10">
|
||||||
|
<input type="password" class="form-control" id="inputPassword" placeholder="Password" required name="password">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-10 pull-right">
|
||||||
|
<button type="submit" class="btn btn-raised btn-primary">Submit<div class="ripple-container"></div></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||||
|
<!-- Include all compiled plugins (below), or include individual files as needed -->
|
||||||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/bootstrap.material-design/0.5.10/js/material.min.js" integrity="sha256-uZbIqasulk7Y9yEwknbeQ0FpF3aUhtPwuggbpvQaI8Y=" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/bootstrap.material-design/0.5.10/js/ripples.min.js" integrity="sha256-TY/EO/++Ug/P+fSBjaqlmtuphCBKwlP7TOnS+SGnN8g=" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
$.material.init();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -3,6 +3,7 @@
|
||||||
"dbhost": "",
|
"dbhost": "",
|
||||||
"dbname": "pastebin.db",
|
"dbname": "pastebin.db",
|
||||||
"dbtable": "pastebin",
|
"dbtable": "pastebin",
|
||||||
|
"dbaccountstable": "accounts",
|
||||||
"dbtype": "sqlite3",
|
"dbtype": "sqlite3",
|
||||||
"dbport": "",
|
"dbport": "",
|
||||||
"dbuser":"",
|
"dbuser":"",
|
||||||
|
|
|
@ -5,13 +5,13 @@ CREATE TABLE `pastebin` (
|
||||||
`data` longtext,
|
`data` longtext,
|
||||||
`delkey` char(40) default NULL,
|
`delkey` char(40) default NULL,
|
||||||
`expiry` int,
|
`expiry` int,
|
||||||
`userid` int,
|
`userid` varchar(255),
|
||||||
PRIMARY KEY (`id`)
|
PRIMARY KEY (`id`)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE `accounts` (
|
CREATE TABLE `accounts` (
|
||||||
`id` varchar(30) NOT NULL,
|
|
||||||
`email` varchar(255) NOT NULL,
|
`email` varchar(255) NOT NULL,
|
||||||
`pass` varchar(255) NOT NULL,
|
`password` varchar(255) NOT NULL,
|
||||||
PRIMARY KEY (`id`)
|
`key` varchar(255) NOT NULL,
|
||||||
|
PRIMARY KEY (`key`)
|
||||||
);
|
);
|
||||||
|
|
250
pastebin.go
250
pastebin.go
|
@ -30,6 +30,10 @@ import (
|
||||||
|
|
||||||
// For url routing
|
// For url routing
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
// securecookie for cookie handling
|
||||||
|
"github.com/gorilla/securecookie"
|
||||||
|
// bcrypt for password hashing
|
||||||
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Configuration struct,
|
// Configuration struct,
|
||||||
|
@ -38,9 +42,10 @@ type Configuration struct {
|
||||||
DBHost string `json:"dbhost"` // Name of your database host
|
DBHost string `json:"dbhost"` // Name of your database host
|
||||||
DBName string `json:"dbname"` // Name of your database
|
DBName string `json:"dbname"` // Name of your database
|
||||||
DBPassword string `json:"dbpassword"` // The password for the database user
|
DBPassword string `json:"dbpassword"` // The password for the database user
|
||||||
DBPlaceHolder [6]string // ? / $[i] Depending on db driver.
|
DBPlaceHolder [7]string // ? / $[i] Depending on db driver.
|
||||||
DBPort string `json:"dbport"` // Port of the database
|
DBPort string `json:"dbport"` // Port of the database
|
||||||
DBTable string `json:"dbtable"` // Name of the table in the database
|
DBTable string `json:"dbtable"` // Name of the table in the database
|
||||||
|
DBAccountsTable string `json:"dbaccountstable"` // Name of the table in the database
|
||||||
DBType string `json:"dbtype"` // Type of database
|
DBType string `json:"dbtype"` // Type of database
|
||||||
DBUser string `json:"dbuser"` // The database user
|
DBUser string `json:"dbuser"` // The database user
|
||||||
DisplayName string `json:"displayname"` // Name of your pastebin
|
DisplayName string `json:"displayname"` // Name of your pastebin
|
||||||
|
@ -77,6 +82,7 @@ type Request struct {
|
||||||
Paste string `json:"paste"` // The actual pase
|
Paste string `json:"paste"` // The actual pase
|
||||||
Style string `json:"style"` // The style of the paste
|
Style string `json:"style"` // The style of the paste
|
||||||
Title string `json:"title"` // The title of the paste
|
Title string `json:"title"` // The title of the paste
|
||||||
|
UserKey string `json:"key"` // The title of the paste
|
||||||
WebReq bool `json:"webreq"` // If its a webrequest or not
|
WebReq bool `json:"webreq"` // If its a webrequest or not
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,11 +104,18 @@ type Page struct {
|
||||||
UrlHome string
|
UrlHome string
|
||||||
UrlRaw string
|
UrlRaw string
|
||||||
WrapperErr string
|
WrapperErr string
|
||||||
|
UserKey string
|
||||||
|
}
|
||||||
|
type Pastes struct {
|
||||||
|
Response []Response
|
||||||
}
|
}
|
||||||
|
|
||||||
// Template pages,
|
// Template pages,
|
||||||
var templates = template.Must(template.ParseFiles("assets/index.html",
|
var templates = template.Must(template.ParseFiles("assets/index.html",
|
||||||
"assets/syntax.html"))
|
"assets/syntax.html",
|
||||||
|
"assets/register.html",
|
||||||
|
"assets/pastes.html",
|
||||||
|
"assets/login.html"))
|
||||||
|
|
||||||
// Global variables, *shrug*
|
// Global variables, *shrug*
|
||||||
var configuration Configuration
|
var configuration Configuration
|
||||||
|
@ -113,6 +126,12 @@ var listOfLangsFirst map[string]string
|
||||||
var listOfLangsLast map[string]string
|
var listOfLangsLast map[string]string
|
||||||
var listOfStyles map[string]string
|
var listOfStyles map[string]string
|
||||||
|
|
||||||
|
// generate new random cookie keys
|
||||||
|
var cookieHandler = securecookie.New(
|
||||||
|
securecookie.GenerateRandomKey(64),
|
||||||
|
securecookie.GenerateRandomKey(32),
|
||||||
|
)
|
||||||
|
|
||||||
//
|
//
|
||||||
// Functions below,
|
// Functions below,
|
||||||
//
|
//
|
||||||
|
@ -261,7 +280,7 @@ func checkArgs() {
|
||||||
func getDBHandle() *sql.DB {
|
func getDBHandle() *sql.DB {
|
||||||
|
|
||||||
var dbinfo string
|
var dbinfo string
|
||||||
for i := 0; i < 6; i++ {
|
for i := 0; i < 7; i++ {
|
||||||
configuration.DBPlaceHolder[i] = "?"
|
configuration.DBPlaceHolder[i] = "?"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +299,7 @@ func getDBHandle() *sql.DB {
|
||||||
configuration.DBUser,
|
configuration.DBUser,
|
||||||
configuration.DBPassword,
|
configuration.DBPassword,
|
||||||
configuration.DBName)
|
configuration.DBName)
|
||||||
for i := 0; i < 6; i++ {
|
for i := 0; i < 7; i++ {
|
||||||
configuration.DBPlaceHolder[i] = "$" + strconv.Itoa(i+1)
|
configuration.DBPlaceHolder[i] = "$" + strconv.Itoa(i+1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,13 +384,14 @@ func shaPaste(paste string) string {
|
||||||
// paste, the actual paste data as a string,
|
// paste, the actual paste data as a string,
|
||||||
// expiry, the epxpiry date in epoch time as an int64
|
// expiry, the epxpiry date in epoch time as an int64
|
||||||
// Returns the Response struct
|
// Returns the Response struct
|
||||||
func savePaste(title string, paste string, expiry int64) Response {
|
func savePaste(title string, paste string, expiry int64, user_key string) Response {
|
||||||
|
|
||||||
var id, hash, delkey, url string
|
var id, hash, delkey, url string
|
||||||
|
|
||||||
// Escape user input,
|
// Escape user input,
|
||||||
paste = html.EscapeString(paste)
|
paste = html.EscapeString(paste)
|
||||||
title = html.EscapeString(title)
|
title = html.EscapeString(title)
|
||||||
|
user_key = html.EscapeString(user_key)
|
||||||
|
|
||||||
// Hash paste data and query database to see if paste exists
|
// Hash paste data and query database to see if paste exists
|
||||||
sha := shaPaste(paste)
|
sha := shaPaste(paste)
|
||||||
|
@ -419,15 +439,15 @@ func savePaste(title string, paste string, expiry int64) Response {
|
||||||
|
|
||||||
// This is needed since mysql/postgres uses different placeholders,
|
// This is needed since mysql/postgres uses different placeholders,
|
||||||
var dbQuery string
|
var dbQuery string
|
||||||
for i := 0; i < 6; i++ {
|
for i := 0; i < 7; i++ {
|
||||||
dbQuery += configuration.DBPlaceHolder[i] + ","
|
dbQuery += configuration.DBPlaceHolder[i] + ","
|
||||||
}
|
}
|
||||||
dbQuery = dbQuery[:len(dbQuery)-1]
|
dbQuery = dbQuery[:len(dbQuery)-1]
|
||||||
|
|
||||||
stmt, err := dbHandle.Prepare("INSERT INTO " + configuration.DBTable + " (id,title,hash,data,delkey,expiry)values(" + dbQuery + ")")
|
stmt, err := dbHandle.Prepare("INSERT INTO " + configuration.DBTable + " (id,title,hash,data,delkey,expiry,userid)values(" + dbQuery + ")")
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
_, err = stmt.Exec(id, title, sha, paste, delKey, expiry)
|
_, err = stmt.Exec(id, title, sha, paste, delKey, expiry, user_key)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
loggy(fmt.Sprintf("Sucessfully inserted data at id '%s', title '%s', expiry '%v' and data \n \n* * * *\n\n%s\n\n* * * *\n",
|
loggy(fmt.Sprintf("Sucessfully inserted data at id '%s', title '%s', expiry '%v' and data \n \n* * * *\n\n%s\n\n* * * *\n",
|
||||||
|
@ -453,6 +473,9 @@ func savePaste(title string, paste string, expiry int64) Response {
|
||||||
func DelHandler(w http.ResponseWriter, r *http.Request) {
|
func DelHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
var inData Request
|
var inData Request
|
||||||
|
loggy(fmt.Sprintf("Recieving request to delete a paste, trying to parse indata."))
|
||||||
|
decoder := json.NewDecoder(r.Body)
|
||||||
|
err := decoder.Decode(&inData)
|
||||||
|
|
||||||
inData.Id = vars["pasteId"]
|
inData.Id = vars["pasteId"]
|
||||||
|
|
||||||
|
@ -516,7 +539,7 @@ func SaveHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
p := savePaste(inData.Title, inData.Paste, inData.Expiry)
|
p := savePaste(inData.Title, inData.Paste, inData.Expiry, inData.UserKey)
|
||||||
|
|
||||||
d, _ = json.MarshalIndent(p, "DEBUG : ", " ")
|
d, _ = json.MarshalIndent(p, "DEBUG : ", " ")
|
||||||
loggy(fmt.Sprintf("Returning json data to requester \nDEBUG : %s", d))
|
loggy(fmt.Sprintf("Returning json data to requester \nDEBUG : %s", d))
|
||||||
|
@ -802,6 +825,7 @@ func CloneHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
Body: template.HTML(p.Paste),
|
Body: template.HTML(p.Paste),
|
||||||
PasteTitle: "Copy of " + p.Title,
|
PasteTitle: "Copy of " + p.Title,
|
||||||
Title: "Copy of " + p.Title,
|
Title: "Copy of " + p.Title,
|
||||||
|
UserKey: getUserKey(r),
|
||||||
}
|
}
|
||||||
|
|
||||||
err := templates.ExecuteTemplate(w, "index.html", page)
|
err := templates.ExecuteTemplate(w, "index.html", page)
|
||||||
|
@ -835,6 +859,209 @@ func RawHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
io.WriteString(w, p.Paste)
|
io.WriteString(w, p.Paste)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// loginHandler
|
||||||
|
func loginHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.Method {
|
||||||
|
case "GET":
|
||||||
|
err := templates.ExecuteTemplate(w, "login.html", "")
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
case "POST":
|
||||||
|
email := r.FormValue("email")
|
||||||
|
password := r.FormValue("password")
|
||||||
|
email_escaped := html.EscapeString(email)
|
||||||
|
|
||||||
|
// Query database if id exists and if it does call generateName again
|
||||||
|
var hashedPassword []byte
|
||||||
|
err := dbHandle.QueryRow("select password from "+configuration.DBAccountsTable+
|
||||||
|
" where email="+configuration.DBPlaceHolder[0], email_escaped).
|
||||||
|
Scan(&hashedPassword)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case err == sql.ErrNoRows:
|
||||||
|
loggy(fmt.Sprintf("Email '%s' is not taken.", email))
|
||||||
|
http.Redirect(w, r, "/register", 302)
|
||||||
|
case err != nil:
|
||||||
|
debugLogger.Println(" Database error : " + err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
default:
|
||||||
|
loggy(fmt.Sprintf("Account '%s' exists.", email))
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare bcrypt hash to userinput password
|
||||||
|
err = bcrypt.CompareHashAndPassword(hashedPassword, []byte(password))
|
||||||
|
if err == nil {
|
||||||
|
// prepare cookie
|
||||||
|
value := map[string]string{
|
||||||
|
"email": email,
|
||||||
|
}
|
||||||
|
// encode variables into cookie
|
||||||
|
if encoded, err := cookieHandler.Encode("session", value); err == nil {
|
||||||
|
cookie := &http.Cookie{
|
||||||
|
Name: "session",
|
||||||
|
Value: encoded,
|
||||||
|
Path: "/",
|
||||||
|
}
|
||||||
|
// set user cookie
|
||||||
|
http.SetCookie(w, cookie)
|
||||||
|
}
|
||||||
|
loggy(fmt.Sprintf("Successfully logged account '%s' in.", email))
|
||||||
|
// Redirect to home page
|
||||||
|
http.Redirect(w, r, "/", 302)
|
||||||
|
}
|
||||||
|
// Redirect to login page
|
||||||
|
http.Redirect(w, r, "/login", 302)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func pastesHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
key := getUserKey(r)
|
||||||
|
b := Pastes{Response: []Response{}}
|
||||||
|
|
||||||
|
rows, err := dbHandle.Query("select id, title, delkey, data from "+
|
||||||
|
configuration.DBTable+" where userid="+
|
||||||
|
configuration.DBPlaceHolder[0], key)
|
||||||
|
switch {
|
||||||
|
case err == sql.ErrNoRows:
|
||||||
|
loggy("Pasted data is not in the database, will insert it.")
|
||||||
|
case err != nil:
|
||||||
|
debugLogger.Println(" Database error : " + err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
default:
|
||||||
|
for rows.Next() {
|
||||||
|
var id, title, url, delKey, data string
|
||||||
|
rows.Scan(&id, &title, &delKey, &data)
|
||||||
|
url = configuration.Address + "/p/" + id
|
||||||
|
res := Response{
|
||||||
|
Id: id,
|
||||||
|
Title: title,
|
||||||
|
Url: url,
|
||||||
|
Size: len(data),
|
||||||
|
DelKey: delKey}
|
||||||
|
|
||||||
|
b.Response = append(b.Response, res)
|
||||||
|
|
||||||
|
}
|
||||||
|
rows.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
err = templates.ExecuteTemplate(w, "pastes.html", &b)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// loggedIn returns true if cookie exists
|
||||||
|
func getUserKey(r *http.Request) string {
|
||||||
|
cookie, err := r.Cookie("session")
|
||||||
|
cookieValue := make(map[string]string)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
err = cookieHandler.Decode("session", cookie.Value, &cookieValue)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
email := cookieValue["email"]
|
||||||
|
// Query database if id exists and if it does call generateName again
|
||||||
|
var user_key string
|
||||||
|
err = dbHandle.QueryRow("select key from "+configuration.DBAccountsTable+
|
||||||
|
" where email="+configuration.DBPlaceHolder[0], email).
|
||||||
|
Scan(&user_key)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case err == sql.ErrNoRows:
|
||||||
|
loggy(fmt.Sprintf("Key does not exist for user '%s'", email))
|
||||||
|
case err != nil:
|
||||||
|
debugLogger.Println(" Database error : " + err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
default:
|
||||||
|
loggy(fmt.Sprintf("User key found for user '%s'", email))
|
||||||
|
}
|
||||||
|
|
||||||
|
return user_key
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// registerHandler
|
||||||
|
func registerHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.Method {
|
||||||
|
case "GET":
|
||||||
|
err := templates.ExecuteTemplate(w, "register.html", "")
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
case "POST":
|
||||||
|
email := r.FormValue("email")
|
||||||
|
pass := r.FormValue("password")
|
||||||
|
email_escaped := html.EscapeString(email)
|
||||||
|
|
||||||
|
loggy(fmt.Sprintf("Attempting to create account '%s', checking if it's already taken in the database",
|
||||||
|
email))
|
||||||
|
|
||||||
|
// Query database if id exists and if it does call generateName again
|
||||||
|
var email_taken string
|
||||||
|
err := dbHandle.QueryRow("select email from "+configuration.DBAccountsTable+
|
||||||
|
" where email="+configuration.DBPlaceHolder[0], email_escaped).
|
||||||
|
Scan(&email_taken)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case err == sql.ErrNoRows:
|
||||||
|
loggy(fmt.Sprintf("Email '%s' is not taken, will use it.", email))
|
||||||
|
case err != nil:
|
||||||
|
debugLogger.Println(" Database error : " + err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
default:
|
||||||
|
loggy(fmt.Sprintf("Email '%s' is taken.", email_taken))
|
||||||
|
http.Redirect(w, r, "/register", 302)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is needed since mysql/postgres uses different placeholders,
|
||||||
|
var dbQuery string
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
dbQuery += configuration.DBPlaceHolder[i] + ","
|
||||||
|
}
|
||||||
|
dbQuery = dbQuery[:len(dbQuery)-1]
|
||||||
|
|
||||||
|
stmt, err := dbHandle.Prepare("INSERT into " + configuration.DBAccountsTable + "(email, password, key) values(" + dbQuery + ")")
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost)
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
|
key := uniuri.NewLen(24)
|
||||||
|
|
||||||
|
_, err = stmt.Exec(email_escaped, hashedPassword, key)
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
|
loggy(fmt.Sprintf("Successfully created account '%s' with hashed password '%s'",
|
||||||
|
email,
|
||||||
|
hashedPassword))
|
||||||
|
stmt.Close()
|
||||||
|
checkErr(err)
|
||||||
|
http.Redirect(w, r, "/login", 302)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// logoutHandler destroys cookie data and redirects to root
|
||||||
|
func logoutHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
cookie := &http.Cookie{
|
||||||
|
Name: "session",
|
||||||
|
Value: "",
|
||||||
|
Path: "/",
|
||||||
|
MaxAge: -1,
|
||||||
|
}
|
||||||
|
http.SetCookie(w, cookie)
|
||||||
|
http.Redirect(w, r, "/", 301)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// RootHandler handles generating the root page
|
// RootHandler handles generating the root page
|
||||||
func RootHandler(w http.ResponseWriter, r *http.Request) {
|
func RootHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
@ -843,6 +1070,7 @@ func RootHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
LangsLast: listOfLangsLast,
|
LangsLast: listOfLangsLast,
|
||||||
Title: configuration.DisplayName,
|
Title: configuration.DisplayName,
|
||||||
UrlAddress: configuration.Address,
|
UrlAddress: configuration.Address,
|
||||||
|
UserKey: getUserKey(r),
|
||||||
}
|
}
|
||||||
|
|
||||||
err := templates.ExecuteTemplate(w, "index.html", p)
|
err := templates.ExecuteTemplate(w, "index.html", p)
|
||||||
|
@ -906,6 +1134,10 @@ func main() {
|
||||||
|
|
||||||
router.HandleFunc("/raw/{pasteId}", RawHandler).Methods("GET")
|
router.HandleFunc("/raw/{pasteId}", RawHandler).Methods("GET")
|
||||||
router.HandleFunc("/clone/{pasteId}", CloneHandler).Methods("GET")
|
router.HandleFunc("/clone/{pasteId}", CloneHandler).Methods("GET")
|
||||||
|
router.HandleFunc("/login", loginHandler)
|
||||||
|
router.HandleFunc("/logout", logoutHandler)
|
||||||
|
router.HandleFunc("/register", registerHandler)
|
||||||
|
router.HandleFunc("/pastes", pastesHandler).Methods("GET")
|
||||||
|
|
||||||
router.HandleFunc("/download/{pasteId}", DownloadHandler).Methods("GET")
|
router.HandleFunc("/download/{pasteId}", DownloadHandler).Methods("GET")
|
||||||
router.HandleFunc("/assets/pastebin.css", serveCss).Methods("GET")
|
router.HandleFunc("/assets/pastebin.css", serveCss).Methods("GET")
|
||||||
|
|
Loading…
Reference in New Issue