im.go 30.1 KB
Newer Older
H
hongming 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*

 Copyright 2019 The KubeSphere Authors.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.

*/
package iam

import (
H
hongming 已提交
21
	"encoding/json"
H
hongming 已提交
22 23
	"errors"
	"fmt"
R
runzexia 已提交
24
	"github.com/emicklei/go-restful"
H
hongming 已提交
25
	"io/ioutil"
H
hongming 已提交
26
	"kubesphere.io/kubesphere/pkg/constants"
R
runzexia 已提交
27
	"kubesphere.io/kubesphere/pkg/db"
H
hongming 已提交
28
	"kubesphere.io/kubesphere/pkg/informers"
R
runzexia 已提交
29
	"kubesphere.io/kubesphere/pkg/models/devops"
H
hongming 已提交
30 31
	"kubesphere.io/kubesphere/pkg/models/kubeconfig"
	"kubesphere.io/kubesphere/pkg/models/kubectl"
H
hongming 已提交
32
	"kubesphere.io/kubesphere/pkg/params"
R
runzexia 已提交
33 34
	"kubesphere.io/kubesphere/pkg/simple/client/admin_jenkins"
	"kubesphere.io/kubesphere/pkg/simple/client/devops_mysql"
H
hongming 已提交
35 36
	"kubesphere.io/kubesphere/pkg/simple/client/k8s"
	"kubesphere.io/kubesphere/pkg/simple/client/redis"
H
hongming 已提交
37
	"kubesphere.io/kubesphere/pkg/utils/k8sutil"
H
hongming 已提交
38
	"kubesphere.io/kubesphere/pkg/utils/sliceutil"
R
runzexia 已提交
39
	"net/http"
H
hongming 已提交
40
	"regexp"
H
hongming 已提交
41
	"sort"
H
hongming 已提交
42 43 44 45 46 47 48 49 50 51
	"strconv"
	"strings"
	"time"

	"github.com/dgrijalva/jwt-go"
	"github.com/go-ldap/ldap"
	"github.com/golang/glog"
	"k8s.io/api/rbac/v1"
	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/labels"
H
hongming 已提交
52
	ldapclient "kubesphere.io/kubesphere/pkg/simple/client/ldap"
H
hongming 已提交
53 54

	"kubesphere.io/kubesphere/pkg/models"
H
hongming 已提交
55
	"kubesphere.io/kubesphere/pkg/utils/jwtutil"
H
hongming 已提交
56 57 58
)

var (
Z
zryfish 已提交
59 60 61
	adminEmail      string
	adminPassword   string
	tokenExpireTime time.Duration
H
hongming 已提交
62
	initUsers       []initUser
H
hongming 已提交
63 64
)

H
hongming 已提交
65 66 67 68 69
type initUser struct {
	models.User
	Hidden bool `json:"hidden"`
}

H
hongming 已提交
70
const (
H
hongming 已提交
71
	userInitFile = "/etc/ks-iam/users.json"
H
hongming 已提交
72 73
)

Z
zryfish 已提交
74 75 76 77
func Init(email, password string, t time.Duration) error {
	adminEmail = email
	adminPassword = password
	tokenExpireTime = t
H
hongming 已提交
78

H
hongming 已提交
79
	conn, err := ldapclient.Client()
H
hongming 已提交
80 81 82 83 84 85 86

	if err != nil {
		return err
	}

	defer conn.Close()

H
hongming 已提交
87 88
	err = checkAndCreateDefaultUser(conn)

H
hongming 已提交
89
	if err != nil {
H
hongming 已提交
90
		glog.Errorln("create default users", err)
H
hongming 已提交
91 92 93
		return err
	}

H
hongming 已提交
94 95
	err = checkAndCreateDefaultGroup(conn)

H
hongming 已提交
96 97 98 99 100 101
	if err != nil {
		glog.Errorln("create default groups", err)
		return err
	}

	return nil
H
hongming 已提交
102 103 104 105 106 107
}

func checkAndCreateDefaultGroup(conn ldap.Client) error {

	groupSearchRequest := ldap.NewSearchRequest(
		ldapclient.GroupSearchBase,
H
hongming 已提交
108
		ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
H
hongming 已提交
109
		"(&(objectClass=posixGroup))",
H
hongming 已提交
110 111 112 113
		nil,
		nil,
	)

H
hongming 已提交
114
	_, err := conn.Search(groupSearchRequest)
H
hongming 已提交
115

H
hongming 已提交
116 117
	if ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) {
		err = createGroupsBaseDN(conn)
Z
zryfish 已提交
118 119 120
		if err != nil {
			return fmt.Errorf("GroupBaseDN %s create failed: %s\n", ldapclient.GroupSearchBase, err)
		}
H
hongming 已提交
121 122
	}

H
hongming 已提交
123
	if err != nil {
Z
zryfish 已提交
124
		return fmt.Errorf("iam database init failed: %s\n", err)
H
hongming 已提交
125
	}
H
hongming 已提交
126

H
hongming 已提交
127 128 129 130 131 132 133
	return nil
}

func checkAndCreateDefaultUser(conn ldap.Client) error {

	userSearchRequest := ldap.NewSearchRequest(
		ldapclient.UserSearchBase,
H
hongming 已提交
134
		ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
H
hongming 已提交
135
		"(&(objectClass=inetOrgPerson))",
H
hongming 已提交
136
		[]string{"uid"},
H
hongming 已提交
137 138 139
		nil,
	)

H
hongming 已提交
140
	result, err := conn.Search(userSearchRequest)
H
hongming 已提交
141

H
hongming 已提交
142 143
	if ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) {
		err = createUserBaseDN(conn)
Z
zryfish 已提交
144 145 146
		if err != nil {
			return fmt.Errorf("UserBaseDN %s create failed: %s\n", ldapclient.UserSearchBase, err)
		}
H
hongming 已提交
147 148
	}

H
hongming 已提交
149
	if err != nil {
Z
zryfish 已提交
150
		return fmt.Errorf("iam database init failed: %s\n", err)
H
hongming 已提交
151
	}
