code.gitea.io/gitea@v1.21.7/models/asymkey/ssh_key_principals.go (about) 1 // Copyright 2021 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package asymkey 5 6 import ( 7 "context" 8 "fmt" 9 "strings" 10 11 "code.gitea.io/gitea/models/db" 12 "code.gitea.io/gitea/models/perm" 13 user_model "code.gitea.io/gitea/models/user" 14 "code.gitea.io/gitea/modules/setting" 15 "code.gitea.io/gitea/modules/util" 16 ) 17 18 // __________ .__ .__ .__ 19 // \______ _______|__| ____ ____ |_____________ | | ______ 20 // | ___\_ __ | |/ \_/ ___\| \____ \__ \ | | / ___/ 21 // | | | | \| | | \ \___| | |_> / __ \| |__\___ \ 22 // |____| |__| |__|___| /\___ |__| __(____ |____/____ > 23 // \/ \/ |__| \/ \/ 24 // 25 // This file contains functions related to principals 26 27 // AddPrincipalKey adds new principal to database and authorized_principals file. 28 func AddPrincipalKey(ownerID int64, content string, authSourceID int64) (*PublicKey, error) { 29 ctx, committer, err := db.TxContext(db.DefaultContext) 30 if err != nil { 31 return nil, err 32 } 33 defer committer.Close() 34 35 // Principals cannot be duplicated. 36 has, err := db.GetEngine(ctx). 37 Where("content = ? AND type = ?", content, KeyTypePrincipal). 38 Get(new(PublicKey)) 39 if err != nil { 40 return nil, err 41 } else if has { 42 return nil, ErrKeyAlreadyExist{0, "", content} 43 } 44 45 key := &PublicKey{ 46 OwnerID: ownerID, 47 Name: content, 48 Content: content, 49 Mode: perm.AccessModeWrite, 50 Type: KeyTypePrincipal, 51 LoginSourceID: authSourceID, 52 } 53 if err = db.Insert(ctx, key); err != nil { 54 return nil, fmt.Errorf("addKey: %w", err) 55 } 56 57 if err = committer.Commit(); err != nil { 58 return nil, err 59 } 60 61 committer.Close() 62 63 return key, RewriteAllPrincipalKeys(db.DefaultContext) 64 } 65 66 // CheckPrincipalKeyString strips spaces and returns an error if the given principal contains newlines 67 func CheckPrincipalKeyString(ctx context.Context, user *user_model.User, content string) (_ string, err error) { 68 if setting.SSH.Disabled { 69 return "", db.ErrSSHDisabled{} 70 } 71 72 content = strings.TrimSpace(content) 73 if strings.ContainsAny(content, "\r\n") { 74 return "", util.NewInvalidArgumentErrorf("only a single line with a single principal please") 75 } 76 77 // check all the allowed principals, email, username or anything 78 // if any matches, return ok 79 for _, v := range setting.SSH.AuthorizedPrincipalsAllow { 80 switch v { 81 case "anything": 82 return content, nil 83 case "email": 84 emails, err := user_model.GetEmailAddresses(ctx, user.ID) 85 if err != nil { 86 return "", err 87 } 88 for _, email := range emails { 89 if !email.IsActivated { 90 continue 91 } 92 if content == email.Email { 93 return content, nil 94 } 95 } 96 97 case "username": 98 if content == user.Name { 99 return content, nil 100 } 101 } 102 } 103 104 return "", fmt.Errorf("didn't match allowed principals: %s", setting.SSH.AuthorizedPrincipalsAllow) 105 } 106 107 // ListPrincipalKeys returns a list of principals belongs to given user. 108 func ListPrincipalKeys(uid int64, listOptions db.ListOptions) ([]*PublicKey, error) { 109 sess := db.GetEngine(db.DefaultContext).Where("owner_id = ? AND type = ?", uid, KeyTypePrincipal) 110 if listOptions.Page != 0 { 111 sess = db.SetSessionPagination(sess, &listOptions) 112 113 keys := make([]*PublicKey, 0, listOptions.PageSize) 114 return keys, sess.Find(&keys) 115 } 116 117 keys := make([]*PublicKey, 0, 5) 118 return keys, sess.Find(&keys) 119 }