Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 67 additions & 32 deletions src/fs/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,41 @@ func use(h http.HandlerFunc, middleware ...func(http.HandlerFunc) http.HandlerFu
return h
}

func isAdmin(r *http.Request) bool {
// if Authorization header is not present, this is admin user
authToken := r.Header.Get("Authorization")
return authToken == ""
}

func (service *MercuryFsService) authenticate(writer http.ResponseWriter, request *http.Request) {
// decode and parse json request body
defer request.Body.Close()
decoder := json.NewDecoder(request.Body)
data := make(map[string]interface{})
err := decoder.Decode(&data)
if err != nil {
panic(err)
writer.WriteHeader(http.StatusBadRequest)
return
}
defer request.Body.Close()
// read pin from the json body
pin, ok := data["pin"].(string)
if !ok {
// pin is not a string
// pin is not a string, send 400 Bad Request
writer.WriteHeader(http.StatusBadRequest)
return
}
// query user for the given pin from the list of all users
authToken, err := service.Users.queryUser(pin)
switch {
case err == sql.ErrNoRows:
case err == sql.ErrNoRows: // if no such user exits, send 401 Unauthorized
log("No user with pin: %s", pin)
http.Error(writer, "Authentication Failed", http.StatusUnauthorized)
break
case err != nil:
case err != nil: // if some other error, send 500 Internal Server Error
http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
log(err.Error())
break
default:
default: // if no error, send proper auth token for that user
respJson := fmt.Sprintf("{\"auth_token\": \"%s\"}", *authToken)
writer.WriteHeader(http.StatusOK)
size := int64(len(respJson))
Expand All @@ -58,6 +68,7 @@ func (service *MercuryFsService) logout(w http.ResponseWriter, r *http.Request)
func (service *MercuryFsService) checkAuthHeader(w http.ResponseWriter, r *http.Request) (user *HdaUser) {
authToken := r.Header.Get("Authorization")
user = service.Users.find(authToken)
// if user is nil, respond with 401 Unauthorized
if user == nil {
http.Error(w, "Authentication Failed", http.StatusUnauthorized)
}
Expand All @@ -66,47 +77,71 @@ func (service *MercuryFsService) checkAuthHeader(w http.ResponseWriter, r *http.

func (service *MercuryFsService) authMiddleware(pass http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
user := service.checkAuthHeader(w, r)
if user != nil {
if isAdmin(r) {
// auth header is not present, pass as this is admin user
pass(w, r)
} else {
// auth header is present, pass only if a user exists for the given auth_token
user := service.checkAuthHeader(w, r)
if user != nil {
pass(w, r)
}
}
}
}

func (service *MercuryFsService) shareReadAccess(pass http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
user := service.checkAuthHeader(w, r)
if user == nil {
return
}
shareName := r.URL.Query().Get("s")
if access, err := user.HasReadAccess(shareName); !access {
if err == nil {
http.Error(w, "Access Forbidden", http.StatusForbidden)
} else {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
if isAdmin(r) {
// auth header is not present, pass as this is admin user
pass(w, r)
} else {
user := service.checkAuthHeader(w, r)
// if user is nil, we have already responded with 401 Unauthorized, so return
if user == nil {
return
}
return
// check for share name, and if the user has read access for it
// if no access, send 403 Forbidden
// else if error, send 500 Internal Server Error
shareName := r.URL.Query().Get("s")
if access, err := user.HasReadAccess(shareName); !access {
if err == nil {
http.Error(w, "Access Forbidden", http.StatusForbidden)
} else {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
return
}
pass(w, r)
}
pass(w, r)
}
}

func (service *MercuryFsService) shareWriteAccess(pass http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
user := service.checkAuthHeader(w, r)
if user == nil {
return
}
shareName := r.URL.Query().Get("s")
if access, err := user.HasWriteAccess(shareName); !access {
if err == nil {
http.Error(w, "Access Forbidden", http.StatusForbidden)
} else {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
if isAdmin(r) {
// auth header is not present, pass as this is admin user
pass(w, r)
} else {
user := service.checkAuthHeader(w, r)
// if user is nil, we have already responded with 401 Unauthorized, so return
if user == nil {
return
}
return
// check for share name, and if the user has write access for it
// if no access, send 403 Forbidden
// else if error, send 500 Internal Server Error
shareName := r.URL.Query().Get("s")
if access, err := user.HasWriteAccess(shareName); !access {
if err == nil {
http.Error(w, "Access Forbidden", http.StatusForbidden)
} else {
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
return
}
pass(w, r)
}
pass(w, r)
}
}
11 changes: 7 additions & 4 deletions src/fs/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,13 +273,16 @@ func (service *MercuryFsService) serveFile(writer http.ResponseWriter, request *
}

func (service *MercuryFsService) serveShares(writer http.ResponseWriter, request *http.Request) {
user := service.checkAuthHeader(writer, request)
if user == nil {
return
var user *HdaUser
if !isAdmin(request) {
user = service.checkAuthHeader(writer, request)
if user == nil {
return
}
}
var shares []*HdaShare
var err error
if service.Shares.rootDir == "" {
if service.Shares.rootDir == "" && user != nil {
shares, err = user.AvailableShares()
if err != nil {
http.Error(writer, "Internal Server Error", http.StatusInternalServerError)
Expand Down