"Fossies" - the Fresh Open Source Software Archive

Member "gogs-0.12.3/internal/db/access_tokens.go" (7 Oct 2020, 4446 Bytes) of package /linux/misc/gogs-0.12.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Go source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Copyright 2020 The Gogs Authors. All rights reserved.
    2 // Use of this source code is governed by a MIT-style
    3 // license that can be found in the LICENSE file.
    4 
    5 package db
    6 
    7 import (
    8     "fmt"
    9     "time"
   10 
   11     "github.com/jinzhu/gorm"
   12     gouuid "github.com/satori/go.uuid"
   13 
   14     "gogs.io/gogs/internal/cryptoutil"
   15     "gogs.io/gogs/internal/errutil"
   16 )
   17 
   18 // AccessTokensStore is the persistent interface for access tokens.
   19 //
   20 // NOTE: All methods are sorted in alphabetical order.
   21 type AccessTokensStore interface {
   22     // Create creates a new access token and persist to database.
   23     // It returns ErrAccessTokenAlreadyExist when an access token
   24     // with same name already exists for the user.
   25     Create(userID int64, name string) (*AccessToken, error)
   26     // DeleteByID deletes the access token by given ID.
   27     // 🚨 SECURITY: The "userID" is required to prevent attacker
   28     // deletes arbitrary access token that belongs to another user.
   29     DeleteByID(userID, id int64) error
   30     // GetBySHA returns the access token with given SHA1.
   31     // It returns ErrAccessTokenNotExist when not found.
   32     GetBySHA(sha string) (*AccessToken, error)
   33     // List returns all access tokens belongs to given user.
   34     List(userID int64) ([]*AccessToken, error)
   35     // Save persists all values of given access token.
   36     // The Updated field is set to current time automatically.
   37     Save(t *AccessToken) error
   38 }
   39 
   40 var AccessTokens AccessTokensStore
   41 
   42 // AccessToken is a personal access token.
   43 type AccessToken struct {
   44     ID     int64
   45     UserID int64 `xorm:"uid INDEX" gorm:"COLUMN:uid;INDEX"`
   46     Name   string
   47     Sha1   string `xorm:"UNIQUE VARCHAR(40)" gorm:"TYPE:VARCHAR(40);UNIQUE"`
   48 
   49     Created           time.Time `xorm:"-" gorm:"-" json:"-"`
   50     CreatedUnix       int64
   51     Updated           time.Time `xorm:"-" gorm:"-" json:"-"`
   52     UpdatedUnix       int64
   53     HasRecentActivity bool `xorm:"-" gorm:"-" json:"-"`
   54     HasUsed           bool `xorm:"-" gorm:"-" json:"-"`
   55 }
   56 
   57 // NOTE: This is a GORM create hook.
   58 func (t *AccessToken) BeforeCreate() {
   59     if t.CreatedUnix > 0 {
   60         return
   61     }
   62     t.CreatedUnix = gorm.NowFunc().Unix()
   63 }
   64 
   65 // NOTE: This is a GORM update hook.
   66 func (t *AccessToken) BeforeUpdate() {
   67     t.UpdatedUnix = gorm.NowFunc().Unix()
   68 }
   69 
   70 // NOTE: This is a GORM query hook.
   71 func (t *AccessToken) AfterFind() {
   72     t.Created = time.Unix(t.CreatedUnix, 0).Local()
   73     t.Updated = time.Unix(t.UpdatedUnix, 0).Local()
   74     t.HasUsed = t.Updated.After(t.Created)
   75     t.HasRecentActivity = t.Updated.Add(7 * 24 * time.Hour).After(gorm.NowFunc())
   76 }
   77 
   78 var _ AccessTokensStore = (*accessTokens)(nil)
   79 
   80 type accessTokens struct {
   81     *gorm.DB
   82 }
   83 
   84 type ErrAccessTokenAlreadyExist struct {
   85     args errutil.Args
   86 }
   87 
   88 func IsErrAccessTokenAlreadyExist(err error) bool {
   89     _, ok := err.(ErrAccessTokenAlreadyExist)
   90     return ok
   91 }
   92 
   93 func (err ErrAccessTokenAlreadyExist) Error() string {
   94     return fmt.Sprintf("access token already exists: %v", err.args)
   95 }
   96 
   97 func (db *accessTokens) Create(userID int64, name string) (*AccessToken, error) {
   98     err := db.Where("uid = ? AND name = ?", userID, name).First(new(AccessToken)).Error
   99     if err == nil {
  100         return nil, ErrAccessTokenAlreadyExist{args: errutil.Args{"userID": userID, "name": name}}
  101     } else if !gorm.IsRecordNotFoundError(err) {
  102         return nil, err
  103     }
  104 
  105     token := &AccessToken{
  106         UserID: userID,
  107         Name:   name,
  108         Sha1:   cryptoutil.SHA1(gouuid.NewV4().String()),
  109     }
  110     return token, db.DB.Create(token).Error
  111 }
  112 
  113 func (db *accessTokens) DeleteByID(userID, id int64) error {
  114     return db.Where("id = ? AND uid = ?", id, userID).Delete(new(AccessToken)).Error
  115 }
  116 
  117 var _ errutil.NotFound = (*ErrAccessTokenNotExist)(nil)
  118 
  119 type ErrAccessTokenNotExist struct {
  120     args errutil.Args
  121 }
  122 
  123 func IsErrAccessTokenNotExist(err error) bool {
  124     _, ok := err.(ErrAccessTokenNotExist)
  125     return ok
  126 }
  127 
  128 func (err ErrAccessTokenNotExist) Error() string {
  129     return fmt.Sprintf("access token does not exist: %v", err.args)
  130 }
  131 
  132 func (ErrAccessTokenNotExist) NotFound() bool {
  133     return true
  134 }
  135 
  136 func (db *accessTokens) GetBySHA(sha string) (*AccessToken, error) {
  137     token := new(AccessToken)
  138     err := db.Where("sha1 = ?", sha).First(token).Error
  139     if err != nil {
  140         if gorm.IsRecordNotFoundError(err) {
  141             return nil, ErrAccessTokenNotExist{args: errutil.Args{"sha": sha}}
  142         }
  143         return nil, err
  144     }
  145     return token, nil
  146 }
  147 
  148 func (db *accessTokens) List(userID int64) ([]*AccessToken, error) {
  149     var tokens []*AccessToken
  150     return tokens, db.Where("uid = ?", userID).Find(&tokens).Error
  151 }
  152 
  153 func (db *accessTokens) Save(t *AccessToken) error {
  154     return db.DB.Save(t).Error
  155 }