M grants.go => grants.go +10 -6
@@ 19,8 19,10 @@ func GetGrants(ctx context.Context, opts *database.FilterOptions) ([]*Grant, err
if err := database.WithTx(ctx, database.TxOptionsRO, func(tx *sql.Tx) error {
q := opts.GetBuilder(nil)
rows, err := q.
- Columns("id", "issued", "expires", "comment", "token_hash", "user_id", "client_id").
- From("oauth2_grants").
+ Columns("g.id", "g.issued", "g.expires", "g.comment", "g.grants", "g.token_hash",
+ "g.user_id", "g.client_id", "c.name").
+ From("oauth2_grants g").
+ LeftJoin("oauth2_clients c ON c.id = g.client_id").
PlaceholderFormat(sq.Dollar).
RunWith(tx).
QueryContext(ctx)
@@ 34,8 36,8 @@ func GetGrants(ctx context.Context, opts *database.FilterOptions) ([]*Grant, err
for rows.Next() {
var g Grant
- if err = rows.Scan(&g.ID, &g.Issued, &g.Expires, &g.Comment, &g.TokenHash,
- &g.UserID, &g.ClientID); err != nil {
+ if err = rows.Scan(&g.ID, &g.Issued, &g.Expires, &g.Comment, &g.Grants, &g.TokenHash,
+ &g.UserID, &g.ClientID, &g.ClientName); err != nil {
return err
}
grants = append(grants, &g)
@@ 54,8 56,9 @@ func (g *Grant) Store(ctx context.Context) error {
if g.ID == 0 {
err = sq.
Insert("oauth2_grants").
- Columns("issued", "expires", "comment", "token_hash", "user_id", "client_id").
- Values(g.Issued, g.Expires, g.Comment, g.TokenHash, g.UserID, g.ClientID).
+ Columns("issued", "expires", "comment", "grants", "token_hash", "user_id",
+ "client_id").
+ Values(g.Issued, g.Expires, g.Comment, g.Grants, g.TokenHash, g.UserID, g.ClientID).
Suffix(`RETURNING (id)`).
PlaceholderFormat(sq.Dollar).
RunWith(tx).
@@ 66,6 69,7 @@ func (g *Grant) Store(ctx context.Context) error {
Set("issued", g.Issued).
Set("expires", g.Expires).
Set("comment", g.Comment).
+ Set("grants", g.Grants).
Set("token_hash", g.TokenHash).
Set("user_id", g.UserID).
Set("client_id", g.ClientID).
M models.go => models.go +3 -0
@@ 27,9 27,12 @@ type Grant struct {
Issued time.Time `db:"issued"`
Expires time.Time `db:"expires"`
Comment string `db:"comment"`
+ Grants string `db:"grants"`
TokenHash string `db:"token_hash"`
UserID int `db:"user_id"`
ClientID sql.NullInt64 `db:"client_id"`
+
+ ClientName sql.NullString `db:"-"`
}
// Authorization ...
M routes.go => routes.go +17 -9
@@ 59,20 59,28 @@ func (s *Service) RegisterRoutes() {
// ListPersonal ...
func (s *Service) ListPersonal(c echo.Context) error {
+ var tokens, clients []*Grant
gctx := c.(*server.Context)
opts := &database.FilterOptions{
Filter: sq.And{
- sq.Eq{"user_id": gctx.User.GetID()},
- sq.Expr("client_id IS NULL"),
- sq.Expr("expires > NOW() at time zone 'UTC'"),
+ sq.Eq{"g.user_id": gctx.User.GetID()},
+ sq.Expr("g.expires > NOW() at time zone 'UTC'"),
},
}
- tokens, err := GetGrants(c.Request().Context(), opts)
+ grants, err := GetGrants(c.Request().Context(), opts)
if err != nil {
return err
}
+ for _, grant := range grants {
+ if !grant.ClientID.Valid {
+ tokens = append(tokens, grant)
+ } else {
+ clients = append(clients, grant)
+ }
+ }
return gctx.Render(http.StatusOK, "oauth2_personal_list.html", gobwebs.Map{
- "tokens": tokens,
+ "tokens": tokens,
+ "clients": clients,
})
}
@@ 134,10 142,9 @@ func (s *Service) RevokePersonal(c echo.Context) error {
gctx := c.(*server.Context)
opts := &database.FilterOptions{
Filter: sq.And{
- sq.Eq{"id": id},
- sq.Eq{"user_id": gctx.User.GetID()},
- sq.Expr("client_id IS NULL"),
- sq.Expr("expires > NOW() at time zone 'UTC'"),
+ sq.Eq{"g.id": id},
+ sq.Eq{"g.user_id": gctx.User.GetID()},
+ sq.Expr("g.expires > NOW() at time zone 'UTC'"),
},
}
tokens, err := GetGrants(c.Request().Context(), opts)
@@ 593,6 600,7 @@ func (s *Service) AccessTokenPOST(c echo.Context) error {
grant := &Grant{
Issued: issued,
Expires: expires,
+ Grants: payload.Grants,
TokenHash: tokenHash,
UserID: payload.UserID,
ClientID: sql.NullInt64{Int64: int64(client.ID), Valid: true},
M schema.sql => schema.sql +1 -0
@@ 37,6 37,7 @@ CREATE TABLE oauth2_grants (
issued TIMESTAMPTZ NOT NULL,
expires TIMESTAMPTZ NOT NULL,
comment character varying,
+ grants character varying,
token_hash character varying(128) NOT NULL,
user_id integer NOT NULL REFERENCES users (id) ON DELETE CASCADE,
client_id integer REFERENCES oauth2_clients (id) ON DELETE CASCADE