Toggle navigation
Toggle navigation
This project
Loading...
Sign in
김명현
/
Classroom-Reservation
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
freckie
2020-12-19 16:38:45 +0900
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
9cb5ad61ea2584d712086e76184f92643607cef2
9cb5ad61
1 parent
0407b64d
Update: database shcema
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
90 additions
and
260 deletions
api/endpoints/allowlist.go
api/endpoints/cell.go
api/endpoints/reservation.go
api/endpoints/users.go
api/main.go
api/utils/sheets.go
api/endpoints/allowlist.go
deleted
100644 → 0
View file @
0407b64
package
endpoints
import
(
"classroom/functions"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"strings"
"github.com/julienschmidt/httprouter"
)
// POST /timetables/<file_id>/<sheet_id>/allow
func
(
e
*
Endpoints
)
AllowlistPost
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
ps
httprouter
.
Params
)
{
// Get user email
var
email
string
if
_email
,
ok
:=
r
.
Header
[
"X-User-Email"
];
ok
{
email
=
_email
[
0
]
}
else
{
functions
.
ResponseError
(
w
,
401
,
"X-User-Email 헤더를 보내세요."
)
return
}
// Get Path Parameters
fileID
:=
ps
.
ByName
(
"file_id"
)
sheetID
:=
ps
.
ByName
(
"sheet_id"
)
// Check Permission
var
_count
,
_isSuper
int64
timetable
:=
fmt
.
Sprintf
(
"%s,%s"
,
fileID
,
sheetID
)
row
:=
e
.
DB
.
QueryRow
(
`
SELECT count(timetable_id)
FROM allowlist
WHERE timetable_id=?;
`
,
timetable
)
if
err
:=
row
.
Scan
(
&
_count
);
err
==
nil
{
if
_count
<=
0
{
functions
.
ResponseError
(
w
,
404
,
"존재하지 않는 timetable."
)
return
}
}
row
=
e
.
DB
.
QueryRow
(
`
SELECT (
SELECT count(a.timetable_id)
FROM allowlist AS a, users AS u
WHERE a.user_id=u.id
AND a.timetable_id=?
AND u.email=?
) AS count,
(
SELECT is_super FROM users WHERE email=?
) AS is_super;
`
,
timetable
,
email
,
email
)
if
err
:=
row
.
Scan
(
&
_count
,
&
_isSuper
);
err
==
nil
{
if
_isSuper
!=
1
{
functions
.
ResponseError
(
w
,
403
,
"관리자만 접근할 수 있는 기능입니다."
)
return
}
if
_count
<=
0
{
functions
.
ResponseError
(
w
,
403
,
"timetable에 접근할 권한이 부족합니다."
)
return
}
}
else
{
functions
.
ResponseError
(
w
,
500
,
"예기치 못한 에러 : "
+
err
.
Error
())
return
}
// Parse Request Data
type
reqDataStruct
struct
{
Email
*
string
`json:"email"`
}
var
reqData
reqDataStruct
if
strings
.
Contains
(
r
.
Header
.
Get
(
"Content-Type"
),
"application/json"
)
{
body
,
err
:=
ioutil
.
ReadAll
(
r
.
Body
)
if
err
!=
nil
{
functions
.
ResponseError
(
w
,
500
,
"예기치 못한 에러 : "
+
err
.
Error
())
return
}
json
.
Unmarshal
(
body
,
&
reqData
)
}
else
{
functions
.
ResponseError
(
w
,
400
,
"JSON 형식만 가능합니다."
)
return
}
if
reqData
.
Email
==
nil
{
functions
.
ResponseError
(
w
,
400
,
"파라미터를 전부 보내주세요."
)
return
}
// Querying
_
,
err
:=
e
.
DB
.
Exec
(
`
INSERT INTO allowlist
VALUES (?, (
SELECT id FROM users WHERE email=?
));
`
,
timetable
,
*
(
reqData
.
Email
))
if
err
!=
nil
{
functions
.
ResponseError
(
w
,
500
,
"예기치 못한 에러 : "
+
err
.
Error
())
return
}
functions
.
ResponseOK
(
w
,
"success"
,
nil
)
}
// DELETE /timetables/<file_id>/<sheet_id>/allow
func
(
e
*
Endpoints
)
AllowlistDelete
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
ps
httprouter
.
Params
)
{
// Get user email
var
email
string
if
_email
,
ok
:=
r
.
Header
[
"X-User-Email"
];
ok
{
email
=
_email
[
0
]
}
else
{
functions
.
ResponseError
(
w
,
401
,
"X-User-Email 헤더를 보내세요."
)
return
}
// Get Path Parameters
fileID
:=
ps
.
ByName
(
"file_id"
)
sheetID
:=
ps
.
ByName
(
"sheet_id"
)
// Check Permission
var
_count
,
_isSuper
int64
timetable
:=
fmt
.
Sprintf
(
"%s,%s"
,
fileID
,
sheetID
)
row
:=
e
.
DB
.
QueryRow
(
`
SELECT count(timetable_id)
FROM allowlist
WHERE timetable_id=?;
`
,
timetable
)
if
err
:=
row
.
Scan
(
&
_count
);
err
==
nil
{
if
_count
<=
0
{
functions
.
ResponseError
(
w
,
404
,
"존재하지 않는 timetable."
)
return
}
}
row
=
e
.
DB
.
QueryRow
(
`
SELECT (
SELECT count(a.timetable_id)
FROM allowlist AS a, users AS u
WHERE a.user_id=u.id
AND a.timetable_id=?
AND u.email=?
) AS count,
(
SELECT is_super FROM users WHERE email=?
) AS is_super;
`
,
timetable
,
email
,
email
)
if
err
:=
row
.
Scan
(
&
_count
,
&
_isSuper
);
err
==
nil
{
if
_isSuper
!=
1
{
functions
.
ResponseError
(
w
,
403
,
"관리자만 접근할 수 있는 기능입니다."
)
return
}
if
_count
<=
0
{
functions
.
ResponseError
(
w
,
403
,
"timetable에 접근할 권한이 부족합니다."
)
return
}
}
else
{
functions
.
ResponseError
(
w
,
500
,
"예기치 못한 에러 : "
+
err
.
Error
())
return
}
// Parse Request Data
type
reqDataStruct
struct
{
Email
*
string
`json:"email"`
}
var
reqData
reqDataStruct
if
strings
.
Contains
(
r
.
Header
.
Get
(
"Content-Type"
),
"application/json"
)
{
body
,
err
:=
ioutil
.
ReadAll
(
r
.
Body
)
if
err
!=
nil
{
functions
.
ResponseError
(
w
,
500
,
"예기치 못한 에러 : "
+
err
.
Error
())
return
}
json
.
Unmarshal
(
body
,
&
reqData
)
}
else
{
functions
.
ResponseError
(
w
,
400
,
"JSON 형식만 가능합니다."
)
return
}
if
reqData
.
Email
==
nil
{
functions
.
ResponseError
(
w
,
400
,
"파라미터를 전부 보내주세요."
)
return
}
// Querying
_
,
err
:=
e
.
DB
.
Exec
(
`
DELETE FROM allowlist
WHERE timetable_id=?
AND user_id=(SELECT id FROM users WHERE email=?);
`
,
timetable
,
*
(
reqData
.
Email
))
if
err
!=
nil
{
functions
.
ResponseError
(
w
,
500
,
"예기치 못한 에러 : "
+
err
.
Error
())
return
}
functions
.
ResponseOK
(
w
,
"success"
,
nil
)
}
api/endpoints/cell.go
View file @
9cb5ad6
...
...
@@ -12,7 +12,7 @@ import (
"github.com/julienschmidt/httprouter"
)
// GET /
timetab
les/<file_id>/<sheet_id>/cell
// GET /
fi
les/<file_id>/<sheet_id>/cell
func
(
e
*
Endpoints
)
CellGet
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
ps
httprouter
.
Params
)
{
// Get user email
var
email
string
...
...
@@ -57,28 +57,32 @@ func (e *Endpoints) CellGet(w http.ResponseWriter, r *http.Request, ps httproute
}
// Check Permission
var
_count
,
isSuper
int64
timetable
:=
fmt
.
Sprintf
(
"%s,%s"
,
fileID
,
sheetID
)
var
_count
int64
var
isSuper
,
sheetIDAuto
sql
.
NullInt64
row
:=
e
.
DB
.
QueryRow
(
`
SELECT count(timetable_id)
FROM allowlist
WHERE timetable_id=?;
`
,
timetable
)
if
err
:=
row
.
Scan
(
&
_count
);
err
==
nil
{
if
_count
<=
0
{
functions
.
ResponseError
(
w
,
404
,
"존재하지 않는 timetable."
)
SELECT
(SELECT count(s.id)
FROM sheets AS s, files AS f
WHERE s.file_id=f.id
AND f.id=?
AND s.id=?) AS count,
(SELECT id_auto
FROM sheets
WHERE id=?) AS id_auto,
(SELECT is_super
FROM users
WHERE email=?) AS is_super;
`
,
fileID
,
sheetID
,
sheetID
,
email
)
if
err
:=
row
.
Scan
(
&
_count
,
&
sheetIDAuto
,
&
isSuper
);
err
==
nil
{
if
_count
!=
1
||
!
sheetIDAuto
.
Valid
{
functions
.
ResponseError
(
w
,
404
,
"해당 파일이나 시트가 존재하지 않습니다."
)
return
}
}
row
=
e
.
DB
.
QueryRow
(
`
SELECT is_super FROM users WHERE email=?
`
,
email
)
if
err
:=
row
.
Scan
(
&
isSuper
);
err
!=
nil
{
if
err
==
sql
.
ErrNoRows
{
functions
.
ResponseError
(
w
,
401
,
"해당 유저가 존재하지 않음"
)
if
!
isSuper
.
Valid
{
functions
.
ResponseError
(
w
,
401
,
"등록되지 않은 사용자입니다."
)
return
}
}
else
{
functions
.
ResponseError
(
w
,
500
,
"예기치 못한 에러 : "
+
err
.
Error
())
return
}
...
...
@@ -93,8 +97,8 @@ func (e *Endpoints) CellGet(w http.ResponseWriter, r *http.Request, ps httproute
FROM transactions AS t, users AS u
WHERE t.user_id=u.id
AND t.transaction_type=1
AND t.
timetable
_id=?
AND t.cell_column=?;`
,
timetable
,
cellColumn
)
AND t.
sheet
_id=?
AND t.cell_column=?;`
,
sheetIDAuto
.
Int64
,
cellColumn
)
if
err
!=
nil
{
if
err
==
sql
.
ErrNoRows
{
resp
.
CellsCount
=
0
...
...
api/endpoints/reservation.go
View file @
9cb5ad6
...
...
@@ -15,7 +15,7 @@ import (
"github.com/julienschmidt/httprouter"
)
// POST /
timetab
les/<file_id>/<sheet_id>/reservation
// POST /
fi
les/<file_id>/<sheet_id>/reservation
func
(
e
*
Endpoints
)
ReservationPost
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
ps
httprouter
.
Params
)
{
// Get user email
var
email
string
...
...
@@ -31,18 +31,38 @@ func (e *Endpoints) ReservationPost(w http.ResponseWriter, r *http.Request, ps h
sheetID
:=
ps
.
ByName
(
"sheet_id"
)
// Check Permission
var
_timetableName
string
timetable
:=
fmt
.
Sprintf
(
"%s,%s"
,
fileID
,
sheetID
)
var
_count
int64
var
isSuper
,
sheetIDAuto
sql
.
NullInt64
var
sheetName
sql
.
NullString
row
:=
e
.
DB
.
QueryRow
(
`
SELECT name
FROM timetables
WHERE timetable_id=?;
`
,
timetable
)
if
err
:=
row
.
Scan
(
&
_timetableName
);
err
!=
nil
{
if
err
==
sql
.
ErrNoRows
{
functions
.
ResponseError
(
w
,
404
,
"존재하지 않는 timetable."
)
SELECT
(SELECT count(s.id)
FROM sheets AS s, files AS f
WHERE s.file_id=f.id
AND f.id=?
AND s.id=?) AS count,
(SELECT name
FROM sheets
WHERE id=?) AS sheet_name,
(SELECT id_auto
FROM sheets
WHERE id=?) AS id_auto,
(SELECT is_super
FROM users
WHERE email=?) AS is_super;
`
,
fileID
,
sheetID
,
sheetID
,
sheetID
,
email
)
if
err
:=
row
.
Scan
(
&
_count
,
&
sheetName
,
&
sheetIDAuto
,
&
isSuper
);
err
==
nil
{
if
_count
!=
1
||
!
sheetName
.
Valid
||
!
sheetIDAuto
.
Valid
{
functions
.
ResponseError
(
w
,
404
,
"해당 파일이나 시트가 존재하지 않습니다."
)
return
}
if
!
isSuper
.
Valid
{
functions
.
ResponseError
(
w
,
401
,
"등록되지 않은 사용자입니다."
)
return
}
}
else
{
functions
.
ResponseError
(
w
,
500
,
"예기치 못한 에러 : "
+
err
.
Error
())
return
}
// Parse Request Data
...
...
@@ -86,9 +106,9 @@ func (e *Endpoints) ReservationPost(w http.ResponseWriter, r *http.Request, ps h
SELECT cell_start, cell_end
FROM transactions
WHERE transaction_type=1
AND
timetable
_id=?
AND
sheet
_id=?
AND cell_column=?;
`
,
timetable
,
*
(
reqData
.
Column
))
`
,
sheetIDAuto
.
Int64
,
*
(
reqData
.
Column
))
if
err
==
sql
.
ErrNoRows
{
isPossible
=
true
}
...
...
@@ -119,11 +139,11 @@ loopCheckingValidation:
// Querying
res
,
err
:=
tx
.
Exec
(
`
INSERT INTO transactions (transaction_type, user_id,
timetable
_id, lecture, capacity, cell_column, cell_start, cell_end, professor)
INSERT INTO transactions (transaction_type, user_id,
sheet
_id, lecture, capacity, cell_column, cell_start, cell_end, professor)
VALUES (1, (
SELECT id FROM users WHERE email=?
), ?, ?, ?, ?, ?, ?, ?);
`
,
email
,
timetable
,
*
(
reqData
.
Lecture
),
*
(
reqData
.
Capacity
),
*
(
reqData
.
Column
),
*
(
reqData
.
Start
),
*
(
reqData
.
End
),
*
(
reqData
.
Professor
))
`
,
email
,
sheetIDAuto
.
Int64
,
*
(
reqData
.
Lecture
),
*
(
reqData
.
Capacity
),
*
(
reqData
.
Column
),
*
(
reqData
.
Start
),
*
(
reqData
.
End
),
*
(
reqData
.
Professor
))
if
err
!=
nil
{
functions
.
ResponseError
(
w
,
500
,
err
.
Error
())
return
...
...
@@ -134,14 +154,13 @@ loopCheckingValidation:
sheetIDint
,
_
:=
strconv
.
Atoi
(
sheetID
)
sr
:=
utils
.
NewSheetsRequest
(
fileID
,
_timetableName
,
sheetName
.
String
,
int64
(
sheetIDint
),
*
(
reqData
.
Column
),
int64
(
*
(
reqData
.
Start
)),
int64
(
*
(
reqData
.
End
)),
cellValue
,
)
fmt
.
Println
(
sr
)
err
=
e
.
Sheets
.
WriteAndMerge
(
sr
)
if
err
!=
nil
{
functions
.
ResponseError
(
w
,
500
,
"예기치 못한 에러 : "
+
err
.
Error
())
...
...
@@ -171,7 +190,7 @@ loopCheckingValidation:
functions
.
ResponseOK
(
w
,
"success"
,
resp
)
}
// DELETE /
timetab
les/<file_id>/<sheet_id>/reservation/<reservation_id>
// DELETE /
fi
les/<file_id>/<sheet_id>/reservation/<reservation_id>
func
(
e
*
Endpoints
)
ReservationDelete
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
ps
httprouter
.
Params
)
{
// Get user email
var
email
string
...
...
@@ -188,29 +207,33 @@ func (e *Endpoints) ReservationDelete(w http.ResponseWriter, r *http.Request, ps
reservationID
:=
ps
.
ByName
(
"reservation_id"
)
// Check Permission
var
isSuper
int64
var
_timetableName
string
timetable
:=
fmt
.
Sprintf
(
"%s,%s"
,
fileID
,
sheetID
)
var
_count
int64
var
isSuper
sql
.
NullInt64
var
sheetName
sql
.
NullString
row
:=
e
.
DB
.
QueryRow
(
`
SELECT name
FROM timetables
WHERE timetable_id=?;
`
,
timetable
)
if
err
:=
row
.
Scan
(
&
_timetableName
);
err
!=
nil
{
if
err
==
sql
.
ErrNoRows
{
functions
.
ResponseError
(
w
,
404
,
"존재하지 않는 timetable."
)
SELECT
(SELECT count(s.id)
FROM sheets AS s, files AS f
WHERE s.file_id=f.id
AND f.id=?
AND s.id=?) AS count,
(SELECT name
FROM sheets
WHERE id=?) AS sheet_name,
(SELECT is_super
FROM users
WHERE email=?) AS is_super;
`
,
fileID
,
sheetID
,
sheetID
,
email
)
if
err
:=
row
.
Scan
(
&
_count
,
&
sheetName
,
&
isSuper
);
err
==
nil
{
if
_count
!=
1
||
!
sheetName
.
Valid
{
functions
.
ResponseError
(
w
,
404
,
"해당 파일이나 시트가 존재하지 않습니다."
)
return
}
}
row
=
e
.
DB
.
QueryRow
(
`
SELECT is_super FROM users WHERE email=?
`
,
email
)
if
err
:=
row
.
Scan
(
&
isSuper
);
err
!=
nil
{
if
err
==
sql
.
ErrNoRows
{
functions
.
ResponseError
(
w
,
401
,
"해당 유저가 존재하지 않음"
)
if
!
isSuper
.
Valid
{
functions
.
ResponseError
(
w
,
401
,
"등록되지 않은 사용자입니다."
)
return
}
}
else
{
functions
.
ResponseError
(
w
,
500
,
"예기치 못한 에러 : "
+
err
.
Error
())
return
}
...
...
@@ -241,7 +264,7 @@ func (e *Endpoints) ReservationDelete(w http.ResponseWriter, r *http.Request, ps
functions
.
ResponseError
(
w
,
500
,
"예기치 못한 에러 발생 : "
+
err
.
Error
())
return
}
if
isSuper
==
0
{
if
isSuper
.
Int64
==
0
{
if
_email
!=
email
{
functions
.
ResponseError
(
w
,
403
,
"예약 접근 권한 부족"
)
return
...
...
@@ -269,7 +292,7 @@ func (e *Endpoints) ReservationDelete(w http.ResponseWriter, r *http.Request, ps
sheetIDint
,
_
:=
strconv
.
Atoi
(
sheetID
)
sr
:=
utils
.
NewSheetsRequest
(
fileID
,
_timetableName
,
sheetName
.
String
,
int64
(
sheetIDint
),
_cellColumn
,
_cellStart
,
...
...
api/endpoints/users.go
View file @
9cb5ad6
...
...
@@ -30,7 +30,7 @@ func (e *Endpoints) UsersGet(w http.ResponseWriter, r *http.Request, ps httprout
`
,
email
)
if
err
:=
row
.
Scan
(
&
isSuper
);
err
!=
nil
{
if
err
==
sql
.
ErrNoRows
{
functions
.
ResponseError
(
w
,
401
,
"해당 유저가 존재하지 않
음
"
)
functions
.
ResponseError
(
w
,
401
,
"해당 유저가 존재하지 않
습니다.
"
)
return
}
functions
.
ResponseError
(
w
,
500
,
"예기치 못한 에러 : "
+
err
.
Error
())
...
...
api/main.go
View file @
9cb5ad6
...
...
@@ -74,11 +74,9 @@ func main() {
router
.
GET
(
"/api"
,
ep
.
IndexGet
)
router
.
GET
(
"/api/users"
,
ep
.
UsersGet
)
router
.
POST
(
"/api/users"
,
ep
.
UsersPost
)
router
.
GET
(
"/api/timetables/:file_id/:sheet_id/cell"
,
ep
.
CellGet
)
router
.
POST
(
"/api/timetables/:file_id/:sheet_id/allow"
,
ep
.
AllowlistPost
)
router
.
DELETE
(
"/api/timetables/:file_id/:sheet_id/allow"
,
ep
.
AllowlistDelete
)
router
.
POST
(
"/api/timetables/:file_id/:sheet_id/reservation"
,
ep
.
ReservationPost
)
router
.
DELETE
(
"/api/timetables/:file_id/:sheet_id/reservation/:reservation_id"
,
ep
.
ReservationDelete
)
router
.
GET
(
"/api/files/:file_id/:sheet_id/cell"
,
ep
.
CellGet
)
router
.
POST
(
"/api/files/:file_id/:sheet_id/reservation"
,
ep
.
ReservationPost
)
router
.
DELETE
(
"/api/files/:file_id/:sheet_id/reservation/:reservation_id"
,
ep
.
ReservationDelete
)
// Local Mode
portStr
:=
strconv
.
Itoa
(
cfg
.
Server
.
Port
)
...
...
api/utils/sheets.go
View file @
9cb5ad6
...
...
@@ -96,12 +96,12 @@ func (s *SheetsService) RemoveValue(sr SheetsRequest) error {
Requests
:
[]
*
sheets
.
Request
{
req
,
req2
},
}
_
,
err
:=
s
.
srv
.
Spreadsheets
.
BatchUpdate
(
sr
.
SpreadSheetID
,
rb
)
.
Context
(
s
.
ctx
)
.
Do
()
_
,
err
:=
s
.
srv
.
Spreadsheets
.
Values
.
Clear
(
sr
.
SpreadSheetID
,
sr
.
RangeStr
,
&
sheets
.
ClearValuesRequest
{}
)
.
Do
()
if
err
!=
nil
{
return
err
}
_
,
err
=
s
.
srv
.
Spreadsheets
.
Values
.
Clear
(
sr
.
SpreadSheetID
,
sr
.
RangeStr
,
&
sheets
.
ClearValuesRequest
{}
)
.
Do
()
_
,
err
=
s
.
srv
.
Spreadsheets
.
BatchUpdate
(
sr
.
SpreadSheetID
,
rb
)
.
Context
(
s
.
ctx
)
.
Do
()
if
err
!=
nil
{
return
err
}
...
...
Please
register
or
login
to post a comment