H
hongming 已提交
152

H
hongming 已提交
153 154 155 156
	data, err := ioutil.ReadFile(userInitFile)
	if err == nil {
		json.Unmarshal(data, &initUsers)
	}
H
hongming 已提交
157
	initUsers = append(initUsers, initUser{User: models.User{Username: constants.AdminUserName, Email: adminEmail, Password: adminPassword, Description: "Administrator account that was always created by default.", ClusterRole: constants.ClusterAdmin}})
H
hongming 已提交
158

H
hongming 已提交
159 160 161
	for _, user := range initUsers {
		if result == nil || !containsUser(result.Entries, user) {
			_, err = CreateUser(&user.User)
H
hongming 已提交
162
			if err != nil && !ldap.IsErrorWithCode(err, ldap.LDAPResultEntryAlreadyExists) {
H
hongming 已提交
163
				glog.Errorln("user init failed", user.Username, err)
H
hongming 已提交
164 165
				return fmt.Errorf("user %s init failed: %s\n", user.Username, err)
			}
H
hongming 已提交
166 167 168 169 170 171
		}
	}

	return nil
}

H
hongming 已提交
172 173 174 175 176 177 178 179 180 181
func containsUser(entries []*ldap.Entry, user initUser) bool {
	for _, entry := range entries {
		uid := entry.GetAttributeValue("uid")
		if uid == user.Username {
			return true
		}
	}
	return false
}

H
hongming 已提交
182
func createUserBaseDN(conn ldap.Client) error {
H
hongming 已提交
183

H
hongming 已提交
184
	conn, err := ldapclient.Client()
H
hongming 已提交
185 186 187 188 189
	if err != nil {
		return err
	}
	defer conn.Close()

H
hongming 已提交
190
	groupsCreateRequest := ldap.NewAddRequest(ldapclient.UserSearchBase, nil)
H
hongming 已提交
191 192 193 194 195
	groupsCreateRequest.Attribute("objectClass", []string{"organizationalUnit", "top"})
	groupsCreateRequest.Attribute("ou", []string{"Users"})
	return conn.Add(groupsCreateRequest)
}

H
hongming 已提交
196 197
func createGroupsBaseDN(conn ldap.Client) error {
	groupsCreateRequest := ldap.NewAddRequest(ldapclient.GroupSearchBase, nil)
H
hongming 已提交
198 199 200 201 202 203
	groupsCreateRequest.Attribute("objectClass", []string{"organizationalUnit", "top"})
	groupsCreateRequest.Attribute("ou", []string{"Groups"})
	return conn.Add(groupsCreateRequest)
}

// User login
H
hongming 已提交
204
func Login(username string, password string, ip string) (*models.Token, error) {
H
hongming 已提交
205

H
hongming 已提交
206
	conn, err := ldapclient.Client()
H
hongming 已提交
207 208

	if err != nil {
H
hongming 已提交
209
		return nil, err
H
hongming 已提交
210 211 212 213 214
	}

	defer conn.Close()

	userSearchRequest := ldap.NewSearchRequest(
H
hongming 已提交
215
		ldapclient.UserSearchBase,
H
hongming 已提交
216 217 218 219 220 221 222 223 224
		ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
		fmt.Sprintf("(&(objectClass=inetOrgPerson)(|(uid=%s)(mail=%s)))", username, username),
		[]string{"uid", "mail"},
		nil,
	)

	result, err := conn.Search(userSearchRequest)

	if err != nil {
H
hongming 已提交
225
		return nil, err
H
hongming 已提交
226 227 228
	}

	if len(result.Entries) != 1 {
H
hongming 已提交
229
		return nil, ldap.NewError(ldap.LDAPResultInvalidCredentials, errors.New("incorrect password"))
H
hongming 已提交
230 231 232 233 234 235 236 237 238 239
	}

	uid := result.Entries[0].GetAttributeValue("uid")
	email := result.Entries[0].GetAttributeValue("mail")
	dn := result.Entries[0].DN

	// bind as the user to verify their password
	err = conn.Bind(dn, password)

	if err != nil {
H
hongming 已提交
240
		glog.Errorln("auth error", username, err)
H
hongming 已提交
241
		return nil, err
H
hongming 已提交
242 243 244 245
	}

	claims := jwt.MapClaims{}

Z
zryfish 已提交
246 247 248
	claims["exp"] = time.Now().Add(tokenExpireTime).Unix()
	claims["username"] = uid
	claims["email"] = email
H
hongming 已提交
249

H
hongming 已提交
250
	token := jwtutil.MustSigned(claims)
H
hongming 已提交
251

Z
zryfish 已提交
252 253
	loginLog(uid, ip)

H
hongming 已提交
254
	return &models.Token{Token: token}, nil
H
hongming 已提交
255 256
}

Z
zryfish 已提交
257 258 259 260 261 262 263 264
func loginLog(uid, ip string) {
	if ip != "" {
		redisClient := redis.Client()
		redisClient.RPush(fmt.Sprintf("kubesphere:users:%s:login-log", uid), fmt.Sprintf("%s,%s", time.Now().UTC().Format("2006-01-02T15:04:05Z"), ip))
		redisClient.LTrim(fmt.Sprintf("kubesphere:users:%s:login-log", uid), -10, -1)
	}
}

H
hongming 已提交
265 266 267 268 269 270 271 272 273 274 275 276 277
func LoginLog(username string) ([]string, error) {
	redisClient := redis.Client()

	data, err := redisClient.LRange(fmt.Sprintf("kubesphere:users:%s:login-log", username), -10, -1).Result()

	if err != nil {
		return nil, err
	}

	return data, nil
}

