feat: close profile (#978)

This commit is contained in:
lalka2018 2023-12-02 20:21:16 +03:00 committed by GitHub
parent 04eb724cd5
commit 1e7fdeff27
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
41 changed files with 598 additions and 142 deletions

View file

@ -26,6 +26,9 @@ class Notes implements Handler
if(!$noteOwner->getPrivacyPermission("notes.read", $this->user))
$reject(160, "You don't have permission to access this note");
if(!$note->canBeViewedBy($this->user))
$reject(15, "Access to note denied");
$resolve([
"title" => $note->getName(),
"link" => "/note" . $note->getPrettyId(),

View file

@ -46,7 +46,7 @@ class Search implements Handler
break;
}
$res = $repo->find($query, ["doNotSearchMe" => $this->user->getId()], $sort);
$res = $repo->find($query, ["doNotSearchMe" => $this->user->getId(), "doNotSearchPrivate" => true,], $sort);
$results = array_slice(iterator_to_array($res), 0, 5);

View file

@ -27,6 +27,9 @@ class Wall implements Handler
if($post->getSuggestionType() != 0)
$reject(25, "Can't get suggested post");
if(!$post->canBeViewedBy($this->user))
$reject(12, "Access denied");
$res = (object) [];
$res->id = $post->getId();
$res->wall = $post->getTargetWall();

View file

@ -18,11 +18,15 @@ final class Friends extends VKAPIRequestHandler
$user_id = $this->getUser()->getId();
}
if (is_null($users->get($user_id))) {
$this->fail(100, "One of the parameters specified was missing or invalid");
}
$user = $users->get($user_id);
foreach($users->get($user_id)->getFriends($offset, $count) as $friend) {
if(!$user || $user->isDeleted())
$this->fail(100, "Invalid user");
if(!$user->getPrivacyPermission("friends.read", $this->getUser()))
$this->fail(15, "Access denied: this user chose to hide his friends.");
foreach($user->getFriends($offset, $count) as $friend) {
$friends[$i] = $friend->getId();
$i++;
}

View file

@ -19,6 +19,17 @@ final class Gifts extends VKAPIRequestHandler
if(!$user || $user->isDeleted())
$this->fail(177, "Invalid user");
if(!$user->canBeViewedBy($this->getUser()))
$this->fail(15, "Access denied");
/*
if(!$user->getPrivacyPermission('gifts.read', $this->getUser()))
$this->fail(15, "Access denied: this user chose to hide his gifts");*/
if(!$user->canBeViewedBy($this->getUser()))
$this->fail(15, "Access denied");
$gift_item = [];
$userGifts = array_slice(iterator_to_array($user->getGifts(1, $count, false)), $offset);
@ -62,6 +73,9 @@ final class Gifts extends VKAPIRequestHandler
if(!$user || $user->isDeleted())
$this->fail(177, "Invalid user");
if(!$user->canBeViewedBy($this->getUser()))
$this->fail(15, "Access denied");
$gift = (new GiftsRepo)->get($gift_id);
if(!$gift)

View file

@ -19,9 +19,12 @@ final class Groups extends VKAPIRequestHandler
$users = new UsersRepo;
$user = $users->get($user_id);
if(is_null($user))
if(is_null($user) || $user->isDeleted())
$this->fail(15, "Access denied");
if(!$user->getPrivacyPermission('groups.read', $this->getUser()))
$this->fail(15, "Access denied: this user chose to hide his groups.");
foreach($user->getClubs($offset, $filter == "admin", $count, true) as $club)
$clbs[] = $club;
@ -400,9 +403,15 @@ final class Groups extends VKAPIRequestHandler
];
foreach($filds as $fild) {
$canView = $member->canBeViewedBy($this->getUser());
switch($fild) {
case "bdate":
$arr->items[$i]->bdate = $member->getBirthday()->format('%e.%m.%Y');
if(!$canView) {
$arr->items[$i]->bdate = "01.01.1970";
break;
}
$arr->items[$i]->bdate = $member->getBirthday() ? $member->getBirthday()->format('%e.%m.%Y') : NULL;
break;
case "can_post":
$arr->items[$i]->can_post = $club->canBeModifiedBy($member);
@ -423,6 +432,11 @@ final class Groups extends VKAPIRequestHandler
$arr->items[$i]->connections = 1;
break;
case "contacts":
if(!$canView) {
$arr->items[$i]->contacts = "secret@gmail.com";
break;
}
$arr->items[$i]->contacts = $member->getContactEmail();
break;
case "country":
@ -438,15 +452,30 @@ final class Groups extends VKAPIRequestHandler
$arr->items[$i]->has_mobile = false;
break;
case "last_seen":
if(!$canView) {
$arr->items[$i]->last_seen = 0;
break;
}
$arr->items[$i]->last_seen = $member->getOnline()->timestamp();
break;
case "lists":
$arr->items[$i]->lists = "";
break;
case "online":
if(!$canView) {
$arr->items[$i]->online = false;
break;
}
$arr->items[$i]->online = $member->isOnline();
break;
case "online_mobile":
if(!$canView) {
$arr->items[$i]->online_mobile = false;
break;
}
$arr->items[$i]->online_mobile = $member->getOnlinePlatform() == "android" || $member->getOnlinePlatform() == "iphone" || $member->getOnlinePlatform() == "mobile";
break;
case "photo_100":
@ -477,12 +506,27 @@ final class Groups extends VKAPIRequestHandler
$arr->items[$i]->schools = 0;
break;
case "sex":
if(!$canView) {
$arr->items[$i]->sex = -1;
break;
}
$arr->items[$i]->sex = $member->isFemale() ? 1 : 2;
break;
case "site":
if(!$canView) {
$arr->items[$i]->site = NULL;
break;
}
$arr->items[$i]->site = $member->getWebsite();
break;
case "status":
if(!$canView) {
$arr->items[$i]->status = "r";
break;
}
$arr->items[$i]->status = $member->getStatus();
break;
case "universities":

View file

@ -44,7 +44,7 @@ final class Likes extends VKAPIRequestHandler
if(is_null($postable) || $postable->isDeleted())
$this->fail(100, "One of the parameters specified was missing or invalid: object not found");
if(method_exists($postable, "canBeViewedBy") && !$postable->canBeViewedBy($this->getUser() ?? NULL)) {
if(!$postable->canBeViewedBy($this->getUser() ?? NULL)) {
$this->fail(2, "Access to postable denied");
}
@ -89,7 +89,7 @@ final class Likes extends VKAPIRequestHandler
if(is_null($postable) || $postable->isDeleted())
$this->fail(100, "One of the parameters specified was missing or invalid: object not found");
if(method_exists($postable, "canBeViewedBy") && !$postable->canBeViewedBy($this->getUser() ?? NULL)) {
if(!$postable->canBeViewedBy($this->getUser() ?? NULL)) {
$this->fail(2, "Access to postable denied");
}
@ -111,7 +111,7 @@ final class Likes extends VKAPIRequestHandler
if(is_null($user) || $user->isDeleted())
$this->fail(100, "One of the parameters specified was missing or invalid: user not found");
if(method_exists($user, "canBeViewedBy") && !$user->canBeViewedBy($this->getUser())) {
if(!$user->canBeViewedBy($this->getUser())) {
$this->fail(1984, "Access denied: you can't see this user");
}
@ -181,6 +181,9 @@ final class Likes extends VKAPIRequestHandler
if(!$object || $object->isDeleted())
$this->fail(56, "Invalid postable");
if(!$object->canBeViewedBy($this->getUser()))
$this->fail(665, "Access to postable denied");
$res = (object)[
"count" => $object->getLikesCount(),
"items" => []

View file

@ -51,7 +51,8 @@ final class Newsfeed extends VKAPIRequestHandler
{
$this->requireUser();
$queryBase = "FROM `posts` LEFT JOIN `groups` ON GREATEST(`posts`.`wall`, 0) = 0 AND `groups`.`id` = ABS(`posts`.`wall`) WHERE (`groups`.`hide_from_global_feed` = 0 OR `groups`.`name` IS NULL) AND `posts`.`deleted` = 0 AND `posts`.`suggested` = 0";
$queryBase = "FROM `posts` LEFT JOIN `groups` ON GREATEST(`posts`.`wall`, 0) = 0 AND `groups`.`id` = ABS(`posts`.`wall`) LEFT JOIN `profiles` ON LEAST(`posts`.`wall`, 0) = 0 AND `profiles`.`id` = ABS(`posts`.`wall`)";
$queryBase .= "WHERE (`groups`.`hide_from_global_feed` = 0 OR `groups`.`name` IS NULL) AND (`profiles`.`profile_type` = 0 OR `profiles`.`first_name` IS NULL) AND `posts`.`deleted` = 0 AND `posts`.`suggested` = 0";
if($this->getUser()->getNsfwTolerance() === User::NSFW_INTOLERANT)
$queryBase .= " AND `nsfw` = 0";

View file

@ -40,6 +40,9 @@ final class Notes extends VKAPIRequestHandler
if($note->getOwner()->isDeleted())
$this->fail(403, "Owner is deleted");
if(!$note->canBeViewedBy($this->getUser()))
$this->fail(15, "Access denied");
if(!$note->getOwner()->getPrivacyPermission('notes.read', $this->getUser()))
$this->fail(43, "No access");
@ -153,7 +156,10 @@ final class Notes extends VKAPIRequestHandler
$this->fail(15, "Invalid user");
if(!$user->getPrivacyPermission('notes.read', $this->getUser()))
$this->fail(43, "Access denied: this user chose to hide his notes");
$this->fail(15, "Access denied: this user chose to hide his notes");
if(!$user->canBeViewedBy($this->getUser()))
$this->fail(15, "Access denied");
if(empty($note_ids)) {
$notes = array_slice(iterator_to_array((new NotesRepo)->getUserNotes($user, 1, $count + $offset, $sort == 0 ? "ASC" : "DESC")), $offset);
@ -204,6 +210,9 @@ final class Notes extends VKAPIRequestHandler
if(!$note->getOwner()->getPrivacyPermission('notes.read', $this->getUser()))
$this->fail(40, "Access denied: this user chose to hide his notes");
if(!$note->canBeViewedBy($this->getUser()))
$this->fail(15, "Access to note denied");
return $note->toVkApiStruct();
}
@ -225,6 +234,9 @@ final class Notes extends VKAPIRequestHandler
if(!$note->getOwner()->getPrivacyPermission('notes.read', $this->getUser()))
$this->fail(14, "No access");
if(!$note->canBeViewedBy($this->getUser()))
$this->fail(15, "Access to note denied");
$arr = (object) [
"count" => $note->getCommentsCount(),
"comments" => []];

View file

@ -304,7 +304,6 @@ final class Photos extends VKAPIRequestHandler
if(!$user || $user->isDeleted())
$this->fail(2, "Invalid user");
if(!$user->getPrivacyPermission('photos.read', $this->getUser()))
$this->fail(21, "This user chose to hide his albums.");
@ -363,26 +362,21 @@ final class Photos extends VKAPIRequestHandler
$this->requireUser();
$this->willExecuteWriteAction();
if($user_id == 0 && $group_id == 0 || $user_id > 0 && $group_id > 0) {
if($user_id == 0 && $group_id == 0 || $user_id > 0 && $group_id > 0)
$this->fail(21, "Select user_id or group_id");
}
if($user_id > 0) {
$us = (new UsersRepo)->get($user_id);
if(!$us || $us->isDeleted()) {
if(!$us || $us->isDeleted())
$this->fail(21, "Invalid user");
}
if(!$us->getPrivacyPermission('photos.read', $this->getUser())) {
if(!$us->getPrivacyPermission('photos.read', $this->getUser()))
$this->fail(21, "This user chose to hide his albums.");
}
return (new Albums)->getUserAlbumsCount($us);
}
if($group_id > 0)
{
if($group_id > 0) {
$cl = (new Clubs)->get($group_id);
if(!$cl) {
$this->fail(21, "Invalid club");
@ -404,17 +398,11 @@ final class Photos extends VKAPIRequestHandler
$ph = explode("_", $phota);
$photo = (new PhotosRepo)->getByOwnerAndVID((int)$ph[0], (int)$ph[1]);
if(!$photo || $photo->isDeleted()) {
if(!$photo || $photo->isDeleted())
$this->fail(21, "Invalid photo");
}
if($photo->getOwner()->isDeleted()) {
$this->fail(21, "Owner of this photo is deleted");
}
if(!$photo->getOwner()->getPrivacyPermission('photos.read', $this->getUser())) {
$this->fail(21, "This user chose to hide his photos.");
}
if(!$photo->canBeViewedBy($this->getUser()))
$this->fail(15, "Access denied");
$res[] = $photo->toVkApiStruct($photo_sizes, $extended);
}
@ -435,8 +423,8 @@ final class Photos extends VKAPIRequestHandler
if(!$album || $album->isDeleted())
$this->fail(21, "Invalid album");
if(!$album->getOwner()->getPrivacyPermission('photos.read', $this->getUser()))
$this->fail(21, "This user chose to hide his albums.");
if(!$album->canBeViewedBy($this->getUser()))
$this->fail(15, "Access denied");
$photos = array_slice(iterator_to_array($album->getPhotos(1, $count + $offset)), $offset);
$res["count"] = sizeof($photos);
@ -458,7 +446,7 @@ final class Photos extends VKAPIRequestHandler
$id = explode("_", $photo);
$phot = (new PhotosRepo)->getByOwnerAndVID((int)$id[0], (int)$id[1]);
if($phot && !$phot->isDeleted()) {
if($phot && !$phot->isDeleted() && $phot->canBeViewedBy($this->getUser())) {
$res["items"][] = $phot->toVkApiStruct($photo_sizes, $extended);
}
}
@ -474,13 +462,11 @@ final class Photos extends VKAPIRequestHandler
$album = (new Albums)->get($album_id);
if(!$album || $album->canBeModifiedBy($this->getUser())) {
if(!$album || $album->canBeModifiedBy($this->getUser()))
$this->fail(21, "Invalid album");
}
if($album->isDeleted()) {
if($album->isDeleted())
$this->fail(22, "Album already deleted");
}
$album->delete();
@ -494,13 +480,11 @@ final class Photos extends VKAPIRequestHandler
$photo = (new PhotosRepo)->getByOwnerAndVID($owner_id, $photo_id);
if(!$photo) {
if(!$photo)
$this->fail(21, "Invalid photo");
}
if($photo->isDeleted()) {
if($photo->isDeleted())
$this->fail(21, "Photo is deleted");
}
if(!empty($caption)) {
$photo->setDescription($caption);
@ -518,17 +502,14 @@ final class Photos extends VKAPIRequestHandler
if(empty($photos)) {
$photo = (new PhotosRepo)->getByOwnerAndVID($owner_id, $photo_id);
if($this->getUser()->getId() !== $photo->getOwner()->getId()) {
if($this->getUser()->getId() !== $photo->getOwner()->getId())
$this->fail(21, "You can't delete another's photo");
}
if(!$photo) {
if(!$photo)
$this->fail(21, "Invalid photo");
}
if($photo->isDeleted()) {
$this->fail(21, "Photo already deleted");
}
if($photo->isDeleted())
$this->fail(21, "Photo is already deleted");
$photo->delete();
} else {
@ -540,17 +521,14 @@ final class Photos extends VKAPIRequestHandler
$phot = (new PhotosRepo)->getByOwnerAndVID((int)$id[0], (int)$id[1]);
if($this->getUser()->getId() !== $phot->getOwner()->getId()) {
if($this->getUser()->getId() !== $phot->getOwner()->getId())
$this->fail(21, "You can't delete another's photo");
}
if(!$phot) {
if(!$phot)
$this->fail(21, "Invalid photo");
}
if($phot->isDeleted()) {
if($phot->isDeleted())
$this->fail(21, "Photo already deleted");
}
$phot->delete();
}
@ -570,17 +548,11 @@ final class Photos extends VKAPIRequestHandler
$this->willExecuteWriteAction();
$comment = (new CommentsRepo)->get($comment_id);
if(!$comment) {
if(!$comment)
$this->fail(21, "Invalid comment");
}
if(!$comment->canBeModifiedBy($this->getUser())) {
$this->fail(21, "Forbidden");
}
if($comment->isDeleted()) {
$this->fail(4, "Comment already deleted");
}
if(!$comment->canBeModifiedBy($this->getUser()))
$this->fail(21, "Access denied");
$comment->delete();
@ -592,20 +564,16 @@ final class Photos extends VKAPIRequestHandler
$this->requireUser();
$this->willExecuteWriteAction();
if(empty($message) && empty($attachments)) {
if(empty($message) && empty($attachments))
$this->fail(100, "Required parameter 'message' missing.");
}
$photo = (new PhotosRepo)->getByOwnerAndVID($owner_id, $photo_id);
if(!$photo->getAlbum()->getOwner()->getPrivacyPermission('photos.read', $this->getUser())) {
$this->fail(21, "This user chose to hide his albums.");
}
if(!$photo || $photo->isDeleted())
$this->fail(180, "Invalid photo");
if(!$photo)
$this->fail(180, "Photo not found");
if($photo->isDeleted())
$this->fail(189, "Photo is deleted");
if(!$photo->canBeViewedBy($this->getUser()))
$this->fail(15, "Access to photo denied");
$comment = new Comment;
$comment->setOwner($this->getUser()->getId());
@ -666,22 +634,21 @@ final class Photos extends VKAPIRequestHandler
$this->requireUser();
$this->willExecuteWriteAction();
if($owner_id < 0) {
if($owner_id < 0)
$this->fail(4, "This method doesn't works with clubs");
}
$user = (new UsersRepo)->get($owner_id);
if(!$user) {
if(!$user)
$this->fail(4, "Invalid user");
}
if(!$user->getPrivacyPermission('photos.read', $this->getUser())) {
if(!$user->getPrivacyPermission('photos.read', $this->getUser()))
$this->fail(21, "This user chose to hide his albums.");
}
$photos = array_slice(iterator_to_array((new PhotosRepo)->getEveryUserPhoto($user, 1, $count + $offset)), $offset);
$res = [];
$res = [
"items" => [],
];
foreach($photos as $photo) {
if(!$photo || $photo->isDeleted()) continue;
@ -699,17 +666,11 @@ final class Photos extends VKAPIRequestHandler
$photo = (new PhotosRepo)->getByOwnerAndVID($owner_id, $photo_id);
$comms = array_slice(iterator_to_array($photo->getComments(1, $offset + $count)), $offset);
if(!$photo) {
if(!$photo || $photo->isDeleted())
$this->fail(4, "Invalid photo");
}
if(!$photo->getAlbum()->getOwner()->getPrivacyPermission('photos.read', $this->getUser())) {
$this->fail(21, "This user chose to hide his photos.");
}
if($photo->isDeleted()) {
$this->fail(4, "Photo is deleted");
}
if(!$photo->canBeViewedBy($this->getUser()))
$this->fail(21, "Access denied");
$res = [
"count" => sizeof($comms),

View file

@ -16,6 +16,10 @@ final class Status extends VKAPIRequestHandler
$this->fail(501, "Group statuses are not implemented");
else {
$user = (new UsersRepo)->get($user_id);
if(!$user || $user->isDeleted() || !$user->canBeViewedBy($this->getUser()))
$this->fail(15, "Invalid user");
$audioStatus = $user->getCurrentAudioStatus();
if($audioStatus) {
return [

View file

@ -50,12 +50,12 @@ final class Users extends VKAPIRequestHandler
"id" => $usr->getId(),
"first_name" => $usr->getFirstName(true),
"last_name" => $usr->getLastName(true),
"is_closed" => false,
"can_access_closed" => true,
"is_closed" => $usr->isClosed(),
"can_access_closed" => (bool)$usr->canBeViewedBy($this->getUser()),
];
$flds = explode(',', $fields);
$canView = $usr->canBeViewedBy($this->getUser());
foreach($flds as $field) {
switch($field) {
case "verified":
@ -150,36 +150,91 @@ final class Users extends VKAPIRequestHandler
];
}
case "music":
if(!$canView) {
$response[$i]->music = "secret";
break;
}
$response[$i]->music = $usr->getFavoriteMusic();
break;
case "movies":
if(!$canView) {
$response[$i]->movies = "secret";
break;
}
$response[$i]->movies = $usr->getFavoriteFilms();
break;
case "tv":
if(!$canView) {
$response[$i]->tv = "secret";
break;
}
$response[$i]->tv = $usr->getFavoriteShows();
break;
case "books":
if(!$canView) {
$response[$i]->books = "secret";
break;
}
$response[$i]->books = $usr->getFavoriteBooks();
break;
case "city":
if(!$canView) {
$response[$i]->city = "Воскресенск";
break;
}
$response[$i]->city = $usr->getCity();
break;
case "interests":
if(!$canView) {
$response[$i]->interests = "secret";
break;
}
$response[$i]->interests = $usr->getInterests();
break;
case "quotes":
$response[$i]->interests = $usr->getFavoriteQuote();
if(!$canView) {
$response[$i]->quotes = "secret";
break;
}
$response[$i]->quotes = $usr->getFavoriteQuote();
break;
case "email":
$response[$i]->interests = $usr->getEmail();
if(!$canView) {
$response[$i]->email = "secret@gmail.com";
break;
}
$response[$i]->email = $usr->getContactEmail();
break;
case "telegram":
$response[$i]->interests = $usr->getTelegram();
if(!$canView) {
$response[$i]->telegram = "@secret";
break;
}
$response[$i]->telegram = $usr->getTelegram();
break;
case "about":
$response[$i]->interests = $usr->getDescription();
if(!$canView) {
$response[$i]->about = "secret";
break;
}
$response[$i]->about = $usr->getDescription();
break;
case "rating":
if(!$canView) {
$response[$i]->rating = 22;
break;
}
$response[$i]->rating = $usr->getRating();
break;
case "counters":
@ -214,6 +269,14 @@ final class Users extends VKAPIRequestHandler
$this->requireUser();
$user = $users->get($user_id);
if(!$user || $user->isDeleted())
$this->fail(14, "Invalid user");
if(!$user->canBeViewedBy($this->getUser()))
$this->fail(15, "Access denied");
foreach($users->get($user_id)->getFollowers($offset, $count) as $follower)
$followers[] = $follower->getId();
@ -306,6 +369,7 @@ final class Users extends VKAPIRequestHandler
"fav_shows" => !empty($fav_shows) ? $fav_shows : NULL,
"fav_books" => !empty($fav_books) ? $fav_books : NULL,
"fav_quotes" => !empty($fav_quotes) ? $fav_quotes : NULL,
"doNotSearchPrivate" => true,
];
$find = $users->find($q, $parameters, $sortg);

View file

@ -40,9 +40,11 @@ final class Video extends VKAPIRequestHandler
else
$this->fail(1, "Not implemented");
if(!$user->getPrivacyPermission('videos.read', $this->getUser())) {
$this->fail(20, "Access denied: this user chose to hide his videos");
}
if(!$user || $user->isDeleted())
$this->fail(14, "Invalid user");
if(!$user->getPrivacyPermission('videos.read', $this->getUser()))
$this->fail(21, "This user chose to hide his videos.");
$videos = (new VideosRepo)->getByUser($user, $offset + 1, $count);
$videosCount = (new VideosRepo)->getUserVideosCount($user);

View file

@ -39,6 +39,9 @@ final class Wall extends VKAPIRequestHandler
if ($owner_id > 0)
if(!$wallOnwer || $wallOnwer->isDeleted())
$this->fail(18, "User was deleted or banned");
if(!$wallOnwer->canBeViewedBy($this->getUser()))
$this->fail(15, "Access denied");
else
if(!$wallOnwer)
$this->fail(15, "Access denied: wall is disabled"); // Don't search for logic here pls
@ -234,8 +237,8 @@ final class Wall extends VKAPIRequestHandler
"first_name" => $user->getFirstName(),
"id" => $user->getId(),
"last_name" => $user->getLastName(),
"can_access_closed" => false,
"is_closed" => false,
"can_access_closed" => (bool)$user->canBeViewedBy($this->getUser()),
"is_closed" => $user->isClosed(),
"sex" => $user->isFemale() ? 1 : ($user->isNeutral() ? 0 : 2),
"screen_name" => $user->getShortCode(),
"photo_50" => $user->getAvatarUrl(),
@ -289,7 +292,11 @@ final class Wall extends VKAPIRequestHandler
foreach($psts as $pst) {
$id = explode("_", $pst);
$post = (new PostsRepo)->getPostById(intval($id[0]), intval($id[1]));
if($post && !$post->isDeleted()) {
if(!$post->canBeViewedBy($this->getUser()))
continue;
$from_id = get_class($post->getOwner()) == "openvk\Web\Models\Entities\Club" ? $post->getOwner()->getId() * (-1) : $post->getOwner()->getId();
$attachments = [];
$repost = []; // чел высрал семь сигарет 😳 помянем 🕯
@ -440,8 +447,8 @@ final class Wall extends VKAPIRequestHandler
"first_name" => $user->getFirstName(),
"id" => $user->getId(),
"last_name" => $user->getLastName(),
"can_access_closed" => false,
"is_closed" => false,
"can_access_closed" => (bool)$user->canBeViewedBy($this->getUser()),
"is_closed" => $user->isClosed(),
"sex" => $user->isFemale() ? 1 : 2,
"screen_name" => $user->getShortCode(),
"photo_50" => $user->getAvatarUrl(),
@ -495,7 +502,7 @@ final class Wall extends VKAPIRequestHandler
$wallOwner = ($owner_id > 0 ? (new UsersRepo)->get($owner_id) : (new ClubsRepo)->get($owner_id * -1))
?? $this->fail(18, "User was deleted or banned");
if($owner_id > 0)
$canPost = $wallOwner->getPrivacyPermission("wall.write", $this->getUser());
$canPost = $wallOwner->getPrivacyPermission("wall.write", $this->getUser()) && $wallOwner->canBeViewedBy($this->getUser());
else if($owner_id < 0)
if($wallOwner->canBeModifiedBy($this->getUser()))
$canPost = true;
@ -696,6 +703,9 @@ final class Wall extends VKAPIRequestHandler
$post = (new PostsRepo)->getPostById((int) $postArray[1], (int) $postArray[2]);
if(!$post || $post->isDeleted()) $this->fail(100, "One of the parameters specified was missing or invalid");
if(!$post->canBeViewedBy($this->getUser()))
$this->fail(15, "Access denied");
$nPost = new Post;
$nPost->setOwner($this->user->getId());
@ -735,6 +745,9 @@ final class Wall extends VKAPIRequestHandler
$post = (new PostsRepo)->getPostById($owner_id, $post_id);
if(!$post || $post->isDeleted()) $this->fail(100, "One of the parameters specified was missing or invalid");
if(!$post->canBeViewedBy($this->getUser()))
$this->fail(15, "Access denied");
$comments = (new CommentsRepo)->getCommentsByTarget($post, $offset+1, $count, $sort == "desc" ? "DESC" : "ASC");
$items = [];
@ -820,6 +833,9 @@ final class Wall extends VKAPIRequestHandler
if(!$comment || $comment->isDeleted())
$this->fail(100, "Invalid comment");
if(!$comment->canBeViewedBy($this->getUser()))
$this->fail(15, "Access denied");
$profiles = [];
$attachments = [];
@ -886,6 +902,9 @@ final class Wall extends VKAPIRequestHandler
$post = (new PostsRepo)->getPostById($owner_id, $post_id);
if(!$post || $post->isDeleted()) $this->fail(100, "Invalid post");
if(!$post->canBeViewedBy($this->getUser()))
$this->fail(15, "Access denied");
if($post->getTargetWall() < 0)
$club = (new ClubsRepo)->get(abs($post->getTargetWall()));

View file

@ -67,6 +67,21 @@ class Album extends MediaCollection
return $this->has($photo);
}
function canBeViewedBy(?User $user = NULL): bool
{
if($this->isDeleted()) {
return false;
}
$owner = $this->getOwner();
if(get_class($owner) == "openvk\\Web\\Models\\Entities\\User") {
return $owner->canBeViewedBy($user) && $owner->getPrivacyPermission('photos.read', $user);
} else {
return $owner->canBeViewedBy($user);
}
}
function toVkApiStruct(?User $user = NULL, bool $need_covers = false, bool $photo_sizes = false): object
{
$res = (object) [];

View file

@ -399,6 +399,11 @@ class Club extends RowModel
$this->save();
}
function canBeViewedBy(?User $user = NULL)
{
return is_null($this->getBanReason());
}
function getAlert(): ?string
{
return $this->getRecord()->alert;

View file

@ -95,6 +95,15 @@ class Comment extends Post
return "/wall" . $this->getTarget()->getPrettyId() . "#_comment" . $this->getId();
}
function canBeViewedBy(?User $user = NULL): bool
{
if($this->isDeleted() || $this->getTarget()->isDeleted()) {
return false;
}
return $this->getTarget()->canBeViewedBy($user);
}
function toNotifApiStruct()
{
$res = (object)[];

View file

@ -119,6 +119,15 @@ class Note extends Postable
return $this->getRecord()->source;
}
function canBeViewedBy(?User $user = NULL): bool
{
if($this->isDeleted() || $this->getOwner()->isDeleted()) {
return false;
}
return $this->getOwner()->getPrivacyPermission('notes.read', $user) && $this->getOwner()->canBeViewedBy($user);
}
function toVkApiStruct(): object
{
$res = (object) [];

View file

@ -329,6 +329,19 @@ class Photo extends Media
return $res;
}
function canBeViewedBy(?User $user = NULL): bool
{
if($this->isDeleted() || $this->getOwner()->isDeleted()) {
return false;
}
if(!is_null($this->getAlbum())) {
return $this->getAlbum()->canBeViewedBy($user);
} else {
return $this->getOwner()->canBeViewedBy($user);
}
}
static function fastMake(int $owner, string $description = "", array $file, ?Album $album = NULL, bool $anon = false): Photo
{
$photo = new static;

View file

@ -279,6 +279,17 @@ class Poll extends Attachable
return $poll;
}
function canBeViewedBy(?User $user = NULL): bool
{
# waiting for #935 :(
/*if(!is_null($this->getAttachedPost())) {
return $this->getAttachedPost()->canBeViewedBy($user);
} else {*/
return true;
#}
}
function save(?bool $log = false): void
{
if(empty($this->choicesToPersist))

View file

@ -249,6 +249,15 @@ class Post extends Postable
$this->save();
}
function canBeViewedBy(?User $user = NULL): bool
{
if($this->isDeleted()) {
return false;
}
return $this->getWallOwner()->canBeViewedBy($user);
}
function getSuggestionType()
{
return $this->getRecord()->suggested;

View file

@ -4,9 +4,13 @@ use openvk\Web\Models\Entities\User;
trait TOwnable
{
function canBeViewedBy(?User $user): bool
function canBeViewedBy(?User $user = NULL): bool
{
// TODO implement normal check in master
# TODO: #950
if($this->isDeleted()) {
return false;
}
return true;
}

View file

@ -508,6 +508,9 @@ class User extends RowModel
else if($user->getId() === $this->getId())
return true;
if($permission != "messages.write" && !$this->canBeViewedBy($user))
return false;
switch($permStatus) {
case User::PRIVACY_ONLY_FRIENDS:
return $this->getSubscriptionStatus($user) === User::SUBSCRIPTION_MUTUAL;
@ -1261,12 +1264,59 @@ class User extends RowModel
return $response;
}
function getProfileType(): int
{
# 0 — открытый профиль, 1 — закрытый
return $this->getRecord()->profile_type;
}
function canBeViewedBy(?User $user = NULL): bool
{
if(!is_null($user)) {
if($this->getId() == $user->getId()) {
return true;
}
if($user->getChandlerUser()->can("access")->model("admin")->whichBelongsTo(NULL)) {
return true;
}
if($this->getProfileType() == 0) {
return true;
} else {
if($user->getSubscriptionStatus($this) == User::SUBSCRIPTION_MUTUAL) {
return true;
} else {
return false;
}
}
} else {
if($this->getProfileType() == 0) {
if($this->getPrivacySetting("page.read") == 3) {
return true;
} else {
return false;
}
} else {
return false;
}
}
return true;
}
function isClosed()
{
return (bool) $this->getProfileType();
}
function getRealId()
{
return $this->getId();
}
function toVkApiStruct(): object
function toVkApiStruct(?User $user = NULL): object
{
$res = (object) [];
@ -1280,6 +1330,12 @@ class User extends RowModel
$res->photo_id = !is_null($this->getAvatarPhoto()) ? $this->getAvatarPhoto()->getPrettyId() : NULL;
# TODO: Perenesti syuda vsyo ostalnoyie
$res->is_closed = $this->isClosed();
if(!is_null($user)) {
$res->can_access_closed = (bool)$this->canBeViewedBy($user);
}
return $res;
}

View file

@ -225,6 +225,20 @@ class Video extends Media
return $video;
}
function canBeViewedBy(?User $user = NULL): bool
{
if($this->isDeleted() || $this->getOwner()->isDeleted()) {
return false;
}
if(get_class($this->getOwner()) == "openvk\\Web\\Models\\Entities\\User") {
return $this->getOwner()->canBeViewedBy($user) && $this->getOwner()->getPrivacyPermission('videos.read', $user);
} else {
# Groups doesn't have videos but ok
return $this->getOwner()->canBeViewedBy($user);
}
}
function toNotifApiStruct()
{
$fromYoutube = $this->getType() == Video::TYPE_EMBED;

View file

@ -128,6 +128,9 @@ class Users
case "doNotSearchMe":
$result->where("id !=", $paramValue);
break;
case "doNotSearchPrivate":
$result->where("profile_type", 0);
break;
}
}
}

View file

@ -43,6 +43,10 @@ final class CommentPresenter extends OpenVKPresenter
$entity = $repo->get($eId);
if(!$entity) $this->notFound();
if(!$entity->canBeViewedBy($this->user->identity)) {
$this->flashFail("err", tr("error"), tr("forbidden"));
}
if($entity instanceof Topic && $entity->isClosed())
$this->notFound();

View file

@ -20,9 +20,12 @@ final class GiftsPresenter extends OpenVKPresenter
$this->assertUserLoggedIn();
$user = $this->users->get($user);
if(!$user)
if(!$user || $user->isDeleted())
$this->notFound();
if(!$user->canBeViewedBy($this->user->identity ?? NULL))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
$this->template->user = $user;
$this->template->page = $page = (int) ($this->queryParam("p") ?? 1);
$this->template->count = $user->getGiftCount();
@ -52,6 +55,9 @@ final class GiftsPresenter extends OpenVKPresenter
if(!$user || !$cat)
$this->flashFail("err", tr("error_when_gifting"), tr("error_user_not_exists"));
if(!$user->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
$this->template->page = $page = (int) ($this->queryParam("p") ?? 1);
$gifts = $cat->getGifts($page, null, $this->template->count);
@ -72,6 +78,9 @@ final class GiftsPresenter extends OpenVKPresenter
if(!$gift->canUse($this->user->identity))
$this->flashFail("err", tr("error_when_gifting"), tr("error_no_more_gifts"));
if(!$user->canBeViewedBy($this->user->identity ?? NULL))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
$coinsLeft = $this->user->identity->getCoins() - $gift->getPrice();
if($coinsLeft < 0)
$this->flashFail("err", tr("error_when_gifting"), tr("error_no_money"));

View file

@ -40,6 +40,8 @@ final class NotesPresenter extends OpenVKPresenter
$this->notFound();
if(!$note->getOwner()->getPrivacyPermission('notes.read', $this->user->identity ?? NULL))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
if(!$note->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
$this->template->cCount = $note->getCommentsCount();
$this->template->cPage = (int) ($this->queryParam("p") ?? 1);

View file

@ -137,6 +137,9 @@ final class PhotosPresenter extends OpenVKPresenter
if($album->getPrettyId() !== $owner . "_" . $id || $album->isDeleted())
$this->notFound();
if(!$album->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
if($owner > 0 /* bc we currently don't have perms for clubs */) {
$ownerObject = (new Users)->get($owner);
if(!$ownerObject->getPrivacyPermission('photos.read', $this->user->identity ?? NULL))
@ -158,7 +161,8 @@ final class PhotosPresenter extends OpenVKPresenter
{
$photo = $this->photos->getByOwnerAndVID($ownerId, $photoId);
if(!$photo || $photo->isDeleted()) $this->notFound();
if(!$photo->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
if(!is_null($this->queryParam("from"))) {
if(preg_match("%^album([0-9]++)$%", $this->queryParam("from"), $matches) === 1) {
$album = $this->albums->get((int) $matches[1]);

View file

@ -97,6 +97,7 @@ final class SearchPresenter extends OpenVKPresenter
"before" => $this->queryParam("datebefore") != "" ? strtotime($this->queryParam("datebefore")) : NULL,
"after" => $this->queryParam("dateafter") != "" ? strtotime($this->queryParam("dateafter")) : NULL,
"gender" => $this->queryParam("gender") != "" && $this->queryParam("gender") != 2 ? $this->queryParam("gender") : NULL,
"doNotSearchPrivate" => true,
"only_performers" => $this->queryParam("only_performers") == "on" ? "1" : NULL,
"with_lyrics" => $this->queryParam("with_lyrics") == "on" ? true : NULL,
];

View file

@ -29,10 +29,14 @@ final class UserPresenter extends OpenVKPresenter
function renderView(int $id): void
{
$user = $this->users->get($id);
if(!$user || $user->isDeleted()) {
if(!$user || $user->isDeleted() || !$user->canBeViewedBy($this->user->identity)) {
if(!is_null($user) && $user->isDeactivated()) {
$this->template->_template = "User/deactivated.xml";
$this->template->user = $user;
} else if(!$user->canBeViewedBy($this->user->identity)) {
$this->template->_template = "User/private.xml";
$this->template->user = $user;
} else {
$this->template->_template = "User/deleted.xml";
@ -464,6 +468,10 @@ final class UserPresenter extends OpenVKPresenter
$input = $this->postParam(str_replace(".", "_", $setting));
$user->setPrivacySetting($setting, min(3, (int)abs((int)$input ?? $user->getPrivacySetting($setting))));
}
$prof = $this->postParam("profile_type") == 1 || $this->postParam("profile_type") == 0 ? (int)$this->postParam("profile_type") : 0;
$user->setProfile_type($prof);
} else if($_GET['act'] === "finance.top-up") {
$token = $this->postParam("key0") . $this->postParam("key1") . $this->postParam("key2") . $this->postParam("key3");
$voucher = (new Vouchers)->getByToken($token);

View file

@ -39,12 +39,13 @@ final class VideosPresenter extends OpenVKPresenter
function renderView(int $owner, int $vId): void
{
$user = $this->users->get($owner);
$video = $this->videos->getByOwnerAndVID($owner, $vId);
if(!$user) $this->notFound();
if(!$video || $video->isDeleted()) $this->notFound();
if(!$user->getPrivacyPermission('videos.read', $this->user->identity ?? NULL))
$this->flashFail("err", tr("forbidden"), tr("forbidden_comment"));
if($this->videos->getByOwnerAndVID($owner, $vId)->isDeleted()) $this->notFound();
$this->template->user = $user;
$this->template->video = $this->videos->getByOwnerAndVID($owner, $vId);
$this->template->cCount = $this->template->video->getCommentsCount();

View file

@ -46,7 +46,7 @@ final class WallPresenter extends OpenVKPresenter
function renderWall(int $user, bool $embedded = false): void
{
$owner = ($user < 0 ? (new Clubs) : (new Users))->get(abs($user));
if ($owner->isBanned())
if ($owner->isBanned() || !$owner->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("error"), tr("forbidden"));
if(is_null($this->user)) {
@ -114,7 +114,7 @@ final class WallPresenter extends OpenVKPresenter
if(is_null($this->user)) {
$canPost = false;
} else if($user > 0) {
if(!$owner->isBanned())
if(!$owner->isBanned() && $owner->canBeViewedBy($this->user->identity))
$canPost = $owner->getPrivacyPermission("wall.write", $this->user->identity);
else
$this->flashFail("err", tr("error"), tr("forbidden"));
@ -191,7 +191,8 @@ final class WallPresenter extends OpenVKPresenter
$page = (int) ($_GET["p"] ?? 1);
$pPage = min((int) ($_GET["posts"] ?? OPENVK_DEFAULT_PER_PAGE), 50);
$queryBase = "FROM `posts` LEFT JOIN `groups` ON GREATEST(`posts`.`wall`, 0) = 0 AND `groups`.`id` = ABS(`posts`.`wall`) WHERE (`groups`.`hide_from_global_feed` = 0 OR `groups`.`name` IS NULL) AND `posts`.`deleted` = 0 AND `posts`.`suggested` = 0";
$queryBase = "FROM `posts` LEFT JOIN `groups` ON GREATEST(`posts`.`wall`, 0) = 0 AND `groups`.`id` = ABS(`posts`.`wall`) LEFT JOIN `profiles` ON LEAST(`posts`.`wall`, 0) = 0 AND `profiles`.`id` = ABS(`posts`.`wall`)";
$queryBase .= "WHERE (`groups`.`hide_from_global_feed` = 0 OR `groups`.`name` IS NULL) AND (`profiles`.`profile_type` = 0 OR `profiles`.`first_name` IS NULL) AND `posts`.`deleted` = 0 AND `posts`.`suggested` = 0";
if($this->user->identity->getNsfwTolerance() === User::NSFW_INTOLERANT)
$queryBase .= " AND `nsfw` = 0";
@ -431,6 +432,9 @@ final class WallPresenter extends OpenVKPresenter
if(!$post || $post->isDeleted())
$this->notFound();
if(!$post->canBeViewedBy($this->user->identity))
$this->flashFail("err", tr("error"), tr("forbidden"));
$this->logPostView($post, $wall);
$this->template->post = $post;

View file

@ -189,7 +189,7 @@
</div>
{elseif $type == "posts"}
<div n:foreach="$data as $dat" class="content">
{if !$dat || $dat->getTargetWall() < 0 && $dat->getWallOwner()->isHideFromGlobalFeedEnabled()}
{if !$dat || $dat->getTargetWall() < 0 && $dat->getWallOwner()->isHideFromGlobalFeedEnabled() || !$dat->canBeViewedBy($thisUser)}
{_closed_group_post}.
{else}
{include "../components/post.xml", post => $dat, commentSection => true, onWallOf => true}

View file

@ -266,8 +266,6 @@
<select name="page.read" style="width: 164px;">
<option value="3" {if $user->getPrivacySetting('page.read') == 3}selected{/if}>{_privacy_value_anybody_dative}</option>
<option value="2" {if $user->getPrivacySetting('page.read') == 2}selected{/if}>{_privacy_value_users}</option>
<option value="1" {if $user->getPrivacySetting('page.read') == 1}selected{/if}>{_privacy_value_friends_dative}</option>
<option value="0" {if $user->getPrivacySetting('page.read') == 0}selected{/if}>{_privacy_value_only_me_dative}</option>
</select>
</td>
</tr>
@ -397,6 +395,17 @@
</select>
</td>
</tr>
<tr>
<td width="120" valign="top">
<span class="nobold">{_profile_type}</span>
</td>
<td>
<select name="profile_type", style="width: 164px;">
<option value="0" {if $user->getProfileType() == 0}selected{/if}>{_profile_type_open}</option>
<option value="1" {if $user->getProfileType() == 1}selected{/if}>{_profile_type_closed}</option>
</select>
</td>
</tr>
<tr>
<td>

View file

@ -0,0 +1,96 @@
{extends "../@layout.xml"}
{block title}{$user->getCanonicalName()}{/block}
{block header}
{$user->getCanonicalName()}
<img n:if="$user->isVerified()"
class="name-checkmark"
src="/assets/packages/static/openvk/img/checkmark.png"
/>
{/block}
{block content}
<div class="left_small_block">
<div>
<img src="{$user->getAvatarUrl('normal')}"
alt="{$user->getCanonicalName()}"
style="width: 100%; image-rendering: -webkit-optimize-contrast;" />
</div>
<div id="profile_links" n:if="isset($thisUser)">
<a style="width: 194px;" n:if="$user->getPrivacyPermission('messages.write', $thisUser)" href="/im?sel={$user->getId()}" class="profile_link">{_send_message}</a>
{var $subStatus = $user->getSubscriptionStatus($thisUser)}
{if $subStatus === 0}
<form action="/setSub/user" method="post" class="profile_link_form" id="addToFriends">
<input type="hidden" name="act" value="add" />
<input type="hidden" name="id" value="{$user->getId()}" />
<input type="hidden" name="hash" value="{$csrfToken}" />
<input type="submit" class="profile_link" value="{_friends_add}" style="width: 194px;" />
</form>
{elseif $subStatus === 1}
<form action="/setSub/user" method="post" class="profile_link_form" id="addToFriends">
<input type="hidden" name="act" value="add" />
<input type="hidden" name="id" value="{$user->getId()}" />
<input type="hidden" name="hash" value="{$csrfToken}" />
<input type="submit" class="profile_link" value="{_friends_accept}" style="width: 194px;" />
</form>
{elseif $subStatus === 2}
<form action="/setSub/user" method="post" class="profile_link_form" id="addToFriends">
<input type="hidden" name="act" value="rem" />
<input type="hidden" name="id" value="{$user->getId()}" />
<input type="hidden" name="hash" value="{$csrfToken}" />
<input type="submit" class="profile_link" value="{_friends_reject}" style="width: 194px;" />
</form>
{/if}
<a class="profile_link" style="display:block;width:96%;" href="javascript:reportUser()">{_report}</a>
<script>
function reportUser() {
uReportMsgTxt = "Вы собираетесь пожаловаться на данного пользователя.";
uReportMsgTxt += "<br/>Что именно вам кажется недопустимым в этом материале?";
uReportMsgTxt += "<br/><br/><b>Причина жалобы</b>: <input type='text' id='uReportMsgInput' placeholder='Причина' />"
MessageBox("Пожаловаться?", uReportMsgTxt, ["Подтвердить", "Отмена"], [
(function() {
res = document.querySelector("#uReportMsgInput").value;
xhr = new XMLHttpRequest();
xhr.open("GET", "/report/" + {$user->getId()} + "?reason=" + res + "&type=user", true);
xhr.onload = (function() {
if(xhr.responseText.indexOf("reason") === -1)
MessageBox("Ошибка", "Не удалось подать жалобу...", ["OK"], [Function.noop]);
else
MessageBox("Операция успешна", "Скоро её рассмотрят модераторы", ["OK"], [Function.noop]);
});
xhr.send(null);
}),
Function.noop
]);
}
</script>
</div>
</div>
<div class="right_big_block">
<div class="page_info">
<div class="accountInfo clearFix">
<div class="profileName">
<h2>{$user->getFullName()}</h2>
<div class="page_status" style="color: #AAA;">{_closed_page}</div>
</div>
</div>
<div class="msg msg_yellow" style="width: 93%;margin-top: 10px;">
{var $m = $user->isFemale() ? "f" : "m"}
{tr("limited_access_to_page_$m", $user->getFirstName())}
{if isset($thisUser)}
{if $subStatus != 2}
<br /><br />
{_you_can_add}
<a href="javascript:addToFriends.submit()">{tr("add_to_friends_$m")}</a>
{/if}
{else}
<br /><br />
{tr("register_to_access_page_$m")}
{/if}
</div>
</div>
</div>
{/block}

View file

@ -10,7 +10,6 @@
</a>
{/if}
{elseif $attachment instanceof \openvk\Web\Models\Entities\Video}
{if !$attachment->isDeleted()}
{if $attachment->getType() === 0}
<div class="bsdn media" data-name="{$attachment->getName()}" data-author="{$attachment->getOwner()->getCanonicalName()}">
<video class="media" src="{$attachment->getURL()}"></video>
@ -28,10 +27,6 @@
<img src="/assets/packages/static/openvk/img/videoico.png" />
<a href="/video{$attachment->getPrettyId()}" id="videoOpen" data-id="{$attachment->getId()}">{$attachment->getName()}</a>
</div>
{else}
<span style="color:gray;">{_video_is_deleted}</span>
{/if}
{elseif $attachment instanceof \openvk\Web\Models\Entities\Poll}
{presenter "openvk!Poll->view", $attachment->getId()}
{elseif $attachment instanceof \openvk\Web\Models\Entities\Note}

View file

@ -1013,6 +1013,11 @@ table.User {
background-color: #f5e9ec;
}
.msg.msg_yellow {
border-color:#D4BC4C;
background-color:#F9F6E7;
}
.edit_link {
color: #c5c5c5;
font-family: verdana, arial, sans-serif;

View file

@ -0,0 +1 @@
ALTER TABLE `profiles` ADD `profile_type` TINYINT(1) NOT NULL DEFAULT '0' AFTER `client_name`;

View file

@ -163,6 +163,18 @@
"before" = "before";
"forever" = "forever";
"closed_page" = "Closed page";
"limited_access_to_page_m" = "$1 limited access to his page.";
"limited_access_to_page_f" = "$1 limited access to her page.";
"you_can_add" = "You can";
"add_to_friends_m" = "add him to friends.";
"add_to_friends_f" = "add her to friends.";
"register_to_access_page_m" = "Sign up to get access to his page.";
"register_to_access_page_f" = "Sign up to get access to her page.";
/* Wall */
"feed" = "News";
@ -653,6 +665,10 @@
"privacy_value_only_me_dative" = "Only me";
"privacy_value_nobody" = "Nobody";
"profile_type" = "Profile type";
"profile_type_open" = "Open";
"profile_type_closed" = "Closed";
"your_email_address" = "Your Email address";
"your_page_address" = "Your address page";
"page_address" = "Address page";

View file

@ -140,6 +140,22 @@
"updated_at" = "Обновлено $1";
"user_banned" = "К сожалению, нам пришлось заблокировать страницу пользователя <b>$1</b>.";
"user_banned_comment" = "Комментарий модератора:";
"closed_page" = "Закрытая страница";
"limited_access_to_page_m" = "$1 ограничил доступ к своей странице.";
"limited_access_to_page_f" = "$1 ограничила доступ к своей странице.";
"you_can_add" = "Вы можете";
"add_to_friends_m" = "добавить его в друзья.";
"add_to_friends_f" = "добавить её в друзья.";
"register_to_access_page_m" = "Зарегистрируйтесь, чтобы получить доступ к его странице.";
"register_to_access_page_f" = "Зарегистрируйтесь, чтобы получить доступ к её странице.";
"private_profile_warning" = "Этот профиль закрытый, но вы имеете к нему доступ, потому что вы — администратор.";
"private_profile_warning_desc" = "Пожалуйста, уважайте право на личную жизнь и не злоупотребляйте этой возможностью.";
"verified_page" = "Подтверждённая страница";
"user_is_blocked" = "Пользователь заблокирован";
"before" = "до";
@ -625,6 +641,9 @@
"privacy_value_only_me" = "Только я";
"privacy_value_only_me_dative" = "Только мне";
"privacy_value_nobody" = "Никто";
"profile_type" = "Тип профиля";
"profile_type_open" = "Открытый";
"profile_type_closed" = "Закрытый";
"your_email_address" = "Адрес Вашей электронной почты";
"your_page_address" = "Адрес Вашей страницы";
"page_address" = "Адрес страницы";