Skip to content

Commit

Permalink
feat(rbac): Added role and checked permission (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
hoangtk0100 committed Oct 27, 2023
1 parent e10e7ad commit aa69049
Show file tree
Hide file tree
Showing 43 changed files with 153 additions and 129 deletions.
46 changes: 23 additions & 23 deletions api/account_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestGetAccountAPI(t *testing.T) {
name: "OK",
accountID: account.ID,
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().
Expand All @@ -52,7 +52,7 @@ func TestGetAccountAPI(t *testing.T) {
name: "UnauthorizedUser",
accountID: account.ID,
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "unauthorized_user", time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "unauthorized_user", user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().
Expand Down Expand Up @@ -82,7 +82,7 @@ func TestGetAccountAPI(t *testing.T) {
name: "NotFound",
accountID: account.ID,
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().
Expand All @@ -98,7 +98,7 @@ func TestGetAccountAPI(t *testing.T) {
name: "InternalError",
accountID: account.ID,
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().
Expand All @@ -114,7 +114,7 @@ func TestGetAccountAPI(t *testing.T) {
name: "InvalidID",
accountID: 0,
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().
Expand Down Expand Up @@ -179,7 +179,7 @@ func TestCreateAccountAPI(t *testing.T) {
"currency": account.Currency,
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
arg := db.CreateAccountParams{
Expand Down Expand Up @@ -220,7 +220,7 @@ func TestCreateAccountAPI(t *testing.T) {
"currency": account.Currency,
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().
Expand All @@ -238,7 +238,7 @@ func TestCreateAccountAPI(t *testing.T) {
"currency": "invalid",
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().
Expand Down Expand Up @@ -307,7 +307,7 @@ func TestListAccountsAPI(t *testing.T) {
pageSize: n,
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
arg := db.ListAccountsParams{
Expand Down Expand Up @@ -350,7 +350,7 @@ func TestListAccountsAPI(t *testing.T) {
pageSize: n,
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().
Expand All @@ -369,7 +369,7 @@ func TestListAccountsAPI(t *testing.T) {
pageSize: n,
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().
Expand All @@ -387,7 +387,7 @@ func TestListAccountsAPI(t *testing.T) {
pageSize: 100000,
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().
Expand Down Expand Up @@ -450,7 +450,7 @@ func TestUpdateAccountAPI(t *testing.T) {
"balance": balance,
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().GetAccount(gomock.Any(), gomock.Eq(account.ID)).Times(1).Return(account, nil)
Expand All @@ -473,7 +473,7 @@ func TestUpdateAccountAPI(t *testing.T) {
"balance": balance,
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "unauthorized_user", time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "unauthorized_user", user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().GetAccount(gomock.Any(), gomock.Eq(account.ID)).Times(1).Return(account, nil)
Expand Down Expand Up @@ -506,7 +506,7 @@ func TestUpdateAccountAPI(t *testing.T) {
"balance": balance,
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().GetAccount(gomock.Any(), gomock.Eq(account.ID)).Times(1).Return(db.Account{}, sql.ErrConnDone)
Expand All @@ -523,7 +523,7 @@ func TestUpdateAccountAPI(t *testing.T) {
"balance": balance,
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().GetAccount(gomock.Any(), gomock.Eq(account.ID)).Times(1).Return(db.Account{}, db.ErrRecordNotFound)
Expand All @@ -540,7 +540,7 @@ func TestUpdateAccountAPI(t *testing.T) {
"balance": balance,
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().GetAccount(gomock.Any(), gomock.Any()).Times(0)
Expand All @@ -557,7 +557,7 @@ func TestUpdateAccountAPI(t *testing.T) {
"balance": -10,
},
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().GetAccount(gomock.Any(), gomock.Any()).Times(0)
Expand Down Expand Up @@ -612,7 +612,7 @@ func TestDeleteAccountAPI(t *testing.T) {
name: "OK",
accountID: account.ID,
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().GetAccount(gomock.Any(), gomock.Eq(account.ID)).Times(1).Return(account, nil)
Expand All @@ -626,7 +626,7 @@ func TestDeleteAccountAPI(t *testing.T) {
name: "UnauthorizedUser",
accountID: account.ID,
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "unauthorized_user", time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "unauthorized_user", user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().GetAccount(gomock.Any(), gomock.Eq(account.ID)).Times(1).Return(account, nil)
Expand All @@ -653,7 +653,7 @@ func TestDeleteAccountAPI(t *testing.T) {
name: "InternalError",
accountID: account.ID,
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().GetAccount(gomock.Any(), gomock.Eq(account.ID)).Times(1).Return(db.Account{}, sql.ErrConnDone)
Expand All @@ -667,7 +667,7 @@ func TestDeleteAccountAPI(t *testing.T) {
name: "NotFound",
accountID: account.ID,
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().GetAccount(gomock.Any(), gomock.Eq(account.ID)).Times(1).Return(db.Account{}, db.ErrRecordNotFound)
Expand All @@ -681,7 +681,7 @@ func TestDeleteAccountAPI(t *testing.T) {
name: "InvalidID",
accountID: 0,
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, user.Username, user.Role, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
store.EXPECT().GetAccount(gomock.Any(), gomock.Any()).Times(0)
Expand Down
4 changes: 2 additions & 2 deletions api/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,13 @@ func (server *Server) login(ctx *gin.Context) {
return
}

accessToken, accessPayload, err := server.tokenMaker.CreateToken(user.Username, server.config.AccessTokenDuration)
accessToken, accessPayload, err := server.tokenMaker.CreateToken(user.Username, user.Role, server.config.AccessTokenDuration)
if err != nil {
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
return
}

refreshToken, refreshPayload, err := server.tokenMaker.CreateToken(user.Username, server.config.RefreshTokenDuration)
refreshToken, refreshPayload, err := server.tokenMaker.CreateToken(user.Username, user.Role, server.config.RefreshTokenDuration)
if err != nil {
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
return
Expand Down
13 changes: 8 additions & 5 deletions api/middleware_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/gin-gonic/gin"
"github.com/hoangtk0100/simple-bank/token"
"github.com/hoangtk0100/simple-bank/util"
"github.com/stretchr/testify/require"
)

Expand All @@ -18,9 +19,10 @@ func addAuthorization(
tokenMaker token.Maker,
authorizationType string,
username string,
role string,
duration time.Duration,
) {
token, payload, err := tokenMaker.CreateToken(username, duration)
token, payload, err := tokenMaker.CreateToken(username, role, duration)
require.NoError(t, err)
require.NotEmpty(t, token)
require.NotEmpty(t, payload)
Expand All @@ -30,6 +32,7 @@ func addAuthorization(
}

func TestAuthMiddleware(t *testing.T) {
role := util.DepositorRole
testcases := []struct {
name string
setupAuth func(t *testing.T, request *http.Request, tokenMaker token.Maker)
Expand All @@ -38,7 +41,7 @@ func TestAuthMiddleware(t *testing.T) {
{
name: "OK",
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "user", time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "user", role, time.Minute)
},
checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusOK, recorder.Code)
Expand All @@ -55,7 +58,7 @@ func TestAuthMiddleware(t *testing.T) {
{
name: "UnsupportedAuthorization",
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, "unsupported", "user", time.Minute)
addAuthorization(t, request, tokenMaker, "unsupported", "user", role, time.Minute)
},
checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusUnauthorized, recorder.Code)
Expand All @@ -64,7 +67,7 @@ func TestAuthMiddleware(t *testing.T) {
{
name: "InvalidAuthorization",
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, "", "user", time.Minute)
addAuthorization(t, request, tokenMaker, "", "user", role, time.Minute)
},
checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusUnauthorized, recorder.Code)
Expand All @@ -73,7 +76,7 @@ func TestAuthMiddleware(t *testing.T) {
{
name: "ExpiredToken",
setupAuth: func(t *testing.T, request *http.Request, tokenMaker token.Maker) {
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "user", -time.Minute)
addAuthorization(t, request, tokenMaker, authorizationTypeBearer, "user", role, -time.Minute)
},
checkResponse: func(t *testing.T, recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusUnauthorized, recorder.Code)
Expand Down
2 changes: 1 addition & 1 deletion api/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func (server *Server) renewAccessToken(ctx *gin.Context) {
return
}

accessToken, accessPayload, err := server.tokenMaker.CreateToken(refreshPayload.Username, server.config.AccessTokenDuration)
accessToken, accessPayload, err := server.tokenMaker.CreateToken(refreshPayload.Username, refreshPayload.Role, server.config.AccessTokenDuration)
if err != nil {
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
return
Expand Down
Loading

0 comments on commit aa69049

Please sign in to comment.