func ListUsers(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
H
hongming 已提交
278

H
hongming 已提交
279
	conn, err := ldapclient.Client()
H
hongming 已提交
280 281

	if err != nil {
H
hongming 已提交
282
		return nil, err
H
hongming 已提交
283 284 285 286
	}

	defer conn.Close()

H
hongming 已提交
287
	pageControl := ldap.NewControlPaging(1000)
H
hongming 已提交
288

H
hongming 已提交
289 290
	users := make([]models.User, 0)

H
hongming 已提交
291
	filter := "(&(objectClass=inetOrgPerson))"
H
hongming 已提交
292

H
hongming 已提交
293 294 295
	if keyword := conditions.Match["keyword"]; keyword != "" {
		filter = fmt.Sprintf("(&(objectClass=inetOrgPerson)(|(uid=*%s*)(mail=*%s*)(description=*%s*)))", keyword, keyword, keyword)
	}
H
hongming 已提交
296

H
hongming 已提交
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
	if username := conditions.Match["username"]; username != "" {
		uidFilter := ""
		for _, username := range strings.Split(username, "|") {
			uidFilter += fmt.Sprintf("(uid=%s)", username)
		}
		filter = fmt.Sprintf("(&(objectClass=inetOrgPerson)(|%s))", uidFilter)
	}

	if email := conditions.Match["email"]; email != "" {
		emailFilter := ""
		for _, username := range strings.Split(email, "|") {
			emailFilter += fmt.Sprintf("(mail=%s)", username)
		}
		filter = fmt.Sprintf("(&(objectClass=inetOrgPerson)(|%s))", emailFilter)
	}

H
hongming 已提交
313 314
	for {
		userSearchRequest := ldap.NewSearchRequest(
H
hongming 已提交
315
			ldapclient.UserSearchBase,
H
hongming 已提交
316
			ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
H
hongming 已提交
317 318
			filter,
			[]string{"uid", "mail", "description", "preferredLanguage", "createTimestamp"},
H
hongming 已提交
319 320 321 322 323 324
			[]ldap.Control{pageControl},
		)

		response, err := conn.Search(userSearchRequest)

		if err != nil {
H
hongming 已提交
325
			glog.Errorln("search user", err)
H
hongming 已提交
326
			return nil, err
H
hongming 已提交
327 328 329
		}

		for _, entry := range response.Entries {
H
hongming 已提交
330 331 332 333 334 335 336 337 338

			uid := entry.GetAttributeValue("uid")
			email := entry.GetAttributeValue("mail")
			description := entry.GetAttributeValue("description")
			lang := entry.GetAttributeValue("preferredLanguage")
			createTimestamp, _ := time.Parse("20060102150405Z", entry.GetAttributeValue("createTimestamp"))

			user := models.User{Username: uid, Email: email, Description: description, Lang: lang, CreateTime: createTimestamp}

H
hongming 已提交
339 340 341
			if !shouldHidden(user) {
				users = append(users, user)
			}
H
hongming 已提交
342 343 344 345 346 347 348 349 350 351 352
		}

		updatedControl := ldap.FindControl(response.Controls, ldap.ControlTypePaging)
		if ctrl, ok := updatedControl.(*ldap.ControlPaging); ctrl != nil && ok && len(ctrl.Cookie) != 0 {
			pageControl.SetCookie(ctrl.Cookie)
			continue
		}

		break
	}

H
hongming 已提交
353 354 355 356 357 358 359 360
	sort.Slice(users, func(i, j int) bool {
		if reverse {
			tmp := i
			i = j
			j = tmp
		}
		switch orderBy {
		case "username":
H
hongming 已提交
361
			return strings.Compare(users[i].Username, users[j].Username) <= 0
H
hongming 已提交
362
		case "createTime":
H
hongming 已提交
363
			fallthrough
H
hongming 已提交
364
		default:
H
hongming 已提交
365
			return users[i].CreateTime.Before(users[j].CreateTime)
H
hongming 已提交
366 367
		}
	})
H
hongming 已提交
368

H
hongming 已提交
369
	items := make([]interface{}, 0)
H
hongming 已提交
370

H
hongming 已提交
371
	for i, user := range users {
H
hongming 已提交
372

H
hongming 已提交
373
		if i >= offset && len(items) < limit {
H
hongming 已提交
374

H
hongming 已提交
375 376
			user.AvatarUrl = getAvatar(user.Username)
			user.LastLoginTime = getLastLoginTime(user.Username)
H
hongming 已提交
377 378 379 380 381 382 383
			clusterRole, err := GetUserClusterRole(user.Username)
			if err != nil {
				return nil, err
			}
			user.ClusterRole = clusterRole.Name
			items = append(items, user)
		}
H
hongming 已提交
384 385
	}

H
hongming 已提交
386
	return &models.PageableResponse{Items: items, TotalCount: len(users)}, nil
H
hongming 已提交
387 388
}

H
hongming 已提交
389 390 391 392 393 394 395 396 397
func shouldHidden(user models.User) bool {
	for _, initUser := range initUsers {
		if initUser.Username == user.Username {
			return initUser.Hidden
		}
	}
	return false
}

H
hongming 已提交
398
func DescribeUser(username string) (*models.User, error) {
H
hongming 已提交
399

H
hongming 已提交
400
	user, err := GetUserInfo(username)
H
hongming 已提交
401 402 403 404 405

	if err != nil {
		return nil, err
	}

H
hongming 已提交
406
	groups, err := GetUserGroups(username)
H
hongming 已提交
407

H
hongming 已提交
408 409
	if err == nil {
		user.Groups = groups
H
hongming 已提交
410 411
	}

H
hongming 已提交
412
	user.AvatarUrl = getAvatar(username)
H
hongming 已提交
413

H
hongming 已提交
414 415 416
	return user, nil
}

