MCPcopy
hub / github.com/tinode/chat / thisUserSub

Method thisUserSub

server/topic.go:1506–1873  ·  view source on GitHub ↗

User requests or updates a self-subscription to a topic. Called as a result of {sub} or {meta set=sub}. Returns new access mode as *MsgAccessMode if user's access mode has changed, nil otherwise. sess - originating session pkt - client message which triggered this request; {sub} or {set} asUi

(sess *Session, pkt *ClientComMessage, asUid types.Uid, asChan bool, want string,
	private any)

Source from the content-addressed store, hash-verified

1504// E. User is accepting ownership transfer (requesting ownership transfer is not permitted).
1505// In case of a group topic the user may be a reader or a full subscriber.
1506func (t *Topic) thisUserSub(sess *Session, pkt *ClientComMessage, asUid types.Uid, asChan bool, want string,
1507 private any) (*MsgAccessMode, error) {
1508
1509 now := types.TimeNow()
1510 asLvl := auth.Level(pkt.AuthLvl)
1511
1512 // Access mode values as they were before this request was processed.
1513 oldWant := types.ModeNone
1514 oldGiven := types.ModeNone
1515
1516 // Parse access mode requested by the user
1517 modeWant := types.ModeUnset
1518 if want != "" {
1519 if err := modeWant.UnmarshalText([]byte(want)); err != nil {
1520 sess.queueOut(ErrMalformedReply(pkt, now))
1521 return nil, err
1522 }
1523 }
1524
1525 var err error
1526 // Check if it's an attempt at a new subscription to the topic / a first connection of a channel reader
1527 // (channel readers are not permanently cached).
1528 // It could be an actual subscription (IsJoiner() == true) or a ban (IsJoiner() == false).
1529 userData, existingSub := t.perUser[asUid]
1530 if !existingSub || userData.deleted {
1531 // New subscription or a not yet cached channel reader, either new or existing.
1532
1533 // Check if the max number of subscriptions is already reached.
1534 if t.cat == types.TopicCatGrp && !asChan && t.subsCount() >= globals.maxSubscriberCount {
1535 sess.queueOut(ErrPolicyReply(pkt, now))
1536 return nil, errors.New("max subscription count exceeded")
1537 }
1538
1539 var sub *types.Subscription
1540 tname := t.name
1541 if t.cat == types.TopicCatP2P {
1542 // P2P could be here only if it was previously deleted. I.e. existingSub is always true for P2P.
1543 if modeWant != types.ModeUnset {
1544 userData.modeWant = modeWant
1545 }
1546 // If no modeWant is provided, leave existing one unchanged.
1547
1548 // Make sure the user is not asking for unreasonable permissions
1549 userData.modeWant = (userData.modeWant & globals.typesModeCP2P) | types.ModeApprove
1550 } else if t.cat == types.TopicCatSys {
1551 if asLvl != auth.LevelRoot {
1552 sess.queueOut(ErrPermissionDeniedReply(pkt, now))
1553 return nil, errors.New("subscription to 'sys' topic requires root access level")
1554 }
1555
1556 // Assign default access levels
1557 userData.modeWant = types.ModeCSys
1558 userData.modeGiven = types.ModeCSys
1559 if modeWant != types.ModeUnset {
1560 userData.modeWant = (modeWant & types.ModeCSys) | types.ModeWrite | types.ModeJoin
1561 }
1562 } else if asChan {
1563 userData.isChan = true

Callers 2

subscriptionReplyMethod · 0.95
replySetSubMethod · 0.95

Calls 15

subsCountMethod · 0.95
accessForMethod · 0.95
channelSubUnsubMethod · 0.95
notifySubChangeMethod · 0.95
presUsersOfInterestMethod · 0.95
presSingleUserOfflineMethod · 0.95
evictUserMethod · 0.95
TimeNowFunction · 0.92
LevelTypeAlias · 0.92
ErrMalformedReplyFunction · 0.85
ErrPolicyReplyFunction · 0.85
ErrPermissionDeniedReplyFunction · 0.85

Tested by

no test coverage detected