diff --git a/server/init_topic.go b/server/init_topic.go index 75977a14..fd2ad8e8 100644 --- a/server/init_topic.go +++ b/server/init_topic.go @@ -189,8 +189,8 @@ func initTopicFnd(t *Topic, sreg *sessionJoin) error { } // Make sure no one can join the topic. - t.accessAuth = getDefaultAccess(t.cat, true) - t.accessAnon = getDefaultAccess(t.cat, false) + t.accessAuth = getDefaultAccess(t.cat, true, false) + t.accessAnon = getDefaultAccess(t.cat, false, false) if err = t.loadSubscribers(); err != nil { return err @@ -487,14 +487,8 @@ func initTopicNewGrp(t *Topic, sreg *sessionJoin, isChan bool) error { // Generic topics have parameters stored in the topic object t.owner = types.ParseUserId(sreg.pkt.AsUser) - if isChan { - // The channel is not accessible by default. - t.accessAuth = types.ModeNone - t.accessAnon = types.ModeNone - } else { - t.accessAuth = getDefaultAccess(t.cat, true) - t.accessAnon = getDefaultAccess(t.cat, false) - } + t.accessAuth = getDefaultAccess(t.cat, true, isChan) + t.accessAnon = getDefaultAccess(t.cat, false, isChan) // Owner/creator gets full access to the topic. Owner may change the default modeWant through 'set'. userData := perUserData{ diff --git a/server/store/types/types.go b/server/store/types/types.go index 69b31f74..ad36722b 100644 --- a/server/store/types/types.go +++ b/server/store/types/types.go @@ -526,8 +526,10 @@ const ( ModeCReadOnly = ModeJoin | ModeRead // Access to 'sys' topic by a root user ("JRWPD", 79, 0x4F) ModeCSys = ModeJoin | ModeRead | ModeWrite | ModePres | ModeDelete - // Public access mode to a channel (JRP, 11, 0xB). - ModeCChn = ModeJoin | ModeRead | ModePres + // Channel publisher: person authorized to publish content; no J: by invitation only ("RWPD", 78, 0x4E) + ModeCChnWriter = ModeRead | ModeWrite | ModePres | ModeShare + // Reader's access mode to a channel (JRP, 11, 0xB). + ModeCChnReader = ModeJoin | ModeRead | ModePres // Admin: user who can modify access mode ("OA", dec: 144, hex: 0x90) ModeCAdmin = ModeOwner | ModeApprove diff --git a/server/topic.go b/server/topic.go index 40e08bf9..f0b2a392 100644 --- a/server/topic.go +++ b/server/topic.go @@ -1207,20 +1207,20 @@ func (t *Topic) thisUserSub(h *Hub, sess *Session, pkt *ClientComMessage, asUid } // Given mode is immutable. - oldGiven = types.ModeCChn - userData.modeGiven = types.ModeCChn + oldGiven = types.ModeCChnReader + userData.modeGiven = types.ModeCChnReader if sub != nil { // Subscription exists, read old access mode. oldWant = sub.ModeWant } else { // Subscription not found, use default. - oldWant = types.ModeCChn + oldWant = types.ModeCChnReader } if modeWant != types.ModeUnset { // New access mode is explicitly assigned. - userData.modeWant = (modeWant & types.ModeCChn) | types.ModeRead | types.ModeJoin + userData.modeWant = (modeWant & types.ModeCChnReader) | types.ModeRead | types.ModeJoin } else { // Default: unchanged. userData.modeWant = oldWant @@ -1551,6 +1551,8 @@ func (t *Topic) anotherUserSub(h *Hub, sess *Session, asUid, target types.Uid, // Request to use default access mode for the new subscriptions. // Assuming LevelAuth. Approver should use non-default access if that is not suitable. modeGiven = t.accessFor(auth.LevelAuth) + // Enable new subscription even if default is no joiner. + modeGiven |= types.ModeJoin } // Get user's default access mode to be used as modeWant @@ -2136,7 +2138,7 @@ func (t *Topic) replyGetSub(sess *Session, asUid types.Uid, authLevel auth.Level mts.Acs.Want = sub.ModeWant.String() mts.Acs.Given = sub.ModeGiven.String() } else if isChannel(sub.Topic) { - mts.Acs.Mode = types.ModeCChn.String() + mts.Acs.Mode = types.ModeCChnReader.String() } else if defacs := sub.GetDefaultAccess(); defacs != nil { switch authLevel { case auth.LevelAnon: @@ -2805,7 +2807,7 @@ func (t *Topic) replyLeaveUnsub(h *Hub, sess *Session, pkt *ClientComMessage, as } oldWant, oldGiven = pud.modeWant, pud.modeGiven } else { - oldWant, oldGiven = types.ModeCChn, types.ModeCChn + oldWant, oldGiven = types.ModeCChnReader, types.ModeCChnReader // Unsubscribe user's devices from the channel (FCM topic). t.channelSubUnsub(asUid, false) } @@ -3218,7 +3220,7 @@ func (t *Topic) fndRemovePublic(sess *Session) { } func (t *Topic) accessFor(authLvl auth.Level) types.AccessMode { - return selectAccessMode(authLvl, t.accessAnon, t.accessAuth, getDefaultAccess(t.cat, true)) + return selectAccessMode(authLvl, t.accessAnon, t.accessAuth, getDefaultAccess(t.cat, true, false)) } // subsCount returns the number of topic subsribers diff --git a/server/user.go b/server/user.go index 2551ff5f..6abad9ec 100644 --- a/server/user.go +++ b/server/user.go @@ -85,8 +85,10 @@ func replyCreateUser(s *Session, msg *ClientComMessage, rec *auth.Rec) { } // Assign default access values in case the acc creator has not provided them - user.Access.Auth = getDefaultAccess(types.TopicCatP2P, true) | getDefaultAccess(types.TopicCatGrp, true) - user.Access.Anon = getDefaultAccess(types.TopicCatP2P, false) | getDefaultAccess(types.TopicCatGrp, false) + user.Access.Auth = getDefaultAccess(types.TopicCatP2P, true, false) | + getDefaultAccess(types.TopicCatGrp, true, false) + user.Access.Anon = getDefaultAccess(types.TopicCatP2P, false, false) | + getDefaultAccess(types.TopicCatGrp, false, false) // Assign actual access values, public and private. if msg.Acc.Desc != nil { diff --git a/server/utils.go b/server/utils.go index 71c1cb6d..d407760d 100644 --- a/server/utils.go +++ b/server/utils.go @@ -296,7 +296,7 @@ func selectAccessMode(authLvl auth.Level, anonMode, authMode, rootMode types.Acc } // Get default modeWant for the given topic category -func getDefaultAccess(cat types.TopicCat, authUser bool) types.AccessMode { +func getDefaultAccess(cat types.TopicCat, authUser, isChan bool) types.AccessMode { if !authUser { return types.ModeNone } @@ -307,6 +307,9 @@ func getDefaultAccess(cat types.TopicCat, authUser bool) types.AccessMode { case types.TopicCatFnd: return types.ModeNone case types.TopicCatGrp: + if isChan { + return types.ModeCChnWriter + } return types.ModeCPublic case types.TopicCatMe: return types.ModeCSelf diff --git a/tinode-db/chan-128.jpg b/tinode-db/chan-128.jpg index db0523f9..49e7beec 100644 Binary files a/tinode-db/chan-128.jpg and b/tinode-db/chan-128.jpg differ diff --git a/tinode-db/data.json b/tinode-db/data.json index 298d4de0..62d6d5db 100644 --- a/tinode-db/data.json +++ b/tinode-db/data.json @@ -156,7 +156,7 @@ "channel": true, "tags": ["coffee","channel"], "public": {"fn": "Coffee Channel", "photo": "chan-128.jpg", "type": "jpg"}, - "access": {"auth": "N", "anon": "N"} + "access": {"auth": "RWPD", "anon": "N"} } ], "p2psubs": [ diff --git a/tinode-db/gendb.go b/tinode-db/gendb.go index 539492e8..9c2f66a0 100644 --- a/tinode-db/gendb.go +++ b/tinode-db/gendb.go @@ -237,8 +237,8 @@ func genDb(data *Data) { for _, ss := range data.Groupsubs { var want, given types.AccessMode if ss.AsChan { - want = types.ModeCChn - given = types.ModeCChn + want = types.ModeCChnReader + given = types.ModeCChnReader } else { want = types.ModeCPublic given = types.ModeCPublic