H
hongming 已提交
417 418
// Get user info only included email description & lang
func GetUserInfo(username string) (*models.User, error) {
H
hongming 已提交
419

H
hongming 已提交
420
	conn, err := ldapclient.Client()
H
hongming 已提交
421

H
hongming 已提交
422 423
	if err != nil {
		return nil, err
H
hongming 已提交
424 425 426
	}

	userSearchRequest := ldap.NewSearchRequest(
H
hongming 已提交
427
		ldapclient.UserSearchBase,
H
hongming 已提交
428 429
		ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
		fmt.Sprintf("(&(objectClass=inetOrgPerson)(uid=%s))", username),
H
hongming 已提交
430
		[]string{"mail", "description", "preferredLanguage", "createTimestamp"},
H
hongming 已提交
431 432 433 434 435 436
		nil,
	)

	result, err := conn.Search(userSearchRequest)

	if err != nil {
H
hongming 已提交
437
		glog.Errorln("search user", err)
H
hongming 已提交
438 439 440 441 442 443 444 445 446 447
		return nil, err
	}

	if len(result.Entries) != 1 {
		return nil, ldap.NewError(ldap.LDAPResultNoSuchObject, fmt.Errorf("user %s does not exist", username))
	}

	email := result.Entries[0].GetAttributeValue("mail")
	description := result.Entries[0].GetAttributeValue("description")
	lang := result.Entries[0].GetAttributeValue("preferredLanguage")
H
hongming 已提交
448 449 450
	createTimestamp, _ := time.Parse("20060102150405Z", result.Entries[0].GetAttributeValue("createTimestamp"))
	user := &models.User{Username: username, Email: email, Description: description, Lang: lang, CreateTime: createTimestamp}

H
hongming 已提交
451 452
	user.LastLoginTime = getLastLoginTime(username)

H
hongming 已提交
453 454 455 456 457 458 459 460 461 462 463
	return user, nil
}

func GetUserGroups(username string) ([]string, error) {
	conn, err := ldapclient.Client()

	if err != nil {
		return nil, err
	}

	defer conn.Close()
H
hongming 已提交
464 465

	groupSearchRequest := ldap.NewSearchRequest(
H
hongming 已提交
466
		ldapclient.GroupSearchBase,
H
hongming 已提交
467 468 469 470 471 472
		ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
		fmt.Sprintf("(&(objectClass=posixGroup)(memberUid=%s))", username),
		nil,
		nil,
	)

H
hongming 已提交
473
	result, err := conn.Search(groupSearchRequest)
H
hongming 已提交
474 475 476 477 478 479 480 481 482 483 484 485

	if err != nil {
		return nil, err
	}

	groups := make([]string, 0)

	for _, group := range result.Entries {
		groupName := convertDNToPath(group.DN)
		groups = append(groups, groupName)
	}

H
hongming 已提交
486 487
	return groups, nil
}
H
hongming 已提交
488

H
hongming 已提交
489
func getLastLoginTime(username string) string {
H
hongming 已提交
490
	lastLogin, err := redis.Client().LRange(fmt.Sprintf("kubesphere:users:%s:login-log", username), -1, -1).Result()
H
hongming 已提交
491 492

	if err != nil {
H
hongming 已提交
493
		return ""
H
hongming 已提交
494 495
	}

H
hongming 已提交
496
	if len(lastLogin) > 0 {
H
hongming 已提交
497
		return strings.Split(lastLogin[0], ",")[0]
H
hongming 已提交
498
	}
H
hongming 已提交
499 500

	return ""
H
hongming 已提交
501 502 503 504 505 506
}

func setAvatar(username, avatar string) error {
	_, err := redis.Client().HMSet("kubesphere:users:avatar", map[string]interface{}{"username": avatar}).Result()
	return err
}
H
hongming 已提交
507

H
hongming 已提交
508
func getAvatar(username string) string {
H
hongming 已提交
509

H
hongming 已提交
510
	avatar, err := redis.Client().HMGet("kubesphere:users:avatar", username).Result()
H
hongming 已提交
511 512

	if err != nil {
H
hongming 已提交
513
		return ""
H
hongming 已提交
514 515
	}

H
hongming 已提交
516 517
	if len(avatar) > 0 {
		if url, ok := avatar[0].(string); ok {
H
hongming 已提交
518
			return url
H
hongming 已提交
519
		}
H
hongming 已提交
520
	}
H
hongming 已提交
521 522

	return ""
H
hongming 已提交
523 524 525 526
}

func DeleteUser(username string) error {

H
hongming 已提交
527
	conn, err := ldapclient.Client()
H
hongming 已提交
528

H
hongming 已提交
529 530 531 532 533 534
	if err != nil {
		return err
	}

	defer conn.Close()

H
hongming 已提交
535
	deleteRequest := ldap.NewDelRequest(fmt.Sprintf("uid=%s,%s", username, ldapclient.UserSearchBase), nil)
H
hongming 已提交
536

H
hongming 已提交
537
	if err = conn.Del(deleteRequest); err != nil {
H
hongming 已提交
538
		glog.Errorln("delete user", err)
H
hongming 已提交
539 540 541
		return err
	}

H
hongming 已提交
542 543 544 545 546 547 548
	if err = deleteRoleBindings(username); err != nil {
		glog.Errorln("delete user role bindings failed", username, err)
	}

	if err := kubeconfig.DelKubeConfig(username); err != nil {
		glog.Errorln("delete user kubeconfig failed", username, err)
	}
H
hongming 已提交
549

H
hongming 已提交
550 551 552 553
	if err := kubectl.DelKubectlDeploy(username); err != nil {
		glog.Errorln("delete user terminal pod failed", username, err)
	}

R
runzexia 已提交
554 555 556
	devopsDb := devops_mysql.OpenDatabase()

	jenkinsClient := admin_jenkins.Client()
R
runzexia 已提交
557 558 559 560 561
	if jenkinsClient == nil {
		err := fmt.Errorf("could not connect to jenkins")
		glog.Error(err)
		return restful.NewError(http.StatusServiceUnavailable, err.Error())
	}
R
runzexia 已提交
562 563 564 565 566 567
	_, err = devopsDb.DeleteFrom(devops.DevOpsProjectMembershipTableName).
		Where(db.And(
			db.Eq(devops.DevOpsProjectMembershipUsernameColumn, username),
		)).Exec()
	if err != nil {
		glog.Errorf("%+v", err)
R
runzexia 已提交
568
		return err
R
runzexia 已提交
569 570 571 572 573
	}

	err = jenkinsClient.DeleteUserInProject(username)
	if err != nil {
		glog.Errorf("%+v", err)
R
runzexia 已提交
574
		return err
R
runzexia 已提交
575 576
	}

H
hongming 已提交
577
	return nil
R
runzexia 已提交
578

H
hongming 已提交
579 580 581 582 583 584 585 586 587 588 589
}

