Toggle navigation
Toggle navigation
This project
Loading...
Sign in
2020-2-capstone-design1
/
JJS_project1
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
Ma Suhyeon
2020-11-26 22:09:45 +0900
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
3a8fc5542d99d6aea683c93067ba507e745a9056
3a8fc554
1 parent
0794f28a
Implement two more APIs
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
463 additions
and
288 deletions
source/server/.gitignore
source/server/app.go
source/server/config.go
source/server/data.go
source/server/extraction.go
source/server/go.mod
source/server/go.sum
source/server/main.go
source/server/types.go
source/server/user.go
source/server/util.go
source/server/.gitignore
View file @
3a8fc55
# Created by https://www.toptal.com/developers/gitignore/api/go,vscode
# Edit at https://www.toptal.com/developers/gitignore?templates=go,vscode
### Go ###
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
### Go Patch ###
/vendor/
/Godeps/
### vscode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# End of https://www.toptal.com/developers/gitignore/api/go,vscode
__debug_bin
config.json
# Created by https://www.toptal.com/developers/gitignore/api/go,vscode
# Edit at https://www.toptal.com/developers/gitignore?templates=go,vscode
### Go ###
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
### Go Patch ###
/vendor/
/Godeps/
### vscode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# End of https://www.toptal.com/developers/gitignore/api/go,vscode
__debug_bin
config.json
data
\ No newline at end of file
...
...
source/server/app.go
View file @
3a8fc55
package
main
import
(
"fmt"
"net/http"
"github.com/gorilla/mux"
_
"github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
type
Prop
int
const
(
PropUserNo
Prop
=
iota
)
type
App
struct
{
Config
Config
db
*
sqlx
.
DB
router
*
mux
.
Router
}
func
NewApp
(
config
Config
)
*
App
{
app
:=
new
(
App
)
app
.
Config
=
config
dsn
:=
fmt
.
Sprintf
(
"%s:%s@tcp(%s)/%s"
,
config
.
Database
.
User
,
config
.
Database
.
Password
,
config
.
Database
.
Host
,
config
.
Database
.
Name
)
app
.
db
=
sqlx
.
MustOpen
(
"mysql"
,
dsn
)
app
.
router
=
mux
.
NewRouter
()
app
.
router
.
HandleFunc
(
"/users"
,
app
.
PostUsers
)
.
Methods
(
"POST"
)
app
.
router
.
HandleFunc
(
"/users/tokens"
,
app
.
PostTokens
)
.
Methods
(
"POST"
)
app
.
router
.
Handle
(
"/extractions"
,
app
.
WithAuth
(
app
.
PostExtractions
))
.
Methods
(
"Post"
)
return
app
}
func
(
app
*
App
)
Serve
()
{
http
.
ListenAndServe
(
fmt
.
Sprintf
(
":%d"
,
app
.
Config
.
Port
),
app
.
router
)
}
package
main
import
(
"fmt"
"net/http"
"github.com/gorilla/mux"
_
"github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
type
Prop
int
const
(
PropUserNo
Prop
=
iota
)
type
App
struct
{
Config
Config
db
*
sqlx
.
DB
router
*
mux
.
Router
}
func
NewApp
(
config
Config
)
*
App
{
app
:=
new
(
App
)
app
.
Config
=
config
dsn
:=
fmt
.
Sprintf
(
"%s:%s@tcp(%s)/%s"
,
config
.
Database
.
User
,
config
.
Database
.
Password
,
config
.
Database
.
Host
,
config
.
Database
.
Name
)
app
.
db
=
sqlx
.
MustOpen
(
"mysql"
,
dsn
)
app
.
router
=
mux
.
NewRouter
()
app
.
router
.
HandleFunc
(
"/users"
,
app
.
PostUsers
)
.
Methods
(
"POST"
)
app
.
router
.
HandleFunc
(
"/users/tokens"
,
app
.
PostTokens
)
.
Methods
(
"POST"
)
app
.
router
.
Handle
(
"/extractions"
,
app
.
WithAuth
(
app
.
PostExtractions
))
.
Methods
(
"Post"
)
app
.
router
.
HandleFunc
(
"/extractions/{file}/calls"
,
app
.
GetCalls
)
.
Methods
(
"GET"
)
app
.
router
.
HandleFunc
(
"/extractions/{file}/messages"
,
app
.
GetMessages
)
.
Methods
(
"GET"
)
app
.
router
.
HandleFunc
(
"/extractions/{file}/calls/analyses"
,
app
.
GetCallsAnalyses
)
.
Methods
(
"GET"
)
app
.
router
.
HandleFunc
(
"/extractions/{file}/apps/analyses"
,
app
.
GetAppsAnalyses
)
.
Methods
(
"GET"
)
app
.
router
.
HandleFunc
(
"/extractions/{file}/messages/analyses"
,
app
.
GetMessagesAnalyses
)
.
Methods
(
"GET"
)
return
app
}
func
(
app
*
App
)
Serve
()
{
http
.
ListenAndServe
(
fmt
.
Sprintf
(
":%d"
,
app
.
Config
.
Port
),
app
.
router
)
}
...
...
source/server/config.go
View file @
3a8fc55
package
main
import
(
"encoding/json"
"io/ioutil"
)
type
Config
struct
{
Port
int
`json:"port"`
Database
struct
{
Host
string
`json:"host"`
Name
string
`json:"name"`
User
string
`json:"user"`
Password
string
`json:"password"`
}
`json:"database"`
TokenSecret
string
`json:"token_secret"`
}
func
LoadConfig
(
path
string
)
(
Config
,
error
)
{
config
:=
Config
{}
data
,
err
:=
ioutil
.
ReadFile
(
path
)
if
err
==
nil
{
err
=
json
.
Unmarshal
(
data
,
&
config
)
}
return
config
,
err
}
package
main
import
(
"encoding/json"
"io/ioutil"
)
type
Config
struct
{
Port
int
`json:"port"`
Database
struct
{
Host
string
`json:"host"`
Name
string
`json:"name"`
User
string
`json:"user"`
Password
string
`json:"password"`
}
`json:"database"`
TokenSecret
string
`json:"token_secret"`
}
func
LoadConfig
(
path
string
)
(
Config
,
error
)
{
config
:=
Config
{}
data
,
err
:=
ioutil
.
ReadFile
(
path
)
if
err
==
nil
{
err
=
json
.
Unmarshal
(
data
,
&
config
)
}
return
config
,
err
}
...
...
source/server/data.go
0 → 100644
View file @
3a8fc55
package
main
import
(
"fmt"
"net/http"
"time"
"github.com/gorilla/mux"
"github.com/jmoiron/sqlx"
_
"github.com/mattn/go-sqlite3"
)
type
Call
struct
{
ID
int
`json:"id" db:"id"`
Type
int
`json:"type" db:"type"`
Name
*
string
`json:"name" db:"name"`
Number
int
`json:"number" db:"number"`
Duration
int
`json:"duration" db:"duration"`
Date
Time
`json:"date" db:"date"`
}
func
(
app
*
App
)
GetCalls
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
vars
:=
mux
.
Vars
(
r
)
calls
:=
[]
Call
{}
db
,
err
:=
sqlx
.
Connect
(
"sqlite3"
,
fmt
.
Sprintf
(
"data/1/%s"
,
vars
[
"file"
]))
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Could not open db file"
)
return
}
defer
db
.
Close
()
query
:=
`SELECT * FROM calllog`
fmt
.
Println
(
db
.
Select
(
&
calls
,
query
))
WriteJson
(
w
,
calls
)
}
type
CallStats
struct
{
Number
string
`json:"number" db:"number"`
Name
*
string
`json:"name" db:"name"`
Incoming
int
`json:"incoming" db:"incoming"`
Outgoing
int
`json:"outgoing" db:"outgoing"`
Duration
int
`json:"duration" db:"duration"`
}
func
(
app
*
App
)
GetCallsAnalyses
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
vars
:=
mux
.
Vars
(
r
)
calls
:=
[]
CallStats
{}
db
,
err
:=
sqlx
.
Connect
(
"sqlite3"
,
fmt
.
Sprintf
(
"data/1/%s"
,
vars
[
"file"
]))
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Could not open db file"
)
return
}
defer
db
.
Close
()
query
:=
`SELECT number, name,
(SELECT COUNT(1) FROM calllog s WHERE s.number=c.number AND s.type=1) incoming,
(SELECT COUNT(1) FROM calllog s WHERE s.number=c.number AND s.type=2) outgoing,
SUM(duration) duration
FROM calllog c GROUP BY number ORDER BY duration DESC`
db
.
Select
(
&
calls
,
query
)
WriteJson
(
w
,
calls
)
}
type
AppInfo
struct
{
PackageName
string
`json:"package_name" db:"packagename"`
Name
string
`json:"name" db:"name"`
Version
string
`json:"version" db:"version"`
WifiUsage
int
`json:"wifi_usage" db:"wifiusage"`
CellularUsage
int
`json:"cellular_usage" db:"cellularusage"`
LastUsed
time
.
Time
`json:"last_used" db:"lasttimeused"`
ForegroundTime
int
`json:"foreground_time" db:"totaltimeforeground"`
}
func
(
app
*
App
)
GetAppsAnalyses
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
vars
:=
mux
.
Vars
(
r
)
apps
:=
[]
AppInfo
{}
db
,
err
:=
sqlx
.
Connect
(
"sqlite3"
,
fmt
.
Sprintf
(
"data/1/%s"
,
vars
[
"file"
]))
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Could not open db file"
)
return
}
defer
db
.
Close
()
query
:=
`SELECT
a.packagename, a.name, a.version, a.wifiusage, a.cellularusage,
u.lasttimeused, u.totaltimeforeground
FROM AppInfo a JOIN AppUsageYear u
ORDER BY totaltimeforeground DESC`
db
.
Select
(
&
apps
,
query
)
WriteJson
(
w
,
apps
)
}
type
Message
struct
{
ID
int
`json:"id" db:"mid"`
Type
int
`json:"type" db:"type"`
Address
string
`json:"address"`
Body
string
`json:"body"`
Date
Time
`json:"date" db:"date"`
}
func
(
app
*
App
)
GetMessages
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
vars
:=
mux
.
Vars
(
r
)
messages
:=
[]
Message
{}
db
,
err
:=
sqlx
.
Connect
(
"sqlite3"
,
fmt
.
Sprintf
(
"data/1/%s"
,
vars
[
"file"
]))
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Could not open db file"
)
return
}
defer
db
.
Close
()
query
:=
`SELECT mid, type, address, body, date FROM sms`
db
.
Select
(
&
messages
,
query
)
WriteJson
(
w
,
messages
)
}
type
MessageStats
struct
{
Address
string
`json:"number" db:"number"`
Receive
int
`json:"incoming" db:"incoming"`
Send
int
`json:"outgoing" db:"outgoing"`
}
func
(
app
*
App
)
GetMessagesAnalyses
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
vars
:=
mux
.
Vars
(
r
)
messages
:=
[]
MessageStats
{}
db
,
err
:=
sqlx
.
Connect
(
"sqlite3"
,
fmt
.
Sprintf
(
"data/1/%s"
,
vars
[
"file"
]))
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Could not open db file"
)
return
}
defer
db
.
Close
()
query
:=
`SELECT address,
(SELECT COUNT(1) FROM sms m WHERE m.address=s.address AND m.type=1) receive,
(SELECT COUNT(1) FROM sms m WHERE m.address=s.address AND m.type=2) send
FROM sms s GROUP BY address ORDER BY receive + send DESC`
db
.
Select
(
&
messages
,
query
)
WriteJson
(
w
,
messages
)
}
source/server/extraction.go
View file @
3a8fc55
package
main
import
(
"fmt"
"io"
"net/http"
"os"
"strings"
"github.com/google/uuid"
)
func
(
app
*
App
)
PostExtractions
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
userNo
:=
r
.
Context
()
.
Value
(
PropUserNo
)
.
(
uint64
)
r
.
ParseMultipartForm
(
32
<<
20
)
form
,
_
,
err
:=
r
.
FormFile
(
"file"
)
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Unknown error"
)
return
}
defer
form
.
Close
()
dir
:=
fmt
.
Sprintf
(
"data/%d"
,
userNo
)
os
.
MkdirAll
(
dir
,
0644
)
name
:=
strings
.
Replace
(
uuid
.
New
()
.
String
(),
"-"
,
""
,
-
1
)
file
,
err
:=
os
.
Create
(
fmt
.
Sprintf
(
"%s/%s"
,
dir
,
name
))
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Unknown error"
)
return
}
defer
file
.
Close
()
_
,
err
=
io
.
Copy
(
file
,
form
)
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Unknown error"
)
return
}
w
.
Write
([]
byte
(
"success"
))
}
package
main
import
(
"fmt"
"io"
"net/http"
"os"
"strings"
"github.com/google/uuid"
)
func
(
app
*
App
)
PostExtractions
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
userNo
:=
r
.
Context
()
.
Value
(
PropUserNo
)
.
(
uint64
)
r
.
ParseMultipartForm
(
32
<<
20
)
form
,
_
,
err
:=
r
.
FormFile
(
"file"
)
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Unknown error"
)
return
}
defer
form
.
Close
()
dir
:=
fmt
.
Sprintf
(
"data/%d"
,
userNo
)
os
.
MkdirAll
(
dir
,
0644
)
name
:=
strings
.
Replace
(
uuid
.
New
()
.
String
(),
"-"
,
""
,
-
1
)
file
,
err
:=
os
.
Create
(
fmt
.
Sprintf
(
"%s/%s"
,
dir
,
name
))
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Unknown error"
)
return
}
defer
file
.
Close
()
_
,
err
=
io
.
Copy
(
file
,
form
)
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Unknown error"
)
return
}
w
.
Write
([]
byte
(
"success"
))
}
...
...
source/server/go.mod
View file @
3a8fc55
...
...
@@ -8,5 +8,6 @@ require (
github.com/google/uuid v1.1.2
github.com/gorilla/mux v1.8.0
github.com/jmoiron/sqlx v1.2.0
github.com/mattn/go-sqlite3 v1.9.0
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897
)
...
...
source/server/go.sum
View file @
3a8fc55
...
...
@@ -11,6 +11,7 @@ github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB7
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897 h1:pLI5jrR7OSLijeIDcmRxNmw2api+jEfxLoykJVice/E=
...
...
source/server/main.go
View file @
3a8fc55
package
main
import
(
"log"
)
func
main
()
{
config
,
err
:=
LoadConfig
(
"config.json"
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
app
:=
NewApp
(
config
)
app
.
Serve
()
}
package
main
import
(
"log"
)
func
main
()
{
config
,
err
:=
LoadConfig
(
"config.json"
)
if
err
!=
nil
{
log
.
Fatal
(
err
)
}
app
:=
NewApp
(
config
)
app
.
Serve
()
}
...
...
source/server/types.go
0 → 100644
View file @
3a8fc55
package
main
import
(
"time"
)
type
Time
time
.
Time
func
(
t
*
Time
)
Scan
(
v
interface
{})
error
{
p
,
err
:=
time
.
Parse
(
"2006-01-02 15:04:05"
,
string
(
v
.
([]
byte
)))
*
t
=
Time
(
p
)
return
err
}
func
(
t
*
Time
)
MarshalJSON
()
([]
byte
,
error
)
{
return
time
.
Time
(
*
t
)
.
MarshalJSON
()
}
source/server/user.go
View file @
3a8fc55
package
main
import
(
"context"
"encoding/json"
"net/http"
"strings"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/go-sql-driver/mysql"
"golang.org/x/crypto/sha3"
)
type
User
struct
{
No
uint64
`json:"no"`
ID
string
`json:"id"`
Name
string
`json:"name"`
CreatedAt
time
.
Time
`json:"created_at"`
ExpiredAt
time
.
Time
`json:"expired_at"`
}
func
(
app
*
App
)
PostUsers
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
body
:=
make
(
map
[
string
]
interface
{})
err
:=
json
.
NewDecoder
(
r
.
Body
)
.
Decode
(
&
body
)
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusBadRequest
,
"Failed to parse request json"
)
return
}
hash
:=
sha3
.
Sum256
([]
byte
(
body
[
"password"
]
.
(
string
)))
res
,
err
:=
app
.
db
.
Exec
(
"INSERT INTO users (`id`, `password`, `name`) VALUES (?, ?, ?)"
,
body
[
"id"
],
hash
[
:
],
body
[
"name"
])
if
err
!=
nil
{
if
merr
,
ok
:=
err
.
(
*
mysql
.
MySQLError
);
ok
{
if
merr
.
Number
==
1062
{
WriteError
(
w
,
http
.
StatusConflict
,
"Already registered"
)
return
}
}
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Failed to register"
)
return
}
no
,
_
:=
res
.
LastInsertId
()
WriteJson
(
w
,
map
[
string
]
interface
{}{
"user_no"
:
no
})
}
type
AuthClaims
struct
{
UserNo
uint64
`json:"user_no"`
jwt
.
StandardClaims
}
func
(
app
*
App
)
PostTokens
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
body
:=
make
(
map
[
string
]
interface
{})
err
:=
json
.
NewDecoder
(
r
.
Body
)
.
Decode
(
&
body
)
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusBadRequest
,
"Failed to parse request json"
)
return
}
hash
:=
sha3
.
Sum256
([]
byte
(
body
[
"password"
]
.
(
string
)))
rows
,
err
:=
app
.
db
.
Query
(
"SELECT `no` FROM users WHERE `id`=? AND `password`=?"
,
body
[
"id"
],
hash
[
:
])
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Failed to register"
)
return
}
if
!
rows
.
Next
()
{
WriteError
(
w
,
http
.
StatusUnauthorized
,
"Login failed"
)
return
}
no
:=
uint64
(
0
)
rows
.
Scan
(
&
no
)
token
:=
jwt
.
NewWithClaims
(
jwt
.
SigningMethodHS256
,
AuthClaims
{
UserNo
:
no
})
auth
,
err
:=
token
.
SignedString
([]
byte
(
app
.
Config
.
TokenSecret
))
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Login failed"
)
return
}
WriteJson
(
w
,
map
[
string
]
interface
{}{
"token"
:
auth
})
}
func
(
app
*
App
)
WithAuth
(
next
func
(
http
.
ResponseWriter
,
*
http
.
Request
))
http
.
Handler
{
return
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
auth
:=
r
.
Header
.
Get
(
"Authorization"
)
if
len
(
auth
)
>
6
&&
strings
.
Index
(
auth
,
"Bearer "
)
==
0
{
token
,
err
:=
jwt
.
ParseWithClaims
(
auth
[
7
:
],
&
AuthClaims
{},
func
(
token
*
jwt
.
Token
)
(
interface
{},
error
)
{
return
[]
byte
(
app
.
Config
.
TokenSecret
),
nil
})
if
err
==
nil
{
claims
:=
token
.
Claims
.
(
*
AuthClaims
)
ctx
:=
context
.
WithValue
(
r
.
Context
(),
PropUserNo
,
claims
.
UserNo
)
next
(
w
,
r
.
WithContext
(
ctx
))
return
}
}
WriteError
(
w
,
http
.
StatusUnauthorized
,
"Authorization failed"
)
})
}
package
main
import
(
"context"
"encoding/json"
"net/http"
"strings"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/go-sql-driver/mysql"
"golang.org/x/crypto/sha3"
)
type
User
struct
{
No
uint64
`json:"no"`
ID
string
`json:"id"`
Name
string
`json:"name"`
CreatedAt
time
.
Time
`json:"created_at"`
ExpiredAt
time
.
Time
`json:"expired_at"`
}
func
(
app
*
App
)
PostUsers
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
body
:=
make
(
map
[
string
]
interface
{})
err
:=
json
.
NewDecoder
(
r
.
Body
)
.
Decode
(
&
body
)
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusBadRequest
,
"Failed to parse request json"
)
return
}
hash
:=
sha3
.
Sum256
([]
byte
(
body
[
"password"
]
.
(
string
)))
res
,
err
:=
app
.
db
.
Exec
(
"INSERT INTO users (`id`, `password`, `name`) VALUES (?, ?, ?)"
,
body
[
"id"
],
hash
[
:
],
body
[
"name"
])
if
err
!=
nil
{
if
merr
,
ok
:=
err
.
(
*
mysql
.
MySQLError
);
ok
{
if
merr
.
Number
==
1062
{
WriteError
(
w
,
http
.
StatusConflict
,
"Already registered"
)
return
}
}
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Failed to register"
)
return
}
no
,
_
:=
res
.
LastInsertId
()
WriteJson
(
w
,
map
[
string
]
interface
{}{
"user_no"
:
no
})
}
type
AuthClaims
struct
{
UserNo
uint64
`json:"user_no"`
jwt
.
StandardClaims
}
func
(
app
*
App
)
PostTokens
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
body
:=
make
(
map
[
string
]
interface
{})
err
:=
json
.
NewDecoder
(
r
.
Body
)
.
Decode
(
&
body
)
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusBadRequest
,
"Failed to parse request json"
)
return
}
hash
:=
sha3
.
Sum256
([]
byte
(
body
[
"password"
]
.
(
string
)))
rows
,
err
:=
app
.
db
.
Query
(
"SELECT `no` FROM users WHERE `id`=? AND `password`=?"
,
body
[
"id"
],
hash
[
:
])
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Failed to register"
)
return
}
if
!
rows
.
Next
()
{
WriteError
(
w
,
http
.
StatusUnauthorized
,
"Login failed"
)
return
}
no
:=
uint64
(
0
)
rows
.
Scan
(
&
no
)
token
:=
jwt
.
NewWithClaims
(
jwt
.
SigningMethodHS256
,
AuthClaims
{
UserNo
:
no
})
auth
,
err
:=
token
.
SignedString
([]
byte
(
app
.
Config
.
TokenSecret
))
if
err
!=
nil
{
WriteError
(
w
,
http
.
StatusInternalServerError
,
"Login failed"
)
return
}
WriteJson
(
w
,
map
[
string
]
interface
{}{
"token"
:
auth
})
}
func
(
app
*
App
)
WithAuth
(
next
func
(
http
.
ResponseWriter
,
*
http
.
Request
))
http
.
Handler
{
return
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
auth
:=
r
.
Header
.
Get
(
"Authorization"
)
if
len
(
auth
)
>
6
&&
strings
.
Index
(
auth
,
"Bearer "
)
==
0
{
token
,
err
:=
jwt
.
ParseWithClaims
(
auth
[
7
:
],
&
AuthClaims
{},
func
(
token
*
jwt
.
Token
)
(
interface
{},
error
)
{
return
[]
byte
(
app
.
Config
.
TokenSecret
),
nil
})
if
err
==
nil
{
claims
:=
token
.
Claims
.
(
*
AuthClaims
)
ctx
:=
context
.
WithValue
(
r
.
Context
(),
PropUserNo
,
claims
.
UserNo
)
next
(
w
,
r
.
WithContext
(
ctx
))
return
}
}
WriteError
(
w
,
http
.
StatusUnauthorized
,
"Authorization failed"
)
})
}
...
...
source/server/util.go
View file @
3a8fc55
package
main
import
(
"encoding/json"
"net/http"
)
func
WriteJson
(
w
http
.
ResponseWriter
,
data
interface
{})
{
w
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
json
.
NewEncoder
(
w
)
.
Encode
(
data
)
}
func
WriteError
(
w
http
.
ResponseWriter
,
status
int
,
message
string
)
{
w
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
w
.
WriteHeader
(
status
)
json
.
NewEncoder
(
w
)
.
Encode
(
map
[
string
]
interface
{}{
"msg"
:
message
})
}
package
main
import
(
"encoding/json"
"net/http"
)
func
WriteJson
(
w
http
.
ResponseWriter
,
data
interface
{})
{
w
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
json
.
NewEncoder
(
w
)
.
Encode
(
data
)
}
func
WriteError
(
w
http
.
ResponseWriter
,
status
int
,
message
string
)
{
w
.
Header
()
.
Set
(
"Content-Type"
,
"application/json"
)
w
.
WriteHeader
(
status
)
json
.
NewEncoder
(
w
)
.
Encode
(
map
[
string
]
interface
{}{
"msg"
:
message
})
}
...
...
Please
register
or
login
to post a comment