anotherUserSub processes a request to initiate an invite or approve a subscription request from another user. Returns changed == true if user's access mode has changed. Handle these cases: A. Sharer or Approver is inviting another user for the first time (no prior subscription) B. Sharer or Approver
(sess *Session, asUid, target types.Uid, asChan bool, pkt *ClientComMessage)
| 1879 | // B. Sharer or Approver is re-inviting another user (adjusting modeGiven, modeWant is still Unset) |
| 1880 | // C. Approver is changing modeGiven for another user, modeWant != Unset |
| 1881 | func (t *Topic) anotherUserSub(sess *Session, asUid, target types.Uid, asChan bool, |
| 1882 | pkt *ClientComMessage) (*MsgAccessMode, error) { |
| 1883 | |
| 1884 | now := types.TimeNow() |
| 1885 | set := pkt.Set |
| 1886 | |
| 1887 | // Check if approver actually has permission to manage sharing |
| 1888 | hostData, ok := t.perUser[asUid] |
| 1889 | // Access mode of the person who is executing this approval process |
| 1890 | hostMode := hostData.modeGiven & hostData.modeWant |
| 1891 | if !ok || !hostMode.IsSharer() { |
| 1892 | sess.queueOut(ErrPermissionDeniedReply(pkt, now)) |
| 1893 | return nil, errors.New("topic access denied; approver has no permission") |
| 1894 | } |
| 1895 | |
| 1896 | if asChan { |
| 1897 | // TODO: need to implement promoting reader to subscriber. Rejecting for now. |
| 1898 | sess.queueOut(ErrPermissionDeniedReply(pkt, now)) |
| 1899 | return nil, errors.New("topic access denied: cannot subscribe reader to channel") |
| 1900 | } |
| 1901 | |
| 1902 | // Check if topic is suspended. |
| 1903 | if t.isReadOnly() { |
| 1904 | sess.queueOut(ErrPermissionDeniedReply(pkt, now)) |
| 1905 | return nil, errors.New("topic is suspended") |
| 1906 | } |
| 1907 | |
| 1908 | // Parse the access mode granted |
| 1909 | modeGiven := types.ModeUnset |
| 1910 | if set.Sub.Mode != "" { |
| 1911 | if err := modeGiven.UnmarshalText([]byte(set.Sub.Mode)); err != nil { |
| 1912 | sess.queueOut(ErrMalformedReply(pkt, now)) |
| 1913 | return nil, err |
| 1914 | } |
| 1915 | |
| 1916 | // Make sure the new permissions are reasonable in P2P topics: permissions no greater than allowed, |
| 1917 | // approver permission cannot be removed. |
| 1918 | if t.cat == types.TopicCatP2P { |
| 1919 | modeGiven = (modeGiven & globals.typesModeCP2P) | types.ModeApprove |
| 1920 | } |
| 1921 | } |
| 1922 | |
| 1923 | // Make sure only the owner & approvers can set non-default access mode |
| 1924 | if modeGiven != types.ModeUnset && !hostMode.IsAdmin() { |
| 1925 | sess.queueOut(ErrPermissionDeniedReply(pkt, now)) |
| 1926 | return nil, errors.New("sharer cannot set explicit modeGiven") |
| 1927 | } |
| 1928 | |
| 1929 | // Make sure no one but the owner can do an ownership transfer |
| 1930 | if modeGiven.IsOwner() && t.owner != asUid { |
| 1931 | sess.queueOut(ErrPermissionDeniedReply(pkt, now)) |
| 1932 | return nil, errors.New("attempt to transfer ownership by non-owner") |
| 1933 | } |
| 1934 | |
| 1935 | // Access mode values as they were before this request was processed. |
| 1936 | oldWant := types.ModeUnset |
| 1937 | oldGiven := types.ModeUnset |
| 1938 |
no test coverage detected