func deleteRoleBindings(username string) error {
	roleBindingLister := informers.SharedInformerFactory().Rbac().V1().RoleBindings().Lister()
	roleBindings, err := roleBindingLister.List(labels.Everything())

	if err != nil {
		return err
	}

	for _, roleBinding := range roleBindings {
H
hongming 已提交
590
		roleBinding = roleBinding.DeepCopy()
H
hongming 已提交
591 592 593 594 595 596 597 598 599 600 601 602 603
		length1 := len(roleBinding.Subjects)

		for index, subject := range roleBinding.Subjects {
			if subject.Kind == v1.UserKind && subject.Name == username {
				roleBinding.Subjects = append(roleBinding.Subjects[:index], roleBinding.Subjects[index+1:]...)
				index--
			}
		}

		length2 := len(roleBinding.Subjects)

		if length2 == 0 {
			deletePolicy := meta_v1.DeletePropagationForeground
H
hongming 已提交
604
			err = k8s.Client().RbacV1().RoleBindings(roleBinding.Namespace).Delete(roleBinding.Name, &meta_v1.DeleteOptions{PropagationPolicy: &deletePolicy})
H
hongming 已提交
605 606 607 608 609

			if err != nil {
				glog.Errorf("delete role binding %s %s %s failed: %v", username, roleBinding.Namespace, roleBinding.Name, err)
			}
		} else if length2 < length1 {
H
hongming 已提交
610
			_, err = k8s.Client().RbacV1().RoleBindings(roleBinding.Namespace).Update(roleBinding)
H
hongming 已提交
611 612 613 614 615 616 617 618 619 620 621

			if err != nil {
				glog.Errorf("update role binding %s %s %s failed: %v", username, roleBinding.Namespace, roleBinding.Name, err)
			}
		}
	}

	clusterRoleBindingLister := informers.SharedInformerFactory().Rbac().V1().ClusterRoleBindings().Lister()
	clusterRoleBindings, err := clusterRoleBindingLister.List(labels.Everything())

	for _, clusterRoleBinding := range clusterRoleBindings {
H
hongming 已提交
622
		clusterRoleBinding = clusterRoleBinding.DeepCopy()
H
hongming 已提交
623 624 625 626 627 628 629 630 631 632 633 634
		length1 := len(clusterRoleBinding.Subjects)

		for index, subject := range clusterRoleBinding.Subjects {
			if subject.Kind == v1.UserKind && subject.Name == username {
				clusterRoleBinding.Subjects = append(clusterRoleBinding.Subjects[:index], clusterRoleBinding.Subjects[index+1:]...)
				index--
			}
		}

		length2 := len(clusterRoleBinding.Subjects)
		if length2 == 0 {
			if groups := regexp.MustCompile(fmt.Sprintf(`^system:(\S+):(%s)$`, strings.Join(constants.WorkSpaceRoles, "|"))).FindStringSubmatch(clusterRoleBinding.RoleRef.Name); len(groups) == 3 {
H
hongming 已提交
635
				_, err = k8s.Client().RbacV1().ClusterRoleBindings().Update(clusterRoleBinding)
H
hongming 已提交
636 637
			} else {
				deletePolicy := meta_v1.DeletePropagationForeground
H
hongming 已提交
638
				err = k8s.Client().RbacV1().ClusterRoleBindings().Delete(clusterRoleBinding.Name, &meta_v1.DeleteOptions{PropagationPolicy: &deletePolicy})
H
hongming 已提交
639 640 641 642 643
			}
			if err != nil {
				glog.Errorf("update cluster role binding %s failed:%s", clusterRoleBinding.Name, err)
			}
		} else if length2 < length1 {
H
hongming 已提交
644
			_, err = k8s.Client().RbacV1().ClusterRoleBindings().Update(clusterRoleBinding)
H
hongming 已提交
645 646 647 648 649 650 651 652 653 654 655 656 657 658

			if err != nil {
				glog.Errorf("update cluster role binding %s failed:%s", clusterRoleBinding.Name, err)
			}
		}

	}

	return nil
}

func UserCreateCheck(check string) (exist bool, err error) {

	// bind root DN
H
hongming 已提交
659
	conn, err := ldapclient.Client()
H
hongming 已提交
660 661 662 663 664 665 666 667 668

	if err != nil {
		return false, err
	}

	defer conn.Close()

	// search for the given username
	userSearchRequest := ldap.NewSearchRequest(
H
hongming 已提交
669
		ldapclient.UserSearchBase,
H
hongming 已提交
670 671 672 673 674 675 676 677 678
		ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
		fmt.Sprintf("(&(objectClass=inetOrgPerson)(|(uid=%s)(mail=%s)))", check, check),
		[]string{"uid", "mail"},
		nil,
	)

	result, err := conn.Search(userSearchRequest)

	if err != nil {
H
hongming 已提交
679
		glog.Errorln("search user", err)
H
hongming 已提交
680 681 682
		return false, err
	}

H
hongming 已提交
683
	return len(result.Entries) > 0, nil
H
hongming 已提交
684 685
}

