Login via api

This commit is contained in:
Abhishek Shroff
2024-07-31 01:03:50 -07:00
parent 6433b91f45
commit 71dda36499
7 changed files with 102 additions and 23 deletions

View File

@@ -0,0 +1,72 @@
package api
import (
"errors"
"strings"
"github.com/gin-gonic/gin"
"github.com/shroff/phylum/server/internal/app"
"github.com/sirupsen/logrus"
)
func Setup(r *gin.RouterGroup) {
setupAuthRoutes(r)
r.Use(func(c *gin.Context) {
authHeader := strings.Split(c.GetHeader("Authorization"), " ")
logrus.Info(authHeader)
rersponseObj := gin.H{
"ERR": "Unauthorized",
}
c.JSON(401, rersponseObj)
})
setupResourceRoutes(r)
}
func setupAuthRoutes(r *gin.RouterGroup) {
group := r.Group("/auth")
group.POST("/login", handleLoginRoute)
}
func setupResourceRoutes(r *gin.RouterGroup) {
group := r.Group("/resources")
group.GET("/:id/metadata")
group.PUT("/:id/metadata")
group.GET("/:id/contents")
group.PUT("/:id/contents")
}
func handleLoginRoute(c *gin.Context) {
username, ok := c.GetQuery("username")
if !ok {
c.AbortWithStatusJSON(401, gin.H{
"ERR_CODE": "missing_params",
"ERR_DETAILS": "Missing username input",
})
return
}
password, ok := c.GetQuery("password")
if !ok {
c.AbortWithStatusJSON(401, gin.H{
"ERR_CODE": "missing_params",
"ERR_DETAILS": "Missing password input",
})
return
}
if token, err := app.Default.CreateAccessToken(username, password); err != nil {
if errors.Is(err, app.ErrInvalidUsernamePassword) {
c.AbortWithStatusJSON(401, gin.H{
"ERR_CODE": "invalid_username_or_password",
})
} else {
c.AbortWithStatusJSON(401, gin.H{
"ERR_DETAILS": err.Error(),
})
}
} else {
c.JSON(200, gin.H{
"access_token": token.ID,
"expires": token.Expires.Time.String(),
})
}
}

View File

@@ -24,30 +24,30 @@ var accessTokenValiditiy = pgtype.Interval{
var ErrInvalidUsernamePassword = errors.New("invalid username or password")
var ErrAccessTokenExpired = errors.New("access token expired")
func (a App) CreateAccessToken(username, password, deviceInfo string) (string, error) {
func (a App) CreateAccessToken(username, password string) (sql.AccessToken, error) {
if user, err := a.FindUser(context.Background(), username); err != nil {
if err == pgx.ErrNoRows {
return "", ErrInvalidUsernamePassword
return sql.AccessToken{}, ErrInvalidUsernamePassword
}
logrus.Info(err)
return "", err
return sql.AccessToken{}, err
} else {
if b, err := cryptutil.VerifyPassword(password, user.PasswordHash); err != nil {
logrus.Info(err.Error())
return "", err
return sql.AccessToken{}, err
} else if !b {
return "", ErrInvalidUsernamePassword
return sql.AccessToken{}, ErrInvalidUsernamePassword
}
}
accessToken := GenerateRandomString(accessTokenLength)
if err := a.Db.Queries().InsertAccessToken(context.Background(), sql.InsertAccessTokenParams{
ID: accessToken,
if token, err := a.Db.Queries().InsertAccessToken(context.Background(), sql.InsertAccessTokenParams{
ID: GenerateRandomString(accessTokenLength),
Validity: accessTokenValiditiy,
Username: username,
}); err != nil {
return "", err
return sql.AccessToken{}, err
} else {
return token, nil
}
return accessToken, nil
}
func (a App) VerifyAccessToken(accessToken string) (string, error) {

View File

@@ -8,10 +8,6 @@ import (
"github.com/shroff/phylum/server/internal/storage"
)
type storageManager struct {
db *db.DbHandler
}
func restoreStorageBackends(db *db.DbHandler) (map[string]storage.Storage, error) {
backends, err := db.Queries().AllStorageBackends(context.Background())
if err != nil {

View File

@@ -7,6 +7,7 @@ import (
"github.com/fvbock/endless"
"github.com/gin-contrib/cors"
"github.com/gin-gonic/gin"
"github.com/shroff/phylum/server/internal/api"
"github.com/shroff/phylum/server/internal/app"
webdav "github.com/shroff/phylum/server/internal/handler_webdav"
"github.com/sirupsen/logrus"
@@ -24,6 +25,8 @@ func setupServeCommand() *cobra.Command {
webdav.SetupHandler(engine.Group(config.GetString("webdav_prefix")), app.Default)
api.Setup(engine.Group("/api/v1"))
server := endless.NewServer(config.GetString("listen"), engine)
server.BeforeBegin = func(addr string) {
logrus.Info("Listening on " + addr)

View File

@@ -108,11 +108,12 @@ func setupUserLoginCommand() *cobra.Command {
}
password := string(bytes)
accessToken, err := app.Default.CreateAccessToken(username, password, "cmd")
accessToken, err := app.Default.CreateAccessToken(username, password)
if err != nil {
logrus.Fatal(err)
}
logrus.Info("Access Token: " + accessToken)
logrus.Info("Access Token: " + accessToken.ID)
logrus.Info(" Valid Until: " + accessToken.Expires.Time.String())
},
}
}

View File

@@ -27,12 +27,12 @@ func (q *Queries) AccessTokenById(ctx context.Context, id string) (AccessToken,
return i, err
}
const insertAccessToken = `-- name: InsertAccessToken :exec
const insertAccessToken = `-- name: InsertAccessToken :one
INSERT INTO access_tokens(
id, created, expires, username
) VALUES(
$1::text, NOW(), NOW() + $2::interval, $3::text
)
) RETURNING id, created, expires, username
`
type InsertAccessTokenParams struct {
@@ -41,7 +41,14 @@ type InsertAccessTokenParams struct {
Username string
}
func (q *Queries) InsertAccessToken(ctx context.Context, arg InsertAccessTokenParams) error {
_, err := q.db.Exec(ctx, insertAccessToken, arg.ID, arg.Validity, arg.Username)
return err
func (q *Queries) InsertAccessToken(ctx context.Context, arg InsertAccessTokenParams) (AccessToken, error) {
row := q.db.QueryRow(ctx, insertAccessToken, arg.ID, arg.Validity, arg.Username)
var i AccessToken
err := row.Scan(
&i.ID,
&i.Created,
&i.Expires,
&i.Username,
)
return i, err
}

View File

@@ -1,9 +1,9 @@
-- name: AccessTokenById :one
SELECT * from access_tokens where id = $1;
-- name: InsertAccessToken :exec
-- name: InsertAccessToken :one
INSERT INTO access_tokens(
id, created, expires, username
) VALUES(
@id::text, NOW(), NOW() + @validity::interval, @username::text
);
) RETURNING *;