@ -0,0 +1 @@ |
|||||
|
keys |
@ -0,0 +1,18 @@ |
|||||
|
# decentralized-blogging-platform |
||||
|
|
||||
|
Decentralized blogging platform, using IPFS |
||||
|
|
||||
|
|
||||
|
|
||||
|
### Instructions |
||||
|
|
||||
|
- Need to add: |
||||
|
``` |
||||
|
ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["*"]' |
||||
|
``` |
||||
|
in order to allow access to IPFS from the app. |
||||
|
|
||||
|
- Start the IPFS daemon |
||||
|
``` |
||||
|
ipfs daemon |
||||
|
``` |
@ -0,0 +1,96 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"encoding/json" |
||||
|
"fmt" |
||||
|
"net/http" |
||||
|
|
||||
|
"gopkg.in/mgo.v2/bson" |
||||
|
) |
||||
|
|
||||
|
type User struct { |
||||
|
Id bson.ObjectId `json:"id" bson:"_id,omitempty"` |
||||
|
Username string `json:"username"` |
||||
|
Email string `json:"email"` |
||||
|
Password string `json:"password"` |
||||
|
Token string `json:"token"` |
||||
|
} |
||||
|
|
||||
|
func Index(w http.ResponseWriter, r *http.Request) { |
||||
|
fmt.Fprintln(w, "clientApp") |
||||
|
} |
||||
|
|
||||
|
func Signup(w http.ResponseWriter, r *http.Request) { |
||||
|
decoder := json.NewDecoder(r.Body) |
||||
|
var user User |
||||
|
err := decoder.Decode(&user) |
||||
|
if err != nil { |
||||
|
panic(err) |
||||
|
} |
||||
|
defer r.Body.Close() |
||||
|
|
||||
|
fmt.Print("user signup: ") |
||||
|
fmt.Println(user.Username) |
||||
|
|
||||
|
//save the new project to mongodb
|
||||
|
rUser := User{} |
||||
|
err = userCollection.Find(bson.M{"email": user.Email}).One(&rUser) |
||||
|
if err != nil { |
||||
|
//user not exists
|
||||
|
err = userCollection.Insert(user) |
||||
|
err = userCollection.Find(bson.M{"email": user.Email}).One(&user) |
||||
|
} else { |
||||
|
//user exists
|
||||
|
http.Error(w, "user already registered", http.StatusConflict) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
fmt.Println(user.Username) |
||||
|
jResp, err := json.Marshal(user) |
||||
|
if err != nil { |
||||
|
panic(err) |
||||
|
} |
||||
|
fmt.Fprintln(w, string(jResp)) |
||||
|
} |
||||
|
|
||||
|
func Login(w http.ResponseWriter, r *http.Request) { |
||||
|
|
||||
|
decoder := json.NewDecoder(r.Body) |
||||
|
var user User |
||||
|
err := decoder.Decode(&user) |
||||
|
if err != nil { |
||||
|
panic(err) |
||||
|
} |
||||
|
defer r.Body.Close() |
||||
|
//TODO check if the user password exists in the database
|
||||
|
|
||||
|
fmt.Print("user login: ") |
||||
|
fmt.Println(user) |
||||
|
|
||||
|
//save the new project to mongodb
|
||||
|
rUser := User{} |
||||
|
err = userCollection.Find(bson.M{"email": user.Email}).One(&rUser) |
||||
|
if err != nil { |
||||
|
http.Error(w, "error login, email not foun", http.StatusConflict) |
||||
|
return |
||||
|
} |
||||
|
//user exists, check password
|
||||
|
if user.Password != rUser.Password { |
||||
|
http.Error(w, "error login, password not match", http.StatusConflict) |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
token, err := newToken() |
||||
|
check(err) |
||||
|
rUser.Token = token |
||||
|
|
||||
|
//update with the token
|
||||
|
err = userCollection.Update(bson.M{"_id": rUser.Id}, rUser) |
||||
|
check(err) |
||||
|
|
||||
|
jResp, err := json.Marshal(rUser) |
||||
|
if err != nil { |
||||
|
panic(err) |
||||
|
} |
||||
|
fmt.Fprintln(w, string(jResp)) |
||||
|
} |
@ -0,0 +1,8 @@ |
|||||
|
{ |
||||
|
"apiport": "3000", |
||||
|
"webport": "8081", |
||||
|
"mongodb": { |
||||
|
"ip": "127.0.0.1:27017", |
||||
|
"database": "decentralized-blogging-platform" |
||||
|
} |
||||
|
} |
@ -0,0 +1,15 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"log" |
||||
|
"runtime" |
||||
|
) |
||||
|
|
||||
|
func check(err error) { |
||||
|
if err != nil { |
||||
|
_, fn, line, _ := runtime.Caller(1) |
||||
|
log.Println(line) |
||||
|
log.Println(fn) |
||||
|
log.Println(err) |
||||
|
} |
||||
|
} |
@ -0,0 +1,12 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"crypto/sha256" |
||||
|
"encoding/base64" |
||||
|
) |
||||
|
|
||||
|
func hash(s string) string { |
||||
|
h := sha256.New() |
||||
|
h.Write([]byte(s)) |
||||
|
return base64.URLEncoding.EncodeToString(h.Sum(nil)) |
||||
|
} |
@ -0,0 +1,19 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"io" |
||||
|
"log" |
||||
|
"os" |
||||
|
"time" |
||||
|
) |
||||
|
|
||||
|
func savelog() { |
||||
|
timeS := time.Now().String() |
||||
|
_ = os.Mkdir("logs", os.ModePerm) |
||||
|
logFile, err := os.OpenFile("logs/log-"+timeS+".log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666) |
||||
|
if err != nil { |
||||
|
panic(err) |
||||
|
} |
||||
|
mw := io.MultiWriter(os.Stdout, logFile) |
||||
|
log.SetOutput(mw) |
||||
|
} |
@ -0,0 +1,51 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
"log" |
||||
|
"net/http" |
||||
|
|
||||
|
"github.com/fatih/color" |
||||
|
"github.com/gorilla/handlers" |
||||
|
mgo "gopkg.in/mgo.v2" |
||||
|
) |
||||
|
|
||||
|
const keysDir = "keys" |
||||
|
const keysize = 2048 |
||||
|
const hashize = 1536 |
||||
|
|
||||
|
var userCollection *mgo.Collection |
||||
|
|
||||
|
func main() { |
||||
|
color.Blue("Starting ipfs-ai-models-market") |
||||
|
|
||||
|
readConfig("config.json") |
||||
|
fmt.Println(config) |
||||
|
|
||||
|
initializeToken() |
||||
|
|
||||
|
//mongodb
|
||||
|
session, err := getSession() |
||||
|
check(err) |
||||
|
userCollection = getCollection(session, "users") |
||||
|
|
||||
|
//run thw webserver
|
||||
|
go GUI() |
||||
|
|
||||
|
//run API
|
||||
|
log.Println("api server running") |
||||
|
log.Print("port: ") |
||||
|
log.Println(config.APIPort) |
||||
|
router := NewRouter() |
||||
|
headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Access-Control-Allow-Origin"}) |
||||
|
originsOk := handlers.AllowedOrigins([]string{"*"}) |
||||
|
methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS"}) |
||||
|
log.Fatal(http.ListenAndServe(":"+config.APIPort, handlers.CORS(originsOk, headersOk, methodsOk)(router))) |
||||
|
} |
||||
|
|
||||
|
func GUI() { |
||||
|
//here, run webserver
|
||||
|
log.Println("webserver in port " + config.WebPort) |
||||
|
http.Handle("/", http.FileServer(http.Dir("./webapp"))) |
||||
|
http.ListenAndServe(":"+config.WebPort, nil) |
||||
|
} |
@ -0,0 +1,26 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
mgo "gopkg.in/mgo.v2" |
||||
|
) |
||||
|
|
||||
|
func getSession() (*mgo.Session, error) { |
||||
|
session, err := mgo.Dial("mongodb://" + config.Mongodb.IP) |
||||
|
if err != nil { |
||||
|
panic(err) |
||||
|
} |
||||
|
//defer session.Close()
|
||||
|
|
||||
|
// Optional. Switch the session to a monotonic behavior.
|
||||
|
session.SetMode(mgo.Monotonic, true) |
||||
|
|
||||
|
// Optional. Switch the session to a monotonic behavior.
|
||||
|
session.SetMode(mgo.Monotonic, true) |
||||
|
|
||||
|
return session, err |
||||
|
} |
||||
|
func getCollection(session *mgo.Session, collection string) *mgo.Collection { |
||||
|
|
||||
|
c := session.DB(config.Mongodb.Database).C(collection) |
||||
|
return c |
||||
|
} |
@ -0,0 +1,26 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"encoding/json" |
||||
|
"io/ioutil" |
||||
|
) |
||||
|
|
||||
|
//Config reads the config
|
||||
|
type Config struct { |
||||
|
APIPort string `json:"apiport"` |
||||
|
WebPort string `json:"webport"` |
||||
|
Mongodb MongoConfig `json:"mongodb"` |
||||
|
} |
||||
|
type MongoConfig struct { |
||||
|
IP string `json:"ip"` |
||||
|
Database string `json:"database"` |
||||
|
} |
||||
|
|
||||
|
var config Config |
||||
|
|
||||
|
func readConfig(path string) { |
||||
|
file, err := ioutil.ReadFile(path) |
||||
|
check(err) |
||||
|
content := string(file) |
||||
|
json.Unmarshal([]byte(content), &config) |
||||
|
} |
@ -0,0 +1,47 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"log" |
||||
|
"net/http" |
||||
|
"time" |
||||
|
|
||||
|
"github.com/gorilla/mux" |
||||
|
) |
||||
|
|
||||
|
type Route struct { |
||||
|
Name string |
||||
|
Method string |
||||
|
Pattern string |
||||
|
HandlerFunc http.HandlerFunc |
||||
|
} |
||||
|
|
||||
|
func Logger(inner http.Handler, name string) http.Handler { |
||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
||||
|
start := time.Now() |
||||
|
|
||||
|
inner.ServeHTTP(w, r) |
||||
|
|
||||
|
log.Printf( |
||||
|
"%s\t%s\t%s\t%s", |
||||
|
r.Method, |
||||
|
r.RequestURI, |
||||
|
name, |
||||
|
time.Since(start), |
||||
|
) |
||||
|
}) |
||||
|
} |
||||
|
func NewRouter() *mux.Router { |
||||
|
router := mux.NewRouter().StrictSlash(true) |
||||
|
for _, route := range routes { |
||||
|
var handler http.Handler |
||||
|
handler = route.HandlerFunc |
||||
|
handler = Logger(handler, route.Name) |
||||
|
|
||||
|
router. |
||||
|
Methods(route.Method). |
||||
|
Path(route.Pattern). |
||||
|
Name(route.Name). |
||||
|
Handler(handler) |
||||
|
} |
||||
|
return router |
||||
|
} |
@ -0,0 +1,24 @@ |
|||||
|
package main |
||||
|
|
||||
|
type Routes []Route |
||||
|
|
||||
|
var routes = Routes{ |
||||
|
Route{ |
||||
|
"Index", |
||||
|
"GET", |
||||
|
"/", |
||||
|
Index, |
||||
|
}, |
||||
|
Route{ |
||||
|
"Signup", |
||||
|
"POST", |
||||
|
"/signup", |
||||
|
Signup, |
||||
|
}, |
||||
|
Route{ |
||||
|
"Login", |
||||
|
"POST", |
||||
|
"/login", |
||||
|
Login, |
||||
|
}, |
||||
|
} |
@ -0,0 +1,49 @@ |
|||||
|
package main |
||||
|
|
||||
|
import ( |
||||
|
"fmt" |
||||
|
"time" |
||||
|
|
||||
|
jwt "github.com/dgrijalva/jwt-go" |
||||
|
) |
||||
|
|
||||
|
const ( |
||||
|
signingKey = "this is the secret signing key" |
||||
|
) |
||||
|
|
||||
|
var createdToken string |
||||
|
|
||||
|
func initializeToken() { |
||||
|
var err error |
||||
|
createdToken, err = newToken() |
||||
|
if err != nil { |
||||
|
fmt.Println("Creating token failed") |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func newToken() (string, error) { |
||||
|
signingKeyB := []byte(signingKey) |
||||
|
// Create the token
|
||||
|
token := jwt.New(jwt.SigningMethodHS256) |
||||
|
// Set some claims
|
||||
|
claims := make(jwt.MapClaims) |
||||
|
claims["foo"] = "bar" |
||||
|
claims["exp"] = time.Now().Add(time.Hour * 72).Unix() |
||||
|
token.Claims = claims |
||||
|
|
||||
|
// Sign and get the complete encoded token as a string
|
||||
|
tokenString, err := token.SignedString(signingKeyB) |
||||
|
return tokenString, err |
||||
|
} |
||||
|
|
||||
|
func parseToken(myToken string, myKey string) { |
||||
|
token, err := jwt.Parse(myToken, func(token *jwt.Token) (interface{}, error) { |
||||
|
return []byte(myKey), nil |
||||
|
}) |
||||
|
|
||||
|
if err == nil && token.Valid { |
||||
|
fmt.Println("Your token is valid. I like your style.") |
||||
|
} else { |
||||
|
fmt.Println("This token is terrible! I cannot accept this.") |
||||
|
} |
||||
|
} |
@ -0,0 +1,5 @@ |
|||||
|
bower_components |
||||
|
node_modules |
||||
|
package-lock.json |
||||
|
keys |
||||
|
*.pem |
@ -0,0 +1,88 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
var apiurl = "http://127.0.0.1:3000/"; |
||||
|
|
||||
|
angular.module('app', [ |
||||
|
'ngRoute', |
||||
|
'ngMessages', |
||||
|
'toastr', |
||||
|
'chart.js', |
||||
|
'app.navbar', |
||||
|
'app.signup', |
||||
|
'app.login', |
||||
|
'app.main', |
||||
|
'app.newmodel', |
||||
|
'app.profile' |
||||
|
]). |
||||
|
config(['$locationProvider', '$routeProvider', function($locationProvider, $routeProvider) { |
||||
|
$locationProvider.hashPrefix('!'); |
||||
|
/*$routeProvider.otherwise({ |
||||
|
redirectTo: '/main' |
||||
|
});*/ |
||||
|
|
||||
|
if((localStorage.getItem('dblog_user'))) |
||||
|
{ |
||||
|
console.log(window.location.hash); |
||||
|
if((window.location.hash==='#!/login')||(window.location.hash==='#!/signup')) |
||||
|
{ |
||||
|
window.location='#!/main'; |
||||
|
} |
||||
|
|
||||
|
$routeProvider.otherwise({redirectTo: '/main'}); |
||||
|
}else{ |
||||
|
if((window.location!=='#!/login')||(window.location!=='#!/signup')||(window.location!=='#!/main')) |
||||
|
{ |
||||
|
console.log('app, user no logged'); |
||||
|
|
||||
|
localStorage.removeItem('dblog_user'); |
||||
|
localStorage.removeItem('dblog_user'); |
||||
|
window.location='#!/main'; |
||||
|
$routeProvider.otherwise({redirectTo: '/main'}); |
||||
|
} |
||||
|
} |
||||
|
}]) |
||||
|
.config(function(toastrConfig) { |
||||
|
angular.extend(toastrConfig, { |
||||
|
autoDismiss: false, |
||||
|
containerId: 'toast-container', |
||||
|
maxOpened: 0, |
||||
|
newestOnTop: true, |
||||
|
positionClass: 'toast-bottom-right', |
||||
|
preventDuplicates: false, |
||||
|
preventOpenDuplicates: false, |
||||
|
target: 'body' |
||||
|
}); |
||||
|
}) |
||||
|
.factory('httpInterceptor', function httpInterceptor() { |
||||
|
return { |
||||
|
request: function(config) { |
||||
|
return config; |
||||
|
}, |
||||
|
|
||||
|
requestError: function(config) { |
||||
|
return config; |
||||
|
}, |
||||
|
|
||||
|
response: function(res) { |
||||
|
return res; |
||||
|
}, |
||||
|
|
||||
|
responseError: function(res) { |
||||
|
return res; |
||||
|
} |
||||
|
}; |
||||
|
}) |
||||
|
.factory('api', function($http) { |
||||
|
return { |
||||
|
init: function() { |
||||
|
var dblog_user = JSON.parse(localStorage.getItem('dblog_user')); |
||||
|
if (dblog_user) { |
||||
|
$http.defaults.headers.common['Authorization'] = dblog_user.token; |
||||
|
$http.defaults.headers.post['Authorization'] = dblog_user.token; |
||||
|
} |
||||
|
} |
||||
|
}; |
||||
|
}) |
||||
|
.run(function(api) { |
||||
|
api.init(); |
||||
|
}); |
@ -0,0 +1,19 @@ |
|||||
|
{ |
||||
|
"name": "ipfs-ai-models-market", |
||||
|
"description": "", |
||||
|
"version": "0.0.0", |
||||
|
"homepage": "", |
||||
|
"license": "GNU", |
||||
|
"private": true, |
||||
|
"dependencies": { |
||||
|
"angular": "^1.6.2", |
||||
|
"angular-route": "^1.6.1", |
||||
|
"angular-messages": "^1.6.5", |
||||
|
"angular-bootstrap-material": "abm#^0.1.4", |
||||
|
"angular-bootstrap": "^2.5.0", |
||||
|
"components-font-awesome": "^4.7.0", |
||||
|
"angular-toastr": "^2.1.1", |
||||
|
"cssMaterialColors": "*", |
||||
|
"angular-chart.js": "^1.1.1" |
||||
|
} |
||||
|
} |
@ -0,0 +1,5 @@ |
|||||
|
.o_nav { |
||||
|
background: #ffffff!important; |
||||
|
color: #000000!important; |
||||
|
/*border-bottom: 2px solid #4DD0E1!important;*/ |
||||
|
} |
@ -0,0 +1,73 @@ |
|||||
|
<!DOCTYPE html> |
||||
|
<html lang="en" ng-app="app" ng-cloak> |
||||
|
|
||||
|
<head> |
||||
|
<meta charset="utf-8"> |
||||
|
<title>ipfs-ai-models-market</title> |
||||
|
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
|
|
||||
|
<link rel="icon" type="image/png" href="img/icon.png"> |
||||
|
|
||||
|
<!-- Fonts --> |
||||
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans|Overpass+Mono:700|Raleway:700" rel="stylesheet"> |
||||
|
|
||||
|
<!-- Bootstrap --> |
||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> |
||||
|
|
||||
|
|
||||
|
<link rel="stylesheet" href="bower_components/components-font-awesome/css/font-awesome.min.css"> |
||||
|
|
||||
|
<link rel="stylesheet" href="css/own.css"> |
||||
|
|
||||
|
<link href="bower_components/cssMaterialColors/colors.css" rel="stylesheet"> |
||||
|
</head> |
||||
|
|
||||
|
<body ng-app="webapp"> |
||||
|
<div ng-include="'views/navbar.html'"></div> |
||||
|
<br><br><br><br> |
||||
|
<div ng-view></div> |
||||
|
|
||||
|
|
||||
|
|
||||
|
<!-- ELECTRON |
||||
|
Insert this line above script imports |
||||
|
Works for both browser and electron with the same code --> |
||||
|
<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script> |
||||
|
|
||||
|
|
||||
|
<!-- Angular js --> |
||||
|
<script src="bower_components/angular/angular.js"></script> |
||||
|
<script src="bower_components/angular-route/angular-route.js"></script> |
||||
|
<script src="bower_components/angular-messages/angular-messages.js"></script> |
||||
|
|
||||
|
|
||||
|
<!-- Bootstrap --> |
||||
|
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> |
||||
|
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> |
||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script> |
||||
|
|
||||
|
<!-- Angular Chart --> |
||||
|
<script src="bower_components/chart.js/dist/Chart.min.js"></script> |
||||
|
<script src="bower_components/angular-chart.js/dist/angular-chart.min.js"></script> |
||||
|
|
||||
|
<!-- toastr --> |
||||
|
<link rel="stylesheet" type="text/css" href="bower_components/angular-toastr/dist/angular-toastr.css" /> |
||||
|
<script type="text/javascript" src="bower_components/angular-toastr/dist/angular-toastr.tpls.js"></script> |
||||
|
|
||||
|
<!-- app's js --> |
||||
|
<script src="app.js"></script> |
||||
|
<script src="views/navbar.js"></script> |
||||
|
<script src="views/signup/signup.js"></script> |
||||
|
<script src="views/login/login.js"></script> |
||||
|
<script src="views/main/main.js"></script> |
||||
|
<script src="views/newmodel/newmodel.js"></script> |
||||
|
<script src="views/profile/profile.js"></script> |
||||
|
|
||||
|
|
||||
|
<!-- ELECTRON |
||||
|
Insert this line after script imports --> |
||||
|
<script>if (window.module) module = window.module;</script> |
||||
|
|
||||
|
</body> |
||||
|
|
||||
|
</html> |
@ -0,0 +1,13 @@ |
|||||
|
{ |
||||
|
"name": "decentralized-blogging-platform", |
||||
|
"version": "1.0.0", |
||||
|
"description": "", |
||||
|
"scripts": { |
||||
|
"postinstall": "bower install", |
||||
|
"prestart": "npm install", |
||||
|
"start": "http-server" |
||||
|
}, |
||||
|
"dependencies": { |
||||
|
"bootstrap": "^4.0.0" |
||||
|
} |
||||
|
} |
@ -0,0 +1,35 @@ |
|||||
|
<div class="container" style="margin-top: -60px;"> |
||||
|
<div class="row"> |
||||
|
<div class="col-sm-3"> |
||||
|
|
||||
|
</div> |
||||
|
<div class="col-sm-6"> |
||||
|
<div class="card"> |
||||
|
<div class="card-body"> |
||||
|
<h4 class="card-title"> |
||||
|
Login |
||||
|
</h4> |
||||
|
<div class="form-group"> |
||||
|
<input ng-model="user.email" type="email" class="form-control" placeholder="Email"> |
||||
|
</div> |
||||
|
<div class="form-group"> |
||||
|
<input ng-model="user.password" type="password" class="form-control" placeholder="Password"> |
||||
|
</div> |
||||
|
<div class="row"> |
||||
|
<div class="col-sm-6"> |
||||
|
<a href="#!/signup" class="btn btn-raised btn-block c_o_pink300">Signup</a> |
||||
|
</div> |
||||
|
<div class="col-sm-6"> |
||||
|
<div ng-click="login()" class="btn btn-raised btn-block c_o_cyan300 pull-right">Login</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
<div class="col-sm-3"> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
@ -0,0 +1,36 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
angular.module('app.login', ['ngRoute']) |
||||
|
|
||||
|
.config(['$routeProvider', function($routeProvider) { |
||||
|
$routeProvider.when('/login', { |
||||
|
templateUrl: 'views/login/login.html', |
||||
|
controller: 'LoginCtrl' |
||||
|
}); |
||||
|
}]) |
||||
|
|
||||
|
.controller('LoginCtrl', function($scope, $rootScope, $http, $routeParams, toastr) { |
||||
|
$rootScope.server = "" |
||||
|
$scope.user = {}; |
||||
|
|
||||
|
$scope.login = function() { |
||||
|
$http({ |
||||
|
url: apiurl + 'login', |
||||
|
method: "POST", |
||||
|
headers: { |
||||
|
"Content-Type": undefined |
||||
|
}, |
||||
|
data: $scope.user |
||||
|
}) |
||||
|
.then(function(data) { |
||||
|
console.log("data: "); |
||||
|
console.log(data.data); |
||||
|
localStorage.setItem("dblog_user", JSON.stringify(data.data)); |
||||
|
window.location.reload(); |
||||
|
}, |
||||
|
function(data) { |
||||
|
console.log(data); |
||||
|
}); |
||||
|
|
||||
|
}; |
||||
|
}); |
@ -0,0 +1,14 @@ |
|||||
|
<div class="container"> |
||||
|
<div class="row"> |
||||
|
<div class="col-sm-3"> |
||||
|
<div class="card" style="width: 18rem;"> |
||||
|
<img class="card-img-top" ng-src="http://localhost:8080/ipfs/QmUE6hhNsyUA5emj2dviVDNYK7mSbPeZmRKeCYthmtemeA" alt="Card image cap"> |
||||
|
<div class="card-body"> |
||||
|
<h5 class="card-title">Post1</h5> |
||||
|
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p> |
||||
|
<a href="#" class="btn btn-primary">Go somewhere</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
@ -0,0 +1,16 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
angular.module('app.main', ['ngRoute']) |
||||
|
|
||||
|
.config(['$routeProvider', function($routeProvider) { |
||||
|
$routeProvider.when('/main', { |
||||
|
templateUrl: 'views/main/main.html', |
||||
|
controller: 'MainCtrl' |
||||
|
}); |
||||
|
}]) |
||||
|
|
||||
|
.controller('MainCtrl', function($scope, $rootScope, $http) { |
||||
|
|
||||
|
|
||||
|
|
||||
|
}); |
@ -0,0 +1,49 @@ |
|||||
|
<div ng-controller="NavbarCtrl"> |
||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-light"> |
||||
|
<a class="navbar-brand" href="#"> |
||||
|
<i title="Server" class="fa fa-cube fa-1x"></i> decentralized-blogging-platform |
||||
|
</a> |
||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> |
||||
|
<span class="navbar-toggler-icon"></span> |
||||
|
</button> |
||||
|
|
||||
|
<div class="collapse navbar-collapse" id="navbarSupportedContent"> |
||||
|
<ul class="navbar-nav mr-auto"> |
||||
|
<li class="nav-item active"> |
||||
|
<a class="nav-link" href="#">Top Posts <span class="sr-only">(current)</span></a> |
||||
|
</li> |
||||
|
<li class="nav-item"> |
||||
|
<a class="nav-link" href="#">Top Writters</a> |
||||
|
</li> |
||||
|
</ul> |
||||
|
<form class="form-inline my-2 my-lg-0"> |
||||
|
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search"> |
||||
|
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button> |
||||
|
</form> |
||||
|
<ul class="navbar-nav" ng-show="user"> |
||||
|
<li class="nav-item"> |
||||
|
<a href="#!/profile" class="nav-link"> |
||||
|
<i title="Profile" class="fa fa-user fa-1x"></i> {{user.username}} |
||||
|
</a> |
||||
|
</li> |
||||
|
<li class="nav-item"> |
||||
|
<a ng-click="logout()" class="nav-link"> |
||||
|
<i title="Logout" class="fa fa-power-off fa-1x"></i> |
||||
|
</a> |
||||
|
</li> |
||||
|
</ul> |
||||
|
<ul class="navbar-nav" ng-show="!user"> |
||||
|
<li class="nav-item"> |
||||
|
<a href="#!/signup" class="nav-link"> |
||||
|
<i title="Signup" class="fa fa-sign-in fa-1x"></i> Signup |
||||
|
</a> |
||||
|
</li> |
||||
|
<li class="nav-item"> |
||||
|
<a href="#!/login" class="nav-link"> |
||||
|
<i title="Login" class="fa fa-sign-in fa-1x"></i> Login |
||||
|
</a> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
</nav> |
||||
|
</div> |
@ -0,0 +1,20 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
angular.module('app.navbar', ['ngRoute']) |
||||
|
|
||||
|
.config(['$routeProvider', function($routeProvider) { |
||||
|
$routeProvider.when('/navbar', { |
||||
|
templateUrl: 'views/navbar.html', |
||||
|
controller: 'NavbarCtrl' |
||||
|
}); |
||||
|
}]) |
||||
|
|
||||
|
.controller('NavbarCtrl', function($scope) { |
||||
|
$scope.user = JSON.parse(localStorage.getItem("dblog_user")); |
||||
|
console.log("user", $scope.user); |
||||
|
$scope.logout = function() { |
||||
|
localStorage.removeItem("dblog_user"); |
||||
|
window.location.reload(); |
||||
|
}; |
||||
|
|
||||
|
}); |
@ -0,0 +1,51 @@ |
|||||
|
<div ng-controller="NavbarCtrl"> |
||||
|
<nav class="navbar navbar-fixed-top o_nav"> |
||||
|
<div class="container-fluid"> |
||||
|
<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="#!/" title="darkID"> |
||||
|
<i title="Server" class="fa fa-cube fa-1x"></i> decentralized-blogging-platform |
||||
|
</a> |
||||
|
</div> |
||||
|
<div class="navbar-collapse collapse navbar-responsive-collapse"> |
||||
|
<ul class="nav navbar-nav"> |
||||
|
<li> |
||||
|
<a href="#!/stats" title="Stats"> |
||||
|
<i title="Server" class="fa fa-th-large fa-1x"></i> Models |
||||
|
</a> |
||||
|
</li> |
||||
|
</ul> |
||||
|
<ul class="nav navbar-nav navbar-right" ng-show="user"><!--logged--> |
||||
|
<li> |
||||
|
<a href="#!/profile"> |
||||
|
<i title="Profile" class="fa fa-user fa-1x"></i> {{user.username}} |
||||
|
</a> |
||||
|
</li> |
||||
|
<li> |
||||
|
<a href="" ng-click="logout()"> |
||||
|
<i title="Create Account" class="fa fa-sign-out fa-1x"></i> Logout |
||||
|
</a> |
||||
|
</li> |
||||
|
</ul> |
||||
|
<ul class="nav navbar-nav navbar-right" ng-show="!user"><!--unlogged--> |
||||
|
<li> |
||||
|
<a href="#!/signup"> |
||||
|
<i title="Create Account" class="fa fa-sign-in fa-1x"></i> Signup |
||||
|
</a> |
||||
|
</li> |
||||
|
</ul> |
||||
|
<ul class="nav navbar-nav navbar-right" ng-show="!user"><!--unlogged--> |
||||
|
<li> |
||||
|
<a href="#!/login"> |
||||
|
<i title="Login" class="fa fa-sign-in fa-1x"></i> Login |
||||
|
</a> |
||||
|
</li> |
||||
|
</ul> |
||||
|
</div> |
||||
|
</div> |
||||
|
</nav> |
||||
|
</div> |
@ -0,0 +1,18 @@ |
|||||
|
<div class="container"> |
||||
|
<div class="row"> |
||||
|
<div class="col-sm-6 col-sm-offset-3"> |
||||
|
<div class="card"> |
||||
|
<div class="card-body"> |
||||
|
<h4>New model</h4> |
||||
|
<input ng-model="model.title" placeholder="Title" type="text" class="form-control"> |
||||
|
<input ng-model="model.description" placeholder="Description" type="text" class="form-control"> |
||||
|
|
||||
|
<input type="file" file-model="file"/> |
||||
|
|
||||
|
<input ng-model="model.accuracy" placeholder="Accuracy" type="text" class="form-control"> |
||||
|
<a ng-click="upload()" class="btn btn-raised pull-right c_o_pink300">Upload</a> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
@ -0,0 +1,79 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
angular.module('app.newmodel', ['ngRoute']) |
||||
|
|
||||
|
.config(['$routeProvider', function($routeProvider) { |
||||
|
$routeProvider.when('/newmodel', { |
||||
|
templateUrl: 'views/newmodel/newmodel.html', |
||||
|
controller: 'NewModelCtrl' |
||||
|
}); |
||||
|
}]) |
||||
|
|
||||
|
.controller('NewModelCtrl', function($scope, $rootScope, $http, toastr) { |
||||
|
|
||||
|
$scope.file = {}; |
||||
|
|
||||
|
$scope.upload = function() { |
||||
|
console.log("upload model"); |
||||
|
var formdata = new FormData(); |
||||
|
formdata.append("file", $scope.file); |
||||
|
|
||||
|
//add the file to ipfs
|
||||
|
/*$http({ |
||||
|
url: ipfs_url + 'add', |
||||
|
method: "POST", |
||||
|
headers: { |
||||
|
"Content-Type": undefined |
||||
|
}, |
||||
|
data: formdata |
||||
|
}) |
||||
|
.then(function(data) { |
||||
|
console.log("data: "); |
||||
|
console.log(data.data); |
||||
|
toastr.success("Model added to IPFS"); |
||||
|
}, |
||||
|
function(data) { |
||||
|
console.log(data); |
||||
|
toastr.error("Error adding Model to IPFS"); |
||||
|
});*/ |
||||
|
|
||||
|
//add the data to userdata
|
||||
|
$http({ |
||||
|
url: clienturl + 'model', |
||||
|
method: "POST", |
||||
|
headers: { |
||||
|
"Content-Type": undefined |
||||
|
}, |
||||
|
data: $scope.model |
||||
|
}) |
||||
|
.then(function(data) { |
||||
|
console.log("data: "); |
||||
|
console.log(data.data); |
||||
|
window.location="/"; |
||||
|
toastr.success("Model uploaded"); |
||||
|
}, |
||||
|
function(data) { |
||||
|
console.log(data); |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
}; |
||||
|
|
||||
|
|
||||
|
|
||||
|
}) |
||||
|
.directive('fileModel', ['$parse', function($parse) { |
||||
|
//directive code from https://www.tutorialspoint.com/angularjs/angularjs_upload_file.htm
|
||||
|
return { |
||||
|
restrict: 'A', |
||||
|
link: function(scope, element, attrs) { |
||||
|
var model = $parse(attrs.fileModel); |
||||
|
var modelSetter = model.assign; |
||||
|
element.bind('change', function() { |
||||
|
scope.$apply(function() { |
||||
|
modelSetter(scope, element[0].files[0]); |
||||
|
}); |
||||
|
}); |
||||
|
} |
||||
|
}; |
||||
|
}]); |
@ -0,0 +1,31 @@ |
|||||
|
<div class="container"> |
||||
|
<div class="row"> |
||||
|
<div class="col-sm-4"> |
||||
|
<div ng-include="'views/user_template.html'"></div> |
||||
|
</div> |
||||
|
<div class="col-sm-8"> |
||||
|
<div class="card"> |
||||
|
<table class="table table-striped table-hover "> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th>#</th> |
||||
|
<th>Title</th> |
||||
|
<th>Description</th> |
||||
|
<th>Accuracy</th> |
||||
|
<th>Rating</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody> |
||||
|
<tr ng-repeat="model in user.models"> |
||||
|
<td>1</td> |
||||
|
<td>{{model.title}}</td> |
||||
|
<td>{{model.description}}</td> |
||||
|
<td>{{model.accuracy}}</td> |
||||
|
<td>{{model.rating}}</td> |
||||
|
</tr> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
@ -0,0 +1,24 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
angular.module('app.profile', ['ngRoute']) |
||||
|
|
||||
|
.config(['$routeProvider', function($routeProvider) { |
||||
|
$routeProvider.when('/profile', { |
||||
|
templateUrl: 'views/profile/profile.html', |
||||
|
controller: 'ProfileCtrl' |
||||
|
}); |
||||
|
}]) |
||||
|
|
||||
|
.controller('ProfileCtrl', function($scope, $rootScope, $http) { |
||||
|
|
||||
|
$http.get(clienturl + 'user') |
||||
|
.then(function(data) { |
||||
|
console.log('data success'); |
||||
|
console.log(data); |
||||
|
$scope.user = data.data; |
||||
|
localStorage.setItem("ai_user", JSON.stringify($scope.user)); |
||||
|
|
||||
|
}, function(data) { |
||||
|
console.log('no user'); |
||||
|
}); |
||||
|
}); |
@ -0,0 +1,38 @@ |
|||||
|
<div class="container" style="margin-top: -80px;"> |
||||
|
<div class="row"> |
||||
|
<div class="col-sm-3"> |
||||
|
|
||||
|
</div> |
||||
|
<div class="col-sm-6"> |
||||
|
<div class="card"> |
||||
|
<div class="card-body"> |
||||
|
<h4 class="card-title"> |
||||
|
Signup |
||||
|
</h4> |
||||
|
<div class="form-group"> |
||||
|
<input ng-model="user.username" class="form-control" placeholder="Username"> |
||||
|
</div> |
||||
|
<div class="form-group"> |
||||
|
<input ng-model="user.email" type="email" class="form-control" placeholder="Email"> |
||||
|
</div> |
||||
|
<div class="form-group"> |
||||
|
<input ng-model="user.password" type="password" class="form-control" placeholder="Password"> |
||||
|
</div> |
||||
|
<div class="row"> |
||||
|
<div class="col-sm-6"> |
||||
|
<a href="#!/login" class="btn btn-raised btn-block c_o_blue300">Cancel</a> |
||||
|
</div> |
||||
|
<div class="col-sm-6"> |
||||
|
<div ng-click="signup()" class="btn btn-raised btn-block c_o_green300 pull-right">Signup</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
|
||||
|
<div class="col-sm-3"> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
@ -0,0 +1,34 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
angular.module('app.signup', ['ngRoute']) |
||||
|
|
||||
|
.config(['$routeProvider', function($routeProvider) { |
||||
|
$routeProvider.when('/signup', { |
||||
|
templateUrl: 'views/signup/signup.html', |
||||
|
controller: 'SignupCtrl' |
||||
|
}); |
||||
|
}]) |
||||
|
|
||||
|
.controller('SignupCtrl', function($scope, $http, $routeParams, $rootScope) { |
||||
|
$scope.signup = function() { |
||||
|
console.log('Doing signup', $scope.user); |
||||
|
$http({ |
||||
|
url: apiurl + 'signup', |
||||
|
method: "POST", |
||||
|
headers: { |
||||
|
"Content-Type": undefined |
||||
|
}, |
||||
|
data: $scope.user |
||||
|
}) |
||||
|
.then(function(data) { |
||||
|
console.log("data: "); |
||||
|
console.log(data.data); |
||||
|
window.location="/#!/login"; |
||||
|
|
||||
|
}, |
||||
|
function(data) { |
||||
|
console.log(data); |
||||
|
}); |
||||
|
|
||||
|
}; |
||||
|
}); |