H
hongming 已提交
686
func CreateUser(user *models.User) (*models.User, error) {
H
hongming 已提交
687 688 689 690 691
	user.Username = strings.TrimSpace(user.Username)
	user.Email = strings.TrimSpace(user.Email)
	user.Password = strings.TrimSpace(user.Password)
	user.Description = strings.TrimSpace(user.Description)

H
hongming 已提交
692
	conn, err := ldapclient.Client()
H
hongming 已提交
693 694

	if err != nil {
H
hongming 已提交
695
		return nil, err
H
hongming 已提交
696 697 698 699 700
	}

	defer conn.Close()

	userSearchRequest := ldap.NewSearchRequest(
H
hongming 已提交
701
		ldapclient.UserSearchBase,
H
hongming 已提交
702 703 704 705 706 707 708 709 710
		ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
		fmt.Sprintf("(&(objectClass=inetOrgPerson)(|(uid=%s)(mail=%s)))", user.Username, user.Email),
		[]string{"uid", "mail"},
		nil,
	)

	result, err := conn.Search(userSearchRequest)

	if err != nil {
H
hongming 已提交
711
		glog.Errorln("search user", err)
H
hongming 已提交
712
		return nil, err
H
hongming 已提交
713 714 715
	}

	if len(result.Entries) > 0 {
H
hongming 已提交
716
		return nil, ldap.NewError(ldap.LDAPResultEntryAlreadyExists, fmt.Errorf("username or email already exists"))
H
hongming 已提交
717 718 719 720 721
	}

	maxUid, err := getMaxUid(conn)

	if err != nil {
H
hongming 已提交
722
		glog.Errorln("get max uid", err)
H
hongming 已提交
723
		return nil, err
H
hongming 已提交
724 725 726 727
	}

	maxUid += 1

H
hongming 已提交
728
	userCreateRequest := ldap.NewAddRequest(fmt.Sprintf("uid=%s,%s", user.Username, ldapclient.UserSearchBase), nil)
H
hongming 已提交
729 730 731 732 733 734 735 736 737 738
	userCreateRequest.Attribute("objectClass", []string{"inetOrgPerson", "posixAccount", "top"})
	userCreateRequest.Attribute("cn", []string{user.Username})                       // RFC4519: common name(s) for which the entity is known by
	userCreateRequest.Attribute("sn", []string{" "})                                 // RFC2256: last (family) name(s) for which the entity is known by
	userCreateRequest.Attribute("gidNumber", []string{"500"})                        // RFC2307: An integer uniquely identifying a group in an administrative domain
	userCreateRequest.Attribute("homeDirectory", []string{"/home/" + user.Username}) // The absolute path to the home directory
	userCreateRequest.Attribute("uid", []string{user.Username})                      // RFC4519: user identifier
	userCreateRequest.Attribute("uidNumber", []string{strconv.Itoa(maxUid)})         // RFC2307: An integer uniquely identifying a user in an administrative domain
	userCreateRequest.Attribute("mail", []string{user.Email})                        // RFC1274: RFC822 Mailbox
	userCreateRequest.Attribute("userPassword", []string{user.Password})             // RFC4519/2307: password of user
	if user.Lang != "" {
H
hongming 已提交
739
		userCreateRequest.Attribute("preferredLanguage", []string{user.Lang})
H
hongming 已提交
740 741 742 743 744 745 746 747
	}
	if user.Description != "" {
		userCreateRequest.Attribute("description", []string{user.Description}) // RFC4519: descriptive information
	}

	err = conn.Add(userCreateRequest)

	if err != nil {
H
hongming 已提交
748
		glog.Errorln("create user", err)
H
hongming 已提交
749
		return nil, err
H
hongming 已提交
750 751
	}

H
hongming 已提交
752 753 754
	if user.AvatarUrl != "" {
		setAvatar(user.Username, user.AvatarUrl)
	}
H
hongming 已提交
755

H
hongming 已提交
756 757 758 759
	if err := kubeconfig.CreateKubeConfig(user.Username); err != nil {
		glog.Errorln("create user kubeconfig failed", user.Username, err)
	}

H
hongming 已提交
760
	if user.ClusterRole != "" {
H
hongming 已提交
761 762 763
		err := CreateClusterRoleBinding(user.Username, user.ClusterRole)

		if err != nil {
H
hongming 已提交
764
			glog.Errorln("create cluster role binding filed", err)
H
hongming 已提交
765 766
			return nil, err
		}
H
hongming 已提交
767 768
	}

H
hongming 已提交
769
	return DescribeUser(user.Username)
H
hongming 已提交
770 771 772
}

func getMaxUid(conn ldap.Client) (int, error) {
H
hongming 已提交
773
	userSearchRequest := ldap.NewSearchRequest(ldapclient.UserSearchBase,
H
hongming 已提交
774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802
		ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
		"(&(objectClass=inetOrgPerson))",
		[]string{"uidNumber"},
		nil)

	result, err := conn.Search(userSearchRequest)

	if err != nil {
		return 0, err
	}

	var maxUid int

	if len(result.Entries) == 0 {
		maxUid = 1000
	} else {
		for _, usr := range result.Entries {
			uid, _ := strconv.Atoi(usr.GetAttributeValue("uidNumber"))
			if uid > maxUid {
				maxUid = uid
			}
		}
	}

	return maxUid, nil
}

func getMaxGid(conn ldap.Client) (int, error) {

H
hongming 已提交
803
	groupSearchRequest := ldap.NewSearchRequest(ldapclient.GroupSearchBase,
H
hongming 已提交
804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830
		ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
		"(&(objectClass=posixGroup))",
		[]string{"gidNumber"},
		nil)

	result, err := conn.Search(groupSearchRequest)

	if err != nil {
		return 0, err
	}

	var maxGid int

	if len(result.Entries) == 0 {
		maxGid = 500
	} else {
		for _, group := range result.Entries {
			gid, _ := strconv.Atoi(group.GetAttributeValue("gidNumber"))
			if gid > maxGid {
				maxGid = gid
			}
		}
	}

	return maxGid, nil
}

H
hongming 已提交
831
func UpdateUser(user *models.User) (*models.User, error) {
H
hongming 已提交
832

H
hongming 已提交
833
	conn, err := ldapclient.Client()
H
hongming 已提交
834

H
hongming 已提交
835
	if err != nil {
H
hongming 已提交
836
		return nil, err
H
hongming 已提交
837 838 839 840
	}

	defer conn.Close()

H
hongming 已提交
841
	dn := fmt.Sprintf("uid=%s,%s", user.Username, ldapclient.UserSearchBase)
H
hongming 已提交
842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857
	userModifyRequest := ldap.NewModifyRequest(dn, nil)
	if user.Email != "" {
		userModifyRequest.Replace("mail", []string{user.Email})
	}
	if user.Description != "" {
		userModifyRequest.Replace("description", []string{user.Description})
	}

	if user.Lang != "" {
		userModifyRequest.Replace("preferredLanguage", []string{user.Lang})
	}

	if user.Password != "" {
		userModifyRequest.Replace("userPassword", []string{user.Password})
	}

H
hongming 已提交
858 859 860 861 862 863 864 865
	if user.AvatarUrl != "" {
		err = setAvatar(user.Username, user.AvatarUrl)
	}

	if err != nil {
		return nil, err
	}

H
hongming 已提交
866 867 868
	err = conn.Modify(userModifyRequest)

	if err != nil {
H
hongming 已提交
869
		return nil, err
H
hongming 已提交
870 871 872 873 874
	}

	err = CreateClusterRoleBinding(user.Username, user.ClusterRole)

	if err != nil {
H
hongming 已提交
875
		glog.Errorln("create cluster role binding filed", err)
H
hongming 已提交
876
		return nil, err
H
hongming 已提交
877 878
	}

H
hongming 已提交
879
	return GetUserInfo(user.Username)
H
hongming 已提交
880 881 882 883
}
func DeleteGroup(path string) error {

	// bind root DN
H
hongming 已提交
884
	conn, err := ldapclient.Client()
H
hongming 已提交
885 886 887 888 889 890 891 892 893 894 895
	if err != nil {
		return err
	}
	defer conn.Close()

	searchBase, cn := splitPath(path)

	groupDeleteRequest := ldap.NewDelRequest(fmt.Sprintf("cn=%s,%s", cn, searchBase), nil)
	err = conn.Del(groupDeleteRequest)

	if err != nil {
H
hongming 已提交
896
		glog.Errorln("delete user group", err)
H
hongming 已提交
897 898 899 900 901 902
		return err
	}

	return nil
}

H
hongming 已提交
903
func CreateGroup(group *models.Group) (*models.Group, error) {
H
hongming 已提交
904

H
hongming 已提交
905
	conn, err := ldapclient.Client()
H
hongming 已提交
906

H
hongming 已提交
907 908 909
	if err != nil {
		return nil, err
	}
H
hongming 已提交
910

H
hongming 已提交
911 912 913 914 915
	defer conn.Close()

	maxGid, err := getMaxGid(conn)

	if err != nil {
H
hongming 已提交
916
		glog.Errorln("get max gid", err)
H
hongming 已提交
917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936
		return nil, err
	}

	maxGid += 1

	if group.Path == "" {
		group.Path = group.Name
	}

	searchBase, cn := splitPath(group.Path)

	groupCreateRequest := ldap.NewAddRequest(fmt.Sprintf("cn=%s,%s", cn, searchBase), nil)
	groupCreateRequest.Attribute("objectClass", []string{"posixGroup", "top"})
	groupCreateRequest.Attribute("cn", []string{cn})
	groupCreateRequest.Attribute("gidNumber", []string{strconv.Itoa(maxGid)})

	if group.Description != "" {
		groupCreateRequest.Attribute("description", []string{group.Description})
	}

H
hongming 已提交
937 938 939
	if group.Members != nil {
		groupCreateRequest.Attribute("memberUid", group.Members)
	}
H
hongming 已提交
940 941 942 943

	err = conn.Add(groupCreateRequest)

	if err != nil {
H
hongming 已提交
944
		glog.Errorln("create group", err)
H
hongming 已提交
945 946 947 948 949
		return nil, err
	}

	group.Gid = strconv.Itoa(maxGid)

H
hongming 已提交
950
	return DescribeGroup(group.Path)
H
hongming 已提交
951 952 953 954 955
}

func UpdateGroup(group *models.Group) (*models.Group, error) {

	// bind root DN
H
hongming 已提交
956
	conn, err := ldapclient.Client()
H
hongming 已提交
957 958 959 960 961
	if err != nil {
		return nil, err
	}
	defer conn.Close()

H
hongming 已提交
962
	old, err := DescribeGroup(group.Path)
H
hongming 已提交
963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990

	if err != nil {
		return nil, err
	}

	searchBase, cn := splitPath(group.Path)

	groupUpdateRequest := ldap.NewModifyRequest(fmt.Sprintf("cn=%s,%s", cn, searchBase), nil)

	if old.Description == "" {
		if group.Description != "" {
			groupUpdateRequest.Add("description", []string{group.Description})
		}
	} else {
		if group.Description != "" {
			groupUpdateRequest.Replace("description", []string{group.Description})
		} else {
			groupUpdateRequest.Delete("description", []string{})
		}
	}

	if group.Members != nil {
		groupUpdateRequest.Replace("memberUid", group.Members)
	}

	err = conn.Modify(groupUpdateRequest)

	if err != nil {
H
hongming 已提交
991
		glog.Errorln("update group", err)
H
hongming 已提交
992 993 994 995 996 997 998 999 1000
		return nil, err
	}

	return group, nil
}

func ChildList(path string) ([]models.Group, error) {

	// bind root DN
H
hongming 已提交
1001
	conn, err := ldapclient.Client()
H
hongming 已提交
1002 1003 1004 1005 1006 1007 1008 1009 1010

	if err != nil {
		return nil, err
	}

	defer conn.Close()

	var groupSearchRequest *ldap.SearchRequest
	if path == "" {
H
hongming 已提交
1011
		groupSearchRequest = ldap.NewSearchRequest(ldapclient.GroupSearchBase,
H
hongming 已提交
1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
			ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false,
			"(&(objectClass=posixGroup))",
			[]string{"cn", "gidNumber", "memberUid", "description"},
			nil)
	} else {
		searchBase, cn := splitPath(path)
		groupSearchRequest = ldap.NewSearchRequest(fmt.Sprintf("cn=%s,%s", cn, searchBase),
			ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false,
			"(&(objectClass=posixGroup))",
			[]string{"cn", "gidNumber", "memberUid", "description"},
			nil)
	}

	result, err := conn.Search(groupSearchRequest)

	if err != nil {
		return nil, err
	}

	groups := make([]models.Group, 0)

	for _, v := range result.Entries {
		dn := v.DN
		cn := v.GetAttributeValue("cn")
		gid := v.GetAttributeValue("gidNumber")
		members := v.GetAttributeValues("memberUid")
		description := v.GetAttributeValue("description")

		group := models.Group{Path: convertDNToPath(dn), Name: cn, Gid: gid, Members: members, Description: description}

		childSearchRequest := ldap.NewSearchRequest(dn,
			ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false,
			"(&(objectClass=posixGroup))",
			[]string{""},
			nil)

		result, err = conn.Search(childSearchRequest)

		if err != nil {
			return nil, err
		}

		childGroups := make([]string, 0)

		for _, v := range result.Entries {
			child := convertDNToPath(v.DN)
			childGroups = append(childGroups, child)
		}

		group.ChildGroups = childGroups

		groups = append(groups, group)
	}

	return groups, nil
}

H
hongming 已提交
1069
func DescribeGroup(path string) (*models.Group, error) {
H
hongming 已提交
1070 1071 1072

	searchBase, cn := splitPath(path)

H
hongming 已提交
1073 1074 1075 1076 1077 1078
	conn, err := ldapclient.Client()

	if err != nil {
		return nil, err
	}

H
hongming 已提交
1079 1080 1081 1082 1083 1084 1085 1086 1087
	groupSearchRequest := ldap.NewSearchRequest(searchBase,
		ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false,
		fmt.Sprintf("(&(objectClass=posixGroup)(cn=%s))", cn),
		[]string{"cn", "gidNumber", "memberUid", "description"},
		nil)

	result, err := conn.Search(groupSearchRequest)

	if err != nil {
H
hongming 已提交
1088
		glog.Errorln("search group", err)
H
hongming 已提交
1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
		return nil, err
	}

	if len(result.Entries) != 1 {
		return nil, ldap.NewError(ldap.LDAPResultNoSuchObject, fmt.Errorf("group %s does not exist", path))
	}

	dn := result.Entries[0].DN
	cn = result.Entries[0].GetAttributeValue("cn")
	gid := result.Entries[0].GetAttributeValue("gidNumber")
	members := result.Entries[0].GetAttributeValues("memberUid")
	description := result.Entries[0].GetAttributeValue("description")

	group := models.Group{Path: convertDNToPath(dn), Name: cn, Gid: gid, Members: members, Description: description}

	childGroups := make([]string, 0)

	group.ChildGroups = childGroups

H
hongming 已提交
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
	return &group, nil

}

func WorkspaceUsersTotalCount(workspace string) (int, error) {
	workspaceRoleBindings, err := GetWorkspaceRoleBindings(workspace)

	if err != nil {
		return 0, err
	}
H
hongming 已提交
1118

H
hongming 已提交
1119
	users := make([]string, 0)
H
hongming 已提交
1120

H
hongming 已提交
1121 1122 1123 1124 1125
	for _, roleBinding := range workspaceRoleBindings {
		for _, subject := range roleBinding.Subjects {
			if subject.Kind == v1.UserKind && !k8sutil.ContainsUser(users, subject.Name) {
				users = append(users, subject.Name)
			}
H
hongming 已提交
1126 1127 1128
		}
	}

H
hongming 已提交
1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140
	return len(users), nil
}

func ListWorkspaceUsers(workspace string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {

	workspaceRoleBindings, err := GetWorkspaceRoleBindings(workspace)

	if err != nil {
		return nil, err
	}

	users := make([]*models.User, 0)
H
hongming 已提交
1141

H
hongming 已提交
1142 1143 1144
	for _, roleBinding := range workspaceRoleBindings {
		for _, subject := range roleBinding.Subjects {
			if subject.Kind == v1.UserKind && !k8sutil.ContainsUser(users, subject.Name) {
H
hongming 已提交
1145
				user, err := GetUserInfo(subject.Name)
H
hongming 已提交
1146 1147 1148 1149 1150
				if err != nil {
					return nil, err
				}
				prefix := fmt.Sprintf("workspace:%s:", workspace)
				user.WorkspaceRole = fmt.Sprintf("workspace-%s", strings.TrimPrefix(roleBinding.Name, prefix))
H
hongming 已提交
1151 1152 1153
				if matchConditions(conditions, user) {
					users = append(users, user)
				}
H
hongming 已提交
1154
			}
H
hongming 已提交
1155 1156 1157
		}
	}

H
hongming 已提交
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
	// order & reverse
	sort.Slice(users, func(i, j int) bool {
		if reverse {
			tmp := i
			i = j
			j = tmp
		}
		switch orderBy {
		default:
			fallthrough
		case "name":
			return strings.Compare(users[i].Username, users[j].Username) <= 0
		}
	})

	result := make([]interface{}, 0)

	for i, d := range users {
		if i >= offset && (limit == -1 || len(result) < limit) {
			result = append(result, d)
		}
	}
H
hongming 已提交
1180

H
hongming 已提交
1181
	return &models.PageableResponse{Items: result, TotalCount: len(users)}, nil
H
hongming 已提交
1182
}
H
hongming 已提交
1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210

func matchConditions(conditions *params.Conditions, user *models.User) bool {
	for k, v := range conditions.Match {
		switch k {
		case "keyword":
			if !strings.Contains(user.Username, v) &&
				!strings.Contains(user.Email, v) &&
				!strings.Contains(user.Description, v) {
				return false
			}
		case "name":
			names := strings.Split(v, "|")
			if !sliceutil.HasString(names, user.Username) {
				return false
			}
		case "email":
			email := strings.Split(v, "|")
			if !sliceutil.HasString(email, user.Email) {
				return false
			}
		case "role":
			if user.WorkspaceRole != v {
				return false
			}
		}
	}
	return true
}